-
Notifications
You must be signed in to change notification settings - Fork 24
/
floatingLabel.js
236 lines (203 loc) · 7.32 KB
/
floatingLabel.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
'use strict'
module.exports = {
config: {
floatingClassName: 'floating',
delegateEvents: false
},
init: function initializeFloatingLabel (opt) {
this._eventsDelegated = false
if (opt instanceof Object) {
for (var option in opt) {
if (window.Object.hasOwnProperty.call(opt, option) && window.Object.hasOwnProperty.call(this.config, option)) {
this.config[option] = opt[option]
}
}
}
// Once the DOM is loaded, evaluate the inputs on the page
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', this.evaluateInputs.bind(this), false)
} else {
document.onreadystatechange = this.evaluateInputs.bind(this)
}
},
/**
* evaluateInputs - Loop through all the elements currently on the page and display the floating label if needed.
* @version 1.0.0
* @example
* this.evaluateInputs();
* @return {void}
*/
evaluateInputs: function evaluateInputs () {
var self = this
var inputs = document.querySelectorAll('input[type="text"], input[type="password"], input[type="email"], input[type="search"], input[type="url"], input[type="tel"], input[type="number"], textarea')
function showHideLabel (input, label) {
if (input.value.length) {
self.addClass(label, self.config.floatingClassName)
} else {
self.removeClass(label, self.config.floatingClassName)
}
}
function inputEventHandler (evt) {
if (!evt) {
evt = window.event
}
var inputEl = evt.target || evt.srcElement
var inputID = inputEl.getAttribute('id')
var labelEl = document.querySelector('label[for="' + inputID + '"]')
var typeRe = /text|password|url|email|tel|search|number/i
if (!labelEl) {
return
}
if ((inputEl.nodeName === 'INPUT' && typeRe.test(inputEl.getAttribute('type'))) || inputEl.nodeName === 'TEXTAREA') {
showHideLabel(inputEl, labelEl)
}
}
for (var input = 0; input < inputs.length; input++) {
if ((inputs[input] instanceof window.Element) && window.Object.hasOwnProperty.call(inputs, input)) {
var inputEl = inputs[input]
var inputID = inputEl.getAttribute('id')
var labelEl = document.querySelector('label[for="' + inputID + '"]')
if (!labelEl) {
return
}
showHideLabel(inputEl, labelEl)
this.removeEventListener(inputEl, 'keyup', inputEventHandler, false)
this.removeEventListener(inputEl, 'input', inputEventHandler, false)
if (!this.config.delegateEvents) {
this.addEventListener(inputEl, 'keyup', inputEventHandler, false)
this.addEventListener(inputEl, 'input', inputEventHandler, false)
}
}
}
if (this.config.delegateEvents && !this._eventsDelegated) {
this.addEventListener(document.body, 'keyup', inputEventHandler, false)
this.addEventListener(document.body, 'input', inputEventHandler, false)
this._eventsDelegated = true
}
},
/**
* getPreviousSibling - Small function to get the previous sibling of an element. Should be compatible with IE8+
* @version 1.0.0
* @example
* this.getPreviousSibling( el );
* @param {element} el - The element to get the previous sibling of
* @return {element} - The previous sibling element
*/
getPreviousSibling: function getPreviousSibling (el) {
el = el.previousSibling
while (el && el.nodeType !== 1) {
el = el.previousSibling
}
return el
},
/**
* addClass - Small function to add a class to an element. Should be compatible with IE8+
* @version 1.0.0
* @example
* this.addClass( this.currentTooltip, 'visible' );
* @param {element} el - The element to add the class to
* @param {string} className - The class name to add to the element
* @return {element} - The element that had the class added to it
* @api private
*/
addClass: function addClass (el, className) {
if (el.classList) {
el.classList.add(className)
} else {
el.className += ' ' + className
}
return el
},
/**
* removeClass - Small function to remove a class from an element. Should be compatible with IE8+
* @version 1.0.0
* @example
* this.removeClass( this.currentTooltip, 'visible' );
* @param {element} el - The element to remove the class from
* @param {string} className - The class name to remove from the element
* @return {element} - The element that had the class removed from it
* @api private
*/
removeClass: function removeClass (el, className) {
if (el) {
if (el.classList) {
el.classList.remove(className)
} else {
el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ')
}
}
return el
},
/**
* hasClass - Small function to see if an element has a specific class. Should be compatible with IE8+
* @version 1.0.0
* @example
* this.hasClass( this.currentTooltip, 'visible' );
* @param {element} el - The element to check the class existence on
* @param {string} className - The class to check for
* @return {boolean} - True or false depending on if the element has the class
* @api private
*/
hasClass: function hasClass (el, className) {
if (el.classList) {
return el.classList.contains(className)
} else {
return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className)
}
},
/**
* addEventListener - Small function to add an event listener. Should be compatible with IE8+
* @version 1.0.0
* @example
* this.addEventListener( document.body, 'click', this.open( this.currentTooltip ));
* @param {element} el - The element node that needs to have the event listener added
* @param {string} eventName - The event name (sans the "on")
* @param {function} handler - The function to be run when the event is triggered
* @return {element} - The element that had an event bound
* @api private
*/
addEventListener: function addEventListener (el, eventName, handler, useCapture) {
if (!useCapture) {
useCapture = false
}
if (el.addEventListener) {
el.addEventListener(eventName, handler, useCapture)
return el
} else {
if (eventName === 'focus') {
eventName = 'focusin'
}
el.attachEvent('on' + eventName, function () {
handler.call(el)
})
return el
}
},
/**
* removeEventListener - Small function to remove and event listener. Should be compatible with IE8+
* @version 1.0.0
* @example
* this.removeEventListener( document.body, 'click', this.open( this.currentTooltip ));
* @param {element} el - The element node that needs to have the event listener removed
* @param {string} eventName - The event name (sans the "on")
* @param {function} handler - The function that was to be run when the event is triggered
* @return {element} - The element that had an event removed
* @api private
*/
removeEventListener: function removeEventListener (el, eventName, handler, useCapture) {
if (!useCapture) {
useCapture = false
}
if (el.removeEventListener) {
el.removeEventListener(eventName, handler, useCapture)
} else {
if (eventName === 'focus') {
eventName = 'focusin'
}
el.detachEvent('on' + eventName, function () {
handler.call(el)
})
}
return el
}
}