diff --git a/core/css/fixes.css b/core/css/fixes.css
index 0f18f0a56c..fc122b1eff 100644
--- a/core/css/fixes.css
+++ b/core/css/fixes.css
@@ -42,10 +42,6 @@ select {
border-bottom: 1px solid lightgrey;
background-color: white; /* don't change background on hover */
}
-.lte9 #body-login form label.infield {
- background-color: white; /* don't change background on hover */
- -ms-filter: "progid:DXImageTransform.Microsoft.Chroma(color='white')";
-}
/* disable opacity of info text on gradient
since we cannot set a good backround color to use the filter&background hack as with the input labels */
diff --git a/core/css/styles.css b/core/css/styles.css
index a9ffd83629..bd688f0ada 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -469,14 +469,14 @@ input[name='password-clone'] {
#user+label+img,
#password-icon {
position: absolute;
- left: 1.25em;
- top: 1.65em;
+ left: 16px;
+ top: 20px;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
filter: alpha(opacity=30);
opacity: .3;
}
#adminpass-icon, #password-icon {
- top: 1.1em;
+ top: 15px;
}
/* General new input field look */
@@ -489,6 +489,11 @@ input[name='password-clone'] {
}
/* Nicely grouping input field sets */
+.grouptop,
+.groupmiddle,
+.groupbottom {
+ position: relative;
+}
#body-login .grouptop input {
margin-bottom: 0;
border-bottom: 0;
@@ -511,23 +516,11 @@ input[name='password-clone'] {
box-shadow: 0 1px 0 rgba(0,0,0,.1) inset !important;
}
-/* In field labels. No, HTML placeholder does not work as well. */
-#body-login .groupmiddle label, #body-login .groupbottom label { top:.65em; }
-p.infield { position:relative; }
-label.infield { cursor:text !important; top:1.05em; left:.85em; }
-#body-login form label.infield { /* labels are ellipsized when too long, keep them short */
- position: absolute;
- width: 82%;
- margin-left: 26px;
- font-size: 19px;
- color: #aaa;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-#body-login #databaseField .infield {
- margin-left: 0;
+/* keep the labels for screen readers but hide them since we use placeholders */
+label.infield {
+ display: none;
}
+
#body-login form input[type="checkbox"]+label {
position: relative;
margin: 0;
@@ -585,7 +578,7 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; }
}
#show + label, #dbpassword + label, #personal-show + label {
position: absolute !important;
- height: 14px;
+ height: 20px;
width: 24px;
background-image: url("../img/actions/toggle.png");
background-repeat: no-repeat;
@@ -599,8 +592,9 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; }
width: 8em;
}
#personal-show + label {
- margin-top: 1em;
- margin-left: -3em;
+ height: 14px;
+ margin-top: 14px;
+ margin-left: -36px;
}
#passwordbutton {
margin-left: .5em;
@@ -685,7 +679,7 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; }
#body-login input {
font-size: 20px;
margin: 5px;
- padding: 12px 10px 8px;
+ padding: 11px 10px 9px;
}
#body-login input[type="text"],
#body-login input[type="password"] {
diff --git a/core/js/core.json b/core/js/core.json
index f1e0ba883d..4815116c33 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -4,7 +4,6 @@
"jquery-migrate-1.2.1.min.js",
"jquery-ui-1.10.0.custom.js",
"jquery-showpassword.js",
- "jquery.infieldlabel.js",
"jquery.placeholder.js",
"jquery-tipsy.js",
"underscore.js"
diff --git a/core/js/jquery.infieldlabel.js b/core/js/jquery.infieldlabel.js
deleted file mode 100644
index fad15102bc..0000000000
--- a/core/js/jquery.infieldlabel.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * jquery.infieldlabel
- * A simple jQuery plugin for adding labels that sit over a form field and fade away when the fields are populated.
- *
- * Copyright (c) 2009 - 2013 Doug Neiner (http://code.dougneiner.com)
- * Source: https://github.com/dcneiner/In-Field-Labels-jQuery-Plugin
- * Dual licensed MIT or GPL
- * MIT (http://www.opensource.org/licenses/mit-license)
- * GPL (http://www.opensource.org/licenses/gpl-license)
- *
- * @version 0.1.3
- */
-(function ($) {
-
- $.InFieldLabels = function (label, field, options) {
- // To avoid scope issues, use 'base' instead of 'this'
- // to reference this class from internal events and functions.
- var base = this;
-
- // Access to jQuery and DOM versions of each element
- base.$label = $(label);
- base.label = label;
-
- base.$field = $(field);
- base.field = field;
-
- base.$label.data("InFieldLabels", base);
- base.showing = true;
-
- base.init = function () {
- var initialSet;
-
- // Merge supplied options with default options
- base.options = $.extend({}, $.InFieldLabels.defaultOptions, options);
-
- // Check if the field is already filled in
- // add a short delay to handle autocomplete
- setTimeout(function() {
- if (base.$field.val() !== "") {
- base.$label.hide();
- base.showing = false;
- } else {
- base.$label.show();
- base.showing = true;
- }
- }, 200);
-
- base.$field.focus(function () {
- base.fadeOnFocus();
- }).blur(function () {
- base.checkForEmpty(true);
- }).bind('keydown.infieldlabel', function (e) {
- // Use of a namespace (.infieldlabel) allows us to
- // unbind just this method later
- base.hideOnChange(e);
- }).bind('paste', function () {
- // Since you can not paste an empty string we can assume
- // that the fieldis not empty and the label can be cleared.
- base.setOpacity(0.0);
- }).change(function () {
- base.checkForEmpty();
- }).bind('onPropertyChange', function () {
- base.checkForEmpty();
- }).bind('keyup.infieldlabel', function () {
- base.checkForEmpty();
- });
-
- if ( base.options.pollDuration > 0 ) {
- initialSet = setInterval( function () {
- if (base.$field.val() !== "") {
- base.$label.hide();
- base.showing = false;
- clearInterval( initialSet );
- }
- }, base.options.pollDuration );
-
- }
- };
-
- // If the label is currently showing
- // then fade it down to the amount
- // specified in the settings
- base.fadeOnFocus = function () {
- if (base.showing) {
- base.setOpacity(base.options.fadeOpacity);
- }
- };
-
- base.setOpacity = function (opacity) {
- base.$label.stop().animate({ opacity: opacity }, base.options.fadeDuration);
- base.showing = (opacity > 0.0);
- };
-
- // Checks for empty as a fail safe
- // set blur to true when passing from
- // the blur event
- base.checkForEmpty = function (blur) {
- if (base.$field.val() === "") {
- base.prepForShow();
- base.setOpacity(blur ? 1.0 : base.options.fadeOpacity);
- } else {
- base.setOpacity(0.0);
- }
- };
-
- base.prepForShow = function () {
- if (!base.showing) {
- // Prepare for a animate in...
- base.$label.css({opacity: 0.0}).show();
-
- // Reattach the keydown event
- base.$field.bind('keydown.infieldlabel', function (e) {
- base.hideOnChange(e);
- });
- }
- };
-
- base.hideOnChange = function (e) {
- if (
- (e.keyCode === 16) || // Skip Shift
- (e.keyCode === 9) // Skip Tab
- ) {
- return;
- }
-
- if (base.showing) {
- base.$label.hide();
- base.showing = false;
- }
-
- // Remove keydown event to save on CPU processing
- base.$field.unbind('keydown.infieldlabel');
- };
-
- // Run the initialization method
- base.init();
- };
-
- $.InFieldLabels.defaultOptions = {
- fadeOpacity: 0.5, // Once a field has focus, how transparent should the label be
- fadeDuration: 300, // How long should it take to animate from 1.0 opacity to the fadeOpacity
- pollDuration: 0, // If set to a number greater than zero, this will poll until content is detected in a field
- enabledInputTypes: [ "text", "search", "tel", "url", "email", "password", "number", "textarea" ]
- };
-
-
- $.fn.inFieldLabels = function (options) {
- var allowed_types = options && options.enabledInputTypes || $.InFieldLabels.defaultOptions.enabledInputTypes;
-
- return this.each(function () {
- // Find input or textarea based on for= attribute
- // The for attribute on the label must contain the ID
- // of the input or textarea element
- var for_attr = $(this).attr('for'), field, restrict_type;
- if (!for_attr) {
- return; // Nothing to attach, since the for field wasn't used
- }
-
- // Find the referenced input or textarea element
- field = document.getElementById( for_attr );
- if ( !field ) {
- return; // No element found
- }
-
- // Restrict input type
- restrict_type = $.inArray( field.type, allowed_types );
-
- if ( restrict_type === -1 && field.nodeName !== "TEXTAREA" ) {
- return; // Again, nothing to attach
- }
-
- // Only create object for matched input types and textarea
- (new $.InFieldLabels(this, field, options));
- });
- };
-
-}(jQuery));
diff --git a/core/js/js.js b/core/js/js.js
index 1c4fb98c60..834916b2e3 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -1039,11 +1039,6 @@ function initCore() {
setShowPassword($('#pass2'), $('label[for=personal-show]'));
setShowPassword($('#dbpass'), $('label[for=dbpassword]'));
- //use infield labels
- $("label.infield").inFieldLabels({
- pollDuration: 100
- });
-
var checkShowCredentials = function() {
var empty = false;
$('input#user, input#password').each(function() {
diff --git a/core/js/placeholders.js b/core/js/placeholders.js
new file mode 100644
index 0000000000..e63f429d40
--- /dev/null
+++ b/core/js/placeholders.js
@@ -0,0 +1,459 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2012 James Allardice
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * 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:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * 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
+ * THE SOFTWARE.
+ */
+
+// Defines the global Placeholders object along with various utility methods
+(function (global) {
+
+ "use strict";
+
+ // Cross-browser DOM event binding
+ function addEventListener(elem, event, fn) {
+ if (elem.addEventListener) {
+ return elem.addEventListener(event, fn, false);
+ }
+ if (elem.attachEvent) {
+ return elem.attachEvent("on" + event, fn);
+ }
+ }
+
+ // 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)
+ function inArray(arr, item) {
+ var i, len;
+ for (i = 0, len = arr.length; i < len; i++) {
+ if (arr[i] === item) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Move the caret to the index position specified. Assumes that the element has focus
+ function moveCaret(elem, index) {
+ var range;
+ if (elem.createTextRange) {
+ range = elem.createTextRange();
+ range.move("character", index);
+ range.select();
+ } else if (elem.selectionStart) {
+ elem.focus();
+ elem.setSelectionRange(index, index);
+ }
+ }
+
+ // Attempt to change the type property of an input element
+ function changeType(elem, type) {
+ try {
+ elem.type = type;
+ return true;
+ } catch (e) {
+ // You can't change input type in IE8 and below
+ return false;
+ }
+ }
+
+ // Expose public methods
+ global.Placeholders = {
+ Utils: {
+ addEventListener: addEventListener,
+ inArray: inArray,
+ moveCaret: moveCaret,
+ changeType: changeType
+ }
+ };
+
+}(this));
+
+(function (global) {
+
+ "use strict";
+
+ var validTypes = [
+ "text",
+ "search",
+ "url",
+ "tel",
+ "email",
+ "password",
+ "number",
+ "textarea"
+ ],
+
+ // The list of keycodes that are not allowed when the polyfill is configured to hide-on-input
+ badKeys = [
+
+ // The following keys all cause the caret to jump to the end of the input value
+ 27, // Escape
+ 33, // Page up
+ 34, // Page down
+ 35, // End
+ 36, // Home
+
+ // Arrow keys allow you to move the caret manually, which should be prevented when the placeholder is visible
+ 37, // Left
+ 38, // Up
+ 39, // Right
+ 40, // Down
+
+ // The following keys allow you to modify the placeholder text by removing characters, which should be prevented when the placeholder is visible
+ 8, // Backspace
+ 46 // Delete
+ ],
+
+ // Styling variables
+ placeholderStyleColor = "#ccc",
+ placeholderClassName = "placeholdersjs",
+ classNameRegExp = new RegExp("(?:^|\\s)" + placeholderClassName + "(?!\\S)"),
+
+ // These will hold references to all elements that can be affected. NodeList objects are live, so we only need to get those references once
+ inputs, textareas,
+
+ // The various data-* attributes used by the polyfill
+ ATTR_CURRENT_VAL = "data-placeholder-value",
+ ATTR_ACTIVE = "data-placeholder-active",
+ ATTR_INPUT_TYPE = "data-placeholder-type",
+ ATTR_FORM_HANDLED = "data-placeholder-submit",
+ ATTR_EVENTS_BOUND = "data-placeholder-bound",
+ ATTR_OPTION_FOCUS = "data-placeholder-focus",
+ ATTR_OPTION_LIVE = "data-placeholder-live",
+ ATTR_MAXLENGTH = "data-placeholder-maxlength",
+
+ // Various other variables used throughout the rest of the script
+ test = document.createElement("input"),
+ head = document.getElementsByTagName("head")[0],
+ root = document.documentElement,
+ Placeholders = global.Placeholders,
+ Utils = Placeholders.Utils,
+ hideOnInput, liveUpdates, keydownVal, styleElem, styleRules, placeholder, timer, form, elem, len, i;
+
+ // No-op (used in place of public methods when native support is detected)
+ function noop() {}
+
+ // Avoid IE9 activeElement of death when an iframe is used.
+ // More info:
+ // http://bugs.jquery.com/ticket/13393
+ // https://github.com/jquery/jquery/commit/85fc5878b3c6af73f42d61eedf73013e7faae408
+ function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch (err) {}
+ }
+
+ // 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)
+ function hidePlaceholder(elem, keydownValue) {
+ var type,
+ maxLength,
+ valueChanged = (!!keydownValue && elem.value !== keydownValue),
+ isPlaceholderValue = (elem.value === elem.getAttribute(ATTR_CURRENT_VAL));
+
+ if ((valueChanged || isPlaceholderValue) && elem.getAttribute(ATTR_ACTIVE) === "true") {
+ elem.removeAttribute(ATTR_ACTIVE);
+ elem.value = elem.value.replace(elem.getAttribute(ATTR_CURRENT_VAL), "");
+ elem.className = elem.className.replace(classNameRegExp, "");
+
+ // Restore the maxlength value
+ maxLength = elem.getAttribute(ATTR_MAXLENGTH);
+ if (parseInt(maxLength, 10) >= 0) { // Old FF returns -1 if attribute not set (see GH-56)
+ elem.setAttribute("maxLength", maxLength);
+ elem.removeAttribute(ATTR_MAXLENGTH);
+ }
+
+ // If the polyfill has changed the type of the element we need to change it back
+ type = elem.getAttribute(ATTR_INPUT_TYPE);
+ if (type) {
+ elem.type = type;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ // 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)
+ function showPlaceholder(elem) {
+ var type,
+ maxLength,
+ val = elem.getAttribute(ATTR_CURRENT_VAL);
+ if (elem.value === "" && val) {
+ elem.setAttribute(ATTR_ACTIVE, "true");
+ elem.value = val;
+ elem.className += " " + placeholderClassName;
+
+ // Store and remove the maxlength value
+ maxLength = elem.getAttribute(ATTR_MAXLENGTH);
+ if (!maxLength) {
+ elem.setAttribute(ATTR_MAXLENGTH, elem.maxLength);
+ elem.removeAttribute("maxLength");
+ }
+
+ // If the type of element needs to change, change it (e.g. password inputs)
+ type = elem.getAttribute(ATTR_INPUT_TYPE);
+ if (type) {
+ elem.type = "text";
+ } else if (elem.type === "password") {
+ if (Utils.changeType(elem, "text")) {
+ elem.setAttribute(ATTR_INPUT_TYPE, "password");
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ function handleElem(node, callback) {
+
+ var handleInputsLength, handleTextareasLength, handleInputs, handleTextareas, elem, len, i;
+
+ // Check if the passed in node is an input/textarea (in which case it can't have any affected descendants)
+ if (node && node.getAttribute(ATTR_CURRENT_VAL)) {
+ callback(node);
+ } else {
+
+ // If an element was passed in, get all affected descendants. Otherwise, get all affected elements in document
+ handleInputs = node ? node.getElementsByTagName("input") : inputs;
+ handleTextareas = node ? node.getElementsByTagName("textarea") : textareas;
+
+ handleInputsLength = handleInputs ? handleInputs.length : 0;
+ handleTextareasLength = handleTextareas ? handleTextareas.length : 0;
+
+ // Run the callback for each element
+ for (i = 0, len = handleInputsLength + handleTextareasLength; i < len; i++) {
+ elem = i < handleInputsLength ? handleInputs[i] : handleTextareas[i - handleInputsLength];
+ callback(elem);
+ }
+ }
+ }
+
+ // Return all affected elements to their normal state (remove placeholder value if present)
+ function disablePlaceholders(node) {
+ handleElem(node, hidePlaceholder);
+ }
+
+ // Show the placeholder value on all appropriate elements
+ function enablePlaceholders(node) {
+ handleElem(node, showPlaceholder);
+ }
+
+ // Returns a function that is used as a focus event handler
+ function makeFocusHandler(elem) {
+ return function () {
+
+ // Only hide the placeholder value if the (default) hide-on-focus behaviour is enabled
+ if (hideOnInput && elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
+
+ // Move the caret to the start of the input (this mimics the behaviour of all browsers that do not hide the placeholder on focus)
+ Utils.moveCaret(elem, 0);
+
+ } else {
+
+ // Remove the placeholder
+ hidePlaceholder(elem);
+ }
+ };
+ }
+
+ // Returns a function that is used as a blur event handler
+ function makeBlurHandler(elem) {
+ return function () {
+ showPlaceholder(elem);
+ };
+ }
+
+ // Functions that are used as a event handlers when the hide-on-input behaviour has been activated - very basic implementation of the "input" event
+ function makeKeydownHandler(elem) {
+ return function (e) {
+ keydownVal = elem.value;
+
+ //Prevent the use of the arrow keys (try to keep the cursor before the placeholder)
+ if (elem.getAttribute(ATTR_ACTIVE) === "true") {
+ if (keydownVal === elem.getAttribute(ATTR_CURRENT_VAL) && Utils.inArray(badKeys, e.keyCode)) {
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ return false;
+ }
+ }
+ };
+ }
+ function makeKeyupHandler(elem) {
+ return function () {
+ hidePlaceholder(elem, keydownVal);
+
+ // If the element is now empty we need to show the placeholder
+ if (elem.value === "") {
+ elem.blur();
+ Utils.moveCaret(elem, 0);
+ }
+ };
+ }
+ function makeClickHandler(elem) {
+ return function () {
+ if (elem === safeActiveElement() && elem.value === elem.getAttribute(ATTR_CURRENT_VAL) && elem.getAttribute(ATTR_ACTIVE) === "true") {
+ Utils.moveCaret(elem, 0);
+ }
+ };
+ }
+
+ // Returns a function that is used as a submit event handler on form elements that have children affected by this polyfill
+ function makeSubmitHandler(form) {
+ return function () {
+
+ // Turn off placeholders on all appropriate descendant elements
+ disablePlaceholders(form);
+ };
+ }
+
+ // Bind event handlers to an element that we need to affect with the polyfill
+ function newElement(elem) {
+
+ // If the element is part of a form, make sure the placeholder string is not submitted as a value
+ if (elem.form) {
+ form = elem.form;
+
+ // If the type of the property is a string then we have a "form" attribute and need to get the real form
+ if (typeof form === "string") {
+ form = document.getElementById(form);
+ }
+
+ // Set a flag on the form so we know it's been handled (forms can contain multiple inputs)
+ if (!form.getAttribute(ATTR_FORM_HANDLED)) {
+ Utils.addEventListener(form, "submit", makeSubmitHandler(form));
+ form.setAttribute(ATTR_FORM_HANDLED, "true");
+ }
+ }
+
+ // Bind event handlers to the element so we can hide/show the placeholder as appropriate
+ Utils.addEventListener(elem, "focus", makeFocusHandler(elem));
+ Utils.addEventListener(elem, "blur", makeBlurHandler(elem));
+
+ // If the placeholder should hide on input rather than on focus we need additional event handlers
+ if (hideOnInput) {
+ Utils.addEventListener(elem, "keydown", makeKeydownHandler(elem));
+ Utils.addEventListener(elem, "keyup", makeKeyupHandler(elem));
+ Utils.addEventListener(elem, "click", makeClickHandler(elem));
+ }
+
+ // Remember that we've bound event handlers to this element
+ elem.setAttribute(ATTR_EVENTS_BOUND, "true");
+ elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
+
+ // If the element doesn't have a value and is not focussed, set it to the placeholder string
+ if (hideOnInput || elem !== safeActiveElement()) {
+ showPlaceholder(elem);
+ }
+ }
+
+ Placeholders.nativeSupport = test.placeholder !== void 0;
+
+ if (!Placeholders.nativeSupport) {
+
+ // Get references to all the input and textarea elements currently in the DOM (live NodeList objects to we only need to do this once)
+ inputs = document.getElementsByTagName("input");
+ textareas = document.getElementsByTagName("textarea");
+
+ // 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)
+ hideOnInput = root.getAttribute(ATTR_OPTION_FOCUS) === "false";
+ liveUpdates = root.getAttribute(ATTR_OPTION_LIVE) !== "false";
+
+ // Create style element for placeholder styles (instead of directly setting style properties on elements - allows for better flexibility alongside user-defined styles)
+ styleElem = document.createElement("style");
+ styleElem.type = "text/css";
+
+ // Create style rules as text node
+ styleRules = document.createTextNode("." + placeholderClassName + " { color:" + placeholderStyleColor + "; }");
+
+ // Append style rules to newly created stylesheet
+ if (styleElem.styleSheet) {
+ styleElem.styleSheet.cssText = styleRules.nodeValue;
+ } else {
+ styleElem.appendChild(styleRules);
+ }
+
+ // Prepend new style element to the head (before any existing stylesheets, so user-defined rules take precedence)
+ head.insertBefore(styleElem, head.firstChild);
+
+ // Set up the placeholders
+ for (i = 0, len = inputs.length + textareas.length; i < len; i++) {
+ elem = i < inputs.length ? inputs[i] : textareas[i - inputs.length];
+
+ // Get the value of the placeholder attribute, if any. IE10 emulating IE7 fails with getAttribute, hence the use of the attributes node
+ placeholder = elem.attributes.placeholder;
+ if (placeholder) {
+
+ // IE returns an empty object instead of undefined if the attribute is not present
+ placeholder = placeholder.nodeValue;
+
+ // Only apply the polyfill if this element is of a type that supports placeholders, and has a placeholder attribute with a non-empty value
+ if (placeholder && Utils.inArray(validTypes, elem.type)) {
+ newElement(elem);
+ }
+ }
+ }
+
+ // If enabled, the polyfill will repeatedly check for changed/added elements and apply to those as well
+ timer = setInterval(function () {
+ for (i = 0, len = inputs.length + textareas.length; i < len; i++) {
+ elem = i < inputs.length ? inputs[i] : textareas[i - inputs.length];
+
+ // Only apply the polyfill if this element is of a type that supports placeholders, and has a placeholder attribute with a non-empty value
+ placeholder = elem.attributes.placeholder;
+ if (placeholder) {
+ placeholder = placeholder.nodeValue;
+ if (placeholder && Utils.inArray(validTypes, elem.type)) {
+
+ // If the element hasn't had event handlers bound to it then add them
+ if (!elem.getAttribute(ATTR_EVENTS_BOUND)) {
+ newElement(elem);
+ }
+
+ // If the placeholder value has changed or not been initialised yet we need to update the display
+ if (placeholder !== elem.getAttribute(ATTR_CURRENT_VAL) || (elem.type === "password" && !elem.getAttribute(ATTR_INPUT_TYPE))) {
+
+ // Attempt to change the type of password inputs (fails in IE < 9)
+ if (elem.type === "password" && !elem.getAttribute(ATTR_INPUT_TYPE) && Utils.changeType(elem, "text")) {
+ elem.setAttribute(ATTR_INPUT_TYPE, "password");
+ }
+
+ // If the placeholder value has changed and the placeholder is currently on display we need to change it
+ if (elem.value === elem.getAttribute(ATTR_CURRENT_VAL)) {
+ elem.value = placeholder;
+ }
+
+ // Keep a reference to the current placeholder value in case it changes via another script
+ elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
+ }
+ }
+ } else if (elem.getAttribute(ATTR_ACTIVE)) {
+ hidePlaceholder(elem);
+ elem.removeAttribute(ATTR_CURRENT_VAL);
+ }
+ }
+
+ // If live updates are not enabled cancel the timer
+ if (!liveUpdates) {
+ clearInterval(timer);
+ }
+ }, 100);
+ }
+
+ Utils.addEventListener(global, "beforeunload", function () {
+ Placeholders.disable();
+ });
+
+ // Expose public methods
+ Placeholders.disable = Placeholders.nativeSupport ? noop : disablePlaceholders;
+ Placeholders.enable = Placeholders.nativeSupport ? noop : enablePlaceholders;
+
+}(this));
diff --git a/core/lostpassword/templates/lostpassword.php b/core/lostpassword/templates/lostpassword.php
index d0fed38ee2..fdfa32344e 100644
--- a/core/lostpassword/templates/lostpassword.php
+++ b/core/lostpassword/templates/lostpassword.php
@@ -16,8 +16,10 @@ OCP\Util::addStyle('lostpassword', 'lostpassword');
t('You will receive a link to reset your password via Email.')); ?>