PageSourceSearch

https://www.sparkshomestore.com/js/libs/jquery.raty.min.js

js sparkshomestore.com collected 2026-09-27 08:38:49 UTC 25,261 bytes, 770 lines download raw bytes

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

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.