third batch
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Wed, 2 Apr 2014 12:17:10 +0000 (14:17 +0200)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Tue, 6 May 2014 09:37:47 +0000 (11:37 +0200)
- register
- replacing on class change
- first approach to new rendering code path

src/editor/modules/documentCanvas/canvas/canvas.js
src/editor/modules/documentCanvas/canvas/canvas.test.js
src/editor/modules/documentCanvas/canvas/documentElement.js
src/editor/modules/documentCanvas/canvas/elementsRegister.js [new file with mode: 0644]
src/editor/modules/documentCanvas/canvas/elementsRegister.test.js [new file with mode: 0644]
src/editor/modules/documentCanvas/canvas/wlxmlListener.js
src/editor/plugins/core/canvasElements.js

index af1ed28..0ec22a1 100644 (file)
@@ -3,13 +3,13 @@ define([
 'libs/underscore',
 'libs/backbone',
 'fnpjs/logging/logging',
 'libs/underscore',
 'libs/backbone',
 'fnpjs/logging/logging',
-'wlxml/wlxml',
 'modules/documentCanvas/canvas/documentElement',
 'modules/documentCanvas/canvas/keyboard',
 'modules/documentCanvas/canvas/utils',
 'modules/documentCanvas/canvas/wlxmlListener',
 'modules/documentCanvas/canvas/documentElement',
 'modules/documentCanvas/canvas/keyboard',
 'modules/documentCanvas/canvas/utils',
 'modules/documentCanvas/canvas/wlxmlListener',
-'modules/documentCanvas/canvas/genericElement'
-], function($, _, Backbone, logging, wlxml, documentElement, keyboard, utils, wlxmlListener, genericElement) {
+'modules/documentCanvas/canvas/elementsRegister',
+'modules/documentCanvas/canvas/genericElement',
+], function($, _, Backbone, logging, documentElement, keyboard, utils, wlxmlListener, ElementsRegister, genericElement) {
     
 'use strict';
 /* global document:false, window:false, Node:false, gettext */
     
 'use strict';
 /* global document:false, window:false, Node:false, gettext */
@@ -56,48 +56,20 @@ $.extend(TextHandler.prototype, {
 
 });
 
 
 });
 
-var ElementsRegister = function() {
-    this._register = {
-        '': ElementsRegister.createCanvasElementType(genericElement, documentElement.DocumentNodeElement)
-    };
-
-}
-_.extend(ElementsRegister, {
-    createCanvasElementType: function(elementPrototype, inheritFrom) {
-        var Constructor = function() {
-            if(!this.super) {
-                this.super = inheritFrom.prototype;
-            }
-            inheritFrom.apply(this, Array.prototype.slice.call(arguments, 0));
-            
-        };
-        Constructor.prototype = Object.create(inheritFrom.prototype);
-        _.extend(Constructor.prototype, elementPrototype);
-        return Constructor;
-    }
-});
-_.extend(ElementsRegister.prototype, {
-    register: function(klass, elementPrototype) {
-        this._register[klass] = ElementsRegister.createCanvasElementType(elementPrototype, this.getFactoryFor(''));
-    },
-    getFactoryFor: function(klass) {
-        var Factory;
-        wlxml.getClassHierarchy(klass).reverse().some(function(klass) {
-            Factory = this._register[klass];
-            if(Factory) {
-                return true;
-            }
-        }.bind(this));
-        return Factory;
-    }
-});
-
-
 
 var Canvas = function(wlxmlDocument, elements) {
 
 var Canvas = function(wlxmlDocument, elements) {
-    this.elementsRegister = new ElementsRegister();
-    (elements || []).forEach(function(elementDesc) {
-        this.elementsRegister.register(elementDesc.klass, elementDesc.element);
+    this.elementsRegister = new ElementsRegister(documentElement.DocumentNodeElement, genericElement);
+
+    elements = [
+        {tag: 'section', klass: null, prototype: genericElement},
+        {tag: 'div', klass: null, prototype: genericElement},
+        {tag: 'header', klass: null, prototype: genericElement},
+        {tag: 'span', klass: null, prototype: genericElement},
+        {tag: 'aside', klass: null, prototype: genericElement}
+    ].concat(elements || []);
+
+    (elements).forEach(function(elementDesc) {
+        this.elementsRegister.register(elementDesc);
     }.bind(this));
     this.eventBus = _.extend({}, Backbone.Events);
     this.wrapper = $('<div>').addClass('canvas-wrapper').attr('contenteditable', true);
     }.bind(this));
     this.eventBus = _.extend({}, Backbone.Events);
     this.wrapper = $('<div>').addClass('canvas-wrapper').attr('contenteditable', true);
@@ -122,12 +94,9 @@ $.extend(Canvas.prototype, Backbone.Events, {
     createElement: function(wlxmlNode) {
         var Factory;
         if(wlxmlNode.nodeType === Node.TEXT_NODE) {
     createElement: function(wlxmlNode) {
         var Factory;
         if(wlxmlNode.nodeType === Node.TEXT_NODE) {
-            Factory = documentElement.DocumentTextElement
+            Factory = documentElement.DocumentTextElement;
         } else {
         } else {
-            if(wlxmlNode.getClass() === 'p') {
-               // debugger;
-            }
-            Factory = this.elementsRegister.getFactoryFor(wlxmlNode.getClass());
+            Factory = this.elementsRegister.getElement({tag: wlxmlNode.getTagName(), klass: wlxmlNode.getClass()});
         }
         return new Factory(wlxmlNode, this);
     },
         }
         return new Factory(wlxmlNode, this);
     },
index 8e3c1c8..9059e3f 100644 (file)
@@ -12,8 +12,8 @@ define([
 
 var expect = chai.expect;
 
 
 var expect = chai.expect;
 
-var getCanvasFromXML = function(xml) {
-    return canvas.fromXMLDocument(getDocumentFromXML(xml), null);
+var getCanvasFromXML = function(xml, elements) {
+    return canvas.fromXMLDocument(getDocumentFromXML(xml), elements);
 };
 
 var getDocumentFromXML = function(xml) {
 };
 
 var getDocumentFromXML = function(xml) {
@@ -35,7 +35,7 @@ describe('wtf', function() {
         txtNode.wrapWith({tagName: 'header', start: 1, end: 2});
         expect(c.doc().children().length).to.equal(3);
     });
         txtNode.wrapWith({tagName: 'header', start: 1, end: 2});
         expect(c.doc().children().length).to.equal(3);
     });
-})
+});
 
 describe('new Canvas', function() {
     it('abc', function() {
 
 describe('new Canvas', function() {
     it('abc', function() {
@@ -81,7 +81,6 @@ describe('Listening to document changes', function() {
             b = doc.root.contents()[1],
             c = canvas.fromXMLDocument(doc);
 
             b = doc.root.contents()[1],
             c = canvas.fromXMLDocument(doc);
 
-        debugger;
         a.before(b);
         var sectionChildren = c.doc().children();
         expect(sectionChildren.length).to.equal(2);
         a.before(b);
         var sectionChildren = c.doc().children();
         expect(sectionChildren.length).to.equal(2);
@@ -229,34 +228,34 @@ describe('Default document changes handling', function() {
     
 describe('Custom elements based on wlxml class attribute', function() {
     it('allows custom rendering', function() {
     
 describe('Custom elements based on wlxml class attribute', function() {
     it('allows custom rendering', function() {
-        var c = getCanvasFromXML('<section><div class="testClass"></div></section>', {
-            testClass: {
+        var c = getCanvasFromXML('<section><div class="testClass"></div></section>', [
+            {tag: 'div', klass: 'testClass', prototype: {
                 init: function() {
                 init: function() {
-                    debugger;
-                    this.dom.append('<test></test>');
+                    this._container().append('<test></test>');
                 }
                 }
-            }
-        });
+            }, extending: {tag: 'div'}}
+        ]);
+
         expect(c.doc().children()[0]._container().children('test').length).to.equal(1); // @!
     });
 
     it('allows handling changes to internal structure of rendered node', function() {
         expect(c.doc().children()[0]._container().children('test').length).to.equal(1); // @!
     });
 
     it('allows handling changes to internal structure of rendered node', function() {
-        var c = getCanvasFromXML('<section><div class="testClass"><a></a></div></section>', {
-            testClass: {
+        var c = getCanvasFromXML('<section><div class="testClass"><a></a></div></section>', [
+            {tag: 'div', klass: 'testClass', prototype: {
                 init: function() {
                     this.header = $('<h1>');
                 init: function() {
                     this.header = $('<h1>');
-                    this.dom.append(this.header);
+                    this._container().append(this.header);
                     this.refresh2();
                 },
                 refresh2: function() {
                     this.refresh2();
                 },
                 refresh2: function() {
-                    this.header.text(this.el.wlxmlNode.contents().length);
+                    this.header.text(this.wlxmlNode.contents().length);
                 },
                 onNodeAdded: function(event) {
                     void(event);
                     this.refresh2();
                 }
                 },
                 onNodeAdded: function(event) {
                     void(event);
                     this.refresh2();
                 }
-            }
-        });
+            }, extending: {tag: 'div'}}
+        ]);
 
         var node = c.wlxmlDocument.root.contents()[0],
             element = node.getData('canvasElement');
 
         var node = c.wlxmlDocument.root.contents()[0],
             element = node.getData('canvasElement');
index 283f873..7325938 100644 (file)
@@ -12,7 +12,7 @@ var DocumentElement = function(wlxmlNode, canvas) {
     this.wlxmlNode = wlxmlNode;
     this.canvas = canvas;
 
     this.wlxmlNode = wlxmlNode;
     this.canvas = canvas;
 
-    this.createDOM();
+    this.$element = this.createDOM();
     this.$element.data('canvas-element', this);
 };
 
     this.$element.data('canvas-element', this);
 };
 
@@ -80,10 +80,7 @@ $.extend(DocumentElement.prototype, {
 var DocumentNodeElement = function(wlxmlNode, canvas) {
     DocumentElement.call(this, wlxmlNode, canvas);
     wlxmlNode.setData('canvasElement', this);
 var DocumentNodeElement = function(wlxmlNode, canvas) {
     DocumentElement.call(this, wlxmlNode, canvas);
     wlxmlNode.setData('canvasElement', this);
-    if(this.init) {
-        this.init();
-    }
-
+    this.init(this.$element);
 };
 
 
 };
 
 
@@ -126,8 +123,7 @@ $.extend(DocumentNodeElement.prototype, {
         
         wrapper.append(widgetsContainer, contentContainer);
         widgetsContainer.find('*').add(widgetsContainer).attr('tabindex', -1);
         
         wrapper.append(widgetsContainer, contentContainer);
         widgetsContainer.find('*').add(widgetsContainer).attr('tabindex', -1);
-        this.$element = wrapper;
-        this.displayAs(this.defaultDisplayStyle);
+        return wrapper;
     },
     _container: function() {
         return this.dom().children('[document-element-content]');
     },
     _container: function() {
         return this.dom().children('[document-element-content]');
@@ -182,7 +178,7 @@ $.extend(DocumentNodeElement.prototype, {
         //     }
         // })
         this.dom().css('display', what);
         //     }
         // })
         this.dom().css('display', what);
-        this._container().css('display', what);   
+        this._container().css('display', what);
     }
 });
 
     }
 });
 
@@ -202,9 +198,10 @@ DocumentTextElement.prototype = Object.create(DocumentElement.prototype);
 
 $.extend(DocumentTextElement.prototype, {
     createDOM: function() {
 
 $.extend(DocumentTextElement.prototype, {
     createDOM: function() {
-        this.$element = $('<div>')
+        var dom = $('<div>')
             .attr('document-text-element', '')
             .text(this.wlxmlNode.getText() || utils.unicode.ZWS);
             .attr('document-text-element', '')
             .text(this.wlxmlNode.getText() || utils.unicode.ZWS);
+        return dom;
     },
     detach: function() {
         this.dom().detach();
     },
     detach: function() {
         this.dom().detach();
diff --git a/src/editor/modules/documentCanvas/canvas/elementsRegister.js b/src/editor/modules/documentCanvas/canvas/elementsRegister.js
new file mode 100644 (file)
index 0000000..0d31c7d
--- /dev/null
@@ -0,0 +1,59 @@
+define(function(require) {
+    
+'use strict';
+var _ = require('libs/underscore'),
+    wlxml = require('wlxml/wlxml');
+
+
+var ElementsRegister = function(basePrototype, defaultPrototype) {
+    this._register = {};
+    this.basePrototype = basePrototype;
+    this.DefaultType = this.createCanvasElementType(defaultPrototype);
+};
+
+_.extend(ElementsRegister.prototype, {
+    createCanvasElementType: function(elementPrototype, extending) {
+        var inheritFrom = this.basePrototype;
+        if(extending && extending.tag) {
+            inheritFrom = this.getElement(extending);
+        }
+        var Constructor = function() {
+            if(!this.super) {
+                this.super = inheritFrom.prototype;
+            }
+            inheritFrom.apply(this, Array.prototype.slice.call(arguments, 0));
+            
+        };
+        Constructor.prototype = Object.create(inheritFrom.prototype);
+        _.extend(Constructor.prototype, elementPrototype);
+        return Constructor;
+    },
+    register: function(params) {
+        params.klass = params.klass || '';
+        params.prototype = params.prototype || Object.create({});
+
+        this._register[params.tag] = this._register[params.tag] || {};
+        this._register[params.tag][params.klass] = this.createCanvasElementType(params.prototype, params.extending);
+    },
+    getElement: function(params) {
+        params.klass = params.klass || '';
+        var Factory;
+        if(this._register[params.tag]) {
+            wlxml.getClassHierarchy(params.klass).reverse().some(function(klass) {
+                Factory = this._register[params.tag][klass];
+                if(Factory) {
+                    return true;
+                }
+            }.bind(this));
+        }
+        if(!Factory) {
+            Factory = this.DefaultType;
+        }
+        return Factory;
+    }
+});
+
+
+return ElementsRegister;
+
+});
diff --git a/src/editor/modules/documentCanvas/canvas/elementsRegister.test.js b/src/editor/modules/documentCanvas/canvas/elementsRegister.test.js
new file mode 100644 (file)
index 0000000..eb7ad89
--- /dev/null
@@ -0,0 +1,64 @@
+define(function(require) {
+    
+'use strict';
+/* globals describe, it */
+
+
+var ElementsRegister = require('./elementsRegister.js'),
+    documentElement = require('./documentElement.js'),
+    chai = require('libs/chai');
+
+var expect = chai.expect;
+
+describe('Elements register', function() {
+    it('registers element for a tag', function() {
+        var register = new ElementsRegister(documentElement.DocumentNodeElement),
+            prototype = {testMethod: function(){}};
+
+        register.register({
+            tag: 'div',
+            prototype: prototype,
+        });
+
+        var Element = register.getElement({tag: 'div'});
+        expect(Element.prototype.testMethod).to.equal(prototype.testMethod, '1');
+        expect(Element.prototype instanceof documentElement.DocumentNodeElement).to.equal(true, '2');
+    });
+    it('registers element for a class', function() {
+        var register = new ElementsRegister(documentElement.DocumentNodeElement),
+            prototype = {testMethod: function(){}};
+
+        register.register({
+            tag: 'div',
+            klass: 'a.b',
+            prototype: prototype,
+        });
+        var Element = register.getElement({tag: 'div', klass: 'a.b.c'});
+        expect(Element.prototype.testMethod).to.equal(prototype.testMethod, '1');
+        expect(Element.prototype instanceof documentElement.DocumentNodeElement).to.equal(true, '2');
+    });
+    it('allows inheriting from selected element', function() {
+        var register = new ElementsRegister(documentElement.DocumentNodeElement),
+            method1 = function() {},
+            method2 = function() {};
+
+        register.register({
+            tag: 'div',
+            prototype: {method1: method1}
+        });
+
+        register.register({
+            tag: 'div',
+            klass: 'a',
+            prototype: {method2: method2},
+            extending: {tag: 'div'}
+        });
+
+        var Element = register.getElement({tag: 'div', klass: 'a'});
+        expect(Element.prototype.method2).to.equal(method2, '2');
+        expect(Element.prototype instanceof register.getElement({tag: 'div'})).to.equal(true, '2');
+    });
+});
+
+
+});
index faee6c8..e521c97 100644 (file)
@@ -43,12 +43,18 @@ var _metadataEventHandler = function(event) {
 var handlers = {
     nodeAttrChange: function(event) {
         var element = utils.getElementForNode(event.meta.node),
 var handlers = {
     nodeAttrChange: function(event) {
         var element = utils.getElementForNode(event.meta.node),
-            objectChanged;
+            newElement;
         if(event.meta.attr === 'class') {
         if(event.meta.attr === 'class') {
-            objectChanged = element.updateObject();
-        }
+            if(element.wlxmlNode.getClass() !== event.meta.attr) {
+                if(event.meta.node.isRoot()) {
+                    this.canvas.reloadRoot();
+                } else {
+                    newElement = this.canvas.createElement(event.meta.node);
+                    element.dom().replaceWith(newElement.dom());
+                }
+            }
 
 
-        if(!objectChanged) {
+        } else {
             element.handle(event);
         }
     },
             element.handle(event);
         }
     },
index 37eefb8..b0f51b6 100644 (file)
@@ -1,6 +1,7 @@
 define(function(require) {
     
 'use strict';
 define(function(require) {
     
 'use strict';
+var $ = require('libs/jquery');
 
 
 var widgets = {
 
 
 var widgets = {
@@ -49,7 +50,7 @@ var widgets = {
         });
         return mydom;
     }
         });
         return mydom;
     }
-}
+};
 
 
 var comment = {
 
 
 var comment = {
@@ -102,12 +103,12 @@ var footnote = {
             this.trigger('elementToggled', toggle, this.documentElement);
         }
     }
             this.trigger('elementToggled', toggle, this.documentElement);
         }
     }
-}
+};
 
 
 return [
 
 
 return [
-    {klass: 'comment', element: comment},
-    {klass: 'footnote', element: footnote}
+    {tag: 'aside',   klass: 'comment', prototype: comment, extending: {tag: 'div'}},
+    {tag: 'aside', klass: 'footnote', prototype: footnote, extending: {tag: 'aside'}}
 ];
 
 
 ];