From 6d12e07b28ec388ace97585992d555846354389a Mon Sep 17 00:00:00 2001 From: Alexander Gugel Date: Thu, 4 Jun 2015 15:11:34 +0200 Subject: [PATCH 1/2] fix: Prevent nested void elements [#96086006] Addresses nested img tags issue #226 --- dom-renderers/DOMRenderer.js | 6 +++++ dom-renderers/ElementCache.js | 23 +++++++++------- dom-renderers/VoidElements.js | 51 +++++++++++++++++++++++++++++++++++ dom-renderers/index.js | 11 ++++---- 4 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 dom-renderers/VoidElements.js diff --git a/dom-renderers/DOMRenderer.js b/dom-renderers/DOMRenderer.js index af0bda2b..f73b7871 100644 --- a/dom-renderers/DOMRenderer.js +++ b/dom-renderers/DOMRenderer.js @@ -420,6 +420,12 @@ DOMRenderer.prototype.insertEl = function insertEl (tagName) { this._assertParentLoaded(); this._assertChildrenLoaded(); + if (this._parent.void) + throw new Error( + this._parent.path + ' is a void element. ' + + 'Void elements are not allowed to have children.' + ); + if (this._target) this._parent.element.removeChild(this._target.element); this._target = new ElementCache(document.createElement(tagName), this._path); diff --git a/dom-renderers/ElementCache.js b/dom-renderers/ElementCache.js index 7a896bfa..9282c523 100644 --- a/dom-renderers/ElementCache.js +++ b/dom-renderers/ElementCache.js @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * + * * Copyright (c) 2015 Famous Industries Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -24,7 +24,9 @@ 'use strict'; -// Transform identity matrix. +var VoidElements = require('./VoidElements'); + +// Transform identity matrix. var ident = [ 1, 0, 0, 0, 0, 1, 0, 0, @@ -37,13 +39,16 @@ var ident = [ * path, world transform, inverted parent, final transform (as being used for * setting the actual `transform`-property) and post render size (final size as * being rendered to the DOM). - * + * * @class ElementCache - * + * * @param {Element} element DOMElement - * @param {String} path Path used for uniquely identifying the location in the scene graph. - */ + * @param {String} path Path used for uniquely identifying the location in the + * scene graph. + */ function ElementCache (element, path) { + this.tagName = element.tagName.toLowerCase(); + this.void = VoidElements[this.tagName]; this.element = element; this.path = path; this.content = null; diff --git a/dom-renderers/VoidElements.js b/dom-renderers/VoidElements.js new file mode 100644 index 00000000..edd5c584 --- /dev/null +++ b/dom-renderers/VoidElements.js @@ -0,0 +1,51 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2015 Famous Industries Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +'use strict'; + +/** + * Map of void elements as defined by the + * [HTML5 spec](http://www.w3.org/TR/html5/syntax.html#elements-0). + * + * @type {Object} + */ +var VoidElements = { + area : true, + base : true, + br : true, + col : true, + embed : true, + hr : true, + img : true, + input : true, + keygen: true, + link : true, + meta : true, + param : true, + source: true, + track : true, + wbr : true +}; + +module.exports = VoidElements; diff --git a/dom-renderers/index.js b/dom-renderers/index.js index 3708100e..2343cc5a 100644 --- a/dom-renderers/index.js +++ b/dom-renderers/index.js @@ -1,18 +1,18 @@ /** * The MIT License (MIT) - * + * * Copyright (c) 2015 Famous Industries Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -28,5 +28,6 @@ module.exports = { DOMRenderer: require('./DOMRenderer'), ElementCache: require('./ElementCache'), Events: require('./events'), - Math: require('./Math') + Math: require('./Math'), + VoidElements: require('./VoidElements') }; From 1f5c8f55a1959a35f5687afe188f76df0ad0e855 Mon Sep 17 00:00:00 2001 From: Alexander Gugel Date: Thu, 4 Jun 2015 18:08:24 +0200 Subject: [PATCH 2/2] fix: Correctly set content on textarea and input elements [#96172404] --- dom-renderers/DOMRenderer.js | 22 ++++++++++++++-------- dom-renderers/ElementCache.js | 7 +++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/dom-renderers/DOMRenderer.js b/dom-renderers/DOMRenderer.js index f73b7871..4fdc0103 100644 --- a/dom-renderers/DOMRenderer.js +++ b/dom-renderers/DOMRenderer.js @@ -564,15 +564,21 @@ DOMRenderer.prototype.setContent = function setContent(content) { this._assertTargetLoaded(); this.findChildren(); - if (!this._target.content) { - this._target.content = document.createElement('div'); - this._target.content.classList.add('famous-dom-element-content'); - this._target.element.insertBefore( - this._target.content, - this._target.element.firstChild - ); + if (this._target.formElement) { + this._target.element.value = content; } - this._target.content.innerHTML = content; + else { + if (!this._target.content) { + this._target.content = document.createElement('div'); + this._target.content.classList.add('famous-dom-element-content'); + this._target.element.insertBefore( + this._target.content, + this._target.element.firstChild + ); + } + this._target.content.innerHTML = content; + } + this.setSize( this._target.explicitWidth ? false : this._target.size[0], diff --git a/dom-renderers/ElementCache.js b/dom-renderers/ElementCache.js index 9282c523..9f56dd05 100644 --- a/dom-renderers/ElementCache.js +++ b/dom-renderers/ElementCache.js @@ -49,6 +49,13 @@ var ident = [ function ElementCache (element, path) { this.tagName = element.tagName.toLowerCase(); this.void = VoidElements[this.tagName]; + + var constructor = element.constructor; + + this.formElement = constructor === HTMLInputElement || + constructor === HTMLTextAreaElement || + constructor === HTMLSelectElement; + this.element = element; this.path = path; this.content = null;