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.

333 lines
9.4 KiB

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