UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

180 lines (153 loc) 6.33 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2012 1&1 Internet AG, Germany, http://www.1und1.de License: MIT: https://opensource.org/licenses/MIT See the LICENSE file in the project's top-level directory for details. Authors: * Martin Wittemann (wittemann) ************************************************************************ */ /** * The module supplies a fallback implementation for placeholders, which is * used on input and textarea elements. If the browser supports native placeholders * the API silently ignores all calls. If not, an element will be created for every * given input element and acts as placeholder. Most modern browsers support * placeholders which makes the fallback only relevant for IE < 10 and FF < 4. * * * <a href="http://dev.w3.org/html5/spec/single-page.html#the-placeholder-attribute">HTML Spec</a> * * * <a href="http://caniuse.com/#feat=input-placeholder">Browser Support</a> * * @require(qx.module.Manipulating) * @require(qx.module.Css) * @require(qx.module.Attribute) * @require(qx.module.Event) * @require(qx.module.Environment) * @require(qx.module.Polyfill) * @require(qx.module.Traversing) */ qx.Bootstrap.define("qx.module.Placeholder", { statics : { /** * String holding the property name which holds the placeholder * element for each input. */ PLACEHOLDER_NAME : "$qx_placeholder", /** * Queries for all input and textarea elements on the page and updates * their placeholder. * @attachStatic{qxWeb, placeholder.update} */ update : function() { // ignore if native placeholder are supported if (!qxWeb.env.get("css.placeholder")) { qxWeb("input[placeholder], textarea[placeholder]").updatePlaceholder(); } }, /** * Internal helper method to update the styles for a given input element. * @param item {qxWeb} The input element to update. */ __syncStyles : function(item) { var placeholder = item.getAttribute("placeholder"); var placeholderEl = item.getProperty(qx.module.Placeholder.PLACEHOLDER_NAME); var zIndex= item.getStyle("z-index"); var paddingHor = parseInt(item.getStyle("padding-left")) + 2 * parseInt(item.getStyle("padding-right")); var paddingVer = parseInt(item.getStyle("padding-top")) + 2 * parseInt(item.getStyle("padding-bottom")); placeholderEl.setHtml(placeholder).setStyles({ display : item.getValue() == "" ? "inline" : "none", zIndex : zIndex == "auto" ? 1 : zIndex + 1, textAlign: item.getStyle("text-align"), width: (item.getWidth() - paddingHor - 4) + "px", height: (item.getHeight() - paddingVer - 4) + "px", left: item.getPosition().left + "px", top: item.getPosition().top + "px", fontFamily : item.getStyle("font-family"), fontStyle : item.getStyle("font-style"), fontVariant : item.getStyle("font-variant"), fontWeight : item.getStyle("font-weight"), fontSize : item.getStyle("font-size"), paddingTop : (parseInt(item.getStyle("padding-top")) + 2) + "px", paddingRight : (parseInt(item.getStyle("padding-right")) + 2) + "px", paddingBottom : (parseInt(item.getStyle("padding-bottom")) + 2) + "px", paddingLeft : (parseInt(item.getStyle("padding-left")) + 2) + "px" }); }, /** * Creates a placeholder element based on the given input element. * @param item {qxWeb} The input element. * @return {qxWeb} The placeholder element. */ __createPlaceholderElement : function(item) { // create the label with initial styles var placeholderEl = qxWeb.create("<label>").setStyles({ position: "absolute", color: "#989898", overflow: "hidden", pointerEvents : "none" }); // store the label at the input field item.setProperty(qx.module.Placeholder.PLACEHOLDER_NAME, placeholderEl); // update the placeholders visibility on keyUp item.on("keyup", function(item) { var el = item.getProperty(qx.module.Placeholder.PLACEHOLDER_NAME); el.setStyle("display", item.getValue() == "" ? "inline" : "none"); }.bind(this, item)); // for browsers not supporting pointer events if (!qxWeb.env.get("css.pointerevents")) { placeholderEl.setStyle("cursor", "text").on("tap", function(item) { item.focus(); }.bind(this, item)); } return placeholderEl; } }, members : { /** * Updates the placeholders for input's and textarea's in the collection. * This includes positioning, styles and DOM positioning. * In case the browser supports native placeholders, this methods simply * does nothing. * * @attach {qxWeb} * @return {qxWeb} The collection for chaining */ updatePlaceholder : function() { // ignore everything if native placeholder are supported if (!qxWeb.env.get("css.placeholder")) { for (var i=0; i < this.length; i++) { var item = qxWeb(this[i]); // ignore all not fitting items in the collection var placeholder = item.getAttribute("placeholder"); var tagName = item.getProperty("tagName"); if (!placeholder || (tagName != "TEXTAREA"&& tagName != "INPUT")) { continue; } // create the element if necessary var placeholderEl = item.getProperty(qx.module.Placeholder.PLACEHOLDER_NAME); if (!placeholderEl) { placeholderEl = qx.module.Placeholder.__createPlaceholderElement(item); } // remove and add handling var itemInBody = item.isRendered(); var placeholderElInBody = placeholderEl.isRendered(); if (itemInBody && !placeholderElInBody) { item.before(placeholderEl); } else if (!itemInBody && placeholderElInBody) { placeholderEl.remove(); return this; } qx.module.Placeholder.__syncStyles(item); }; } return this; } }, defer : function(statics) { qxWeb.$attachAll(this, "placeholder"); } });