Authored by xuqi

jquery placeholder

@@ -22,4 +22,5 @@ @@ -22,4 +22,5 @@
22 * [zepto.lazyload](/zepto-lazyload) **yoho.zeptolazyload** 22 * [zepto.lazyload](/zepto-lazyload) **yoho.zeptolazyload**
23 * [hammer](/hammer) **yoho.hammer** 23 * [hammer](/hammer) **yoho.hammer**
24 * [sizzle](/sizzle) **yoho.sizzle** 24 * [sizzle](/sizzle) **yoho.sizzle**
25 -* [json2](/json2) **yoho.json2**  
  25 +* [json2](/json2) **yoho.json2**
  26 +* [jquery-placeholder](/jquery-placeholder)
  1 +dist
  2 +_site
  3 +sea-modules
  4 +spm_modules
  5 +node_modules
  6 +.git
  7 +tests
  8 +examples
  9 +test
  10 +coverage
  1 +# yoho.placeholder [![spm version](http://spm.yoho.cn/badge/yoho.placeholder)](http://spm.yoho.cn/package/yoho.placeholder)
  2 +
  3 +---
  4 +
  5 +jquery.placeholder
  6 +
  7 +## Install
  8 +
  9 +```
  10 +$ spm install yoho.placeholder --save
  11 +```
  12 +
  13 +## Usage
  14 +
  15 +```js
  16 +var placeholder = require('yoho.placeholder');
  17 +// use yoho.placeholder
  18 +$('[placeholder]').placeholder();
  19 +```
  1 +/*!
  2 + * jQuery Placeholder Plugin v2.3.0
  3 + * https://github.com/mathiasbynens/jquery-placeholder
  4 + *
  5 + * Copyright 2011, 2015 Mathias Bynens
  6 + * Released under the MIT license
  7 + */
  8 +var jQuery = require('yoho.jquery');
  9 +
  10 +(function($) {
  11 +
  12 + /****
  13 + * Allows plugin behavior simulation in modern browsers for easier debugging.
  14 + * When setting to true, use attribute "placeholder-x" rather than the usual "placeholder" in your inputs/textareas
  15 + * i.e. <input type="text" placeholder-x="my placeholder text" />
  16 + */
  17 + var debugMode = false;
  18 +
  19 + // Opera Mini v7 doesn't support placeholder although its DOM seems to indicate so
  20 + var isOperaMini = Object.prototype.toString.call(window.operamini) === '[object OperaMini]';
  21 + var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini && !debugMode;
  22 + var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini && !debugMode;
  23 + var valHooks = $.valHooks;
  24 + var propHooks = $.propHooks;
  25 + var hooks;
  26 + var placeholder;
  27 + var settings = {};
  28 +
  29 + if (isInputSupported && isTextareaSupported) {
  30 +
  31 + placeholder = $.fn.placeholder = function() {
  32 + return this;
  33 + };
  34 +
  35 + placeholder.input = true;
  36 + placeholder.textarea = true;
  37 +
  38 + } else {
  39 +
  40 + placeholder = $.fn.placeholder = function(options) {
  41 +
  42 + var defaults = {customClass: 'placeholder'};
  43 + settings = $.extend({}, defaults, options);
  44 +
  45 + return this.filter((isInputSupported ? 'textarea' : ':input') + '[' + (debugMode ? 'placeholder-x' : 'placeholder') + ']')
  46 + .not('.'+settings.customClass)
  47 + .not(':radio, :checkbox, :hidden')
  48 + .bind({
  49 + 'focus.placeholder': clearPlaceholder,
  50 + 'blur.placeholder': setPlaceholder
  51 + })
  52 + .data('placeholder-enabled', true)
  53 + .trigger('blur.placeholder');
  54 + };
  55 +
  56 + placeholder.input = isInputSupported;
  57 + placeholder.textarea = isTextareaSupported;
  58 +
  59 + hooks = {
  60 + 'get': function(element) {
  61 +
  62 + var $element = $(element);
  63 + var $passwordInput = $element.data('placeholder-password');
  64 +
  65 + if ($passwordInput) {
  66 + return $passwordInput[0].value;
  67 + }
  68 +
  69 + return $element.data('placeholder-enabled') && $element.hasClass(settings.customClass) ? '' : element.value;
  70 + },
  71 + 'set': function(element, value) {
  72 +
  73 + var $element = $(element);
  74 + var $replacement;
  75 + var $passwordInput;
  76 +
  77 + if (value !== '') {
  78 +
  79 + $replacement = $element.data('placeholder-textinput');
  80 + $passwordInput = $element.data('placeholder-password');
  81 +
  82 + if ($replacement) {
  83 + clearPlaceholder.call($replacement[0], true, value) || (element.value = value);
  84 + $replacement[0].value = value;
  85 +
  86 + } else if ($passwordInput) {
  87 + clearPlaceholder.call(element, true, value) || ($passwordInput[0].value = value);
  88 + element.value = value;
  89 + }
  90 + }
  91 +
  92 + if (!$element.data('placeholder-enabled')) {
  93 + element.value = value;
  94 + return $element;
  95 + }
  96 +
  97 + if (value === '') {
  98 +
  99 + element.value = value;
  100 +
  101 + // Setting the placeholder causes problems if the element continues to have focus.
  102 + if (element != safeActiveElement()) {
  103 + // We can't use `triggerHandler` here because of dummy text/password inputs :(
  104 + setPlaceholder.call(element);
  105 + }
  106 +
  107 + } else {
  108 +
  109 + if ($element.hasClass(settings.customClass)) {
  110 + clearPlaceholder.call(element);
  111 + }
  112 +
  113 + element.value = value;
  114 + }
  115 + // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
  116 + return $element;
  117 + }
  118 + };
  119 +
  120 + if (!isInputSupported) {
  121 + valHooks.input = hooks;
  122 + propHooks.value = hooks;
  123 + }
  124 +
  125 + if (!isTextareaSupported) {
  126 + valHooks.textarea = hooks;
  127 + propHooks.value = hooks;
  128 + }
  129 +
  130 + $(function() {
  131 + // Look for forms
  132 + $(document).delegate('form', 'submit.placeholder', function() {
  133 +
  134 + // Clear the placeholder values so they don't get submitted
  135 + var $inputs = $('.'+settings.customClass, this).each(function() {
  136 + clearPlaceholder.call(this, true, '');
  137 + });
  138 +
  139 + setTimeout(function() {
  140 + $inputs.each(setPlaceholder);
  141 + }, 10);
  142 + });
  143 + });
  144 +
  145 + // Clear placeholder values upon page reload
  146 + $(window).bind('beforeunload.placeholder', function() {
  147 +
  148 + var clearPlaceholders = true;
  149 +
  150 + try {
  151 + // Prevent IE javascript:void(0) anchors from causing cleared values
  152 + if (document.activeElement.toString() === 'javascript:void(0)') {
  153 + clearPlaceholders = false;
  154 + }
  155 + } catch (exception) { }
  156 +
  157 + if (clearPlaceholders) {
  158 + $('.'+settings.customClass).each(function() {
  159 + this.value = '';
  160 + });
  161 + }
  162 + });
  163 + }
  164 +
  165 + function args(elem) {
  166 + // Return an object of element attributes
  167 + var newAttrs = {};
  168 + var rinlinejQuery = /^jQuery\d+$/;
  169 +
  170 + $.each(elem.attributes, function(i, attr) {
  171 + if (attr.specified && !rinlinejQuery.test(attr.name)) {
  172 + newAttrs[attr.name] = attr.value;
  173 + }
  174 + });
  175 +
  176 + return newAttrs;
  177 + }
  178 +
  179 + function clearPlaceholder(event, value) {
  180 +
  181 + var input = this;
  182 + var $input = $(this);
  183 +
  184 + if (input.value === $input.attr((debugMode ? 'placeholder-x' : 'placeholder')) && $input.hasClass(settings.customClass)) {
  185 +
  186 + input.value = '';
  187 + $input.removeClass(settings.customClass);
  188 +
  189 + if ($input.data('placeholder-password')) {
  190 +
  191 + $input = $input.hide().nextAll('input[type="password"]:first').show().attr('id', $input.removeAttr('id').data('placeholder-id'));
  192 +
  193 + // If `clearPlaceholder` was called from `$.valHooks.input.set`
  194 + if (event === true) {
  195 + $input[0].value = value;
  196 +
  197 + return value;
  198 + }
  199 +
  200 + $input.focus();
  201 +
  202 + } else {
  203 + input == safeActiveElement() && input.select();
  204 + }
  205 + }
  206 + }
  207 +
  208 + function setPlaceholder(event) {
  209 + var $replacement;
  210 + var input = this;
  211 + var $input = $(this);
  212 + var id = input.id;
  213 +
  214 + // If the placeholder is activated, triggering blur event (`$input.trigger('blur')`) should do nothing.
  215 + if (event && event.type === 'blur' && $input.hasClass(settings.customClass)) {
  216 + return;
  217 + }
  218 +
  219 + if (input.value === '') {
  220 + if (input.type === 'password') {
  221 + if (!$input.data('placeholder-textinput')) {
  222 +
  223 + try {
  224 + $replacement = $input.clone().prop({ 'type': 'text' });
  225 + } catch(e) {
  226 + $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
  227 + }
  228 +
  229 + $replacement
  230 + .removeAttr('name')
  231 + .data({
  232 + 'placeholder-enabled': true,
  233 + 'placeholder-password': $input,
  234 + 'placeholder-id': id
  235 + })
  236 + .bind('focus.placeholder', clearPlaceholder);
  237 +
  238 + $input
  239 + .data({
  240 + 'placeholder-textinput': $replacement,
  241 + 'placeholder-id': id
  242 + })
  243 + .before($replacement);
  244 + }
  245 +
  246 + input.value = '';
  247 + $input = $input.removeAttr('id').hide().prevAll('input[type="text"]:first').attr('id', $input.data('placeholder-id')).show();
  248 +
  249 + } else {
  250 +
  251 + var $passwordInput = $input.data('placeholder-password');
  252 +
  253 + if ($passwordInput) {
  254 + $passwordInput[0].value = '';
  255 + $input.attr('id', $input.data('placeholder-id')).show().nextAll('input[type="password"]:last').hide().removeAttr('id');
  256 + }
  257 + }
  258 +
  259 + $input.addClass(settings.customClass);
  260 + $input[0].value = $input.attr((debugMode ? 'placeholder-x' : 'placeholder'));
  261 +
  262 + } else {
  263 + $input.removeClass(settings.customClass);
  264 + }
  265 + }
  266 +
  267 + function safeActiveElement() {
  268 + // Avoid IE9 `document.activeElement` of death
  269 + try {
  270 + return document.activeElement;
  271 + } catch (exception) {}
  272 + }
  273 +}(jQuery));
  1 +{
  2 + "name": "yoho.placeholder",
  3 + "version": "0.0.1",
  4 + "description": "jquery.placeholder",
  5 + "keywords": [],
  6 + "homepage": "",
  7 + "author": "xuqi <xuqi9010@gmail.com>",
  8 + "repository": {
  9 + "type": "git",
  10 + "url": ""
  11 + },
  12 + "bugs": {
  13 + "url": ""
  14 + },
  15 + "licenses": "MIT",
  16 + "spm": {
  17 + "main": "jquery.placeholder.js",
  18 + "dependencies": {
  19 + "yoho.jquery": "1.8.3"
  20 + },
  21 + "devDependencies": {
  22 + "expect.js": "0.3.1"
  23 + }
  24 + },
  25 + "devDependencies": {
  26 + "spm": "3"
  27 + },
  28 + "scripts": {
  29 + "test": "spm test",
  30 + "build": "spm build"
  31 + }
  32 +}