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.

406 lines
11 KiB

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