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.

378 lines
11 KiB

10 years ago
  1. /*
  2. * # Semantic - Checkbox
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2013 Contributors
  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. $.proxy(module.toggle, this)();
  101. }
  102. }
  103. },
  104. is: {
  105. radio: function() {
  106. return $module.hasClass(className.radio);
  107. },
  108. checked: function() {
  109. return $input.prop('checked') !== undefined && $input.prop('checked');
  110. },
  111. unchecked: function() {
  112. return !module.is.checked();
  113. }
  114. },
  115. can: {
  116. uncheck: function() {
  117. return (typeof settings.required === 'boolean')
  118. ? settings.required
  119. : !module.is.radio()
  120. ;
  121. }
  122. },
  123. check: function() {
  124. module.debug('Enabling checkbox', $input);
  125. $input
  126. .prop('checked', true)
  127. .trigger('change')
  128. ;
  129. $.proxy(settings.onChange, $input.get())();
  130. $.proxy(settings.onChecked, $input.get())();
  131. },
  132. uncheck: function() {
  133. module.debug('Disabling checkbox');
  134. $input
  135. .prop('checked', false)
  136. .trigger('change')
  137. ;
  138. $.proxy(settings.onChange, $input.get())();
  139. $.proxy(settings.onUnchecked, $input.get())();
  140. },
  141. toggle: function(event) {
  142. module.verbose('Determining new checkbox state');
  143. if( module.is.unchecked() ) {
  144. module.check();
  145. }
  146. else if( module.is.checked() && module.can.uncheck() ) {
  147. module.uncheck();
  148. }
  149. },
  150. setting: function(name, value) {
  151. module.debug('Changing setting', name, value);
  152. if( $.isPlainObject(name) ) {
  153. $.extend(true, settings, name);
  154. }
  155. else if(value !== undefined) {
  156. settings[name] = value;
  157. }
  158. else {
  159. return settings[name];
  160. }
  161. },
  162. internal: function(name, value) {
  163. if( $.isPlainObject(name) ) {
  164. $.extend(true, module, name);
  165. }
  166. else if(value !== undefined) {
  167. module[name] = value;
  168. }
  169. else {
  170. return module[name];
  171. }
  172. },
  173. debug: function() {
  174. if(settings.debug) {
  175. if(settings.performance) {
  176. module.performance.log(arguments);
  177. }
  178. else {
  179. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  180. module.debug.apply(console, arguments);
  181. }
  182. }
  183. },
  184. verbose: function() {
  185. if(settings.verbose && settings.debug) {
  186. if(settings.performance) {
  187. module.performance.log(arguments);
  188. }
  189. else {
  190. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  191. module.verbose.apply(console, arguments);
  192. }
  193. }
  194. },
  195. error: function() {
  196. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  197. module.error.apply(console, arguments);
  198. },
  199. performance: {
  200. log: function(message) {
  201. var
  202. currentTime,
  203. executionTime,
  204. previousTime
  205. ;
  206. if(settings.performance) {
  207. currentTime = new Date().getTime();
  208. previousTime = time || currentTime;
  209. executionTime = currentTime - previousTime;
  210. time = currentTime;
  211. performance.push({
  212. 'Element' : element,
  213. 'Name' : message[0],
  214. 'Arguments' : [].slice.call(message, 1) || '',
  215. 'Execution Time' : executionTime
  216. });
  217. }
  218. clearTimeout(module.performance.timer);
  219. module.performance.timer = setTimeout(module.performance.display, 100);
  220. },
  221. display: function() {
  222. var
  223. title = settings.name + ':',
  224. totalTime = 0
  225. ;
  226. time = false;
  227. clearTimeout(module.performance.timer);
  228. $.each(performance, function(index, data) {
  229. totalTime += data['Execution Time'];
  230. });
  231. title += ' ' + totalTime + 'ms';
  232. if(moduleSelector) {
  233. title += ' \'' + moduleSelector + '\'';
  234. }
  235. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  236. console.groupCollapsed(title);
  237. if(console.table) {
  238. console.table(performance);
  239. }
  240. else {
  241. $.each(performance, function(index, data) {
  242. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  243. });
  244. }
  245. console.groupEnd();
  246. }
  247. performance = [];
  248. }
  249. },
  250. invoke: function(query, passedArguments, context) {
  251. var
  252. object = instance,
  253. maxDepth,
  254. found,
  255. response
  256. ;
  257. passedArguments = passedArguments || queryArguments;
  258. context = element || context;
  259. if(typeof query == 'string' && object !== undefined) {
  260. query = query.split(/[\. ]/);
  261. maxDepth = query.length - 1;
  262. $.each(query, function(depth, value) {
  263. var camelCaseValue = (depth != maxDepth)
  264. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  265. : query
  266. ;
  267. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  268. object = object[camelCaseValue];
  269. }
  270. else if( object[camelCaseValue] !== undefined ) {
  271. found = object[camelCaseValue];
  272. return false;
  273. }
  274. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  275. object = object[value];
  276. }
  277. else if( object[value] !== undefined ) {
  278. found = object[value];
  279. return false;
  280. }
  281. else {
  282. return false;
  283. }
  284. });
  285. }
  286. if ( $.isFunction( found ) ) {
  287. response = found.apply(context, passedArguments);
  288. }
  289. else if(found !== undefined) {
  290. response = found;
  291. }
  292. if($.isArray(returnedValue)) {
  293. returnedValue.push(response);
  294. }
  295. else if(returnedValue !== undefined) {
  296. returnedValue = [returnedValue, response];
  297. }
  298. else if(response !== undefined) {
  299. returnedValue = response;
  300. }
  301. return found;
  302. }
  303. };
  304. if(methodInvoked) {
  305. if(instance === undefined) {
  306. module.initialize();
  307. }
  308. module.invoke(query);
  309. }
  310. else {
  311. if(instance !== undefined) {
  312. module.destroy();
  313. }
  314. module.initialize();
  315. }
  316. })
  317. ;
  318. return (returnedValue !== undefined)
  319. ? returnedValue
  320. : this
  321. ;
  322. };
  323. $.fn.checkbox.settings = {
  324. name : 'Checkbox',
  325. namespace : 'checkbox',
  326. verbose : true,
  327. debug : true,
  328. performance : true,
  329. // delegated event context
  330. context : false,
  331. required : 'auto',
  332. onChange : function(){},
  333. onChecked : function(){},
  334. onUnchecked : function(){},
  335. error : {
  336. method : 'The method you called is not defined.'
  337. },
  338. selector : {
  339. input : 'input[type=checkbox], input[type=radio]',
  340. label : 'label'
  341. },
  342. className : {
  343. radio : 'radio'
  344. }
  345. };
  346. })( jQuery, window , document );