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.

307 lines
8.9 KiB

  1. /* ******************************
  2. Semantic Module: Checkbox
  3. Author: Jack Lukic
  4. Notes: First Commit March 25, 2013
  5. Simple plug-in which maintains the state for ui checkbox
  6. This can be done without javascript, only in instances
  7. where each checkbox is assigned a unique ID. This provides a separate
  8. programmatic option when that is not possible.
  9. ****************************** */
  10. ;(function ( $, window, document, undefined ) {
  11. $.fn.checkbox = function(parameters) {
  12. var
  13. $allModules = $(this),
  14. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  15. eventNamespace = '.' + settings.namespace,
  16. moduleNamespace = 'module-' + settings.namespace,
  17. selector = $allModules.selector || '',
  18. time = new Date().getTime(),
  19. performance = [],
  20. query = arguments[0],
  21. methodInvoked = (typeof query == 'string'),
  22. queryArguments = [].slice.call(arguments, 1),
  23. invokedResponse
  24. ;
  25. $allModules
  26. .each(function() {
  27. var
  28. $module = $(this),
  29. $input = $(this).find(settings.selector.input),
  30. selector = $module.selector || '',
  31. element = this,
  32. instance = $module.data('module-' + settings.namespace),
  33. className = settings.className,
  34. namespace = settings.namespace,
  35. errors = settings.errors,
  36. module
  37. ;
  38. module = {
  39. initialize: function() {
  40. if(settings.context && selector !== '') {
  41. module.verbose('Initializing checkbox with delegated events', $module);
  42. $(element, settings.context)
  43. .on(selector, 'click' + eventNamespace, module.toggle)
  44. .data(moduleNamespace, module)
  45. ;
  46. }
  47. else {
  48. module.verbose('Initializing checkbox with bound events', $module);
  49. $module
  50. .on('click' + eventNamespace, module.toggle)
  51. .data(moduleNamespace, module)
  52. ;
  53. }
  54. },
  55. is: {
  56. radio: function() {
  57. return $module
  58. .hasClass(className.radio)
  59. ;
  60. }
  61. },
  62. can: {
  63. disable: function() {
  64. return (typeof settings.required === 'boolean')
  65. ? settings.required
  66. : !module.is.radio()
  67. ;
  68. }
  69. },
  70. destroy: function() {
  71. module.verbose('Destroying previous module for', $module);
  72. $module
  73. .off(namespace)
  74. ;
  75. },
  76. enable: function() {
  77. module.debug('Enabling checkbox');
  78. $module
  79. .addClass(className.active)
  80. ;
  81. $input
  82. .prop('checked', true)
  83. ;
  84. $.proxy(settings.onChange, $input.get())();
  85. $.proxy(settings.onEnable, $input.get())();
  86. },
  87. disable: function() {
  88. module.debug('Disabling checkbox');
  89. $module
  90. .removeClass(className.active)
  91. ;
  92. $input
  93. .prop('checked', false)
  94. ;
  95. $.proxy(settings.onChange, $input.get())();
  96. $.proxy(settings.onDisable, $input.get())();
  97. },
  98. toggle: function() {
  99. module.verbose('Toggling checkbox state');
  100. if($input.prop('checked') === undefined || !$input.prop('checked')) {
  101. module.enable();
  102. }
  103. else if( module.can.disable() ) {
  104. module.disable();
  105. }
  106. },
  107. setting: function(name, value) {
  108. if(value !== undefined) {
  109. if( $.isPlainObject(name) ) {
  110. module.verbose('Modifying settings object', name, value);
  111. $.extend(true, settings, name);
  112. }
  113. else {
  114. module.verbose('Modifying setting', name, value);
  115. settings[name] = value;
  116. }
  117. }
  118. else {
  119. return settings[name];
  120. }
  121. },
  122. internal: function(name, value) {
  123. if(value !== undefined) {
  124. if( $.isPlainObject(name) ) {
  125. module.verbose('Modifying internal property', name, value);
  126. $.extend(true, module, name);
  127. }
  128. else {
  129. module.verbose('Changing internal method to', value);
  130. module[name] = value;
  131. }
  132. }
  133. else {
  134. return module[name];
  135. }
  136. },
  137. debug: function() {
  138. if(settings.debug) {
  139. module.performance.log(arguments[0]);
  140. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  141. }
  142. },
  143. verbose: function() {
  144. if(settings.verbose && settings.debug) {
  145. module.performance.log(arguments[0]);
  146. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  147. }
  148. },
  149. error: function() {
  150. if(console.log !== undefined) {
  151. module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
  152. }
  153. },
  154. performance: {
  155. log: function(message) {
  156. var
  157. currentTime,
  158. executionTime,
  159. previousTime
  160. ;
  161. if(settings.performance) {
  162. currentTime = new Date().getTime();
  163. previousTime = time || currentTime,
  164. executionTime = currentTime - previousTime;
  165. time = currentTime;
  166. performance.push({
  167. 'Element' : element,
  168. 'Name' : message,
  169. 'Execution Time' : executionTime
  170. });
  171. clearTimeout(module.performance.timer);
  172. module.performance.timer = setTimeout(module.performance.display, 100);
  173. }
  174. },
  175. display: function() {
  176. var
  177. title = settings.moduleName,
  178. caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)',
  179. totalExecutionTime = 0
  180. ;
  181. if(selector) {
  182. title += 'Performance (' + selector + ')';
  183. }
  184. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  185. console.groupCollapsed(title);
  186. if(console.table) {
  187. $.each(performance, function(index, data) {
  188. totalExecutionTime += data['Execution Time'];
  189. });
  190. console.table(performance);
  191. }
  192. else {
  193. $.each(performance, function(index, data) {
  194. totalExecutionTime += data['Execution Time'];
  195. });
  196. }
  197. console.log('Total Execution Time:', totalExecutionTime +'ms');
  198. console.groupEnd();
  199. performance = [];
  200. time = false;
  201. }
  202. }
  203. },
  204. invoke: function(query, passedArguments, context) {
  205. var
  206. maxDepth,
  207. found
  208. ;
  209. passedArguments = passedArguments || queryArguments;
  210. context = element || context;
  211. if(typeof query == 'string' && instance !== undefined) {
  212. query = query.split('.');
  213. maxDepth = query.length - 1;
  214. $.each(query, function(depth, value) {
  215. if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
  216. instance = instance[value];
  217. return true;
  218. }
  219. else if( instance[value] !== undefined ) {
  220. found = instance[value];
  221. return true;
  222. }
  223. module.error(errors.method);
  224. return false;
  225. });
  226. }
  227. if ( $.isFunction( found ) ) {
  228. module.verbose('Executing invoked function', found);
  229. return found.apply(context, passedArguments);
  230. }
  231. return found || false;
  232. }
  233. };
  234. if(methodInvoked) {
  235. if(instance === undefined) {
  236. module.initialize();
  237. }
  238. invokedResponse = module.invoke(query);
  239. }
  240. else {
  241. if(instance !== undefined) {
  242. module.destroy();
  243. }
  244. module.initialize();
  245. }
  246. })
  247. ;
  248. return (invokedResponse)
  249. ? invokedResponse
  250. : this
  251. ;
  252. };
  253. $.fn.checkbox.settings = {
  254. moduleName : 'Checkbox Module',
  255. namespace : 'checkbox',
  256. verbose : true,
  257. debug : true,
  258. performance : false,
  259. // delegated event context
  260. context : false,
  261. required : 'auto',
  262. onChange : function(){},
  263. onEnable : function(){},
  264. onDisable : function(){},
  265. errors : {
  266. method : 'The method you called is not defined.'
  267. },
  268. selector : {
  269. input : 'input'
  270. },
  271. className : {
  272. active : 'active',
  273. radio : 'radio'
  274. }
  275. };
  276. })( jQuery, window , document );