Project

General

Profile

1
// Native Javascript for Bootstrap 3 | Button
2
// by dnp_theme
3

    
4
(function(factory){
5

    
6
  // CommonJS/RequireJS and "native" compatibility
7
  if(typeof module !== "undefined" && typeof exports == "object") {
8
    // A commonJS/RequireJS environment
9
    if(typeof window != "undefined") {
10
      // Window and document exist, so return the factory's return value.
11
      module.exports = factory();
12
    } else {
13
      // Let the user give the factory a Window and Document.
14
      module.exports = factory;
15
    }
16
  } else {
17
    // Assume a traditional browser.
18
    window.Button = factory();
19
  }
20

    
21
})(function(){
22

    
23
  // BUTTON DEFINITION
24
  // ===================
25
  var Button = function( element, option ) {
26
    this.btn = typeof element === 'object' ? element : document.querySelector(element);
27
    this.option = typeof option === 'string' ? option : null;
28

    
29
    this.init();
30
  };
31

    
32
  // BUTTON METHODS
33
  // ================
34
  Button.prototype = {
35

    
36
    init : function() {
37
      var self = this;
38
      this.actions();
39

    
40
      if ( /btn/.test(this.btn.className) ) {
41
        if ( this.option && this.option !== 'reset' ) {
42

    
43
          this.state = this.btn.getAttribute('data-'+this.option+'-text') || null;
44

    
45
          !this.btn.getAttribute('data-original-text') && this.btn.setAttribute('data-original-text',self.btn.innerHTML.replace(/^\s+|\s+$/g, ''));
46
          this.setState();
47

    
48
        } else if ( this.option === 'reset' ) {
49
          this.reset();
50
        }
51
      }
52

    
53
      if ( /btn-group/.test(this.btn.className) ) {
54
        this.btn.addEventListener('click', this.toggle, false);
55
      }
56
    },
57

    
58
    actions : function() {
59
      var self = this,
60
        changeEvent = (('CustomEvent' in window) && window.dispatchEvent) 
61
          ? new CustomEvent('bs.button.change') : null; // The custom event that will be triggered on demand
62

    
63
      // assign event to a trigger function
64
      function triggerChange(t) { if (changeEvent) { t.dispatchEvent(changeEvent); } }
65

    
66
      this.setState = function() {
67
        if ( this.option === 'loading' ) {
68
          this.addClass(this.btn,'disabled');          
69
          this.btn.setAttribute('disabled','disabled');
70
        }
71
        this.btn.innerHTML = this.state;
72
      },
73

    
74
      this.reset = function() {
75
        if ( /disabled/.test(self.btn.className) || self.btn.getAttribute('disabled') === 'disabled' ) {
76
          this.removeClass(this.btn,'disabled');  
77
          self.btn.removeAttribute('disabled');
78
        }
79
        self.btn.innerHTML = self.btn.getAttribute('data-original-text');
80
      },
81

    
82
      this.toggle = function(e) {
83
        var parent = e.target.parentNode,
84
          label = e.target.tagName === 'LABEL' ? e.target : parent.tagName === 'LABEL' ? parent : null; // the .btn label
85
        
86
        if ( !label ) return; //react if a label or its immediate child is clicked
87
        
88
        var target = this, //e.currentTarget || e.srcElement; // the button group, the target of the handler function
89
          labels = target.querySelectorAll('.btn'), ll = labels.length, i = 0, // all the button group buttons
90
          input = label.getElementsByTagName('INPUT')[0];
91
          
92
        if ( !input ) return; //return if no input found
93

    
94
        //manage the dom manipulation
95
        if ( input.type === 'checkbox' ) { //checkboxes          
96
          if ( !input.checked ) {
97
            self.addClass(label,'active');
98
            input.getAttribute('checked');          
99
            input.setAttribute('checked','checked');
100
            input.checked = true;
101
          } else {
102
            self.removeClass(label,'active');
103
            input.getAttribute('checked');            
104
            input.removeAttribute('checked');
105
            input.checked = false;
106
          }
107
          triggerChange(input); //trigger the change for the input
108
          triggerChange(self.btn); //trigger the change for the btn-group
109
        }
110

    
111
        if ( input.type === 'radio' ) { // radio buttons
112
          if ( !input.checked ) { // don't trigger if already active
113
            self.addClass(label,'active');
114
            input.setAttribute('checked','checked');
115
            input.checked = true;
116
            triggerChange(self.btn);     
117
            triggerChange(input); //trigger the change
118
            
119
            for (i;i<ll;i++) {
120
              var l = labels[i];
121
              if ( l !== label && /active/.test(l.className) )  {
122
                var inp = l.getElementsByTagName('INPUT')[0];
123
                self.removeClass(l,'active');
124
                inp.removeAttribute('checked');
125
                inp.checked = false;
126
                triggerChange(inp); // trigger the change                
127
              }        
128
            }
129
          }                
130
        }
131
      },
132
      this.addClass = function(el,c) { // where modern browsers fail, use classList  
133
        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; el.offsetWidth; }
134
      },
135
      this.removeClass = function(el,c) {
136
        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); el.offsetWidth; }
137
      }
138
    }
139
  }
140

    
141
  // BUTTON DATA API
142
  // =================
143
  var Buttons = document.querySelectorAll('[data-toggle=button]'), i = 0, btl = Buttons.length;
144
  for (i;i<btl;i++) {
145
    new Button(Buttons[i]);
146
  }
147
  
148
  var ButtonGroups = document.querySelectorAll('[data-toggle=buttons]'), j = 0, bgl = ButtonGroups.length;
149
  for (j;j<bgl;j++) {
150
    new Button(ButtonGroups[j]);
151
  }
152

    
153
  return Button;
154

    
155
});
(3-3/17)