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.

303 lines
8.7 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. if($input.prop('checked') === undefined || !$input.prop('checked')) {
  100. module.enable();
  101. }
  102. else if( module.can.disable() ) {
  103. console.log(settings.required, module.can.disable());
  104. module.disable();
  105. }
  106. },
  107. setting: function(name, value) {
  108. if(value !== undefined) {
  109. if( $.isPlainObject(name) ) {
  110. $.extend(true, settings, name);
  111. }
  112. else {
  113. settings[name] = value;
  114. }
  115. }
  116. else {
  117. return settings[name];
  118. }
  119. },
  120. internal: function(name, value) {
  121. if(value !== undefined) {
  122. if( $.isPlainObject(name) ) {
  123. $.extend(true, module, name);
  124. }
  125. else {
  126. module[name] = value;
  127. }
  128. }
  129. else {
  130. return module[name];
  131. }
  132. },
  133. debug: function() {
  134. if(settings.debug) {
  135. module.performance.log(arguments[0]);
  136. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  137. }
  138. },
  139. verbose: function() {
  140. if(settings.verbose && settings.debug) {
  141. module.performance.log(arguments[0]);
  142. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  143. }
  144. },
  145. error: function() {
  146. if(console.log !== undefined) {
  147. module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
  148. }
  149. },
  150. performance: {
  151. log: function(message) {
  152. var
  153. currentTime,
  154. executionTime,
  155. previousTime
  156. ;
  157. if(settings.performance) {
  158. currentTime = new Date().getTime();
  159. previousTime = time || currentTime,
  160. executionTime = currentTime - previousTime;
  161. time = currentTime;
  162. performance.push({
  163. 'Element' : element,
  164. 'Name' : message,
  165. 'Execution Time' : executionTime
  166. });
  167. clearTimeout(module.performance.timer);
  168. module.performance.timer = setTimeout(module.performance.display, 100);
  169. }
  170. },
  171. display: function() {
  172. var
  173. title = settings.moduleName,
  174. caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)',
  175. totalExecutionTime = 0
  176. ;
  177. if(selector) {
  178. title += 'Performance (' + selector + ')';
  179. }
  180. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  181. console.groupCollapsed(title);
  182. if(console.table) {
  183. $.each(performance, function(index, data) {
  184. totalExecutionTime += data['Execution Time'];
  185. });
  186. console.table(performance);
  187. }
  188. else {
  189. $.each(performance, function(index, data) {
  190. totalExecutionTime += data['Execution Time'];
  191. });
  192. }
  193. console.log('Total Execution Time:', totalExecutionTime +'ms');
  194. console.groupEnd();
  195. performance = [];
  196. time = false;
  197. }
  198. }
  199. },
  200. invoke: function(query, passedArguments, context) {
  201. var
  202. maxDepth,
  203. found
  204. ;
  205. passedArguments = passedArguments || queryArguments;
  206. context = element || context;
  207. if(typeof query == 'string' && instance !== undefined) {
  208. query = query.split('.');
  209. maxDepth = query.length - 1;
  210. $.each(query, function(depth, value) {
  211. if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
  212. instance = instance[value];
  213. return true;
  214. }
  215. else if( instance[value] !== undefined ) {
  216. found = instance[value];
  217. return true;
  218. }
  219. module.error(errors.method);
  220. return false;
  221. });
  222. }
  223. if ( $.isFunction( found ) ) {
  224. module.verbose('Executing invoked function', found);
  225. return found.apply(context, passedArguments);
  226. }
  227. return found || false;
  228. }
  229. };
  230. if(methodInvoked) {
  231. if(instance === undefined) {
  232. module.initialize();
  233. }
  234. invokedResponse = module.invoke(query);
  235. }
  236. else {
  237. if(instance !== undefined) {
  238. module.destroy();
  239. }
  240. module.initialize();
  241. }
  242. })
  243. ;
  244. return (invokedResponse)
  245. ? invokedResponse
  246. : this
  247. ;
  248. };
  249. $.fn.checkbox.settings = {
  250. moduleName : 'Checkbox Module',
  251. namespace : 'checkbox',
  252. verbose : true,
  253. debug : true,
  254. performance : false,
  255. // delegated event context
  256. context : false,
  257. required : 'auto',
  258. onChange : function(){},
  259. onEnable : function(){},
  260. onDisable : function(){},
  261. errors : {
  262. method : 'The method you called is not defined.'
  263. },
  264. selector : {
  265. input : 'input'
  266. },
  267. className : {
  268. active : 'active',
  269. radio : 'radio'
  270. }
  271. };
  272. })( jQuery, window , document );