1/*! 2 * jQuery Raty - A Star Rating Plugin 3 * 4 * The MIT License 5 * 6 * @author : Washington Botelho 7 * @doc : http://wbotelhos.com/raty 8 * @version : 2.7.0 9 * 10 */ 11 12; 13(function($) { 14 'use strict'; 15 16 var methods = { 17 init: function(options) { 18 return this.each(function() { 19 this.self = $(this); 20 21 methods.destroy.call(this.self); 22 23 this.opt = $.extend(true, {}, $.fn.raty.defaults, options); 24 25 methods._adjustCallback.call(this); 26 methods._adjustNumber.call(this); 27 methods._adjustHints.call(this); 28 29 this.opt.score = methods._adjustedScore.call(this, this.opt.score); 30 31 if (this.opt.starType !== 'img') { 32 methods._adjustStarType.call(this); 33 } 34 35 methods._adjustPath.call(this); 36 methods._createStars.call(this); 37 38 if (this.opt.cancel) { 39 methods._createCancel.call(this); 40 } 41 42 if (this.opt.precision) { 43 methods._adjustPrecision.call(this); 44 } 45 46 methods._createScore.call(this); 47 methods._apply.call(this, this.opt.score); 48 methods._setTitle.call(this, this.opt.score); 49 methods._target.call(this, this.opt.score); 50 51 if (this.opt.readOnly) { 52 methods._lock.call(this); 53 } else { 54 this.style.cursor = 'pointer'; 55 56 methods._binds.call(this); 57 } 58 }); 59 }, 60 61 _adjustCallback: function() { 62 var options = ['number', 'readOnly', 'score', 'scoreName', 'target']; 63 64 for (var i = 0; i < options.length; i++) { 65 if (typeof this.opt[options[i]] === 'function') { 66 this.opt[options[i]] = this.opt[options[i]].call(this); 67 } 68 } 69 }, 70 71 _adjustedScore: function(score) { 72 if (!score) { 73 return score; 74 } 75 76 return methods._between(score, 0, this.opt.number); 77 }, 78 79 _adjustHints: function() { 80 if (!this.opt.hints) { 81 this.opt.hints = []; 82 } 83 84 if (!this.opt.halfShow && !this.opt.half) { 85 return; 86 } 87 88 var steps = this.opt.precision ? 10 : 2; 89 90 for (var i = 0; i < this.opt.number; i++) { 91 var group = this.opt.hints[i]; 92 93 if (Object.prototype.toString.call(group) !== '[object Array]') { 94 group = [group]; 95 } 96 97 this.opt.hints[i] = []; 98 99 for (var j = 0; j < steps; j++) { 100 var 101 hint = group[j], 102 last = group[group.length - 1]; 103 104 if (last === undefined) { 105 last = null; 106 } 107 108 this.opt.hints[i][j] = hint === undefined ? last : hint; 109 } 110 } 111 }, 112 113 _adjustNumber: function() { 114 this.opt.number = methods._between(this.opt.number, 1, this.opt.numberMax); 115 }, 116 117 _adjustPath: function() { 118 this.opt.path = this.opt.path || ''; 119 120 if (this.opt.path && this.opt.path.charAt(this.opt.path.length - 1) !== '/') { 121 this.opt.path += '/'; 122 } 123 }, 124 125 _adjustPrecision: function() { 126 this.opt.half = true; 127 }, 128 129 _adjustStarType: function() { 130 var replaces = ['cancelOff', 'cancelOn', 'starHalf', 'starOff', 'starOn']; 131 132 this.opt.path = ''; 133 134 for (var i = 0; i < replaces.length; i++) { 135 this.opt[replaces[i]] = this.opt[replaces[i]].replace('.', '-'); 136 } 137 }, 138 139 _apply: function(score) { 140 methods._fill.call(this, score); 141 142 if (score) { 143 if (score > 0) { 144 this.score.val(score); 145 } 146 147 methods._roundStars.call(this, score); 148 } 149 }, 150 151 _between: function(value, min, max) { 152 return Math.min(Math.max(parseFloat(value), min), max); 153 }, 154 155 _binds: function() { 156 if (this.cancel) { 157 methods._bindOverCancel.call(this); 158 methods._bindClickCancel.call(this); 159 methods._bindOutCancel.call(this); 160 } 161 162 methods._bindOver.call(this); 163 methods._bindClick.call(this); 164 methods._bindOut.call(this); 165 }, 166 167 _bindClick: function() { 168 var that = this; 169 170 that.stars.on('click.raty', function(evt) { 171 var 172 execute = true, 173 score = (that.opt.half || that.opt.precision) ? that.self.data('score') : (this.alt || $(this).data('alt')); 174 175 if (that.opt.click) { 176 execute = that.opt.click.call(that, +score, evt); 177 } 178 179 if (execute || execute === undefined) { 180 if (that.opt.half && !that.opt.precision) {
181 score = methods._roundHalfScore.call(that, score); 182 } 183 184 methods._apply.call(that, score); 185 } 186 }); 187 }, 188 189 _bindClickCancel: function() { 190 var that = this; 191 192 that.cancel.on('click.raty', function(evt) { 193 that.score.removeAttr('value'); 194 195 if (that.opt.click) { 196 that.opt.click.call(that, null, evt); 197 } 198 }); 199 }, 200 201 _bindOut: function() { 202 var that = this; 203 204 that.self.on('mouseleave.raty', function(evt) { 205 var score = +that.score.val() || undefined; 206 207 methods._apply.call(that, score); 208 methods._target.call(that, score, evt); 209 methods._resetTitle.call(that); 210 211 if (that.opt.mouseout) { 212 that.opt.mouseout.call(that, score, evt); 213 } 214 }); 215 }, 216 217 _bindOutCancel: function() { 218 var that = this; 219 220 that.cancel.on('mouseleave.raty', function(evt) { 221 var icon = that.opt.cancelOff; 222 223 if (that.opt.starType !== 'img') { 224 icon = that.opt.cancelClass + ' ' + icon; 225 } 226 227 methods._setIcon.call(that, this, icon); 228 229 if (that.opt.mouseout) { 230 var score = +that.score.val() || undefined; 231 232 that.opt.mouseout.call(that, score, evt); 233 } 234 }); 235 }, 236 237 _bindOver: function() { 238 var that = this, 239 action = that.opt.half ? 'mousemove.raty' : 'mouseover.raty'; 240 241 that.stars.on(action, function(evt) { 242 var score = methods._getScoreByPosition.call(that, evt, this); 243 244 methods._fill.call(that, score); 245 246 if (that.opt.half) { 247 methods._roundStars.call(that, score, evt); 248 methods._setTitle.call(that, score, evt); 249 250 that.self.data('score', score); 251 } 252 253 methods._target.call(that, score, evt); 254 255 if (that.opt.mouseover) { 256 that.opt.mouseover.call(that, score, evt); 257 } 258 }); 259 }, 260 261 _bindOverCancel: function() { 262 var that = this; 263 264 that.cancel.on('mouseover.raty', function(evt) { 265 var 266 starOff = that.opt.path + that.opt.starOff, 267 icon = that.opt.cancelOn; 268 269 if (that.opt.starType === 'img') { 270 that.stars.attr('src', starOff); 271 } else { 272 icon = that.opt.cancelClass + ' ' + icon; 273 274 that.stars.attr('class', starOff); 275 } 276 277 methods._setIcon.call(that, this, icon); 278 methods._target.call(that, null, evt); 279 280 if (that.opt.mouseover) { 281 that.opt.mouseover.call(that, null); 282 } 283 }); 284 }, 285 286 _buildScoreField: function() { 287 return $('<input />', { name: this.opt.scoreName, type: 'hidden' }).appendTo(this); 288 }, 289 290 _createCancel: function() { 291 var icon = this.opt.path + this.opt.cancelOff, 292 cancel = $('<' + this.opt.starType + ' />', { title: this.opt.cancelHint, 'class': this.opt.cancelClass }); 293 294 if (this.opt.starType === 'img') { 295 cancel.attr({ src: icon, alt: 'x' }); 296 } else { 297 // TODO: use $.data 298 cancel.attr('data-alt', 'x').addClass(icon); 299 } 300 301 if (this.opt.cancelPlace === 'left') { 302 this.self.prepend(' ').prepend(cancel); 303 } else { 304 this.self.append(' ').append(cancel); 305 } 306 307 this.cancel = cancel; 308 }, 309 310 _createScore: function() { 311 var score = $(this.opt.targetScore); 312 313 this.score = score.length ? score : methods._buildScoreField.call(this); 314 }, 315 316 _createStars: function() { 317 for (var i = 1; i <= this.opt.number; i++) { 318 var 319 name = methods._nameForIndex.call(this, i), 320 attrs = { alt: i, src: this.opt.path + this.opt[name] }; 321 322 if (this.opt.starType !== 'img') { 323 attrs = { 'data-alt': i, 'class': attrs.src }; // TODO: use $.data. 324 } 325 326 attrs.title = methods._getHint.call(this, i); 327 328 $('<' + this.opt.starType + ' />', attrs).appendTo(this); 329 330 if (this.opt.space) { 331 this.self.append(i < this.opt.number ? ' ' : ''); 332 } 333 } 334 335 this.stars = this.self.children(this.opt.starType); 336 }, 337 338 _error: function(message) { 339 $(this).text(message); 340 341 $.error(message); 342 }, 343 344 _fill: function(score) { 345 var hash = 0; 346 347 for (var i = 1; i <= this.stars.length; i++) { 348 var 349 icon, 350 star = this.stars[i - 1], 351 turnOn = methods._turnOn.call(this, i, score); 352 353 if (this.opt.iconRange && this.opt.iconRange.length > hash) { 354 var irange = this.opt.iconRange[hash]; 355 356 icon = methods._getRangeIcon.call(this, irange, turnOn); 357 358 if (i <= irange.range) { 359 methods._setIcon.call(this, star, icon); 360 } 361 362 if (i === irange.range) { 363 hash++; 364 } 365 } else { 366 icon = this.opt[turnOn ? 'starOn' : 'starOff']; 367 368 methods._setIcon.call(this, star, icon); 369 } 370 } 371 }, 372
373 _getFirstDecimal: function(number) { 374 var 375 decimal = number.toString().split('.')[1], 376 result = 0; 377 378 if (decimal) { 379 result = parseInt(decimal.charAt(0), 10); 380 381 if (decimal.slice(1, 5) === '9999') { 382 result++; 383 } 384 } 385 386 return result; 387 }, 388 389 _getRangeIcon: function(irange, turnOn) { 390 return turnOn ? irange.on || this.opt.starOn : irange.off || this.opt.starOff; 391 }, 392 393 _getScoreByPosition: function(evt, icon) { 394 var score = parseInt(icon.alt || icon.getAttribute('data-alt'), 10); 395 396 if (this.opt.half) { 397 var 398 size = methods._getWidth.call(this), 399 percent = parseFloat((evt.pageX - $(icon).offset().left) / size); 400 401 score = score - 1 + percent; 402 } 403 404 return score; 405 }, 406 407 _getHint: function(score, evt) { 408 if (score !== 0 && !score) { 409 return this.opt.noRatedMsg; 410 } 411 412 var 413 decimal = methods._getFirstDecimal.call(this, score), 414 integer = Math.ceil(score), 415 group = this.opt.hints[(integer || 1) - 1], 416 hint = group, 417 set = !evt || this.move; 418 419 if (this.opt.precision) { 420 if (set) { 421 decimal = decimal === 0 ? 9 : decimal - 1; 422 } 423 424 hint = group[decimal]; 425 } else if (this.opt.halfShow || this.opt.half) { 426 decimal = set && decimal === 0 ? 1 : decimal > 5 ? 1 : 0; 427 428 hint = group[decimal]; 429 } 430 431 return hint === '' ? '' : hint || score; 432 }, 433 434 _getWidth: function() { 435 var width = this.stars[0].width || parseFloat(this.stars.eq(0).css('font-size')); 436 437 if (!width) { 438 methods._error.call(this, 'Could not get the icon width!'); 439 } 440 441 return width; 442 }, 443 444 _lock: function() { 445 var hint = methods._getHint.call(this, this.score.val()); 446 447 this.style.cursor = ''; 448 this.title = hint; 449 450 this.score.prop('readonly', true); 451 this.stars.prop('title', hint); 452 453 if (this.cancel) { 454 this.cancel.hide(); 455 } 456 457 this.self.data('readonly', true); 458 }, 459 460 _nameForIndex: function(i) { 461 return this.opt.score && this.opt.score >= i ? 'starOn' : 'starOff'; 462 }, 463 464 _resetTitle: function(star) { 465 for (var i = 0; i < this.opt.number; i++) { 466 this.stars[i].title = methods._getHint.call(this, i + 1); 467 } 468 }, 469 470 _roundHalfScore: function(score) { 471 var integer = parseInt(score, 10), 472 decimal = methods._getFirstDecimal.call(this, score); 473 474 if (decimal !== 0) { 475 decimal = decimal > 5 ? 1 : 0.5; 476 } 477 478 return integer + decimal; 479 }, 480 481 _roundStars: function(score, evt) { 482 var 483 decimal = (score % 1).toFixed(2), 484 name ; 485 486 if (evt || this.move) { 487 name = decimal > 0.5 ? 'starOn' : 'starHalf'; 488 } else if (decimal > this.opt.round.down) { // Up: [x.76 .. x.99] 489 name = 'starOn'; 490 491 if (this.opt.halfShow && decimal < this.opt.round.up) { // Half: [x.26 .. x.75] 492 name = 'starHalf'; 493 } else if (decimal < this.opt.round.full) { // Down: [x.00 .. x.5] 494 name = 'starOff'; 495 } 496 } 497 498 if (name) { 499 var 500 icon = this.opt[name], 501 star = this.stars[Math.ceil(score) - 1]; 502 503 methods._setIcon.call(this, star, icon); 504 } // Full down: [x.00 .. x.25] 505 }, 506 507 _setIcon: function(star, icon) { 508 star[this.opt.starType === 'img' ? 'src' : 'className'] = this.opt.path + icon; 509 }, 510 511 _setTarget: function(target, score) { 512 if (score) { 513 score = this.opt.targetFormat.toString().replace('{score}', score); 514 } 515 516 if (target.is(':input')) { 517 target.val(score); 518 } else { 519 target.html(score); 520 } 521 }, 522 523 _setTitle: function(score, evt) { 524 if (score) { 525 var 526 integer = parseInt(Math.ceil(score), 10), 527 star = this.stars[integer - 1]; 528 529 star.title = methods._getHint.call(this, score, evt); 530 } 531 }, 532 533 _target: function(score, evt) { 534 if (this.opt.target) { 535 var target = $(this.opt.target); 536 537 if (!target.length) { 538 methods._error.call(this, 'Target selector invalid or missing!'); 539 } 540 541 var mouseover = evt && evt.type === 'mouseover'; 542 543 if (score === undefined) { 544 score = this.opt.targetText; 545 } else if (score === null) { 546 score = mouseover ? this.opt.cancelHint : this.opt.targetText; 547 } else { 548 if (this.opt.targetType === 'hint') { 549 score = methods._getHint.call(this, score, evt); 550 } else if (this.opt.precision) { 551 score = parseFloat(score).toFixed(1); 552 } 553 554 var mousemove = evt && evt.type === 'mousemove'; 555 556 if (!mouseover && !mousemove && !this.opt.targetKeep) { 557 score = this.opt.targetText; 558 } 559 } 560 561 methods._setTarget.call(this, target, score); 562 } 563 }, 564 565 _turnOn: function(i, score) { 566 return this.opt.single ? (i === score) : (i <= score); 567 }, 568 569 _unlock: function() { 570 this.style.cursor = 'pointer'; 571 this.removeAttribute('title'); 572 573 this.score.removeAttr('readonly'); 574 575 this.self.data('readonly', false); 576 577 for (var i = 0; i < this.opt.number; i++) { 578 this.stars[i].title = methods._getHint.call(this, i + 1); 579 } 580 581 if (this.cancel) { 582 this.cancel.css('display', ''); 583 } 584 }, 585 586 cancel: function(click) { 587 return this.each(function() { 588 var self = $(this); 589 590 if (self.data('readonly') !== true) { 591 methods[click ? 'click' : 'score'].call(self, null); 592 593 this.score.removeAttr('value'); 594 } 595 }); 596 }, 597 598 click: function(score) { 599 return this.each(function() { 600 if ($(this).data('readonly') !== true) {
601 score = methods._adjustedScore.call(this, score); 602 603 methods._apply.call(this, score); 604 605 if (this.opt.click) { 606 this.opt.click.call(this, score, $.Event('click')); 607 } 608 609 methods._target.call(this, score); 610 } 611 }); 612 }, 613 614 destroy: function() { 615 return this.each(function() { 616 var self = $(this), 617 raw = self.data('raw'); 618 619 if (raw) { 620 self.off('.raty').empty().css({ cursor: raw.style.cursor }).removeData('readonly'); 621 } else { 622 self.data('raw', self.clone()[0]); 623 } 624 }); 625 }, 626 627 getScore: function() { 628 var score = [], 629 value ; 630 631 this.each(function() { 632 value = this.score.val(); 633 634 score.push(value ? +value : undefined); 635 }); 636 637 return (score.length > 1) ? score : score[0]; 638 }, 639 640 move: function(score) { 641 return this.each(function() { 642 var 643 integer = parseInt(score, 10), 644 decimal = methods._getFirstDecimal.call(this, score); 645 646 if (integer >= this.opt.number) { 647 integer = this.opt.number - 1; 648 decimal = 10; 649 } 650 651 var 652 width = methods._getWidth.call(this), 653 steps = width / 10, 654 star = $(this.stars[integer]), 655 percent = star.offset().left + steps * decimal, 656 evt = $.Event('mousemove', { pageX: percent }); 657 658 this.move = true; 659 660 star.trigger(evt); 661 662 this.move = false; 663 }); 664 }, 665 666 readOnly: function(readonly) { 667 return this.each(function() { 668 var self = $(this); 669 670 if (self.data('readonly') !== readonly) { 671 if (readonly) { 672 self.off('.raty').children('img').off('.raty'); 673 674 methods._lock.call(this); 675 } else { 676 methods._binds.call(this); 677 methods._unlock.call(this); 678 } 679 680 self.data('readonly', readonly); 681 } 682 }); 683 }, 684 685 reload: function() { 686 return methods.set.call(this, {}); 687 }, 688 689 score: function() { 690 var self = $(this); 691 692 return arguments.length ? methods.setScore.apply(self, arguments) : methods.getScore.call(self); 693 }, 694 695 set: function(options) { 696 return this.each(function() { 697 $(this).raty($.extend({}, this.opt, options)); 698 }); 699 }, 700 701 setScore: function(score) { 702 return this.each(function() { 703 if ($(this).data('readonly') !== true) { 704 score = methods._adjustedScore.call(this, score); 705 706 methods._apply.call(this, score); 707 methods._target.call(this, score); 708 } 709 }); 710 } 711 }; 712 713 $.fn.raty = function(method) { 714 if (methods[method]) { 715 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 716 } else if (typeof method === 'object' || !method) { 717 return methods.init.apply(this, arguments); 718 } else { 719 $.error('Method ' + method + ' does not exist!'); 720 } 721 }; 722 723 $.fn.raty.defaults = { 724 cancel : false, 725 cancelClass : 'raty-cancel', 726 cancelHint : 'Cancel this rating!', 727 cancelOff : 'cancel-off.png', 728 cancelOn : 'cancel-on.png', 729 cancelPlace : 'left', 730 click : undefined, 731 half : false, 732 halfShow : true, 733 hints : ['bad', 'poor', 'regular', 'good', 'gorgeous'], 734 iconRange : undefined, 735 mouseout : undefined, 736 mouseover : undefined, 737 noRatedMsg : 'Not rated yet!', 738 number : 5, 739 numberMax : 20, 740 path : undefined, 741 precision : false, 742 readOnly : false, 743 round : { down: 0.25, full: 0.6, up: 0.76 }, 744 score : undefined, 745 scoreName : 'score', 746 single : false, 747 space : true, 748 starHalf : 'star-half.png', 749 starOff : 'star-off.png', 750 starOn : 'star-on.png', 751 starType : 'img', 752 target : undefined, 753 targetFormat : '{score}', 754 targetKeep : false, 755 targetScore : undefined, 756 targetText : '', 757 targetType : 'hint' 758 }; 759 760})(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.