/** * 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));