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.

527 lines
15 KiB

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