'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/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 */
});
-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) {
- 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);
createElement: function(wlxmlNode) {
var Factory;
if(wlxmlNode.nodeType === Node.TEXT_NODE) {
- Factory = documentElement.DocumentTextElement
+ Factory = documentElement.DocumentTextElement;
} 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);
},
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) {
txtNode.wrapWith({tagName: 'header', start: 1, end: 2});
expect(c.doc().children().length).to.equal(3);
});
-})
+});
describe('new Canvas', function() {
it('abc', function() {
b = doc.root.contents()[1],
c = canvas.fromXMLDocument(doc);
- debugger;
a.before(b);
var sectionChildren = c.doc().children();
expect(sectionChildren.length).to.equal(2);
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() {
- 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() {
- 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>');
- this.dom.append(this.header);
+ this._container().append(this.header);
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();
}
- }
- });
+ }, extending: {tag: 'div'}}
+ ]);
var node = c.wlxmlDocument.root.contents()[0],
element = node.getData('canvasElement');
this.wlxmlNode = wlxmlNode;
this.canvas = canvas;
- this.createDOM();
+ this.$element = this.createDOM();
this.$element.data('canvas-element', this);
};
var DocumentNodeElement = function(wlxmlNode, canvas) {
DocumentElement.call(this, wlxmlNode, canvas);
wlxmlNode.setData('canvasElement', this);
- if(this.init) {
- this.init();
- }
-
+ this.init(this.$element);
};
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]');
// }
// })
this.dom().css('display', what);
- this._container().css('display', what);
+ this._container().css('display', what);
}
});
$.extend(DocumentTextElement.prototype, {
createDOM: function() {
- this.$element = $('<div>')
+ var dom = $('<div>')
.attr('document-text-element', '')
.text(this.wlxmlNode.getText() || utils.unicode.ZWS);
+ return dom;
},
detach: function() {
this.dom().detach();
--- /dev/null
+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;
+
+});
--- /dev/null
+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');
+ });
+});
+
+
+});
var handlers = {
nodeAttrChange: function(event) {
var element = utils.getElementForNode(event.meta.node),
- objectChanged;
+ newElement;
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);
}
},
define(function(require) {
'use strict';
+var $ = require('libs/jquery');
var widgets = {
});
return mydom;
}
-}
+};
var comment = {
this.trigger('elementToggled', toggle, this.documentElement);
}
}
-}
+};
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'}}
];