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.

315 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. $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. destroy: function() {
  56. module.verbose('Destroying previous module for', $module);
  57. $module
  58. .off(namespace)
  59. ;
  60. },
  61. is: {
  62. radio: function() {
  63. return $module
  64. .hasClass(className.radio)
  65. ;
  66. }
  67. },
  68. can: {
  69. disable: function() {
  70. return (typeof settings.required === 'boolean')
  71. ? settings.required
  72. : !module.is.radio()
  73. ;
  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. if(settings.performance) {
  140. module.performance.log(arguments);
  141. }
  142. else {
  143. module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  144. }
  145. }
  146. },
  147. verbose: function() {
  148. if(settings.verbose && settings.debug) {
  149. if(settings.performance) {
  150. module.performance.log(arguments);
  151. }
  152. else {
  153. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  154. }
  155. }
  156. },
  157. error: function() {
  158. module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
  159. },
  160. performance: {
  161. log: function(message) {
  162. var
  163. currentTime,
  164. executionTime,
  165. previousTime
  166. ;
  167. if(settings.performance) {
  168. currentTime = new Date().getTime();
  169. previousTime = time || currentTime,
  170. executionTime = currentTime - previousTime;
  171. time = currentTime;
  172. performance.push({
  173. 'Element' : element,
  174. 'Name' : message[0],
  175. 'Arguments' : message[1] || 'None',
  176. 'Execution Time' : executionTime
  177. });
  178. clearTimeout(module.performance.timer);
  179. module.performance.timer = setTimeout(module.performance.display, 100);
  180. }
  181. },
  182. display: function() {
  183. var
  184. title = settings.moduleName,
  185. caption = settings.moduleName + ': ' + moduleSelector + '(' + $allModules.size() + ' elements)',
  186. totalExecutionTime = 0
  187. ;
  188. if(moduleSelector) {
  189. title += ' Performance (' + moduleSelector + ')';
  190. }
  191. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  192. console.groupCollapsed(title);
  193. if(console.table) {
  194. $.each(performance, function(index, data) {
  195. totalExecutionTime += data['Execution Time'];
  196. });
  197. console.table(performance);
  198. }
  199. else {
  200. $.each(performance, function(index, data) {
  201. totalExecutionTime += data['Execution Time'];
  202. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  203. });
  204. }
  205. console.log('Total Execution Time:', totalExecutionTime +'ms');
  206. console.groupEnd();
  207. performance = [];
  208. time = false;
  209. }
  210. }
  211. },
  212. invoke: function(query, passedArguments, context) {
  213. var
  214. maxDepth,
  215. found
  216. ;
  217. passedArguments = passedArguments || queryArguments;
  218. context = element || context;
  219. if(typeof query == 'string' && instance !== undefined) {
  220. query = query.split('.');
  221. maxDepth = query.length - 1;
  222. $.each(query, function(depth, value) {
  223. if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
  224. instance = instance[value];
  225. return true;
  226. }
  227. else if( instance[value] !== undefined ) {
  228. found = instance[value];
  229. return true;
  230. }
  231. module.error(errors.method);
  232. return false;
  233. });
  234. }
  235. if ( $.isFunction( found ) ) {
  236. module.verbose('Executing invoked function', found);
  237. return found.apply(context, passedArguments);
  238. }
  239. return found || false;
  240. }
  241. };
  242. if(methodInvoked) {
  243. if(instance === undefined) {
  244. module.initialize();
  245. }
  246. invokedResponse = module.invoke(query);
  247. }
  248. else {
  249. if(instance !== undefined) {
  250. module.destroy();
  251. }
  252. module.initialize();
  253. }
  254. })
  255. ;
  256. return (invokedResponse)
  257. ? invokedResponse
  258. : this
  259. ;
  260. };
  261. $.fn.checkbox.settings = {
  262. moduleName : 'Checkbox Module',
  263. namespace : 'checkbox',
  264. verbose : true,
  265. debug : true,
  266. performance : true,
  267. // delegated event context
  268. context : false,
  269. required : 'auto',
  270. onChange : function(){},
  271. onEnable : function(){},
  272. onDisable : function(){},
  273. errors : {
  274. method : 'The method you called is not defined.'
  275. },
  276. selector : {
  277. input : 'input'
  278. },
  279. className : {
  280. active : 'active',
  281. radio : 'radio'
  282. }
  283. };
  284. })( jQuery, window , document );