'libs/underscore',
'libs/backbone',
'fnpjs/logging/logging',
+'views/menu/menu',
'modules/documentCanvas/canvas/documentElement',
'modules/documentCanvas/canvas/keyboard',
'modules/documentCanvas/canvas/utils',
'modules/documentCanvas/canvas/nullElement',
'modules/documentCanvas/canvas/gutter',
'modules/documentCanvas/canvas/selection',
+'modules/documentCanvas/canvas/keyEvent',
'libs/text!./canvas.html'
-], function($, _, Backbone, logging, documentElement, keyboard, utils, wlxmlListener, ElementsRegister, genericElement, nullElement, gutter, selection, canvasTemplate) {
-
+], function($, _, Backbone, logging, Menu, documentElement, keyboard, utils, wlxmlListener, ElementsRegister, genericElement, nullElement, gutter, selection, keyEvent, canvasTemplate) {
+
'use strict';
/* global document:false, window:false, Node:false, gettext */
});
-var Canvas = function(wlxmlDocument, elements, metadata) {
+var Canvas = function(wlxmlDocument, elements, metadata, sandbox) {
this.metadata = metadata || {};
- this.elementsRegister = new ElementsRegister(documentElement.DocumentNodeElement, nullElement);
+ this.sandbox = sandbox;
+ this.elementsRegister = this.createElementsRegister();
elements = [
{tag: 'section', klass: null, prototype: genericElement},
$.extend(Canvas.prototype, Backbone.Events, {
+ createElementType: function(elementPrototype) {
+ /* TODO: reconcile this with ElementsRegister behavior */
+ var Constructor = function() {
+ documentElement.DocumentNodeElement.apply(this, Array.prototype.slice.call(arguments, 0));
+ };
+ Constructor.prototype = elementPrototype;
+ return Constructor;
+ },
+
getElementOffset: function(element) {
return element.dom.offset().top - this.dom.offset().top;
},
this.reloadRoot();
},
- createElement: function(wlxmlNode) {
+ createElement: function(wlxmlNode, register, useRoot) {
var Factory;
+ register = register || this.elementsRegister;
if(wlxmlNode.nodeType === Node.TEXT_NODE) {
Factory = documentElement.DocumentTextElement;
} else {
+ Factory = register.getElement({tag: wlxmlNode.getTagName(), klass: wlxmlNode.getClass()});
+ }
+ if(!Factory && useRoot) {
Factory = this.elementsRegister.getElement({tag: wlxmlNode.getTagName(), klass: wlxmlNode.getClass()});
+ if(!Factory) {
+ Factory = documentElement.DocumentNodeElement;
+ }
+ }
+
+ if(Factory) {
+ return new Factory(wlxmlNode, this);
}
- return new Factory(wlxmlNode, this);
+ },
+
+ createElementsRegister: function() {
+ return new ElementsRegister(documentElement.DocumentNodeElement, nullElement);
},
getDocumentElement: function(htmlElement) {
this.rootWrapper.append(this.rootElement.dom);
},
+ triggerKeyEvent: function(keyEvent, selection) {
+ selection = selection || this.getSelection();
+ if(selection && (
+ (selection.type === 'caret' || selection.type === 'textSelection') && selection.toDocumentFragment().isValid()
+ || selection.type == 'nodeSelection')) {
+ keyboard.handleKeyEvent(keyEvent, selection);
+ }
+ },
+
+ createAction: function(fqName, config) {
+ return this.sandbox.createAction(fqName, config);
+ },
+
setupEventHandling: function() {
var canvas = this;
/* globals document */
$(document.body).on('keydown', function(e) {
- var cursor = canvas.getCursor();
- if(cursor.isSelecting() || Object.keys(cursor.getPosition()).length) {
- keyboard.handleKey(e, canvas);
- }
+ canvas.triggerKeyEvent(keyEvent.fromNativeEvent(e));
});
this.rootWrapper.on('mouseup', function() {
}
});
+ this.rootWrapper.on('contextmenu', function(e) {
+ var el = canvas.getDocumentElement(e.target);
+
+ if(!el) {
+ return;
+ }
+
+ e.preventDefault();
+ this.showContextMenu(el, {x: e.clientX, y: e.clientY});
+ }.bind(this));
+
this.rootWrapper.on('paste', function(e) {
e.preventDefault();
if(mutation.target.data === '') {
mutation.target.data = utils.unicode.ZWS;
}
- else if(mutation.oldValue === utils.unicode.ZWS) {
+ if(mutation.target.data === mutation.oldValue) {
+ return; // shouldn't happen, but better be safe
+ }
+ if(mutation.oldValue === utils.unicode.ZWS) {
mutation.target.data = mutation.target.data.replace(utils.unicode.ZWS, '');
canvas._moveCaretToTextElement(canvas.getDocumentElement(mutation.target), 'end');
}
}
},
+ setSelection: function(selection) {
+ this.select(this, selection.toDocumentFragment());
+ },
+
+ createSelection: function(params) {
+ return selection.fromParams(this, params);
+ },
setCurrentElement: function(element, params) {
if(!element) {
logger.debug('Invalid element passed to setCurrentElement: ' + element);
if(position.element) {
this._moveCaretToTextElement(position.element, position.offset);
}
+ },
+ showContextMenu: function(element, coors) {
+ var menu = new Menu();
+
+ while(element) {
+ (element.contextMenuActions || []).forEach(menu.addAction.bind(menu));
+ element = element.parent();
+ }
+ if(menu.actions.length) {
+ menu.updateContextParam('fragment', this.getSelection().toDocumentFragment());
+ this.sandbox.showContextMenu(menu, {x: coors.x, y: coors.y});
+ }
}
});
return this.getSelectionAnchor();
},
getSelectionStart: function() {
- return this.getSelectionBoundry('start');
+ return this.getSelectionBoundary('start');
},
getSelectionEnd: function() {
- return this.getSelectionBoundry('end');
+ return this.getSelectionBoundary('end');
},
getSelectionAnchor: function() {
- return this.getSelectionBoundry('anchor');
+ return this.getSelectionBoundary('anchor');
},
getSelectionFocus: function() {
- return this.getSelectionBoundry('focus');
+ return this.getSelectionBoundary('focus');
},
- getSelectionBoundry: function(which) {
+ getSelectionBoundary: function(which) {
/* globals window */
var selection = window.getSelection(),
anchorElement = this.canvas.getDocumentElement(selection.anchorNode),
});
return {
- fromXMLDocument: function(wlxmlDocument, elements, metadata) {
- return new Canvas(wlxmlDocument, elements, metadata);
+ fromXMLDocument: function(wlxmlDocument, elements, metadata, sandbox) {
+ return new Canvas(wlxmlDocument, elements, metadata, sandbox);
}
};