Skip to content

Instantly share code, notes, and snippets.

@henrik
Created September 27, 2011 19:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save henrik/1245969 to your computer and use it in GitHub Desktop.
Save henrik/1245969 to your computer and use it in GitHub Desktop.
CoffeeScript/jQuery plugin for iOS style placeholders.
input.placeholding { color: #BBB; }
# CoffeeScript/jQuery plugin for iOS style placeholders.
# By Henrik Nyh <http://henrik.nyh.se> 2011-09-27 under the MIT license.
# Based on http://robertnyman.com/2011/05/02/html5-placeholder-and-an-alternative-approach-introducing-roberts-playground/
#
# Define a CSS rule like:
#
# input.placeholding { color: #BBB; }
#
# And use by assigning placeholder attributes to input fields and doing:
#
# $.iOSPlaceholder()
#
# with an optional selector:
#
# $.iOSPlaceholder(".only-with-this-class")
# $.iOSPlaceholder("#only-this-element")
# $.iOSPlaceholder($("#only-this-element"))
$ = jQuery
KLASS = "placeholding"
MOVEMENT_KCODES = [
PAGE_UP = 33
PAGE_DOWN = 34
END = 35
HOME = 36
LEFT = 37
UP = 38
RIGHT = 39
DOWN = 40
]
NON_INPUT_KCODES = MOVEMENT_KCODES.concat [
BACKSPACE = 8
TAB = 9
SHIFT = 16
CTRL = 17
OPT_ALT = 18
CMD = 91
]
setSelectionRange = (input, selectionStart, selectionEnd) ->
if input.setSelectionRange
input.focus()
input.setSelectionRange(selectionStart, selectionEnd)
else if input.createTextRange
range = input.createTextRange()
range.collapse(true)
range.moveEnd('character', selectionEnd)
range.moveStart('character', selectionStart)
range.select()
rewindCaret = ->
if hasPlaceholderValue(this)
# Without the timeout, tabbing out and back may leave the text selected in Chrome.
setTimeout (=> this.setSelectionRange(0,0)), 0
clearPlaceholder = (e) ->
if hasPlaceholderValue(this)
if e.which in NON_INPUT_KCODES
# Don't clear placeholder, but do rewind caret if it might have moved.
# It's important that we don't do this when tabbing, or we break tabbing out of the element.
rewindCaret.apply(this) if e.which in MOVEMENT_KCODES
else
$(this).val("").removeClass(KLASS)
this.type = "password" if this.getAttribute("data-type") == "password"
restorePlaceholder = ->
if this.value.length == 0
$this = $(this)
$this.addClass(KLASS).val(this.getAttribute("data-placeholder"))
this.type = "text" if this.type == "password"
if $this.is(":focus")
rewindCaret.apply(this)
clearPlaceholdersAtSubmit = ->
$(this).find("input[data-placeholder]").each ->
$(this).val("") if hasPlaceholderValue(this)
hasPlaceholderValue = (field) ->
field.value == field.getAttribute("data-placeholder")
$.iOSPlaceholder = (filter) ->
$inputs = $("input[placeholder]")
$inputs = $inputs.filter(filter) if filter
$inputs.each ->
$this = $(this)
this.setAttribute "data-type", this.type
this.setAttribute "data-placeholder", this.getAttribute("placeholder")
this.removeAttribute "placeholder"
restorePlaceholder.apply this
$this.bind 'focus drop click', rewindCaret
$this.bind 'keydown', clearPlaceholder
$this.bind 'keyup blur', restorePlaceholder
$(this.form).submit clearPlaceholdersAtSubmit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment