},
setText: function(text, node) {
//this.canvas.wlxmlDocument.transform('setText', {node:node, text: text});
- node.transform('setText', {text: text});
+ node.transform('smartxml.setText', {text: text});
}
}
//var nodes = position.element.data('wlxmlNode').split({offset: position.offset}),
- var nodes = position.element.data('wlxmlNode').transform('split', {offset: position.offset}),
- newEmpty,
- goto,
- gotoOptions;
-
- if(position.offsetAtBeginning)
- newEmpty = nodes.first;
- else if(position.offsetAtEnd)
- newEmpty = nodes.second;
+ // var nodes = position.element.data('wlxmlNode').transform('split', {offset: position.offset}),
+ // newEmpty,
+ // goto,
+ // gotoOptions;
+
+ // if(position.offsetAtBeginning)
+ // newEmpty = nodes.first;
+ // else if(position.offsetAtEnd)
+ // newEmpty = nodes.second;
- if(newEmpty) {
- //goto = newEmpty.append({text: ''});
+ // if(newEmpty) {
+ // //goto = newEmpty.append({text: ''});
+ // gotoOptions = {};
+ // } else {
+ // goto = nodes.second;
+ // gotoOptions = {caretTo: 'start'};
+ // }
+
+ var result = position.element.data('wlxmlNode').transform('rng.breakContent', {offset: position.offset}),
+ goto, gotoOptions;
+ if(result.emptyText) {
+ goto = result.createdEmpty;
gotoOptions = {};
} else {
- goto = nodes.second;
- gotoOptions = {caretTo: 'start'};
+ goto = result.second;
+ gotoOptions = {caretTo: 'start'};
}
canvas.setCurrentElement(utils.findCanvasElement(goto), gotoOptions);
parent1 = selectionStart.element.parent() || undefined,
parent2 = selectionEnd.element.parent() || undefined;
- canvas.wlxmlDocument.transform('detach2', {node:canvas.getCurrentNodeElement().data('wlxmlNode')});
+// canvas.wlxmlDocument.transform('detach2', {node:canvas.getCurrentNodeElement().data('wlxmlNode')});
+ canvas.getCurrentNodeElement().data('wlxmlNode').transform('smartxml.detach');
+
});
commands.register('unwrap-node', function(canvas) {
if(cursor.isSelectingWithinElement()) {
var wlxmlNode = selectionStart.element.data('wlxmlNode'),
caretTo = selectionStart.offset < selectionEnd.offset ? 'start' : 'end',
- wrapper = wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}, start: selectionStart.offset, end: selectionEnd.offset}),
- wrapperCanvasElement = utils.findCanvasElement(wrapper);
+ //wrapper = wlxmlNode.wrapWith({tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}, start: selectionStart.offset, end: selectionEnd.offset}),
+ wrapper = wlxmlNode.transform('smartxml.wrapWith', {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}, start: selectionStart.offset, end: selectionEnd.offset})
+ ;
+ var wrapperCanvasElement = utils.findCanvasElement(wrapper);
canvas.setCurrentElement(wrapperCanvasElement.children()[0], {caretTo: caretTo});
}
else {
var wlxmlNode = selectionStart.element.data('wlxmlNode').parent(),
caretTo = selectionStart.element.sameNode(cursor.getSelectionAnchor().element) ? 'end' : 'start';
- var wrapper = wlxmlNode.wrapText({
+ // var wrapper = wlxmlNode.wrapText({
+ // _with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}},
+ // offsetStart: selectionStart.offset,
+ // offsetEnd: selectionEnd.offset,
+ // textNodeIdx: [wlxmlNode.indexOf(selectionStart.element.data('wlxmlNode')), wlxmlNode.indexOf(selectionEnd.element.data('wlxmlNode'))] //parent.childIndex(selectionEnd.element)]
+ // }),
+ var wrapper = wlxmlNode.transform('smartxml.wrapText', {
_with: {tagName: params.wlxmlTag, attrs: {'class': params.wlxmlClass}},
offsetStart: selectionStart.offset,
offsetEnd: selectionEnd.offset,
siblingParents = canvas.wlxmlDocument.getSiblingParents({node1: node1, node2: node2});
if(siblingParents) {
- canvas.wlxmlDocument.wrapNodes({
- element1: siblingParents.node1,
- element2: siblingParents.node2,
+ // canvas.wlxmlDocument.wrapNodes({
+ // element1: siblingParents.node1,
+ // element2: siblingParents.node2,
+ // _with: {tagName: params.wlxmlTag, attrs: {klass: params.wlxmlClass}}
+ // });
+ canvas.wlxmlDocument.transform('smartxml.wrapNodes', {
+ node1: siblingParents.node1,
+ node2: siblingParents.node2,
_with: {tagName: params.wlxmlTag, attrs: {klass: params.wlxmlClass}}
});
}
}
} else if(canvas.getCurrentNodeElement()) {
- var node = findCanvasElement(canvas.getCurrentNodeElement),
- wrapper = node.wrapWith({tagName: params.wlxmlTag, attrs: {klass: params.wlxmlClass}});
- canvas.setCurrentElement(findCanvasElement(wrapper));
+ var node = canvas.getCurrentNodeElement().data('wlxmlNode'),
+ // wrapper = node.wrapWith({tagName: params.wlxmlTag, attrs: {klass: params.wlxmlClass}});
+ wrapper = node.transform('smartxml.wrapWith', {tagName: params.wlxmlTag, attrs: {klass: params.wlxmlClass}});
+ canvas.setCurrentElement(utils.findCanvasElement(wrapper));
}
if(attr === 'Class') {
//currentNode.document.transform('setClass', {node: currentNode, klass: value});
- currentNode.transform('setAttr', {name: 'class', value: value});
+ currentNode.transform('smartxml.setAttr', {name: 'class', value: value});
}
//currentNode['set' + attr](value);
});
-
+
return {
start: function() {
sandbox.publish('ready');
return view;
},
setNodeElement: function(wlxmlNodeElement) {
+ var module = this;
+ if(!currentNode) {
+ wlxmlNodeElement.document.on('change', function(event) {
+ if(event.type === 'nodeAttrChange' && event.meta.node.sameNode(currentNode)) {
+ module.setNodeElement(currentNode);
+ }
+ });
+ }
+
view.find('.rng-module-nodePane-tagSelect').val(wlxmlNodeElement.getTagName());
var escapedClassName = (wlxmlNodeElement.getClass() || '').replace(/\./g, '-');
var widget = metaWidget.create({attrs:wlxmlNodeElement.getMetaAttributes()});
widget.on('valueChanged', function(key, value) {
- wlxmlNodeElement.setMetaAttribute(key, value);
+ wlxmlNodeElement.transform('wlxml.setMetaAttribute', {name: key, value: value});
+ //wlxmlNodeElement.setMetaAttribute(key, value);
});
view.find('.metaFields').empty().append(widget.el);
--- /dev/null
+define([
+
+], function() {
+
+'use strict';
+
+var breakContentTransformation = {
+ impl: function(args) {
+ var node = this.context,
+ newNodes, emptyNode, emptyText;
+ newNodes = node.transform('smartxml.split', {offset: args.offset});
+ [newNodes.first, newNodes.second].some(function(newNode) {
+ if(!(newNode.contents().length)) {
+ newNode.transform('smartxml.append', {text: ''});
+ return true; // break
+ }
+ });
+ return _.extend(newNodes, {emptyText: emptyText});
+ },
+ isAllowed: function() {
+
+ }
+};
+
+
+var breakContentAction = function(document, context) {
+ var textNode = context.cursor.currentNode;
+ if(textNode) {
+ var result, goto;
+
+ result = textNode.transform('core.break-content', {offset: context.cursor.offset});
+
+ if(result.emptyText) {
+ goto = result.createdEmpty;
+ gotoOptions = {};
+ } else {
+ goto = result.second;
+ gotoOptions = {caretTo: 'start'};
+ }
+
+ context.setCurrentElement(goto, gotoOptions);
+ }
+}
+breakContentAction.isAllowed = function(document, context) {
+ /* globals Node */
+ var node = context.cursor.currentNode;
+ return node.nodeType === Node.TEXT_NODE;
+}
+
+return {
+ keyHandlers: [
+ {key: 'ENTER', target: 'main-document-area', handler: function(editor) {
+ var action = editor.getAction('core.break-document-content');
+ if(action.isAllowed()) {
+ action.execute();
+ }
+ }},
+ {key: 'ENTER', target: 'main-document-area', actionHandler: 'core.break-document-content'}
+ ],
+
+ documentActions: [
+ {
+ name: 'core.break-document-content',
+ context: 'main-document-area',
+ label: 'break here'
+ icon: 'core:some-name',
+ action: breakContentAction
+ }
+ ],
+
+ // zapisywanie dokumentu:
+
+ documentTransformations: [
+ {name: 'core.break-content', textNode: true, t: breakContentTransformation},
+
+ // transformacja z poziomu smartxml
+ {name: 'core.wrap-with', textNode: true, t: wrapWith}
+
+ // list plugin:
+ {name: 'list.remove-list', elementNode: 'list', t: null}
+ // hipotetyczna akcja na itemie listy
+ {name: 'list.extract', elementNode: 'item', requiresParent: 'list', requiresInParents: '?'}
+ ]
+};
+
+});
\ No newline at end of file
'libs/jquery',
'libs/underscore',
'libs/backbone',
- 'smartxml/events'
-], function($, _, Backbone, events) {
+ 'smartxml/events',
+ 'smartxml/transformations'
+], function($, _, Backbone, events, transformations) {
'use strict';
/* globals Node */
return toret;
};
-// var TRANSFORMATION = function(name, implementation) {
-// //implementation._isTransformation = true;
-
-// createDumbTransformation(name, implementation, )
-
-// return implementation;
-// };
-
var DocumentNode = function(nativeNode, document) {
if(!document) {
throw new Error('undefined document for a node');
$.extend(DocumentNode.prototype, {
+ transformations: new transformations.TransformationStorage(),
+
transform: function(name, args) {
- var Transformation = contextTransformations[name],
+ var Transformation = this.transformations.get(name),
transformation;
if(Transformation) {
transformation = new Transformation(this.document, this, args);
}
});
+// trans
+
+// todo - split+append
+
+ElementNode.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'smartxml.setAttr',
+ impl: function(args) {
+ this.setAttr(args.name, args.value);
+ },
+ getChangeRoot: function() {
+ return this.context;
+ }
+}));
+
+DocumentNode.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'smartxml.wrapWith',
+ getChangeRoot: function() {
+ return this.context.parent();
+ },
+ impl: function(args) {
+ return this.wrapWith(args);
+ }
+}));
+
+DocumentNode.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'smartxml.wrapText',
+ getChangeRoot: function() {
+ return this.context;
+ },
+ impl: function(args) {
+ return this.wrapText(args);
+ }
+}));
+
+DocumentNode.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'smartxml.detach',
+ getChangeRoot: function() {
+ return this.context.parent();
+ },
+ impl: function(args) {
+ return this.detach();
+ }
+}));
+
+///
+
var TextNode = function(nativeNode, document) {
DocumentNode.call(this, nativeNode, document);
};
});
+TextNode.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'rng.breakContent',
+ // impl: function(args) {
+ // var node = this.context,
+ // newNodes, emptyNode, emptyText;
+ // newNodes = node.transform('smartxml.split', {offset: args.offset});
+ // [newNodes.first, newNodes.second].some(function(newNode) {
+ // if(!(newNode.contents().length)) {
+ // newNode.transform('smartxml.append', {text: ''});
+ // return true; // break
+ // }
+ // });
+ // return _.extend(newNodes, {emptyText: emptyText});
+ // },
+ impl: function(args) {
+ var node = this,
+ newNodes, emptyNode, emptyText;
+ newNodes = node.split({offset: args.offset});
+ [newNodes.first, newNodes.second].some(function(newNode) {
+ if(!(newNode.contents().length)) {
+ newNode.append({text: ''});
+ return true; // break
+ }
+ });
+ return _.extend(newNodes, {emptyText: emptyText});
+ },
+ getChangeRoot: function() {
+ return this.context.parent().parent();
+ }
+}));
+
+
+ElementNode.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'smartxml.setText',
+ impl: function(args) {
+ this.setText(args.text);
+ },
+ getChangeRoot: function() {
+ return this.context;
+ }
+}));
+
+
var parseXML = function(xml) {
return $($.trim(xml))[0];
};
$.extend(Document.prototype, Backbone.Events, {
ElementNodeFactory: ElementNode,
TextNodeFactory: TextNode,
+ transformations: new transformations.TransformationStorage(),
createDocumentNode: function(from) {
if(!(from instanceof Node)) {
return insertion.ofNode;
},
- transform: function(transformationName, args) {
+ transform: function(transformation, args) {
console.log('transform');
- var Transformation, transformation, toret;
- if(typeof transformationName === 'string') {
- Transformation = transformations[transformationName];
+ var Transformation, toret;
+ if(typeof transformation === 'string') {
+ Transformation = this.transformations.get(transformation);
if(Transformation) {
- transformation = new Transformation(args);
+ transformation = new Transformation(this, this, args);
}
- } else {
- transformation = transformationName;
- }
+ }
if(transformation) {
toret = transformation.run();
this.undoStack.push(transformation);
this.redoStack = [];
return toret;
} else {
- throw new Error('Transformation ' + transformationName + ' doesn\'t exist!');
+ throw new Error('Transformation ' + transformation + ' doesn\'t exist!');
}
},
undo: function() {
}, configurable: true});
};
+Document.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'smartxml.wrapNodes',
+ // init: function() {
-// var registerTransformationsFromObject = function(object) {
-// _.values(object).filter(function(val) {
-// return typeof val === 'function' && val._isTransformation;
-// })
-// .forEach(function(val) {
-// registerTransformation(val._transformationName, val, object);
-// });
-// };
-// registerTransformationsFromObject(ElementNode.prototype);
-// registerTransformationsFromObject(TextNode.prototype);
-// registerTransformationsFromObject(Document.prototype);
-
-// var Transformation = function() {
-// };
-// $.extend(Transformation.prototype, {
-
-// });
-
-
-// var createDumbTransformation = function(impl, contextObject) {
-// var DumbTransformation = function(args) {
-// this.args = this.args;
-// };
-// DumbTransformation.prototype = Object.create(Transformation.prototype);
-// $.extend(DumbTransformation.prototype, {
-// run: function() {
-// impl.apply(contextObject, this.args);
-// }
-// });
-
-// return DumbTransformation;
-
-
-// };
-
-var transformations = {};
-// var registerTransformation = function(name, impl, contextObject) {
-// if(typeof impl === 'function') {
-// transformations[name] = createDumbTransformation(impl, contextObject);
-// }
-// };
-
-// registerTransformation('detachx', DocumentNode.prototype.detach, )
-
-
-// 1. detach via totalny fallback
-var DetachNodeTransformation = function(args) {
- this.node = args.node;
- this.document = this.node.document;
-};
-$.extend(DetachNodeTransformation.prototype, {
- run: function() {
- this.oldRoot = this.node.document.root.clone();
- this.path = this.node.getPath();
- this.node.detach(); // @TS
-
- },
- undo: function() {
- this.document.root.replaceWith(this.oldRoot); // this.getDocument?
- this.node = this.document.getNodeByPath(this.path);
- }
-});
-transformations['detach'] = DetachNodeTransformation;
-
-//2. detach via wskazanie changeroot
-
-var Detach2NodeTransformation = function(args) {
- this.nodePath = args.node.getPath();
- this.document = args.node.document;
-};
-$.extend(Detach2NodeTransformation.prototype, {
- run: function() {
- var node = this.document.getNodeByPath(this.nodePath),
- root = node.parent() ? node.parent() : this.document.root;
-
- this.rootPath = root.getPath();
- this.oldRoot = (root).clone();
- node.detach();
- },
- undo: function() {
- this.document.getNodeByPath(this.rootPath).replaceWith(this.oldRoot);
- }
-});
-//transformations['detach2'] = Detach2NodeTransformation;
-
-//2a. generyczna transformacja
-
-var createTransformation = function(desc) {
-
- var NodeTransformation = function(args) {
- this.nodePath = args.node.getPath();
- this.document = args.node.document;
- this.args = args;
- };
- $.extend(NodeTransformation.prototype, {
- run: function() {
- var node = this.document.getNodeByPath(this.nodePath),
- root;
-
- if(desc.getRoot) {
- root = desc.getRoot(node);
- } else {
- root = this.document.root;
- }
-
- this.rootPath = root.getPath();
- this.oldRoot = (root).clone();
- desc.impl.call(node, this.args);
- },
- undo: function() {
- this.document.getNodeByPath(this.rootPath).replaceWith(this.oldRoot);
- }
- });
-
- return NodeTransformation;
-}
-
-///
-var Transformation = function(args) {
- this.args = args;
-};
-$.extend(Transformation.prototype, {
- run: function() {
- throw new Error('not implemented');
- },
- undo: function() {
- throw new Error('not implemented');
- },
-});
-
-var createGenericTransformation = function(desc) {
- var GenericTransformation = function(document, args) {
- //document.getNodeByPath(contextPath).call(this, args);
- this.args = args;
- this.document = document;
- };
- $.extend(GenericTransformation.prototype, {
- run: function() {
- var changeRoot = desc.getChangeRoot ? desc.getChangeRoot.call(this) : this.document.root;
- this.snapshot = changeRoot.clone();
- this.changeRootPath = changeRoot.getPath();
- return desc.impl.call(this.context, this.args); // a argumenty do metody?
- },
- undo: function() {
- this.document.getNodeByPath(this.changeRootPath).replaceWith(this.snapshot);
- },
- });
-
- return GenericTransformation;
-};
-
-// var T = createGenericTransformation({impl: function() {}});
-// var t = T(doc, {a:1,b:2,c3:3});
-
-
-var createContextTransformation = function(desc) {
- // mozna sie pozbyc przez przeniesienie object/context na koniec argumentow konstruktora generic transformation
- var GenericTransformation = createGenericTransformation(desc);
-
- var ContextTransformation = function(document, object, args) {
- var contextPath = object.getPath();
-
- GenericTransformation.call(this, document, args);
-
- Object.defineProperty(this, 'context', {
- get: function() {
- return document.getNodeByPath(contextPath);
- }
- });
- }
- ContextTransformation.prototype = Object.create(GenericTransformation.prototype);
- return ContextTransformation;
-}
-// var T = createContextTransformation({impl: function() {}});
-// var t = T(doc, node, {a:1,b:2,c3:3});
-///
-
-var contextTransformations = {};
-contextTransformations['setText'] = createContextTransformation({
- impl: function(args) {
- this.setText(args.text);
- },
- getChangeRoot: function() {
- return this.context;
- }
-});
-
-contextTransformations['setAttr'] = createContextTransformation({
- impl: function(args) {
- this.setAttr(args.name, args.value);
- },
- getChangeRoot: function() {
- return this.context;
- }
-});
-
-contextTransformations['split'] = createContextTransformation({
- impl: function(args) {
- return this.split({offset: args.offset});
- }//,
+ // },
// getChangeRoot: function() {
- // return this.context.parent().parent();
- // }
-});
-
-// var TRANSFORMATION2 = function(f, getChangeRoot, undo) {
-// var context = this,
-
-
-// var transformation = createContextTransformation({
-// impl: f,
-// getChangeRoot: getChangeRoot,
-
-// });
-
-// var toret = function() {
-// var
-// f.apply(context, createArgs ? createArgs(arguments) : arguments)
-// };
-// return toret;
-// }
-
-transformations['detach2'] = createTransformation({
- // impl: function() {
- // //this.setAttr('class', 'cite'); //
+ // return this.context;
// },
- impl: ElementNode.prototype.detach,
- getRoot: function(node) {
- return node.parent();
- }
-
-});
-
-transformations['setText-old'] = createTransformation({
- impl: function(args) {
- this.setText(args.text)
- },
- getRoot: function(node) {
- return node;
- }
-
-});
-
-transformations['setClass-old'] = createTransformation({
impl: function(args) {
- this.setClass(args.klass);
+ this.wrapNodes(args);
},
- getRoot: function(node) {
- return node;
- }
-})
-//3. detach z pełnym własnym redo
+}));
-var Detach3NodeTransformation = function(args) {
- this.node = args.node;
- this.document = this.node.document;
-};
-$.extend(Detach3NodeTransformation.prototype, {
- run: function() {
- //this.index = this.node.getIndex();
- //this.parent = this.node.parent();
-
- this.path = this.node.getPath();
- if(this.node.isSurroundedByTextElements()) {
- this.prevText = this.node.prev().getText();
- this.nextText = this.node.next().getText();
- this.merge = true;
- } else {
- this.prevText = this.nextText = null;
- this.merge = false;
- }
-
- this.node.detach();
- },
- undo: function() {
- var parent = this.document.getNodeByPath(this.path.slice(0,-1)),
- idx = _.last(this.path);
- var inserted = parent.insertAtIndex(this.node, idx);
- if(this.merge) {
- if(inserted.next()) {
- inserted.before({text: this.prevText});
- inserted.next().setText(this.nextText);
- } else {
- inserted.prev().setText(this.prevText);
- inserted.after({text: this.nextText});
- }
- }
- }
-});
-transformations['detach3'] = Detach3NodeTransformation;
-
-
-var registerTransformationsFromObject = function(object) {
- _.pairs(object).filter(function(pair) {
- var property = pair[1];
- return typeof property === 'function' && property._isTransformation;
- })
- .forEach(function(pair) {
- var name = pair[0],
- method = pair[1];
- object.registerTransformation(name, createContextTransformation(method));
- });
-};
-registerTransformationsFromObject(ElementNode.prototype);
-registerTransformationsFromObject(TextNode.prototype);
-registerTransformationsFromObject(Document.prototype);
return {
documentFromXML: function(xml) {
--- /dev/null
+//use case: edytor robi split, jesli split był na koncu (czyli druga czesc jest pusta)
+// chce tam dodac wezel tekstowy
+
+// flow: plugin_key_handler(enter, main-canvas-area) -> plugin_document_action('break-content')
+// --w srodku--> refactoring tego co teraz w keyboard:
+
+//1. jedna transformacja z warunkiem (Zarejestrowana przez plugin)
+
+
+
+var breakContentTransformation = {
+ impl: function(args) {
+ var node = this.context;
+ emptyText = false,
+ newNodes,
+ emptyNode;
+
+ newNodes = node.transform('core.split', {offset: args.offset});
+
+ if(args.offset === 0)
+ emptyNode = newNodes.first;
+ else if(args.offset === node.getText().length); //@ nie ma atEnd :(
+ emptyNode = newNodes.second;
+
+ if(emptyNode) {
+ emptyText = emptyNode.transform('core.append', {text: ''});
+ }
+
+ return _.extend(newNodes, {emptyText: emptyText});
+ }
+};
+
+
+var breakContentAction = function(document, context) {
+ var textNode = context.currentTextNode;
+ if(textNode) {
+ var result, goto;
+
+ result = textNode.transform('core.break-content', {offset: context.offset});
+
+ if(result.emptyText) {
+ goto = result.createdEmpty;
+ gotoOptions = {};
+ } else {
+ goto = result.second;
+ gotoOptions = {caretTo: 'start'};
+ }
+
+ context.setCurrentElement(goto, gotoOptions);
+ }
+}
+
+var toret = {
+ keyHandlers: [
+ {key: 'ENTER', target: 'main-document-area', handler: function(editor) {
+ editor.getAction('core.break-document-content').execute();
+ }},
+ ],
+
+ actions: [
+ {name: 'core.break-document-content', context: 'main-document-area', action: breakContentAction}
+ ],
+
+ // zapisywanie dokumentu:
+
+ contextTransformations: [
+ {name: 'core.break-content', textNode: true, t: breakContentTransformation},
+
+ // list plugin:
+ {name: 'list.remove-list', elementNode: 'list', t: null}
+ // hipotetyczna akcja na itemie listy
+ {name: 'list.extract', elementNode: 'item', requiresParent: 'list', requiresInParents: '?'}
+ ],
+
+}
+
+
+/// STARE
+
+// 1. detach via totalny fallback
+var DetachNodeTransformation = function(args) {
+ this.node = args.node;
+ this.document = this.node.document;
+};
+$.extend(DetachNodeTransformation.prototype, {
+ run: function() {
+ this.oldRoot = this.node.document.root.clone();
+ this.path = this.node.getPath();
+ this.node.detach(); // @TS
+
+ },
+ undo: function() {
+ this.document.root.replaceWith(this.oldRoot); // this.getDocument?
+ this.node = this.document.getNodeByPath(this.path);
+ }
+});
+transformations['detach'] = DetachNodeTransformation;
+
+//2. detach via wskazanie changeroot
+
+var Detach2NodeTransformation = function(args) {
+ this.nodePath = args.node.getPath();
+ this.document = args.node.document;
+};
+$.extend(Detach2NodeTransformation.prototype, {
+ run: function() {
+ var node = this.document.getNodeByPath(this.nodePath),
+ root = node.parent() ? node.parent() : this.document.root;
+
+ this.rootPath = root.getPath();
+ this.oldRoot = (root).clone();
+ node.detach();
+ },
+ undo: function() {
+ this.document.getNodeByPath(this.rootPath).replaceWith(this.oldRoot);
+ }
+});
+//transformations['detach2'] = Detach2NodeTransformation;
+
+//2a. generyczna transformacja
+
+var createTransformation = function(desc) {
+
+ var NodeTransformation = function(args) {
+ this.nodePath = args.node.getPath();
+ this.document = args.node.document;
+ this.args = args;
+ };
+ $.extend(NodeTransformation.prototype, {
+ run: function() {
+ var node = this.document.getNodeByPath(this.nodePath),
+ root;
+
+ if(desc.getRoot) {
+ root = desc.getRoot(node);
+ } else {
+ root = this.document.root;
+ }
+
+ this.rootPath = root.getPath();
+ this.oldRoot = (root).clone();
+ desc.impl.call(node, this.args);
+ },
+ undo: function() {
+ this.document.getNodeByPath(this.rootPath).replaceWith(this.oldRoot);
+ }
+ });
+
+ return NodeTransformation;
+}
+
+
+
+var contextTransformations = {};
+contextTransformations['setText'] = createContextTransformation({
+ impl: function(args) {
+ this.setText(args.text);
+ },
+ getChangeRoot: function() {
+ return this.context;
+ }
+});
+
+contextTransformations['setAttr'] = createContextTransformation({
+ impl: function(args) {
+ this.setAttr(args.name, args.value);
+ },
+ getChangeRoot: function() {
+ return this.context;
+ }
+});
+
+contextTransformations['split'] = createContextTransformation({
+ impl: function(args) {
+ return this.split({offset: args.offset});
+ }//,
+ // getChangeRoot: function() {
+ // return this.context.parent().parent();
+ // }
+});
+
+
+contextTransformations['before'] = createContextTransformation({
+ getChangeRoot: function() {
+ return this.context.parent();
+ },
+ impl: function(args) {
+ this.before(args.node)
+ },
+
+});
+
+contextTransformations['before'] = createContextTransformation({
+ impl: function(args) {
+ this.before(args.node)
+ },
+ undo: function() {
+ this.context.detach();
+ }
+});
+
+
+
+transformations['detach2'] = createTransformation({
+ // impl: function() {
+ // //this.setAttr('class', 'cite'); //
+ // },
+ impl: ElementNode.prototype.detach,
+ getRoot: function(node) {
+ return node.parent();
+ }
+
+});
+
+transformations['setText-old'] = createTransformation({
+ impl: function(args) {
+ this.setText(args.text)
+ },
+ getRoot: function(node) {
+ return node;
+ }
+
+});
+
+transformations['setClass-old'] = createTransformation({
+ impl: function(args) {
+ this.setClass(args.klass);
+ },
+ getRoot: function(node) {
+ return node;
+ }
+})
+
+//3. detach z pełnym własnym redo
+
+var Detach3NodeTransformation = function(args) {
+ this.node = args.node;
+ this.document = this.node.document;
+};
+$.extend(Detach3NodeTransformation.prototype, {
+ run: function() {
+ //this.index = this.node.getIndex();
+ //this.parent = this.node.parent();
+
+ this.path = this.node.getPath();
+ if(this.node.isSurroundedByTextElements()) {
+ this.prevText = this.node.prev().getText();
+ this.nextText = this.node.next().getText();
+ this.merge = true;
+ } else {
+ this.prevText = this.nextText = null;
+ this.merge = false;
+ }
+
+ this.node.detach();
+ },
+ undo: function() {
+ var parent = this.document.getNodeByPath(this.path.slice(0,-1)),
+ idx = _.last(this.path);
+ var inserted = parent.insertAtIndex(this.node, idx);
+ if(this.merge) {
+ if(inserted.next()) {
+ inserted.before({text: this.prevText});
+ inserted.next().setText(this.nextText);
+ } else {
+ inserted.prev().setText(this.prevText);
+ inserted.after({text: this.nextText});
+ }
+ }
+ }
+});
+transformations['detach3'] = Detach3NodeTransformation;
+
+
+var registerTransformationsFromObject = function(object) {
+ _.pairs(object).filter(function(pair) {
+ var property = pair[1];
+ return typeof property === 'function' && property._isTransformation;
+ })
+ .forEach(function(pair) {
+ var name = pair[0],
+ method = pair[1];
+ object.registerTransformation(name, createContextTransformation(method));
+ });
+};
+registerTransformationsFromObject(ElementNode.prototype);
+registerTransformationsFromObject(TextNode.prototype);
+registerTransformationsFromObject(Document.prototype);
\ No newline at end of file
--- /dev/null
+define(function(require) {
+
+'use strict';
+
+var _ = require('libs/underscore'),
+ toret = {};
+
+
+toret.createGenericTransformation = function(desc) {
+
+ var GenericTransformation = function(document, args) {
+ this.args = args || {};
+
+ var transformation = this;
+ _.keys(this.args).forEach(function(key) {
+ if(transformation.args[key].nodeType) { //@@ change to instanceof check, fix circular dependency
+ var value = transformation.args[key],
+ path = value.getPath();
+ Object.defineProperty(transformation.args, key, {
+ get: function() {
+ if(transformation.hasRun) {
+ console.log('returning via path');
+ return transformation.document.getNodeByPath(path);
+ } else {
+ console.log('returning original arg');
+ return value;
+
+ }
+ }
+ });
+ }
+ });
+ this.document = document;
+ this.hasRun = false;
+ if(desc.init) {
+ desc.init.call(this);
+ }
+ };
+ _.extend(GenericTransformation.prototype, {
+ name: desc.name,
+ run: function() {
+ var changeRoot;
+ if(!desc.undo) {
+ changeRoot = desc.getChangeRoot ? desc.getChangeRoot.call(this) : this.document.root;
+ this.snapshot = changeRoot.clone();
+ this.changeRootPath = changeRoot.getPath();
+ }
+ var toret = desc.impl.call(this.context, this.args); // a argumenty do metody?
+ this.hasRun = true;
+ return toret;
+ },
+ undo: function() {
+ if(desc.undo) {
+ desc.undo.call(this.context);
+ } else {
+ this.document.getNodeByPath(this.changeRootPath).replaceWith(this.snapshot);
+ }
+ },
+ });
+
+ return GenericTransformation;
+};
+// var T = createGenericTransformation({impl: function() {}});
+// var t = T(doc, {a:1,b:2,c3:3});
+
+
+toret.createContextTransformation = function(desc) {
+ // mozna sie pozbyc przez przeniesienie object/context na koniec argumentow konstruktora generic transformation
+ var GenericTransformation = toret.createGenericTransformation(desc);
+
+ var ContextTransformation = function(document, object, args) {
+ GenericTransformation.call(this, document, args);
+
+ if(document === object) {
+ this.context = document;
+ } else {
+ var contextPath = object.getPath();
+ Object.defineProperty(this, 'context', {
+ get: function() {
+ // todo: to jakos inaczej, bo np. this.context w undo transformacji before to juz nie ten sam obiekt
+ // moze transformacja powinna zwracac zmodyfikowana sciezke do obiektu po dzialaniu run?
+
+ // tu tez trick z hasRun
+ return document.getNodeByPath(contextPath);
+ }
+ });
+ }
+ }
+ ContextTransformation.prototype = Object.create(GenericTransformation.prototype);
+ return ContextTransformation;
+}
+// var T = createContextTransformation({impl: function() {}});
+// var t = T(doc, node, {a:1,b:2,c3:3});
+///
+
+
+
+toret.TransformationStorage = function() {};
+
+_.extend(toret.TransformationStorage.prototype, {
+ _transformations: {},
+
+ register: function(Transformation) {
+ var list = (this._transformations[Transformation.prototype.name] = this._transformations[Transformation.prototype.name] || []);
+ list.push(Transformation);
+ },
+
+ get: function(name) {
+ var transformations = this._transformations[name];
+ if(!transformations) {
+ throw new Error('Transformation "' + name + '" not found!');
+ }
+ // na razie zwraca pierwsza
+ return transformations[0];
+ }
+});
+
+
+
+// var registerTransformationFromMethod = (object, methodName, desc) {
+// if(!object[methodName]) {
+// throw new Exeption('Cannot register transformation from unknown method ' + methodName + ' on ' + object);
+// }
+// desc.impl = object[name];
+// Transformation = createContextTransformation(desc);
+// object.prototype.registerContextTransformation(name, createContextTransformation(method));
+// };
+
+
+// registerTransformationFromMethod(ElementNode, 'setAttr', {
+// impl: function(args) {
+// this.setAttr(args.name, args.value);
+// },
+// getChangeRoot: function() {
+// return this.context;
+// }
+
+// });
+
+return toret;
+
+});
\ No newline at end of file
define([
'libs/jquery',
'libs/underscore',
- 'smartxml/smartxml'
-], function($, _, smartxml) {
+ 'smartxml/smartxml',
+ 'smartxml/transformations'
+], function($, _, smartxml, transformations) {
'use strict';
}
});
-
+WLXMLElementNode.prototype.transformations.register(transformations.createContextTransformation({
+ name: 'wlxml.setMetaAttribute',
+ impl: function(args) {
+ this.setMetaAttribute(args.name, args.value);
+ },
+ getChangeRoot: function() {
+ return this.context;
+ }
+}));