Follow me: @D_mitar

Most read posts recently



Oct 31st 2011 × mooPlaceholder revisited: a flexible placeholder input solution for IE and older browsers

Creating some javascript that can mimic the HTML5 behavior of a placeholder= attribute on an input element can be simple. Unfortunately, getting a single solution you can work with that fits all browsers and have little overhead to work with is not that easy.

The following are the requirements when making it universal:

  • work as progressive enhancement for browsers that don’t support it only (feature-detect)
  • respect initial values
  • be able to attach and detach the placeholder behavior on demand

Since the progressive enhancement only works by using the value property of the input in older browsers, it presents a problem for form validation. You don’t want your form submission to go through with fields that have the placeholders assigned as the actual values. This is not what the native placeholder behavior is so you need a way to remove the enhancement prior to your form validation and submission. You also need to be able to re-attach it, should validation fail and submission be stopped pending user action.

http://jsfiddle.net/dimitar/bYQ8P/ is the updated mooPlaceholder class. I suggest you view it in IE6/7/8 to actually experience the difference. It should act *exactly* how the placeholder works in say, FireFox 7. To get around the jsfiddle issues with IE, view it under the full /show/ url here

So, to recap: if you want to validate a form that has child elements managed by the class, you’d do the following when using my Class:

var placeholders = new mooPlaceholder().attachToElements(); // add it.
formElement.addEvent("submit", function(e) {
    // remove placeholder while validating...
    placeholders.detachFromElements();
    // run validation code here.
    if (failed) {
        e.stop(); // stop submit
        placeholders.attachToElements(); // restore placeholders
    }
});

I think this overhead is quite acceptable, considering. It can be done automatically on your form submits by doing a element.getParent(“form”) but this way is also fine. Hope it helps somebody.


May 7th 2010 × mooPlaceholder: input placeholder behaviour class

Some of the HTML5 features just won’t come fast enough. One such feature is the ability to apply a placeholder input attribute, something like placeholder=’your text’ which takes the text and sets it as a pseudo default input value until it’s focused or changed. Currently (at time of writing), this only works in webkit-based browsers like Chrome and Safari but it’s not difficult to bring it into all other browsers.

Here’s a little class / mootools plugin that I wrote to do it:

var mooPlaceholder = new Class({
    // behaviour for default values of inputs class
    Implements: [Options],

    options: {
        // default options
        htmlPlaceholder: "placeholder", // the element attribute, eg, data-placeholder="MM/YY" -> "data-placeholder"
        unmoddedClass: "unchanged", // apply a class to the unmodded input, say, to grey it out
        parentNode: document, // limit to a particular set of child nodes
        defaultSelector: "input[placeholder]"
    },

    initialize: function(options) {
        this.setOptions(options);
        // detect native support (nothing gets done if true)
        this.nativeSupport = 'placeholder' in document.createElement('input');
    },

    attachToElements: function(selector) {
        // basic function example that uses a class selector to
        var inputs = this.options.parentNode.getElements(selector || this.options.defaultSelector);

        if (inputs.length) {
            inputs.each(function(el) {
                this.attachEvents(el);
            }, this);
        }
    }, // end attachToElements

    attachEvents: function(el, placeholder) {
        // method that attaches the events to an input element.
        var placeholder = placeholder || el.get(this.options.htmlPlaceholder);
        if (this.nativeSupport || !$(el) || !placeholder || !placeholder.length)
            return;

        el.set("value", placeholder).store("placeholder", placeholder);

        // append unmodded class to input at start
        if (this.options.unmoddedClass)
            el.addClass(this.options.unmoddedClass);

        // now cater for the events
        el.addEvents({
            change: function() {
                // when value changes
                var value = el.get("value").trim(), placeholder = el.retrieve("placeholder");
                if (value != placeholder) {
                    // once it changes, remove this check and remove the unmoddedClass
                    el.removeClass(this.options.unmoddedClass).removeEvents("change");
                }
            }.bind(this),

            focus: function() {
                var value = el.get("value").trim(), placeholder = el.retrieve("placeholder");
                if (value == placeholder) {
                    el.set("value", "").removeClass(this.options.unmoddedClass);
                }
            }.bind(this),
            blur: function() {
                var value = el.get("value").trim(), placeholder = el.retrieve("placeholder");
                if (value == placeholder || value == "") {
                    el.set("value", placeholder).addClass(this.options.unmoddedClass);
                }
            }.bind(this)
        });
    }
});

// example use for a single element:
new mooPlaceholder().attachEvents($("searchfield"), "type here to search site..."); // override placeholder

new mooPlaceholder().attachEvents($("searchfield")); // use placeholder= value instead

// example use for any input element that has a placeholder property:
new mooPlaceholder().attachToElements(); // defaults to "input[placeholder]"

// or a custom selector
new mooPlaceholder().attachToElements("input.foo");

// or only inputs of a particular form with a particular class (required)
new mooPlaceholder({
    parentNode: $("mysignupform"),
}).attachToElements("input.required[placeholder]");

Clearly, many ways to use it. It will only work as progressive enhancement and won’t attach anything if the browser already supports placeholders.

Make sue you set the CSS class for the unmodded input (look at the CSS tab on JSFIDDLE for an example) – it seems that natively, the text goes to #A9A9A9 but you may be able to override that. Vendor specific CSS styles allow you to work with this:

input.unmodded::-webkit-input-placeholder {
    color: rgb(100, 0, 0);
}

Have fun.