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.

361 lines
10 KiB

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