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.

509 lines
14 KiB

9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
10 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
  1. /*!
  2. * # Semantic UI 1.11.4 - Checkbox
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributors
  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. selector = settings.selector,
  31. error = settings.error,
  32. eventNamespace = '.' + namespace,
  33. moduleNamespace = 'module-' + namespace,
  34. $module = $(this),
  35. $label = $(this).find(selector.label).first(),
  36. $input = $(this).find(selector.input),
  37. instance = $module.data(moduleNamespace),
  38. observer,
  39. element = this,
  40. module
  41. ;
  42. module = {
  43. initialize: function() {
  44. module.verbose('Initializing checkbox', settings);
  45. module.create.label();
  46. module.add.events();
  47. if( module.is.checked() ) {
  48. module.set.checked();
  49. if(settings.fireOnInit) {
  50. settings.onChecked.call($input.get());
  51. }
  52. }
  53. else {
  54. module.remove.checked();
  55. if(settings.fireOnInit) {
  56. settings.onUnchecked.call($input.get());
  57. }
  58. }
  59. module.observeChanges();
  60. module.instantiate();
  61. },
  62. instantiate: function() {
  63. module.verbose('Storing instance of module', module);
  64. instance = module;
  65. $module
  66. .data(moduleNamespace, module)
  67. ;
  68. },
  69. destroy: function() {
  70. module.verbose('Destroying module');
  71. module.remove.events();
  72. $module
  73. .removeData(moduleNamespace)
  74. ;
  75. },
  76. refresh: function() {
  77. $module = $(this);
  78. $label = $(this).find(selector.label).first();
  79. $input = $(this).find(selector.input);
  80. },
  81. observeChanges: function() {
  82. if('MutationObserver' in window) {
  83. observer = new MutationObserver(function(mutations) {
  84. module.debug('DOM tree modified, updating selector cache');
  85. module.refresh();
  86. });
  87. observer.observe(element, {
  88. childList : true,
  89. subtree : true
  90. });
  91. module.debug('Setting up mutation observer', observer);
  92. }
  93. },
  94. attachEvents: function(selector, event) {
  95. var
  96. $element = $(selector)
  97. ;
  98. event = $.isFunction(module[event])
  99. ? module[event]
  100. : module.toggle
  101. ;
  102. if($element.length > 0) {
  103. module.debug('Attaching checkbox events to element', selector, event);
  104. $element
  105. .on('click' + eventNamespace, event)
  106. ;
  107. }
  108. else {
  109. module.error(error.notFound);
  110. }
  111. },
  112. event: {
  113. keydown: function(event) {
  114. var
  115. key = event.which,
  116. keyCode = {
  117. enter : 13,
  118. space : 32,
  119. escape : 27
  120. }
  121. ;
  122. if( key == keyCode.escape) {
  123. module.verbose('Escape key pressed blurring field');
  124. $module
  125. .blur()
  126. ;
  127. }
  128. if(!event.ctrlKey && (key == keyCode.enter || key == keyCode.space)) {
  129. module.verbose('Enter key pressed, toggling checkbox');
  130. module.toggle.call(this);
  131. event.preventDefault();
  132. }
  133. }
  134. },
  135. is: {
  136. radio: function() {
  137. return $module.hasClass(className.radio);
  138. },
  139. checked: function() {
  140. return $input.prop('checked') !== undefined && $input.prop('checked');
  141. },
  142. unchecked: function() {
  143. return !module.is.checked();
  144. }
  145. },
  146. can: {
  147. change: function() {
  148. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') );
  149. },
  150. uncheck: function() {
  151. return (typeof settings.uncheckable === 'boolean')
  152. ? settings.uncheckable
  153. : !module.is.radio()
  154. ;
  155. }
  156. },
  157. set: {
  158. checked: function() {
  159. $module.addClass(className.checked);
  160. },
  161. tab: function() {
  162. if( $input.attr('tabindex') === undefined) {
  163. $input
  164. .attr('tabindex', 0)
  165. ;
  166. }
  167. }
  168. },
  169. create: {
  170. label: function() {
  171. if($input.prevAll(selector.label).length > 0) {
  172. $input.prev(selector.label).detach().insertAfter($input);
  173. module.debug('Moving existing label', $label);
  174. }
  175. else if( !module.has.label() ) {
  176. $label = $('<label>').insertAfter($input);
  177. module.debug('Creating label', $label);
  178. }
  179. }
  180. },
  181. has: {
  182. label: function() {
  183. return ($label.length > 0);
  184. }
  185. },
  186. add: {
  187. events: function() {
  188. module.verbose('Attaching checkbox events');
  189. $module
  190. .on('click' + eventNamespace, module.toggle)
  191. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  192. ;
  193. }
  194. },
  195. remove: {
  196. checked: function() {
  197. $module.removeClass(className.checked);
  198. },
  199. events: function() {
  200. module.debug('Removing events');
  201. $module
  202. .off(eventNamespace)
  203. .removeData(moduleNamespace)
  204. ;
  205. $input
  206. .off(eventNamespace, module.event.keydown)
  207. ;
  208. $label
  209. .off(eventNamespace)
  210. ;
  211. }
  212. },
  213. enable: function() {
  214. module.debug('Enabling checkbox functionality');
  215. $module.removeClass(className.disabled);
  216. $input.prop('disabled', false);
  217. settings.onEnabled.call($input.get());
  218. },
  219. disable: function() {
  220. module.debug('Disabling checkbox functionality');
  221. $module.addClass(className.disabled);
  222. $input.prop('disabled', 'disabled');
  223. settings.onDisabled.call($input.get());
  224. },
  225. check: function() {
  226. module.debug('Enabling checkbox', $input);
  227. $input
  228. .prop('checked', true)
  229. .trigger('change')
  230. ;
  231. module.set.checked();
  232. $input.trigger('blur');
  233. settings.onChange.call($input.get());
  234. settings.onChecked.call($input.get());
  235. },
  236. uncheck: function() {
  237. module.debug('Disabling checkbox');
  238. $input
  239. .prop('checked', false)
  240. .trigger('change')
  241. ;
  242. module.remove.checked();
  243. $input.trigger('blur');
  244. settings.onChange.call($input.get());
  245. settings.onUnchecked.call($input.get());
  246. },
  247. toggle: function(event) {
  248. if( !module.can.change() ) {
  249. console.log(module.can.change());
  250. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  251. return;
  252. }
  253. module.verbose('Determining new checkbox state');
  254. if( module.is.unchecked() ) {
  255. module.check();
  256. }
  257. else if( module.is.checked() && module.can.uncheck() ) {
  258. module.uncheck();
  259. }
  260. },
  261. setting: function(name, value) {
  262. module.debug('Changing setting', name, value);
  263. if( $.isPlainObject(name) ) {
  264. $.extend(true, settings, name);
  265. }
  266. else if(value !== undefined) {
  267. settings[name] = value;
  268. }
  269. else {
  270. return settings[name];
  271. }
  272. },
  273. internal: function(name, value) {
  274. if( $.isPlainObject(name) ) {
  275. $.extend(true, module, name);
  276. }
  277. else if(value !== undefined) {
  278. module[name] = value;
  279. }
  280. else {
  281. return module[name];
  282. }
  283. },
  284. debug: function() {
  285. if(settings.debug) {
  286. if(settings.performance) {
  287. module.performance.log(arguments);
  288. }
  289. else {
  290. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  291. module.debug.apply(console, arguments);
  292. }
  293. }
  294. },
  295. verbose: function() {
  296. if(settings.verbose && settings.debug) {
  297. if(settings.performance) {
  298. module.performance.log(arguments);
  299. }
  300. else {
  301. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  302. module.verbose.apply(console, arguments);
  303. }
  304. }
  305. },
  306. error: function() {
  307. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  308. module.error.apply(console, arguments);
  309. },
  310. performance: {
  311. log: function(message) {
  312. var
  313. currentTime,
  314. executionTime,
  315. previousTime
  316. ;
  317. if(settings.performance) {
  318. currentTime = new Date().getTime();
  319. previousTime = time || currentTime;
  320. executionTime = currentTime - previousTime;
  321. time = currentTime;
  322. performance.push({
  323. 'Name' : message[0],
  324. 'Arguments' : [].slice.call(message, 1) || '',
  325. 'Element' : element,
  326. 'Execution Time' : executionTime
  327. });
  328. }
  329. clearTimeout(module.performance.timer);
  330. module.performance.timer = setTimeout(module.performance.display, 100);
  331. },
  332. display: function() {
  333. var
  334. title = settings.name + ':',
  335. totalTime = 0
  336. ;
  337. time = false;
  338. clearTimeout(module.performance.timer);
  339. $.each(performance, function(index, data) {
  340. totalTime += data['Execution Time'];
  341. });
  342. title += ' ' + totalTime + 'ms';
  343. if(moduleSelector) {
  344. title += ' \'' + moduleSelector + '\'';
  345. }
  346. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  347. console.groupCollapsed(title);
  348. if(console.table) {
  349. console.table(performance);
  350. }
  351. else {
  352. $.each(performance, function(index, data) {
  353. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  354. });
  355. }
  356. console.groupEnd();
  357. }
  358. performance = [];
  359. }
  360. },
  361. invoke: function(query, passedArguments, context) {
  362. var
  363. object = instance,
  364. maxDepth,
  365. found,
  366. response
  367. ;
  368. passedArguments = passedArguments || queryArguments;
  369. context = element || context;
  370. if(typeof query == 'string' && object !== undefined) {
  371. query = query.split(/[\. ]/);
  372. maxDepth = query.length - 1;
  373. $.each(query, function(depth, value) {
  374. var camelCaseValue = (depth != maxDepth)
  375. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  376. : query
  377. ;
  378. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  379. object = object[camelCaseValue];
  380. }
  381. else if( object[camelCaseValue] !== undefined ) {
  382. found = object[camelCaseValue];
  383. return false;
  384. }
  385. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  386. object = object[value];
  387. }
  388. else if( object[value] !== undefined ) {
  389. found = object[value];
  390. return false;
  391. }
  392. else {
  393. module.error(error.method, query);
  394. return false;
  395. }
  396. });
  397. }
  398. if ( $.isFunction( found ) ) {
  399. response = found.apply(context, passedArguments);
  400. }
  401. else if(found !== undefined) {
  402. response = found;
  403. }
  404. if($.isArray(returnedValue)) {
  405. returnedValue.push(response);
  406. }
  407. else if(returnedValue !== undefined) {
  408. returnedValue = [returnedValue, response];
  409. }
  410. else if(response !== undefined) {
  411. returnedValue = response;
  412. }
  413. return found;
  414. }
  415. };
  416. if(methodInvoked) {
  417. if(instance === undefined) {
  418. module.initialize();
  419. }
  420. module.invoke(query);
  421. }
  422. else {
  423. if(instance !== undefined) {
  424. instance.invoke('destroy');
  425. }
  426. module.initialize();
  427. }
  428. })
  429. ;
  430. return (returnedValue !== undefined)
  431. ? returnedValue
  432. : this
  433. ;
  434. };
  435. $.fn.checkbox.settings = {
  436. name : 'Checkbox',
  437. namespace : 'checkbox',
  438. debug : false,
  439. verbose : true,
  440. performance : true,
  441. // delegated event context
  442. uncheckable : 'auto',
  443. fireOnInit : true,
  444. onChange : function(){},
  445. onChecked : function(){},
  446. onUnchecked : function(){},
  447. onEnabled : function(){},
  448. onDisabled : function(){},
  449. className : {
  450. checked : 'checked',
  451. disabled : 'disabled',
  452. radio : 'radio',
  453. readOnly : 'read-only'
  454. },
  455. error : {
  456. method : 'The method you called is not defined'
  457. },
  458. selector : {
  459. input : 'input[type="checkbox"], input[type="radio"]',
  460. label : 'label'
  461. }
  462. };
  463. })( jQuery, window , document );