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
|
})();
|