diff --git a/demos/blockfactory/factory_utils.js b/demos/blockfactory/factory_utils.js index b02bfa034..bfcd66b00 100644 --- a/demos/blockfactory/factory_utils.js +++ b/demos/blockfactory/factory_utils.js @@ -921,12 +921,12 @@ FactoryUtils.sameBlockXml = function(blockXml1, blockXml2) { // Each XML element should contain a single child element with a 'block' tag if (blockXml1.tagName.toLowerCase() != 'xml' || blockXml2.tagName.toLowerCase() != 'xml') { - throw new Error('Expected two XML elements, recieved elements with tag ' + + throw new Error('Expected two XML elements, received elements with tag ' + 'names: ' + blockXml1.tagName + ' and ' + blockXml2.tagName + '.'); } // Compare the block elements directly. The XML tags may include other meta - // information we want to igrore. + // information we want to ignore. var blockElement1 = blockXml1.getElementsByTagName('block')[0]; var blockElement2 = blockXml2.getElementsByTagName('block')[0]; @@ -934,8 +934,11 @@ FactoryUtils.sameBlockXml = function(blockXml1, blockXml2) { throw new Error('Could not get find block element in XML.'); } - var blockXmlText1 = Blockly.Xml.domToText(blockElement1); - var blockXmlText2 = Blockly.Xml.domToText(blockElement2); + var cleanBlockXml1 = FactoryUtils.cleanXml(blockElement1); + var cleanBlockXml2 = FactoryUtils.cleanXml(blockElement2); + + var blockXmlText1 = Blockly.Xml.domToText(cleanBlockXml1); + var blockXmlText2 = Blockly.Xml.domToText(cleanBlockXml2); // Strip white space. blockXmlText1 = blockXmlText1.replace(/\s+/g, ''); @@ -945,6 +948,47 @@ FactoryUtils.sameBlockXml = function(blockXml1, blockXml2) { return blockXmlText1 == blockXmlText2; }; +/** + * Strips the provided xml of any attributes that don't describe the + * 'structure' of the blocks (i.e. block order, field values, etc). + * @param {Node} xml The xml to clean. + * @return {Node} + */ +FactoryUtils.cleanXml = function(xml) { + var newXml = xml.cloneNode(true); + var node = newXml; + while (node) { + // Things like text inside tags are still treated as nodes, but they + // don't have attributes (or the removeAttribute function) so we can + // skip removing attributes from them. + if (node.removeAttribute) { + node.removeAttribute('xmlns'); + node.removeAttribute('x'); + node.removeAttribute('y'); + node.removeAttribute('id'); + } + + // Try to go down the tree + var nextNode = node.firstChild || node.nextSibling; + // If we can't go down, try to go back up the tree. + if (!nextNode) { + nextNode = node.parentNode; + while (nextNode) { + // We are valid again! + if (nextNode.nextSibling) { + nextNode = nextNode.nextSibling; + break; + } + // Try going up again. If parentNode is null that means we have + // reached the top, and we will break out of both loops. + nextNode = nextNode.parentNode; + } + } + node = nextNode; + } + return newXml; +}; + /* * Checks if a block has a variable field. Blocks with variable fields cannot * be shadow blocks.