button-native.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /* Native Javascript for Bootstrap 3 | Button
  2. ---------------------------------------------*/
  3. // BUTTON DEFINITION
  4. // ===================
  5. var Button = function( element, option ) {
  6. // initialization element
  7. element = queryElement(element);
  8. // set option
  9. option = option || null;
  10. // constant
  11. var toggled = false, // toggled makes sure to prevent triggering twice the change.bs.button events
  12. // strings
  13. component = 'button',
  14. checked = 'checked',
  15. reset = 'reset',
  16. LABEL = 'LABEL',
  17. INPUT = 'INPUT',
  18. // private methods
  19. setState = function() {
  20. if ( !! option && option !== reset ) {
  21. if ( option === loading ) {
  22. addClass(element,disabled);
  23. element[setAttribute](disabled,disabled);
  24. element[setAttribute](dataOriginalText, element[innerHTML].trim()); // trim the text
  25. }
  26. element[innerHTML] = element[getAttribute]('data-'+option+'-text');
  27. }
  28. },
  29. resetState = function() {
  30. if (element[getAttribute](dataOriginalText)) {
  31. if ( hasClass(element,disabled) || element[getAttribute](disabled) === disabled ) {
  32. removeClass(element,disabled);
  33. element.removeAttribute(disabled);
  34. }
  35. element[innerHTML] = element[getAttribute](dataOriginalText);
  36. }
  37. },
  38. keyHandler = function(e){
  39. var key = e.which || e.keyCode;
  40. key === 32 && e[target] === DOC.activeElement && toggle(e);
  41. },
  42. preventScroll = function(e){
  43. var key = e.which || e.keyCode;
  44. key === 32 && e[preventDefault]();
  45. },
  46. toggle = function(e) {
  47. var label = e[target].tagName === LABEL ? e[target] : e[target][parentNode].tagName === LABEL ? e[target][parentNode] : null; // the .btn label
  48. if ( !label ) return; //react if a label or its immediate child is clicked
  49. var labels = getElementsByClassName(label[parentNode],'btn'), // all the button group buttons
  50. input = label[getElementsByTagName](INPUT)[0];
  51. if ( !input ) return; // return if no input found
  52. // manage the dom manipulation
  53. if ( input.type === 'checkbox' ) { //checkboxes
  54. if ( !input[checked] ) {
  55. addClass(label,active);
  56. input[getAttribute](checked);
  57. input[setAttribute](checked,checked);
  58. input[checked] = true;
  59. } else {
  60. removeClass(label,active);
  61. input[getAttribute](checked);
  62. input.removeAttribute(checked);
  63. input[checked] = false;
  64. }
  65. if (!toggled) { // prevent triggering the event twice
  66. toggled = true;
  67. bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
  68. bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
  69. }
  70. }
  71. if ( input.type === 'radio' && !toggled ) { // radio buttons
  72. // don't trigger if already active (the OR condition is a hack to check if the buttons were selected with key press and NOT mouse click)
  73. if ( !input[checked] || (e.screenX === 0 && e.screenY == 0) ) {
  74. addClass(label,active);
  75. input[setAttribute](checked,checked);
  76. input[checked] = true;
  77. bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
  78. bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
  79. toggled = true;
  80. for (var i = 0, ll = labels[length]; i<ll; i++) {
  81. var otherLabel = labels[i], otherInput = otherLabel[getElementsByTagName](INPUT)[0];
  82. if ( otherLabel !== label && hasClass(otherLabel,active) ) {
  83. removeClass(otherLabel,active);
  84. otherInput.removeAttribute(checked);
  85. otherInput[checked] = false;
  86. bootstrapCustomEvent.call(otherInput, changeEvent, component); // trigger the change
  87. }
  88. }
  89. }
  90. }
  91. setTimeout( function() { toggled = false; }, 50 );
  92. };
  93. // init
  94. if ( hasClass(element,'btn') ) { // when Button text is used we execute it as an instance method
  95. if ( option !== null ) {
  96. if ( option !== reset ) { setState(); }
  97. else { resetState(); }
  98. }
  99. } else { // if ( hasClass(element,'btn-group') ) // we allow the script to work outside btn-group component
  100. if ( !( stringButton in element ) ) { // prevent adding event handlers twice
  101. on( element, clickEvent, toggle );
  102. on( element, keyupEvent, keyHandler ), on( element, keydownEvent, preventScroll );
  103. }
  104. // activate items on load
  105. var labelsToACtivate = getElementsByClassName(element, 'btn'), lbll = labelsToACtivate[length];
  106. for (var i=0; i<lbll; i++) {
  107. !hasClass(labelsToACtivate[i],active) && queryElement('input',labelsToACtivate[i])[getAttribute](checked)
  108. && addClass(labelsToACtivate[i],active);
  109. }
  110. element[stringButton] = this;
  111. }
  112. };
  113. // BUTTON DATA API
  114. // =================
  115. supports[push]( [ stringButton, Button, '['+dataToggle+'="buttons"]' ] );