From 31c2165770406732c20e19cf428aa9cb84026c64 Mon Sep 17 00:00:00 2001 From: Catrope Date: Wed, 8 May 2013 00:38:50 -0700 Subject: [PATCH] Also render attributes of the form html/i-j/attrName in CE Factored the parsing of html/* attributes out into a static function. Factored attribute (re)rendering out into ce.View, attribute updates are much simpler now. Change-Id: I4caa6d5e1e2c21c28ddff61c3c864e47f66cc6b2 --- modules/ve/ce/ve.ce.Node.js | 14 +---------- modules/ve/ce/ve.ce.View.js | 26 ++++++++++++++------ modules/ve/dm/ve.dm.Converter.js | 42 ++++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/modules/ve/ce/ve.ce.Node.js b/modules/ve/ce/ve.ce.Node.js index 16cb9e7031..2a5bf96408 100644 --- a/modules/ve/ce/ve.ce.Node.js +++ b/modules/ve/ce/ve.ce.Node.js @@ -63,19 +63,7 @@ ve.ce.Node.static.canBeSplit = false; * @param {string} to New value */ ve.ce.Node.prototype.onAttributeChange = function ( key, from, to ) { - var htmlKey = key.substr( 7 ).toLowerCase(); - if ( - this.constructor.static.renderHtmlAttributes && - key.indexOf( 'html/0/' ) === 0 && - htmlKey.length && - this.constructor.static.domAttributeWhitelist.indexOf( htmlKey ) !== -1 - ) { - if ( to === undefined ) { - this.$.removeAttr( htmlKey ); - } else { - this.$.attr( htmlKey, to ); - } - } + this.renderAttributes( { key: to } ); }; /** diff --git a/modules/ve/ce/ve.ce.View.js b/modules/ve/ce/ve.ce.View.js index 188ac6d567..891bd8a366 100644 --- a/modules/ve/ce/ve.ce.View.js +++ b/modules/ve/ce/ve.ce.View.js @@ -26,13 +26,7 @@ ve.ce.View = function VeCeView( model, $element ) { // Initialization this.$.data( 'view', this ); - if ( this.constructor.static.renderHtmlAttributes ) { - ve.setDomAttributes( - this.$[0], - this.model.getAttributes( 'html/0/' ), - this.constructor.static.domAttributeWhitelist - ); - } + this.renderAttributes( this.model.getAttributes() ); }; /* Inheritance */ @@ -116,3 +110,21 @@ ve.ce.View.prototype.setLive = function ( live ) { this.live = live; this.emit( 'live' ); }; + +ve.ce.View.prototype.renderAttributes = function ( attributes ) { + var key, parsed, + whitelist = this.constructor.static.domAttributeWhitelist; + if ( !this.constructor.static.renderHtmlAttributes ) { + return; + } + for ( key in attributes ) { + parsed = ve.dm.Converter.parseHtmlAttribute( key, this.$ ); + if ( parsed && whitelist.indexOf( parsed.attribute ) !== -1 ) { + if ( attributes[key] === undefined ) { + parsed.domElement.removeAttribute( parsed.attribute ); + } else { + parsed.domElement.setAttribute( parsed.attribute, attributes[key] ); + } + } + } +}; \ No newline at end of file diff --git a/modules/ve/dm/ve.dm.Converter.js b/modules/ve/dm/ve.dm.Converter.js index ff1af085a0..dd16935b47 100644 --- a/modules/ve/dm/ve.dm.Converter.js +++ b/modules/ve/dm/ve.dm.Converter.js @@ -100,6 +100,31 @@ ve.dm.Converter.openAndCloseAnnotations = function ( currentSet, targetSet, open } }; +/** + * Parse a linear model attribute name of the form html/i-j-k/attrName. + * + * @param {string} attribute Name of a linear model attribute + * @param {HTMLElement[]|jQuery} domElements DOM elements array that the attribute indexes into + * @returns {Object|null} Object with domElement and attribute keys, or null + */ +ve.dm.Converter.parseHtmlAttribute = function ( attribute, domElements ) { + var i, ilen, indexes, child, + /*jshint regexp:false */ + matches = attribute.match( /^html\/((?:\d+\-)*\d)\/(.*)$/ ); + if ( !matches ) { + return null; + } + indexes = matches[1].split( '-' ); // matches[1] like '1-2-3' + child = domElements[indexes[0]]; + for ( i = 1, ilen = indexes.length; i < ilen; i++ ) { + child = child && child.childNodes[indexes[i]]; + } + if ( !child ) { + return null; + } + return { 'domElement': child, 'attribute': matches[2] }; +}; + /* Methods */ /** @@ -201,7 +226,7 @@ ve.dm.Converter.prototype.canCloseWrapper = function () { * @returns {HTMLElement|boolean} DOM element, or false if the element cannot be converted */ ve.dm.Converter.prototype.getDomElementsFromDataElement = function ( dataElements, doc ) { - var domElements, dataElementAttributes, key, matches, indexes, i, ilen, child, + var domElements, dataElementAttributes, key, parsed, dataElement = ve.isArray( dataElements ) ? dataElements[0] : dataElements, nodeClass = this.modelRegistry.lookup( dataElement.type ); @@ -218,18 +243,9 @@ ve.dm.Converter.prototype.getDomElementsFromDataElement = function ( dataElement dataElementAttributes = dataElement.attributes; if ( dataElementAttributes ) { for ( key in dataElementAttributes ) { - // Only include 'html/*' attributes and strip the prefix - /*jshint regexp:false */ - matches = key.match( /^html\/((?:\d+\-)*\d)\/(.*)$/ ); - if ( matches ) { - indexes = matches[1].split( '-' ); // matches[1] like '1-2-3' - child = domElements[indexes[0]]; - for ( i = 1, ilen = indexes.length; i < ilen; i++ ) { - child = child && child.childNodes[indexes[i]]; - } - if ( child && !child.hasAttribute( matches[2] ) ) { - child.setAttribute( matches[2], dataElementAttributes[key] ); - } + parsed = ve.dm.Converter.parseHtmlAttribute( key, domElements ); + if ( parsed && !parsed.domElement.hasAttribute( parsed.attribute ) ) { + parsed.domElement.setAttribute( parsed.attribute, dataElementAttributes[key] ); } } }