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
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[camelCaseValue] ) && (depth != maxDepth) ) {
  291. instance = instance[camelCaseValue];
  292. }
  293. else if( instance[camelCaseValue] !== undefined ) {
  294. found = instance[camelCaseValue];
  295. return false;
  296. }
  297. else if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
  298. instance = instance[value];
  299. }
  300. else if( instance[value] !== undefined ) {
  301. found = instance[value];
  302. return false;
  303. }
  304. else {
  305. module.error(error.method, query);
  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 );