You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

413 lines
12 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. * # Semantic - Rating
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributor
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ($, window, document, undefined) {
  12. "use strict";
  13. $.fn.rating = function(parameters) {
  14. var
  15. $allModules = $(this),
  16. moduleSelector = $allModules.selector || '',
  17. time = new Date().getTime(),
  18. performance = [],
  19. query = arguments[0],
  20. methodInvoked = (typeof query == 'string'),
  21. queryArguments = [].slice.call(arguments, 1),
  22. returnedValue
  23. ;
  24. $allModules
  25. .each(function() {
  26. var
  27. settings = ( $.isPlainObject(parameters) )
  28. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  29. : $.extend({}, $.fn.rating.settings),
  30. namespace = settings.namespace,
  31. className = settings.className,
  32. metadata = settings.metadata,
  33. selector = settings.selector,
  34. error = settings.error,
  35. eventNamespace = '.' + namespace,
  36. moduleNamespace = 'module-' + namespace,
  37. element = this,
  38. instance = $(this).data(moduleNamespace),
  39. $module = $(this),
  40. $icon = $module.find(selector.icon),
  41. module
  42. ;
  43. module = {
  44. initialize: function() {
  45. module.verbose('Initializing rating module', settings);
  46. if(settings.interactive) {
  47. module.enable();
  48. }
  49. else {
  50. module.disable();
  51. }
  52. if(settings.initialRating) {
  53. module.debug('Setting initial rating');
  54. module.setRating(settings.initialRating);
  55. }
  56. if( $module.data(metadata.rating) ) {
  57. module.debug('Rating found in metadata');
  58. module.setRating( $module.data(metadata.rating) );
  59. }
  60. module.instantiate();
  61. },
  62. instantiate: function() {
  63. module.verbose('Instantiating module', settings);
  64. instance = module;
  65. $module
  66. .data(moduleNamespace, module)
  67. ;
  68. },
  69. destroy: function() {
  70. module.verbose('Destroying previous instance', instance);
  71. $module
  72. .removeData(moduleNamespace)
  73. ;
  74. $icon
  75. .off(eventNamespace)
  76. ;
  77. },
  78. event: {
  79. mouseenter: function() {
  80. var
  81. $activeIcon = $(this)
  82. ;
  83. $activeIcon
  84. .nextAll()
  85. .removeClass(className.hover)
  86. ;
  87. $module
  88. .addClass(className.hover)
  89. ;
  90. $activeIcon
  91. .addClass(className.hover)
  92. .prevAll()
  93. .addClass(className.hover)
  94. ;
  95. },
  96. mouseleave: function() {
  97. $module
  98. .removeClass(className.hover)
  99. ;
  100. $icon
  101. .removeClass(className.hover)
  102. ;
  103. },
  104. click: function() {
  105. var
  106. $activeIcon = $(this),
  107. currentRating = module.getRating(),
  108. rating = $icon.index($activeIcon) + 1,
  109. canClear = (settings.clearable == 'auto')
  110. ? ($icon.size() === 1)
  111. : settings.clearable
  112. ;
  113. if(canClear && currentRating == rating) {
  114. module.clearRating();
  115. }
  116. else {
  117. module.setRating( rating );
  118. }
  119. }
  120. },
  121. clearRating: function() {
  122. module.debug('Clearing current rating');
  123. module.setRating(0);
  124. },
  125. getRating: function() {
  126. var
  127. currentRating = $icon.filter('.' + className.active).size()
  128. ;
  129. module.verbose('Current rating retrieved', currentRating);
  130. return currentRating;
  131. },
  132. enable: function() {
  133. module.debug('Setting rating to interactive mode');
  134. $icon
  135. .on('mouseenter' + eventNamespace, module.event.mouseenter)
  136. .on('mouseleave' + eventNamespace, module.event.mouseleave)
  137. .on('click' + eventNamespace, module.event.click)
  138. ;
  139. $module
  140. .removeClass(className.disabled)
  141. ;
  142. },
  143. disable: function() {
  144. module.debug('Setting rating to read-only mode');
  145. $icon
  146. .off(eventNamespace)
  147. ;
  148. $module
  149. .addClass(className.disabled)
  150. ;
  151. },
  152. setRating: function(rating) {
  153. var
  154. ratingIndex = (rating - 1 >= 0)
  155. ? (rating - 1)
  156. : 0,
  157. $activeIcon = $icon.eq(ratingIndex)
  158. ;
  159. $module
  160. .removeClass(className.hover)
  161. ;
  162. $icon
  163. .removeClass(className.hover)
  164. .removeClass(className.active)
  165. ;
  166. if(rating > 0) {
  167. module.verbose('Setting current rating to', rating);
  168. $activeIcon
  169. .addClass(className.active)
  170. .prevAll()
  171. .addClass(className.active)
  172. ;
  173. }
  174. $.proxy(settings.onRate, element)(rating);
  175. },
  176. setting: function(name, value) {
  177. module.debug('Changing setting', name, value);
  178. if( $.isPlainObject(name) ) {
  179. $.extend(true, settings, name);
  180. }
  181. else if(value !== undefined) {
  182. settings[name] = value;
  183. }
  184. else {
  185. return settings[name];
  186. }
  187. },
  188. internal: function(name, value) {
  189. if( $.isPlainObject(name) ) {
  190. $.extend(true, module, name);
  191. }
  192. else if(value !== undefined) {
  193. module[name] = value;
  194. }
  195. else {
  196. return module[name];
  197. }
  198. },
  199. debug: function() {
  200. if(settings.debug) {
  201. if(settings.performance) {
  202. module.performance.log(arguments);
  203. }
  204. else {
  205. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  206. module.debug.apply(console, arguments);
  207. }
  208. }
  209. },
  210. verbose: function() {
  211. if(settings.verbose && settings.debug) {
  212. if(settings.performance) {
  213. module.performance.log(arguments);
  214. }
  215. else {
  216. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  217. module.verbose.apply(console, arguments);
  218. }
  219. }
  220. },
  221. error: function() {
  222. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  223. module.error.apply(console, arguments);
  224. },
  225. performance: {
  226. log: function(message) {
  227. var
  228. currentTime,
  229. executionTime,
  230. previousTime
  231. ;
  232. if(settings.performance) {
  233. currentTime = new Date().getTime();
  234. previousTime = time || currentTime;
  235. executionTime = currentTime - previousTime;
  236. time = currentTime;
  237. performance.push({
  238. 'Element' : element,
  239. 'Name' : message[0],
  240. 'Arguments' : [].slice.call(message, 1) || '',
  241. 'Execution Time' : executionTime
  242. });
  243. }
  244. clearTimeout(module.performance.timer);
  245. module.performance.timer = setTimeout(module.performance.display, 100);
  246. },
  247. display: function() {
  248. var
  249. title = settings.name + ':',
  250. totalTime = 0
  251. ;
  252. time = false;
  253. clearTimeout(module.performance.timer);
  254. $.each(performance, function(index, data) {
  255. totalTime += data['Execution Time'];
  256. });
  257. title += ' ' + totalTime + 'ms';
  258. if(moduleSelector) {
  259. title += ' \'' + moduleSelector + '\'';
  260. }
  261. if($allModules.size() > 1) {
  262. title += ' ' + '(' + $allModules.size() + ')';
  263. }
  264. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  265. console.groupCollapsed(title);
  266. if(console.table) {
  267. console.table(performance);
  268. }
  269. else {
  270. $.each(performance, function(index, data) {
  271. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  272. });
  273. }
  274. console.groupEnd();
  275. }
  276. performance = [];
  277. }
  278. },
  279. invoke: function(query, passedArguments, context) {
  280. var
  281. object = instance,
  282. maxDepth,
  283. found,
  284. response
  285. ;
  286. passedArguments = passedArguments || queryArguments;
  287. context = element || context;
  288. if(typeof query == 'string' && object !== undefined) {
  289. query = query.split(/[\. ]/);
  290. maxDepth = query.length - 1;
  291. $.each(query, function(depth, value) {
  292. var camelCaseValue = (depth != maxDepth)
  293. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  294. : query
  295. ;
  296. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  297. object = object[camelCaseValue];
  298. }
  299. else if( object[camelCaseValue] !== undefined ) {
  300. found = object[camelCaseValue];
  301. return false;
  302. }
  303. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  304. object = object[value];
  305. }
  306. else if( object[value] !== undefined ) {
  307. found = object[value];
  308. return false;
  309. }
  310. else {
  311. return false;
  312. }
  313. });
  314. }
  315. if ( $.isFunction( found ) ) {
  316. response = found.apply(context, passedArguments);
  317. }
  318. else if(found !== undefined) {
  319. response = found;
  320. }
  321. if($.isArray(returnedValue)) {
  322. returnedValue.push(response);
  323. }
  324. else if(returnedValue !== undefined) {
  325. returnedValue = [returnedValue, response];
  326. }
  327. else if(response !== undefined) {
  328. returnedValue = response;
  329. }
  330. return found;
  331. }
  332. };
  333. if(methodInvoked) {
  334. if(instance === undefined) {
  335. module.initialize();
  336. }
  337. module.invoke(query);
  338. }
  339. else {
  340. if(instance !== undefined) {
  341. module.destroy();
  342. }
  343. module.initialize();
  344. }
  345. })
  346. ;
  347. return (returnedValue !== undefined)
  348. ? returnedValue
  349. : this
  350. ;
  351. };
  352. $.fn.rating.settings = {
  353. name : 'Rating',
  354. namespace : 'rating',
  355. debug : true,
  356. verbose : true,
  357. performance : true,
  358. initialRating : 0,
  359. interactive : true,
  360. clearable : 'auto',
  361. onRate : function(rating){},
  362. error : {
  363. method : 'The method you called is not defined'
  364. },
  365. metadata: {
  366. rating: 'rating'
  367. },
  368. className : {
  369. active : 'active',
  370. disabled : 'disabled',
  371. hover : 'hover',
  372. loading : 'loading'
  373. },
  374. selector : {
  375. icon : '.icon'
  376. }
  377. };
  378. })( jQuery, window , document );