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.

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