radio.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Fuel UX Radio
  3. * https://github.com/ExactTarget/fuelux
  4. *
  5. * Copyright (c) 2014 ExactTarget
  6. * Licensed under the BSD New license.
  7. */
  8. // -- BEGIN UMD WRAPPER PREFACE --
  9. // For more information on UMD visit:
  10. // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
  11. (function (factory) {
  12. if (typeof define === 'function' && define.amd) {
  13. // if AMD loader is available, register as an anonymous module.
  14. define(['jquery'], factory);
  15. } else {
  16. // OR use browser globals if AMD is not present
  17. factory(jQuery);
  18. }
  19. }(function ($) {
  20. // -- END UMD WRAPPER PREFACE --
  21. // -- BEGIN MODULE CODE HERE --
  22. var old = $.fn.radio;
  23. // RADIO CONSTRUCTOR AND PROTOTYPE
  24. var Radio = function (element, options) {
  25. this.options = $.extend({}, $.fn.radio.defaults, options);
  26. // cache elements
  27. this.$radio = $(element).is('input[type="radio"]') ? $(element) : $(element).find('input[type="radio"]:first');
  28. this.$label = this.$radio.parent();
  29. this.groupName = this.$radio.attr('name');
  30. this.$blockWrapper = this.$label.parent('.radio'); // only used if block radio control, otherwise radio is inline
  31. this.isBlockWrapped = true; // initialized as a block radio control
  32. this.$toggleContainer = null;
  33. if (this.$blockWrapper.length === 0) {
  34. this.isBlockWrapped = false;
  35. }
  36. var toggleSelector = this.$radio.attr('data-toggle');
  37. if (toggleSelector) {
  38. this.$toggleContainer = $(toggleSelector);
  39. }
  40. // set default state
  41. this.setState(this.$radio);
  42. // handle events
  43. this.$radio.on('change.fu.radio', $.proxy(this.itemchecked, this));
  44. };
  45. Radio.prototype = {
  46. constructor: Radio,
  47. destroy: function () {
  48. // remove any external bindings
  49. // [none]
  50. // empty elements to return to original markup
  51. // [none]
  52. // return string of markup
  53. if (this.isBlockWrapped) {
  54. this.$blockWrapper.remove();
  55. return this.$blockWrapper[0].outerHTML;
  56. } else {
  57. this.$label.remove();
  58. return this.$label[0].outerHTML;
  59. }
  60. },
  61. setState: function ($radio) {
  62. $radio = $radio || this.$radio;
  63. var checked = $radio.is(':checked');
  64. var disabled = !!$radio.prop('disabled');
  65. this.$label.removeClass('checked');
  66. if (this.isBlockWrapped) {
  67. this.$blockWrapper.removeClass('checked disabled');
  68. }
  69. // set state of radio
  70. if (checked === true) {
  71. this.$label.addClass('checked');
  72. if (this.isBlockWrapped) {
  73. this.$blockWrapper.addClass('checked');
  74. }
  75. }
  76. if (disabled === true) {
  77. this.$label.addClass('disabled');
  78. if (this.isBlockWrapped) {
  79. this.$blockWrapper.addClass('disabled');
  80. }
  81. }
  82. //toggle container
  83. this.toggleContainer();
  84. },
  85. resetGroup: function () {
  86. var group = $('input[name="' + this.groupName + '"]');
  87. group.each(function () {
  88. var lbl = $(this).parent('label');
  89. lbl.removeClass('checked');
  90. lbl.parent('.radio').removeClass('checked');
  91. });
  92. },
  93. enable: function () {
  94. this.$radio.attr('disabled', false);
  95. this.$label.removeClass('disabled');
  96. if (this.isBlockWrapped) {
  97. this.$blockWrapper.removeClass('disabled');
  98. }
  99. },
  100. disable: function () {
  101. this.$radio.attr('disabled', true);
  102. this.$label.addClass('disabled');
  103. if (this.isBlockWrapped) {
  104. this.$blockWrapper.addClass('disabled');
  105. }
  106. },
  107. itemchecked: function (e) {
  108. var radio = $(e.target);
  109. this.resetGroup();
  110. this.setState(radio);
  111. },
  112. check: function () {
  113. this.resetGroup();
  114. this.$radio.prop('checked', true);
  115. this.$radio.attr('checked', 'checked');
  116. this.setState(this.$radio);
  117. },
  118. toggleContainer: function () {
  119. var group;
  120. if (this.$toggleContainer) {
  121. // show corresponding container for currently selected radio
  122. if (this.isChecked()) {
  123. // hide containers for each item in group
  124. group = $('input[name="' + this.groupName + '"]');
  125. group.each(function () {
  126. var selector = $(this).attr('data-toggle');
  127. $(selector).addClass('hidden');
  128. $(selector).attr('aria-hidden', 'true');
  129. });
  130. this.$toggleContainer.removeClass('hide hidden');
  131. this.$toggleContainer.attr('aria-hidden', 'false');
  132. } else {
  133. this.$toggleContainer.addClass('hidden');
  134. this.$toggleContainer.attr('aria-hidden', 'true');
  135. }
  136. }
  137. },
  138. uncheck: function () {
  139. this.$radio.prop('checked', false);
  140. this.$radio.removeAttr('checked');
  141. this.setState(this.$radio);
  142. },
  143. isChecked: function () {
  144. return this.$radio.is(':checked');
  145. }
  146. };
  147. // RADIO PLUGIN DEFINITION
  148. $.fn.radio = function (option) {
  149. var args = Array.prototype.slice.call(arguments, 1);
  150. var methodReturn;
  151. var $set = this.each(function () {
  152. var $this = $(this);
  153. var data = $this.data('fu.radio');
  154. var options = typeof option === 'object' && option;
  155. if (!data) {
  156. $this.data('fu.radio', (data = new Radio(this, options)));
  157. }
  158. if (typeof option === 'string') {
  159. methodReturn = data[option].apply(data, args);
  160. }
  161. });
  162. return (methodReturn === undefined) ? $set : methodReturn;
  163. };
  164. $.fn.radio.defaults = {};
  165. $.fn.radio.Constructor = Radio;
  166. $.fn.radio.noConflict = function () {
  167. $.fn.radio = old;
  168. return this;
  169. };
  170. // DATA-API
  171. $(document).on('mouseover.fu.checkbox.data-api', '[data-initialize=radio]', function (e) {
  172. var $control = $(e.target).closest('.radio').find('[type=radio]');
  173. if (!$control.data('fu.radio')) {
  174. $control.radio($control.data());
  175. }
  176. });
  177. // Must be domReady for AMD compatibility
  178. $(function () {
  179. $('[data-initialize=radio] [type=radio]').each(function () {
  180. var $this = $(this);
  181. if ($this.data('fu.radio')) return;
  182. $this.radio($this.data());
  183. });
  184. });
  185. // -- BEGIN UMD WRAPPER AFTERWORD --
  186. }));
  187. // -- END UMD WRAPPER AFTERWORD --