Project

General

Profile

1
/*!
2
 * Bootstrap without jQuery v0.5.0 for Bootstrap 3
3
 * By Daniel Davis under MIT License
4
 * https://github.com/tagawa/bootstrap-without-jquery
5
 */
6

    
7
(function() {
8
    'use strict';
9
    
10
    /*
11
     * Utility functions
12
     */
13
     
14
    // transitionend - source: https://stackoverflow.com/questions/5023514/how-do-i-normalize-css3-transition-functions-across-browsers#answer-9090128
15
    function transitionEndEventName() {
16
        var i,
17
            el = document.createElement('div'),
18
            transitions = {
19
                'transition':'transitionend',
20
                'OTransition':'otransitionend',  // oTransitionEnd in very old Opera
21
                'MozTransition':'transitionend',
22
                'WebkitTransition':'webkitTransitionEnd'
23
            };
24

    
25
        for (i in transitions) {
26
            if (transitions.hasOwnProperty(i) && el.style[i] !== undefined) {
27
                return transitions[i];
28
            }
29
        }
30

    
31
        return false;
32
    }
33
    var transitionend = transitionEndEventName();
34
    
35
    // Get an event's target element and the element specified by the "data-target" attribute
36
    function getTargets(event) {
37
        var targets = {};
38
        event = event || window.event;
39
        targets.evTarget = event.currentTarget || event.srcElement;
40
        var dataTarget = targets.evTarget.getAttribute('data-target');
41
        targets.dataTarget = (dataTarget) ? document.querySelector(dataTarget) : false;
42
        return targets;
43
    }
44
    
45
    // Get the potential max height of an element
46
    function getMaxHeight(element) {
47
        // Source: http://n12v.com/css-transition-to-from-auto/
48
        var prevHeight = element.style.height;
49
        element.style.height = 'auto';
50
        var maxHeight = getComputedStyle(element).height;
51
        element.style.height = prevHeight;
52
        element.offsetHeight; // force repaint
53
        return maxHeight;
54
    }
55
    
56
    // Fire a specified event
57
    // Source: http://youmightnotneedjquery.com/
58
    function fireTrigger(element, eventType) {
59
        if (document.createEvent) {
60
            var event = document.createEvent('HTMLEvents');
61
            event.initEvent(eventType, true, false);
62
            element.dispatchEvent(event);
63
        } else {
64
            element.fireEvent('on' + eventType);
65
        }
66
    }
67

    
68
    
69
    /*
70
     * Collapse action
71
     * 1. Get list of all elements that are collapse triggers
72
     * 2. Add click event listener to these elements
73
     * 3. When clicked, change target element's class name from "collapse" to "collapsing"
74
     * 4. When action (collapse) is complete, change target element's class name from "collapsing" to "collapse in"
75
     * 5. Do the reverse, i.e. "collapse in" -> "collapsing" -> "collapse"
76
     */
77
     
78
    // Show a target element
79
    function show(element, trigger) {
80
        element.classList.remove('collapse');
81
        element.classList.add('collapsing');
82
        trigger.classList.remove('collapsed');
83
        trigger.setAttribute('aria-expanded', true);
84
        
85
        // Set element's height to its maximum height
86
        element.style.height = getMaxHeight(element);
87
        
88
        // Call the complete() function after the transition has finished
89
        if (transitionend) {
90
            element.addEventListener(transitionend, function() {
91
                complete(element);
92
            }, false);
93
        } else {
94
            // For browsers that don't support transitions (e.g. IE9 and lower);
95
            complete(element);
96
        }
97
    }
98
    
99
    // Hide a target element
100
    function hide(element, trigger) {
101
        element.classList.remove('collapse');
102
        element.classList.remove('in');
103
        element.classList.add('collapsing');
104
        trigger.classList.add('collapsed');
105
        trigger.setAttribute('aria-expanded', false);
106
        
107
        // Reset element's height
108
        element.style.height = getComputedStyle(element).height;
109
        element.offsetHeight; // force repaint
110
        element.style.height = '0px';
111
    }
112
    
113
    // Change classes once transition is complete
114
    function complete(element) {
115
        element.classList.remove('collapsing');
116
        element.classList.add('collapse');
117
        element.setAttribute('aria-expanded', false);
118
        
119
        // Check whether the element is unhidden
120
        if (element.style.height !== '0px') {
121
            element.classList.add('in');
122
            element.style.height = 'auto';
123
        }
124
    }
125

    
126
    // Start the collapse action on the chosen element
127
    function doCollapse(event) {
128
        event.preventDefault();
129
        var targets = getTargets(event);
130
        var dataTarget = targets.dataTarget;
131
        
132
        // Add the "in" class name when elements are unhidden
133
        if (dataTarget.classList.contains('in')) {
134
            hide(dataTarget, targets.evTarget);
135
        } else {
136
            show(dataTarget, targets.evTarget);
137
        }
138
        return false;
139
    }
140
    
141
    // Get all elements that are collapse triggers and add click event listeners
142
    var collapsibleList = document.querySelectorAll('[data-toggle=collapse]');
143
    for (var i = 0, leni = collapsibleList.length; i < leni; i++) {
144
        collapsibleList[i].onclick = doCollapse;
145
    }
146
    
147
    
148
    /*
149
     * Alert dismiss action
150
     * 1. Get list of all elements that are alert dismiss buttons
151
     * 2. Add click event listener to these elements
152
     * 3. When clicked, find the target or parent element with class name "alert"
153
     * 4. Remove that element from the DOM
154
     */
155
     
156
    // Start the collapse action on the chosen element
157
    function doDismiss(event) {
158
        event.preventDefault();
159
        // Get target element from data-target attribute
160
        var targets = getTargets(event);
161
        var target = targets.dataTarget;
162
        
163
        if (!target) {
164
            // If data-target not specified, get parent or grandparent node with class="alert"
165
            var parent = targets.evTarget.parentNode;
166
            if (parent.classList.contains('alert')) {
167
                target = parent;
168
            } else if (parent.parentNode.classList.contains('alert')) {
169
                target = parent.parentNode;
170
            }
171
        }
172
        
173
        fireTrigger(target, 'close.bs.alert');
174
        target.classList.remove('in');
175
        
176
        function removeElement() {
177
            // Remove alert from DOM
178
            try {
179
                target.parentNode.removeChild(target);
180
                fireTrigger(target, 'closed.bs.alert');
181
            } catch(e) {
182
                window.console.error('Unable to remove alert');
183
            }
184
        }
185
        
186
        // Call the complete() function after the transition has finished
187
        if (transitionend && target.classList.contains('fade')) {
188
            target.addEventListener(transitionend, function() {
189
                removeElement();
190
            }, false);
191
        } else {
192
            // For browsers that don't support transitions (e.g. IE9 and lower);
193
            removeElement();
194
        }
195

    
196
        return false;
197
    }
198
    
199
     // Get all alert dismiss buttons and add click event listeners
200
    var dismissList = document.querySelectorAll('[data-dismiss=alert]');
201
    for (var j = 0, lenj = dismissList.length; j < lenj; j++) {
202
        dismissList[j].onclick = doDismiss;
203
    }
204
})();
(3-3/9)