X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/ae032450627538fabf7df31fbda6cf7bd097b94f..5ecc2f0247f9d648dc1795b9633a3c37cc86bb52:/src/wlxml/wlxml.js diff --git a/src/wlxml/wlxml.js b/src/wlxml/wlxml.js index c3ed84f..f370223 100644 --- a/src/wlxml/wlxml.js +++ b/src/wlxml/wlxml.js @@ -2,28 +2,66 @@ define([ 'libs/jquery', 'libs/underscore', 'smartxml/smartxml', - 'smartxml/transformations' -], function($, _, smartxml, transformations) { + 'smartxml/transformations', + 'wlxml/extensions/metadata/metadata', + 'wlxml/extensions/comments/comments' +], function($, _, smartxml, transformations, metadataExtension, commentExtension) { 'use strict'; /* globals Node */ -var metadataKey = 'wlxml.metadata'; +var WLXMLDocumentNodeMethods = { + isInside: function(query) { + var parent = this.getParent(query); + return !!parent; + }, + getParent: function(query) { + /* globals Node */ + var me = this.nodeType === Node.ELEMENT_NODE ? [this] : [], + toret; + me.concat(this.parents()).some(function(node) { + if(node.is(query)) { + toret = node; + return true; + } + }); + return toret; + }, +}; + var AttributesList = function() {}; AttributesList.prototype = Object.create({}); AttributesList.prototype.keys = function() { return _.keys(this); }; +var getClassLists = function(klassName) { + var toret = [], + classParts = [''].concat(klassName.split('.')), + classCurrent; + + classParts.forEach(function(part) { + classCurrent = classCurrent ? classCurrent + '.' + part : part; + toret.push(classCurrent); + }); + return toret; +}; + var installObject = function(instance, klass) { - var methods = instance.document.classMethods[klass] || {}, - transformations = instance.document.classTransformations[klass] || {}; + var methods = {}, + transformations = {}; + getClassLists(klass).forEach(function(klassName) { + _.extend(methods, instance.document.classMethods[klassName] || {}); + _.extend(methods, instance.document.classTransformations[klassName] || {}); + }); instance.object = Object.create(_.extend({}, methods, transformations)); _.keys(methods).concat(_.keys(transformations)).forEach(function(key) { - instance.object[key] = _.bind(instance.object[key], instance); + if(_.isFunction(instance.object[key])) { + instance.object[key] = _.bind(instance.object[key], instance); + } }); }; @@ -33,18 +71,30 @@ var WLXMLElementNode = function(nativeNode, document) { }; WLXMLElementNode.prototype = Object.create(smartxml.ElementNode.prototype); -$.extend(WLXMLElementNode.prototype, smartxml.ElementNode.prototype, { +$.extend(WLXMLElementNode.prototype, WLXMLDocumentNodeMethods, smartxml.ElementNode.prototype, { getClass: function() { return this.getAttr('class') || ''; }, + getClassHierarchy: function() { + return getClassLists(this.getClass()); + }, setClass: function(klass) { if(klass !== this.klass) { installObject(this, klass); return this.setAttr('class', klass); } }, - is: function(klass) { - return this.getClass().substr(0, klass.length) === klass; + is: function(query) { + if(typeof query === 'string') { + query = {klass: query}; + } + return (_.isUndefined(query.klass) || this.getClass().substr(0, query.klass.length) === query.klass) && + (_.isUndefined(query.tagName) || this.getTagName() === query.tagName); + }, + hasChild: function(query) { + return this.contents().some(function(child) { + return child.is(query); + }.bind(this)); }, getMetaAttributes: function() { var toret = new AttributesList(), @@ -79,26 +129,6 @@ $.extend(WLXMLElementNode.prototype, smartxml.ElementNode.prototype, { return attrName !== 'class' &&_.contains(_.keys(this.getMetaAttributes()), attrName); }, - getMetadata: function() { - return this.getData(metadataKey) || []; - }, - - addMetadataRow: function(row) { - this.setMetadataRow(null, row); - }, - - setMetadataRow: function(index, row) { - var metadata = this.getData(metadataKey) || []; - if(typeof index !== 'number' || index > metadata.length - 1) { - metadata.push(row); - index = metadata.length - 1; - } else { - metadata[index] = _.extend(metadata[index], row); - } - this.setData(metadataKey, metadata); - this.triggerChangeEvent('metadataChange', {index: index}); - }, - _getXMLDOMToDump: function() { var DOM = this._$.clone(true, true), doc = this.document; @@ -179,10 +209,19 @@ var WLXMLDocumentNode = function() { }; WLXMLDocumentNode.prototype = Object.create(smartxml.DocumentNode.prototype); + +var WLXMLTextNode = function() { + smartxml.TextNode.apply(this, arguments); +}; +WLXMLTextNode.prototype = Object.create(smartxml.TextNode.prototype); +$.extend(WLXMLTextNode.prototype, WLXMLDocumentNodeMethods, { + is: function() { return false; } +}); + var WLXMLDocument = function(xml, options) { this.classMethods = {}; this.classTransformations = {}; - smartxml.Document.call(this, xml); + smartxml.Document.call(this, xml, [metadataExtension, commentExtension]); this.options = options; }; @@ -192,6 +231,7 @@ var formatter_prefix = '_wlxml_formatter_'; WLXMLDocument.prototype = Object.create(smartxml.Document.prototype); $.extend(WLXMLDocument.prototype, { ElementNodeFactory: WLXMLElementNode, + TextNodeFactory: WLXMLTextNode, loadXML: function(xml) { smartxml.Document.prototype.loadXML.call(this, xml, {silent: true}); this.trigger('contentSet'); @@ -201,6 +241,18 @@ $.extend(WLXMLDocument.prototype, { var doc = this, prefixLength = 'dc:'.length; + $(nativeNode).find('metadata').each(function() { + var metadataNode = $(this), + owner = doc.createDocumentNode(metadataNode.parent()[0]), + metadata = owner.getMetadata(); + + metadataNode.children().each(function() { + metadata.add({key: (this.tagName).toLowerCase().substr(prefixLength), value: $(this).text()}, {undoable: false}); + }); + metadataNode.remove(); + }); + nativeNode.normalize(); + $(nativeNode).find(':not(iframe)').addBack().contents() .filter(function() {return this.nodeType === Node.TEXT_NODE;}) .each(function() { @@ -284,21 +336,14 @@ $.extend(WLXMLDocument.prototype, { el.replaceWith(document.createTextNode(text.transformed)); }); - $(nativeNode).find('metadata').each(function() { - var metadataNode = $(this), - owner = doc.createDocumentNode(metadataNode.parent()[0]); - - metadataNode.children().each(function() { - owner.addMetadataRow({key: (this.tagName).toLowerCase().substr(prefixLength), value: $(this).text()}); - }); - metadataNode.remove(); - }); + }, registerClassTransformation: function(Transformation, className) { var thisClassTransformations = (this.classTransformations[className] = this.classTransformations[className] || {}); - thisClassTransformations[Transformation.prototype.name] = function(args) { + thisClassTransformations[Transformation.prototype.name] = function() { var nodeInstance = this; + var args = Array.prototype.slice.call(arguments, 0); return nodeInstance.transform(Transformation, args); }; }, @@ -342,14 +387,18 @@ var wlxmlClasses = { return { - WLXMLDocumentFromXML: function(xml, options) { + WLXMLDocumentFromXML: function(xml, options, Factory) { options = _.extend({wlxmlClasses: wlxmlClasses}, options); - return new WLXMLDocument(xml, options); + Factory = Factory || WLXMLDocument; + return new Factory(xml, options); }, WLXMLElementNodeFromXML: function(xml) { return this.WLXMLDocumentFromXML(xml).root; - } + }, + + WLXMLDocument: WLXMLDocument, + getClassHierarchy: getClassLists }; }); \ No newline at end of file