Reusable Accessible Mapping Platform

API Docs for: 5.3.1
Show:

File: src/js/RAMP/Utils/checkbox.js

  1. /* global define */
  2.  
  3. /**
  4. * @module Utils
  5. */
  6.  
  7. /**
  8. * Wraps the specified checkbox input nodes to provide an alternative rendering of checkbox without compromising
  9. * its functionality. Handles synchronization of the checkbox's state with its new rendering.
  10. * Also adds highlight/unhighlight on focus/unfocus, update label when checked/unchecked
  11. *
  12. * ####Imports RAMP Modules:
  13. * {{#crossLink "Util"}}{{/crossLink}}
  14. *
  15. * @class Checkbox
  16. * @constructor
  17. * @uses dojo/Evented
  18. * @uses dojo/_base/declare
  19. * @uses dojo/lang
  20. *
  21. * @param {jObject} node a jQuery object representing the input checkbox node to be wrapped
  22. * @param {Object} [options] Additional options
  23. * @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,
  24. * `nodeIdAttr` is used directly, failing that, regular `id` is used.
  25. * @param {Object} [options.cssClass] `active`, `focus`, and `check` CSS class to be applied to the Checkbox correspondingly.
  26. * @param {Object} [options.cssClass.active] CSS class to be set when the Checkbox is `active`.
  27. * @param {Object} [options.cssClass.focus] CSS class to be set when the Checkbox is `focused`.
  28. * @param {Object} [options.cssClass.check] CSS class to be set when the Checkbox is `checked`.
  29. * @param {Object} [options.label] `check` and `uncheck` label texts to be applied to the Checkbox labels.
  30. * @param {Object} [options.label.check] A text to be set as a label when the Checkbox is `checked`
  31. * @param {Object} [options.label.uncheck] A text to be set as a label when the Checkbox is `unchecked`
  32. * @param {Function} [options.onChnage] A function to be called when the state of the Checkbox changes.
  33. *
  34. * @return {Checkbox} A control objects allowing to toggle checkbox.
  35. */
  36.  
  37. define(["dojo/Evented", "dojo/_base/declare", "dojo/_base/lang", "utils/util"],
  38. function (Evented, declare, lang, Util) {
  39. "use strict";
  40.  
  41. var Checkbox;
  42.  
  43. Checkbox = declare([Evented], {
  44. constructor: function (node, options) {
  45. // declare individual properties inside the constructor: http://dojotoolkit.org/reference-guide/1.9/dojo/_base/declare.html#id6
  46. lang.mixin(this,
  47. {
  48. /**
  49. * Node of the input checkbox originally supplied to the Checkbox.
  50. *
  51. * @property node
  52. * @type JObject
  53. * @default null
  54. */
  55. node: null,
  56.  
  57. /**
  58. * Node of the input checkbox label.
  59. *
  60. * @property labelNode
  61. * @type JObject
  62. * @default null
  63. * @private
  64. */
  65. labelNode: null,
  66.  
  67. /**
  68. * Name of the "data-*" attribute set on the checkbox node to be treated as the checkbox id.
  69. *
  70. * @property nodeIdAttr
  71. * @type String
  72. * @default "id"
  73. */
  74. nodeIdAttr: "id",
  75.  
  76. /**
  77. * `active`, `focus`, and `check` CSS class to be applied to the Checkbox correspondingly.
  78. *
  79. * @property cssClass
  80. * @type {Object}
  81. * @default
  82. * @example
  83. * cssClass: {
  84. * active: "active",
  85. * focus: "focused",
  86. * check: "checked"
  87. * }
  88. */
  89. cssClass: {
  90. active: "active",
  91. focus: "focused",
  92. check: "checked"
  93. },
  94.  
  95. /**
  96. * `check` and `uncheck` label texts to be applied to the Checkbox labels.
  97. *
  98. * @property label
  99. * @type {Object}
  100. * @default
  101. * @example
  102. * label: {
  103. * check: "check",
  104. * uncheck: "unchecked"
  105. * }
  106. */
  107. label: {
  108. check: "checked",
  109. uncheck: "unchecked"
  110. },
  111.  
  112. /**
  113. * A function to be called when the state of the Checkbox changes.
  114. *
  115. * @property onChnage
  116. * @type Function
  117. * @default
  118. * @example function () { }
  119. */
  120. onChange: function () { },
  121.  
  122. /**
  123. * State of the Checkbox: true | false or INVALID
  124. *
  125. * @property state
  126. * @type Boolean | String
  127. * @default null
  128. */
  129. state: null,
  130.  
  131. /**
  132. * Id of the Checkbox as specified by `nodeIdAttr`.
  133. *
  134. * @property id
  135. * @type String
  136. * @default null
  137. */
  138. id: null
  139. },
  140. options,
  141. {
  142. node: node
  143. }
  144. );
  145.  
  146. this._initListeners();
  147.  
  148. this.id = this.node.data(this.nodeIdAttr) || this.node.attr(this.nodeIdAttr) || this.node.id;
  149. this.labelNode = this.node.findInputLabel();
  150.  
  151. this._toggleLabel();
  152. },
  153.  
  154. _initListeners: function () {
  155. var that = this;
  156.  
  157. this.node
  158. .on("change", function () {
  159. that._toggleLabel();
  160.  
  161. that._emit(Checkbox.agency.USER);
  162. })
  163. .on("focus", function () {
  164. that.node.findInputLabel().addClass(that.cssClass.focus);
  165. })
  166. .on("focusout", function () {
  167. that.node.findInputLabel().removeClass(that.cssClass.focus);
  168. });
  169. },
  170.  
  171. /*
  172. * Adds the "checked", "focused" or "active" CSS class to the label so it displays visually matches the changed state.
  173. * Updates the title attribute and text inside an invisible span housed inside the label.
  174. *
  175. * @method _toggleLabel
  176. * @private
  177. */
  178. _toggleLabel: function () {
  179. var newText;
  180.  
  181. this.state = this.node.is(':checked');
  182.  
  183. if (this.state) {
  184. newText = String.format(this.label.check,
  185. this.labelNode.data("label-name"));
  186.  
  187. this.labelNode
  188. .addClass(this.cssClass.check)
  189. .prop('title', newText)
  190. .find("> span").text(newText);
  191. } else {
  192. newText = String.format(this.label.uncheck,
  193. this.labelNode.data("label-name"));
  194.  
  195. this.labelNode
  196. .removeClass(this.cssClass.check)
  197. .prop('title', newText)
  198. .find("> span").text(newText);
  199. }
  200.  
  201. this.onChange.call(this);
  202. },
  203.  
  204. /**
  205. * Emits a `TOGGLE` event when the checkbox's state is changed.
  206. *
  207. * @method _emit
  208. * @private
  209. * @param {String} agency Specified the agency that toggled the Checkbox.
  210. *
  211. */
  212. _emit: function (agency) {
  213. //console.log("Checkbox ->", this.id, "set by", agency, "to", this.state);
  214.  
  215. this.emit(Checkbox.event.TOGGLE, {
  216. agency: agency,
  217. checkbox: this
  218. });
  219. },
  220.  
  221. /**
  222. * Toggle the state of Checkbox.
  223. *
  224. * @method setState
  225. * @param {Boolean} state Specifies the state of the checkbox: true, false
  226. * @return {Checkbox} Control object for chaining
  227. * @chainable
  228. */
  229. setState: function (state) {
  230. this.validate();
  231.  
  232. if (this.state !== Checkbox.state.INVALID) {
  233.  
  234. // change state only if it's different from the current one
  235. if (this.state !== state) {
  236. this.node.prop('checked', state);
  237. this._toggleLabel();
  238.  
  239. this._emit(Checkbox.agency.CODE);
  240. }
  241. }
  242.  
  243. return this;
  244. },
  245.  
  246. /**
  247. * Validates that the checkbox node is in fact in dom. If not, set checkbox's state to "checkbox-invalid" to prevent any interactions.
  248. *
  249. * @method validate
  250. * @return {Checkbox} Control object for chaining
  251. * @chainable
  252. */
  253. validate: function () {
  254. if (!this.node || !Util.containsInDom(this.node[0])) {
  255. this.state = Checkbox.state.INVALID;
  256. } else if (this.state === Checkbox.state.INVALID) {
  257. this.reset();
  258. }
  259. return this;
  260. },
  261.  
  262. reset: function () {
  263. // remove previous listeners
  264. this.node
  265. .off("change focus focusout")
  266. .removeClass("tooltipstered")
  267. ;
  268. this._initListeners();
  269. this._toggleLabel();
  270. }
  271. });
  272.  
  273. lang.mixin(Checkbox,
  274. {
  275. state: {
  276. INVALID: "checkbox-invalid"
  277. },
  278.  
  279. /**
  280. * An object specifying possible agencies that can affect the Checkbox.
  281. *
  282. * @property agency
  283. * @type Object
  284. * @private
  285. * @default
  286. * @example
  287. * agency: {
  288. * USER: "USER",
  289. * CODE: "CODE"
  290. * }
  291. */
  292. agency: {
  293. USER: "USER",
  294. CODE: "CODE"
  295. },
  296.  
  297. /**
  298. * Event names published by the Checkbox
  299. *
  300. * @private
  301. * @property event
  302. * @type Object
  303. * @default null
  304. * @example
  305. * {
  306. * TOGGLE: "checkbox/toggle"
  307. * }
  308. */
  309. event: {
  310. /**
  311. * Published whenever a Checkbox get toggled.
  312. *
  313. * @event TOGGLE
  314. * @param event {Object}
  315. * @param event.checkbox {Checkbox} Checkbox object that has been toggled
  316. * @param event.agency {String} Agency that toggled the Checkbox
  317. */
  318. TOGGLE: "checkbox/toggle"
  319. }
  320. }
  321. );
  322.  
  323. return Checkbox;
  324. });