123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- /*!
- * bootstrap-star-rating v4.0.2
- * http://plugins.krajee.com/star-rating
- *
- * Author: Kartik Visweswaran
- * Copyright: 2013 - 2017, Kartik Visweswaran, Krajee.com
- *
- * Licensed under the BSD 3-Clause
- * https://github.com/kartik-v/bootstrap-star-rating/blob/master/LICENSE.md
- */
- (function (factory) {
- "use strict";
- //noinspection JSUnresolvedVariable
- if (typeof define === 'function' && define.amd) { // jshint ignore:line
- // AMD. Register as an anonymous module.
- define(['jquery'], factory); // jshint ignore:line
- } else { // noinspection JSUnresolvedVariable
- if (typeof module === 'object' && module.exports) { // jshint ignore:line
- // Node/CommonJS
- // noinspection JSUnresolvedVariable
- module.exports = factory(require('jquery')); // jshint ignore:line
- } else {
- // Browser globals
- factory(window.jQuery);
- }
- }
- }(function ($) {
- "use strict";
- $.fn.ratingLocales = {};
- $.fn.ratingThemes = {};
- var $h, Rating;
- // global helper methods and constants
- $h = {
- NAMESPACE: '.rating',
- DEFAULT_MIN: 0,
- DEFAULT_MAX: 5,
- DEFAULT_STEP: 0.5,
- isEmpty: function (value, trim) {
- return value === null || value === undefined || value.length === 0 || (trim && $.trim(value) === '');
- },
- getCss: function (condition, css) {
- return condition ? ' ' + css : '';
- },
- addCss: function ($el, css) {
- $el.removeClass(css).addClass(css);
- },
- getDecimalPlaces: function (num) {
- var m = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
- return !m ? 0 : Math.max(0, (m[1] ? m[1].length : 0) - (m[2] ? +m[2] : 0));
- },
- applyPrecision: function (val, precision) {
- return parseFloat(val.toFixed(precision));
- },
- handler: function ($el, event, callback, skipOff, skipNS) {
- var ev = skipNS ? event : event.split(' ').join($h.NAMESPACE + ' ') + $h.NAMESPACE;
- if (!skipOff) {
- $el.off(ev);
- }
- $el.on(ev, callback);
- }
- };
- // rating constructor
- Rating = function (element, options) {
- var self = this;
- self.$element = $(element);
- self._init(options);
- };
- Rating.prototype = {
- constructor: Rating,
- _parseAttr: function (vattr, options) {
- var self = this, $el = self.$element, elType = $el.attr('type'), finalVal, val, chk, out;
- if (elType === 'range' || elType === 'number') {
- val = options[vattr] || $el.data(vattr) || $el.attr(vattr);
- switch (vattr) {
- case 'min':
- chk = $h.DEFAULT_MIN;
- break;
- case 'max':
- chk = $h.DEFAULT_MAX;
- break;
- default:
- chk = $h.DEFAULT_STEP;
- }
- finalVal = $h.isEmpty(val) ? chk : val;
- out = parseFloat(finalVal);
- } else {
- out = parseFloat(options[vattr]);
- }
- return isNaN(out) ? chk : out;
- },
- _parseValue: function (val) {
- var self = this, v = parseFloat(val);
- if (isNaN(v)) {
- v = self.clearValue;
- }
- return (self.zeroAsNull && (v === 0 || v === '0') ? null : v);
- },
- _setDefault: function (key, val) {
- var self = this;
- if ($h.isEmpty(self[key])) {
- self[key] = val;
- }
- },
- _initSlider: function (options) {
- var self = this, v = self.$element.val();
- self.initialValue = $h.isEmpty(v) ? 0 : v;
- self._setDefault('min', self._parseAttr('min', options));
- self._setDefault('max', self._parseAttr('max', options));
- self._setDefault('step', self._parseAttr('step', options));
- if (isNaN(self.min) || $h.isEmpty(self.min)) {
- self.min = $h.DEFAULT_MIN;
- }
- if (isNaN(self.max) || $h.isEmpty(self.max)) {
- self.max = $h.DEFAULT_MAX;
- }
- if (isNaN(self.step) || $h.isEmpty(self.step) || self.step === 0) {
- self.step = $h.DEFAULT_STEP;
- }
- self.diff = self.max - self.min;
- },
- _initHighlight: function (v) {
- var self = this, w, cap = self._getCaption();
- if (!v) {
- v = self.$element.val();
- }
- w = self.getWidthFromValue(v) + '%';
- self.$filledStars.width(w);
- self.cache = {caption: cap, width: w, val: v};
- },
- _getContainerCss: function () {
- var self = this;
- return 'rating-container' +
- $h.getCss(self.theme, 'theme-' + self.theme) +
- $h.getCss(self.rtl, 'rating-rtl') +
- $h.getCss(self.size, 'rating-' + self.size) +
- $h.getCss(self.animate, 'rating-animate') +
- $h.getCss(self.disabled || self.readonly, 'rating-disabled') +
- $h.getCss(self.containerClass, self.containerClass);
- },
- _checkDisabled: function () {
- var self = this, $el = self.$element, opts = self.options;
- self.disabled = opts.disabled === undefined ? $el.attr('disabled') || false : opts.disabled;
- self.readonly = opts.readonly === undefined ? $el.attr('readonly') || false : opts.readonly;
- self.inactive = (self.disabled || self.readonly);
- $el.attr({disabled: self.disabled, readonly: self.readonly});
- },
- _addContent: function (type, content) {
- var self = this, $container = self.$container, isClear = type === 'clear';
- if (self.rtl) {
- return isClear ? $container.append(content) : $container.prepend(content);
- } else {
- return isClear ? $container.prepend(content) : $container.append(content);
- }
- },
- _generateRating: function () {
- var self = this, $el = self.$element, $rating, $container, w;
- $container = self.$container = $(document.createElement("div")).insertBefore($el);
- $h.addCss($container, self._getContainerCss());
- self.$rating = $rating = $(document.createElement("div")).attr('class', 'rating-stars').appendTo($container)
- .append(self._getStars('empty')).append(self._getStars('filled'));
- self.$emptyStars = $rating.find('.empty-stars');
- self.$filledStars = $rating.find('.filled-stars');
- self._renderCaption();
- self._renderClear();
- self._initHighlight();
- $container.append($el);
- if (self.rtl) {
- w = Math.max(self.$emptyStars.outerWidth(), self.$filledStars.outerWidth());
- self.$emptyStars.width(w);
- }
- $el.appendTo($rating);
- },
- _getCaption: function () {
- var self = this;
- return self.$caption && self.$caption.length ? self.$caption.html() : self.defaultCaption;
- },
- _setCaption: function (content) {
- var self = this;
- if (self.$caption && self.$caption.length) {
- self.$caption.html(content);
- }
- },
- _renderCaption: function () {
- var self = this, val = self.$element.val(), html, $cap = self.captionElement ? $(self.captionElement) : '';
- if (!self.showCaption) {
- return;
- }
- html = self.fetchCaption(val);
- if ($cap && $cap.length) {
- $h.addCss($cap, 'caption');
- $cap.html(html);
- self.$caption = $cap;
- return;
- }
- self._addContent('caption', '<div class="caption">' + html + '</div>');
- self.$caption = self.$container.find(".caption");
- },
- _renderClear: function () {
- var self = this, css, $clr = self.clearElement ? $(self.clearElement) : '';
- if (!self.showClear) {
- return;
- }
- css = self._getClearClass();
- if ($clr.length) {
- $h.addCss($clr, css);
- $clr.attr({"title": self.clearButtonTitle}).html(self.clearButton);
- self.$clear = $clr;
- return;
- }
- self._addContent('clear',
- '<div class="' + css + '" title="' + self.clearButtonTitle + '">' + self.clearButton + '</div>');
- self.$clear = self.$container.find('.' + self.clearButtonBaseClass);
- },
- _getClearClass: function () {
- var self = this;
- return self.clearButtonBaseClass + ' ' + (self.inactive ? '' : self.clearButtonActiveClass);
- },
- _toggleHover: function (out) {
- var self = this, w, width, caption;
- if (!out) {
- return;
- }
- if (self.hoverChangeStars) {
- w = self.getWidthFromValue(self.clearValue);
- width = out.val <= self.clearValue ? w + '%' : out.width;
- self.$filledStars.css('width', width);
- }
- if (self.hoverChangeCaption) {
- caption = out.val <= self.clearValue ? self.fetchCaption(self.clearValue) : out.caption;
- if (caption) {
- self._setCaption(caption + '');
- }
- }
- },
- _init: function (options) {
- var self = this, $el = self.$element.addClass('rating-input'), v;
- self.options = options;
- $.each(options, function (key, value) {
- self[key] = value;
- });
- if (self.rtl || $el.attr('dir') === 'rtl') {
- self.rtl = true;
- $el.attr('dir', 'rtl');
- }
- self.starClicked = false;
- self.clearClicked = false;
- self._initSlider(options);
- self._checkDisabled();
- if (self.displayOnly) {
- self.inactive = true;
- self.showClear = false;
- self.showCaption = false;
- }
- self._generateRating();
- self._initEvents();
- self._listen();
- v = self._parseValue($el.val());
- $el.val(v);
- return $el.removeClass('rating-loading');
- },
- _initEvents: function () {
- var self = this;
- self.events = {
- _getTouchPosition: function (e) {
- var pageX = $h.isEmpty(e.pageX) ? e.originalEvent.touches[0].pageX : e.pageX;
- return pageX - self.$rating.offset().left;
- },
- _listenClick: function (e, callback) {
- e.stopPropagation();
- e.preventDefault();
- if (e.handled !== true) {
- callback(e);
- e.handled = true;
- } else {
- return false;
- }
- },
- _noMouseAction: function (e) {
- return !self.hoverEnabled || self.inactive || (e && e.isDefaultPrevented());
- },
- initTouch: function (e) {
- //noinspection JSUnresolvedVariable
- var ev, touches, pos, out, caption, w, width, params, clrVal = self.clearValue || 0,
- isTouchCapable = 'ontouchstart' in window ||
- (window.DocumentTouch && document instanceof window.DocumentTouch);
- if (!isTouchCapable || self.inactive) {
- return;
- }
- ev = e.originalEvent;
- //noinspection JSUnresolvedVariable
- touches = !$h.isEmpty(ev.touches) ? ev.touches : ev.changedTouches;
- pos = self.events._getTouchPosition(touches[0]);
- if (e.type === "touchend") {
- self._setStars(pos);
- params = [self.$element.val(), self._getCaption()];
- self.$element.trigger('change').trigger('rating.change', params);
- self.starClicked = true;
- } else {
- out = self.calculate(pos);
- caption = out.val <= clrVal ? self.fetchCaption(clrVal) : out.caption;
- w = self.getWidthFromValue(clrVal);
- width = out.val <= clrVal ? w + '%' : out.width;
- self._setCaption(caption);
- self.$filledStars.css('width', width);
- }
- },
- starClick: function (e) {
- var pos, params;
- self.events._listenClick(e, function (ev) {
- if (self.inactive) {
- return false;
- }
- pos = self.events._getTouchPosition(ev);
- self._setStars(pos);
- params = [self.$element.val(), self._getCaption()];
- self.$element.trigger('change').trigger('rating.change', params);
- self.starClicked = true;
- });
- },
- clearClick: function (e) {
- self.events._listenClick(e, function () {
- if (!self.inactive) {
- self.clear();
- self.clearClicked = true;
- }
- });
- },
- starMouseMove: function (e) {
- var pos, out;
- if (self.events._noMouseAction(e)) {
- return;
- }
- self.starClicked = false;
- pos = self.events._getTouchPosition(e);
- out = self.calculate(pos);
- self._toggleHover(out);
- self.$element.trigger('rating.hover', [out.val, out.caption, 'stars']);
- },
- starMouseLeave: function (e) {
- var out;
- if (self.events._noMouseAction(e) || self.starClicked) {
- return;
- }
- out = self.cache;
- self._toggleHover(out);
- self.$element.trigger('rating.hoverleave', ['stars']);
- },
- clearMouseMove: function (e) {
- var caption, val, width, out;
- if (self.events._noMouseAction(e) || !self.hoverOnClear) {
- return;
- }
- self.clearClicked = false;
- caption = '<span class="' + self.clearCaptionClass + '">' + self.clearCaption + '</span>';
- val = self.clearValue;
- width = self.getWidthFromValue(val) || 0;
- out = {caption: caption, width: width, val: val};
- self._toggleHover(out);
- self.$element.trigger('rating.hover', [val, caption, 'clear']);
- },
- clearMouseLeave: function (e) {
- var out;
- if (self.events._noMouseAction(e) || self.clearClicked || !self.hoverOnClear) {
- return;
- }
- out = self.cache;
- self._toggleHover(out);
- self.$element.trigger('rating.hoverleave', ['clear']);
- },
- resetForm: function (e) {
- if (e && e.isDefaultPrevented()) {
- return;
- }
- if (!self.inactive) {
- self.reset();
- }
- }
- };
- },
- _listen: function () {
- var self = this, $el = self.$element, $form = $el.closest('form'), $rating = self.$rating,
- $clear = self.$clear, events = self.events;
- $h.handler($rating, 'touchstart touchmove touchend', $.proxy(events.initTouch, self));
- $h.handler($rating, 'click touchstart', $.proxy(events.starClick, self));
- $h.handler($rating, 'mousemove', $.proxy(events.starMouseMove, self));
- $h.handler($rating, 'mouseleave', $.proxy(events.starMouseLeave, self));
- if (self.showClear && $clear.length) {
- $h.handler($clear, 'click touchstart', $.proxy(events.clearClick, self));
- $h.handler($clear, 'mousemove', $.proxy(events.clearMouseMove, self));
- $h.handler($clear, 'mouseleave', $.proxy(events.clearMouseLeave, self));
- }
- if ($form.length) {
- $h.handler($form, 'reset', $.proxy(events.resetForm, self), true);
- }
- return $el;
- },
- _getStars: function (type) {
- var self = this, stars = '<span class="' + type + '-stars">', i;
- for (i = 1; i <= self.stars; i++) {
- stars += '<span class="star">' + self[type + 'Star'] + '</span>';
- }
- return stars + '</span>';
- },
- _setStars: function (pos) {
- var self = this, out = arguments.length ? self.calculate(pos) : self.calculate(), $el = self.$element,
- v = self._parseValue(out.val);
- $el.val(v);
- self.$filledStars.css('width', out.width);
- self._setCaption(out.caption);
- self.cache = out;
- return $el;
- },
- showStars: function (val) {
- var self = this, v = self._parseValue(val);
- self.$element.val(v);
- return self._setStars();
- },
- calculate: function (pos) {
- var self = this, defaultVal = $h.isEmpty(self.$element.val()) ? 0 : self.$element.val(),
- val = arguments.length ? self.getValueFromPosition(pos) : defaultVal,
- caption = self.fetchCaption(val), width = self.getWidthFromValue(val);
- width += '%';
- return {caption: caption, width: width, val: val};
- },
- getValueFromPosition: function (pos) {
- var self = this, precision = $h.getDecimalPlaces(self.step), val, factor, maxWidth = self.$rating.width();
- factor = (self.diff * pos) / (maxWidth * self.step);
- factor = self.rtl ? Math.floor(factor) : Math.ceil(factor);
- val = $h.applyPrecision(parseFloat(self.min + factor * self.step), precision);
- val = Math.max(Math.min(val, self.max), self.min);
- return self.rtl ? (self.max - val) : val;
- },
- getWidthFromValue: function (val) {
- var self = this, min = self.min, max = self.max, factor, $r = self.$emptyStars, w;
- if (!val || val <= min || min === max) {
- return 0;
- }
- w = $r.outerWidth();
- factor = w ? $r.width() / w : 1;
- if (val >= max) {
- return 100;
- }
- return (val - min) * factor * 100 / (max - min);
- },
- fetchCaption: function (rating) {
- var self = this, val = parseFloat(rating) || self.clearValue, css, cap, capVal, cssVal, caption,
- vCap = self.starCaptions, vCss = self.starCaptionClasses;
- if (val && val !== self.clearValue) {
- val = $h.applyPrecision(val, $h.getDecimalPlaces(self.step));
- }
- cssVal = typeof vCss === "function" ? vCss(val) : vCss[val];
- capVal = typeof vCap === "function" ? vCap(val) : vCap[val];
- cap = $h.isEmpty(capVal) ? self.defaultCaption.replace(/\{rating}/g, val) : capVal;
- css = $h.isEmpty(cssVal) ? self.clearCaptionClass : cssVal;
- caption = (val === self.clearValue) ? self.clearCaption : cap;
- return '<span class="' + css + '">' + caption + '</span>';
- },
- destroy: function () {
- var self = this, $el = self.$element;
- if (!$h.isEmpty(self.$container)) {
- self.$container.before($el).remove();
- }
- $.removeData($el.get(0));
- return $el.off('rating').removeClass('rating rating-input');
- },
- create: function (options) {
- var self = this, opts = options || self.options || {};
- return self.destroy().rating(opts);
- },
- clear: function () {
- var self = this, title = '<span class="' + self.clearCaptionClass + '">' + self.clearCaption + '</span>';
- if (!self.inactive) {
- self._setCaption(title);
- }
- return self.showStars(self.clearValue).trigger('change').trigger('rating.clear');
- },
- reset: function () {
- var self = this;
- return self.showStars(self.initialValue).trigger('rating.reset');
- },
- update: function (val) {
- var self = this;
- return arguments.length ? self.showStars(val) : self.$element;
- },
- refresh: function (options) {
- var self = this, $el = self.$element;
- if (!options) {
- return $el;
- }
- return self.destroy().rating($.extend(true, self.options, options)).trigger('rating.refresh');
- }
- };
- $.fn.rating = function (option) {
- var args = Array.apply(null, arguments), retvals = [];
- args.shift();
- this.each(function () {
- var self = $(this), data = self.data('rating'), options = typeof option === 'object' && option,
- theme = options.theme || self.data('theme'), lang = options.language || self.data('language') || 'en',
- thm = {}, loc = {}, opts;
- if (!data) {
- if (theme) {
- thm = $.fn.ratingThemes[theme] || {};
- }
- if (lang !== 'en' && !$h.isEmpty($.fn.ratingLocales[lang])) {
- loc = $.fn.ratingLocales[lang];
- }
- opts = $.extend(true, {}, $.fn.rating.defaults, thm, $.fn.ratingLocales.en, loc, options, self.data());
- data = new Rating(this, opts);
- self.data('rating', data);
- }
- if (typeof option === 'string') {
- retvals.push(data[option].apply(data, args));
- }
- });
- switch (retvals.length) {
- case 0:
- return this;
- case 1:
- return retvals[0] === undefined ? this : retvals[0];
- default:
- return retvals;
- }
- };
- $.fn.rating.defaults = {
- theme: '',
- language: 'en',
- stars: 5,
- filledStar: '<i class="glyphicon glyphicon-star"></i>',
- emptyStar: '<i class="glyphicon glyphicon-star-empty"></i>',
- containerClass: '',
- size: 'md',
- animate: true,
- displayOnly: false,
- rtl: false,
- showClear: true,
- showCaption: true,
- starCaptionClasses: {
- 0.5: 'label label-danger',
- 1: 'label label-danger',
- 1.5: 'label label-warning',
- 2: 'label label-warning',
- 2.5: 'label label-info',
- 3: 'label label-info',
- 3.5: 'label label-primary',
- 4: 'label label-primary',
- 4.5: 'label label-success',
- 5: 'label label-success'
- },
- clearButton: '<i class="glyphicon glyphicon-minus-sign"></i>',
- clearButtonBaseClass: 'clear-rating',
- clearButtonActiveClass: 'clear-rating-active',
- clearCaptionClass: 'label label-default',
- clearValue: null,
- captionElement: null,
- clearElement: null,
- hoverEnabled: true,
- hoverChangeCaption: true,
- hoverChangeStars: true,
- hoverOnClear: true,
- zeroAsNull: true
- };
- $.fn.ratingLocales.en = {
- defaultCaption: '{rating} Stars',
- starCaptions: {
- 0.5: 'Half Star',
- 1: 'One Star',
- 1.5: 'One & Half Star',
- 2: 'Two Stars',
- 2.5: 'Two & Half Stars',
- 3: 'Three Stars',
- 3.5: 'Three & Half Stars',
- 4: 'Four Stars',
- 4.5: 'Four & Half Stars',
- 5: 'Five Stars'
- },
- clearButtonTitle: 'Clear',
- clearCaption: 'Not Rated'
- };
- $.fn.rating.Constructor = Rating;
- /**
- * Convert automatically inputs with class 'rating' into Krajee's star rating control.
- */
- $(document).ready(function () {
- var $input = $('input.rating');
- if ($input.length) {
- $input.removeClass('rating-loading').addClass('rating-loading').rating();
- }
- });
- }));
|