UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

157 lines (135 loc) 4.69 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2019-2020 Zenesis Limited, https://www.zenesis.com License: MIT: https://opensource.org/licenses/MIT See the LICENSE file in the project's top-level directory for details. Authors: * John Spackman (https://github.com/johnspackman, john.spackman@zenesis.com) ************************************************************************ */ /** * Factory class used to create Virtual DOM instances by JSX support */ qx.Class.define("qx.html.Factory", { extend: qx.core.Object, type: "singleton", construct() { super(); this.__factoriesByTagName = {}; this.registerFactory( "#text", (tagName, styles, attributes) => new qx.html.Text("") ); this.registerFactory( "iframe", (tagName, styles, attributes) => new qx.html.Iframe(attributes.src, styles, attributes) ); this.registerFactory( "input", (tagName, styles, attributes) => new qx.html.Input(attributes.type || "text", styles, attributes) ); this.registerFactory("slot", (tagName, styles, attributes) => { if (tagName !== "slot") { throw new Error( `Cannot create slot with tag <${tagName}> - only <slot> is supported` ); } if (Object.keys(styles).length > 0) { throw new Error( `Cannot create slot with attribute "style" - only the "name" attribute is supported` ); } Object.keys(attributes).forEach(key => { if (key !== "name") { throw new Error( `Cannot create slot with attribute "${key}" - only the "name" attribute is supported` ); } }); return new qx.html.Slot(attributes.name); }); }, members: { __factoriesByTagName: null, /** * Registers a factory; a factory is either a class, or a function which is * called with the parameters (tagName {String}, styles{Map?}, attributes {Map?}), and * which is expected to return an {Element} * * @param tagName {String} the name of the tag * @param factory {Class|Function} the function used to create instances for that tagName */ registerFactory(tagName, factory) { tagName = tagName.toLowerCase(); if (this.__factoriesByTagName[tagName] === undefined) { this.__factoriesByTagName[tagName] = []; } this.__factoriesByTagName[tagName].push(factory); }, /** * Called to create an {Element} * * @param tagName {String} the name of the tag * @param attributes {Map?} the attributes to create (including style etc) * @return {qx.html.Node} */ createElement(tagName, attributes) { tagName = tagName.toLowerCase(); if (attributes) { if (window.NamedNodeMap && attributes instanceof window.NamedNodeMap) { var newAttrs = {}; for (var i = attributes.length - 1; i >= 0; i--) { newAttrs[attributes[i].name] = attributes[i].value; } attributes = newAttrs; } var styles = {}; if (attributes.style) { attributes.style.split(/;/).forEach(function (seg) { var pos = seg.indexOf(":"); var key = seg.substring(0, pos); var value = seg.substring(pos + 1).trim(); if (key) { styles[key] = value; } }); delete attributes.style; } var classname = attributes["data-qx-classname"]; if (classname) { var clazz = qx.Class.getByName(classname); if (qx.core.Environment.get("qx.debug")) { this.assertTrue( clazz && qx.Class.isSubClassOf(clazz, qx.html.Element) ); return new clazz(tagName, styles, attributes); } } } var factories = this.__factoriesByTagName[tagName]; if (factories) { for (var i = factories.length - 1; i > -1; i--) { var factory = factories[i]; if ( factory.classname && qx.Class.getByName(factory.classname) === factory ) { return new factory(tagName, styles, attributes); } if (qx.core.Environment.get("qx.debug")) { this.assertTrue(typeof factory == "function"); } var element = factory(tagName, styles, attributes); if (element) { return element; } } } return new qx.html.Element(tagName, styles, attributes); } } });