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.

728 lines
22 KiB

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