star-rating.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*!
  2. * bootstrap-star-rating v4.0.2
  3. * http://plugins.krajee.com/star-rating
  4. *
  5. * Author: Kartik Visweswaran
  6. * Copyright: 2013 - 2017, Kartik Visweswaran, Krajee.com
  7. *
  8. * Licensed under the BSD 3-Clause
  9. * https://github.com/kartik-v/bootstrap-star-rating/blob/master/LICENSE.md
  10. */
  11. (function (factory) {
  12. "use strict";
  13. //noinspection JSUnresolvedVariable
  14. if (typeof define === 'function' && define.amd) { // jshint ignore:line
  15. // AMD. Register as an anonymous module.
  16. define(['jquery'], factory); // jshint ignore:line
  17. } else { // noinspection JSUnresolvedVariable
  18. if (typeof module === 'object' && module.exports) { // jshint ignore:line
  19. // Node/CommonJS
  20. // noinspection JSUnresolvedVariable
  21. module.exports = factory(require('jquery')); // jshint ignore:line
  22. } else {
  23. // Browser globals
  24. factory(window.jQuery);
  25. }
  26. }
  27. }(function ($) {
  28. "use strict";
  29. $.fn.ratingLocales = {};
  30. $.fn.ratingThemes = {};
  31. var $h, Rating;
  32. // global helper methods and constants
  33. $h = {
  34. NAMESPACE: '.rating',
  35. DEFAULT_MIN: 0,
  36. DEFAULT_MAX: 5,
  37. DEFAULT_STEP: 0.5,
  38. isEmpty: function (value, trim) {
  39. return value === null || value === undefined || value.length === 0 || (trim && $.trim(value) === '');
  40. },
  41. getCss: function (condition, css) {
  42. return condition ? ' ' + css : '';
  43. },
  44. addCss: function ($el, css) {
  45. $el.removeClass(css).addClass(css);
  46. },
  47. getDecimalPlaces: function (num) {
  48. var m = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
  49. return !m ? 0 : Math.max(0, (m[1] ? m[1].length : 0) - (m[2] ? +m[2] : 0));
  50. },
  51. applyPrecision: function (val, precision) {
  52. return parseFloat(val.toFixed(precision));
  53. },
  54. handler: function ($el, event, callback, skipOff, skipNS) {
  55. var ev = skipNS ? event : event.split(' ').join($h.NAMESPACE + ' ') + $h.NAMESPACE;
  56. if (!skipOff) {
  57. $el.off(ev);
  58. }
  59. $el.on(ev, callback);
  60. }
  61. };
  62. // rating constructor
  63. Rating = function (element, options) {
  64. var self = this;
  65. self.$element = $(element);
  66. self._init(options);
  67. };
  68. Rating.prototype = {
  69. constructor: Rating,
  70. _parseAttr: function (vattr, options) {
  71. var self = this, $el = self.$element, elType = $el.attr('type'), finalVal, val, chk, out;
  72. if (elType === 'range' || elType === 'number') {
  73. val = options[vattr] || $el.data(vattr) || $el.attr(vattr);
  74. switch (vattr) {
  75. case 'min':
  76. chk = $h.DEFAULT_MIN;
  77. break;
  78. case 'max':
  79. chk = $h.DEFAULT_MAX;
  80. break;
  81. default:
  82. chk = $h.DEFAULT_STEP;
  83. }
  84. finalVal = $h.isEmpty(val) ? chk : val;
  85. out = parseFloat(finalVal);
  86. } else {
  87. out = parseFloat(options[vattr]);
  88. }
  89. return isNaN(out) ? chk : out;
  90. },
  91. _parseValue: function (val) {
  92. var self = this, v = parseFloat(val);
  93. if (isNaN(v)) {
  94. v = self.clearValue;
  95. }
  96. return (self.zeroAsNull && (v === 0 || v === '0') ? null : v);
  97. },
  98. _setDefault: function (key, val) {
  99. var self = this;
  100. if ($h.isEmpty(self[key])) {
  101. self[key] = val;
  102. }
  103. },
  104. _initSlider: function (options) {
  105. var self = this, v = self.$element.val();
  106. self.initialValue = $h.isEmpty(v) ? 0 : v;
  107. self._setDefault('min', self._parseAttr('min', options));
  108. self._setDefault('max', self._parseAttr('max', options));
  109. self._setDefault('step', self._parseAttr('step', options));
  110. if (isNaN(self.min) || $h.isEmpty(self.min)) {
  111. self.min = $h.DEFAULT_MIN;
  112. }
  113. if (isNaN(self.max) || $h.isEmpty(self.max)) {
  114. self.max = $h.DEFAULT_MAX;
  115. }
  116. if (isNaN(self.step) || $h.isEmpty(self.step) || self.step === 0) {
  117. self.step = $h.DEFAULT_STEP;
  118. }
  119. self.diff = self.max - self.min;
  120. },
  121. _initHighlight: function (v) {
  122. var self = this, w, cap = self._getCaption();
  123. if (!v) {
  124. v = self.$element.val();
  125. }
  126. w = self.getWidthFromValue(v) + '%';
  127. self.$filledStars.width(w);
  128. self.cache = {caption: cap, width: w, val: v};
  129. },
  130. _getContainerCss: function () {
  131. var self = this;
  132. return 'rating-container' +
  133. $h.getCss(self.theme, 'theme-' + self.theme) +
  134. $h.getCss(self.rtl, 'rating-rtl') +
  135. $h.getCss(self.size, 'rating-' + self.size) +
  136. $h.getCss(self.animate, 'rating-animate') +
  137. $h.getCss(self.disabled || self.readonly, 'rating-disabled') +
  138. $h.getCss(self.containerClass, self.containerClass);
  139. },
  140. _checkDisabled: function () {
  141. var self = this, $el = self.$element, opts = self.options;
  142. self.disabled = opts.disabled === undefined ? $el.attr('disabled') || false : opts.disabled;
  143. self.readonly = opts.readonly === undefined ? $el.attr('readonly') || false : opts.readonly;
  144. self.inactive = (self.disabled || self.readonly);
  145. $el.attr({disabled: self.disabled, readonly: self.readonly});
  146. },
  147. _addContent: function (type, content) {
  148. var self = this, $container = self.$container, isClear = type === 'clear';
  149. if (self.rtl) {
  150. return isClear ? $container.append(content) : $container.prepend(content);
  151. } else {
  152. return isClear ? $container.prepend(content) : $container.append(content);
  153. }
  154. },
  155. _generateRating: function () {
  156. var self = this, $el = self.$element, $rating, $container, w;
  157. $container = self.$container = $(document.createElement("div")).insertBefore($el);
  158. $h.addCss($container, self._getContainerCss());
  159. self.$rating = $rating = $(document.createElement("div")).attr('class', 'rating-stars').appendTo($container)
  160. .append(self._getStars('empty')).append(self._getStars('filled'));
  161. self.$emptyStars = $rating.find('.empty-stars');
  162. self.$filledStars = $rating.find('.filled-stars');
  163. self._renderCaption();
  164. self._renderClear();
  165. self._initHighlight();
  166. $container.append($el);
  167. if (self.rtl) {
  168. w = Math.max(self.$emptyStars.outerWidth(), self.$filledStars.outerWidth());
  169. self.$emptyStars.width(w);
  170. }
  171. $el.appendTo($rating);
  172. },
  173. _getCaption: function () {
  174. var self = this;
  175. return self.$caption && self.$caption.length ? self.$caption.html() : self.defaultCaption;
  176. },
  177. _setCaption: function (content) {
  178. var self = this;
  179. if (self.$caption && self.$caption.length) {
  180. self.$caption.html(content);
  181. }
  182. },
  183. _renderCaption: function () {
  184. var self = this, val = self.$element.val(), html, $cap = self.captionElement ? $(self.captionElement) : '';
  185. if (!self.showCaption) {
  186. return;
  187. }
  188. html = self.fetchCaption(val);
  189. if ($cap && $cap.length) {
  190. $h.addCss($cap, 'caption');
  191. $cap.html(html);
  192. self.$caption = $cap;
  193. return;
  194. }
  195. self._addContent('caption', '<div class="caption">' + html + '</div>');
  196. self.$caption = self.$container.find(".caption");
  197. },
  198. _renderClear: function () {
  199. var self = this, css, $clr = self.clearElement ? $(self.clearElement) : '';
  200. if (!self.showClear) {
  201. return;
  202. }
  203. css = self._getClearClass();
  204. if ($clr.length) {
  205. $h.addCss($clr, css);
  206. $clr.attr({"title": self.clearButtonTitle}).html(self.clearButton);
  207. self.$clear = $clr;
  208. return;
  209. }
  210. self._addContent('clear',
  211. '<div class="' + css + '" title="' + self.clearButtonTitle + '">' + self.clearButton + '</div>');
  212. self.$clear = self.$container.find('.' + self.clearButtonBaseClass);
  213. },
  214. _getClearClass: function () {
  215. var self = this;
  216. return self.clearButtonBaseClass + ' ' + (self.inactive ? '' : self.clearButtonActiveClass);
  217. },
  218. _toggleHover: function (out) {
  219. var self = this, w, width, caption;
  220. if (!out) {
  221. return;
  222. }
  223. if (self.hoverChangeStars) {
  224. w = self.getWidthFromValue(self.clearValue);
  225. width = out.val <= self.clearValue ? w + '%' : out.width;
  226. self.$filledStars.css('width', width);
  227. }
  228. if (self.hoverChangeCaption) {
  229. caption = out.val <= self.clearValue ? self.fetchCaption(self.clearValue) : out.caption;
  230. if (caption) {
  231. self._setCaption(caption + '');
  232. }
  233. }
  234. },
  235. _init: function (options) {
  236. var self = this, $el = self.$element.addClass('rating-input'), v;
  237. self.options = options;
  238. $.each(options, function (key, value) {
  239. self[key] = value;
  240. });
  241. if (self.rtl || $el.attr('dir') === 'rtl') {
  242. self.rtl = true;
  243. $el.attr('dir', 'rtl');
  244. }
  245. self.starClicked = false;
  246. self.clearClicked = false;
  247. self._initSlider(options);
  248. self._checkDisabled();
  249. if (self.displayOnly) {
  250. self.inactive = true;
  251. self.showClear = false;
  252. self.showCaption = false;
  253. }
  254. self._generateRating();
  255. self._initEvents();
  256. self._listen();
  257. v = self._parseValue($el.val());
  258. $el.val(v);
  259. return $el.removeClass('rating-loading');
  260. },
  261. _initEvents: function () {
  262. var self = this;
  263. self.events = {
  264. _getTouchPosition: function (e) {
  265. var pageX = $h.isEmpty(e.pageX) ? e.originalEvent.touches[0].pageX : e.pageX;
  266. return pageX - self.$rating.offset().left;
  267. },
  268. _listenClick: function (e, callback) {
  269. e.stopPropagation();
  270. e.preventDefault();
  271. if (e.handled !== true) {
  272. callback(e);
  273. e.handled = true;
  274. } else {
  275. return false;
  276. }
  277. },
  278. _noMouseAction: function (e) {
  279. return !self.hoverEnabled || self.inactive || (e && e.isDefaultPrevented());
  280. },
  281. initTouch: function (e) {
  282. //noinspection JSUnresolvedVariable
  283. var ev, touches, pos, out, caption, w, width, params, clrVal = self.clearValue || 0,
  284. isTouchCapable = 'ontouchstart' in window ||
  285. (window.DocumentTouch && document instanceof window.DocumentTouch);
  286. if (!isTouchCapable || self.inactive) {
  287. return;
  288. }
  289. ev = e.originalEvent;
  290. //noinspection JSUnresolvedVariable
  291. touches = !$h.isEmpty(ev.touches) ? ev.touches : ev.changedTouches;
  292. pos = self.events._getTouchPosition(touches[0]);
  293. if (e.type === "touchend") {
  294. self._setStars(pos);
  295. params = [self.$element.val(), self._getCaption()];
  296. self.$element.trigger('change').trigger('rating.change', params);
  297. self.starClicked = true;
  298. } else {
  299. out = self.calculate(pos);
  300. caption = out.val <= clrVal ? self.fetchCaption(clrVal) : out.caption;
  301. w = self.getWidthFromValue(clrVal);
  302. width = out.val <= clrVal ? w + '%' : out.width;
  303. self._setCaption(caption);
  304. self.$filledStars.css('width', width);
  305. }
  306. },
  307. starClick: function (e) {
  308. var pos, params;
  309. self.events._listenClick(e, function (ev) {
  310. if (self.inactive) {
  311. return false;
  312. }
  313. pos = self.events._getTouchPosition(ev);
  314. self._setStars(pos);
  315. params = [self.$element.val(), self._getCaption()];
  316. self.$element.trigger('change').trigger('rating.change', params);
  317. self.starClicked = true;
  318. });
  319. },
  320. clearClick: function (e) {
  321. self.events._listenClick(e, function () {
  322. if (!self.inactive) {
  323. self.clear();
  324. self.clearClicked = true;
  325. }
  326. });
  327. },
  328. starMouseMove: function (e) {
  329. var pos, out;
  330. if (self.events._noMouseAction(e)) {
  331. return;
  332. }
  333. self.starClicked = false;
  334. pos = self.events._getTouchPosition(e);
  335. out = self.calculate(pos);
  336. self._toggleHover(out);
  337. self.$element.trigger('rating.hover', [out.val, out.caption, 'stars']);
  338. },
  339. starMouseLeave: function (e) {
  340. var out;
  341. if (self.events._noMouseAction(e) || self.starClicked) {
  342. return;
  343. }
  344. out = self.cache;
  345. self._toggleHover(out);
  346. self.$element.trigger('rating.hoverleave', ['stars']);
  347. },
  348. clearMouseMove: function (e) {
  349. var caption, val, width, out;
  350. if (self.events._noMouseAction(e) || !self.hoverOnClear) {
  351. return;
  352. }
  353. self.clearClicked = false;
  354. caption = '<span class="' + self.clearCaptionClass + '">' + self.clearCaption + '</span>';
  355. val = self.clearValue;
  356. width = self.getWidthFromValue(val) || 0;
  357. out = {caption: caption, width: width, val: val};
  358. self._toggleHover(out);
  359. self.$element.trigger('rating.hover', [val, caption, 'clear']);
  360. },
  361. clearMouseLeave: function (e) {
  362. var out;
  363. if (self.events._noMouseAction(e) || self.clearClicked || !self.hoverOnClear) {
  364. return;
  365. }
  366. out = self.cache;
  367. self._toggleHover(out);
  368. self.$element.trigger('rating.hoverleave', ['clear']);
  369. },
  370. resetForm: function (e) {
  371. if (e && e.isDefaultPrevented()) {
  372. return;
  373. }
  374. if (!self.inactive) {
  375. self.reset();
  376. }
  377. }
  378. };
  379. },
  380. _listen: function () {
  381. var self = this, $el = self.$element, $form = $el.closest('form'), $rating = self.$rating,
  382. $clear = self.$clear, events = self.events;
  383. $h.handler($rating, 'touchstart touchmove touchend', $.proxy(events.initTouch, self));
  384. $h.handler($rating, 'click touchstart', $.proxy(events.starClick, self));
  385. $h.handler($rating, 'mousemove', $.proxy(events.starMouseMove, self));
  386. $h.handler($rating, 'mouseleave', $.proxy(events.starMouseLeave, self));
  387. if (self.showClear && $clear.length) {
  388. $h.handler($clear, 'click touchstart', $.proxy(events.clearClick, self));
  389. $h.handler($clear, 'mousemove', $.proxy(events.clearMouseMove, self));
  390. $h.handler($clear, 'mouseleave', $.proxy(events.clearMouseLeave, self));
  391. }
  392. if ($form.length) {
  393. $h.handler($form, 'reset', $.proxy(events.resetForm, self), true);
  394. }
  395. return $el;
  396. },
  397. _getStars: function (type) {
  398. var self = this, stars = '<span class="' + type + '-stars">', i;
  399. for (i = 1; i <= self.stars; i++) {
  400. stars += '<span class="star">' + self[type + 'Star'] + '</span>';
  401. }
  402. return stars + '</span>';
  403. },
  404. _setStars: function (pos) {
  405. var self = this, out = arguments.length ? self.calculate(pos) : self.calculate(), $el = self.$element,
  406. v = self._parseValue(out.val);
  407. $el.val(v);
  408. self.$filledStars.css('width', out.width);
  409. self._setCaption(out.caption);
  410. self.cache = out;
  411. return $el;
  412. },
  413. showStars: function (val) {
  414. var self = this, v = self._parseValue(val);
  415. self.$element.val(v);
  416. return self._setStars();
  417. },
  418. calculate: function (pos) {
  419. var self = this, defaultVal = $h.isEmpty(self.$element.val()) ? 0 : self.$element.val(),
  420. val = arguments.length ? self.getValueFromPosition(pos) : defaultVal,
  421. caption = self.fetchCaption(val), width = self.getWidthFromValue(val);
  422. width += '%';
  423. return {caption: caption, width: width, val: val};
  424. },
  425. getValueFromPosition: function (pos) {
  426. var self = this, precision = $h.getDecimalPlaces(self.step), val, factor, maxWidth = self.$rating.width();
  427. factor = (self.diff * pos) / (maxWidth * self.step);
  428. factor = self.rtl ? Math.floor(factor) : Math.ceil(factor);
  429. val = $h.applyPrecision(parseFloat(self.min + factor * self.step), precision);
  430. val = Math.max(Math.min(val, self.max), self.min);
  431. return self.rtl ? (self.max - val) : val;
  432. },
  433. getWidthFromValue: function (val) {
  434. var self = this, min = self.min, max = self.max, factor, $r = self.$emptyStars, w;
  435. if (!val || val <= min || min === max) {
  436. return 0;
  437. }
  438. w = $r.outerWidth();
  439. factor = w ? $r.width() / w : 1;
  440. if (val >= max) {
  441. return 100;
  442. }
  443. return (val - min) * factor * 100 / (max - min);
  444. },
  445. fetchCaption: function (rating) {
  446. var self = this, val = parseFloat(rating) || self.clearValue, css, cap, capVal, cssVal, caption,
  447. vCap = self.starCaptions, vCss = self.starCaptionClasses;
  448. if (val && val !== self.clearValue) {
  449. val = $h.applyPrecision(val, $h.getDecimalPlaces(self.step));
  450. }
  451. cssVal = typeof vCss === "function" ? vCss(val) : vCss[val];
  452. capVal = typeof vCap === "function" ? vCap(val) : vCap[val];
  453. cap = $h.isEmpty(capVal) ? self.defaultCaption.replace(/\{rating}/g, val) : capVal;
  454. css = $h.isEmpty(cssVal) ? self.clearCaptionClass : cssVal;
  455. caption = (val === self.clearValue) ? self.clearCaption : cap;
  456. return '<span class="' + css + '">' + caption + '</span>';
  457. },
  458. destroy: function () {
  459. var self = this, $el = self.$element;
  460. if (!$h.isEmpty(self.$container)) {
  461. self.$container.before($el).remove();
  462. }
  463. $.removeData($el.get(0));
  464. return $el.off('rating').removeClass('rating rating-input');
  465. },
  466. create: function (options) {
  467. var self = this, opts = options || self.options || {};
  468. return self.destroy().rating(opts);
  469. },
  470. clear: function () {
  471. var self = this, title = '<span class="' + self.clearCaptionClass + '">' + self.clearCaption + '</span>';
  472. if (!self.inactive) {
  473. self._setCaption(title);
  474. }
  475. return self.showStars(self.clearValue).trigger('change').trigger('rating.clear');
  476. },
  477. reset: function () {
  478. var self = this;
  479. return self.showStars(self.initialValue).trigger('rating.reset');
  480. },
  481. update: function (val) {
  482. var self = this;
  483. return arguments.length ? self.showStars(val) : self.$element;
  484. },
  485. refresh: function (options) {
  486. var self = this, $el = self.$element;
  487. if (!options) {
  488. return $el;
  489. }
  490. return self.destroy().rating($.extend(true, self.options, options)).trigger('rating.refresh');
  491. }
  492. };
  493. $.fn.rating = function (option) {
  494. var args = Array.apply(null, arguments), retvals = [];
  495. args.shift();
  496. this.each(function () {
  497. var self = $(this), data = self.data('rating'), options = typeof option === 'object' && option,
  498. theme = options.theme || self.data('theme'), lang = options.language || self.data('language') || 'en',
  499. thm = {}, loc = {}, opts;
  500. if (!data) {
  501. if (theme) {
  502. thm = $.fn.ratingThemes[theme] || {};
  503. }
  504. if (lang !== 'en' && !$h.isEmpty($.fn.ratingLocales[lang])) {
  505. loc = $.fn.ratingLocales[lang];
  506. }
  507. opts = $.extend(true, {}, $.fn.rating.defaults, thm, $.fn.ratingLocales.en, loc, options, self.data());
  508. data = new Rating(this, opts);
  509. self.data('rating', data);
  510. }
  511. if (typeof option === 'string') {
  512. retvals.push(data[option].apply(data, args));
  513. }
  514. });
  515. switch (retvals.length) {
  516. case 0:
  517. return this;
  518. case 1:
  519. return retvals[0] === undefined ? this : retvals[0];
  520. default:
  521. return retvals;
  522. }
  523. };
  524. $.fn.rating.defaults = {
  525. theme: '',
  526. language: 'en',
  527. stars: 5,
  528. filledStar: '<i class="glyphicon glyphicon-star"></i>',
  529. emptyStar: '<i class="glyphicon glyphicon-star-empty"></i>',
  530. containerClass: '',
  531. size: 'md',
  532. animate: true,
  533. displayOnly: false,
  534. rtl: false,
  535. showClear: true,
  536. showCaption: true,
  537. starCaptionClasses: {
  538. 0.5: 'label label-danger',
  539. 1: 'label label-danger',
  540. 1.5: 'label label-warning',
  541. 2: 'label label-warning',
  542. 2.5: 'label label-info',
  543. 3: 'label label-info',
  544. 3.5: 'label label-primary',
  545. 4: 'label label-primary',
  546. 4.5: 'label label-success',
  547. 5: 'label label-success'
  548. },
  549. clearButton: '<i class="glyphicon glyphicon-minus-sign"></i>',
  550. clearButtonBaseClass: 'clear-rating',
  551. clearButtonActiveClass: 'clear-rating-active',
  552. clearCaptionClass: 'label label-default',
  553. clearValue: null,
  554. captionElement: null,
  555. clearElement: null,
  556. hoverEnabled: true,
  557. hoverChangeCaption: true,
  558. hoverChangeStars: true,
  559. hoverOnClear: true,
  560. zeroAsNull: true
  561. };
  562. $.fn.ratingLocales.en = {
  563. defaultCaption: '{rating} Stars',
  564. starCaptions: {
  565. 0.5: 'Half Star',
  566. 1: 'One Star',
  567. 1.5: 'One & Half Star',
  568. 2: 'Two Stars',
  569. 2.5: 'Two & Half Stars',
  570. 3: 'Three Stars',
  571. 3.5: 'Three & Half Stars',
  572. 4: 'Four Stars',
  573. 4.5: 'Four & Half Stars',
  574. 5: 'Five Stars'
  575. },
  576. clearButtonTitle: 'Clear',
  577. clearCaption: 'Not Rated'
  578. };
  579. $.fn.rating.Constructor = Rating;
  580. /**
  581. * Convert automatically inputs with class 'rating' into Krajee's star rating control.
  582. */
  583. $(document).ready(function () {
  584. var $input = $('input.rating');
  585. if ($input.length) {
  586. $input.removeClass('rating-loading').addClass('rating-loading').rating();
  587. }
  588. });
  589. }));