X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/6757e2f4fe80bfdc197d4963c464bf2b3a47f66b..8464a511c74dff643095ce419659df60b0580b7a:/src/smartxml/transformation_api_exp.js diff --git a/src/smartxml/transformation_api_exp.js b/src/smartxml/transformation_api_exp.js new file mode 100644 index 0000000..7a03763 --- /dev/null +++ b/src/smartxml/transformation_api_exp.js @@ -0,0 +1,288 @@ +//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