zurb-foundation 4.3.1 → 4.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile.lock +31 -2
  4. data/Gruntfile.js +54 -10
  5. data/LICENSE +2 -2
  6. data/README.md +11 -2
  7. data/Rakefile +9 -0
  8. data/docs/CHANGELOG.md +9 -0
  9. data/docs/Procfile +2 -2
  10. data/docs/components/abide.html.erb +30 -6
  11. data/docs/components/alert-boxes.html.erb +35 -10
  12. data/docs/components/block-grid.html.erb +1 -1
  13. data/docs/components/breadcrumbs.html.erb +4 -4
  14. data/docs/components/button-groups.html.erb +2 -2
  15. data/docs/components/buttons.html.erb +10 -10
  16. data/docs/components/clearing.html.erb +28 -2
  17. data/docs/components/custom-forms.html.erb +9 -1
  18. data/docs/components/dropdown-buttons.html.erb +36 -11
  19. data/docs/components/dropdown.html.erb +44 -13
  20. data/docs/components/flex-video.html.erb +3 -3
  21. data/docs/components/forms.html.erb +10 -10
  22. data/docs/components/global.html.erb +15 -20
  23. data/docs/components/grid.html.erb +24 -23
  24. data/docs/components/inline-lists.html.erb +3 -3
  25. data/docs/components/interchange.html.erb +28 -2
  26. data/docs/components/joyride.html.erb +34 -10
  27. data/docs/components/keystrokes.html.erb +3 -3
  28. data/docs/components/kitchen-sink.html.erb +1 -1
  29. data/docs/components/labels.html.erb +3 -3
  30. data/docs/components/magellan.html.erb +25 -2
  31. data/docs/components/orbit.html.erb +39 -9
  32. data/docs/components/pagination.html.erb +7 -7
  33. data/docs/components/panels.html.erb +3 -3
  34. data/docs/components/pricing-tables.html.erb +11 -11
  35. data/docs/components/progress-bars.html.erb +5 -5
  36. data/docs/components/reveal.html.erb +31 -8
  37. data/docs/components/section.html.erb +61 -37
  38. data/docs/components/side-nav.html.erb +4 -4
  39. data/docs/components/split-buttons.html.erb +37 -15
  40. data/docs/components/sub-nav.html.erb +10 -6
  41. data/docs/components/switch.html.erb +2 -2
  42. data/docs/components/tables.html.erb +7 -7
  43. data/docs/components/tooltips.html.erb +30 -6
  44. data/docs/components/top-bar.html.erb +101 -13
  45. data/docs/components/type.html.erb +16 -16
  46. data/docs/config.ru +18 -1
  47. data/docs/controller.rb +1 -1
  48. data/docs/css/_coderay.scss +2 -2
  49. data/docs/css/_footer.scss +7 -7
  50. data/docs/css/_offcanvas.scss +16 -16
  51. data/docs/css/docs.scss +1 -3
  52. data/docs/index.html.erb +29 -29
  53. data/docs/layout.html.erb +5 -5
  54. data/docs/media-queries.html.erb +3 -3
  55. data/docs/rails.html.erb +2 -1
  56. data/docs/sass.html.erb +188 -146
  57. data/docs/support.html.erb +2 -2
  58. data/foundation.gemspec +1 -0
  59. data/js/foundation/foundation.abide.js +5 -5
  60. data/js/foundation/foundation.alerts.js +9 -4
  61. data/js/foundation/foundation.clearing.js +2 -2
  62. data/js/foundation/foundation.dropdown.js +11 -5
  63. data/js/foundation/foundation.forms.js +51 -28
  64. data/js/foundation/foundation.joyride.js +7 -5
  65. data/js/foundation/foundation.js +25 -1
  66. data/js/foundation/foundation.magellan.js +3 -2
  67. data/js/foundation/foundation.orbit.js +78 -58
  68. data/js/foundation/foundation.placeholder.js +424 -177
  69. data/js/foundation/foundation.reveal.js +39 -16
  70. data/js/foundation/foundation.section.js +62 -32
  71. data/js/foundation/foundation.tooltips.js +3 -2
  72. data/js/foundation/foundation.topbar.js +139 -69
  73. data/lib/foundation/generators/templates/application.html.erb +2 -1
  74. data/lib/foundation/version.rb +1 -1
  75. data/lib/zurb-foundation.rb +12 -0
  76. data/package.json +4 -3
  77. data/scss/foundation/_variables.scss +183 -159
  78. data/scss/foundation/components/_alert-boxes.scss +8 -8
  79. data/scss/foundation/components/_block-grid.scss +1 -1
  80. data/scss/foundation/components/_breadcrumbs.scss +3 -3
  81. data/scss/foundation/components/_button-groups.scss +2 -2
  82. data/scss/foundation/components/_buttons.scss +20 -20
  83. data/scss/foundation/components/_custom-forms.scss +19 -14
  84. data/scss/foundation/components/_dropdown-buttons.scss +8 -8
  85. data/scss/foundation/components/_dropdown.scss +4 -4
  86. data/scss/foundation/components/_flex-video.scss +2 -2
  87. data/scss/foundation/components/_forms.scss +28 -18
  88. data/scss/foundation/components/_global.scss +43 -18
  89. data/scss/foundation/components/_grid-5.scss +4 -4
  90. data/scss/foundation/components/_grid.scss +6 -4
  91. data/scss/foundation/components/_inline-lists.scss +3 -3
  92. data/scss/foundation/components/_joyride.scss +10 -10
  93. data/scss/foundation/components/_keystrokes.scss +2 -2
  94. data/scss/foundation/components/_labels.scss +2 -2
  95. data/scss/foundation/components/_orbit.scss +58 -44
  96. data/scss/foundation/components/_pagination.scss +6 -6
  97. data/scss/foundation/components/_panels.scss +7 -4
  98. data/scss/foundation/components/_pricing-tables.scss +10 -10
  99. data/scss/foundation/components/_progress-bars.scss +3 -3
  100. data/scss/foundation/components/_reveal.scss +5 -5
  101. data/scss/foundation/components/_section.scss +21 -21
  102. data/scss/foundation/components/_side-nav.scss +3 -3
  103. data/scss/foundation/components/_split-buttons.scss +7 -7
  104. data/scss/foundation/components/_sub-nav.scss +26 -10
  105. data/scss/foundation/components/_switch.scss +15 -11
  106. data/scss/foundation/components/_tables.scss +6 -6
  107. data/scss/foundation/components/_thumbs.scss +2 -4
  108. data/scss/foundation/components/_tooltips.scss +4 -4
  109. data/scss/foundation/components/_top-bar.scss +77 -39
  110. data/scss/foundation/components/_type.scss +25 -23
  111. data/scss/foundation/components/_visibility.scss +28 -28
  112. data/scss/normalize.scss +22 -14
  113. data/spec/js/SectionSpec.js +39 -0
  114. data/spec/js/helpers/SectionSpecHelper.js +22 -0
  115. data/spec/js/helpers/SpecHelper.js +19 -0
  116. metadata +32 -25
  117. data/.rbenv-version +0 -1
@@ -1,179 +1,426 @@
1
- /*! http://mths.be/placeholder v2.0.7 by @mathias
2
- Modified to work with Zepto.js by ZURB
3
- */
4
- ;(function(window, document, $) {
5
-
6
- var isInputSupported = 'placeholder' in document.createElement('input'),
7
- isTextareaSupported = 'placeholder' in document.createElement('textarea'),
8
- prototype = $.fn,
9
- valHooks = $.valHooks,
10
- hooks,
11
- placeholder;
12
-
13
- if (isInputSupported && isTextareaSupported) {
14
-
15
- placeholder = prototype.placeholder = function() {
16
- return this;
17
- };
18
-
19
- placeholder.input = placeholder.textarea = true;
20
-
21
- } else {
22
-
23
- placeholder = prototype.placeholder = function() {
24
- var $this = this;
25
- $this
26
- .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
27
- .not('.placeholder')
28
- .bind({
29
- 'focus.placeholder': clearPlaceholder,
30
- 'blur.placeholder': setPlaceholder
31
- })
32
- .data('placeholder-enabled', true)
33
- .trigger('blur.placeholder');
34
- return $this;
35
- };
36
-
37
- placeholder.input = isInputSupported;
38
- placeholder.textarea = isTextareaSupported;
39
-
40
- hooks = {
41
- 'get': function(element) {
42
- var $element = $(element);
43
- return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
44
- },
45
- 'set': function(element, value) {
46
- var $element = $(element);
47
- if (!$element.data('placeholder-enabled')) {
48
- return element.value = value;
49
- }
50
- if (value == '') {
51
- element.value = value;
52
- // Issue #56: Setting the placeholder causes problems if the element continues to have focus.
53
- if (element != document.activeElement) {
54
- // We can't use `triggerHandler` here because of dummy text/password inputs :(
55
- setPlaceholder.call(element);
56
- }
57
- } else if ($element.hasClass('placeholder')) {
58
- clearPlaceholder.call(element, true, value) || (element.value = value);
59
- } else {
60
- element.value = value;
61
- }
62
- // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
63
- return $element;
64
- }
65
- };
66
-
67
- isInputSupported || (valHooks.input = hooks);
68
- isTextareaSupported || (valHooks.textarea = hooks);
69
-
70
- $(function() {
71
- // Look for forms
72
- $(document).delegate('form', 'submit.placeholder', function() {
73
- // Clear the placeholder values so they don't get submitted
74
- var $inputs = $('.placeholder', this).each(clearPlaceholder);
75
- setTimeout(function() {
76
- $inputs.each(setPlaceholder);
77
- }, 10);
78
- });
79
- });
80
-
81
- // Clear placeholder values upon page reload
82
- $(window).bind('beforeunload.placeholder', function() {
83
- $('.placeholder').each(function() {
84
- this.value = '';
85
- });
86
- });
87
-
88
- }
89
-
90
- function args(elem) {
91
- // Return an object of element attributes
92
- var newAttrs = {},
93
- rinlinejQuery = /^jQuery\d+$/;
94
- $.each(elem.attributes, function(i, attr) {
95
- if (attr.specified && !rinlinejQuery.test(attr.name)) {
96
- newAttrs[attr.name] = attr.value;
97
- }
98
- });
99
- return newAttrs;
100
- }
101
-
102
- function clearPlaceholder(event, value) {
103
- var input = this,
104
- $input = $(input);
105
- if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {
106
- if ($input.data('placeholder-password')) {
107
- $input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
108
- // If `clearPlaceholder` was called from `$.valHooks.input.set`
109
- if (event === true) {
110
- return $input[0].value = value;
111
- }
112
- $input.focus();
113
- } else {
114
- input.value = '';
115
- $input.removeClass('placeholder');
116
- input == document.activeElement && input.select();
117
- }
118
- }
119
- }
120
-
121
- function setPlaceholder() {
122
- var $replacement,
123
- input = this,
124
- $input = $(input),
125
- $origInput = $input,
126
- id = this.id;
127
- if (input.value == '') {
128
- if (input.type == 'password') {
129
- if (!$input.data('placeholder-textinput')) {
130
- try {
131
- $replacement = $input.clone().attr({ 'type': 'text' });
132
- } catch(e) {
133
- $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
134
- }
135
- $replacement
136
- .removeAttr('name')
137
- .data({
138
- 'placeholder-password': true,
139
- 'placeholder-id': id
140
- })
141
- .bind('focus.placeholder', clearPlaceholder);
142
- $input
143
- .data({
144
- 'placeholder-textinput': $replacement,
145
- 'placeholder-id': id
146
- })
147
- .before($replacement);
148
- }
149
- $input = $input.removeAttr('id').hide().prev().attr('id', id).show();
150
- // Note: `$input[0] != input` now!
151
- }
152
- $input.addClass('placeholder');
153
- $input[0].value = $input.attr('placeholder');
154
- } else {
155
- $input.removeClass('placeholder');
156
- }
157
- }
158
-
159
- }(this, document, Foundation.zj));
160
-
161
- ;(function ($, window, document, undefined) {
162
- 'use strict';
163
-
164
- Foundation.libs.placeholder = {
165
- name : 'placeholder',
166
-
167
- version : '4.2.2',
168
-
169
- init : function (scope, method, options) {
170
- this.scope = scope || this.scope;
171
-
172
- if (typeof method !== 'string') {
173
- window.onload = function () {
174
- $('input, textarea').placeholder();
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
+
133
+ // Various other variables used throughout the rest of the script
134
+ test = document.createElement("input"),
135
+ head = document.getElementsByTagName("head")[0],
136
+ root = document.documentElement,
137
+ Placeholders = global.Placeholders,
138
+ Utils = Placeholders.Utils,
139
+ hideOnInput, liveUpdates, keydownVal, styleElem, styleRules, placeholder, timer, form, elem, len, i;
140
+
141
+ // No-op (used in place of public methods when native support is detected)
142
+ function noop() {}
143
+
144
+ // 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
+ function hidePlaceholder(elem) {
146
+ var type;
147
+ if (elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
148
+ elem.setAttribute(ATTR_ACTIVE, "false");
149
+ elem.value = "";
150
+ elem.className = elem.className.replace(classNameRegExp, "");
151
+
152
+ // If the polyfill has changed the type of the element we need to change it back
153
+ type = elem.getAttribute(ATTR_INPUT_TYPE);
154
+ if (type) {
155
+ elem.type = type;
156
+ }
157
+ return true;
158
+ }
159
+ return false;
160
+ }
161
+
162
+ // 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)
163
+ function showPlaceholder(elem) {
164
+ var type,
165
+ val = elem.getAttribute(ATTR_CURRENT_VAL);
166
+ if (elem.value === "" && val) {
167
+ elem.setAttribute(ATTR_ACTIVE, "true");
168
+ elem.value = val;
169
+ elem.className += " " + placeholderClassName;
170
+
171
+ // If the type of element needs to change, change it (e.g. password inputs)
172
+ type = elem.getAttribute(ATTR_INPUT_TYPE);
173
+ if (type) {
174
+ elem.type = "text";
175
+ } else if (elem.type === "password") {
176
+ if (Utils.changeType(elem, "text")) {
177
+ elem.setAttribute(ATTR_INPUT_TYPE, "password");
178
+ }
179
+ }
180
+ return true;
181
+ }
182
+ return false;
183
+ }
184
+
185
+ function handleElem(node, callback) {
186
+
187
+ var handleInputs, handleTextareas, elem, len, i;
188
+
189
+ // Check if the passed in node is an input/textarea (in which case it can't have any affected descendants)
190
+ if (node && node.getAttribute(ATTR_CURRENT_VAL)) {
191
+ callback(node);
192
+ } else {
193
+
194
+ // If an element was passed in, get all affected descendants. Otherwise, get all affected elements in document
195
+ handleInputs = node ? node.getElementsByTagName("input") : inputs;
196
+ handleTextareas = node ? node.getElementsByTagName("textarea") : textareas;
197
+
198
+ // Run the callback for each element
199
+ for (i = 0, len = handleInputs.length + handleTextareas.length; i < len; i++) {
200
+ elem = i < handleInputs.length ? handleInputs[i] : handleTextareas[i - handleInputs.length];
201
+ callback(elem);
202
+ }
203
+ }
204
+ }
205
+
206
+ // Return all affected elements to their normal state (remove placeholder value if present)
207
+ function disablePlaceholders(node) {
208
+ handleElem(node, hidePlaceholder);
209
+ }
210
+
211
+ // Show the placeholder value on all appropriate elements
212
+ function enablePlaceholders(node) {
213
+ handleElem(node, showPlaceholder);
214
+ }
215
+
216
+ // Returns a function that is used as a focus event handler
217
+ function makeFocusHandler(elem) {
218
+ return function () {
219
+
220
+ // Only hide the placeholder value if the (default) hide-on-focus behaviour is enabled
221
+ if (hideOnInput && elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
222
+
223
+ // Move the caret to the start of the input (this mimics the behaviour of all browsers that do not hide the placeholder on focus)
224
+ Utils.moveCaret(elem, 0);
225
+
226
+ } else {
227
+
228
+ // Remove the placeholder
229
+ hidePlaceholder(elem);
230
+ }
231
+ };
232
+ }
233
+
234
+ // Returns a function that is used as a blur event handler
235
+ function makeBlurHandler(elem) {
236
+ return function () {
237
+ showPlaceholder(elem);
238
+ };
239
+ }
240
+
241
+ // Functions that are used as a event handlers when the hide-on-input behaviour has been activated - very basic implementation of the "input" event
242
+ function makeKeydownHandler(elem) {
243
+ return function (e) {
244
+ keydownVal = elem.value;
245
+
246
+ //Prevent the use of the arrow keys (try to keep the cursor before the placeholder)
247
+ if (elem.getAttribute(ATTR_ACTIVE) === "true") {
248
+ if (keydownVal === elem.getAttribute(ATTR_CURRENT_VAL) && Utils.inArray(badKeys, e.keyCode)) {
249
+ if (e.preventDefault) {
250
+ e.preventDefault();
251
+ }
252
+ return false;
253
+ }
254
+ }
255
+ };
256
+ }
257
+ function makeKeyupHandler(elem) {
258
+ return function () {
259
+ var type;
260
+
261
+ if (elem.getAttribute(ATTR_ACTIVE) === "true" && elem.value !== keydownVal) {
262
+
263
+ // Remove the placeholder
264
+ elem.className = elem.className.replace(classNameRegExp, "");
265
+ elem.value = elem.value.replace(elem.getAttribute(ATTR_CURRENT_VAL), "");
266
+ elem.setAttribute(ATTR_ACTIVE, false);
267
+
268
+ // If the type of element needs to change, change it (e.g. password inputs)
269
+ type = elem.getAttribute(ATTR_INPUT_TYPE);
270
+ if (type) {
271
+ elem.type = type;
272
+ }
273
+ }
274
+
275
+ // If the element is now empty we need to show the placeholder
276
+ if (elem.value === "") {
277
+ elem.blur();
278
+ Utils.moveCaret(elem, 0);
279
+ }
280
+ };
281
+ }
282
+ function makeClickHandler(elem) {
283
+ return function () {
284
+ if (elem === document.activeElement && elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
285
+ Utils.moveCaret(elem, 0);
286
+ }
287
+ };
288
+ }
289
+
290
+ // Returns a function that is used as a submit event handler on form elements that have children affected by this polyfill
291
+ function makeSubmitHandler(form) {
292
+ return function () {
293
+
294
+ // Turn off placeholders on all appropriate descendant elements
295
+ disablePlaceholders(form);
296
+ };
297
+ }
298
+
299
+ // Bind event handlers to an element that we need to affect with the polyfill
300
+ function newElement(elem) {
301
+
302
+ // If the element is part of a form, make sure the placeholder string is not submitted as a value
303
+ if (elem.form) {
304
+ form = elem.form;
305
+
306
+ // Set a flag on the form so we know it's been handled (forms can contain multiple inputs)
307
+ if (!form.getAttribute(ATTR_FORM_HANDLED)) {
308
+ Utils.addEventListener(form, "submit", makeSubmitHandler(form));
309
+ form.setAttribute(ATTR_FORM_HANDLED, "true");
310
+ }
311
+ }
312
+
313
+ // Bind event handlers to the element so we can hide/show the placeholder as appropriate
314
+ Utils.addEventListener(elem, "focus", makeFocusHandler(elem));
315
+ Utils.addEventListener(elem, "blur", makeBlurHandler(elem));
316
+
317
+ // If the placeholder should hide on input rather than on focus we need additional event handlers
318
+ if (hideOnInput) {
319
+ Utils.addEventListener(elem, "keydown", makeKeydownHandler(elem));
320
+ Utils.addEventListener(elem, "keyup", makeKeyupHandler(elem));
321
+ Utils.addEventListener(elem, "click", makeClickHandler(elem));
175
322
  }
176
- }
323
+
324
+ // Remember that we've bound event handlers to this element
325
+ elem.setAttribute(ATTR_EVENTS_BOUND, "true");
326
+ elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
327
+
328
+ // If the element doesn't have a value, set it to the placeholder string
329
+ showPlaceholder(elem);
177
330
  }
178
- };
179
- }(Foundation.zj, this, this.document));
331
+
332
+ Placeholders.nativeSupport = test.placeholder !== void 0;
333
+
334
+ if (!Placeholders.nativeSupport) {
335
+
336
+ // Get references to all the input and textarea elements currently in the DOM (live NodeList objects to we only need to do this once)
337
+ inputs = document.getElementsByTagName("input");
338
+ textareas = document.getElementsByTagName("textarea");
339
+
340
+ // 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)
341
+ hideOnInput = root.getAttribute(ATTR_OPTION_FOCUS) === "false";
342
+ liveUpdates = root.getAttribute(ATTR_OPTION_LIVE) !== "false";
343
+
344
+ // Create style element for placeholder styles (instead of directly setting style properties on elements - allows for better flexibility alongside user-defined styles)
345
+ styleElem = document.createElement("style");
346
+ styleElem.type = "text/css";
347
+
348
+ // Create style rules as text node
349
+ styleRules = document.createTextNode("." + placeholderClassName + " { color:" + placeholderStyleColor + "; }");
350
+
351
+ // Append style rules to newly created stylesheet
352
+ if (styleElem.styleSheet) {
353
+ styleElem.styleSheet.cssText = styleRules.nodeValue;
354
+ } else {
355
+ styleElem.appendChild(styleRules);
356
+ }
357
+
358
+ // Prepend new style element to the head (before any existing stylesheets, so user-defined rules take precedence)
359
+ head.insertBefore(styleElem, head.firstChild);
360
+
361
+ // Set up the placeholders
362
+ for (i = 0, len = inputs.length + textareas.length; i < len; i++) {
363
+ elem = i < inputs.length ? inputs[i] : textareas[i - inputs.length];
364
+
365
+ // Get the value of the placeholder attribute, if any. IE10 emulating IE7 fails with getAttribute, hence the use of the attributes node
366
+ placeholder = elem.attributes.placeholder;
367
+ if (placeholder) {
368
+
369
+ // IE returns an empty object instead of undefined if the attribute is not present
370
+ placeholder = placeholder.nodeValue;
371
+
372
+ // Only apply the polyfill if this element is of a type that supports placeholders, and has a placeholder attribute with a non-empty value
373
+ if (placeholder && Utils.inArray(validTypes, elem.type)) {
374
+ newElement(elem);
375
+ }
376
+ }
377
+ }
378
+
379
+ // If enabled, the polyfill will repeatedly check for changed/added elements and apply to those as well
380
+ timer = setInterval(function () {
381
+ for (i = 0, len = inputs.length + textareas.length; i < len; i++) {
382
+ elem = i < inputs.length ? inputs[i] : textareas[i - inputs.length];
383
+
384
+ // Only apply the polyfill if this element is of a type that supports placeholders, and has a placeholder attribute with a non-empty value
385
+ placeholder = elem.attributes.placeholder;
386
+ if (placeholder) {
387
+ placeholder = placeholder.nodeValue;
388
+ if (placeholder && Utils.inArray(validTypes, elem.type)) {
389
+
390
+ // If the element hasn't had event handlers bound to it then add them
391
+ if (!elem.getAttribute(ATTR_EVENTS_BOUND)) {
392
+ newElement(elem);
393
+ }
394
+
395
+ // If the placeholder value has changed or not been initialised yet we need to update the display
396
+ if (placeholder !== elem.getAttribute(ATTR_CURRENT_VAL) || (elem.type === "password" && !elem.getAttribute(ATTR_INPUT_TYPE))) {
397
+
398
+ // Attempt to change the type of password inputs (fails in IE < 9)
399
+ if (elem.type === "password" && !elem.getAttribute(ATTR_INPUT_TYPE) && Utils.changeType(elem, "text")) {
400
+ elem.setAttribute(ATTR_INPUT_TYPE, "password");
401
+ }
402
+
403
+ // If the placeholder value has changed and the placeholder is currently on display we need to change it
404
+ if (elem.value === elem.getAttribute(ATTR_CURRENT_VAL)) {
405
+ elem.value = placeholder;
406
+ }
407
+
408
+ // Keep a reference to the current placeholder value in case it changes via another script
409
+ elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ // If live updates are not enabled cancel the timer
416
+ if (!liveUpdates) {
417
+ clearInterval(timer);
418
+ }
419
+ }, 100);
420
+ }
421
+
422
+ // Expose public methods
423
+ Placeholders.disable = Placeholders.nativeSupport ? noop : disablePlaceholders;
424
+ Placeholders.enable = Placeholders.nativeSupport ? noop : enablePlaceholders;
425
+
426
+ }(this));