├── .gitignore ├── .gitmodules ├── .travis.yml ├── CHANGES ├── Gruntfile.js ├── LICENSE ├── README.md ├── includes └── piwik.html ├── package.json ├── src ├── index.jade ├── index.less ├── jquery.placeholder.css └── jquery.placeholder.js └── test ├── jquery.placeholder.html └── jquery.placeholder_test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .sass-cache 3 | *~ 4 | src/*-min.css 5 | src/*-min.js 6 | src/index.htm 7 | src/index.css 8 | build 9 | .*redcar/ 10 | dist 11 | node_modules 12 | jquery-placeholder-plugin*zip 13 | *.swp 14 | secret.json 15 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/bootstrap"] 2 | path = ext/bootstrap 3 | url = git://github.com/twitter/bootstrap.git 4 | [submodule "ext/qunit"] 5 | path = ext/qunit 6 | url = git://github.com/jquery/qunit.git 7 | [submodule "ext/jquery-loader"] 8 | path = ext/jquery-loader 9 | url = git://github.com/andrewrjones/simple-jquery-loader.git 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | before_install: 6 | - git submodule update --init --recursive 7 | - echo "{}" > secret.json 8 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | 0.7.2 01-03-2014 2 | - Fixed IE 7 issue (#16) [streetdragon]. 3 | 4 | 0.7.1 18-03-2013 5 | - Fix issue with .val() returning back the placeholder value (#12) [rogerhu]. 6 | 7 | 0.7.0 03-12-2012 8 | - Ensure .val() works correctly. Fixes https://github.com/andrewrjones/jquery-placeholder-plugin/issues/5. 9 | 10 | 0.6.1 03-10-2012 11 | - Add note about password fields 12 | - Code tidy 13 | 14 | 0.6 06-06-2012 15 | - Remove debug code 16 | - "use strict" 17 | - Add unit tests 18 | - Use grunt for building 19 | 20 | 0.5 31-01-2012 21 | - Update docs 22 | 23 | 0.4 28-01-2011 24 | - Rename files to be consistent with other jQuery plugins. 25 | Eg: jquery-placeholder-plugin-min.js to jquery.placeholder.min.js 26 | 27 | 0.3 28-01-2011 28 | This release brings in Mal Curtis' work from https://github.com/snikch/jquery-placeholder-plugin/. Each of the changes in this version are attributed to him (which means he has probably wrote more of the code than I have ;-) 29 | 30 | [Setting Changes] 31 | - 'blurClass' has been renamed to 'activeClass' 32 | - 'activeClass' has been renamed to 'focusClass' 33 | 34 | [Enhancements] 35 | - 'preventRefreshIssues' optional setting added to prevent Firefox from auto filling values on refresh, by turning autocomplete off. Defaults to true 36 | 37 | [Bug Fixes] 38 | - If the value is actually set to the same as the placeholder, it's still considered a placeholder 39 | - Refresh in firefox pre fills the input field with the placeholder 40 | - Val() function returns the placeholder, not an empty string 41 | - Submitting a form would submit the placeholder value 42 | - Changing the value of an element with a placeholder via val('string') will removed the placeholder class 43 | 44 | 0.2 24-01-2011 45 | - Doc updates 46 | 47 | 0.1 25-08-2010 48 | - Inital version -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*global module:false, require:false*/ 2 | module.exports = function (grunt) { 3 | 4 | // Project configuration. 5 | grunt.initConfig({ 6 | pkg: grunt.file.readJSON('package.json'), 7 | meta: { 8 | banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %>\\n' + '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' 9 | }, 10 | connect: { 11 | server: { 12 | options: { 13 | port: 8085 14 | } 15 | } 16 | }, 17 | concat: { 18 | options: { 19 | banner: '<%= meta.banner %>', 20 | stripBanners: true 21 | }, 22 | dist: { 23 | src: ['src/<%= pkg.name %>.js'], 24 | dest: 'dist/<%= pkg.name %>.js' 25 | }, 26 | distcss: { 27 | src: ['src/<%= pkg.name %>.css'], 28 | dest: 'dist/<%= pkg.name %>.css' 29 | } 30 | }, 31 | uglify: { 32 | dist: { 33 | files: { 34 | 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>'] 35 | } 36 | } 37 | }, 38 | cssmin: { 39 | dist: { 40 | files: { 41 | 'dist/<%= pkg.name %>.min.css': ['<%= concat.distcss.dest %>'] 42 | } 43 | }, 44 | docs: { 45 | files: { 46 | 'dist/index.min.css': ['<%= less.index.dest %>'] 47 | } 48 | } 49 | }, 50 | jade: { 51 | compile: { 52 | files: { 53 | "dist/index.html": ["src/index.jade"] 54 | }, 55 | options: { 56 | client: false 57 | } 58 | } 59 | }, 60 | less: { 61 | index: { 62 | src: "src/index.less", 63 | dest: "dist/index.css" 64 | } 65 | }, 66 | qunit: { 67 | all: { 68 | options: { 69 | urls: ['1.9.1', '1.10.0', '1.11.0-beta2', '2.0.1', '2.1.0-beta2'].map(function (version) { 70 | return 'http://localhost:<%= connect.server.options.port %>/test/jquery.placeholder.html?jquery=' + version; 71 | }) 72 | } 73 | } 74 | }, 75 | beautify: { 76 | files: '<%= jshint.files.src %>' 77 | }, 78 | watch: { 79 | files: '<%= jshint.files.src %>', 80 | tasks: ['test'] 81 | }, 82 | replace: { 83 | dist: { 84 | options: { 85 | variables: { 86 | 'version': '<%= pkg.version %>' 87 | } 88 | }, 89 | files: { 90 | 'dist/index.html': ['dist/index.html'] 91 | } 92 | } 93 | }, 94 | clean: ['dist', '*zip'], 95 | jshint: { 96 | options: { 97 | curly: true, 98 | eqeqeq: true, 99 | immed: true, 100 | latedef: true, 101 | newcap: true, 102 | noarg: true, 103 | sub: true, 104 | undef: true, 105 | boss: true, 106 | eqnull: true, 107 | browser: true, 108 | globals: { 109 | jQuery: true 110 | } 111 | }, 112 | files: { 113 | src: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'] 114 | } 115 | }, 116 | copy: { 117 | dist: { 118 | options: { 119 | flatten: true 120 | }, 121 | files: [{ 122 | expand: true, 123 | flatten: true, 124 | dest: 'dist/', 125 | src: ['CHANGES', 'LICENSE', 'README', 'ext/bootstrap/bootstrap.min.css'] 126 | }] 127 | } 128 | }, 129 | compress: { 130 | zip: { 131 | options: { 132 | mode: "zip", 133 | rootDir: "jquery-placeholder-plugin", 134 | archive: "jquery-placeholder-plugin-<%= pkg.version %>.zip" 135 | }, 136 | files: [{ 137 | expand: true, 138 | flatten: true, 139 | cwd: 'dist/', 140 | dest: "", 141 | src: ["**"] 142 | }] 143 | } 144 | } 145 | }); 146 | 147 | // Default task. 148 | grunt.registerTask('default', ['jshint', 'beautify']); 149 | grunt.registerTask('test', ['connect', 'jshint', 'qunit']); 150 | grunt.registerTask('build', ['jade', 'less', 'concat', 'uglify', 'cssmin', 'copy']); 151 | grunt.registerTask('dist', ['build', 'replace:dist', 'compress']); 152 | 153 | grunt.loadNpmTasks('grunt-contrib-less'); 154 | grunt.loadNpmTasks('grunt-contrib-watch'); 155 | grunt.loadNpmTasks('grunt-contrib-copy'); 156 | grunt.loadNpmTasks('grunt-contrib-clean'); 157 | grunt.loadNpmTasks('grunt-contrib-compress'); 158 | grunt.loadNpmTasks('grunt-contrib-concat'); 159 | grunt.loadNpmTasks('grunt-contrib-jshint'); 160 | grunt.loadNpmTasks('grunt-contrib-qunit'); 161 | grunt.loadNpmTasks('grunt-contrib-connect'); 162 | grunt.loadNpmTasks('grunt-bump'); 163 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 164 | grunt.loadNpmTasks('grunt-contrib-uglify'); 165 | grunt.loadNpmTasks('grunt-contrib-jade'); 166 | grunt.loadNpmTasks('grunt-beautify'); 167 | grunt.loadNpmTasks('grunt-replace'); 168 | 169 | grunt.registerTask('tidy', 'beautify'); 170 | }; 171 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 - 2013 Andrew Jones, http://andrew-jones.com 2 | Parts Copyright (c) 2010 Mal Curtis, http://mal.co.nz 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | jQuery Placeholder Plugin 2 | ========================= 3 | 4 | This is a small jQuery plugin that emulates the placeholder attribute in web browsers that do not support it. If the browser does support it, the plugin does nothing. 5 | 6 | To use the plugin, add the JS and CSS files to your page and do the following: 7 | 8 | ```js 9 | jQuery(document).ready(function($) { 10 | $(":input[placeholder]").placeholder(); 11 | }); 12 | ``` 13 | 14 | Then, in your HTML you can use the placeholder plugin as documented in the HTML5 spec: 15 | 16 | ```html 17 | 18 | ``` 19 | 20 | For more information and some demos, see http://andrew-jones.com/jquery-placeholder-plugin 21 | 22 | Contributing 23 | ------------ 24 | 25 | I really appreciate any and all contributions. 26 | 27 | I use [Grunt](http://gruntjs.com/) to build this plugin. Once you have installed with `npm install`, run `grunt --help` to see the available tasks. 28 | 29 | If you are contibuting code, please tidy the code by running `grunt tidy`. This helps ensure the pull request only shows relevant changes and keeps the code readable and in one style. 30 | 31 | Ensure the unit tests pass by running `grunt test`. Please also try to add new tests where it helps. 32 | 33 | Thanks again for contributing to this plugin! 34 | 35 | Build status 36 | ------------ 37 | 38 | [![Build Status](https://secure.travis-ci.org/andrewrjones/jquery-placeholder-plugin.png)](http://travis-ci.org/andrewrjones/jquery-placeholder-plugin) 39 | -------------------------------------------------------------------------------- /includes/piwik.html: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery.placeholder", 3 | "title": "jQuery Placeholder Plugin", 4 | "description": "Simple jQuery plugin that adds support for the placeholder attribute in all browsers", 5 | "version": "0.7.2", 6 | "homepage": "http://andrew-jones.com/jquery-placeholder-plugin", 7 | "author": { 8 | "name": "Andrew Jones", 9 | "email": "andrew@arjones.co.uk", 10 | "url": "http://andrew-jones.com" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/andrewrjones/jquery-placeholder-plugin.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/andrewrjones/jquery-placeholder-plugin/issues" 18 | }, 19 | "licenses": [ 20 | { 21 | "type": "MIT", 22 | "url": "http://andrew-jones.com/jquery-placeholder-plugin/LICENSE" 23 | } 24 | ], 25 | "dependencies": { 26 | "jquery": "~1.5" 27 | }, 28 | "devDependencies": { 29 | "grunt": "~0.4.0", 30 | "grunt-cli": "~0.1", 31 | "grunt-contrib-jade": "*", 32 | "grunt-bump": "~0.0.2", 33 | "grunt-beautify": "git://github.com/terryweiss/grunt-beautify.git#FixForGrunt040", 34 | "grunt-contrib-copy": "~0.4.0", 35 | "grunt-contrib-clean": "0.4.0", 36 | "grunt-contrib-jshint": "0.1.1", 37 | "grunt-contrib-qunit": "0.1.1", 38 | "grunt-contrib-clean": "0.4.0", 39 | "grunt-contrib-compress": "~0.4.0", 40 | "grunt-contrib-concat": "~0.1.2", 41 | "grunt-contrib-connect": "~0.1.2", 42 | "grunt-contrib-uglify": "~0.1.2", 43 | "grunt-contrib-less": "~0.5.0", 44 | "grunt-contrib-cssmin": "*", 45 | "grunt-contrib-watch": "*", 46 | "grunt-replace" : "git://github.com/outaTiME/grunt-replace.git" 47 | }, 48 | "scripts": { 49 | "test": "grunt test" 50 | }, 51 | "keywords": [] 52 | } 53 | -------------------------------------------------------------------------------- /src/index.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html(lang='en', xml:lang='en', xmlns='http://www.w3.org/1999/xhtml') 3 | head 4 | title jQuery Placeholder Plugin 5 | meta(content='text/html; charset=utf-8', http-equiv='Content-Type') 6 | meta(content='jQuery plugin that adds support for the placeholder attribute in all browsers', name='description') 7 | meta(content='Andrew Jones, http://andrew-jones.com', name='author') 8 | link(href="https://plus.google.com/112154348489250057838", rel="author") 9 | //if lt IE 9 10 | script(src='http://html5shim.googlecode.com/svn/trunk/html5.js', type='text/javascript') 11 | link(href='bootstrap.min.css?@@version', rel='stylesheet', type='text/css') 12 | link(href='index.min.css?@@version', rel='stylesheet', type='text/css') 13 | script(src='http://code.jquery.com/jquery-1.9.1.min.js', type='text/javascript') 14 | script(src='jquery.placeholder.js?@@version', type='text/javascript') 15 | link(href='jquery.placeholder.css?@@version', rel='stylesheet', type='text/css') 16 | script(src='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js', type='text/javascript') 17 | link(href='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css', rel='stylesheet', type='text/css') 18 | script. 19 | jQuery(document).ready(function($) { 20 | try { 21 | prettyPrint(); 22 | } catch(err) {} 23 | $(":input[placeholder]").placeholder(); 24 | }); 25 | body 26 | a(href='http://github.com/andrewrjones/jquery-placeholder-plugin/') 27 | img(style='position: absolute; top: 0; right: 0; border: 0;', src='http://s3.amazonaws.com/github/ribbons/forkme_right_green_007200.png', alt='Fork me on GitHub') 28 | .container 29 | .content 30 | .page-header 31 | h1 jQuery Placeholder Plugin 32 | .row 33 | .span10 34 | p 35 | | This is a simple plugin for 36 | a(href='http://jquery.com', title='jQuery') jQuery 37 | | that provides support for the 38 | a(href='http://dev.w3.org/html5/spec/Overview.html#the-placeholder-attribute', title='HTML5 placeholder') 39 | | HTML5 40 | code placeholder 41 | | attribute in browsers that do not already support it. 42 | p 43 | | To use it, simply add the plugins CSS and JS files to the page and use the following JS to initialise it: 44 | pre.prettyprint.language-js. 45 | jQuery(document).ready(function($) { 46 | $(":input[placeholder]").placeholder(); 47 | }); 48 | p 49 | | Then in your HTML document, use the 50 | code placeholder 51 | | attribute with 52 | code input 53 | | tags. For example: 54 | pre.prettyprint.language-html. 55 | 56 | p 57 | | If the browser already supports the 58 | code placeholder 59 | | attribute then the plugin will do nothing, unless you provide the 60 | code overrideSupport 61 | | option. 62 | h2 Options 63 | p 64 | | The following options can be passed to the plugin. 65 | h3 activeClass 66 | p.option-description 67 | | The class to apply when input is blurred. Defaults to 68 | code placeholder 69 | | . 70 | h3 focusClass 71 | p.option-description 72 | | The class to apply when input is active. Defaults to 73 | code placeholderFocus 74 | | . 75 | h3 overrideSupport 76 | p.option-description 77 | | Pass 78 | code true 79 | | to force the plugin to work on browsers which natively support the 80 | code placeholder 81 | | attribute. Defaults to 82 | code false 83 | | . 84 | h3 preventRefreshIssues 85 | p.option-description 86 | | Optionally attempt to prevent Firefox from auto filling values on refresh, by turning 87 | code autocomplete 88 | | off. Defaults to 89 | code true 90 | | . 91 | h2 Password Fields 92 | p 93 | | Currently we do not support password fields, as it is very complex to get right. 94 | p 95 | | In my opinion, it is OK to provide placeholders in password fields only for browsers that support it natively. 96 | | If the browser does not support it, then the user will not see the placeholder, but that should be acceptable 97 | | as the placeholder is only an extra bit of help and should not be critical to your interface. 98 | h2 Using With Autofocus 99 | p 100 | | If you want the field to autofocus when the browser loads, you need to ensure that you apply the placeholder first, as follows: 101 | pre.prettyprint.language-js. 102 | // apply placeholders - must be applied first before any autofocus actions 103 | $(":input[placeholder]").placeholder(); 104 | // focus on the first text input field in the first field on the page 105 | $("input[type='text']:first", document.forms[0]).focus().select(); 106 | | Thanks to 107 | a(href='https://github.com/hostdude99', title='hostdude99') hostdude99 108 | | for the hint. 109 | h2 The Code 110 | p 111 | | You can download the source code from 112 | a(href='http://github.com/andrewrjones/jquery-placeholder-plugin/downloads', title='downloads') GitHub 113 | | or go to the plugins 114 | a(href='http://andrew-jones.com/jquery-placeholder-plugin', title='jQuery Placeholder Plugin') homepage 115 | | for more information. 116 | h2 Support 117 | p 118 | | Please use the 119 | a(href='http://github.com/andrewrjones/jquery-placeholder-plugin/issues', title='issues') GitHub issues tracker 120 | | for any bugs or issues. 121 | h2 Acknowledgements 122 | p 123 | | Thanks to 124 | a(href='http://mal.co.nz', title='Mal Curtis') Mal Curtis 125 | | for many bug fixes and enhancements. Has probably writting more of the code than I have ;-) 126 | h2 License 127 | p 128 | | This code is available under the MIT License. See the 129 | a(href='LICENSE', title='MIT license') LICENSE 130 | | file for more details. 131 | .span4 132 | div 133 | p(class='download') 134 | a(href='http://dl.dropbox.com/u/2957481/jquery-placeholder-plugin/jquery-placeholder-plugin-@@version.zip', title='Download') Download v@@version 135 | div(class='examples') 136 | h2 Examples 137 | h3 Text 138 | input(name='text-example', placeholder='Some placeholding text', size='25', type='text') 139 | h3 Search 140 | input(name='search-example', placeholder='Do a search...', size='25', type='search') 141 | h3 Email 142 | input(name='email-example', placeholder='Please enter an email address', size='25', type='email') 143 | h3 URL 144 | input(name='url-example', placeholder='Please enter a URL', size='25', type='url') 145 | .html5-logo 146 | a(href='http://www.w3.org/html/logo/') 147 | img(src='http://www.w3.org/html/logo/badge/html5-badge-h-semantics.png', width='133', height='64', alt='HTML5 Powered with Semantics', title='HTML5 Powered with Semantics') 148 | footer 149 | p 150 | | © 2013 151 | a(href='http://andrew-jones.com') Andrew Jones -------------------------------------------------------------------------------- /src/index.less: -------------------------------------------------------------------------------- 1 | html, body { 2 | background-color: #eee; 3 | } 4 | 5 | .container { 6 | > footer p { 7 | text-align: center; 8 | } 9 | width: 820px; 10 | } 11 | 12 | .content { 13 | background-color: #fff; 14 | padding: 20px; 15 | margin: 0 -20px; /* negative indent the amount of the padding to maintain the grid system */ 16 | -webkit-border-radius: 0 0 6px 6px; 17 | -moz-border-radius: 0 0 6px 6px; 18 | border-radius: 0 0 6px 6px; 19 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); 20 | -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); 21 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); 22 | } 23 | 24 | .page-header { 25 | background-color: #f5f5f5; 26 | padding: 20px 20px 10px; 27 | margin: -20px -20px 20px; 28 | } 29 | 30 | .content { 31 | .span10 { 32 | padding-right: 9px; 33 | border-right: 1px solid #eee; 34 | } 35 | .span4 { 36 | margin-left: 9px; 37 | } 38 | .span4 { 39 | div.html5-logo { 40 | padding-top: 30px; 41 | } 42 | } 43 | } 44 | 45 | .examples { 46 | clear: both; 47 | } 48 | 49 | .download { 50 | float: right; 51 | font-size: 17px; 52 | text-decoration: underline; 53 | } 54 | -------------------------------------------------------------------------------- /src/jquery.placeholder.css: -------------------------------------------------------------------------------- 1 | .placeholder { color: #666; } 2 | .placeholderFocus { color: #000; } -------------------------------------------------------------------------------- /src/jquery.placeholder.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | "use strict"; 3 | 4 | $.extend({ 5 | placeholder: { 6 | settings: { 7 | focusClass: 'placeholderFocus', 8 | activeClass: 'placeholder', 9 | overrideSupport: false, 10 | preventRefreshIssues: true 11 | } 12 | } 13 | 14 | }); 15 | 16 | // check browser support for placeholder 17 | $.support.placeholder = 'placeholder' in document.createElement('input'); 18 | 19 | // Replace the val function to never return placeholders 20 | $.fn.plVal = $.fn.val; 21 | $.fn.val = function (value) { 22 | var el; 23 | if (typeof value === 'undefined') { 24 | el = $(this[0]); 25 | 26 | if (el.hasClass($.placeholder.settings.activeClass) && el.plVal() === el.attr('placeholder')) { 27 | return ''; 28 | } 29 | 30 | return $.fn.plVal.call(this); 31 | } else { 32 | el = $(this[0]); 33 | var currentValue = el.plVal(); 34 | var returnValue = $(this).plVal(value); 35 | if (el.hasClass($.placeholder.settings.activeClass) && currentValue === el.attr('placeholder')) { 36 | el.removeClass($.placeholder.settings.activeClass); 37 | return returnValue; 38 | } 39 | 40 | return $.fn.plVal.call(this, value); 41 | } 42 | }; 43 | 44 | // Clear placeholder values upon page reload 45 | $(window).bind('beforeunload.placeholder', function () { 46 | var els = $('input.' + $.placeholder.settings.activeClass); 47 | if (els.length > 0) { 48 | els.val('').attr('autocomplete', 'off'); 49 | } 50 | }); 51 | 52 | 53 | // plugin code 54 | $.fn.placeholder = function (opts) { 55 | opts = $.extend({}, $.placeholder.settings, opts); 56 | 57 | // we don't have to do anything if the browser supports placeholder 58 | if (!opts.overrideSupport && $.support.placeholder) { 59 | return this; 60 | } 61 | 62 | return this.each(function () { 63 | var $el = $(this); 64 | 65 | // skip if we do not have the placeholder attribute 66 | if (!$el.is('[placeholder]')) { 67 | return; 68 | } 69 | 70 | // we cannot do password fields, but supported browsers can 71 | if ($el.is(':password')) { 72 | return; 73 | } 74 | 75 | // Prevent values from being reapplied on refresh 76 | if (opts.preventRefreshIssues) { 77 | $el.attr('autocomplete', 'off'); 78 | } 79 | 80 | $el.bind('focus.placeholder', function () { 81 | var $el = $(this); 82 | if (this.value === $el.attr('placeholder') && $el.hasClass(opts.activeClass)) { 83 | $el.val('').removeClass(opts.activeClass).addClass(opts.focusClass); 84 | } 85 | }); 86 | 87 | $el.bind('blur.placeholder', function () { 88 | var $el = $(this); 89 | 90 | $el.removeClass(opts.focusClass); 91 | 92 | if (this.value === '') { 93 | $($el.val($el.attr('placeholder'))).addClass(opts.activeClass); 94 | } 95 | }); 96 | 97 | $el.triggerHandler('blur'); 98 | 99 | // Prevent incorrect form values being posted 100 | $el.parents('form').submit(function () { 101 | $el.triggerHandler('focus.placeholder'); 102 | }); 103 | 104 | }); 105 | }; 106 | }(jQuery)); -------------------------------------------------------------------------------- /test/jquery.placeholder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery Placeholder Plugin Test Suite 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |

jQuery Placeholder Plugin Test Suite

19 |

20 |
21 |

22 |
    23 |
    24 | 25 | 26 | 27 | 28 |
    29 | 30 | 31 |
    32 |
    33 | 34 | 35 | -------------------------------------------------------------------------------- /test/jquery.placeholder_test.js: -------------------------------------------------------------------------------- 1 | /*global QUnit:false, module:false, test:false, asyncTest:false, expect:false*/ 2 | /*global start:false, stop:false ok:false, equal:false, notEqual:false, deepEqual:false*/ 3 | /*global notDeepEqual:false, strictEqual:false, notStrictEqual:false, raises:false*/ 4 | (function ($) { 5 | 6 | module('jQuery#placeholder', { 7 | setup: function () { 8 | // find the test elements 9 | this.elems = $('#qunit-fixture'); 10 | this["placeholder-text-foo"] = this.elems.find("#placeholder-text-foo").first(); 11 | this["placeholder-password-foo"] = this.elems.find("#placeholder-password-foo").first(); 12 | this["no-placeholder"] = this.elems.find("#no-placeholder").first(); 13 | } 14 | }); 15 | 16 | test('is chainable', 1, function () { 17 | strictEqual(this.elems.placeholder(), this.elems, 'should be chaninable'); 18 | }); 19 | 20 | test("test default", 14, function () { 21 | var el = this["placeholder-text-foo"].placeholder({ 22 | overrideSupport: true 23 | }); 24 | 25 | // should set the value to the placeholder 26 | strictEqual(el.attr('value'), 'foo'); 27 | strictEqual(el.attr('autocomplete'), 'off'); 28 | 29 | // should have the default class 30 | ok(el.hasClass('placeholder')); 31 | ok(!el.hasClass('placeholderFocus')); 32 | 33 | // test on focus 34 | el.focus(); 35 | 36 | strictEqual(el.attr('value'), ''); 37 | ok(!el.hasClass('placeholder')); 38 | ok(el.hasClass('placeholderFocus')); 39 | 40 | // and unfocus (blur) again 41 | el.blur(); 42 | 43 | strictEqual(el.attr('value'), 'foo'); 44 | ok(el.hasClass('placeholder')); 45 | ok(!el.hasClass('placeholderFocus')); 46 | 47 | // now set the value to something else 48 | el.val('bar'); 49 | 50 | strictEqual(el.attr('value'), 'bar'); 51 | ok(!el.hasClass('placeholder')); 52 | 53 | // and clear it again 54 | el.val(''); 55 | 56 | strictEqual(el.attr('value'), ''); 57 | ok(!el.hasClass('placeholderFocus')); 58 | }); 59 | 60 | test("test set classes", 4, function () { 61 | // class names 62 | var activeClass = 'myactiveclass'; 63 | var focusClass = 'myfocusclass'; 64 | 65 | // run placeholder 66 | var el = this["placeholder-text-foo"].placeholder({ 67 | overrideSupport: true, 68 | activeClass: activeClass, 69 | focusClass: focusClass 70 | }); 71 | 72 | // should have the default class 73 | ok(el.hasClass(activeClass)); 74 | ok(!el.hasClass(focusClass)); 75 | 76 | // test on focus 77 | el.focus(); 78 | 79 | ok(!el.hasClass(activeClass)); 80 | ok(el.hasClass(focusClass)); 81 | }); 82 | 83 | // https://github.com/andrewrjones/jquery-placeholder-plugin/issues/5 84 | test("test issue 5", 2, function () { 85 | var value = 'test'; 86 | var element1 = '#placeholder-text-value-foo'; 87 | var element2 = '#placeholder-text-value-bar'; 88 | 89 | $('#issue5').find(element1).val(value).end().find(element2).val(value); 90 | 91 | strictEqual($(element1).val(), value, element1 + ' not equal to ' + value); 92 | strictEqual($(element2).val(), value, element2 + ' not equal to ' + value); 93 | }); 94 | 95 | test("test no placeholder", 2, function () { 96 | var el = this["no-placeholder"].placeholder({ 97 | overrideSupport: true 98 | }); 99 | 100 | // should not set value 101 | ok(!el.attr('value')); 102 | 103 | // should not set class 104 | ok(!el.hasClass('placeholder')); 105 | }); 106 | 107 | test("test password placeholder", 2, function () { 108 | var el = this["placeholder-password-foo"].placeholder({ 109 | overrideSupport: true 110 | }); 111 | 112 | // should not set value 113 | ok(!el.attr('value')); 114 | 115 | // should not set class 116 | ok(!el.hasClass('placeholder')); 117 | }); 118 | 119 | test("test preventRefreshIssues false", 1, function () { 120 | var el = this["placeholder-text-foo"].placeholder({ 121 | overrideSupport: true, 122 | preventRefreshIssues: false 123 | }); 124 | 125 | // should not set autocomplete 126 | ok(!el.attr('autocomplete')); 127 | }); 128 | 129 | test("test set value", 2, function () { 130 | var el = this["placeholder-text-foo"].placeholder({ 131 | overrideSupport: true 132 | }); 133 | 134 | // default value should be placeholder 135 | strictEqual(el.attr('value'), 'foo'); 136 | 137 | // set the value 138 | el.val('bar'); 139 | 140 | // value should now be bar 141 | strictEqual(el.attr('value'), 'bar'); 142 | }); 143 | 144 | test("test submit form", 1, function () { 145 | ok("TODO: test submiting a form, ensuring that the default placeholder is not sent through"); 146 | }); 147 | 148 | }(jQuery)); --------------------------------------------------------------------------------