Removing HideFieldLabels code

This commit is contained in:
michael3dgoo 2017-05-08 15:48:33 +09:30
parent c38d531161
commit ada8dac4b1
20 changed files with 9 additions and 610 deletions

View File

@ -170,7 +170,6 @@ class UserForm extends Form
$attrs['class'] = $attrs['class'] . ' userform';
$attrs['data-livevalidation'] = (bool)$this->controller->EnableLiveValidation;
$attrs['data-toperrors'] = (bool)$this->controller->DisplayErrorMessagesAtTop;
$attrs['data-hidefieldlabels'] = (bool)$this->controller->HideFieldLabels;
return $attrs;
}

View File

@ -68,7 +68,6 @@ class UserDefinedForm extends Page
"ShowClearButton" => "Boolean",
'DisableSaveSubmissions' => 'Boolean',
'EnableLiveValidation' => 'Boolean',
'HideFieldLabels' => 'Boolean',
'DisplayErrorMessagesAtTop' => 'Boolean',
'DisableAuthenicatedFinishAction' => 'Boolean',
'DisableCsrfSecurityToken' => 'Boolean'
@ -313,7 +312,6 @@ SQL;
new TextField("ClearButtonText", _t('UserDefinedForm.TEXTONCLEAR', 'Text on clear button:'), $clear),
new CheckboxField("ShowClearButton", _t('UserDefinedForm.SHOWCLEARFORM', 'Show Clear Form Button'), $this->ShowClearButton),
new CheckboxField("EnableLiveValidation", _t('UserDefinedForm.ENABLELIVEVALIDATION', 'Enable live validation')),
new CheckboxField("HideFieldLabels", _t('UserDefinedForm.HIDEFIELDLABELS', 'Hide field labels')),
new CheckboxField("DisplayErrorMessagesAtTop", _t('UserDefinedForm.DISPLAYERRORMESSAGESATTOP', 'Display error messages above the form?')),
new CheckboxField('DisableCsrfSecurityToken', _t('UserDefinedForm.DISABLECSRFSECURITYTOKEN', 'Disable CSRF Token')),
new CheckboxField('DisableAuthenicatedFinishAction', _t('UserDefinedForm.DISABLEAUTHENICATEDFINISHACTION', 'Disable Authentication on finish action'))
@ -404,9 +402,6 @@ class UserDefinedForm_Controller extends Page_Controller
Requirements::javascript(
USERFORMS_DIR . "/thirdparty/jquery-validate/localization/methods_{$lang}.min.js"
);
if ($this->HideFieldLabels) {
Requirements::javascript(USERFORMS_DIR . '/thirdparty/Placeholders.js/Placeholders.min.js');
}
// Bind a confirmation message when navigating away from a partially completed form.
if ($page::config()->enable_are_you_sure) {

View File

@ -389,10 +389,10 @@ jQuery(function ($) {
var self = this;
this.$el = element instanceof jQuery ? element : $(element);
// Find button for this step
this.$elButton = $(".step-button-wrapper[data-for='" + this.$el.prop('id') + "']");
// Has the step been viewed by the user?
this.viewed = false;
@ -436,10 +436,10 @@ jQuery(function ($) {
return this;
}
/**
* Determine if this step is conditionally disabled
*
*
* @returns {Boolean}
*/
FormStep.prototype.conditionallyHidden = function(){
@ -502,7 +502,7 @@ jQuery(function ($) {
buttonOffset = -1 * ($button.innerWidth() / 2);
$button.css({left: leftPercent, marginLeft: buttonOffset});
// First and last buttons are kept within userform-progress container
if (index === self.$jsAlign.length - 1) {
$button.css({marginLeft: buttonOffset * 2});
@ -621,11 +621,11 @@ jQuery(function ($) {
// Update the "Prev" button.
this.$el.find('.step-button-prev')[stepID === 0 ? 'hide' : 'show']();
// Find last step, skipping hidden ones
for(i = numberOfSteps - 1; i >= 0; i--) {
lastStep = userform.steps[i];
// Skip if step is hidden
if(lastStep.conditionallyHidden()) {
continue;
@ -636,7 +636,7 @@ jQuery(function ($) {
// Update the "Actions".
this.$el.find('.Actions')[stepID >= i ? 'show' : 'hide']();
// Stop processing last step
break;
}
@ -658,7 +658,6 @@ jQuery(function ($) {
CONSTANTS.ENABLE_LIVE_VALIDATION = $userform.data('livevalidation') !== void 0;
CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP = $userform.data('toperrors') !== void 0;
CONSTANTS.HIDE_FIELD_LABELS = $userform.data('hidefieldlabels') !== void 0;
// Extend the default validation options with conditional options
// that are set by the user in the CMS.
@ -705,7 +704,7 @@ jQuery(function ($) {
});
userform.setCurrentStep(userform.steps[0]);
// Initialise actions and progressbar
progressBar = new ProgressBar($('#userform-progress'));
formActions = new FormActions($('#step-navigation'));

View File

@ -133,7 +133,6 @@ ar:
EmailFromContent: 'عنوان خانة المرسل يسمح لك بتعيين من الذي يأتي منه البريد الالكتروني. في معظم الخوادم هذا سوف يحتاج إلى أن يعين إلى عنوان بريد إلكتروني على نفس اسم مجال موقع الويب الخاص بك. على سبيل المثال على yoursite.com عنوان خانة المرسل قد يحتاج إلى أن يكون something@yoursite.com. يمكنك مع ذلك، تعيين أي عنوان بريد إلكتروني ترغب كعنوان للرد.'
FORM: نموذج
FROMADDRESS: 'ارسل بريد إلكتروني من'
HIDEFIELDLABELS: 'إخفاء تسميات الحقول'
HIDEFORMDATA: 'إخفاء بيانات النموذج من البريد الإلكتروني؟'
ONCOMPLETELABEL: 'اعرض عند الاكتمال'
ORSELECTAFIELDTOUSEASFROM: '.. أو تحديد حقل لاستخدامه كعنوان للرد'

View File

@ -153,7 +153,6 @@ de_DE:
FIELDS: Felder
FORM: Formular
FROMADDRESS: 'E-Mail versendet von'
HIDEFIELDLABELS: 'Feldbezeichnungen verbergen'
HIDEFORMDATA: 'Formulardaten in E-Mail nicht anzeigen'
ONCOMPLETELABEL: 'Nach Vervollständigung anzeigen'
ORSELECTAFIELDTOUSEASFROM: '.. oder wähle ein Formularfeld als Absenderadresse'

View File

@ -196,7 +196,6 @@ en:
FORM: Form
FROMADDRESS: 'Send email from'
FileUploadWarning: 'Files uploaded through this field could be publicly accessible if the exact URL is known'
HIDEFIELDLABELS: 'Hide field labels'
HIDEFORMDATA: 'Hide form data from email?'
NORECIPIENTS: 'Warning: You have not configured any recipients. Form submissions may be missed.'
ONCOMPLETELABEL: 'Show on completion'

View File

@ -191,7 +191,6 @@ eo:
FORM: Formularo
FROMADDRESS: 'Sendi retpoŝton de'
FileUploadWarning: 'Dosieroj alŝutitaj per ĉi tiu kampo eble estos alireblaj se la ĝusta URL estas sciata.'
HIDEFIELDLABELS: 'Kaŝi kampajn etikedojn'
HIDEFORMDATA: 'Ĉu kaŝi formularajn datumojn de retpoŝto?'
NORECIPIENTS: 'Averto: Vi ne agordis ricevantojn. Eble mankos sendoj de formularoj.'
ONCOMPLETELABEL: 'Vidigi je kompletigo'

View File

@ -148,7 +148,6 @@ es_ES:
EmailFromContent: 'La dirección desde permite establecer de quien viene el email. En la mayoría de los servidores esto se necesitará establecer a una dirección de email del mismo nombre de dominio que su sitio. Por ejemplo, en susitio.com la dirección desde puede ser algo como loquesea@susitio.com. Sin embargo, Ud puede establecer cualquier dirección de email que desee como dirección del remitente.'
FORM: Formulario
FROMADDRESS: 'Enviar este mail desde'
HIDEFIELDLABELS: 'Ocultar rótulos de campo'
HIDEFORMDATA: 'Esconder los datos enviados en el mail'
ONCOMPLETELABEL: 'Mostrar al terminar'
ORSELECTAFIELDTOUSEASFROM: '.. o seleccione un campo del formulario para utilizar como dirección del remitente'

View File

@ -191,7 +191,6 @@ fi_FI:
FORM: Lomake
FROMADDRESS: 'Lähetä sähköposti osoitteesta'
FileUploadWarning: 'Tällä kentällä lähetetyt tiedostot ovat avattavissa julkisesti, mikäli tarkka verkko-osoite on käyttäjän tiedossa.'
HIDEFIELDLABELS: 'Piilota kenttien nimikkeet'
HIDEFORMDATA: 'Piilota lomakedata sähköpostista'
NORECIPIENTS: 'Varoitus: et ole lisännyt yhtään vastaanottajaa. Lähetetyt lomakkeet voivat jäädä näkemättä.'
ONCOMPLETELABEL: 'Näytä valmistuessa'

View File

@ -193,7 +193,6 @@ it:
FORM: Modulo
FROMADDRESS: 'Manda e-mail da'
FileUploadWarning: 'I files caricati attraverso questo campo potrebbero essere pubblicamente accessibili se si conosce la loro URL esatta'
HIDEFIELDLABELS: 'Nascondi etichette dei campi'
HIDEFORMDATA: 'Nascondi dati del modulo nell''email?'
NORECIPIENTS: 'Attenzione: Non hai configurato nessun destinatario. Potresti perderti delle risposte al modulo.'
ONCOMPLETELABEL: 'Mostra al completamento'

View File

@ -133,7 +133,6 @@ mi:
EmailFromContent: 'Ka taea koe mā te wāhitau mai te tautuhi i te tangata nā wai te īmēra. Kei te nuinga o ngā tūmau me tautuhi tēnei ki tētahi wāhitau īmēra i te ingoa rohe e ōrite ana ki tō pae. Hei tauira kei yoursite.com me noho te wāhitau mai ko something@yoursite.com. Heoi ka taea te tautuhi i tāu e hiahia ai hei wāhitau whakautu ki.'
FORM: Puka
FROMADDRESS: 'Tuku īmēra mai'
HIDEFIELDLABELS: 'Hunaia ngā tapanga āpure'
HIDEFORMDATA: 'Me huna te raraunga puka i te īmēra?'
ONCOMPLETELABEL: 'Whakaaturia ina oti'
ORSELECTAFIELDTOUSEASFROM: '.. ka tīpako rānei i tētahi āpure hei whakamahi hei wāhitau whakautu ki'

View File

@ -134,7 +134,6 @@ nb_NO:
EmailFromContent: 'Skjemaadressen tillater deg å vis hvem melding kommer fra. På de fleste servere må denne e-post adressen være den samme som doment for din side. For eksempel om du har domene din-side.no, må e-post adressen være noen@din-side.no.'
FORM: Skjema
FROMADDRESS: 'Sendt e-post fra'
HIDEFIELDLABELS: 'Skjul overskrifter'
HIDEFORMDATA: 'Skjul skjemadata fra e-post'
ONCOMPLETELABEL: 'Vis ved ferdigstillelse'
ORSELECTAFIELDTOUSEASFROM: '...eller velg et felt til å bruke som "svar til"-adresse'

View File

@ -140,7 +140,6 @@ nl_NL:
EmailFromContent: 'Met het vanaf adres kunt u instellen waar het ingediende formulier vandaag komt. Op de meeste servers dien je een email in te vullen van hetzelfde domein als deze website. Bijvoorbeeld op jouwwebsite.nl dan dien je het volgende adres in te stellen iets@jouwwebsite.nl. Echter kunt u bij antwoorden op ieder email adres invullen.'
FORM: Formulier
FROMADDRESS: 'Email verzonden vanaf'
HIDEFIELDLABELS: 'Verberg veld labels'
HIDEFORMDATA: 'Verberg formulier gegevens in email?'
ONCOMPLETELABEL: 'Bericht na succesvol verzonden'
ORSELECTAFIELDTOUSEASFROM: '.. of selecteer een veld om te gebruiken als antwoorden op'

View File

@ -147,7 +147,6 @@ pl_PL:
EmailFromContent: 'The from address allows you to set who the email comes from. On most servers this will need to be set to an email address on the same domain name as your site. For example on yoursite.com the from address may need to be something@yoursite.com. You can however, set any email address you wish as the reply to address.'
FORM: Formularz
FROMADDRESS: 'Send Email From'
HIDEFIELDLABELS: 'Ukryj etykiety pola'
HIDEFORMDATA: 'Hide Form Data from Email'
ONCOMPLETELABEL: 'Pokaż po zakończeniu'
ORSELECTAFIELDTOUSEASFROM: '.. or select a field to use as reply to address'

View File

@ -191,7 +191,6 @@ sk:
FORM: Formulár
FROMADDRESS: 'E-mail odosielateľa'
FileUploadWarning: 'Súbory nahraté pomocou tohto políčka môžu byť verejné prístupné, pokiaľ je známa presná URL adresa.'
HIDEFIELDLABELS: 'Skyť popisky (menovky) polí?'
HIDEFORMDATA: 'Skryť dáta z e-mailu?'
NORECIPIENTS: 'Varovanie: Nemáte pridaných žiadnych príjemcov. Podané formuláre môžu chýbať.'
ONCOMPLETELABEL: 'Správa po odoslaní formulára'

View File

@ -146,7 +146,6 @@ sv:
EmailFromContent: 'Från-adressen låter dig ställa in varifrån e-postmeddelandet skickas. På de flesta servrar måste adressen ha samma domännamn som din sajt. Till exempel på yoursite.com så måste adressen vara something@yoursite.com. Det är däremot möjligt att lägga valfri e-postadress under "E-postadress att svara till". '
FORM: Formulär
FROMADDRESS: 'E-postadress att skicka formulär från'
HIDEFIELDLABELS: 'Göm fältetiketter'
HIDEFORMDATA: 'Göm formulärdata från e-post?'
ONCOMPLETELABEL: 'Visa vid slutförande'
ORSELECTAFIELDTOUSEASFROM: '.. eller välj ett fält att använda som svarsadress'

View File

@ -133,7 +133,6 @@ zh:
EmailFromContent: '表格地址允许您设置电子邮件的发送人。在大多数服务器上这必须要设置成域名与您的站点域名一致的电子邮件地址。例如在 yoursite.com 上,发送人的电子邮件地址必须为 something@yoursite.com。但是您可以随意设置回复的电子邮件地址。'
FORM: 表格
FROMADDRESS: 发送人电子邮件
HIDEFIELDLABELS: 隐藏字段标签
HIDEFORMDATA: 从电子邮件中隐藏表格数据?
ONCOMPLETELABEL: 完成时显示
ORSELECTAFIELDTOUSEASFROM: '.. 或选择某字段作为回复地址'

View File

@ -1,470 +0,0 @@
/*
* 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.
*
* -----------------------------------------------------------------------------------------------------------------------------------------------------
*
* Placeholders is a simple polyfill for the HTML5 "placeholder" attribute. The placeholder attribute can be used on input elements of certain types
* and provides a short hint (such as a sample value or a brief description) intended to aid the user with data entry. This polyfill has been tested
* and functions correctly in Internet Explorer 6 and above, Firefox 3.6 and above, Safari 3.2 and above, Opera 9 and above and Chrome 16 and above.
* The script will be tested in further browsers in due course and the above list edited accordingly.
*
* User agents should display the value of the placeholder attribute when the element's value is the empty string and the element does not
* have focus. The user agents that have implemented support for this attribute all display the placeholder inside the element, as if it were
* the element's value, in a light grey colour to differentiate between placeholder text and value text.
*
* The Placeholders polyfill attempts to replicate the functionality of compliant user agents so that non-compliant user agents will still function
* as expected when faced with a "placeholder" attribute.
*
* The script is unobtrusive and will only apply if the placeholder attribute is not supported by the user agent in which it is running. To use a placeholder
* simply add the "placeholder" attribute to a supporting input element:
*
* <input type="text" placeholder="Placeholder text">
*
* To get this placeholder to function in non-supporting user agents simply call the init method when appropriate (the DOM must be ready for manipulation,
* unless the `live` option is true):
*
* Placeholders.init();
*
* The init method accepts one argument, `options`. It's an object that contains settings to control the behaviour of the polyfill. Currently, only 2 options
* are available:
*
* `live` - If truthy, the polyfill will apply to all supported input elements now and in the future, and dynamic
* changes to the placeholder attribute value will be reflected. If falsy, the polyfill will only apply to those elements with a placeholder attribute
* value in the DOM at the time the method is executed. If the live option is not used, the placeholders can be refreshed manually by calling `Placeholders.refresh()`.
*
* `hideOnFocus` - If truthy, the placeholder text will not disappear when the field receives focus. This option is relatively new to the spec, but is
* starting to be implemented in browsers (e.g. Safari, and now Chrome). This option is set to `true` by default, since that's where browsers seem to be heading.
*/
/*jslint browser: true */
var Placeholders = (function () {
"use strict";
/* List of input types that support the placeholder attribute. We only want to modify input elements with one of these types.
* WARNING: If an input type is not supported by a browser, the browser will choose the default type (text) and the placeholder shim will
* apply */
var validTypes = [
"text",
"search",
"url",
"tel",
"email",
"password",
"number",
"textarea"
],
//Default options, can be overridden by passing object to `init`
settings = {
live: false,
hideOnFocus: false,
className: 'placeholderspolyfill', // placeholder class name to apply to form fields
textColor: '#999', // default placeholder text color
styleImportant: true // add !important flag to placeholder style
},
//Keycodes that are not allowed when the placeholder is visible and `hideOnFocus` is `false`
badKeys = [37, 38, 39, 40],
//Used if `live` options is `true`
interval,
//Stores the input value on keydown (used when `hideOnFocus` option is `false`)
valueKeyDown,
// polyfill class name regexp
classNameRegExp = new RegExp('\\b' + settings.className + '\\b');
// The cursorToStart function attempts to jump the cursor to before the first character of input
function cursorToStart(elem) {
var range;
if (elem.createTextRange) {
range = elem.createTextRange();
range.move("character", 0);
range.select();
} else if (elem.selectionStart) {
elem.focus();
elem.setSelectionRange(0, 0);
}
}
/* The focusHandler function is executed when input elements with placeholder attributes receive a focus event. If necessary, the placeholder
* and its associated styles are removed from the element. Must be bound to an element. */
function focusHandler() {
var type;
//If the placeholder is currently visible, remove it and its associated styles
if (this.value === this.getAttribute("placeholder")) {
if (!settings.hideOnFocus) {
cursorToStart(this);
} else {
/* Remove the placeholder class name. Use a regular expression to ensure the string being searched for is a complete word, and not part of a longer
* string, on the off-chance a class name including that string also exists on the element */
this.className = this.className.replace(classNameRegExp, "");
this.value = "";
// Check if we need to switch the input type (this is the case if it's a password input)
type = this.getAttribute("data-placeholdertype");
if (type) {
this.type = type;
}
}
}
}
/* The blurHandler function is executed when input elements with placeholder attributes receive a blur event. If necessary, the placeholder
* and its associated styles are applied to the element. Must be bound to an element. */
function blurHandler() {
var type;
//If the input value is the empty string, apply the placeholder and its associated styles
if (this.value === "") {
this.className = this.className + " " + settings.className;
this.value = this.getAttribute("placeholder");
// Check if we need to switch the input type (this is the case if it's a password input)
type = this.getAttribute("data-placeholdertype");
if (type) {
this.type = "text";
}
}
}
/* The submitHandler function is executed when the containing form, if any, of a given input element is submitted. If necessary, placeholders on any
* input element descendants of the form are removed so that the placeholder value is not submitted as the element value. */
function submitHandler() {
var inputs = this.getElementsByTagName("input"),
textareas = this.getElementsByTagName("textarea"),
numInputs = inputs.length,
num = numInputs + textareas.length,
element,
placeholder,
i;
//Iterate over all descendant input elements and remove placeholder if necessary
for (i = 0; i < num; i += 1) {
element = (i < numInputs) ? inputs[i] : textareas[i - numInputs];
placeholder = element.getAttribute("placeholder");
//If the value of the input is equal to the value of the placeholder attribute we need to clear the value
if (element.value === placeholder) {
element.value = "";
}
}
}
/* The keydownHandler function is executed when the input elements with placeholder attributes receive a keydown event. It simply stores the current
* value of the input (so we can kind-of simulate the poorly-supported `input` event). Used when `hideOnFocus` option is `false`. Must be bound to an element. */
function keydownHandler(event) {
valueKeyDown = this.value;
//Prevent the use of the arrow keys (try to keep the cursor before the placeholder)
return !(valueKeyDown === this.getAttribute("placeholder") && badKeys.indexOf(event.keyCode) > -1);
}
/* The keyupHandler function is executed when the input elements with placeholder attributes receive a keyup event. It kind-of simulates the native but
* poorly-supported `input` event by checking if the key press has changed the value of the element. Used when `hideOnFocus` option is `false`. Must be bound to an element. */
function keyupHandler() {
var type;
if (this.value !== valueKeyDown) {
// Remove the placeholder
this.className = this.className.replace(classNameRegExp, "");
this.value = this.value.replace(this.getAttribute("placeholder"), "");
// Check if we need to switch the input type (this is the case if it's a password input)
type = this.getAttribute("data-placeholdertype");
if (type) {
this.type = type;
}
}
if (this.value === "") {
blurHandler.call(this);
cursorToStart(this);
}
}
//The addEventListener function binds an event handler with the context of an element to a specific event on that element. Handles old-IE and modern browsers.
function addEventListener(element, event, fn) {
if (element.addEventListener) {
return element.addEventListener(event, fn.bind(element), false);
}
if (element.attachEvent) {
return element.attachEvent("on" + event, fn.bind(element));
}
}
//The addEventListeners function binds the appropriate (depending on options) event listeners to the specified input or textarea element.
function addEventListeners(element) {
if (!settings.hideOnFocus) {
addEventListener(element, "keydown", keydownHandler);
addEventListener(element, "keyup", keyupHandler);
}
addEventListener(element, "focus", focusHandler);
addEventListener(element, "blur", blurHandler);
}
/* The updatePlaceholders function checks all input and textarea elements and updates the placeholder if necessary. Elements that have been added to the DOM since the call to
* createPlaceholders will not function correctly until this function is executed. The same goes for any existing elements whose placeholder property has been changed (via
* element.setAttribute("placeholder", "new") for example) */
function updatePlaceholders() {
//Declare variables, get references to all input and textarea elements
var inputs = document.getElementsByTagName("input"),
textareas = document.getElementsByTagName("textarea"),
numInputs = inputs.length,
num = numInputs + textareas.length,
i,
form,
element,
oldPlaceholder,
newPlaceholder;
//Iterate over all input and textarea elements and apply/update the placeholder polyfill if necessary
for (i = 0; i < num; i += 1) {
//Get the next element from either the input NodeList or the textarea NodeList, depending on how many elements we've already looped through
element = (i < numInputs) ? inputs[i] : textareas[i - numInputs];
//Get the value of the placeholder attribute
newPlaceholder = element.getAttribute("placeholder");
//Check whether the current input element is of a type that supports the placeholder attribute
if (validTypes.indexOf(element.type) > -1) {
//The input type does support the placeholder attribute. Check whether the placeholder attribute has a value
if (newPlaceholder) {
//The placeholder attribute has a value. Get the value of the current placeholder data-* attribute
oldPlaceholder = element.getAttribute("data-currentplaceholder");
//Check whether the placeholder attribute value has changed
if (newPlaceholder !== oldPlaceholder) {
//The placeholder attribute value has changed so we need to update. Check whether the placeholder should currently be visible.
if (element.value === oldPlaceholder || element.value === newPlaceholder || !element.value) {
//The placeholder should be visible so change the element value to that of the placeholder attribute and set placeholder styles
element.value = newPlaceholder;
element.className = element.className + " " + settings.className;
}
//If the current placeholder data-* attribute has no value the element wasn't present in the DOM when event handlers were bound, so bind them now
if (!oldPlaceholder) {
//If the element has a containing form bind to the submit event so we can prevent placeholder values being submitted as actual values
if (element.form) {
//Get a reference to the containing form element (if present)
form = element.form;
//The placeholdersubmit data-* attribute is set if this form has already been dealt with
if (!form.getAttribute("data-placeholdersubmit")) {
//The placeholdersubmit attribute wasn't set, so attach a submit event handler
addEventListener(form, "submit", submitHandler);
//Set the placeholdersubmit attribute so we don't repeatedly bind event handlers to this form element
form.setAttribute("data-placeholdersubmit", "true");
}
}
addEventListeners(element);
}
//Update the value of the current placeholder data-* attribute to reflect the new placeholder value
element.setAttribute("data-currentplaceholder", newPlaceholder);
}
}
}
}
}
/* The createPlaceholders function checks all input and textarea elements currently in the DOM for the placeholder attribute. If the attribute
* is present, and the element is of a type (e.g. text) that allows the placeholder attribute, it attaches the appropriate event listeners
* to the element and if necessary sets its value to that of the placeholder attribute */
function createPlaceholders() {
//Declare variables and get references to all input and textarea elements
var inputs = document.getElementsByTagName("input"),
textareas = document.getElementsByTagName("textarea"),
numInputs = inputs.length,
num = numInputs + textareas.length,
i,
element,
form,
placeholder;
//Iterate over all input elements and apply placeholder polyfill if necessary
for (i = 0; i < num; i += 1) {
//Get the next element from either the input NodeList or the textarea NodeList, depending on how many elements we've already looped through
element = (i < numInputs) ? inputs[i] : textareas[i - numInputs];
//Get the value of the placeholder attribute
placeholder = element.getAttribute("placeholder");
//Check whether or not the current element is of a type that allows the placeholder attribute
if (validTypes.indexOf(element.type) > -1) {
//The input type does support placeholders. Check that the placeholder attribute has been given a value
if (placeholder) {
// If the element type is "password", attempt to change it to "text" so we can display the placeholder value in plain text
if (element.type === "password") {
// The `type` property is read-only in IE < 9, so in those cases we just move on. The placeholder will be displayed masked
try {
element.type = "text";
element.setAttribute("data-placeholdertype", "password");
} catch (e) {}
}
//The placeholder attribute has a value. Keep track of the current placeholder value in an HTML5 data-* attribute
element.setAttribute("data-currentplaceholder", placeholder);
//If the value of the element is the empty string set the value to that of the placeholder attribute and apply the placeholder styles
if (element.value === "" || element.value === placeholder) {
element.className = element.className + " " + settings.className;
element.value = placeholder;
}
//If the element has a containing form bind to the submit event so we can prevent placeholder values being submitted as actual values
if (element.form) {
//Get a reference to the containing form element (if present)
form = element.form;
//The placeholdersubmit data-* attribute is set if this form has already been dealt with
if (!form.getAttribute("data-placeholdersubmit")) {
//The placeholdersubmit attribute wasn't set, so attach a submit event handler
addEventListener(form, "submit", submitHandler);
//Set the placeholdersubmit attribute so we don't repeatedly bind event handlers to this form element
form.setAttribute("data-placeholdersubmit", "true");
}
}
//Attach event listeners to this element
addEventListeners(element);
}
}
}
}
/* The init function checks whether or not we need to polyfill the placeholder functionality. If we do, it sets up various things
* needed throughout the script and then calls createPlaceholders to setup initial placeholders */
function init(opts) {
//Create an input element to test for the presence of the placeholder property. If the placeholder property exists, stop.
var test = document.createElement("input"),
opt,
styleElem,
styleRules,
i,
j;
//Test input element for presence of placeholder property. If it doesn't exist, the browser does not support HTML5 placeholders
if (typeof test.placeholder === "undefined") {
//HTML5 placeholder attribute not supported.
//Set the options (or use defaults)
for (opt in opts) {
if (opts.hasOwnProperty(opt)) {
settings[opt] = opts[opt];
}
}
//Create style element for placeholder styles
styleElem = document.createElement("style");
styleElem.type = "text/css";
//Create style rules as text node
var importantValue = (settings.styleImportant) ? "!important" : "";
styleRules = document.createTextNode("." + settings.className + " { color:" + settings.textColor + importantValue + "; }");
//Append style rules to newly created stylesheet
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = styleRules.nodeValue;
} else {
styleElem.appendChild(styleRules);
}
//Append new style element to the head
document.getElementsByTagName("head")[0].appendChild(styleElem);
//We use Array.prototype.indexOf later, so make sure it exists
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, start) {
for (i = (start || 0), j = this.length; i < j; i += 1) {
if (this[i] === obj) { return i; }
}
return -1;
};
}
/* We use Function.prototype.bind later, so make sure it exists. This is the MDN implementation, slightly modified to pass JSLint. See
* https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind */
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
FNop = function () {},
fBound = function () {
return fToBind.apply(this instanceof FNop
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
FNop.prototype = this.prototype;
fBound.prototype = new FNop();
return fBound;
};
}
//Create placeholders for input elements currently part of the DOM
createPlaceholders();
/* If the `live` option is truthy, call updatePlaceholders repeatedly to keep up to date with any DOM changes.
* We use an interval over events such as DOMAttrModified (which are used in some other implementations of the placeholder attribute)
* since the DOM level 2 mutation events are deprecated in the level 3 spec. */
if (settings.live) {
interval = setInterval(updatePlaceholders, 100);
}
//Placeholder attribute was successfully polyfilled :)
return true;
}
//Placeholder attribute already supported by browser :)
return false;
}
//Expose public methods
return {
init: init,
refresh: updatePlaceholders
};
}());

View File

@ -1,11 +0,0 @@
var Placeholders=function(){var validTypes=["text","search","url","tel","email","password","number","textarea"],settings={live:false,hideOnFocus:false,className:"placeholderspolyfill",textColor:"#999",styleImportant:true},badKeys=[37,38,39,40],interval,valueKeyDown,classNameRegExp=new RegExp("\\b"+settings.className+"\\b");function cursorToStart(elem){var range;if(elem.createTextRange){range=elem.createTextRange();range.move("character",0);range.select()}else if(elem.selectionStart){elem.focus();
elem.setSelectionRange(0,0)}}function focusHandler(){var type;if(this.value===this.getAttribute("placeholder"))if(!settings.hideOnFocus)cursorToStart(this);else{this.className=this.className.replace(classNameRegExp,"");this.value="";type=this.getAttribute("data-placeholdertype");if(type)this.type=type}}function blurHandler(){var type;if(this.value===""){this.className=this.className+" "+settings.className;this.value=this.getAttribute("placeholder");type=this.getAttribute("data-placeholdertype");if(type)this.type=
"text"}}function submitHandler(){var inputs=this.getElementsByTagName("input"),textareas=this.getElementsByTagName("textarea"),numInputs=inputs.length,num=numInputs+textareas.length,element,placeholder,i;for(i=0;i<num;i+=1){element=i<numInputs?inputs[i]:textareas[i-numInputs];placeholder=element.getAttribute("placeholder");if(element.value===placeholder)element.value=""}}function keydownHandler(event){valueKeyDown=this.value;return!(valueKeyDown===this.getAttribute("placeholder")&&badKeys.indexOf(event.keyCode)>
-1)}function keyupHandler(){var type;if(this.value!==valueKeyDown){this.className=this.className.replace(classNameRegExp,"");this.value=this.value.replace(this.getAttribute("placeholder"),"");type=this.getAttribute("data-placeholdertype");if(type)this.type=type}if(this.value===""){blurHandler.call(this);cursorToStart(this)}}function addEventListener(element,event,fn){if(element.addEventListener)return element.addEventListener(event,fn.bind(element),false);if(element.attachEvent)return element.attachEvent("on"+
event,fn.bind(element))}function addEventListeners(element){if(!settings.hideOnFocus){addEventListener(element,"keydown",keydownHandler);addEventListener(element,"keyup",keyupHandler)}addEventListener(element,"focus",focusHandler);addEventListener(element,"blur",blurHandler)}function updatePlaceholders(){var inputs=document.getElementsByTagName("input"),textareas=document.getElementsByTagName("textarea"),numInputs=inputs.length,num=numInputs+textareas.length,i,form,element,oldPlaceholder,newPlaceholder;
for(i=0;i<num;i+=1){element=i<numInputs?inputs[i]:textareas[i-numInputs];newPlaceholder=element.getAttribute("placeholder");if(validTypes.indexOf(element.type)>-1)if(newPlaceholder){oldPlaceholder=element.getAttribute("data-currentplaceholder");if(newPlaceholder!==oldPlaceholder){if(element.value===oldPlaceholder||element.value===newPlaceholder||!element.value){element.value=newPlaceholder;element.className=element.className+" "+settings.className}if(!oldPlaceholder){if(element.form){form=element.form;
if(!form.getAttribute("data-placeholdersubmit")){addEventListener(form,"submit",submitHandler);form.setAttribute("data-placeholdersubmit","true")}}addEventListeners(element)}element.setAttribute("data-currentplaceholder",newPlaceholder)}}}}function createPlaceholders(){var inputs=document.getElementsByTagName("input"),textareas=document.getElementsByTagName("textarea"),numInputs=inputs.length,num=numInputs+textareas.length,i,element,form,placeholder;for(i=0;i<num;i+=1){element=i<numInputs?inputs[i]:
textareas[i-numInputs];placeholder=element.getAttribute("placeholder");if(validTypes.indexOf(element.type)>-1)if(placeholder){if(element.type==="password")try{element.type="text";element.setAttribute("data-placeholdertype","password")}catch(e){}element.setAttribute("data-currentplaceholder",placeholder);if(element.value===""||element.value===placeholder){element.className=element.className+" "+settings.className;element.value=placeholder}if(element.form){form=element.form;if(!form.getAttribute("data-placeholdersubmit")){addEventListener(form,
"submit",submitHandler);form.setAttribute("data-placeholdersubmit","true")}}addEventListeners(element)}}}function init(opts){var test=document.createElement("input"),opt,styleElem,styleRules,i,j;if(typeof test.placeholder==="undefined"){for(opt in opts)if(opts.hasOwnProperty(opt))settings[opt]=opts[opt];styleElem=document.createElement("style");styleElem.type="text/css";var importantValue=settings.styleImportant?"!important":"";styleRules=document.createTextNode("."+settings.className+" { color:"+
settings.textColor+importantValue+"; }");if(styleElem.styleSheet)styleElem.styleSheet.cssText=styleRules.nodeValue;else styleElem.appendChild(styleRules);document.getElementsByTagName("head")[0].appendChild(styleElem);if(!Array.prototype.indexOf)Array.prototype.indexOf=function(obj,start){for(i=start||0,j=this.length;i<j;i+=1)if(this[i]===obj)return i;return-1};if(!Function.prototype.bind)Function.prototype.bind=function(oThis){if(typeof this!=="function")throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
var aArgs=Array.prototype.slice.call(arguments,1),fToBind=this,FNop=function(){},fBound=function(){return fToBind.apply(this instanceof FNop?this:oThis,aArgs.concat(Array.prototype.slice.call(arguments)))};FNop.prototype=this.prototype;fBound.prototype=new FNop;return fBound};createPlaceholders();if(settings.live)interval=setInterval(updatePlaceholders,100);return true}return false}return{init:init,refresh:updatePlaceholders}}();

View File

@ -1,99 +0,0 @@
#Placeholders.js - An HTML5 placeholder attribute polyfill
Placeholders.js is a polyfill (or shim, or whatever you like to call it) for the HTML5 placeholder attribute, as defined in the <a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-placeholder">HTML5 draft specification</a>. Placeholder attributes are valid on `input` elements of various types and `textarea` elements.
Placeholders.js is licensed under the [MIT License](http://en.wikipedia.org/wiki/MIT_License). See the unminified file for the full license text.
##Features
- Works on both **`input` and `textarea` elements**
- Works by finding `placeholder` attributes on elements, so there's no need to call it repeatedly for every element. Just add the placeholder attribute **as if it were supported natively**.
- **Simulates native styles** for the placeholders but keeps any custom styles you've defined on the elements
- Placeholder values are **not submitted as form data** if the element is part of a form
- Works for elements that are **added to the DOM after the page has loaded**, and also for elements whose placeholder value changes after the page has loaded
- Works properly for `input` elements of the **`password` type** in all browsers except Internet Explorer 8 and below, in which the placeholder appears as masked text
- Wide range of browsers supported, **including IE6**
- **No dependencies** (so no need to include jQuery, unlike most placeholder polyfill scripts)
- All of the above in just 5kB when minified, and about **1kB when gzipped**!
##How do I use it?
Placeholders.js is designed to replicate native placeholder attribute functionality as best as it can. To get it working, simply define placeholders on your `input` or `textarea` elements as usual:
<input type="text" placeholder="Sample text">
<textarea placeholder="My placeholder"></textarea>
Just include the script and call the `init` method whenever you're ready. I suggest calling it in a DOM ready event listener of some description:
Placeholders.init();
That's all there is to it! Browsers that alreay support the placeholder attribute natively will be unaffected. They continue to use their built-in method.
##The `init` method
The `init` method is all that you need to call to get the polyfill working. It accepts one argument, `settings`. The `settings` argument should be an object. It currently supports two properties:
- `live` - If `true`, this option causes the polyfill to apply to all `input` and `textarea` elements, both now and in the future. This means if you insert a new element into the DOM, its placeholder attribute will function as expected. If the value of a placeholder attribute is modified by code sometime after the `init` method has executed, `live` will cause the changes to be reflected. If the `live` option is `false`, or not specified, the new element would not display its placeholder, and modified placeholder values would not function correctly. **Default: `false`**.
- `hideOnFocus` - If `true`, this option will cause the placeholder to disappear when the element receives focus. If `false`, or not specified, the placeholder will disappear when some input is entered into the element. **Default: `false`**.
- `className` - A custom class name that will be added to each element to which the polyfill applies. **Default: `placeholderspolyfill`**.
- `textColor` - The default color of the placeholder text. **Default: `#999` (gray)**.
- `styleImportant` - Boolean flag that specifies whether or not the `!important` directive should be added to the polyfill styles. **Default: `true`**.
Here's an example call to the `init` method:
Placeholders.init({
live: true, //Apply to future and modified elements too
hideOnFocus: true //Hide the placeholder when the element receives focus
});
##The `refresh` method
The `refresh` method can be called at any time to update the placeholders defined on elements, and detect any elements recently added to the DOM. You only need to use the `refresh` method if the `live` argument was set to `false` when you called `init`.
Placeholders.refresh();
##Known Issues
- When applying a placeholder to an `input` element of type `password`, the default "hidden" character is used instead of plain text in Internet Explorer 8 and below. Password inputs now work correctly in Internet Explorer 9.
- Because the polyfill uses the `value` attribute to display the placeholder, users will be unable to enter the placeholder value as valid input.
- (When the `hideOnFocus` option is `false`) The cursor position can currently be changed after focus, so you can insert characters in the middle of the placeholder value (causing the placeholder not to hide).
- The placeholder text cannot be styled. The ability to do so is currently non-standard, but is present in WebKit (with the `::-webkit-input-placeholder` pseudoelement), Firefox 4+ (with the `:-moz-placeholder` pseudoclass) and Internet Explorer 10 (with the `:-ms-input-placeholder` pseudoclass). This feature will not be added to the polyfill until some standard is defined.
##Supported Browsers
Placeholders.js aims to support the widest range of browsers possible. The idea is that you will be able to use the native `placeholder` attribute along with Placeholders.js and your users on any platform will get the same experience. This table will be updated as and when further browsers are tested. Mobile browser testing is a big one that's high on the list. Currently tested and working in the following browsers on (where applicable) both Windows 7 and CentOS 6:
- Internet Explorer 6 - 9 (with Placeholders.js)
- Firefox 1 - 3 (with Placeholders.js), 4+ (native)
- Opera 7 - 10 (with Placeholders.js), 11+ (native)
- Safari 3.2 (with Placeholders.js), 4+ (native)
- Chrome 4+ (native)
- Flock 1.0+ (with Placeholders.js)
- Konqueror 4.3 (with Placeholders.js)
- SeaMonkey 1+ (with Placeholders.js)
- Maxthon 1+ (with Placeholders.js)
- SlimBrowser 5 (with Placeholders.js)
- K-Meleon 0.7+ (with Placeholders.js)
Do you use some obscure browser that doesn't have native `placeholder` attribute support? If so, please let me know so I can make sure Placeholders.js works with it.
##Contributors
Many thanks to [@ioptics](https://github.com/ioptics) for asking me to write this in the first place. Also thanks to:
- [@markcarlson](https://github.com/markcarlson) for a major bug fix
- [@ralgh](https://github.com/ralgh) for adding options to customize the polyfill styles
##Downloads
You can download the repository at various states from the [tags page](https://github.com/jamesallardice/Placeholders.js/tags), or with the following links:
[Current version (1.3)](https://github.com/jamesallardice/Placeholders.js/zipball/v1.3) | [1.2.1](https://github.com/jamesallardice/Placeholders.js/zipball/v1.2.1) | [1.1](https://github.com/jamesallardice/Placeholders.js/zipball/v1.1) | [1.0](https://github.com/jamesallardice/Placeholders.js/zipball/v1.0)