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.

412 lines
12 KiB

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