placeholder-gem 3.0.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +2 -2
- data/lib/placeholder-gem/version.rb +1 -1
- data/vendor/assets/javascripts/placeholder.js +31 -8
- data/vendor/assets/javascripts/v3.0.2/placeholder.js +459 -0
- metadata +18 -29
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4e78b9f460dc2e373b8b07ba27ed7ecd1fdf2474
|
4
|
+
data.tar.gz: 5888077cf7beea76f2ff8af63d59438f9f45afb1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c89c208d1d229900761c3736b9c35d5f84f389d30a29f8b91508828920141baa764c61da4d3417409721c48f66e44aed03b8dbe2330ecb5222f27a5ceb0a8d18
|
7
|
+
data.tar.gz: f0f2d9147b7bfa892a42d00824ea5d820b1983c0a6ee69bd2d6a7a9f7c99dd43edf40cfa2fb505f165c5bd840c9e9ffa96f9a19daad1a9222e39cc626a5becbf
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Placeholder Gem
|
1
|
+
# Placeholder Gem [](http://badge.fury.io/rb/placeholder-gem)
|
2
2
|
|
3
3
|
[Placeholders.js HTML polyfill][placeholder] as a Ruby gem.
|
4
4
|
|
@@ -44,4 +44,4 @@ Then the maintainer of the gem will need to do the following steps:
|
|
44
44
|
1. Once satisfied, push the gem up to RubyGems.org with ``gem push placeholder-gem-<VERSION>.gem``
|
45
45
|
1. Update [the changelog](CHANGELOG.md)
|
46
46
|
|
47
|
-
[placeholder]: https://github.com/jamesallardice/Placeholders.js
|
47
|
+
[placeholder]: https://github.com/jamesallardice/Placeholders.js
|
@@ -3,8 +3,8 @@
|
|
3
3
|
*
|
4
4
|
* Copyright (c) 2012 James Allardice
|
5
5
|
*
|
6
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
7
|
-
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
7
|
+
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
8
8
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
9
|
*
|
10
10
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
@@ -76,6 +76,7 @@
|
|
76
76
|
};
|
77
77
|
|
78
78
|
}(this));
|
79
|
+
|
79
80
|
(function (global) {
|
80
81
|
|
81
82
|
"use strict";
|
@@ -141,6 +142,16 @@
|
|
141
142
|
// No-op (used in place of public methods when native support is detected)
|
142
143
|
function noop() {}
|
143
144
|
|
145
|
+
// Avoid IE9 activeElement of death when an iframe is used.
|
146
|
+
// More info:
|
147
|
+
// http://bugs.jquery.com/ticket/13393
|
148
|
+
// https://github.com/jquery/jquery/commit/85fc5878b3c6af73f42d61eedf73013e7faae408
|
149
|
+
function safeActiveElement() {
|
150
|
+
try {
|
151
|
+
return document.activeElement;
|
152
|
+
} catch (err) {}
|
153
|
+
}
|
154
|
+
|
144
155
|
// Hide the placeholder value on a single element. Returns true if the placeholder was hidden and false if it was not (because it wasn't visible in the first place)
|
145
156
|
function hidePlaceholder(elem, keydownValue) {
|
146
157
|
var type,
|
@@ -155,7 +166,7 @@
|
|
155
166
|
|
156
167
|
// Restore the maxlength value
|
157
168
|
maxLength = elem.getAttribute(ATTR_MAXLENGTH);
|
158
|
-
if (maxLength) {
|
169
|
+
if (parseInt(maxLength, 10) >= 0) { // Old FF returns -1 if attribute not set (see GH-56)
|
159
170
|
elem.setAttribute("maxLength", maxLength);
|
160
171
|
elem.removeAttribute(ATTR_MAXLENGTH);
|
161
172
|
}
|
@@ -203,7 +214,7 @@
|
|
203
214
|
|
204
215
|
function handleElem(node, callback) {
|
205
216
|
|
206
|
-
var handleInputs, handleTextareas, elem, len, i;
|
217
|
+
var handleInputsLength, handleTextareasLength, handleInputs, handleTextareas, elem, len, i;
|
207
218
|
|
208
219
|
// Check if the passed in node is an input/textarea (in which case it can't have any affected descendants)
|
209
220
|
if (node && node.getAttribute(ATTR_CURRENT_VAL)) {
|
@@ -214,9 +225,12 @@
|
|
214
225
|
handleInputs = node ? node.getElementsByTagName("input") : inputs;
|
215
226
|
handleTextareas = node ? node.getElementsByTagName("textarea") : textareas;
|
216
227
|
|
228
|
+
handleInputsLength = handleInputs ? handleInputs.length : 0;
|
229
|
+
handleTextareasLength = handleTextareas ? handleTextareas.length : 0;
|
230
|
+
|
217
231
|
// Run the callback for each element
|
218
|
-
for (i = 0, len =
|
219
|
-
elem = i <
|
232
|
+
for (i = 0, len = handleInputsLength + handleTextareasLength; i < len; i++) {
|
233
|
+
elem = i < handleInputsLength ? handleInputs[i] : handleTextareas[i - handleInputsLength];
|
220
234
|
callback(elem);
|
221
235
|
}
|
222
236
|
}
|
@@ -286,7 +300,7 @@
|
|
286
300
|
}
|
287
301
|
function makeClickHandler(elem) {
|
288
302
|
return function () {
|
289
|
-
if (elem ===
|
303
|
+
if (elem === safeActiveElement() && elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
|
290
304
|
Utils.moveCaret(elem, 0);
|
291
305
|
}
|
292
306
|
};
|
@@ -308,6 +322,11 @@
|
|
308
322
|
if (elem.form) {
|
309
323
|
form = elem.form;
|
310
324
|
|
325
|
+
// If the type of the property is a string then we have a "form" attribute and need to get the real form
|
326
|
+
if (typeof form === "string") {
|
327
|
+
form = document.getElementById(form);
|
328
|
+
}
|
329
|
+
|
311
330
|
// Set a flag on the form so we know it's been handled (forms can contain multiple inputs)
|
312
331
|
if (!form.getAttribute(ATTR_FORM_HANDLED)) {
|
313
332
|
Utils.addEventListener(form, "submit", makeSubmitHandler(form));
|
@@ -331,7 +350,7 @@
|
|
331
350
|
elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
|
332
351
|
|
333
352
|
// If the element doesn't have a value and is not focussed, set it to the placeholder string
|
334
|
-
if (hideOnInput || elem !==
|
353
|
+
if (hideOnInput || elem !== safeActiveElement()) {
|
335
354
|
showPlaceholder(elem);
|
336
355
|
}
|
337
356
|
}
|
@@ -429,6 +448,10 @@
|
|
429
448
|
}, 100);
|
430
449
|
}
|
431
450
|
|
451
|
+
Utils.addEventListener(global, "beforeunload", function () {
|
452
|
+
Placeholders.disable();
|
453
|
+
});
|
454
|
+
|
432
455
|
// Expose public methods
|
433
456
|
Placeholders.disable = Placeholders.nativeSupport ? noop : disablePlaceholders;
|
434
457
|
Placeholders.enable = Placeholders.nativeSupport ? noop : enablePlaceholders;
|
@@ -0,0 +1,459 @@
|
|
1
|
+
/*
|
2
|
+
* The MIT License
|
3
|
+
*
|
4
|
+
* Copyright (c) 2012 James Allardice
|
5
|
+
*
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
7
|
+
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
8
|
+
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
|
+
*
|
10
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
11
|
+
*
|
12
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
13
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
14
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
15
|
+
* THE SOFTWARE.
|
16
|
+
*/
|
17
|
+
|
18
|
+
// Defines the global Placeholders object along with various utility methods
|
19
|
+
(function (global) {
|
20
|
+
|
21
|
+
"use strict";
|
22
|
+
|
23
|
+
// Cross-browser DOM event binding
|
24
|
+
function addEventListener(elem, event, fn) {
|
25
|
+
if (elem.addEventListener) {
|
26
|
+
return elem.addEventListener(event, fn, false);
|
27
|
+
}
|
28
|
+
if (elem.attachEvent) {
|
29
|
+
return elem.attachEvent("on" + event, fn);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
// Check whether an item is in an array (we don't use Array.prototype.indexOf so we don't clobber any existing polyfills - this is a really simple alternative)
|
34
|
+
function inArray(arr, item) {
|
35
|
+
var i, len;
|
36
|
+
for (i = 0, len = arr.length; i < len; i++) {
|
37
|
+
if (arr[i] === item) {
|
38
|
+
return true;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
return false;
|
42
|
+
}
|
43
|
+
|
44
|
+
// Move the caret to the index position specified. Assumes that the element has focus
|
45
|
+
function moveCaret(elem, index) {
|
46
|
+
var range;
|
47
|
+
if (elem.createTextRange) {
|
48
|
+
range = elem.createTextRange();
|
49
|
+
range.move("character", index);
|
50
|
+
range.select();
|
51
|
+
} else if (elem.selectionStart) {
|
52
|
+
elem.focus();
|
53
|
+
elem.setSelectionRange(index, index);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
// Attempt to change the type property of an input element
|
58
|
+
function changeType(elem, type) {
|
59
|
+
try {
|
60
|
+
elem.type = type;
|
61
|
+
return true;
|
62
|
+
} catch (e) {
|
63
|
+
// You can't change input type in IE8 and below
|
64
|
+
return false;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
// Expose public methods
|
69
|
+
global.Placeholders = {
|
70
|
+
Utils: {
|
71
|
+
addEventListener: addEventListener,
|
72
|
+
inArray: inArray,
|
73
|
+
moveCaret: moveCaret,
|
74
|
+
changeType: changeType
|
75
|
+
}
|
76
|
+
};
|
77
|
+
|
78
|
+
}(this));
|
79
|
+
|
80
|
+
(function (global) {
|
81
|
+
|
82
|
+
"use strict";
|
83
|
+
|
84
|
+
var validTypes = [
|
85
|
+
"text",
|
86
|
+
"search",
|
87
|
+
"url",
|
88
|
+
"tel",
|
89
|
+
"email",
|
90
|
+
"password",
|
91
|
+
"number",
|
92
|
+
"textarea"
|
93
|
+
],
|
94
|
+
|
95
|
+
// The list of keycodes that are not allowed when the polyfill is configured to hide-on-input
|
96
|
+
badKeys = [
|
97
|
+
|
98
|
+
// The following keys all cause the caret to jump to the end of the input value
|
99
|
+
27, // Escape
|
100
|
+
33, // Page up
|
101
|
+
34, // Page down
|
102
|
+
35, // End
|
103
|
+
36, // Home
|
104
|
+
|
105
|
+
// Arrow keys allow you to move the caret manually, which should be prevented when the placeholder is visible
|
106
|
+
37, // Left
|
107
|
+
38, // Up
|
108
|
+
39, // Right
|
109
|
+
40, // Down
|
110
|
+
|
111
|
+
// The following keys allow you to modify the placeholder text by removing characters, which should be prevented when the placeholder is visible
|
112
|
+
8, // Backspace
|
113
|
+
46 // Delete
|
114
|
+
],
|
115
|
+
|
116
|
+
// Styling variables
|
117
|
+
placeholderStyleColor = "#ccc",
|
118
|
+
placeholderClassName = "placeholdersjs",
|
119
|
+
classNameRegExp = new RegExp("(?:^|\\s)" + placeholderClassName + "(?!\\S)"),
|
120
|
+
|
121
|
+
// These will hold references to all elements that can be affected. NodeList objects are live, so we only need to get those references once
|
122
|
+
inputs, textareas,
|
123
|
+
|
124
|
+
// The various data-* attributes used by the polyfill
|
125
|
+
ATTR_CURRENT_VAL = "data-placeholder-value",
|
126
|
+
ATTR_ACTIVE = "data-placeholder-active",
|
127
|
+
ATTR_INPUT_TYPE = "data-placeholder-type",
|
128
|
+
ATTR_FORM_HANDLED = "data-placeholder-submit",
|
129
|
+
ATTR_EVENTS_BOUND = "data-placeholder-bound",
|
130
|
+
ATTR_OPTION_FOCUS = "data-placeholder-focus",
|
131
|
+
ATTR_OPTION_LIVE = "data-placeholder-live",
|
132
|
+
ATTR_MAXLENGTH = "data-placeholder-maxlength",
|
133
|
+
|
134
|
+
// Various other variables used throughout the rest of the script
|
135
|
+
test = document.createElement("input"),
|
136
|
+
head = document.getElementsByTagName("head")[0],
|
137
|
+
root = document.documentElement,
|
138
|
+
Placeholders = global.Placeholders,
|
139
|
+
Utils = Placeholders.Utils,
|
140
|
+
hideOnInput, liveUpdates, keydownVal, styleElem, styleRules, placeholder, timer, form, elem, len, i;
|
141
|
+
|
142
|
+
// No-op (used in place of public methods when native support is detected)
|
143
|
+
function noop() {}
|
144
|
+
|
145
|
+
// Avoid IE9 activeElement of death when an iframe is used.
|
146
|
+
// More info:
|
147
|
+
// http://bugs.jquery.com/ticket/13393
|
148
|
+
// https://github.com/jquery/jquery/commit/85fc5878b3c6af73f42d61eedf73013e7faae408
|
149
|
+
function safeActiveElement() {
|
150
|
+
try {
|
151
|
+
return document.activeElement;
|
152
|
+
} catch (err) {}
|
153
|
+
}
|
154
|
+
|
155
|
+
// Hide the placeholder value on a single element. Returns true if the placeholder was hidden and false if it was not (because it wasn't visible in the first place)
|
156
|
+
function hidePlaceholder(elem, keydownValue) {
|
157
|
+
var type,
|
158
|
+
maxLength,
|
159
|
+
valueChanged = (!!keydownValue && elem.value !== keydownValue),
|
160
|
+
isPlaceholderValue = (elem.value === elem.getAttribute(ATTR_CURRENT_VAL));
|
161
|
+
|
162
|
+
if ((valueChanged || isPlaceholderValue) && elem.getAttribute(ATTR_ACTIVE) === "true") {
|
163
|
+
elem.removeAttribute(ATTR_ACTIVE);
|
164
|
+
elem.value = elem.value.replace(elem.getAttribute(ATTR_CURRENT_VAL), "");
|
165
|
+
elem.className = elem.className.replace(classNameRegExp, "");
|
166
|
+
|
167
|
+
// Restore the maxlength value
|
168
|
+
maxLength = elem.getAttribute(ATTR_MAXLENGTH);
|
169
|
+
if (parseInt(maxLength, 10) >= 0) { // Old FF returns -1 if attribute not set (see GH-56)
|
170
|
+
elem.setAttribute("maxLength", maxLength);
|
171
|
+
elem.removeAttribute(ATTR_MAXLENGTH);
|
172
|
+
}
|
173
|
+
|
174
|
+
// If the polyfill has changed the type of the element we need to change it back
|
175
|
+
type = elem.getAttribute(ATTR_INPUT_TYPE);
|
176
|
+
if (type) {
|
177
|
+
elem.type = type;
|
178
|
+
}
|
179
|
+
return true;
|
180
|
+
}
|
181
|
+
return false;
|
182
|
+
}
|
183
|
+
|
184
|
+
// Show the placeholder value on a single element. Returns true if the placeholder was shown and false if it was not (because it was already visible)
|
185
|
+
function showPlaceholder(elem) {
|
186
|
+
var type,
|
187
|
+
maxLength,
|
188
|
+
val = elem.getAttribute(ATTR_CURRENT_VAL);
|
189
|
+
if (elem.value === "" && val) {
|
190
|
+
elem.setAttribute(ATTR_ACTIVE, "true");
|
191
|
+
elem.value = val;
|
192
|
+
elem.className += " " + placeholderClassName;
|
193
|
+
|
194
|
+
// Store and remove the maxlength value
|
195
|
+
maxLength = elem.getAttribute(ATTR_MAXLENGTH);
|
196
|
+
if (!maxLength) {
|
197
|
+
elem.setAttribute(ATTR_MAXLENGTH, elem.maxLength);
|
198
|
+
elem.removeAttribute("maxLength");
|
199
|
+
}
|
200
|
+
|
201
|
+
// If the type of element needs to change, change it (e.g. password inputs)
|
202
|
+
type = elem.getAttribute(ATTR_INPUT_TYPE);
|
203
|
+
if (type) {
|
204
|
+
elem.type = "text";
|
205
|
+
} else if (elem.type === "password") {
|
206
|
+
if (Utils.changeType(elem, "text")) {
|
207
|
+
elem.setAttribute(ATTR_INPUT_TYPE, "password");
|
208
|
+
}
|
209
|
+
}
|
210
|
+
return true;
|
211
|
+
}
|
212
|
+
return false;
|
213
|
+
}
|
214
|
+
|
215
|
+
function handleElem(node, callback) {
|
216
|
+
|
217
|
+
var handleInputsLength, handleTextareasLength, handleInputs, handleTextareas, elem, len, i;
|
218
|
+
|
219
|
+
// Check if the passed in node is an input/textarea (in which case it can't have any affected descendants)
|
220
|
+
if (node && node.getAttribute(ATTR_CURRENT_VAL)) {
|
221
|
+
callback(node);
|
222
|
+
} else {
|
223
|
+
|
224
|
+
// If an element was passed in, get all affected descendants. Otherwise, get all affected elements in document
|
225
|
+
handleInputs = node ? node.getElementsByTagName("input") : inputs;
|
226
|
+
handleTextareas = node ? node.getElementsByTagName("textarea") : textareas;
|
227
|
+
|
228
|
+
handleInputsLength = handleInputs ? handleInputs.length : 0;
|
229
|
+
handleTextareasLength = handleTextareas ? handleTextareas.length : 0;
|
230
|
+
|
231
|
+
// Run the callback for each element
|
232
|
+
for (i = 0, len = handleInputsLength + handleTextareasLength; i < len; i++) {
|
233
|
+
elem = i < handleInputsLength ? handleInputs[i] : handleTextareas[i - handleInputsLength];
|
234
|
+
callback(elem);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
// Return all affected elements to their normal state (remove placeholder value if present)
|
240
|
+
function disablePlaceholders(node) {
|
241
|
+
handleElem(node, hidePlaceholder);
|
242
|
+
}
|
243
|
+
|
244
|
+
// Show the placeholder value on all appropriate elements
|
245
|
+
function enablePlaceholders(node) {
|
246
|
+
handleElem(node, showPlaceholder);
|
247
|
+
}
|
248
|
+
|
249
|
+
// Returns a function that is used as a focus event handler
|
250
|
+
function makeFocusHandler(elem) {
|
251
|
+
return function () {
|
252
|
+
|
253
|
+
// Only hide the placeholder value if the (default) hide-on-focus behaviour is enabled
|
254
|
+
if (hideOnInput && elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
|
255
|
+
|
256
|
+
// Move the caret to the start of the input (this mimics the behaviour of all browsers that do not hide the placeholder on focus)
|
257
|
+
Utils.moveCaret(elem, 0);
|
258
|
+
|
259
|
+
} else {
|
260
|
+
|
261
|
+
// Remove the placeholder
|
262
|
+
hidePlaceholder(elem);
|
263
|
+
}
|
264
|
+
};
|
265
|
+
}
|
266
|
+
|
267
|
+
// Returns a function that is used as a blur event handler
|
268
|
+
function makeBlurHandler(elem) {
|
269
|
+
return function () {
|
270
|
+
showPlaceholder(elem);
|
271
|
+
};
|
272
|
+
}
|
273
|
+
|
274
|
+
// Functions that are used as a event handlers when the hide-on-input behaviour has been activated - very basic implementation of the "input" event
|
275
|
+
function makeKeydownHandler(elem) {
|
276
|
+
return function (e) {
|
277
|
+
keydownVal = elem.value;
|
278
|
+
|
279
|
+
//Prevent the use of the arrow keys (try to keep the cursor before the placeholder)
|
280
|
+
if (elem.getAttribute(ATTR_ACTIVE) === "true") {
|
281
|
+
if (keydownVal === elem.getAttribute(ATTR_CURRENT_VAL) && Utils.inArray(badKeys, e.keyCode)) {
|
282
|
+
if (e.preventDefault) {
|
283
|
+
e.preventDefault();
|
284
|
+
}
|
285
|
+
return false;
|
286
|
+
}
|
287
|
+
}
|
288
|
+
};
|
289
|
+
}
|
290
|
+
function makeKeyupHandler(elem) {
|
291
|
+
return function () {
|
292
|
+
hidePlaceholder(elem, keydownVal);
|
293
|
+
|
294
|
+
// If the element is now empty we need to show the placeholder
|
295
|
+
if (elem.value === "") {
|
296
|
+
elem.blur();
|
297
|
+
Utils.moveCaret(elem, 0);
|
298
|
+
}
|
299
|
+
};
|
300
|
+
}
|
301
|
+
function makeClickHandler(elem) {
|
302
|
+
return function () {
|
303
|
+
if (elem === safeActiveElement() && elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
|
304
|
+
Utils.moveCaret(elem, 0);
|
305
|
+
}
|
306
|
+
};
|
307
|
+
}
|
308
|
+
|
309
|
+
// Returns a function that is used as a submit event handler on form elements that have children affected by this polyfill
|
310
|
+
function makeSubmitHandler(form) {
|
311
|
+
return function () {
|
312
|
+
|
313
|
+
// Turn off placeholders on all appropriate descendant elements
|
314
|
+
disablePlaceholders(form);
|
315
|
+
};
|
316
|
+
}
|
317
|
+
|
318
|
+
// Bind event handlers to an element that we need to affect with the polyfill
|
319
|
+
function newElement(elem) {
|
320
|
+
|
321
|
+
// If the element is part of a form, make sure the placeholder string is not submitted as a value
|
322
|
+
if (elem.form) {
|
323
|
+
form = elem.form;
|
324
|
+
|
325
|
+
// If the type of the property is a string then we have a "form" attribute and need to get the real form
|
326
|
+
if (typeof form === "string") {
|
327
|
+
form = document.getElementById(form);
|
328
|
+
}
|
329
|
+
|
330
|
+
// Set a flag on the form so we know it's been handled (forms can contain multiple inputs)
|
331
|
+
if (!form.getAttribute(ATTR_FORM_HANDLED)) {
|
332
|
+
Utils.addEventListener(form, "submit", makeSubmitHandler(form));
|
333
|
+
form.setAttribute(ATTR_FORM_HANDLED, "true");
|
334
|
+
}
|
335
|
+
}
|
336
|
+
|
337
|
+
// Bind event handlers to the element so we can hide/show the placeholder as appropriate
|
338
|
+
Utils.addEventListener(elem, "focus", makeFocusHandler(elem));
|
339
|
+
Utils.addEventListener(elem, "blur", makeBlurHandler(elem));
|
340
|
+
|
341
|
+
// If the placeholder should hide on input rather than on focus we need additional event handlers
|
342
|
+
if (hideOnInput) {
|
343
|
+
Utils.addEventListener(elem, "keydown", makeKeydownHandler(elem));
|
344
|
+
Utils.addEventListener(elem, "keyup", makeKeyupHandler(elem));
|
345
|
+
Utils.addEventListener(elem, "click", makeClickHandler(elem));
|
346
|
+
}
|
347
|
+
|
348
|
+
// Remember that we've bound event handlers to this element
|
349
|
+
elem.setAttribute(ATTR_EVENTS_BOUND, "true");
|
350
|
+
elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
|
351
|
+
|
352
|
+
// If the element doesn't have a value and is not focussed, set it to the placeholder string
|
353
|
+
if (hideOnInput || elem !== safeActiveElement()) {
|
354
|
+
showPlaceholder(elem);
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
Placeholders.nativeSupport = test.placeholder !== void 0;
|
359
|
+
|
360
|
+
if (!Placeholders.nativeSupport) {
|
361
|
+
|
362
|
+
// Get references to all the input and textarea elements currently in the DOM (live NodeList objects to we only need to do this once)
|
363
|
+
inputs = document.getElementsByTagName("input");
|
364
|
+
textareas = document.getElementsByTagName("textarea");
|
365
|
+
|
366
|
+
// Get any settings declared as data-* attributes on the root element (currently the only options are whether to hide the placeholder on focus or input and whether to auto-update)
|
367
|
+
hideOnInput = root.getAttribute(ATTR_OPTION_FOCUS) === "false";
|
368
|
+
liveUpdates = root.getAttribute(ATTR_OPTION_LIVE) !== "false";
|
369
|
+
|
370
|
+
// Create style element for placeholder styles (instead of directly setting style properties on elements - allows for better flexibility alongside user-defined styles)
|
371
|
+
styleElem = document.createElement("style");
|
372
|
+
styleElem.type = "text/css";
|
373
|
+
|
374
|
+
// Create style rules as text node
|
375
|
+
styleRules = document.createTextNode("." + placeholderClassName + " { color:" + placeholderStyleColor + "; }");
|
376
|
+
|
377
|
+
// Append style rules to newly created stylesheet
|
378
|
+
if (styleElem.styleSheet) {
|
379
|
+
styleElem.styleSheet.cssText = styleRules.nodeValue;
|
380
|
+
} else {
|
381
|
+
styleElem.appendChild(styleRules);
|
382
|
+
}
|
383
|
+
|
384
|
+
// Prepend new style element to the head (before any existing stylesheets, so user-defined rules take precedence)
|
385
|
+
head.insertBefore(styleElem, head.firstChild);
|
386
|
+
|
387
|
+
// Set up the placeholders
|
388
|
+
for (i = 0, len = inputs.length + textareas.length; i < len; i++) {
|
389
|
+
elem = i < inputs.length ? inputs[i] : textareas[i - inputs.length];
|
390
|
+
|
391
|
+
// Get the value of the placeholder attribute, if any. IE10 emulating IE7 fails with getAttribute, hence the use of the attributes node
|
392
|
+
placeholder = elem.attributes.placeholder;
|
393
|
+
if (placeholder) {
|
394
|
+
|
395
|
+
// IE returns an empty object instead of undefined if the attribute is not present
|
396
|
+
placeholder = placeholder.nodeValue;
|
397
|
+
|
398
|
+
// Only apply the polyfill if this element is of a type that supports placeholders, and has a placeholder attribute with a non-empty value
|
399
|
+
if (placeholder && Utils.inArray(validTypes, elem.type)) {
|
400
|
+
newElement(elem);
|
401
|
+
}
|
402
|
+
}
|
403
|
+
}
|
404
|
+
|
405
|
+
// If enabled, the polyfill will repeatedly check for changed/added elements and apply to those as well
|
406
|
+
timer = setInterval(function () {
|
407
|
+
for (i = 0, len = inputs.length + textareas.length; i < len; i++) {
|
408
|
+
elem = i < inputs.length ? inputs[i] : textareas[i - inputs.length];
|
409
|
+
|
410
|
+
// Only apply the polyfill if this element is of a type that supports placeholders, and has a placeholder attribute with a non-empty value
|
411
|
+
placeholder = elem.attributes.placeholder;
|
412
|
+
if (placeholder) {
|
413
|
+
placeholder = placeholder.nodeValue;
|
414
|
+
if (placeholder && Utils.inArray(validTypes, elem.type)) {
|
415
|
+
|
416
|
+
// If the element hasn't had event handlers bound to it then add them
|
417
|
+
if (!elem.getAttribute(ATTR_EVENTS_BOUND)) {
|
418
|
+
newElement(elem);
|
419
|
+
}
|
420
|
+
|
421
|
+
// If the placeholder value has changed or not been initialised yet we need to update the display
|
422
|
+
if (placeholder !== elem.getAttribute(ATTR_CURRENT_VAL) || (elem.type === "password" && !elem.getAttribute(ATTR_INPUT_TYPE))) {
|
423
|
+
|
424
|
+
// Attempt to change the type of password inputs (fails in IE < 9)
|
425
|
+
if (elem.type === "password" && !elem.getAttribute(ATTR_INPUT_TYPE) && Utils.changeType(elem, "text")) {
|
426
|
+
elem.setAttribute(ATTR_INPUT_TYPE, "password");
|
427
|
+
}
|
428
|
+
|
429
|
+
// If the placeholder value has changed and the placeholder is currently on display we need to change it
|
430
|
+
if (elem.value === elem.getAttribute(ATTR_CURRENT_VAL)) {
|
431
|
+
elem.value = placeholder;
|
432
|
+
}
|
433
|
+
|
434
|
+
// Keep a reference to the current placeholder value in case it changes via another script
|
435
|
+
elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
|
436
|
+
}
|
437
|
+
}
|
438
|
+
} else if (elem.getAttribute(ATTR_ACTIVE)) {
|
439
|
+
hidePlaceholder(elem);
|
440
|
+
elem.removeAttribute(ATTR_CURRENT_VAL);
|
441
|
+
}
|
442
|
+
}
|
443
|
+
|
444
|
+
// If live updates are not enabled cancel the timer
|
445
|
+
if (!liveUpdates) {
|
446
|
+
clearInterval(timer);
|
447
|
+
}
|
448
|
+
}, 100);
|
449
|
+
}
|
450
|
+
|
451
|
+
Utils.addEventListener(global, "beforeunload", function () {
|
452
|
+
Placeholders.disable();
|
453
|
+
});
|
454
|
+
|
455
|
+
// Expose public methods
|
456
|
+
Placeholders.disable = Placeholders.nativeSupport ? noop : disablePlaceholders;
|
457
|
+
Placeholders.enable = Placeholders.nativeSupport ? noop : enablePlaceholders;
|
458
|
+
|
459
|
+
}(this));
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: placeholder-gem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
5
|
-
prerelease:
|
4
|
+
version: 3.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Edward Look
|
@@ -10,86 +9,76 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2014-04-11 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: railties
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '3.1'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - '>='
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '3.1'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: bundler
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - '>='
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: 1.2.2
|
39
35
|
type: :development
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '>='
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: 1.2.2
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: tzinfo
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - '>='
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '0'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - '>='
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '0'
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: nokogiri
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- -
|
60
|
+
- - '>='
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: '0'
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- -
|
67
|
+
- - '>='
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0'
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: coveralls
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
|
-
- -
|
74
|
+
- - '>='
|
85
75
|
- !ruby/object:Gem::Version
|
86
76
|
version: '0'
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
|
-
- -
|
81
|
+
- - '>='
|
93
82
|
- !ruby/object:Gem::Version
|
94
83
|
version: '0'
|
95
84
|
description: Include Placeholder.js in your Rails projects
|
@@ -104,31 +93,31 @@ files:
|
|
104
93
|
- lib/placeholder-gem.rb
|
105
94
|
- vendor/assets/javascripts/placeholder.js
|
106
95
|
- vendor/assets/javascripts/v3.0.0/placeholder.js
|
96
|
+
- vendor/assets/javascripts/v3.0.2/placeholder.js
|
107
97
|
- MIT-LICENSE
|
108
98
|
- Rakefile
|
109
99
|
- README.md
|
110
100
|
homepage: http://github.com/ets-berkeley-edu/placeholder-gem
|
111
101
|
licenses: []
|
102
|
+
metadata: {}
|
112
103
|
post_install_message:
|
113
104
|
rdoc_options: []
|
114
105
|
require_paths:
|
115
106
|
- lib
|
116
107
|
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
-
none: false
|
118
108
|
requirements:
|
119
|
-
- -
|
109
|
+
- - '>='
|
120
110
|
- !ruby/object:Gem::Version
|
121
111
|
version: '0'
|
122
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
-
none: false
|
124
113
|
requirements:
|
125
|
-
- -
|
114
|
+
- - '>='
|
126
115
|
- !ruby/object:Gem::Version
|
127
116
|
version: '0'
|
128
117
|
requirements: []
|
129
118
|
rubyforge_project:
|
130
|
-
rubygems_version:
|
119
|
+
rubygems_version: 2.0.3
|
131
120
|
signing_key:
|
132
|
-
specification_version:
|
121
|
+
specification_version: 4
|
133
122
|
summary: Placeholder.js Javascript Polyfill for HTML5 as a gem
|
134
123
|
test_files: []
|