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.

319 lines
9.2 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. moduleSelector = $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. $label = $(this).next(settings.selector.label).first(),
  30. $input = $(this).find(settings.selector.input),
  31. selector = $module.selector || '',
  32. element = this,
  33. instance = $module.data('module-' + settings.namespace),
  34. className = settings.className,
  35. namespace = settings.namespace,
  36. errors = settings.errors,
  37. module
  38. ;
  39. module = {
  40. initialize: function() {
  41. if(settings.context && selector !== '') {
  42. module.verbose('Initializing checkbox with delegated events', $module);
  43. $(element, settings.context)
  44. .on(selector, 'click' + eventNamespace, module.toggle)
  45. .on(selector + ' + ' + settings.selector.label, 'click' + eventNamespace, module.toggle)
  46. .data(moduleNamespace, module)
  47. ;
  48. }
  49. else {
  50. module.verbose('Initializing checkbox with bound events', $module);
  51. $module
  52. .on('click' + eventNamespace, module.toggle)
  53. .data(moduleNamespace, module)
  54. ;
  55. $label
  56. .on('click' + eventNamespace, module.toggle)
  57. ;
  58. }
  59. },
  60. destroy: function() {
  61. module.verbose('Destroying previous module for', $module);
  62. $module
  63. .off(namespace)
  64. ;
  65. },
  66. is: {
  67. radio: function() {
  68. return $module
  69. .hasClass(className.radio)
  70. ;
  71. }
  72. },
  73. can: {
  74. disable: function() {
  75. return (typeof settings.required === 'boolean')
  76. ? settings.required
  77. : !module.is.radio()
  78. ;
  79. }
  80. },
  81. enable: function() {
  82. module.debug('Enabling checkbox');
  83. $module
  84. .addClass(className.active)
  85. ;
  86. $input
  87. .prop('checked', true)
  88. ;
  89. $.proxy(settings.onChange, $input.get())();
  90. $.proxy(settings.onEnable, $input.get())();
  91. },
  92. disable: function() {
  93. module.debug('Disabling checkbox');
  94. $module
  95. .removeClass(className.active)
  96. ;
  97. $input
  98. .prop('checked', false)
  99. ;
  100. $.proxy(settings.onChange, $input.get())();
  101. $.proxy(settings.onDisable, $input.get())();
  102. },
  103. toggle: function() {
  104. module.verbose('Toggling checkbox state');
  105. if($input.prop('checked') === undefined || !$input.prop('checked')) {
  106. module.enable();
  107. }
  108. else if( module.can.disable() ) {
  109. module.disable();
  110. }
  111. },
  112. setting: function(name, value) {
  113. if(value !== undefined) {
  114. if( $.isPlainObject(name) ) {
  115. module.verbose('Modifying settings object', name, value);
  116. $.extend(true, settings, name);
  117. }
  118. else {
  119. module.verbose('Modifying setting', name, value);
  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. module.verbose('Modifying internal property', name, value);
  131. $.extend(true, module, name);
  132. }
  133. else {
  134. module.verbose('Changing internal method to', value);
  135. module[name] = value;
  136. }
  137. }
  138. else {
  139. return module[name];
  140. }
  141. },
  142. debug: function() {
  143. if(settings.debug) {
  144. if(settings.performance) {
  145. module.performance.log(arguments);
  146. }
  147. else {
  148. module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  149. }
  150. }
  151. },
  152. verbose: function() {
  153. if(settings.verbose && settings.debug) {
  154. if(settings.performance) {
  155. module.performance.log(arguments);
  156. }
  157. else {
  158. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  159. }
  160. }
  161. },
  162. error: function() {
  163. module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
  164. },
  165. performance: {
  166. log: function(message) {
  167. var
  168. currentTime,
  169. executionTime,
  170. previousTime
  171. ;
  172. if(settings.performance) {
  173. currentTime = new Date().getTime();
  174. previousTime = time || currentTime,
  175. executionTime = currentTime - previousTime;
  176. time = currentTime;
  177. performance.push({
  178. 'Element' : element,
  179. 'Name' : message[0],
  180. 'Arguments' : message[1] || '',
  181. 'Execution Time' : executionTime
  182. });
  183. }
  184. clearTimeout(module.performance.timer);
  185. module.performance.timer = setTimeout(module.performance.display, 100);
  186. },
  187. display: function() {
  188. var
  189. title = settings.moduleName + ':',
  190. totalTime = 0
  191. ;
  192. time = false;
  193. $.each(performance, function(index, data) {
  194. totalTime += data['Execution Time'];
  195. });
  196. title += ' ' + totalTime + 'ms';
  197. if(moduleSelector) {
  198. title += ' \'' + moduleSelector + '\'';
  199. }
  200. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  201. console.groupCollapsed(title);
  202. if(console.table) {
  203. console.table(performance);
  204. }
  205. else {
  206. $.each(performance, function(index, data) {
  207. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  208. });
  209. }
  210. console.groupEnd();
  211. }
  212. performance = [];
  213. }
  214. },
  215. invoke: function(query, passedArguments, context) {
  216. var
  217. maxDepth,
  218. found
  219. ;
  220. passedArguments = passedArguments || queryArguments;
  221. context = element || context;
  222. if(typeof query == 'string' && instance !== undefined) {
  223. query = query.split('.');
  224. maxDepth = query.length - 1;
  225. $.each(query, function(depth, value) {
  226. if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
  227. instance = instance[value];
  228. return true;
  229. }
  230. else if( instance[value] !== undefined ) {
  231. found = instance[value];
  232. return true;
  233. }
  234. module.error(errors.method);
  235. return false;
  236. });
  237. }
  238. if ( $.isFunction( found ) ) {
  239. instance.verbose('Executing invoked function', found);
  240. return found.apply(context, passedArguments);
  241. }
  242. return found || false;
  243. }
  244. };
  245. if(methodInvoked) {
  246. if(instance === undefined) {
  247. module.initialize();
  248. }
  249. invokedResponse = module.invoke(query);
  250. }
  251. else {
  252. if(instance !== undefined) {
  253. module.destroy();
  254. }
  255. module.initialize();
  256. }
  257. })
  258. ;
  259. return (invokedResponse)
  260. ? invokedResponse
  261. : this
  262. ;
  263. };
  264. $.fn.checkbox.settings = {
  265. moduleName : 'Checkbox',
  266. namespace : 'checkbox',
  267. verbose : true,
  268. debug : true,
  269. performance : true,
  270. // delegated event context
  271. context : false,
  272. required : 'auto',
  273. onChange : function(){},
  274. onEnable : function(){},
  275. onDisable : function(){},
  276. errors : {
  277. method : 'The method you called is not defined.'
  278. },
  279. selector : {
  280. input : 'input',
  281. label : 'label'
  282. },
  283. className : {
  284. active : 'active',
  285. radio : 'radio'
  286. }
  287. };
  288. })( jQuery, window , document );