'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'
-], function($, _, Backbone, logging, documentElement, keyboard, utils, wlxmlListener) {
+'modules/documentCanvas/canvas/wlxmlListener',
+'modules/documentCanvas/canvas/genericElement'
+], function($, _, Backbone, logging, wlxml, documentElement, keyboard, utils, wlxmlListener, 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) {
+var Canvas = function(wlxmlDocument, elements) {
+ this.elementsRegister = new ElementsRegister();
+ (elements || []).forEach(function(elementDesc) {
+ this.elementsRegister.register(elementDesc.klass, elementDesc.element);
+ }.bind(this));
this.eventBus = _.extend({}, Backbone.Events);
this.wrapper = $('<div>').addClass('canvas-wrapper').attr('contenteditable', true);
this.wlxmlListener = wlxmlListener.create(this);
},
createElement: function(wlxmlNode) {
- var Factory = wlxmlNode.nodeType === Node.TEXT_NODE ? documentElement.DocumentTextElement : documentElement.factoryForTag(wlxmlNode.getTagName());
+ var Factory;
+ if(wlxmlNode.nodeType === Node.TEXT_NODE) {
+ Factory = documentElement.DocumentTextElement
+ } else {
+ if(wlxmlNode.getClass() === 'p') {
+ // debugger;
+ }
+ Factory = this.elementsRegister.getFactoryFor(wlxmlNode.getClass());
+ }
return new Factory(wlxmlNode, this);
},
});
return {
- fromXMLDocument: function(wlxmlDocument) {
- return new Canvas(wlxmlDocument);
+ fromXMLDocument: function(wlxmlDocument, elements) {
+ return new Canvas(wlxmlDocument, elements);
}
};
'libs/sinon',
'modules/documentCanvas/canvas/canvas',
'modules/documentCanvas/canvas/utils',
-'wlxml/wlxml'
+'wlxml/wlxml',
], function($, chai, sinon, canvas, utils, wlxml) {
'use strict';
var expect = chai.expect;
var getCanvasFromXML = function(xml) {
- return canvas.fromXMLDocument(getDocumentFromXML(xml));
+ return canvas.fromXMLDocument(getDocumentFromXML(xml), null);
};
var getDocumentFromXML = function(xml) {
};
+describe('wtf', function() {
+ it('wtf!', function() {
+ var c = getCanvasFromXML('<section>Alice</section>'),
+ doc = c.wlxmlDocument;
+
+ var txtNode = doc.root.contents()[0];
+ txtNode.wrapWith({tagName: 'header', start: 1, end: 2});
+ expect(c.doc().children().length).to.equal(3);
+ });
+})
+
describe('new Canvas', function() {
it('abc', function() {
var doc = wlxml.WLXMLDocumentFromXML('<section>Alice <span>has</span> a cat!</div>'),
b = doc.root.contents()[1],
c = canvas.fromXMLDocument(doc);
+ debugger;
a.before(b);
var sectionChildren = c.doc().children();
expect(sectionChildren.length).to.equal(2);
- expect(sectionChildren[0].getWlxmlTag()).to.equal('b');
- expect(sectionChildren[1].getWlxmlTag()).to.equal('a');
+ expect(sectionChildren[0].wlxmlNode.getTagName()).to.equal('b');
+ expect(sectionChildren[1].wlxmlNode.getTagName()).to.equal('a');
});
it('Handling text node moved', function() {
var sectionChildren = c.doc().children();
expect(sectionChildren.length).to.equal(2);
expect(sectionChildren[0].getText()).to.equal('Alice');
- expect(sectionChildren[1].getWlxmlTag()).to.equal('a');
+ expect(sectionChildren[1].wlxmlNode.getTagName()).to.equal('a');
});
it('Handles nodeTagChange event', function() {
var headerNode = doc.root.contents()[0],
headerElement = c.doc().children()[0];
- expect(headerElement.getWlxmlTag()).to.equal('header', 'element ok');
+ expect(headerElement.wlxmlNode.getTagName()).to.equal('header', 'element ok');
/* Make sure we handle invalidation of reference to wlxmlNode after changing its tag */
expect(headerNode.getData('canvasElement').sameNode(headerElement)).to.equal(true, 'node->element');
expect(aTextElement.getText({raw:true})).to.equal(utils.unicode.ZWS, 'canvas represents this as empty node');
aTextElement.wlxmlNode.detach();
expect(parent.children().length).to.equal(1);
- expect(parent.children()[0].getWlxmlTag()).to.equal('span');
+ expect(parent.children()[0].wlxmlNode.getTagName()).to.equal('span');
done();
});
});
});
});
+
+describe('Default document changes handling', function() {
+ it('handles added node', function() {
+ var c = getCanvasFromXML('<section></section>');
+ c.wlxmlDocument.root.append({tagName:'div'});
+ expect(c.doc().children().length).to.equal(1);
+ c.wlxmlDocument.root.prepend({tagName:'div'});
+ expect(c.doc().children().length).to.equal(2);
+
+ var node = c.wlxmlDocument.root.contents()[1];
+ node.before({tagName: 'div'});
+ expect(c.doc().children().length).to.equal(3);
+ node.after({tagName: 'div'});
+ expect(c.doc().children().length).to.equal(4);
+ });
+
+ it('handles attribute value change for a class attribute', function() {
+ var c = getCanvasFromXML('<section></section>');
+ c.wlxmlDocument.root.setAttr('class', 'test');
+ expect(c.doc().wlxmlNode.getClass()).to.equal('test');
+ });
+
+ it('handles detached node', function() {
+ var c = getCanvasFromXML('<section><div></div></section>');
+ c.wlxmlDocument.root.contents()[0].detach();
+ expect(c.doc().children().length).to.equal(0);
+ });
+
+ it('handles moved node', function() {
+ var doc = getDocumentFromXML('<section><a></a><b></b></section>'),
+ a = doc.root.contents()[0],
+ b = doc.root.contents()[1],
+ c = canvas.fromXMLDocument(doc);
+
+ a.before(b);
+ var sectionChildren = c.doc().children();
+ expect(sectionChildren.length).to.equal(2);
+ expect(sectionChildren[0].wlxmlNode.getTagName()).to.equal('b');
+ expect(sectionChildren[1].wlxmlNode.getTagName()).to.equal('a');
+ });
+
+ it('handles change in a text node', function() {
+ var c = getCanvasFromXML('<section>Alice</section>');
+ c.wlxmlDocument.root.contents()[0].setText('cat');
+ expect(c.doc().children()[0].getText()).to.equal('cat');
+ });
+});
+
+describe('Custom elements based on wlxml class attribute', function() {
+ it('allows custom rendering', function() {
+ var c = getCanvasFromXML('<section><div class="testClass"></div></section>', {
+ testClass: {
+ init: function() {
+ debugger;
+ this.dom.append('<test></test>');
+ }
+ }
+ });
+ 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: {
+ init: function() {
+ this.header = $('<h1>');
+ this.dom.append(this.header);
+ this.refresh2();
+ },
+ refresh2: function() {
+ this.header.text(this.el.wlxmlNode.contents().length);
+ },
+ onNodeAdded: function(event) {
+ void(event);
+ this.refresh2();
+ }
+ }
+ });
+
+ var node = c.wlxmlDocument.root.contents()[0],
+ element = node.getData('canvasElement');
+
+ var header = element.dom().find('h1');
+ expect(header.text()).to.equal('1', 'just <a>');
+
+ node.append({tagName: 'div'});
+
+ expect(header.text()).to.equal('2', 'added div');
+ });
+
+ describe('Handling unknown class', function() {
+ it('Inherits default behavior', function() {
+ var c = getCanvasFromXML('<section><div class="unknown">Hi!</div></section>');
+ expect(c.doc().children()[0].children()[0].getText()).to.equal('Hi!');
+ });
+ });
+});
+
describe('Cursor', function() {
/* globals Node */
var getSelection;
define([
'libs/jquery',
'libs/underscore',
-'modules/documentCanvas/canvas/utils',
-'modules/documentCanvas/canvas/wlxmlManagers'
-], function($, _, utils, wlxmlManagers) {
+'modules/documentCanvas/canvas/utils'
+], function($, _, utils) {
'use strict';
/* global Node:false, document:false */
-
// DocumentElement represents a text or an element node from WLXML document rendered inside Canvas
var DocumentElement = function(wlxmlNode, canvas) {
this.wlxmlNode = wlxmlNode;
this.canvas = canvas;
- this.$element = this.createDOM();
+ this.createDOM();
this.$element.data('canvas-element', this);
};
return other && (typeof other === typeof this) && other.dom()[0] === this.dom()[0];
},
- getVerticallyFirstTextElement: function() {
- var toret;
- this.children().some(function(child) {
- if(child instanceof DocumentTextElement) {
- toret = child;
- return true; // break
- } else {
- toret = child.getVerticallyFirstTextElement();
- if(toret) {
- return true; // break
- }
- }
- });
- return toret;
- },
-
getPreviousTextElement: function(includeInvisible) {
return this.getNearestTextElement('above', includeInvisible);
},
return this.canvas.getDocumentElement(utils.nearestInDocumentOrder(selector, direction, this.dom()[0]));
},
- exec: function(method) {
- if(this.manager && this.manager[method]) {
- return this.manager[method].apply(this.manager, Array.prototype.slice.call(arguments, 1));
- }
+ trigger: function() {
+ //this.canvas.bus.trigger()
}
+
+
});
var DocumentNodeElement = function(wlxmlNode, canvas) {
DocumentElement.call(this, wlxmlNode, canvas);
wlxmlNode.setData('canvasElement', this);
+ if(this.init) {
+ this.init();
+ }
+
};
} else {
element = e.canvas.createElement(params);
}
- var target = (action === 'append' || action === 'prepend') ? e._container() : e.dom();
- target[action](element.dom());
+ e.dom()[action](element.dom());
e.refreshPath();
return element;
};
$.extend(DocumentNodeElement.prototype, {
- init: function() {
- // noo[]
+ defaultDisplayStyle: 'block',
+ addWidget: function(widget) {
+ this.$element.children('.canvas-widgets').append(widget.DOM ? widget.DOM : widget);
+ },
+ clearWidgets: function() {
+ this.$element.children('.canvas-widgets').empty();
+ },
+ handle: function(event) {
+ var method = 'on' + event.type[0].toUpperCase() + event.type.substr(1);
+ if(this[method]) {
+ this[method](event);
+ }
},
createDOM: function() {
- var dom = $('<div>')
- .attr('document-node-element', ''),
+ var wrapper = $('<div>').attr('document-node-element', ''),
widgetsContainer = $('<div>')
.addClass('canvas-widgets')
.attr('contenteditable', false),
- container = $('<div>')
+ contentContainer = $('<div>')
.attr('document-element-content', '');
- dom.append(widgetsContainer, container);
- // Make sure widgets aren't navigable with arrow keys
+ wrapper.append(widgetsContainer, contentContainer);
widgetsContainer.find('*').add(widgetsContainer).attr('tabindex', -1);
- this.$element = dom; //@!!!
-
- this.setWlxmlTag(this.wlxmlNode.getTagName());
- this.setWlxmlClass(this.wlxmlNode.getClass());
-
- this.wlxmlNode.contents().forEach(function(node) {
- container.append(this.canvas.createElement(node).dom());
- }.bind(this));
-
- this.init();
-
- return dom;
+ this.$element = wrapper;
+ this.displayAs(this.defaultDisplayStyle);
},
_container: function() {
return this.dom().children('[document-element-content]');
}
return this;
},
- append: function(params) {
- return manipulate(this, params, 'append');
- },
- prepend: function(params) {
- return manipulate(this, params, 'prepend');
- },
before: function(params) {
return manipulate(this, params, 'before');
after: function(params) {
return manipulate(this, params, 'after');
},
- children: function() {
- var toret = [];
- if(this instanceof DocumentTextElement) {
- return toret;
- }
-
- var elementContent = this._container().contents();
- var element = this;
- elementContent.each(function() {
- var childElement = element.canvas.getDocumentElement(this);
- if(childElement === undefined) {
- return true;
- }
- toret.push(childElement);
- });
- return toret;
- },
- childIndex: function(child) {
- var children = this.children(),
- toret = null;
- children.forEach(function(c, idx) {
- if(c.sameNode(child)) {
- toret = idx;
- return false;
- }
- });
- return toret;
- },
- getWlxmlTag: function() {
- return this._container().attr('wlxml-tag');
- },
- setWlxmlTag: function(tag) {
- this._container().attr('wlxml-tag', tag);
- },
- getWlxmlClass: function() {
- var klass = this._container().attr('wlxml-class');
- if(klass) {
- return klass.replace(/-/g, '.');
- }
- return undefined;
- },
- setWlxmlClass: function(klass) {
- if(klass === this.getWlxmlClass()) {
- return;
- }
- if(klass) {
- this._container().attr('wlxml-class', klass.replace(/\./g, '-'));
- }
- else {
- this._container().removeAttr('wlxml-class');
- }
- this.manager = wlxmlManagers.getFor(this);
- this.manager.setup();
-
- this.refreshPath();
- },
toggleLabel: function(toggle) {
var displayCss = toggle ? 'inline-block' : 'none';
var label = this.dom().children('.canvas-widgets').find('.canvas-widget-label');
this._container().toggleClass('highlighted-element', toggle);
},
- toggle: function(toggle) {
- if(this.manager) {
- this.manager.toggle(toggle);
- }
- },
-
isBlock: function() {
return this.dom().css('display') === 'block';
},
- containsBlock: function() {
- return this.children()
- .filter(function(child) {
- return child instanceof DocumentNodeElement;
- })
- .some(function(child) {
- if(child.isBlock()) {
- return true;
- } else {
- return child.containsBlock();
- }
- });
- },
-
displayAsBlock: function() {
this.dom().css('display', 'block');
this._container().css('display', 'block');
displayInline: function() {
this.dom().css('display', 'inline');
this._container().css('display', 'inline');
+ },
+ displayAs: function(what) {
+ // [this.dom(), this._container()].forEach(e) {
+ // var isBlock = window.getComputedStyle(e).display === 'block';
+ // if(!isBlock && what === 'block') {
+ // e.css('display', what);
+ // } else if(isBlock && what === 'inline') {
+ // e.css('display')
+ // }
+ // })
+ this.dom().css('display', what);
+ this._container().css('display', what);
}
});
$.extend(DocumentTextElement.prototype, {
createDOM: function() {
- return $('<div>')
+ this.$element = $('<div>')
.attr('document-text-element', '')
.text(this.wlxmlNode.getText() || utils.unicode.ZWS);
},
toggleHighlight: function() {
// do nothing for now
+ },
+ children: function() {
+ return [];
}
});
DocumentNodeElement.apply(this, Array.prototype.slice.call(arguments, 0));
};
SpanElement.prototype = $.extend(Object.create(DocumentNodeElement.prototype), {
+ defaultDisplayStyle: 'inline',
init: function() {
if(this.containsBlock()) {
this.displayAsBlock();
--- /dev/null
+define(function(require) {
+
+'use strict';
+
+var documentElement = require('./documentElement'),
+ utils = require('./utils'),
+ wlxmlUtils = require('utils/wlxml');
+
+var labelWidget = function(tag, klass) {
+ return $('<span>')
+ .addClass('canvas-widget canvas-widget-label')
+ .text(wlxmlUtils.getTagLabel(tag) + (klass ? ' / ' + wlxmlUtils.getClassLabel(klass) : ''));
+};
+void(labelWidget); // for linters; labelWidget is unused on purpose for now
+
+
+var generic = {
+ onNodeAttrChange: function(event) {
+ if(event.meta.attr === 'class') {
+ this.setWlxmlClass(event.meta.newVal); //
+ }
+ },
+ onNodeAdded: function(event) {
+ if(event.meta.node.isRoot()) {
+ this.canvas.reloadRoot();
+ return;
+ }
+
+ var nodeIndex = event.meta.node.getIndex(),
+ referenceElement, referenceAction, actionArg;
+
+ if(nodeIndex === 0) {
+ referenceElement = this;
+ referenceAction = 'prepend';
+ } else {
+ referenceElement = this.children()[nodeIndex-1];
+ referenceAction = 'after';
+ }
+
+ actionArg = (event.type === 'nodeMoved' && utils.findCanvasElement(event.meta.node, event.meta.parent)) || event.meta.node;
+ referenceElement[referenceAction](actionArg);
+ },
+ onNodeMoved: function(event) {
+ return this.onNodeAdded.call(this, event, true);
+ },
+ onNodeDetached: function(event) {
+ if(event.meta.node.sameNode(this)) {
+ this.detach();
+ } else {
+ this.children().some(function(child) {
+ if(child.wlxmlNode.sameNode(event.meta.node)) {
+ child.detach();
+ return true;
+ }
+ });
+ }
+ },
+ onNodeTextChange: function(event) {
+ var toSet = event.meta.node.getText();
+ this.children().some(function(child) {
+ if(child.wlxmlNode.sameNode(event.meta.node)) {
+ if(toSet === '') {
+ toSet = utils.unicode.ZWS;
+ }
+ if(toSet !== child.getText()) {
+ child.setText(toSet);
+ }
+ return true;
+ }
+ });
+ },
+
+ prepend: function(param) {
+ var element;
+ if(param instanceof documentElement.DocumentElement) {
+ element = param;
+ } else {
+ element = this.canvas.createElement(param);
+ }
+ this._container().prepend(element.dom());
+ this.refreshPath();
+ return element;
+ },
+
+ children: function() {
+ var element = this,
+ toret = [];
+ this._container().contents().each(function() {
+ var childElement = element.canvas.getDocumentElement(this);
+ if(childElement === undefined) {
+ return true;
+ }
+
+ toret.push(childElement);
+ });
+ return toret;
+ },
+
+ getFirst: function(e1, e2) {
+ var idx1 = this.childIndex(e1),
+ idx2 = this.childIndex(e2);
+ if(e1 === null || e2 === null) {
+ return undefined;
+ }
+ return idx1 <= idx2 ? e1: e2;
+ },
+
+ childIndex: function(child) {
+ var children = this.children(),
+ toret = null;
+ children.forEach(function(c, idx) {
+ if(c.sameNode(child)) {
+ toret = idx;
+ return false;
+ }
+ });
+ return toret;
+ },
+
+ getWlxmlClass: function() {
+ var klass = this._container().attr('wlxml-class');
+ if(klass) {
+ return klass.replace(/-/g, '.');
+ }
+ return undefined;
+ },
+ setWlxmlClass: function(klass) {
+ if(klass === this.getWlxmlClass()) {
+ return;
+ }
+ if(klass) {
+ this._container().attr('wlxml-class', klass.replace(/\./g, '-'));
+ }
+ else {
+ this._container().removeAttr('wlxml-class');
+ }
+ this.refreshPath();
+ },
+ init: function() {
+ this._container()
+ .attr('wlxml-tag', this.wlxmlNode.getTagName());
+ this.setWlxmlClass(this.wlxmlNode.getClass());
+ this.wlxmlNode.contents().forEach(function(node) {
+ this._container().append(this.canvas.createElement(node).dom());
+ }.bind(this));
+ },
+ containsBlock: function() {
+ return this.children()
+ .filter(function(child) {
+ return child instanceof documentElement.DocumentNodeElement;
+ })
+ .some(function(child) {
+ if(child.isBlock()) {
+ return true;
+ } else {
+ return child.containsBlock();
+ }
+ });
+ },
+ getVerticallyFirstTextElement: function() {
+ var toret;
+ this.children().some(function(child) {
+ if(child instanceof documentElement.DocumentTextElement) {
+ toret = child;
+ return true; // break
+ } else {
+ toret = child.getVerticallyFirstTextElement();
+ if(toret) {
+ return true; // break
+ }
+ }
+ });
+ return toret;
+ },
+};
+
+
+return generic;
+
+
+
+});
\ No newline at end of file
return toret;
};
+var getElementForNode = function(node) {
+
+ var ptr = node.nodeType === Node.TEXT_NODE ? node.parent() : node;
+ while(!ptr.getData('canvasElement')) {
+ ptr = ptr.parent();
+ }
+ return ptr.getData('canvasElement');
+};
+
+var getElementForDetachedNode = function(node, originalParent) {
+ var ptr = originalParent;
+ if(ptr === null) {
+ return node.getData('canvasElement');
+ }
+ while(!ptr.getData('canvasElement')) {
+ ptr = ptr.parent();
+ }
+ return ptr.getData('canvasElement');
+};
+
return {
nearestInDocumentOrder: nearestInDocumentOrder,
findCanvasElement: findCanvasElement,
findCanvasElementInParent: findCanvasElementInParent,
unicode: {
ZWS: '\u200B'
- }
+ },
+ getElementForNode: getElementForNode,
+ getElementForDetachedNode: getElementForDetachedNode
};
});
var _metadataEventHandler = function(event) {
- var canvasNode = utils.findCanvasElement(event.meta.node);
- canvasNode.exec('updateMetadata');
+ var element = utils.getElementForNode(event.meta.node);
+ element.handle(event);
};
+
var handlers = {
nodeAttrChange: function(event) {
+ var element = utils.getElementForNode(event.meta.node),
+ objectChanged;
if(event.meta.attr === 'class') {
- var canvasNode = utils.findCanvasElement(event.meta.node);
- canvasNode.setWlxmlClass(event.meta.newVal);
+ objectChanged = element.updateObject();
+ }
+
+ if(!objectChanged) {
+ element.handle(event);
}
},
- nodeAdded: function(event, checkForExistence) {
+ nodeAdded: function(event) {
if(event.meta.node.isRoot()) {
this.canvas.reloadRoot();
return;
}
- var parentElement = utils.findCanvasElement(event.meta.node.parent()),
- nodeIndex = event.meta.node.getIndex(),
- referenceElement, referenceAction, actionArg;
- if(nodeIndex === 0) {
- referenceElement = parentElement;
- referenceAction = 'prepend';
- } else {
- referenceElement = parentElement.children()[nodeIndex-1];
- referenceAction = 'after';
- }
+ var containingNode = event.meta.node.parent(),
+ containingElement = utils.getElementForNode(containingNode);
- actionArg = (checkForExistence && utils.findCanvasElement(event.meta.node, event.meta.parent)) || event.meta.node;
- referenceElement[referenceAction](actionArg);
+ containingElement.handle(event);
},
nodeMoved: function(event) {
- return handlers.nodeAdded.call(this, event, true);
+ return handlers.nodeAdded.call(this, event, true); //
+ //
},
nodeDetached: function(event) {
- var canvasNode = utils.findCanvasElementInParent(event.meta.node, event.meta.parent);
- canvasNode.detach();
+ var element = utils.getElementForDetachedNode(event.meta.node, event.meta.parent);
+ element.handle(event);
},
nodeTextChange: function(event) {
- //console.log('wlxmlListener: ' + event.meta.node.getText());
- var canvasElement = utils.findCanvasElement(event.meta.node),
- toSet = event.meta.node.getText();
- if(toSet === '') {
- toSet = utils.unicode.ZWS;
- }
- if(toSet !== canvasElement.getText()) {
- canvasElement.setText(toSet);
- }
+ var element = utils.getElementForNode(event.meta.node.parent());
+ element.handle(event);
},
metadataChanged: _metadataEventHandler,
return function(sandbox) {
- var canvasElements;
+ var canvasElements = [];
- sandbox.getPlugins(function(plugin) {
+ sandbox.getPlugins().forEach(function(plugin) {
canvasElements = canvasElements.concat(plugin.canvasElements || []);
});
--- /dev/null
+define(function(require) {
+
+'use strict';
+
+
+var widgets = {
+ footnoteHandler: function(clickHandler) {
+ var mydom = $('<span>')
+ .addClass('canvas-widget canvas-widget-footnote-handle')
+ .css('display', 'inline')
+ .show();
+
+ mydom.click(function(e) {
+ e.stopPropagation();
+ clickHandler();
+ });
+
+ return mydom;
+ },
+ commentAdnotation: function(node) {
+ var widget = {
+ DOM: $('<div>').addClass('canvas-widget canvas-widget-comment-adnotation'),
+ update: function(node) {
+ var parts = [],
+ metadata = node.getMetadata(),
+ dt;
+ metadata.forEach(function(row) {
+ parts.push(row.getValue());
+ }, 'creator');
+ metadata.some(function(row) {
+ dt = row.getValue();
+ return true; // break
+ }, 'date');
+ if(dt) {
+ parts.push(dt);
+ }
+ this.DOM.text(parts.join(', '));
+ }
+ };
+ widget.update(node);
+ return widget;
+ },
+ hideButton: function(clickHandler) {
+ var mydom = $('<span>x</span>')
+ .addClass('canvas-widget canvas-widget-hide-button');
+ mydom.click(function(e) {
+ e.stopPropagation();
+ clickHandler();
+ });
+ return mydom;
+ }
+}
+
+
+var comment = {
+ init: function() {
+ this.super.init.call(this);
+ this.commentAdnotation = widgets.commentAdnotation(this.wlxmlNode);
+ this.addWidget(this.commentAdnotation, 'show');
+ this.commentAdnotation.DOM.show();
+ },
+
+ onMetadataChanged: function(event) {
+ this.commentAdnotation.update(event.meta.node);
+ },
+ onMetadataAdded: function(event) {
+ return this.onMetadataChanged(event);
+ },
+ onMetadataRemoved: function(event) {
+ return this.onMetadataChanged(event);
+ }
+};
+
+var footnote = {
+ init: function() {
+ this.super.init.call(this);
+ var clickHandler = function() {
+ this.toggle(true);
+ }.bind(this);
+ this.footnoteHandler = widgets.footnoteHandler(clickHandler);
+ this.addWidget(this.footnoteHandler);
+
+ var closeHandler = function() {
+ this.toggle(false);
+ }.bind(this);
+ this.hideButton = widgets.hideButton(closeHandler);
+ this.addWidget(this.hideButton);
+ this.toggle(false, {silent: true});
+ },
+ toggle: function(toggle, options) {
+ options = options || {};
+ this.hideButton.toggle(toggle);
+ this.footnoteHandler.toggle(!toggle);
+
+ if(toggle) {
+ this.displayAsBlock();
+ } else {
+ this.displayInline();
+ }
+ this._container().toggle(toggle);
+ if(!options.silent) {
+ this.trigger('elementToggled', toggle, this.documentElement);
+ }
+ }
+}
+
+
+return [
+ {klass: 'comment', element: comment},
+ {klass: 'footnote', element: footnote}
+];
+
+
+});
\ No newline at end of file