/**
* HTML5 placeholder emulation for jQuery plugin
*
* This will automatically use the HTML5 placeholder attribute if supported, or emulate this behavior if not.
*
* This is a fork from Mathias Bynens' jquery.placeholder as of this commit
* https://github.com/mathiasbynens/jquery-placeholder/blob/47f05d400e2dd16b59d144141a2cf54a9a77c502/jquery.placeholder.js
*
* @author Mathias Bynens
* @author Trevor Parscal , 2012
* @author Krinkle , 2012
* @author Alex Ivanov , 2013
* @version 2.1.0
* @license MIT
*/
( function ($) {
var isInputSupported = 'placeholder' in document.createElement('input'),
isTextareaSupported = 'placeholder' in document.createElement('textarea'),
prototype = $.fn,
valHooks = $.valHooks,
propHooks = $.propHooks,
hooks,
placeholder;
if (isInputSupported && isTextareaSupported) {
placeholder = prototype.placeholder = function (text) {
var hasArgs = arguments.length;
if (hasArgs) {
changePlaceholder.call(this, text);
}
return this;
};
placeholder.input = placeholder.textarea = true;
} else {
placeholder = prototype.placeholder = function (text) {
var $this = this,
hasArgs = arguments.length;
if (hasArgs) {
changePlaceholder.call(this, text);
}
$this
.filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
.filter( function () {
return !$(this).data('placeholder-enabled');
})
.bind({
'focus.placeholder drop.placeholder': clearPlaceholder,
'blur.placeholder': setPlaceholder
})
.data('placeholder-enabled', true)
.trigger('blur.placeholder');
return $this;
};
placeholder.input = isInputSupported;
placeholder.textarea = isTextareaSupported;
hooks = {
'get': function (element) {
var $element = $(element),
$passwordInput = $element.data('placeholder-password');
if ($passwordInput) {
return $passwordInput[0].value;
}
return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
},
'set': function (element, value) {
var $element = $(element),
$passwordInput = $element.data('placeholder-password');
if ($passwordInput) {
$passwordInput[0].value = value;
return value;
}
if (!$element.data('placeholder-enabled')) {
element.value = value;
return value;
}
if (!value) {
element.value = value;
// Issue #56: Setting the placeholder causes problems if the element continues to have focus.
if (element !== safeActiveElement()) {
// We can't use `triggerHandler` here because of dummy text/password inputs :(
setPlaceholder.call(element);
}
} else if ($element.hasClass('placeholder')) {
if (!clearPlaceholder.call(element, true, value)) {
element.value = value;
}
} else {
element.value = value;
}
// `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
return $element;
}
};
if (!isInputSupported) {
valHooks.input = hooks;
propHooks.value = hooks;
}
if (!isTextareaSupported) {
valHooks.textarea = hooks;
propHooks.value = hooks;
}
$( function () {
// Look for forms
$(document).delegate('form', 'submit.placeholder', function () {
// Clear the placeholder values so they don't get submitted
var $inputs = $('.placeholder', this).each(clearPlaceholder);
setTimeout( function () {
$inputs.each(setPlaceholder);
}, 10);
});
});
// Clear placeholder values upon page reload
$(window).bind('beforeunload.placeholder', function () {
$('.placeholder').each( function () {
this.value = '';
});
});
}
function args(elem) {
// Return an object of element attributes
var newAttrs = {},
rinlinejQuery = /^jQuery\d+$/;
$.each(elem.attributes, function (i, attr) {
if (attr.specified && !rinlinejQuery.test(attr.name)) {
newAttrs[attr.name] = attr.value;
}
});
return newAttrs;
}
function clearPlaceholder(event, value) {
var input = this,
$input = $(input);
if (input.value === $input.attr('placeholder') && $input.hasClass('placeholder')) {
if ($input.data('placeholder-password')) {
$input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
// If `clearPlaceholder` was called from `$.valHooks.input.set`
if (event === true) {
$input[0].value = value;
return value;
}
$input.focus();
} else {
input.value = '';
$input.removeClass('placeholder');
if (input === safeActiveElement()) {
input.select();
}
}
}
}
function setPlaceholder() {
var $replacement,
input = this,
$input = $(input),
id = this.id;
if (!input.value) {
if (input.type === 'password') {
if (!$input.data('placeholder-textinput')) {
try {
$replacement = $input.clone().attr({ 'type': 'text' });
} catch (e) {
$replacement = $('').attr($.extend(args(this), { 'type': 'text' }));
}
$replacement
.removeAttr('name')
.data({
'placeholder-password': $input,
'placeholder-id': id
})
.bind('focus.placeholder drop.placeholder', clearPlaceholder);
$input
.data({
'placeholder-textinput': $replacement,
'placeholder-id': id
})
.before($replacement);
}
$input = $input.removeAttr('id').hide().prev().attr('id', id).show();
// Note: `$input[0] != input` now!
}
$input.addClass('placeholder');
$input[0].value = $input.attr('placeholder');
} else {
$input.removeClass('placeholder');
}
}
function safeActiveElement() {
// Avoid IE9 `document.activeElement` of death
// https://github.com/mathiasbynens/jquery-placeholder/pull/99
try {
return document.activeElement;
} catch (err) {}
}
function changePlaceholder(text) {
var hasArgs = arguments.length,
$input = this;
if (hasArgs) {
if ($input.attr('placeholder') !== text) {
$input.prop('placeholder', text);
if ($input.hasClass('placeholder')) {
$input[0].value = text;
}
}
}
}
}(jQuery));