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.

715 lines
22 KiB

9 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
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 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
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
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
10 years ago
9 years ago
10 years ago
10 years ago
10 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
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
  1. /*!
  2. * # Semantic UI 2.0.1 - Checkbox
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2015 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).children(selector.label),
  36. $input = $(this).children(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.bind.events();
  47. module.set.tabbable();
  48. module.hide.input();
  49. module.observeChanges();
  50. module.instantiate();
  51. module.setup();
  52. },
  53. instantiate: function() {
  54. module.verbose('Storing instance of module', module);
  55. instance = module;
  56. $module
  57. .data(moduleNamespace, module)
  58. ;
  59. },
  60. destroy: function() {
  61. module.verbose('Destroying module');
  62. module.unbind.events();
  63. module.show.input();
  64. $module.removeData(moduleNamespace);
  65. },
  66. fix: {
  67. reference: function() {
  68. if( $module.is(selector.input) ) {
  69. module.debug('Behavior called on <input> adjusting invoked element');
  70. $module = $module.closest(selector.checkbox);
  71. module.refresh();
  72. }
  73. }
  74. },
  75. setup: function() {
  76. if( module.is.indeterminate() ) {
  77. module.debug('Initial value is indeterminate');
  78. module.set.indeterminate();
  79. if(settings.fireOnInit) {
  80. settings.onIndeterminate.call($input[0]);
  81. settings.onChange.call($input[0]);
  82. }
  83. }
  84. else if( module.is.checked() ) {
  85. module.debug('Initial value is checked');
  86. module.set.checked();
  87. if(settings.fireOnInit) {
  88. settings.onChecked.call($input[0]);
  89. settings.onChange.call($input[0]);
  90. }
  91. }
  92. else {
  93. module.debug('Initial value is unchecked');
  94. module.set.unchecked();
  95. if(settings.fireOnInit) {
  96. settings.onUnchecked.call($input[0]);
  97. settings.onChange.call($input[0]);
  98. }
  99. }
  100. },
  101. refresh: function() {
  102. $label = $module.children(selector.label);
  103. $input = $module.children(selector.input);
  104. },
  105. hide: {
  106. input: function() {
  107. module.verbose('Modfying <input> z-index to be unselectable');
  108. $input.addClass(className.hidden);
  109. }
  110. },
  111. show: {
  112. input: function() {
  113. module.verbose('Modfying <input> z-index to be selectable');
  114. $input.removeClass(className.hidden);
  115. }
  116. },
  117. observeChanges: function() {
  118. if('MutationObserver' in window) {
  119. observer = new MutationObserver(function(mutations) {
  120. module.debug('DOM tree modified, updating selector cache');
  121. module.refresh();
  122. });
  123. observer.observe(element, {
  124. childList : true,
  125. subtree : true
  126. });
  127. module.debug('Setting up mutation observer', observer);
  128. }
  129. },
  130. attachEvents: function(selector, event) {
  131. var
  132. $element = $(selector)
  133. ;
  134. event = $.isFunction(module[event])
  135. ? module[event]
  136. : module.toggle
  137. ;
  138. if($element.length > 0) {
  139. module.debug('Attaching checkbox events to element', selector, event);
  140. $element
  141. .on('click' + eventNamespace, event)
  142. ;
  143. }
  144. else {
  145. module.error(error.notFound);
  146. }
  147. },
  148. event: {
  149. click: function(event) {
  150. if( $(event.target).is(selector.input) ) {
  151. module.verbose('Using default check action on initialized checkbox');
  152. return;
  153. }
  154. module.toggle();
  155. },
  156. keydown: function(event) {
  157. var
  158. key = event.which,
  159. keyCode = {
  160. enter : 13,
  161. space : 32,
  162. escape : 27
  163. }
  164. ;
  165. if(key == keyCode.escape) {
  166. module.verbose('Escape key pressed blurring field');
  167. $input.blur();
  168. event.preventDefault();
  169. }
  170. if(!event.ctrlKey && (key == keyCode.enter || key == keyCode.space)) {
  171. module.verbose('Enter key pressed, toggling checkbox');
  172. module.toggle();
  173. event.preventDefault();
  174. }
  175. }
  176. },
  177. check: function() {
  178. if( !module.is.indeterminate() && module.is.checked() ) {
  179. module.debug('Checkbox is already checked');
  180. return;
  181. }
  182. module.debug('Checking checkbox', $input);
  183. module.set.checked();
  184. settings.onChecked.call($input[0]);
  185. settings.onChange.call($input[0]);
  186. },
  187. uncheck: function() {
  188. if( !module.is.indeterminate() && module.is.unchecked() ) {
  189. module.debug('Checkbox is already unchecked');
  190. return;
  191. }
  192. module.debug('Unchecking checkbox');
  193. module.set.unchecked();
  194. settings.onUnchecked.call($input[0]);
  195. settings.onChange.call($input[0]);
  196. },
  197. indeterminate: function() {
  198. if( module.is.indeterminate() ) {
  199. module.debug('Checkbox is already indeterminate');
  200. return;
  201. }
  202. module.debug('Making checkbox indeterminate');
  203. module.set.indeterminate();
  204. settings.onIndeterminate.call($input[0]);
  205. settings.onChange.call($input[0]);
  206. },
  207. determinate: function() {
  208. if( module.is.determinate() ) {
  209. module.debug('Checkbox is already determinate');
  210. return;
  211. }
  212. module.debug('Making checkbox determinate');
  213. module.set.determinate();
  214. settings.onDeterminate.call($input[0]);
  215. settings.onChange.call($input[0]);
  216. },
  217. enable: function() {
  218. if( module.is.enabled() ) {
  219. module.debug('Checkbox is already enabled');
  220. return;
  221. }
  222. module.debug('Enabling checkbox');
  223. module.set.enabled();
  224. settings.onEnable.call($input[0]);
  225. },
  226. disable: function() {
  227. if( module.is.disabled() ) {
  228. module.debug('Checkbox is already disabled');
  229. return;
  230. }
  231. module.debug('Disabling checkbox');
  232. module.set.disabled();
  233. settings.onDisable.call($input[0]);
  234. },
  235. get: {
  236. radios: function() {
  237. var
  238. name = module.get.name()
  239. ;
  240. return $('input[name="' + name + '"]').closest(selector.checkbox);
  241. },
  242. otherRadios: function() {
  243. return module.get.radios().not($module);
  244. },
  245. name: function() {
  246. return $input.attr('name');
  247. }
  248. },
  249. is: {
  250. radio: function() {
  251. return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
  252. },
  253. indeterminate: function() {
  254. return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
  255. },
  256. checked: function() {
  257. return $input.prop('checked') !== undefined && $input.prop('checked');
  258. },
  259. disabled: function() {
  260. return $input.prop('disabled') !== undefined && $input.prop('disabled');
  261. },
  262. enabled: function() {
  263. return !module.is.disabled();
  264. },
  265. determinate: function() {
  266. return !module.is.indeterminate();
  267. },
  268. unchecked: function() {
  269. return !module.is.checked();
  270. }
  271. },
  272. can: {
  273. change: function() {
  274. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
  275. },
  276. uncheck: function() {
  277. return (typeof settings.uncheckable === 'boolean')
  278. ? settings.uncheckable
  279. : !module.is.radio()
  280. ;
  281. }
  282. },
  283. set: {
  284. checked: function() {
  285. module.verbose('Setting class to checked');
  286. $module
  287. .removeClass(className.indeterminate)
  288. .addClass(className.checked)
  289. ;
  290. if( module.is.radio() ) {
  291. module.uncheckOthers();
  292. }
  293. if(!module.is.indeterminate() && module.is.checked()) {
  294. module.debug('Input is already checked, skipping input property change');
  295. return;
  296. }
  297. module.verbose('Setting state to checked', $input[0]);
  298. $input
  299. .prop('indeterminate', false)
  300. .prop('checked', true)
  301. ;
  302. module.trigger.change();
  303. },
  304. unchecked: function() {
  305. module.verbose('Removing checked class');
  306. $module
  307. .removeClass(className.indeterminate)
  308. .removeClass(className.checked)
  309. ;
  310. if(!module.is.indeterminate() && module.is.unchecked() ) {
  311. module.debug('Input is already unchecked');
  312. return;
  313. }
  314. module.debug('Setting state to unchecked');
  315. $input
  316. .prop('indeterminate', false)
  317. .prop('checked', false)
  318. ;
  319. module.trigger.change();
  320. },
  321. indeterminate: function() {
  322. module.verbose('Setting class to indeterminate');
  323. $module
  324. .addClass(className.indeterminate)
  325. ;
  326. if( module.is.indeterminate() ) {
  327. module.debug('Input is already indeterminate, skipping input property change');
  328. return;
  329. }
  330. module.debug('Setting state to indeterminate');
  331. $input
  332. .prop('indeterminate', true)
  333. ;
  334. module.trigger.change();
  335. },
  336. determinate: function() {
  337. module.verbose('Removing indeterminate class');
  338. $module
  339. .removeClass(className.indeterminate)
  340. ;
  341. if( module.is.determinate() ) {
  342. module.debug('Input is already determinate, skipping input property change');
  343. return;
  344. }
  345. module.debug('Setting state to determinate');
  346. $input
  347. .prop('indeterminate', false)
  348. ;
  349. },
  350. disabled: function() {
  351. module.verbose('Setting class to disabled');
  352. $module
  353. .addClass(className.disabled)
  354. ;
  355. if( module.is.disabled() ) {
  356. module.debug('Input is already disabled, skipping input property change');
  357. return;
  358. }
  359. module.debug('Setting state to disabled');
  360. $input
  361. .prop('disabled', 'disabled')
  362. ;
  363. module.trigger.change();
  364. },
  365. enabled: function() {
  366. module.verbose('Removing disabled class');
  367. $module.removeClass(className.disabled);
  368. if( module.is.enabled() ) {
  369. module.debug('Input is already enabled, skipping input property change');
  370. return;
  371. }
  372. module.debug('Setting state to enabled');
  373. $input
  374. .prop('disabled', false)
  375. ;
  376. module.trigger.change();
  377. },
  378. tabbable: function() {
  379. module.verbose('Adding tabindex to checkbox');
  380. if( $input.attr('tabindex') === undefined) {
  381. $input.attr('tabindex', 0);
  382. }
  383. }
  384. },
  385. trigger: {
  386. change: function() {
  387. module.verbose('Triggering change event from programmatic change');
  388. $input
  389. .trigger('change')
  390. ;
  391. }
  392. },
  393. create: {
  394. label: function() {
  395. if($input.prevAll(selector.label).length > 0) {
  396. $input.prev(selector.label).detach().insertAfter($input);
  397. module.debug('Moving existing label', $label);
  398. }
  399. else if( !module.has.label() ) {
  400. $label = $('<label>').insertAfter($input);
  401. module.debug('Creating label', $label);
  402. }
  403. }
  404. },
  405. has: {
  406. label: function() {
  407. return ($label.length > 0);
  408. }
  409. },
  410. bind: {
  411. events: function() {
  412. module.verbose('Attaching checkbox events');
  413. $module
  414. .on('click' + eventNamespace, module.event.click)
  415. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  416. ;
  417. }
  418. },
  419. unbind: {
  420. events: function() {
  421. module.debug('Removing events');
  422. $module
  423. .off(eventNamespace)
  424. ;
  425. }
  426. },
  427. uncheckOthers: function() {
  428. var
  429. $radios = module.get.otherRadios()
  430. ;
  431. module.debug('Unchecking other radios', $radios);
  432. $radios.removeClass(className.checked);
  433. },
  434. toggle: function() {
  435. if( !module.can.change() ) {
  436. if(!module.is.radio()) {
  437. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  438. }
  439. return;
  440. }
  441. if( module.is.indeterminate() || module.is.unchecked() ) {
  442. module.debug('Currently unchecked');
  443. module.check();
  444. }
  445. else if( module.is.checked() && module.can.uncheck() ) {
  446. module.debug('Currently checked');
  447. module.uncheck();
  448. }
  449. },
  450. setting: function(name, value) {
  451. module.debug('Changing setting', name, value);
  452. if( $.isPlainObject(name) ) {
  453. $.extend(true, settings, name);
  454. }
  455. else if(value !== undefined) {
  456. settings[name] = value;
  457. }
  458. else {
  459. return settings[name];
  460. }
  461. },
  462. internal: function(name, value) {
  463. if( $.isPlainObject(name) ) {
  464. $.extend(true, module, name);
  465. }
  466. else if(value !== undefined) {
  467. module[name] = value;
  468. }
  469. else {
  470. return module[name];
  471. }
  472. },
  473. debug: function() {
  474. if(settings.debug) {
  475. if(settings.performance) {
  476. module.performance.log(arguments);
  477. }
  478. else {
  479. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  480. module.debug.apply(console, arguments);
  481. }
  482. }
  483. },
  484. verbose: function() {
  485. if(settings.verbose && settings.debug) {
  486. if(settings.performance) {
  487. module.performance.log(arguments);
  488. }
  489. else {
  490. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  491. module.verbose.apply(console, arguments);
  492. }
  493. }
  494. },
  495. error: function() {
  496. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  497. module.error.apply(console, arguments);
  498. },
  499. performance: {
  500. log: function(message) {
  501. var
  502. currentTime,
  503. executionTime,
  504. previousTime
  505. ;
  506. if(settings.performance) {
  507. currentTime = new Date().getTime();
  508. previousTime = time || currentTime;
  509. executionTime = currentTime - previousTime;
  510. time = currentTime;
  511. performance.push({
  512. 'Name' : message[0],
  513. 'Arguments' : [].slice.call(message, 1) || '',
  514. 'Element' : element,
  515. 'Execution Time' : executionTime
  516. });
  517. }
  518. clearTimeout(module.performance.timer);
  519. module.performance.timer = setTimeout(module.performance.display, 500);
  520. },
  521. display: function() {
  522. var
  523. title = settings.name + ':',
  524. totalTime = 0
  525. ;
  526. time = false;
  527. clearTimeout(module.performance.timer);
  528. $.each(performance, function(index, data) {
  529. totalTime += data['Execution Time'];
  530. });
  531. title += ' ' + totalTime + 'ms';
  532. if(moduleSelector) {
  533. title += ' \'' + moduleSelector + '\'';
  534. }
  535. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  536. console.groupCollapsed(title);
  537. if(console.table) {
  538. console.table(performance);
  539. }
  540. else {
  541. $.each(performance, function(index, data) {
  542. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  543. });
  544. }
  545. console.groupEnd();
  546. }
  547. performance = [];
  548. }
  549. },
  550. invoke: function(query, passedArguments, context) {
  551. var
  552. object = instance,
  553. maxDepth,
  554. found,
  555. response
  556. ;
  557. passedArguments = passedArguments || queryArguments;
  558. context = element || context;
  559. if(typeof query == 'string' && object !== undefined) {
  560. query = query.split(/[\. ]/);
  561. maxDepth = query.length - 1;
  562. $.each(query, function(depth, value) {
  563. var camelCaseValue = (depth != maxDepth)
  564. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  565. : query
  566. ;
  567. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  568. object = object[camelCaseValue];
  569. }
  570. else if( object[camelCaseValue] !== undefined ) {
  571. found = object[camelCaseValue];
  572. return false;
  573. }
  574. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  575. object = object[value];
  576. }
  577. else if( object[value] !== undefined ) {
  578. found = object[value];
  579. return false;
  580. }
  581. else {
  582. module.error(error.method, query);
  583. return false;
  584. }
  585. });
  586. }
  587. if ( $.isFunction( found ) ) {
  588. response = found.apply(context, passedArguments);
  589. }
  590. else if(found !== undefined) {
  591. response = found;
  592. }
  593. if($.isArray(returnedValue)) {
  594. returnedValue.push(response);
  595. }
  596. else if(returnedValue !== undefined) {
  597. returnedValue = [returnedValue, response];
  598. }
  599. else if(response !== undefined) {
  600. returnedValue = response;
  601. }
  602. return found;
  603. }
  604. };
  605. if(methodInvoked) {
  606. if(instance === undefined) {
  607. module.initialize();
  608. }
  609. module.invoke(query);
  610. }
  611. else {
  612. if(instance !== undefined) {
  613. instance.invoke('destroy');
  614. }
  615. module.initialize();
  616. }
  617. })
  618. ;
  619. return (returnedValue !== undefined)
  620. ? returnedValue
  621. : this
  622. ;
  623. };
  624. $.fn.checkbox.settings = {
  625. name : 'Checkbox',
  626. namespace : 'checkbox',
  627. debug : false,
  628. verbose : true,
  629. performance : true,
  630. // delegated event context
  631. uncheckable : 'auto',
  632. fireOnInit : false,
  633. onChange : function(){},
  634. onChecked : function(){},
  635. onUnchecked : function(){},
  636. onDeterminate : function() {},
  637. onIndeterminate : function() {},
  638. onEnabled : function(){},
  639. onDisabled : function(){},
  640. className : {
  641. checked : 'checked',
  642. indeterminate : 'indeterminate',
  643. disabled : 'disabled',
  644. hidden : 'hidden',
  645. radio : 'radio',
  646. readOnly : 'read-only'
  647. },
  648. error : {
  649. method : 'The method you called is not defined'
  650. },
  651. selector : {
  652. checkbox : '.ui.checkbox',
  653. label : 'label, .box',
  654. input : 'input[type="checkbox"], input[type="radio"]',
  655. }
  656. };
  657. })( jQuery, window , document );