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.

380 lines
11 KiB

10 years ago
  1. /*
  2. * # Semantic - Checkbox
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributor
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ( $, window, document, undefined ) {
  12. $.fn.checkbox = function(parameters) {
  13. var
  14. $allModules = $(this),
  15. moduleSelector = $allModules.selector || '',
  16. time = new Date().getTime(),
  17. performance = [],
  18. query = arguments[0],
  19. methodInvoked = (typeof query == 'string'),
  20. queryArguments = [].slice.call(arguments, 1),
  21. returnedValue
  22. ;
  23. $allModules
  24. .each(function() {
  25. var
  26. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  27. className = settings.className,
  28. namespace = settings.namespace,
  29. error = settings.error,
  30. eventNamespace = '.' + namespace,
  31. moduleNamespace = 'module-' + namespace,
  32. $module = $(this),
  33. $label = $(this).next(settings.selector.label).first(),
  34. $input = $(this).find(settings.selector.input),
  35. selector = $module.selector || '',
  36. instance = $module.data(moduleNamespace),
  37. element = this,
  38. module
  39. ;
  40. module = {
  41. initialize: function() {
  42. module.verbose('Initializing checkbox', settings);
  43. if(settings.context && selector !== '') {
  44. module.verbose('Adding delegated events');
  45. $(element, settings.context)
  46. .on(selector, 'click' + eventNamespace, module.toggle)
  47. .on(selector + ' + ' + settings.selector.label, 'click' + eventNamespace, module.toggle)
  48. ;
  49. }
  50. else {
  51. $module
  52. .on('click' + eventNamespace, module.toggle)
  53. .data(moduleNamespace, module)
  54. ;
  55. $input
  56. .on('keydown' + eventNamespace, module.event.keydown)
  57. ;
  58. $label
  59. .on('click' + eventNamespace, module.toggle)
  60. ;
  61. }
  62. module.instantiate();
  63. },
  64. instantiate: function() {
  65. module.verbose('Storing instance of module', module);
  66. instance = module;
  67. $module
  68. .data(moduleNamespace, module)
  69. ;
  70. },
  71. destroy: function() {
  72. module.verbose('Destroying previous module');
  73. $module
  74. .off(eventNamespace)
  75. .removeData(moduleNamespace)
  76. ;
  77. $input
  78. .off(eventNamespace, module.event.keydown)
  79. ;
  80. $label
  81. .off(eventNamespace)
  82. ;
  83. },
  84. event: {
  85. keydown: function(event) {
  86. var
  87. key = event.which,
  88. keyCode = {
  89. enter : 13,
  90. escape : 27
  91. }
  92. ;
  93. if( key == keyCode.escape) {
  94. module.verbose('Escape key pressed blurring field');
  95. $module
  96. .blur()
  97. ;
  98. }
  99. if(!event.ctrlKey && key == keyCode.enter) {
  100. module.verbose('Enter key pressed, toggling checkbox');
  101. $.proxy(module.toggle, this)();
  102. event.preventDefault();
  103. }
  104. }
  105. },
  106. is: {
  107. radio: function() {
  108. return $module.hasClass(className.radio);
  109. },
  110. checked: function() {
  111. return $input.prop('checked') !== undefined && $input.prop('checked');
  112. },
  113. unchecked: function() {
  114. return !module.is.checked();
  115. }
  116. },
  117. can: {
  118. uncheck: function() {
  119. return (typeof settings.required === 'boolean')
  120. ? settings.required
  121. : !module.is.radio()
  122. ;
  123. }
  124. },
  125. check: function() {
  126. module.debug('Enabling checkbox', $input);
  127. $input
  128. .prop('checked', true)
  129. .trigger('change')
  130. ;
  131. $.proxy(settings.onChange, $input.get())();
  132. $.proxy(settings.onChecked, $input.get())();
  133. },
  134. uncheck: function() {
  135. module.debug('Disabling checkbox');
  136. $input
  137. .prop('checked', false)
  138. .trigger('change')
  139. ;
  140. $.proxy(settings.onChange, $input.get())();
  141. $.proxy(settings.onUnchecked, $input.get())();
  142. },
  143. toggle: function(event) {
  144. module.verbose('Determining new checkbox state');
  145. if( module.is.unchecked() ) {
  146. module.check();
  147. }
  148. else if( module.is.checked() && module.can.uncheck() ) {
  149. module.uncheck();
  150. }
  151. },
  152. setting: function(name, value) {
  153. module.debug('Changing setting', name, value);
  154. if( $.isPlainObject(name) ) {
  155. $.extend(true, settings, name);
  156. }
  157. else if(value !== undefined) {
  158. settings[name] = value;
  159. }
  160. else {
  161. return settings[name];
  162. }
  163. },
  164. internal: function(name, value) {
  165. if( $.isPlainObject(name) ) {
  166. $.extend(true, module, name);
  167. }
  168. else if(value !== undefined) {
  169. module[name] = value;
  170. }
  171. else {
  172. return module[name];
  173. }
  174. },
  175. debug: function() {
  176. if(settings.debug) {
  177. if(settings.performance) {
  178. module.performance.log(arguments);
  179. }
  180. else {
  181. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  182. module.debug.apply(console, arguments);
  183. }
  184. }
  185. },
  186. verbose: function() {
  187. if(settings.verbose && settings.debug) {
  188. if(settings.performance) {
  189. module.performance.log(arguments);
  190. }
  191. else {
  192. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  193. module.verbose.apply(console, arguments);
  194. }
  195. }
  196. },
  197. error: function() {
  198. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  199. module.error.apply(console, arguments);
  200. },
  201. performance: {
  202. log: function(message) {
  203. var
  204. currentTime,
  205. executionTime,
  206. previousTime
  207. ;
  208. if(settings.performance) {
  209. currentTime = new Date().getTime();
  210. previousTime = time || currentTime;
  211. executionTime = currentTime - previousTime;
  212. time = currentTime;
  213. performance.push({
  214. 'Element' : element,
  215. 'Name' : message[0],
  216. 'Arguments' : [].slice.call(message, 1) || '',
  217. 'Execution Time' : executionTime
  218. });
  219. }
  220. clearTimeout(module.performance.timer);
  221. module.performance.timer = setTimeout(module.performance.display, 100);
  222. },
  223. display: function() {
  224. var
  225. title = settings.name + ':',
  226. totalTime = 0
  227. ;
  228. time = false;
  229. clearTimeout(module.performance.timer);
  230. $.each(performance, function(index, data) {
  231. totalTime += data['Execution Time'];
  232. });
  233. title += ' ' + totalTime + 'ms';
  234. if(moduleSelector) {
  235. title += ' \'' + moduleSelector + '\'';
  236. }
  237. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  238. console.groupCollapsed(title);
  239. if(console.table) {
  240. console.table(performance);
  241. }
  242. else {
  243. $.each(performance, function(index, data) {
  244. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  245. });
  246. }
  247. console.groupEnd();
  248. }
  249. performance = [];
  250. }
  251. },
  252. invoke: function(query, passedArguments, context) {
  253. var
  254. object = instance,
  255. maxDepth,
  256. found,
  257. response
  258. ;
  259. passedArguments = passedArguments || queryArguments;
  260. context = element || context;
  261. if(typeof query == 'string' && object !== undefined) {
  262. query = query.split(/[\. ]/);
  263. maxDepth = query.length - 1;
  264. $.each(query, function(depth, value) {
  265. var camelCaseValue = (depth != maxDepth)
  266. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  267. : query
  268. ;
  269. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  270. object = object[camelCaseValue];
  271. }
  272. else if( object[camelCaseValue] !== undefined ) {
  273. found = object[camelCaseValue];
  274. return false;
  275. }
  276. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  277. object = object[value];
  278. }
  279. else if( object[value] !== undefined ) {
  280. found = object[value];
  281. return false;
  282. }
  283. else {
  284. return false;
  285. }
  286. });
  287. }
  288. if ( $.isFunction( found ) ) {
  289. response = found.apply(context, passedArguments);
  290. }
  291. else if(found !== undefined) {
  292. response = found;
  293. }
  294. if($.isArray(returnedValue)) {
  295. returnedValue.push(response);
  296. }
  297. else if(returnedValue !== undefined) {
  298. returnedValue = [returnedValue, response];
  299. }
  300. else if(response !== undefined) {
  301. returnedValue = response;
  302. }
  303. return found;
  304. }
  305. };
  306. if(methodInvoked) {
  307. if(instance === undefined) {
  308. module.initialize();
  309. }
  310. module.invoke(query);
  311. }
  312. else {
  313. if(instance !== undefined) {
  314. module.destroy();
  315. }
  316. module.initialize();
  317. }
  318. })
  319. ;
  320. return (returnedValue !== undefined)
  321. ? returnedValue
  322. : this
  323. ;
  324. };
  325. $.fn.checkbox.settings = {
  326. name : 'Checkbox',
  327. namespace : 'checkbox',
  328. verbose : true,
  329. debug : true,
  330. performance : true,
  331. // delegated event context
  332. context : false,
  333. required : 'auto',
  334. onChange : function(){},
  335. onChecked : function(){},
  336. onUnchecked : function(){},
  337. error : {
  338. method : 'The method you called is not defined.'
  339. },
  340. selector : {
  341. input : 'input[type=checkbox], input[type=radio]',
  342. label : 'label'
  343. },
  344. className : {
  345. radio : 'radio'
  346. }
  347. };
  348. })( jQuery, window , document );