checkboxradio.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*!
  2. * jQuery UI Checkboxradio 1.14.1
  3. * https://jqueryui.com
  4. *
  5. * Copyright OpenJS Foundation and other contributors
  6. * Released under the MIT license.
  7. * https://jquery.org/license
  8. */
  9. //>>label: Checkboxradio
  10. //>>group: Widgets
  11. //>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
  12. //>>docs: https://api.jqueryui.com/checkboxradio/
  13. //>>demos: https://jqueryui.com/checkboxradio/
  14. //>>css.structure: ../../themes/base/core.css
  15. //>>css.structure: ../../themes/base/button.css
  16. //>>css.structure: ../../themes/base/checkboxradio.css
  17. //>>css.theme: ../../themes/base/theme.css
  18. ( function( factory ) {
  19. "use strict";
  20. if ( typeof define === "function" && define.amd ) {
  21. // AMD. Register as an anonymous module.
  22. define( [
  23. "jquery",
  24. "../form-reset-mixin",
  25. "../labels",
  26. "../widget"
  27. ], factory );
  28. } else {
  29. // Browser globals
  30. factory( jQuery );
  31. }
  32. } )( function( $ ) {
  33. "use strict";
  34. $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
  35. version: "1.14.1",
  36. options: {
  37. disabled: null,
  38. label: null,
  39. icon: true,
  40. classes: {
  41. "ui-checkboxradio-label": "ui-corner-all",
  42. "ui-checkboxradio-icon": "ui-corner-all"
  43. }
  44. },
  45. _getCreateOptions: function() {
  46. var disabled, labels, labelContents;
  47. var options = this._super() || {};
  48. // We read the type here, because it makes more sense to throw a element type error first,
  49. // rather then the error for lack of a label. Often if its the wrong type, it
  50. // won't have a label (e.g. calling on a div, btn, etc)
  51. this._readType();
  52. labels = this.element.labels();
  53. // If there are multiple labels, use the last one
  54. this.label = $( labels[ labels.length - 1 ] );
  55. if ( !this.label.length ) {
  56. $.error( "No label found for checkboxradio widget" );
  57. }
  58. this.originalLabel = "";
  59. // We need to get the label text but this may also need to make sure it does not contain the
  60. // input itself.
  61. // The label contents could be text, html, or a mix. We wrap all elements
  62. // and read the wrapper's `innerHTML` to get a string representation of
  63. // the label, without the input as part of it.
  64. labelContents = this.label.contents().not( this.element[ 0 ] );
  65. if ( labelContents.length ) {
  66. this.originalLabel += labelContents
  67. .clone()
  68. .wrapAll( "<div></div>" )
  69. .parent()
  70. .html();
  71. }
  72. // Set the label option if we found label text
  73. if ( this.originalLabel ) {
  74. options.label = this.originalLabel;
  75. }
  76. disabled = this.element[ 0 ].disabled;
  77. if ( disabled != null ) {
  78. options.disabled = disabled;
  79. }
  80. return options;
  81. },
  82. _create: function() {
  83. var checked = this.element[ 0 ].checked;
  84. this._bindFormResetHandler();
  85. if ( this.options.disabled == null ) {
  86. this.options.disabled = this.element[ 0 ].disabled;
  87. }
  88. this._setOption( "disabled", this.options.disabled );
  89. this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
  90. this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
  91. if ( this.type === "radio" ) {
  92. this._addClass( this.label, "ui-checkboxradio-radio-label" );
  93. }
  94. if ( this.options.label && this.options.label !== this.originalLabel ) {
  95. this._updateLabel();
  96. } else if ( this.originalLabel ) {
  97. this.options.label = this.originalLabel;
  98. }
  99. this._enhance();
  100. if ( checked ) {
  101. this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
  102. }
  103. this._on( {
  104. change: "_toggleClasses",
  105. focus: function() {
  106. this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
  107. },
  108. blur: function() {
  109. this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
  110. }
  111. } );
  112. },
  113. _readType: function() {
  114. var nodeName = this.element[ 0 ].nodeName.toLowerCase();
  115. this.type = this.element[ 0 ].type;
  116. if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
  117. $.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
  118. " and element.type=" + this.type );
  119. }
  120. },
  121. // Support jQuery Mobile enhanced option
  122. _enhance: function() {
  123. this._updateIcon( this.element[ 0 ].checked );
  124. },
  125. widget: function() {
  126. return this.label;
  127. },
  128. _getRadioGroup: function() {
  129. var group;
  130. var name = this.element[ 0 ].name;
  131. var nameSelector = "input[name='" + CSS.escape( name ) + "']";
  132. if ( !name ) {
  133. return $( [] );
  134. }
  135. if ( this.form.length ) {
  136. group = $( this.form[ 0 ].elements ).filter( nameSelector );
  137. } else {
  138. // Not inside a form, check all inputs that also are not inside a form
  139. group = $( nameSelector ).filter( function() {
  140. return $( $( this ).prop( "form" ) ).length === 0;
  141. } );
  142. }
  143. return group.not( this.element );
  144. },
  145. _toggleClasses: function() {
  146. var checked = this.element[ 0 ].checked;
  147. this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
  148. if ( this.options.icon && this.type === "checkbox" ) {
  149. this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
  150. ._toggleClass( this.icon, null, "ui-icon-blank", !checked );
  151. }
  152. if ( this.type === "radio" ) {
  153. this._getRadioGroup()
  154. .each( function() {
  155. var instance = $( this ).checkboxradio( "instance" );
  156. if ( instance ) {
  157. instance._removeClass( instance.label,
  158. "ui-checkboxradio-checked", "ui-state-active" );
  159. }
  160. } );
  161. }
  162. },
  163. _destroy: function() {
  164. this._unbindFormResetHandler();
  165. if ( this.icon ) {
  166. this.icon.remove();
  167. this.iconSpace.remove();
  168. }
  169. },
  170. _setOption: function( key, value ) {
  171. // We don't allow the value to be set to nothing
  172. if ( key === "label" && !value ) {
  173. return;
  174. }
  175. this._super( key, value );
  176. if ( key === "disabled" ) {
  177. this._toggleClass( this.label, null, "ui-state-disabled", value );
  178. this.element[ 0 ].disabled = value;
  179. // Don't refresh when setting disabled
  180. return;
  181. }
  182. this.refresh();
  183. },
  184. _updateIcon: function( checked ) {
  185. var toAdd = "ui-icon ui-icon-background ";
  186. if ( this.options.icon ) {
  187. if ( !this.icon ) {
  188. this.icon = $( "<span>" );
  189. this.iconSpace = $( "<span> </span>" );
  190. this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
  191. }
  192. if ( this.type === "checkbox" ) {
  193. toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
  194. this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
  195. } else {
  196. toAdd += "ui-icon-blank";
  197. }
  198. this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
  199. if ( !checked ) {
  200. this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
  201. }
  202. this.icon.prependTo( this.label ).after( this.iconSpace );
  203. } else if ( this.icon !== undefined ) {
  204. this.icon.remove();
  205. this.iconSpace.remove();
  206. delete this.icon;
  207. }
  208. },
  209. _updateLabel: function() {
  210. // Remove the contents of the label ( minus the icon, icon space, and input )
  211. var contents = this.label.contents().not( this.element[ 0 ] );
  212. if ( this.icon ) {
  213. contents = contents.not( this.icon[ 0 ] );
  214. }
  215. if ( this.iconSpace ) {
  216. contents = contents.not( this.iconSpace[ 0 ] );
  217. }
  218. contents.remove();
  219. this.label.append( this.options.label );
  220. },
  221. refresh: function() {
  222. var checked = this.element[ 0 ].checked,
  223. isDisabled = this.element[ 0 ].disabled;
  224. this._updateIcon( checked );
  225. this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
  226. if ( this.options.label !== null ) {
  227. this._updateLabel();
  228. }
  229. if ( isDisabled !== this.options.disabled ) {
  230. this._setOptions( { "disabled": isDisabled } );
  231. }
  232. }
  233. } ] );
  234. return $.ui.checkboxradio;
  235. } );