1/* 2RateIt 3version 1.0.9 410/31/2012 5http://rateit.codeplex.com 6Twitter: @gjunge 7*/ 8(function ($) { 9$.fn.rateit = function (p1, p2) { 10//quick way out. 11var options = {}; var mode = 'init'; 12var capitaliseFirstLetter = function (string) { 13return string.charAt(0).toUpperCase() + string.substr(1); 14}; 15if (this.length == 0) return this; 16var tp1 = $.type(p1); 17if (tp1 == 'object' || p1 === undefined || p1 == null) { 18options = $.extend({}, $.fn.rateit.defaults, p1); //wants to init new rateit plugin(s). 19} 20else if (tp1 == 'string' && p2 === undefined) { 21return this.data('rateit' + capitaliseFirstLetter(p1)); //wants to get a value. 22} 23else if (tp1 == 'string') { 24mode = 'setvalue' 25} 26return this.each(function () { 27var item = $(this); 28//shorten all the item.data('rateit-XXX'), will save space in closure compiler, will be like item.data('XXX') will become x('XXX') 29var itemdata = function (key, value) { 30arguments[0] = 'rateit' + capitaliseFirstLetter(key); 31return item.data.apply(item, arguments); ////Fix for WI: 523 32}; 33//add the rate it class. 34if (!item.hasClass('rateit')) item.addClass('rateit'); 35var ltr = item.css('direction') != 'rtl'; 36// set value mode 37if (mode == 'setvalue') { 38if (!itemdata('init')) throw 'Can\'t set value before init'; 39//if readonly now and it wasn't readonly, remove the eventhandlers. 40if (p1 == 'readonly' && !itemdata('readonly')) { 41item.find('.rateit-range').unbind(); 42itemdata('wired', false); 43} 44if (p1 == 'value' && p2 == null) p2 = itemdata('min'); //when we receive a null value, reset the score to its min value. 45if (itemdata('backingfld')) { 46//if we have a backing field, check which fields we should update. 47//In case of input[type=range], although we did read its attributes even in browsers that don't support it (using fld.attr()) 48//we only update it in browser that support it (&& fld[0].min only works in supporting browsers), not only does it save us from checking if it is range input type, it also is unnecessary. 49var fld = $(itemdata('backingfld')); 50if (p1 == 'value') fld.val(p2); 51if (p1 == 'min' && fld[0].min) fld[0].min = p2; 52if (p1 == 'max' && fld[0].max) fld[0].max = p2; 53if (p1 == 'step' && fld[0].step) fld[0].step = p2; 54} 55itemdata(p1, p2); 56} 57//init rateit plugin 58if (!itemdata('init')) { 59//get our values, either from the data-* html5 attribute or from the options. 60itemdata('min', itemdata('min') || options.min); 61itemdata('max', itemdata('max') || options.max); 62itemdata('step', itemdata('step') || options.step); 63itemdata('readonly', itemdata('readonly') !== undefined ? itemdata('readonly') : options.readonly); 64itemdata('resetable', itemdata('resetable') !== undefined ? itemdata('resetable') : options.resetable); 65itemdata('backingfld', itemdata('backingfld') || options.backingfld); 66itemdata('starwidth', itemdata('starwidth') || options.starwidth); 67itemdata('starheight', itemdata('starheight') || options.starheight); 68itemdata('value', itemdata('value') || options.value || options.min); 69itemdata('ispreset', itemdata('ispreset') !== undefined ? itemdata('ispreset') : options.ispreset);
70//are we LTR or RTL? 71if (itemdata('backingfld')) { 72//if we have a backing field, hide it, and get its value, and override defaults if range. 73var fld = $(itemdata('backingfld')); 74itemdata('value', fld.hide().val()); 75if (fld.attr('disabled') || fld.attr('readonly')) 76itemdata('readonly', true); //http://rateit.codeplex.com/discussions/362055 , if a backing field is disabled or readonly at instantiation, make rateit readonly. 77if (fld[0].nodeName == 'INPUT') { 78if (fld[0].type == 'range' || fld[0].type == 'text') { //in browsers not support the range type, it defaults to text 79itemdata('min', parseInt(fld.attr('min')) || itemdata('min')); //if we would have done fld[0].min it wouldn't have worked in browsers not supporting the range type. 80itemdata('max', parseInt(fld.attr('max')) || itemdata('max')); 81itemdata('step', parseInt(fld.attr('step')) || itemdata('step')); 82} 83} 84if (fld[0].nodeName == 'SELECT' && fld[0].options.length > 1) { 85itemdata('min', Number(fld[0].options[0].value)); 86itemdata('max', Number(fld[0].options[fld[0].length - 1].value)); 87itemdata('step', Number(fld[0].options[1].value) - Number(fld[0].options[0].value)); 88} 89} 90//Create the necessary tags. 91item.append('<div class="rateit-reset"></div><div class="rateit-range"><div class="rateit-selected" style="height:' + itemdata('starheight') + 'px"></div><div class="rateit-hover" style="height:' + itemdata('starheight') + 'px"></div></div>'); 92//if we are in RTL mode, we have to change the float of the "reset button" 93if (!ltr) { 94item.find('.rateit-reset').css('float', 'right'); 95item.find('.rateit-selected').addClass('rateit-selected-rtl'); 96item.find('.rateit-hover').addClass('rateit-hover-rtl'); 97} 98itemdata('init', true); 99} 100//set the range element to fit all the stars. 101var range = item.find('.rateit-range'); 102range.width(itemdata('starwidth') * (itemdata('max') - itemdata('min'))).height(itemdata('starheight')); 103//add/remove the preset class 104var presetclass = 'rateit-preset' + ((ltr) ? '' : '-rtl'); 105if (itemdata('ispreset')) 106item.find('.rateit-selected').addClass(presetclass); 107else 108item.find('.rateit-selected').removeClass(presetclass); 109//set the value if we have it. 110if (itemdata('value') != null) { 111var score = (itemdata('value') - itemdata('min')) * itemdata('starwidth'); 112item.find('.rateit-selected').width(score); 113} 114var resetbtn = item.find('.rateit-reset'); 115if (resetbtn.data('wired') !== true) { 116resetbtn.click(function () { 117itemdata('value', itemdata('min')); 118range.find('.rateit-hover').hide().width(0); 119range.find('.rateit-selected').width(0).show(); 120if (itemdata('backingfld')) $(itemdata('backingfld')).val(itemdata('min')); 121item.trigger('reset'); 122}).data('wired', true); 123} 124var calcRawScore = function (element, event) { 125var pageX = (event.changedTouches) ? event.changedTouches[0].pageX : event.pageX; 126var offsetx = pageX - $(element).offset().left; 127if (!ltr) offsetx = range.width() - offsetx; 128if (offsetx > range.width()) offsetx = range.width(); 129if (offsetx < 0) offsetx = 0; 130return score = Math.ceil(offsetx / itemdata('starwidth') * (1 / itemdata('step'))); 131}; 132// 133if (!itemdata('readonly')) { 134//if we are not read only, add all the events 135//if we have a reset button, set the event handler. 136if (!itemdata('resetable')) 137resetbtn.hide(); 138//when the mouse goes over the range div, we set the "hover" stars. 139if (!itemdata('wired')) { 140range.bind('touchmove touchend', touchHandler); //bind touch events 141range.mousemove(function (e) { 142var score = calcRawScore(this, e); 143var w = score * itemdata('starwidth') * itemdata('step'); 144var h = range.find('.rateit-hover'); 145if (h.data('width') != w) { 146range.find('.rateit-selected').hide(); 147h.width(w).show().data('width', w); 148var data = [(score * itemdata('step')) + itemdata('min')]; 149item.trigger('hover', data).trigger('over', data); 150} 151}); 152//when the mouse leaves the range, we have to hide the hover stars, and show the current value. 153range.mouseleave(function (e) { 154range.find('.rateit-hover').hide().width(0).data('width', ''); 155item.trigger('hover', [null]).trigger('over', [null]); 156range.find('.rateit-selected').show(); 157}); 158//when we click on the range, we have to set the value, hide the hover. 159range.mouseup(function (e) { 160var score = calcRawScore(this, e); 161var newvalue = (score * itemdata('step')) + itemdata('min'); 162itemdata('value', newvalue); 163if (itemdata('backingfld')) { 164$(itemdata('backingfld')).val(newvalue); 165} 166if (itemdata('ispreset')) { //if it was a preset value, unset that. 167range.find('.rateit-selected').removeClass(presetclass); 168itemdata('ispreset', false); 169} 170range.find('.rateit-hover').hide(); 171range.find('.rateit-selected').width(score * itemdata('starwidth') * itemdata('step')).show(); 172item.trigger('hover', [null]).trigger('over', [null]).trigger('rated', [newvalue]); 173}); 174itemdata('wired', true); 175} 176if (itemdata('resetable')) { 177resetbtn.show(); 178} 179} 180else { 181resetbtn.hide(); 182} 183}); 184}; 185//touch converter http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/ 186function touchHandler(event) { 187var touches = event.originalEvent.changedTouches, 188first = touches[0], 189type = ""; 190switch (event.type) { 191case "touchmove": type = "mousemove"; break; 192case "touchend": type = "mouseup"; break; 193default: return; 194} 195var simulatedEvent = document.createEvent("MouseEvent"); 196simulatedEvent.initMouseEvent(type, true, true, window, 1, 197first.screenX, first.screenY, 198first.clientX, first.clientY, false, 199false, false, false, 0/*left*/, null); 200first.target.dispatchEvent(simulatedEvent); 201event.preventDefault(); 202}; 203//some default values. 204$.fn.rateit.defaults = { min: 0, max: 5, step: 0.5, starwidth: 16, starheight: 16, readonly: false, resetable: true, ispreset: false }; 205//invoke it on all div.rateit elements. This could be removed if not wanted. 206$(function () { $('div.rateit').rateit(); }); 207})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.