123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*!
- * @copyright © Kartik Visweswaran, Krajee.com, 2014
- * @version 2.5.0
- *
- * A simple yet powerful JQuery star rating plugin that allows rendering
- * fractional star ratings and supports Right to Left (RTL) input.
- *
- * For more JQuery plugins visit http://plugins.krajee.com
- * For more Yii related demos visit http://demos.krajee.com
- */
- (function ($) {
- var DEFAULT_MIN = 0;
- var DEFAULT_MAX = 5;
- var DEFAULT_STEP = 0.5;
- var isEmpty = function (value, trim) {
- return typeof value === 'undefined' || value === null || value === undefined || value == []
- || value === '' || trim && $.trim(value) === '';
- };
- var validateAttr = function ($input, vattr, options) {
- var chk = isEmpty($input.data(vattr)) ? $input.attr(vattr) : $input.data(vattr);
- if (chk) {
- return chk;
- }
- return options[vattr];
- };
- var getDecimalPlaces = function (num) {
- var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
- if (!match) {
- return 0;
- }
- return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
- };
- var applyPrecision = function (val, precision) {
- return parseFloat(val.toFixed(precision));
- };
- // Rating public class definition
- var Rating = function (element, options) {
- this.$element = $(element);
- this.init(options);
- };
- Rating.prototype = {
- constructor: Rating,
- _parseAttr: function (vattr, options) {
- var self = this, $input = self.$element;
- if ($input.attr('type') === 'range' || $input.attr('type') === 'number') {
- var val = validateAttr($input, vattr, options);
- var chk = DEFAULT_STEP;
- if (vattr === 'min') {
- chk = DEFAULT_MIN;
- }
- else if (vattr === 'max') {
- chk = DEFAULT_MAX;
- }
- else if (vattr === 'step') {
- chk = DEFAULT_STEP;
- }
- var final = isEmpty(val) ? chk : val;
- return parseFloat(final);
- }
- return parseFloat(options[vattr]);
- },
- /**
- * Listens to events
- */
- listen: function () {
- var self = this;
- self.$rating.on("click", function (e) {
- if (!self.inactive) {
- w = e.pageX - self.$rating.offset().left;
- self.setStars(w);
- self.$element.trigger('change');
- self.$element.trigger('rating.change', [self.$element.val(), self.$caption.html()]);
- }
- });
- self.$clear.on("click", function (e) {
- if (!self.inactive) {
- self.clear();
- }
- });
- $(self.$element[0].form).on("reset", function (e) {
- if (!self.inactive) {
- self.reset();
- }
- });
- },
- initSlider: function (options) {
- var self = this;
- if (isEmpty(self.$element.val())) {
- self.$element.val(0);
- }
- self.initialValue = self.$element.val();
- self.min = (typeof options.min !== 'undefined') ? options.min : self._parseAttr('min', options);
- self.max = (typeof options.max !== 'undefined') ? options.max : self._parseAttr('max', options);
- self.step = (typeof options.step !== 'undefined') ? options.step : self._parseAttr('step', options);
- if (isNaN(self.min) || isEmpty(self.min)) {
- self.min = DEFAULT_MIN;
- }
- if (isNaN(self.max) || isEmpty(self.max)) {
- self.max = DEFAULT_MAX;
- }
- if (isNaN(self.step) || isEmpty(self.step) || self.step == 0) {
- self.step = DEFAULT_STEP;
- }
- self.diff = self.max - self.min;
- },
- /**
- * Initializes the plugin
- */
- init: function (options) {
- var self = this;
- self.options = options;
- self.initSlider(options);
- self.checkDisabled();
- $element = self.$element;
- self.containerClass = options.containerClass;
- self.glyphicon = options.glyphicon;
- var defaultStar = (self.glyphicon) ? '\ue006' : '\u2605';
- self.symbol = isEmpty(options.symbol) ? defaultStar : options.symbol;
- self.rtl = options.rtl || self.$element.attr('dir');
- if (self.rtl) {
- self.$element.attr('dir', 'rtl');
- }
- self.showClear = options.showClear;
- self.showCaption = options.showCaption;
- self.size = options.size;
- self.stars = options.stars;
- self.defaultCaption = options.defaultCaption;
- self.starCaptions = options.starCaptions;
- self.starCaptionClasses = options.starCaptionClasses;
- self.clearButton = options.clearButton;
- self.clearButtonTitle = options.clearButtonTitle;
- self.clearButtonBaseClass = !isEmpty(options.clearButtonBaseClass) ? options.clearButtonBaseClass : 'clear-rating';
- self.clearButtonActiveClass = !isEmpty(options.clearButtonActiveClass) ? options.clearButtonActiveClass : 'clear-rating-active';
- self.clearCaption = options.clearCaption;
- self.clearCaptionClass = options.clearCaptionClass;
- self.clearValue = options.clearValue;
- self.$element.removeClass('form-control').addClass('form-control');
- self.$clearElement = isEmpty(options.clearElement) ? null : $(options.clearElement);
- self.$captionElement = isEmpty(options.captionElement) ? null : $(options.captionElement);
- if (typeof self.$rating == 'undefined' && typeof self.$container == 'undefined') {
- self.$rating = $(document.createElement("div")).html('<div class="rating-stars"></div>');
- self.$container = $(document.createElement("div"));
- self.$container.before(self.$rating);
- self.$container.append(self.$rating);
- self.$element.before(self.$container).appendTo(self.$rating);
- }
- self.$stars = self.$rating.find('.rating-stars');
- self.generateRating();
- self.$clear = !isEmpty(self.$clearElement) ? self.$clearElement : self.$container.find('.' + self.clearButtonBaseClass);
- self.$caption = !isEmpty(self.$captionElement) ? self.$captionElement : self.$container.find(".caption");
- self.setStars();
- self.$element.hide();
- self.listen();
- if (self.showClear) {
- self.$clear.attr({"class": self.getClearClass()});
- }
- },
- checkDisabled: function () {
- var self = this;
- self.disabled = validateAttr(self.$element, 'disabled', self.options);
- self.readonly = validateAttr(self.$element, 'readonly', self.options);
- self.inactive = (self.disabled || self.readonly);
- },
- getClearClass: function () {
- return this.clearButtonBaseClass + ' ' + ((this.inactive) ? '' : this.clearButtonActiveClass);
- },
- generateRating: function () {
- var self = this, clear = self.renderClear(), caption = self.renderCaption(),
- css = (self.rtl) ? 'rating-container-rtl' : 'rating-container',
- stars = self.getStars();
- css += (self.glyphicon) ? ((self.symbol == '\ue006') ? ' rating-gly-star' : ' rating-gly') : ' rating-uni';
- self.$rating.attr('class', css);
- self.$rating.attr('data-content', stars);
- self.$stars.attr('data-content', stars);
- var css = self.rtl ? 'star-rating-rtl' : 'star-rating';
- self.$container.attr('class', css + ' rating-' + self.size);
- if (self.inactive) {
- self.$container.removeClass('rating-active').addClass('rating-disabled');
- }
- else {
- self.$container.removeClass('rating-disabled').addClass('rating-active');
- }
- if (typeof self.$caption == 'undefined' && typeof self.$clear == 'undefined') {
- if (self.rtl) {
- self.$container.prepend(caption).append(clear);
- }
- else {
- self.$container.prepend(clear).append(caption);
- }
- }
- if (!isEmpty(self.containerClass)) {
- self.$container.removeClass(self.containerClass).addClass(self.containerClass);
- }
- },
- getStars: function () {
- var self = this, numStars = self.stars, stars = '';
- for (var i = 1; i <= numStars; i++) {
- stars += self.symbol;
- }
- return stars;
- },
- renderClear: function () {
- var self = this;
- if (!self.showClear) {
- return '';
- }
- var css = self.getClearClass();
- if (!isEmpty(self.$clearElement)) {
- self.$clearElement.removeClass(css).addClass(css).attr({"title": self.clearButtonTitle});
- self.$clearElement.html(self.clearButton);
- return '';
- }
- return '<div class="' + css + '" title="' + self.clearButtonTitle + '">' + self.clearButton + '</div>';
- },
- renderCaption: function () {
- var self = this, val = self.$element.val();
- if (!self.showCaption) {
- return '';
- }
- var html = self.fetchCaption(val);
- if (!isEmpty(self.$captionElement)) {
- self.$captionElement.removeClass('caption').addClass('caption').attr({"title": self.clearCaption});
- self.$captionElement.html(html);
- return '';
- }
- return '<div class="caption">' + html + '</div>';
- },
- fetchCaption: function (rating) {
- var self = this;
- var val = parseFloat(rating);
- var css = isEmpty(self.starCaptionClasses[val]) ? self.clearCaptionClass : self.starCaptionClasses[val];
- var cap = !isEmpty(self.starCaptions[val]) ? self.starCaptions[val] : self.defaultCaption.replace(/\{rating\}/g, val);
- var caption = (val == self.clearValue) ? self.clearCaption : cap;
- return '<span class="' + css + '">' + caption + '</span>';
- },
- getValueFromPosition: function (pos) {
- var self = this, precision = getDecimalPlaces(self.step),
- percentage, val, maxWidth = self.$rating.width();
- percentage = (pos / maxWidth);
- val = (self.min + Math.ceil(self.diff * percentage / self.step) * self.step);
- if (val < self.min) {
- val = self.min;
- }
- else if (val > self.max) {
- val = self.max;
- }
- val = applyPrecision(parseFloat(val), precision);
- if (self.rtl) {
- val = self.max - val;
- }
- return val;
- },
- setStars: function (pos) {
- var self = this, min = self.min, max = self.max, step = self.step,
- val = arguments.length ? self.getValueFromPosition(pos) : (isEmpty(self.$element.val()) ? 0 : self.$element.val()),
- width = 0, maxWidth = self.$rating.width(), caption = self.fetchCaption(val);
- width = (val - min) / max * 100;
- if (self.rtl) {
- width = 100 - width;
- }
- self.$element.val(val);
- width += '%';
- self.$stars.css('width', width);
- self.$caption.html(caption);
- },
- clear: function () {
- var self = this;
- var title = '<span class="' + self.clearCaptionClass + '">' + self.clearCaption + '</span>';
- self.$stars.removeClass('rated');
- if (!self.inactive) {
- self.$caption.html(title);
- }
- self.$element.val(self.clearValue);
- self.setStars();
- self.$element.trigger('rating.clear');
- },
- reset: function () {
- var self = this;
- self.$element.val(self.initialValue);
- self.setStars();
- self.$element.trigger('rating.reset');
- },
- update: function (val) {
- if (arguments.length > 0) {
- var self = this;
- self.$element.val(val);
- self.setStars();
- }
- },
- refresh: function (options) {
- var self = this;
- if (arguments.length) {
- var cap = '';
- self.init($.extend(self.options, options));
- if (self.showClear) {
- self.$clear.show();
- }
- else {
- self.$clear.hide();
- }
- if (self.showCaption) {
- self.$caption.show();
- }
- else {
- self.$caption.hide();
- }
- }
- }
- };
- //Star rating plugin definition
- $.fn.rating = function (option) {
- var args = Array.apply(null, arguments);
- args.shift();
- return this.each(function () {
- var $this = $(this),
- data = $this.data('rating'),
- options = typeof option === 'object' && option;
- if (!data) {
- $this.data('rating', (data = new Rating(this, $.extend({}, $.fn.rating.defaults, options, $(this).data()))));
- }
- if (typeof option === 'string') {
- data[option].apply(data, args);
- }
- });
- };
- $.fn.rating.defaults = {
- stars: 5,
- glyphicon: true,
- symbol: null,
- disabled: false,
- readonly: false,
- rtl: false,
- size: 'md',
- showClear: true,
- showCaption: true,
- defaultCaption: '{rating} Stars',
- starCaptions: {
- 0.5: '差到极点了',
- 1: '非常差',
- 1.5: '不太好',
- 2: '不太好',
- 2.5: '感觉一般般',
- 3: '感觉还凑合',
- 3.5: '感觉还凑合',
- 4: '我挺满意的',
- 4.5: '总体不错',
- 5: '超级棒棒棒'
- },
- starCaptionClasses: {
- 0.5: 'label label-default',
- 1: 'label label-default',
- 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-danger',
- 5: 'label label-danger'
- },
- clearButton: '<i class="glyphicon glyphicon-minus-sign"></i>',
- clearButtonTitle: 'Clear',
- clearButtonBaseClass: 'clear-rating',
- clearButtonActiveClass: 'clear-rating-active',
- clearCaption: '没有选择评分',
- clearCaptionClass: 'label label-default',
- clearValue: 0,
- captionElement: null,
- clearElement: null,
- containerClass: null
- };
- /**
- * Convert automatically number inputs with class 'rating'
- * into the star rating control.
- */
- $(document).ready(function () {
- var $input = $('input.rating'), count = Object.keys($input).length;
- if (count > 0) {
- $input.rating();
- }
- });
- }(jQuery));
|