/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $
 *
 */
/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */
(function($) {
$.extend({
    metadata : {
        defaults : {
            type: 'class',
            name: 'metadata',
            cre: /({.*})/,
            single: 'metadata'
        },
        setType: function( type, name ){
            this.defaults.type = type;
            this.defaults.name = name;
        },
        get: function( elem, opts ){
            var settings = $.extend({},this.defaults,opts);
            // check for empty string in single property
            if ( !settings.single.length ) settings.single = 'metadata';
            
            var data = $.data(elem, settings.single);
            // returned cached data if it already exists
            if ( data ) return data;
            
            data = "{}";
            
            if ( settings.type == "class" ) {
                var m = settings.cre.exec( elem.className );
                if ( m )
                    data = m[1];
            } else if ( settings.type == "elem" ) {
                if( !elem.getElementsByTagName ) return;
                var e = elem.getElementsByTagName(settings.name);
                if ( e.length )
                    data = $.trim(e[0].innerHTML);
            } else if ( elem.getAttribute != undefined ) {
                var attr = elem.getAttribute( settings.name );
                if ( attr )
                    data = attr;
            }
            
            if ( data.indexOf( '{' ) <0 )
            data = "{" + data + "}";
            
            data = eval("(" + data + ")");
            
            $.data( elem, settings.single, data );
            return data;
        }
    }
});
/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
    return $.metadata.get( this[0], opts );
};
})(jQuery);


/*
 ### jQuery Star Rating Plugin v2.2 - 2008-04-08 ###
 By Diego A, http://www.fyneworks.com, diego@fyneworks.com
 - 'read only' feature by by Keith Wood, http://keith-wood.name/, kbwood@virginbroadband.com.au
 
 Project: http://plugins.jquery.com/project/MultipleFriendlyStarRating
 Website: http://www.fyneworks.com/jquery/star-rating/
 
 This is a modified version of the star rating plugin from:
 http://www.phpletter.com/Demo/Jquery-Star-Rating-Plugin/
*/
// ORIGINAL COMMENTS:
/*************************************************
 This is hacked version of star rating created by <a href="http://php.scripts.psu.edu/rja171/widgets/rating.php">Ritesh Agrawal</a>
 It thansform a set of radio type input elements to star rating type and remain the radio element name and value,
 so could be integrated with your form. It acts as a normal radio button.
 modified by : Logan Cai (cailongqun[at]yahoo.com.cn)
 website:www.phpletter.com
************************************************/


/*# AVOID COLLISIONS #*/
;if(jQuery) (function($){
/*# AVOID COLLISIONS #*/

// default settings
$.rating = {
 cancel: 'Cancel Rating',   // advisory title for the 'cancel' link
 cancelValue: '',           // value to submit when user click the 'cancel' link
 split: 0,                  // split the star into how many parts?
 
 //NB.: These don't need to be defined (can be undefined/null) so let's save some code!
 //half:     false,         // just a shortcut to settings.split = 2
 //required: false,         // disables the 'cancel' button so user can only select one of the specified values
 //readOnly: false,         // disable rating plugin interaction/ values cannot be changed
 //focus:    function(){},  // executed when stars are focused
 //blur:     function(){},  // executed when stars are focused
 //callback: function(){},  // executed when a star is clicked
 
 // required properties:
 groups: {},// allows multiple star ratings on one page
 event: {// plugin event handlers
  fill: function(n, el, settings, state){ // fill to the current mouse position.
         //if(console) console.log(['fill', $(el), $(el).prevAll('.star_group_'+n), arguments]);
   this.drain(n);
   $(el).prevAll('.star_group_'+n).andSelf().addClass('star_'+(state || 'hover'));
   // focus handler, as requested by focusdigital.co.uk
   var lnk = $(el).children('a'); val = lnk.text();
   if(settings.focus) settings.focus.apply($.rating.groups[n].valueElem[0], [val, lnk[0]]);
  },
  drain: function(n, el, settings) { // drain all the stars.
         //if(console) console.log(['drain', $(el), $(el).prevAll('.star_group_'+n), arguments]);
   $.rating.groups[n].valueElem.siblings('.star_group_'+n).removeClass('star_on').removeClass('star_hover');
  },
  reset: function(n, el, settings){ // Reset the stars to the default index.
   if(!$($.rating.groups[n].current).is('.cancel'))
    $($.rating.groups[n].current).prevAll('.star_group_'+n).andSelf().addClass('star_on');
   // blur handler, as requested by focusdigital.co.uk
   var lnk = $(el).children('a'); val = lnk.text();
   if(settings.blur) settings.blur.apply($.rating.groups[n].valueElem[0], [val, lnk[0]]);
  },
  click: function(n, el, settings){ // Selected a star or cancelled
   $.rating.groups[n].current = el;
   var lnk = $(el).children('a'); val = lnk.text();
   // Set value
   $.rating.groups[n].valueElem.val(val);
   // Update display
   $.rating.event.drain(n, el, settings);
   $.rating.event.reset(n, el, settings);
   // click callback, as requested here: http://plugins.jquery.com/node/1655
   if(settings.callback) settings.callback.apply($.rating.groups[n].valueElem[0], [val, lnk[0]]);
  }      
 }// plugin events
};

$.fn.rating = function(instanceSettings){
 if(this.length==0) return this; // quick fail
 
 instanceSettings = $.extend(
  {}/* new object */,
  $.rating/* global settings */,
  instanceSettings || {} /* just-in-time settings */
 );
 
 // loop through each matched element
 this.each(function(i){
  
  var settings = $.extend(
   {}/* new object */,
   instanceSettings || {} /* current call settings */,
   ($.metadata? $(this).metadata(): ($.meta?$(this).data():null)) || {} /* metadata settings */
  );
  
  ////if(console) console.log([this.name, settings.half, settings.split], '#');
  
  // grouping:
  var n = this.name;
  if(!$.rating.groups[n]) $.rating.groups[n] = {count: 0};
  i = $.rating.groups[n].count; $.rating.groups[n].count++;
  
  // Accept readOnly setting from 'disabled' property
  $.rating.groups[n].readOnly = $.rating.groups[n].readOnly || settings.readOnly || $(this).attr('disabled');
  
  // Things to do with the first element...
  if(i == 0){
   // Create value element (disabled if readOnly)
   $.rating.groups[n].valueElem = $('<input type="hidden" name="' + n + '" value=""' + (settings.readOnly ? ' disabled="disabled"' : '') + '>');
   // Insert value element into form
   $(this).before($.rating.groups[n].valueElem);
            //
   
   if($.rating.groups[n].readOnly || settings.required){
    // DO NOT display 'cancel' button
   }
   else{
    // Display 'cancel' button
    $(this).before(
     $('<div class="cancel"><a title="' + settings.cancel + '">' + settings.cancelValue + '</a></div>')
     .mouseover(function(){ $.rating.event.drain(n, this, settings); $(this).addClass('star_on'); })
     .mouseout(function(){ $.rating.event.reset(n, this, settings); $(this).removeClass('star_on'); })
     .click(function(){ $.rating.event.click(n, this, settings); })
    );
   }
  }; // if (i == 0) (first element)
  
  // insert rating option right after preview element
  eStar = $('<div class="star"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
  $(this).after(eStar);
  
  // Half-stars?
  if(settings.half) settings.split = 2;
  
  // Prepare division settings
  if(typeof settings.split=='number' && settings.split>0){
   var spi = (i % settings.split), spw = Math.floor($(eStar).width()/settings.split);
   $(eStar)
   // restrict star's width and hide overflow (already in CSS)
   .width(spw)
   // move the star left by using a negative margin
   // this is work-around to IE's stupid box model (position:relative doesn't work)
   .find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
  };
  
        // Remember group name so controls within the same container don't get mixed up
  $(eStar).addClass('star_group_'+n)
  
        // readOnly?
  if($.rating.groups[n].readOnly){
   // Mark star as readOnly so user can customize display
   $(eStar)
   .addClass('star_readonly');
   //alert([this.name,this.value,this.checked].join('\n'));
  }
  else{
   $(eStar)
   // Enable hover css effects
   .addClass('star_live')
   // Attach mouse events
   .mouseover(function(){ $.rating.event.drain(n, this, settings); $.rating.event.fill(n, this, settings, 'hover'); })
   .mouseout(function(){ $.rating.event.drain(n, this, settings); $.rating.event.reset(n, this, settings); })
   .click(function(){ $.rating.event.click(n, this, settings); });
  };
  
  ////if(console) console.log(['###', n, this.checked, $.rating.groups[n].initial]);
  if(this.checked) $.rating.groups[n].current = eStar;
  
  //remove this checkbox
  $(this).remove();
  
  // reset display if last element
  if(i + 1 == this.length) $.rating.event.reset(n, this, settings);
 
 }); // each element
  
 // initialize groups...
 for(n in $.rating.groups)//{ not needed, save a byte!
  (function(c, v, n){ if(!c) return;
   $.rating.event.fill(n, c, instanceSettings || {}, 'on');
   $(v).val($(c).children('a').text());
  })
  ($.rating.groups[n].current, $.rating.groups[n].valueElem, n);
 //}; not needed, save a byte!
 
 return this; // don't break the chain...
};



/*# AVOID COLLISIONS #*/
})(jQuery);
/*# AVOID COLLISIONS #*/