1/***** 2* rateyo - v2.3.3 3* http://prrashi.github.io/rateyo/ 4* Copyright (c) 2014 Prashanth Pamidi; Licensed MIT 5*****/ 6 7;(function ($) { 8 "use strict"; 9 10 // The basic svg string required to generate stars 11 var BASICSTAR = "<xml version=\"1.0\" encoding=\"utf-8\">"+ 12 "<svg version=\"1.1\""+ 13 "xmlns=\"http://www.w3.org/2000/svg\""+ 14 "viewBox=\"0 12.705 512 486.59\""+ 15 "x=\"0px\" y=\"0px\""+ 16 "xml:space=\"preserve\">"+ 17 "<polygon "+ 18 "points=\"256.814,12.705 317.205,198.566"+ 19 " 512.631,198.566 354.529,313.435 "+ 20 "414.918,499.295 256.814,384.427 "+ 21 "98.713,499.295 159.102,313.435 "+ 22 "1,198.566 196.426,198.566 \" style='stroke:black;stroke-width:30'/>"+ 23 "</svg>"; 24 25 // The Default values of different options available in the Plugin 26 var DEFAULTS = { 27 28 starWidth : "32px", 29 normalFill: "gray", 30 ratedFill : "#f39c12", 31 numStars : 5, 32 maxValue : 5, 33 precision : 1, 34 rating : 0, 35 fullStar : false, 36 halfStar : false, 37 readOnly : false, 38 spacing : "0px", 39 rtl : false, 40 multiColor: null, 41 onInit : null, 42 onChange : null, 43 onSet : null, 44 starSvg : null 45 }; 46 47 //Default colors for multi-color rating 48 var MULTICOLOR_OPTIONS = { 49 50 startColor: "#c0392b", //red 51 endColor : "#f1c40f" //yellow 52 }; 53 54 // http://stackoverflow.com/questions/11381673/detecting-a-mobile-browser 55 function isMobileBrowser () { 56 var check = false; 57 /* jshint ignore:start */ 58 (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera); 59 /* jshint ignore:end */ 60 return check; 61 } 62 63 function checkPrecision (value, minValue, maxValue) { 64 65 /* 66 * This function removes the unnecessary precision, at Min and Max Values 67 */ 68 69 // Its like comparing 0.0 with 0, which is true 70 if (value === minValue) { 71 72 value = minValue; 73 } 74 else if(value === maxValue) { 75 76 value = maxValue; 77 } 78 79 return value; 80 } 81 82 function checkBounds (value, minValue, maxValue) { 83 84 /* 85 * Check if the value is between min and max values, if not, throw an error 86 */ 87 88 var isValid = value >= minValue && value <= maxValue; 89 90 if(!isValid){ 91 92 throw Error("Invalid Rating, expected value between "+ minValue + 93 " and " + maxValue); 94 } 95 96 return value; 97 } 98 99 function isDefined(value) { 100 101 // Better way to check if a variable is defined or not 102 return typeof value !== "undefined"; 103 } 104 105 // Regex to match Colors in Hex Format like #FF00FF 106 var hexRegex = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i; 107 108 var hexToRGB = function (hex) { 109 110 /* 111 * Extracts and returns the Red, Blue, Green Channel values, 112 * in the form of decimals 113 */ 114 115 if (!hexRegex.test(hex)) { 116 117 return null; 118 } 119 120 var hexValues = hexRegex.exec(hex), 121 r = parseInt(hexValues[1], 16), 122 g = parseInt(hexValues[2], 16), 123 b = parseInt(hexValues[3], 16); 124 125 return {r:r, g:g, b:b}; 126 }; 127 128 function getChannelValue(startVal, endVal, percent) { 129 130 /* 131 * Returns a value between `startVal` and `endVal` based on the percent 132 */ 133 134 var newVal = (endVal - startVal)*(percent/100); 135 136 newVal = Math.round(startVal + newVal).toString(16); 137 138 if (newVal.length === 1) { 139 140 newVal = "0" + newVal; 141 } 142 143 return newVal; 144 } 145 146 function getColor (startColor, endColor, percent) { 147 148 /* 149 * Given the percentage( `percent` ) of `endColor` to be mixed 150 * with the `startColor`, returns the mixed color. 151 * Colors should be only in Hex Format 152 */ 153 154 if (!startColor || !endColor) { 155 156 return null; 157 } 158 159 percent = isDefined(percent)? percent : 0; 160 161 startColor = hexToRGB(startColor); 162 endColor = hexToRGB(endColor); 163 164 var r = getChannelValue(startColor.r, endColor.r, percent), 165 b = getChannelValue(startColor.b, endColor.b, percent), 166 g = getChannelValue(startColor.g, endColor.g, percent); 167 168 return "#" + r + g + b; 169 } 170 171 function RateYo ($node, options) { 172 173 /* 174 * The Contructor, whose instances are used by plugin itself 175 */ 176 177 // Storing the HTML element as a property, for future access 178 this.node = $node.get(0); 179 180 var that = this; 181 182 // Remove any stuff that is present inside the container, and add the plugin class 183 $node.empty().addClass("jq-ry-container"); 184 185 /* 186 * Basically the plugin displays the rating using two rows of stars lying one above 187 * the other, the row that is on the top represents the actual rating, and the one 188 * behind acts just like a background. 189 * 190 * `$groupWrapper`: is an element that wraps both the rows 191 * `$normalGroup`: is the container for row of stars thats behind and 192 * acts as background 193 * `$ratedGroup`: is the container for row of stars that display the actual rating. 194 * 195 * The rating is displayed by adjusting the width of `$ratedGroup` 196 */ 197 var $groupWrapper = $("<div/>").addClass("jq-ry-group-wrapper") 198 .appendTo($node); 199 200 var $normalGroup = $("<div/>").addClass("jq-ry-normal-group") 201 .addClass("jq-ry-group") 202 .appendTo($groupWrapper); 203 204 var $ratedGroup = $("<div/>").addClass("jq-ry-rated-group") 205 .addClass("jq-ry-group") 206 .appendTo($groupWrapper); 207 208 /* 209 * Variable `step`: store the value of the rating for each star 210 * eg: if `maxValue` is 5 and `numStars` is 5, value of each star 211 * is 1. 212 * Variable `starWidth`: stores the decimal value of width of star in units of px 213 * Variable `percentOfStar`: stores the percentage of width each star takes w.r.t 214 * the container 215 * Variable `spacing`: stores the decimal value of the spacing between stars 216 * in the units of px 217 * Variable `percentOfSpacing`: stores the percentage of width of the spacing 218 * between stars w.r.t the container 219 */ 220 var step, starWidth, percentOfStar, spacing, 221 percentOfSpacing, containerWidth, minValue = 0; 222 223 /* 224 * `currentRating` contains rating that is being displayed at the latest point of 225 * time. 226 * 227 * When ever you hover over the plugin UI, the rating value changes 228 * according to the place where you point the cursor, currentRating contains 229 * the current value of rating that is being shown in the UI 230 */ 231 var currentRating = options.rating; 232 233 // A flag to store if the plugin is already being displayed in the UI 234 var isInitialized = false;
235 236 function showRating (ratingVal) { 237 238 /* 239 * The function is responsible for displaying the rating by changing 240 * the width of `$ratedGroup` 241 */ 242 243 if (!isDefined(ratingVal)) { 244 245 ratingVal = options.rating; 246 } 247 248 // Storing the value that is being shown in `currentRating`. 249 currentRating = ratingVal; 250 251 var numStarsToShow = ratingVal/step; 252 253 // calculating the percentage of width of $ratedGroup with respect to its parent 254 var percent = numStarsToShow*percentOfStar; 255 256 if (numStarsToShow > 1) { 257 258 // adding the percentage of space that is taken by the gap the stars 259 percent += (Math.ceil(numStarsToShow) - 1)*percentOfSpacing; 260 } 261 262 setRatedFill(options.ratedFill); 263 264 percent = options.rtl ? 100 - percent : percent; 265 266 if (percent < 0) { 267 268 percent = 0; 269 } else if (percent > 100) { 270 271 percent = 100; 272 } 273 274 $ratedGroup.css("width", percent + "%"); 275 } 276 277 function setContainerWidth () { 278 279 /* 280 * Set the width of the `this.node` based on the width of each star and 281 * the space between them 282 */ 283 284 containerWidth = starWidth*options.numStars + spacing*(options.numStars - 1); 285 286 percentOfStar = (starWidth/containerWidth)*100; 287 288 percentOfSpacing = (spacing/containerWidth)*100; 289 290 $node.width(containerWidth); 291 292 showRating(); 293 } 294 295 function setStarWidth (newWidth) { 296 297 /* 298 * Set the width and height of each SVG star, called whenever one changes the 299 * `starWidth` option 300 */ 301 302 // The width and height of the star should be the same 303 var starHeight = options.starWidth = newWidth; 304 305 starWidth = window.parseFloat(options.starWidth.replace("px", "")); 306 307 $normalGroup.find("svg") 308 .attr({width : options.starWidth, 309 height: starHeight}); 310 311 $ratedGroup.find("svg") 312 .attr({width : options.starWidth, 313 height: starHeight}); 314 315 setContainerWidth(); 316 317 return $node; 318 } 319 320 function setSpacing (newSpacing) { 321 322 /* 323 * Set spacing between the SVG stars, called whenever one changes 324 * the `spacing` option 325 */ 326 327 options.spacing = newSpacing; 328 329 spacing = parseFloat(options.spacing.replace("px", "")); 330 331 $normalGroup.find("svg:not(:first-child)") 332 .css({"margin-left": newSpacing}); 333 334 $ratedGroup.find("svg:not(:first-child)") 335 .css({"margin-left": newSpacing}); 336 337 setContainerWidth(); 338 339 return $node; 340 } 341 342 function setNormalFill (newFill) { 343 344 /* 345 * Set the background fill of the Stars, called whenever one changes the 346 * `normalFill` option 347 */ 348 349 options.normalFill = newFill; 350 351 var $svgs = (options.rtl ? $ratedGroup : $normalGroup).find("svg"); 352 353 $svgs.attr({fill: options.normalFill}); 354 355 return $node; 356 } 357 358 /* 359 * Store the recent `ratedFill` option in a variable 360 * so that if multiColor is unset, we can use the perviously set `ratedFill` 361 * from this variable 362 */ 363 var ratedFill = options.ratedFill; 364 365 function setRatedFill (newFill) { 366 367 /* 368 * Set ratedFill of the stars, called when one changes the `ratedFill` option 369 */ 370 371 /* 372 * If `multiColor` option is set, `newFill` variable is dynamically set 373 * based on the rating, what ever set as parameter will be discarded 374 */ 375 if (options.multiColor) { 376 377 var ratingDiff = currentRating - minValue, 378 percentCovered = (ratingDiff/options.maxValue)*100; 379 380 var colorOpts = options.multiColor || {}, 381 startColor = colorOpts.startColor || MULTICOLOR_OPTIONS.startColor, 382 endColor = colorOpts.endColor || MULTICOLOR_OPTIONS.endColor; 383 384 newFill = getColor(startColor, endColor, percentCovered); 385 } else { 386 387 ratedFill = newFill; 388 } 389 390 options.ratedFill = newFill; 391 392 var $svgs = (options.rtl ? $normalGroup : $ratedGroup).find("svg"); 393 394 $svgs.attr({fill: options.ratedFill}); 395 396 return $node; 397 } 398 399 function setRtl (newValue) { 400 401 newValue = !!newValue; 402 403 options.rtl = newValue; 404 405 setNormalFill(options.normalFill); 406 showRating(); 407 } 408 409 function setMultiColor (colorOptions) { 410 411 /* 412 * called whenever one changes the `multiColor` option 413 */ 414 415 options.multiColor = colorOptions; 416 417 // set the recently set `ratedFill` option, if multiColor Options are unset 418 setRatedFill(colorOptions ? colorOptions : ratedFill); 419 } 420 421 function setNumStars (newValue) { 422 423 /* 424 * Set the number of stars to use to display the rating, called whenever one 425 * changes the `numStars` option 426 */ 427 428 options.numStars = newValue; 429 430 step = options.maxValue/options.numStars; 431 432 $normalGroup.empty(); 433 $ratedGroup.empty(); 434 435 for (var i=0; i<options.numStars; i++) { 436 437 $normalGroup.append($(options.starSvg || BASICSTAR)); 438 $ratedGroup.append($(options.starSvg || BASICSTAR)); 439 } 440 441 setStarWidth(options.starWidth); 442 setNormalFill(options.normalFill); 443 setSpacing(options.spacing); 444 445 showRating(); 446 447 return $node; 448 } 449 450 function setMaxValue (newValue) { 451 452 /* 453 * set the Maximum Value of rating to be allowed, called whenever 454 * one changes the `maxValue` option 455 */ 456 457 options.maxValue = newValue; 458 459 step = options.maxValue/options.numStars; 460 461 if (options.rating > newValue) { 462 463 setRating(newValue); 464 } 465 466 showRating(); 467 468 return $node; 469 } 470 471 function setPrecision (newValue) { 472 473 /* 474 * Set the precision of the rating value, called if one changes the 475 * `precision` option 476 */ 477 478 options.precision = newValue; 479 480 setRating(options.rating); 481 482 return $node; 483 } 484 485 function setHalfStar (newValue) { 486 487 /* 488 * This function will be called if one changes the `halfStar` option 489 */ 490 491 options.halfStar = newValue; 492 493 return $node; 494 } 495 496 function setFullStar (newValue) { 497 498 /* 499 * This function will be called if one changes the `fullStar` option 500 */ 501 502 options.fullStar = newValue; 503 504 return $node; 505 } 506 507 function round (value) { 508 509 /* 510 * Rounds the value of rating if `halfStar` or `fullStar` options are chosen 511 */ 512 513 var remainder = value%step, 514 halfStep = step/2, 515 isHalfStar = options.halfStar, 516 isFullStar = options.fullStar; 517 518 if (!isFullStar && !isHalfStar) { 519 520 return value; 521 } 522 523 if (isFullStar || (isHalfStar && remainder > halfStep)) { 524 525 value += step - remainder; 526 } else { 527 528 value = value - remainder; 529 530 if (remainder > 0) { 531 532 value += halfStep; 533 } 534 } 535 536 return value; 537 } 538 539 function calculateRating (e) { 540 541 /* 542 * Calculates and returns the rating based on the position of cursor w.r.t the 543 * plugin container 544 */ 545 546 var position = $normalGroup.offset(), 547 nodeStartX = position.left, 548 nodeEndX = nodeStartX + $normalGroup.width(); 549 550 var maxValue = options.maxValue; 551 552 // The x-coordinate(position) of the mouse pointer w.r.t page 553 var pageX = e.pageX; 554 555 var calculatedRating = 0; 556 557 // If the mouse pointer is to the left of the container 558 if(pageX < nodeStartX) { 559 560 calculatedRating = minValue; 561 }else if (pageX > nodeEndX) { // If the mouse pointer is right of the container 562 563 calculatedRating = maxValue; 564 }else { // If the mouse pointer is inside the continer 565 566 /* 567 * The fraction of width covered by the pointer w.r.t to the total width 568 * of the container. 569 */ 570 var calcPrcnt = ((pageX - nodeStartX)/(nodeEndX - nodeStartX)); 571 572 if (spacing > 0) { 573 574 /* 575 * If there is spacing between stars, take the percentage of width covered 576 * and subtract the percentage of width covered by stars and spacing, to find 577 * how many stars are covered, the number of stars covered is the rating 578 * 579 * TODO: I strongly feel that this logic can be improved!, Please help! 580 */ 581 calcPrcnt *= 100; 582 583 var remPrcnt = calcPrcnt; 584 585 while (remPrcnt > 0) { 586 587 if (remPrcnt > percentOfStar) { 588 589 calculatedRating += step; 590 remPrcnt -= (percentOfStar + percentOfSpacing); 591 } else { 592 593 calculatedRating += remPrcnt/percentOfStar*step; 594 remPrcnt = 0; 595 } 596 } 597 } else { 598 599 /* 600 * If there is not spacing between stars, the fraction of width covered per 601 * `maxValue` is the rating 602 */ 603 calculatedRating = calcPrcnt * (options.maxValue); 604 } 605 606 // Round the rating if `halfStar` or `fullStar` options are chosen 607 calculatedRating = round(calculatedRating); 608 } 609 610 if (options.rtl) { 611 612 calculatedRating = maxValue - calculatedRating; 613 } 614 615 return parseFloat(calculatedRating); 616 } 617 618 function setReadOnly (newValue) { 619 620 /* 621 * UnBinds mouse event handlers, called when whenever one changes the 622 * `readOnly` option 623 */ 624 625 options.readOnly = newValue; 626 627 $node.attr("readonly", true); 628 629 unbindEvents(); 630 631 if (!newValue) { 632 633 $node.removeAttr("readonly"); 634 635 bindEvents(); 636 } 637 638 return $node; 639 } 640 641 function setRating (newValue) { 642 643 /* 644 * Sets the rating of the Plugin, Called when option `rating` is changed 645 * or, when `rating` method is called 646 */ 647 648 var rating = newValue; 649 650 var maxValue = options.maxValue; 651 652 if (typeof rating === "string") { 653 654 // If rating is given in percentage, maxValue should be 100 655 if (rating[rating.length - 1] === "%") { 656 657 rating = rating.substr(0, rating.length - 1); 658 maxValue = 100; 659
660 setMaxValue(maxValue); 661 } 662 663 rating = parseFloat(rating); 664 } 665 666 checkBounds(rating, minValue, maxValue); 667 668 rating = parseFloat(rating.toFixed(options.precision)); 669 670 checkPrecision(parseFloat(rating), minValue, maxValue); 671 672 options.rating = rating; 673 674 showRating(); 675 676 if (isInitialized) { 677 678 $node.trigger("rateyo.set", {rating: rating}); 679 } 680 681 return $node; 682 } 683 684 function setOnInit (method) { 685 686 /* 687 * set what method to be called on Initialization 688 */ 689 690 options.onInit = method; 691 692 return $node; 693 } 694 695 function setOnSet (method) { 696 697 /* 698 * set what method to be called when rating is set 699 */ 700 701 options.onSet = method; 702 703 return $node; 704 } 705 706 function setOnChange (method) { 707 708 /* 709 * set what method to be called rating in the UI is changed 710 */ 711 712 options.onChange = method; 713 714 return $node; 715 } 716 717 this.rating = function (newValue) { 718 719 /* 720 * rating getter/setter 721 */ 722 723 if (!isDefined(newValue)) { 724 725 return options.rating; 726 } 727 728 setRating(newValue); 729 730 return $node; 731 }; 732 733 this.destroy = function () { 734 735 /* 736 * Removes the Rating UI by clearing the content, and removing the custom classes 737 */ 738 739 if (!options.readOnly) { 740 741 unbindEvents(); 742 } 743 744 RateYo.prototype.collection = deleteInstance($node.get(0), 745 this.collection); 746 747 $node.removeClass("jq-ry-container").children().remove(); 748 749 return $node; 750 }; 751 752 this.method = function (methodName) { 753 754 /* 755 * Method to call the methods of RateYo Instance 756 */ 757 758 if (!methodName) { 759 760 throw Error("Method name not specified!"); 761 } 762 763 if (!isDefined(this[methodName])) { 764 765 throw Error("Method " + methodName + " doesn't exist!"); 766 } 767 768 var args = Array.prototype.slice.apply(arguments, []), 769 params = args.slice(1), 770 method = this[methodName]; 771 772 return method.apply(this, params); 773 }; 774 775 this.option = function (optionName, param) { 776 777 /* 778 * Method to get/set Options 779 */ 780 781 if (!isDefined(optionName)) { 782 783 return options; 784 } 785 786 var method; 787 788 switch (optionName) { 789 790 case "starWidth": 791 792 method = setStarWidth; 793 break; 794 case "numStars": 795 796 method = setNumStars; 797 break; 798 case "normalFill": 799 800 method = setNormalFill; 801 break; 802 case "ratedFill": 803 804 method = setRatedFill; 805 break; 806 case "multiColor": 807 808 method = setMultiColor; 809 break; 810 case "maxValue": 811 812 method = setMaxValue; 813 break; 814 case "precision": 815 816 method = setPrecision; 817 break; 818 case "rating": 819 820 method = setRating; 821 break; 822 case "halfStar": 823 824 method = setHalfStar; 825 break; 826 case "fullStar": 827 828 method = setFullStar; 829 break; 830 case "readOnly": 831 832 method = setReadOnly; 833 break; 834 case "spacing": 835 836 method = setSpacing; 837 break; 838 case "rtl": 839 840 method = setRtl; 841 break; 842 case "onInit": 843 844 method = setOnInit; 845 break; 846 case "onSet": 847 848 method = setOnSet; 849 break; 850 case "onChange": 851 852 method = setOnChange; 853 break; 854 default: 855 856 throw Error("No such option as " + optionName); 857 } 858 859 return isDefined(param) ? method(param) : options[optionName]; 860 }; 861 862 function onMouseEnter (e) { 863 864 /* 865 * If the Mouse Pointer is inside the container, calculate and show the rating 866 * in UI 867 */ 868 869 var rating = calculateRating(e).toFixed(options.precision); 870 871 var maxValue = options.maxValue; 872 873 rating = checkPrecision(parseFloat(rating), minValue, maxValue); 874 875 showRating(rating); 876 877 $node.trigger("rateyo.change", {rating: rating}); 878 } 879 880 function onMouseLeave () { 881 if (isMobileBrowser()) { 882 return; 883 } 884 885 /* 886 * If mouse leaves, revert the rating in UI to previously set rating, 887 * when empty value is passed to showRating, it will take the previously set 888 * rating 889 */ 890 891 showRating(); 892 893 $node.trigger("rateyo.change", {rating: options.rating}); 894 } 895 896 function onMouseClick (e) { 897 898 /* 899 * On clicking the mouse inside the container, calculate and set the rating 900 */ 901 902 var resultantRating = calculateRating(e).toFixed(options.precision); 903 resultantRating = parseFloat(resultantRating); 904 905 that.rating(resultantRating); 906 } 907 908 function onInit(e, data) { 909 910 if(options.onInit && typeof options.onInit === "function") { 911 912 /* jshint validthis:true */ 913 options.onInit.apply(this, [data.rating, that]); 914 } 915 } 916 917 function onChange (e, data) { 918 919 if(options.onChange && typeof options.onChange === "function") { 920 921 /* jshint validthis:true */ 922 options.onChange.apply(this, [data.rating, that]); 923 } 924 } 925 926 function onSet (e, data) { 927 928 if(options.onSet && typeof options.onSet === "function") { 929 930 /* jshint validthis:true */ 931 options.onSet.apply(this, [data.rating, that]); 932 } 933 } 934 935 function bindEvents () { 936 937 $node.on("mousemove", onMouseEnter) 938 .on("mouseenter", onMouseEnter) 939 .on("mouseleave", onMouseLeave) 940 .on("click", onMouseClick) 941 .on("rateyo.init", onInit) 942 .on("rateyo.change", onChange) 943 .on("rateyo.set", onSet); 944 } 945 946 function unbindEvents () { 947 948 $node.off("mousemove", onMouseEnter) 949 .off("mouseenter", onMouseEnter) 950 .off("mouseleave", onMouseLeave) 951 .off("click", onMouseClick) 952 .off("rateyo.init", onInit) 953 .off("rateyo.change", onChange) 954 .off("rateyo.set", onSet); 955 } 956 957 setNumStars(options.numStars); 958 setReadOnly(options.readOnly); 959 960 if (options.rtl) { 961 962 setRtl(options.rtl); 963 } 964 965 this.collection.push(this); 966 this.rating(options.rating, true); 967 968 isInitialized = true; 969 $node.trigger("rateyo.init", {rating: options.rating}); 970 } 971 972 RateYo.prototype.collection = []; 973 974 function getInstance (node, collection) { 975 976 /* 977 * Given a HTML element (node) and a collection of RateYo instances, 978 * this function will search through the collection and return the matched 979 * instance having the node 980 */ 981 982 var instance; 983 984 $.each(collection, function () { 985 986 if(node === this.node){ 987 988 instance = this; 989 return false;
990 } 991 }); 992 993 return instance; 994 } 995 996 function deleteInstance (node, collection) { 997 998 /* 999 * Given a HTML element (node) and a collection of RateYo instances, 1000 * this function will search through the collection and delete the 1001 * instance having the node, and return the modified collection 1002 */ 1003 1004 $.each(collection, function (index) { 1005 1006 if (node === this.node) { 1007 1008 var firstPart = collection.slice(0, index), 1009 secondPart = collection.slice(index+1, collection.length); 1010 1011 collection = firstPart.concat(secondPart); 1012 1013 return false; 1014 } 1015 }); 1016 1017 return collection; 1018 } 1019 1020 function _rateYo (options) { 1021 1022 var rateYoInstances = RateYo.prototype.collection; 1023 1024 /* jshint validthis:true */ 1025 var $nodes = $(this); 1026 1027 if($nodes.length === 0) { 1028 1029 return $nodes; 1030 } 1031 1032 var args = Array.prototype.slice.apply(arguments, []); 1033 1034 if (args.length === 0) { 1035 1036 //If args length is 0, Initialize the UI with default settings 1037 options = args[0] = {}; 1038 }else if (args.length === 1 && typeof args[0] === "object") { 1039 1040 //If an Object is specified as first argument, it is considered as options 1041 options = args[0]; 1042 }else if (args.length >= 1 && typeof args[0] === "string") { 1043 1044 /* 1045 * if there is only one argument, and if its a string, it is supposed to be a 1046 * method name, if more than one argument is specified, the remaining arguments 1047 * except the first argument, will be passed as a params to the specified method 1048 */ 1049 1050 var methodName = args[0], 1051 params = args.slice(1); 1052 1053 var result = []; 1054 1055 $.each($nodes, function (i, node) { 1056 1057 var existingInstance = getInstance(node, rateYoInstances); 1058 1059 if(!existingInstance) { 1060 1061 throw Error("Trying to set options before even initialization"); 1062 } 1063 1064 var method = existingInstance[methodName]; 1065 1066 if (!method) { 1067 1068 throw Error("Method " + methodName + " does not exist!"); 1069 } 1070 1071 var returnVal = method.apply(existingInstance, params); 1072 1073 result.push(returnVal); 1074 }); 1075 1076 /* 1077 * If the plugin in being called on only one jQuery Element, return only the 1078 * first value, to support chaining. 1079 */ 1080 result = result.length === 1? result[0]: result; 1081 1082 return result; 1083 }else { 1084 1085 throw Error("Invalid Arguments"); 1086 } 1087 1088 /* 1089 * if only options are passed, extend default options, and if the plugin is not 1090 * initialized on a particular jQuery element, initalize RateYo on it 1091 */ 1092 options = $.extend({}, DEFAULTS, options); 1093 1094 return $.each($nodes, function () { 1095 1096 var existingInstance = getInstance(this, rateYoInstances); 1097 1098 if (existingInstance) { 1099 1100 return existingInstance; 1101 } 1102 1103 var $node = $(this), 1104 dataAttrs = {}, 1105 optionsCopy = $.extend({}, options); 1106 1107 $.each($node.data(), function (key, value) { 1108 1109 if (key.indexOf("rateyo") !== 0) { 1110 1111 return; 1112 } 1113 1114 var optionName = key.replace(/^rateyo/, ""); 1115 1116 optionName = optionName[0].toLowerCase() + optionName.slice(1); 1117 1118 dataAttrs[optionName] = value; 1119 1120 delete optionsCopy[optionName]; 1121 }); 1122 1123 return new RateYo($(this), $.extend({}, dataAttrs, optionsCopy)); 1124 }); 1125 } 1126 1127 function rateYo () { 1128 1129 /* jshint validthis:true */ 1130 return _rateYo.apply(this, Array.prototype.slice.apply(arguments, [])); 1131 } 1132 1133 window.RateYo = RateYo; 1134 $.fn.rateYo = rateYo; 1135 1136}(window.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.