Reusable Accessible Mapping Platform

API Docs for: 3.0.0
Show:

File: src\js\RAMP\Utils\checkboxGroup.js

  1. /* global define, console, $ */
  2.  
  3. /**
  4. * @module Utils
  5. */
  6.  
  7. /**
  8. * Creates a Checkbox group bound from the supplied JArray of input nodes. Optionally, the group is bound to the supplied master input node
  9. * which acts as a global toggle for the group.
  10. *
  11. *
  12. * @class CheckboxGroup
  13. * @constructor
  14. * @uses dojo/Evented
  15. * @uses dojo/_base/declare
  16. * @uses dojo/_base/lang
  17. * @uses dojo/_base/array
  18. * @uses Checkbox
  19. *
  20. * @param {JArray} nodes a jQuery object representing the checkboxes to be grouped
  21. * @param {Object} [options] Additional options
  22. * @param {String} [options.nodeIdAttr] Name of the "data-*" attribute set on the checkbox node to be treated as the checkbox id. If no appropriate "data-*" attribute found,
  23. * `nodeIdAttr` is used directly, failing that, regular `id` is used.
  24. * @param {Object} [options.cssClass] `active`, `focus`, and `check` CSS class to be applied to the Checkbox correspondingly.
  25. * @param {Object} [options.cssClass.active] CSS class to be set when the Checkbox is `active`.
  26. * @param {Object} [options.cssClass.focus] CSS class to be set when the Checkbox is `focused`.
  27. * @param {Object} [options.cssClass.check] CSS class to be set when the Checkbox is `checked`.
  28. * @param {Object} [options.label] `check` and `uncheck` label texts to be applied to the Checkbox labels.
  29. * @param {Object} [options.label.check] A text to be set as a label when the Checkbox is `checked`
  30. * @param {Object} [options.label.uncheck] A text to be set as a label when the Checkbox is `unchecked`
  31. * @param {Function} [options.onChnage] A function to be called when the state of the Checkbox changes.
  32. * @param {Object} [options.master] Additional options applied to the master Checkbox.
  33. * @param {Object} [options.master.node] An `input` node to serve as the master Checkbox for the group.
  34. * @param {Object} [options.master.cssClass] `active`, `focus`, and `check` CSS class to be applied to the master Checkbox correspondingly.
  35. * @param {Object} [options.master.cssClass.active] CSS class to be set when the Checkbox is `active`.
  36. * @param {Object} [options.master.cssClass.focus] CSS class to be set when the master Checkbox is `focused`.
  37. * @param {Object} [options.master.cssClass.check] CSS class to be set when the master Checkbox is `checked`.
  38. * @param {Object} [options.master.label] `check` and `uncheck` label texts to be applied to the master Checkbox labels.
  39. * @param {Object} [options.master.label.check] A text to be set as a label when the master Checkbox is `checked`
  40. * @param {Object} [options.master.label.uncheck] A text to be set as a label when the master Checkbox is `unchecked`
  41. * @param {Function} [options.master.onChnage] A function to be called when the state of the master Checkbox changes.
  42. *
  43. * @return {CheckboxGroup} A control objects allowing to toggle individual checkboxes in a group as well as the group as a whole.
  44. */
  45.  
  46. define(["dojo/Evented", "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array",
  47.  
  48. "utils/checkbox"],
  49. function (Evented, declare, lang, dojoArray,
  50. Checkbox) {
  51. "use strict";
  52.  
  53. return declare([Evented], {
  54. constructor: function (nodes, options) {
  55. var that = this,
  56. checkbox,
  57. checkboxOptions;
  58.  
  59. // declare individual properties inside the constructor: http://dojotoolkit.org/reference-guide/1.9/dojo/_base/declare.html#id6
  60. lang.mixin(this,
  61. {
  62. /**
  63. * Nodes of the checkbox nodes originally supplied to the CheckboxGroup.
  64. *
  65. * @property nodes
  66. * @type JArray
  67. * @default []
  68. */
  69. nodes: [],
  70.  
  71. /**
  72. * Name of the "data-*" attribute set on the checkbox node to be treated as the checkbox id.
  73. *
  74. * @property nodeIdAttr
  75. * @type String
  76. * @default "id"
  77. */
  78. nodeIdAttr: "id",
  79.  
  80. /**
  81. * An array of the Checkbox object belonging to the body of the group.
  82. *
  83. * @property nodes
  84. * @type Array
  85. * @default []
  86. */
  87. checkboxes: [],
  88.  
  89. /**
  90. * `active`, `focus`, and `check` CSS class to be applied to the Checkbox correspondingly.
  91. *
  92. * @property cssClass
  93. * @type {Object}
  94. * @default
  95. * @example
  96. * cssClass: {
  97. * active: "active",
  98. * focus: "focused",
  99. * check: "checked"
  100. * }
  101. */
  102. cssClass: {
  103. active: "active",
  104. focus: "focused",
  105. check: "checked"
  106. },
  107.  
  108. /**
  109. * `check` and `uncheck` label texts to be applied to the Checkbox labels.
  110. *
  111. * @property label
  112. * @type {Object}
  113. * @default
  114. * @example
  115. * label: {
  116. * check: "check",
  117. * uncheck: "unchecked"
  118. * }
  119. */
  120. label: {
  121. check: "checked",
  122. uncheck: "unchecked"
  123. },
  124.  
  125. /**
  126. * A function to be called when the state of the Checkbox changes.
  127. *
  128. * @property onChnage
  129. * @type Function
  130. * @default
  131. * @example function () { }
  132. */
  133. onChange: function () { },
  134.  
  135. /**
  136. * Options for the master Checkbox.
  137. *
  138. * @property master
  139. * @type Object
  140. * @default
  141. * @example
  142. * master: {
  143. * node: null,
  144. * checkbox: null,
  145. * nodeIdAttr: null,
  146. *
  147. * cssClass: {
  148. * active: "active",
  149. * focus: "focused",
  150. * check: "checked"
  151. * },
  152. *
  153. * label: {
  154. * check: "checked",
  155. * uncheck: "unchecked"
  156. * },
  157. *
  158. * onChange: function () { }
  159. * }
  160. *
  161. */
  162. master: {
  163. node: null,
  164. checkbox: null,
  165. nodeIdAttr: null,
  166.  
  167. cssClass: {
  168. active: "active",
  169. focus: "focused",
  170. check: "checked"
  171. },
  172. label: {
  173. check: "checked",
  174. uncheck: "unchecked"
  175. },
  176.  
  177. onChange: function () { }
  178. },
  179.  
  180. /**
  181. * Event names published by the Checkbox
  182. *
  183. * @private
  184. * @property event
  185. * @type Object
  186. * @default null
  187. * @example
  188. * {
  189. * MEMBER_TOGGLE: "checkbox/toggled",
  190. * MASTER_TOGGLE: "checkbox/toggled"
  191. * }
  192. */
  193. event: {
  194. /**
  195. * This event is not published by CheckboxGroup. __Ignore this.__
  196. *
  197. * @event TOGGLE
  198. * @private
  199. */
  200.  
  201. /**
  202. * Published whenever a Checkbox get toggled.
  203. *
  204. * @event MEMBER_TOGGLE
  205. * @param event {Object}
  206. * @param event.checkbox {Checkbox} Checkbox object that has been toggled
  207. * @param event.agency {String} Agency that toggled the Checkbox
  208. */
  209. MEMBER_TOGGLE: "checkbox/member-toggle",
  210.  
  211. /**
  212. * Published whenever the master Checkbox get toggled.
  213. *
  214. * @event MASTER_TOGGLE
  215. * @param event {Object}
  216. * @param event.checkbox {Checkbox} master Checkbox object that has been toggled
  217. * @param event.agency {String} Agency that toggled the Checkbox
  218. */
  219. MASTER_TOGGLE: "checkbox/master-toggle"
  220. }
  221. },
  222. options,
  223. {
  224. nodes: nodes
  225. }
  226. );
  227.  
  228. checkboxOptions = {
  229. nodeIdAttr: this.nodeIdAttr,
  230. cssClass: this.cssClass,
  231. label: this.label,
  232. onChange: this.onChange
  233. };
  234.  
  235. // Create individual Checkboxes
  236. this.nodes.each(function (index, node) {
  237. node = $(node);
  238. checkbox = new Checkbox(node, checkboxOptions);
  239. that.checkboxes.push(checkbox);
  240.  
  241. checkbox.on(checkbox.event.TOGGLE, function (evt) {
  242. // re-emit individual checkbox's toggle event as groups;
  243. //console.log("CheckboxGroup ->", evt.checkbox.id, "set by", evt.agency, "to", evt.checkbox.state);
  244.  
  245. that.emit(that.event.MEMBER_TOGGLE, evt);
  246.  
  247. if (evt.agency === evt.checkbox.agency.USER) {
  248. that._checkMaster();
  249. }
  250. });
  251. });
  252.  
  253. if (this.master.node) {
  254. this.master.checkbox = new Checkbox(
  255. this.master.node,
  256. lang.mixin(checkboxOptions, this.master)
  257. );
  258.  
  259. this.master.checkbox.on(checkbox.event.TOGGLE, function (evt) {
  260. // re-emit individual checkbox's toggle event as groups;
  261. console.log("CheckboxGroup Master ->", evt.checkbox.id, "set by", evt.agency, "to", evt.checkbox.state);
  262.  
  263. that.emit(that.event.MASTER_TOGGLE, evt);
  264.  
  265. if (evt.agency === evt.checkbox.agency.USER) {
  266. that.setState(evt.checkbox.state);
  267. }
  268. });
  269. } else {
  270. this.master = null;
  271. }
  272. },
  273.  
  274. /**
  275. * Synchronizes the state of the master Checkbox with the state of the group.
  276. * All group members checked -> master checked
  277. * Any of the group members unchecked -> master unchecked
  278. *
  279. * @method _checkMaster
  280. * @private
  281. */
  282. _checkMaster: function () {
  283. var allChecked = dojoArray.every(this.checkboxes, function (checkbox) {
  284. //return checkbox.isChecked();
  285. return checkbox.state;
  286. });
  287.  
  288. if (this.master) {
  289. this.master.checkbox.setState(allChecked);
  290. }
  291. },
  292.  
  293. /**
  294. * Toggles the state of the specified Checkbox. If checkboxId is not supplied, toggles the whole group.
  295. *
  296. * @method setState
  297. * @param {Boolean} state Specifies the state of the checkbox: true, false
  298. * @param {String} [checkboxId] Specifies the checkbox to toggle.
  299. * @return CheckboxGroup
  300. * @chainable
  301. */
  302. setState: function (state, checkboxId) {
  303. var checkbox,
  304. masterCheckboxId = this.master.checkbox ? this.master.checkbox.id : undefined;
  305.  
  306. if (!checkboxId || masterCheckboxId === checkboxId) {
  307. this.master.checkbox.setState(state);
  308.  
  309. this.checkboxes.forEach(function (checkbox) {
  310. checkbox.setState(state);
  311. });
  312. } else {
  313. for (var i = 0; i < this.checkboxes.length; i++) {
  314. checkbox = this.checkboxes[i];
  315. if (checkbox.id === checkboxId) {
  316. break;
  317. }
  318. }
  319.  
  320. checkbox.setState(state);
  321.  
  322. this._checkMaster();
  323. }
  324.  
  325. return this;
  326. },
  327.  
  328. /**
  329. * Toggle all the checkboxes based on the return value of the given function.
  330. *
  331. * @param {Function} fcn a function that takes a checkbox as an argument and returns
  332. * true if the given checkbox should be toggled on, false if it should be toggled off
  333. * @method setEachState
  334. * @chainable
  335. */
  336. setEachState: function (fcn) {
  337. this.checkboxes.forEach(function (checkbox) {
  338. checkbox.setState(fcn(checkbox));
  339. });
  340. this._checkMaster();
  341. return this;
  342. }
  343. });
  344. });