Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/richdocuments.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAditya Bhatt <aditya@bhatts.org>2014-03-04 17:37:28 +0400
committerAditya Bhatt <aditya@bhatts.org>2014-03-04 19:19:31 +0400
commit3cd491a5ef061fa97780852aaca97352c9d5e1a8 (patch)
treedbefc197ca3f6b7709f93ded5214425817d7e5ca
parent8b71362d0e709815a4cb90d961456b3ce268d77d (diff)
Sync with WebODF e50bc588ff3e380178ffabecfe2fbca92bef6aed.
* Keyboard support in iOS and other touchscreens * Pinch-zoom support on touch devices * SVG selections that look like those in LibreOffice * Major speed improvements with all editing operations and cursor movements * IME support on desktop browsers * Word-by-word navigation with Ctrl+Left/Right * Fixes for IE11 * Ability to add/edit/remove Hyperlinks.
-rw-r--r--css/3rdparty/webodf/editor.css24
-rw-r--r--js/3rdparty/webodf/editor/Editor.js74
-rw-r--r--js/3rdparty/webodf/editor/EditorSession.js68
-rw-r--r--js/3rdparty/webodf/editor/Tools.js16
-rw-r--r--js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js14
-rw-r--r--js/3rdparty/webodf/editor/widgets/dialogWidgets/alignmentPane.js5
-rw-r--r--js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.html30
-rw-r--r--js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.js110
-rw-r--r--js/3rdparty/webodf/editor/widgets/editHyperlinks.js181
-rw-r--r--js/3rdparty/webodf/editor/widgets/paragraphAlignment.js34
-rw-r--r--js/3rdparty/webodf/editor/widgets/simpleStyles.js38
-rw-r--r--js/3rdparty/webodf/editor/widgets/undoRedoMenu.js92
-rw-r--r--js/3rdparty/webodf/editor/widgets/zoomSlider.js35
-rw-r--r--js/3rdparty/webodf/webodf-debug.js16541
-rw-r--r--js/3rdparty/webodf/webodf.js1828
15 files changed, 9648 insertions, 9442 deletions
diff --git a/css/3rdparty/webodf/editor.css b/css/3rdparty/webodf/editor.css
index 23f86ee9..6f23a0c8 100644
--- a/css/3rdparty/webodf/editor.css
+++ b/css/3rdparty/webodf/editor.css
@@ -25,13 +25,18 @@ body.claro, #mainContainer {
#toolbar {
overflow: hidden;
+ top: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+ z-index: 5;
+ box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
}
#container {
text-align: center;
background-color: #ddd;
overflow: auto;
-
position: absolute;
top: 30px;
bottom: 0;
@@ -40,7 +45,6 @@ body.claro, #mainContainer {
}
#canvas {
- box-shadow: 0px 0px 20px #aaa;
margin-top: 30px;
margin-left: 10px;
margin-right: 10px;
@@ -50,8 +54,16 @@ body.claro, #mainContainer {
-webkit-transform-origin: top center;
-moz-transform-origin: top center;
-o-transform-origin: top center;
- overflow: hidden;
+ overflow: visible;
+}
+/* Add shadow to the sizer and not the canvas,
+ * so that it will follow the smooth zooming
+ * of the slider and not have to be updated
+ * every time a gesture ends
+ */
+#canvas > div {
+ box-shadow: 0px 0px 20px #aaa;
border: 1px solid #ccc;
}
@@ -241,7 +253,7 @@ div.memberListLabel[fullname]:before {
text-align: center;
}
-cursor div {
+cursor .handle {
margin-top: 5px;
padding-top: 3px;
margin-left: auto;
@@ -269,11 +281,11 @@ cursor img {
margin: auto;
}
-cursor div.active {
+cursor .handle.active {
opacity: 0.8;
}
-cursor div:after {
+cursor .handle:after {
content: ' ';
position: absolute;
width: 0px;
diff --git a/js/3rdparty/webodf/editor/Editor.js b/js/3rdparty/webodf/editor/Editor.js
index 86840e2f..ce2d1b92 100644
--- a/js/3rdparty/webodf/editor/Editor.js
+++ b/js/3rdparty/webodf/editor/Editor.js
@@ -317,6 +317,7 @@ define("webodf/editor/Editor", [
runtime.assert(editorSession, "editorSession should exist here.");
tools.setEditorSession(editorSession);
+ editorSession.sessionController.insertLocalCursor();
editorSession.sessionController.startEditing();
};
@@ -330,6 +331,7 @@ define("webodf/editor/Editor", [
tools.setEditorSession(undefined);
editorSession.sessionController.endEditing();
+ editorSession.sessionController.removeLocalCursor();
};
/**
@@ -365,12 +367,51 @@ define("webodf/editor/Editor", [
};
/**
+ * Applies a CSS transformation to the toolbar
+ * to ensure that if there is a body-scroll,
+ * the toolbar remains visible at the top of
+ * the screen.
+ * The bodyscroll quirk has been observed on
+ * iOS, generally when the keyboard appears.
+ * But this workaround should function on
+ * other platforms that exhibit this behaviour
+ * as well.
+ * @return {undefined}
+ */
+ function translateToolbar() {
+ var bar = document.getElementById('toolbar'),
+ y = document.body.scrollTop;
+
+ bar.style.WebkitTransformOrigin = "center top";
+ bar.style.WebkitTransform = 'translateY(' + y + 'px)';
+ }
+
+ /**
+ * FIXME: At the moment both the toolbar and the canvas
+ * container are absolutely positioned. Changing them to
+ * relative positioning to ensure that they do not overlap
+ * causes scrollbars *within* the container to disappear.
+ * Not sure why this happens, and a proper CSS fix has not
+ * been found yet, so for now we need to reposition
+ * the container using Js.
+ * @return {undefined}
+ */
+ function repositionContainer() {
+ document.getElementById('container').style.top = document.getElementById('toolbar').getBoundingClientRect().height + 'px';
+ }
+
+ /**
* @param {!function(!Object=)} callback, passing an error object in case of error
* @return {undefined}
*/
this.destroy = function (callback) {
var destroyMemberListView = memberListView ? memberListView.destroy : function(cb) { cb(); };
+ window.removeEventListener('scroll', translateToolbar);
+ window.removeEventListener('focusout', translateToolbar);
+ window.removeEventListener('touchmove', translateToolbar);
+ window.removeEventListener('resize', repositionContainer);
+
// TODO: decide if some forced close should be done here instead of enforcing proper API usage
runtime.assert(!session, "session should not exist here.");
@@ -407,10 +448,12 @@ define("webodf/editor/Editor", [
var editorPane, memberListPane,
inviteButton,
canvasElement = document.getElementById("canvas"),
+ container = document.getElementById('container'),
memberListElement = document.getElementById('memberList'),
collabEditing = Boolean(server),
directParagraphStylingEnabled = (! collabEditing) || args.unstableFeaturesEnabled,
imageInsertingEnabled = (! collabEditing) || args.unstableFeaturesEnabled,
+ hyperlinkEditingEnabled = (! collabEditing) || args.unstableFeaturesEnabled,
// annotations not yet properly supported for OT
annotationsEnabled = (! collabEditing) || args.unstableFeaturesEnabled,
// undo manager is not yet integrated with collaboration
@@ -471,18 +514,19 @@ define("webodf/editor/Editor", [
}
tools = new Tools({
- onToolDone: setFocusToOdfCanvas,
- loadOdtFile: loadOdtFile,
- saveOdtFile: saveOdtFile,
- close: close,
- directParagraphStylingEnabled: directParagraphStylingEnabled,
- imageInsertingEnabled: imageInsertingEnabled,
- annotationsEnabled: annotationsEnabled,
- undoRedoEnabled: undoRedoEnabled
- });
+ onToolDone: setFocusToOdfCanvas,
+ loadOdtFile: loadOdtFile,
+ saveOdtFile: saveOdtFile,
+ close: close,
+ directParagraphStylingEnabled: directParagraphStylingEnabled,
+ imageInsertingEnabled: imageInsertingEnabled,
+ hyperlinkEditingEnabled: hyperlinkEditingEnabled,
+ annotationsEnabled: annotationsEnabled,
+ undoRedoEnabled: undoRedoEnabled
+ });
odfCanvas = new odf.OdfCanvas(canvasElement);
- odfCanvas.enableAnnotations(annotationsEnabled);
+ odfCanvas.enableAnnotations(annotationsEnabled, true);
odfCanvas.addListener("statereadychange", function () {
var viewOptions = {
@@ -496,7 +540,8 @@ define("webodf/editor/Editor", [
editorSession = new EditorSession(session, pendingMemberId, {
viewOptions: viewOptions,
directParagraphStylingEnabled: directParagraphStylingEnabled,
- imageInsertingEnabled: imageInsertingEnabled
+ imageInsertingEnabled: imageInsertingEnabled,
+ hyperlinkEditingEnabled: hyperlinkEditingEnabled
});
if (undoRedoEnabled) {
editorSession.sessionController.setUndoManager(new gui.TrivialUndoManager());
@@ -512,6 +557,13 @@ define("webodf/editor/Editor", [
pendingEditorReadyCallback = null;
pendingMemberId = null;
});
+
+ repositionContainer();
+
+ window.addEventListener('scroll', translateToolbar);
+ window.addEventListener('focusout', translateToolbar);
+ window.addEventListener('touchmove', translateToolbar);
+ window.addEventListener('resize', repositionContainer);
}
init();
diff --git a/js/3rdparty/webodf/editor/EditorSession.js b/js/3rdparty/webodf/editor/EditorSession.js
index 91d28b43..5c33e5af 100644
--- a/js/3rdparty/webodf/editor/EditorSession.js
+++ b/js/3rdparty/webodf/editor/EditorSession.js
@@ -43,10 +43,6 @@ define("webodf/editor/EditorSession", [
], function (fontsCSS) { // fontsCSS is retrieved as a string, using dojo's text retrieval AMD plugin
"use strict";
- runtime.libraryPaths = function () {
- return [ "../../webodf/lib" ];
- };
-
runtime.loadClass("core.DomUtils");
runtime.loadClass("odf.OdfUtils");
runtime.loadClass("ops.OdtDocument");
@@ -54,11 +50,13 @@ define("webodf/editor/EditorSession", [
runtime.loadClass("ops.Session");
runtime.loadClass("odf.Namespaces");
runtime.loadClass("odf.OdfCanvas");
+ runtime.loadClass("odf.OdfUtils");
runtime.loadClass("gui.CaretManager");
runtime.loadClass("gui.Caret");
runtime.loadClass("gui.SessionController");
runtime.loadClass("gui.SessionView");
runtime.loadClass("gui.TrivialUndoManager");
+ runtime.loadClass("gui.SvgSelectionView");
runtime.loadClass("gui.SelectionViewManager");
runtime.loadClass("core.EventNotifier");
runtime.loadClass("gui.ShadowCursor");
@@ -208,7 +206,7 @@ define("webodf/editor/EditorSession", [
function trackCurrentParagraph(info) {
var cursor = odtDocument.getCursor(localMemberId),
range = cursor && cursor.getSelectedRange(),
- paragraphRange = odtDocument.getDOM().createRange();
+ paragraphRange = odtDocument.getDOMDocument().createRange();
paragraphRange.selectNode(info.paragraphElement);
if ((range && domUtils.rangesIntersect(range, paragraphRange)) || info.paragraphElement === currentParagraphNode) {
self.emit(EditorSession.signalParagraphChanged, info);
@@ -312,7 +310,7 @@ define("webodf/editor/EditorSession", [
/**
* Round the step up to the next step
* @param {!number} step
- * @returns {!boolean}
+ * @return {!boolean}
*/
function roundUp(step) {
return step === ops.StepsTranslator.NEXT_STEP;
@@ -387,14 +385,14 @@ define("webodf/editor/EditorSession", [
return formatting.isStyleUsed(styleElement);
};
- function getDefaultParagraphStyleAttributes () {
+ function getDefaultParagraphStyleAttributes() {
var styleNode = formatting.getDefaultStyleElement('paragraph');
if (styleNode) {
return formatting.getInheritedStyleAttributes(styleNode);
}
return null;
- };
+ }
/**
* Returns the attributes of a given paragraph style name
@@ -522,22 +520,30 @@ define("webodf/editor/EditorSession", [
return array;
};
+ this.getSelectedHyperlinks = function () {
+ var cursor = odtDocument.getCursor(localMemberId);
+ // no own cursor yet/currently added?
+ if (!cursor) {
+ return [];
+ }
+ return odfUtils.getHyperlinkElements(cursor.getSelectedRange());
+ };
+
+ this.getSelectedRange = function () {
+ var cursor = odtDocument.getCursor(localMemberId);
+ return cursor && cursor.getSelectedRange();
+ };
+
function undoStackModified(e) {
self.emit(EditorSession.signalUndoStackChanged, e);
}
- this.hasUndoManager = function () {
- return Boolean(self.sessionController.getUndoManager());
- };
-
this.undo = function () {
- var undoManager = self.sessionController.getUndoManager();
- undoManager.moveBackward(1);
+ self.sessionController.undo();
};
this.redo = function () {
- var undoManager = self.sessionController.getUndoManager();
- undoManager.moveForward(1);
+ self.sessionController.redo();
};
/**
@@ -548,8 +554,8 @@ define("webodf/editor/EditorSession", [
* @param {!number} height
*/
this.insertImage = function (mimetype, content, width, height) {
- self.sessionController.getTextManipulator().removeCurrentSelection();
- self.sessionController.getImageManager().insertImage(mimetype, content, width, height);
+ self.sessionController.getTextController().removeCurrentSelection();
+ self.sessionController.getImageController().insertImage(mimetype, content, width, height);
};
/**
@@ -569,12 +575,12 @@ define("webodf/editor/EditorSession", [
head.removeChild(fontStyles);
- odtDocument.unsubscribe(ops.OdtDocument.signalMemberAdded, onMemberAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalMemberUpdated, onMemberUpdated);
- odtDocument.unsubscribe(ops.OdtDocument.signalMemberRemoved, onMemberRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
+ odtDocument.unsubscribe(ops.Document.signalMemberAdded, onMemberAdded);
+ odtDocument.unsubscribe(ops.Document.signalMemberUpdated, onMemberUpdated);
+ odtDocument.unsubscribe(ops.Document.signalMemberRemoved, onMemberRemoved);
+ odtDocument.unsubscribe(ops.Document.signalCursorAdded, onCursorAdded);
+ odtDocument.unsubscribe(ops.Document.signalCursorRemoved, onCursorRemoved);
+ odtDocument.unsubscribe(ops.Document.signalCursorMoved, onCursorMoved);
odtDocument.unsubscribe(ops.OdtDocument.signalCommonStyleCreated, onStyleCreated);
odtDocument.unsubscribe(ops.OdtDocument.signalCommonStyleDeleted, onStyleDeleted);
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
@@ -623,17 +629,17 @@ define("webodf/editor/EditorSession", [
directParagraphStylingEnabled: config.directParagraphStylingEnabled
});
caretManager = new gui.CaretManager(self.sessionController);
- selectionViewManager = new gui.SelectionViewManager();
+ selectionViewManager = new gui.SelectionViewManager(gui.SvgSelectionView);
self.sessionView = new gui.SessionView(config.viewOptions, localMemberId, session, caretManager, selectionViewManager);
self.availableFonts = getAvailableFonts();
selectionViewManager.registerCursor(shadowCursor, true);
// Custom signals, that make sense in the Editor context. We do not want to expose webodf's ops signals to random bits of the editor UI.
- odtDocument.subscribe(ops.OdtDocument.signalMemberAdded, onMemberAdded);
- odtDocument.subscribe(ops.OdtDocument.signalMemberUpdated, onMemberUpdated);
- odtDocument.subscribe(ops.OdtDocument.signalMemberRemoved, onMemberRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
+ odtDocument.subscribe(ops.Document.signalMemberAdded, onMemberAdded);
+ odtDocument.subscribe(ops.Document.signalMemberUpdated, onMemberUpdated);
+ odtDocument.subscribe(ops.Document.signalMemberRemoved, onMemberRemoved);
+ odtDocument.subscribe(ops.Document.signalCursorAdded, onCursorAdded);
+ odtDocument.subscribe(ops.Document.signalCursorRemoved, onCursorRemoved);
+ odtDocument.subscribe(ops.Document.signalCursorMoved, onCursorMoved);
odtDocument.subscribe(ops.OdtDocument.signalCommonStyleCreated, onStyleCreated);
odtDocument.subscribe(ops.OdtDocument.signalCommonStyleDeleted, onStyleDeleted);
odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
diff --git a/js/3rdparty/webodf/editor/Tools.js b/js/3rdparty/webodf/editor/Tools.js
index 8ab50b2b..c0aa4dad 100644
--- a/js/3rdparty/webodf/editor/Tools.js
+++ b/js/3rdparty/webodf/editor/Tools.js
@@ -49,11 +49,12 @@ define("webodf/editor/Tools", [
"webodf/editor/widgets/undoRedoMenu",
"webodf/editor/widgets/toolbarWidgets/currentStyle",
"webodf/editor/widgets/annotation",
- "webodf/editor/widgets/paragraphStylesDialog",
+ "webodf/editor/widgets/editHyperlinks",
"webodf/editor/widgets/imageInserter",
+ "webodf/editor/widgets/paragraphStylesDialog",
"webodf/editor/widgets/zoomSlider",
"webodf/editor/EditorSession"],
- function (ready, MenuItem, DropDownMenu, Button, DropDownButton, Toolbar, ParagraphAlignment, SimpleStyles, UndoRedoMenu, CurrentStyle, AnnotationControl, ParagraphStylesDialog, ImageInserter, ZoomSlider, EditorSession) {
+ function (ready, MenuItem, DropDownMenu, Button, DropDownButton, Toolbar, ParagraphAlignment, SimpleStyles, UndoRedoMenu, CurrentStyle, AnnotationControl, EditHyperlinks, ImageInserter, ParagraphStylesDialog, ZoomSlider, EditorSession) {
"use strict";
return function Tools(args) {
@@ -72,6 +73,7 @@ define("webodf/editor/Tools", [
paragraphAlignment,
imageInserter,
annotationControl,
+ editHyperlinks,
sessionSubscribers = [];
function handleCursorMoved(cursor) {
@@ -128,6 +130,7 @@ define("webodf/editor/Tools", [
widget.startup();
});
sessionSubscribers.push(undoRedoMenu);
+ undoRedoMenu.onToolDone = onToolDone;
}
// Add annotation
@@ -226,6 +229,15 @@ define("webodf/editor/Tools", [
sessionSubscribers.push(paragraphStylesDialog);
paragraphStylesDialog.onToolDone = onToolDone;
+ if (args.hyperlinkEditingEnabled) {
+ editHyperlinks = new EditHyperlinks(function (widget) {
+ widget.placeAt(toolbar);
+ widget.startup();
+ });
+ sessionSubscribers.push(editHyperlinks);
+ editHyperlinks.onToolDone = onToolDone;
+ }
+
formatMenuButton = new DropDownButton({
dropDown: formatDropDownMenu,
label: tr('Format'),
diff --git a/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js b/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js
index a6cf8d61..de24b50f 100644
--- a/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js
+++ b/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js
@@ -94,7 +94,9 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () {
EVENT_BEFORESAVETOFILE,
EVENT_SAVEDTOFILE,
EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED,
- EVENT_HASSESSIONHOSTCONNECTIONCHANGED
+ EVENT_HASSESSIONHOSTCONNECTIONCHANGED,
+ ops.OperationRouter.signalProcessingBatchStart,
+ ops.OperationRouter.signalProcessingBatchEnd
]),
/**@type{!boolean} tells if any local ops have been modifying ops */
hasPushedModificationOps = false,
@@ -150,6 +152,8 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () {
// take start time
startTime = (new Date()).getTime();
+ eventNotifier.emit(ops.OperationRouter.signalProcessingBatchStart, {});
+
// apply as much as possible in the given time
while (unplayedServerOpspecQueue.length > 0) {
// time over?
@@ -164,11 +168,13 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () {
runtime.log(" op in: "+runtime.toJson(opspec));
if (op !== null) {
if (!playbackFunction(op)) {
+ eventNotifier.emit(ops.OperationRouter.signalProcessingBatchEnd, {});
hasError = true;
errorCallback("opExecutionFailure");
return;
}
} else {
+ eventNotifier.emit(ops.OperationRouter.signalProcessingBatchEnd, {});
hasError = true;
runtime.log("ignoring invalid incoming opspec: " + opspec);
errorCallback("unknownOpReceived");
@@ -176,6 +182,8 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () {
}
}
+ eventNotifier.emit(ops.OperationRouter.signalProcessingBatchEnd, {});
+
// still unplayed opspecs?
if (unplayedServerOpspecQueue.length > 0) {
// let other events be handled. then continue
@@ -493,6 +501,8 @@ runtime.log("OperationRouter: instant opsSync requested");
return;
}
+ eventNotifier.emit(ops.OperationRouter.signalProcessingBatchStart, {});
+
for (i = 0; i < operations.length; i += 1) {
op = operations[i];
opspec = op.spec();
@@ -518,6 +528,8 @@ runtime.log("OperationRouter: instant opsSync requested");
triggerPushingOps();
updateHasLocalUnsyncedOpsState();
+
+ eventNotifier.emit(ops.OperationRouter.signalProcessingBatchEnd, {});
};
/**
diff --git a/js/3rdparty/webodf/editor/widgets/dialogWidgets/alignmentPane.js b/js/3rdparty/webodf/editor/widgets/dialogWidgets/alignmentPane.js
index 9e9a149f..24136f05 100644
--- a/js/3rdparty/webodf/editor/widgets/dialogWidgets/alignmentPane.js
+++ b/js/3rdparty/webodf/editor/widgets/dialogWidgets/alignmentPane.js
@@ -38,10 +38,11 @@
/*global runtime,core,define,require,dijit */
-runtime.loadClass("core.CSSUnits");
-
define("webodf/editor/widgets/dialogWidgets/alignmentPane", [], function () {
"use strict";
+
+ runtime.loadClass("core.CSSUnits");
+
var AlignmentPane = function (callback) {
var self = this,
editorSession,
diff --git a/js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.html b/js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.html
new file mode 100644
index 00000000..ad6b5a11
--- /dev/null
+++ b/js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.html
@@ -0,0 +1,30 @@
+<html>
+ <head></head>
+ <body>
+ <div data-dojo-type="dijit/form/Form" id="editHyperlinkPaneForm" data-dojo-id="editHyperlinkPaneForm">
+ <div>
+ <label text-i18n="Display Text" for="linkDisplayText"></label><br/>
+ <input data-dojo-type="dijit/form/TextBox" id="linkDisplayText"
+ value=""
+ data-dojo-props="trim:true"
+ name="linkDisplayText" />
+ <input data-dojo-type="dijit/form/TextBox" id="isReadOnlyText"
+ type ="hidden"
+ value=""
+ data-dojo-props="trim:true"
+ name="isReadOnlyText" />
+ </div>
+ <div>
+ <label text-i18n="URL" for="linkUrl"></label><br/>
+ <input data-dojo-type="dijit/form/TextBox" id="linkUrl"
+ value="http://"
+ data-dojo-props="trim:true"
+ name="linkUrl" />
+ </div>
+ <div>
+ <button data-dojo-type="dijit/form/Button" id="saveHyperlinkChangeButton" type="submit">Ok</button>
+ <button data-dojo-type="dijit/form/Button" id="cancelHyperlinkChangeButton" data-dojo-id="cancelHyperlinkChangeButton">Cancel</button>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.js b/js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.js
new file mode 100644
index 00000000..d696e787
--- /dev/null
+++ b/js/3rdparty/webodf/editor/widgets/dialogWidgets/editHyperlinkPane.js
@@ -0,0 +1,110 @@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ *
+ * @licstart
+ * The JavaScript code in this page is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public License
+ * (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. The code is distributed
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this code. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As additional permission under GNU AGPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ * As a special exception to the AGPL, any HTML file which merely makes function
+ * calls to this code, and for that purpose includes it by reference shall be
+ * deemed a separate work for copyright law purposes. In addition, the copyright
+ * holders of this code give you permission to combine this code with free
+ * software libraries that are released under the GNU LGPL. You may copy and
+ * distribute such a system following the terms of the GNU AGPL for this code
+ * and the LGPL for the libraries. If you modify this code, you may extend this
+ * exception to your version of the code, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your
+ * version.
+ *
+ * This license applies to this entire compilation.
+ * @licend
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global runtime,core,define,require,document,dijit */
+
+define("webodf/editor/widgets/dialogWidgets/editHyperlinkPane", [
+ "dojo",
+ "dijit/layout/ContentPane"],
+
+ function (dojo, ContentPane) {
+ "use strict";
+
+ runtime.loadClass("core.CSSUnits");
+
+ var EditHyperlinkPane = function () {
+ var self = this,
+ editorBase = dojo.config && dojo.config.paths && dojo.config.paths['webodf/editor'],
+ contentPane,
+ form,
+ displayTextField,
+ initialValue;
+
+ runtime.assert(editorBase, "webodf/editor path not defined in dojoConfig");
+
+ function onSave() {
+ if (self.onSave) {
+ self.onSave();
+ }
+ return false;
+ }
+
+ function onCancel() {
+ form.set('value', initialValue);
+ if (self.onCancel) {
+ self.onCancel();
+ }
+ }
+
+ contentPane = new ContentPane({
+ title: runtime.tr("editLink"),
+ href: editorBase+"/widgets/dialogWidgets/editHyperlinkPane.html",
+ preload: true,
+ onLoad : function () {
+ form = dijit.byId('editHyperlinkPaneForm');
+ form.onSubmit = onSave;
+ dijit.byId('cancelHyperlinkChangeButton').onClick = onCancel;
+ displayTextField = dijit.byId('linkDisplayText');
+ runtime.translateContent(form.domNode);
+ if (initialValue) {
+ form.set('value', initialValue);
+ displayTextField.set('disabled', initialValue.isReadOnlyText);
+ initialValue = undefined;
+ }
+ }
+ });
+
+ this.widget = function () {
+ return contentPane;
+ };
+
+ this.value = function () {
+ return form && form.get('value');
+ };
+
+ this.set = function (value) {
+ initialValue = value;
+ if (form) {
+ form.set('value', value);
+ displayTextField.set('disabled', value.isReadOnlyText);
+ }
+ };
+ };
+
+ return EditHyperlinkPane;
+});
diff --git a/js/3rdparty/webodf/editor/widgets/editHyperlinks.js b/js/3rdparty/webodf/editor/widgets/editHyperlinks.js
new file mode 100644
index 00000000..c1fc8401
--- /dev/null
+++ b/js/3rdparty/webodf/editor/widgets/editHyperlinks.js
@@ -0,0 +1,181 @@
+/**
+ * @license
+ * Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ *
+ * @licstart
+ * The JavaScript code in this page is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public License
+ * (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. The code is distributed
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this code. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As additional permission under GNU AGPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ * As a special exception to the AGPL, any HTML file which merely makes function
+ * calls to this code, and for that purpose includes it by reference shall be
+ * deemed a separate work for copyright law purposes. In addition, the copyright
+ * holders of this code give you permission to combine this code with free
+ * software libraries that are released under the GNU LGPL. You may copy and
+ * distribute such a system following the terms of the GNU AGPL for this code
+ * and the LGPL for the libraries. If you modify this code, you may extend this
+ * exception to your version of the code, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your
+ * version.
+ *
+ * This license applies to this entire compilation.
+ * @licend
+ * @source: http://www.webodf.org/
+ * @source: https://github.com/kogmbh/WebODF/
+ */
+
+/*global define,require,document,odf */
+
+define("webodf/editor/widgets/editHyperlinks", [
+ "webodf/editor/EditorSession",
+ "webodf/editor/widgets/dialogWidgets/editHyperlinkPane",
+ "dijit/form/Button",
+ "dijit/form/DropDownButton",
+ "dijit/TooltipDialog"],
+
+ function (EditorSession, EditHyperlinkPane, Button, DropDownButton, TooltipDialog) {
+ "use strict";
+
+ runtime.loadClass("odf.OdfUtils");
+
+ var EditHyperlinks = function (callback) {
+ var self = this,
+ widget = {},
+ editorSession,
+ hyperlinkController,
+ linkEditorContent,
+ editHyperlinkButton,
+ removeHyperlinkButton,
+ odfUtils = new odf.OdfUtils(),
+ dialog;
+
+ linkEditorContent = new EditHyperlinkPane();
+ dialog = new TooltipDialog({
+ title: runtime.tr("Edit link"),
+ content: linkEditorContent.widget()
+ });
+
+ editHyperlinkButton = new DropDownButton({
+ label: runtime.tr('Edit link'),
+ showLabel: false,
+ iconClass: 'dijitEditorIcon dijitEditorIconCreateLink',
+ dropDown: dialog
+ });
+
+ removeHyperlinkButton = new Button({
+ label: runtime.tr('Remove link'),
+ showLabel: false,
+ disabled: true,
+ iconClass: 'dijitEditorIcon dijitEditorIconUnlink',
+ onClick: function () {
+ hyperlinkController.removeHyperlinks();
+ self.onToolDone();
+ }
+ });
+
+ linkEditorContent.onSave = function () {
+ var hyperlinkData = linkEditorContent.value();
+ editHyperlinkButton.closeDropDown(false);
+ if (hyperlinkData.isReadOnlyText == "true") {
+ hyperlinkController.removeHyperlinks();
+ hyperlinkController.addHyperlink(hyperlinkData.linkUrl);
+ } else {
+ hyperlinkController.addHyperlink(hyperlinkData.linkUrl, hyperlinkData.linkDisplayText);
+ }
+ self.onToolDone();
+ };
+
+ linkEditorContent.onCancel = function () {
+ editHyperlinkButton.closeDropDown(false);
+ self.onToolDone();
+ };
+
+ widget.children = [editHyperlinkButton, removeHyperlinkButton];
+ widget.startup = function () {
+ widget.children.forEach(function (element) {
+ element.startup();
+ });
+ };
+
+ widget.placeAt = function (container) {
+ widget.children.forEach(function (element) {
+ element.placeAt(container);
+ });
+ return widget;
+ };
+
+ function checkHyperlinkButtons() {
+ var selection = editorSession.getSelectedRange(),
+ textContent,
+ linksInSelection = editorSession.getSelectedHyperlinks(),
+ linkTarget = linksInSelection[0] ? odfUtils.getHyperlinkTarget(linksInSelection[0]) : "http://";
+
+ if (selection && selection.collapsed && linksInSelection.length === 1) {
+ // Selection is collapsed within a single hyperlink. Assume user is modifying the hyperlink
+ textContent = selection.cloneRange();
+ textContent.selectNodeContents(linksInSelection[0]);
+ linkEditorContent.set({
+ linkDisplayText: textContent.toString(),
+ linkUrl: linkTarget,
+ isReadOnlyText: true
+ });
+ textContent.detach();
+ } else if (selection && !selection.collapsed) {
+ // User has selected part of a hyperlink or a block of text. Assume user is attempting to modify the
+ // existing hyperlink, or wants to convert the selection into a hyperlink
+ linkEditorContent.set({
+ linkDisplayText: selection.toString(),
+ linkUrl: linkTarget,
+ isReadOnlyText: true
+ });
+ } else {
+ // Selection is collapsed and is not in an existing hyperlink
+ linkEditorContent.set({
+ linkDisplayText: "",
+ linkUrl: linkTarget,
+ isReadOnlyText: false
+ });
+ }
+
+ // The 3rd parameter is false to avoid firing onChange when setting the value programmatically.
+ removeHyperlinkButton.set('disabled', linksInSelection.length === 0, false);
+ }
+
+ this.setEditorSession = function (session) {
+ if (editorSession) {
+ editorSession.unsubscribe(EditorSession.signalCursorMoved, checkHyperlinkButtons);
+ editorSession.unsubscribe(EditorSession.signalParagraphChanged, checkHyperlinkButtons);
+ editorSession.unsubscribe(EditorSession.signalParagraphStyleModified, checkHyperlinkButtons);
+ }
+ editorSession = session;
+ hyperlinkController = session && session.sessionController.getHyperlinkController();
+ widget.children.forEach(function (element) {
+ element.setAttribute('disabled', !hyperlinkController);
+ });
+ if (editorSession) {
+ editorSession.subscribe(EditorSession.signalCursorMoved, checkHyperlinkButtons);
+ editorSession.subscribe(EditorSession.signalParagraphChanged, checkHyperlinkButtons);
+ editorSession.subscribe(EditorSession.signalParagraphStyleModified, checkHyperlinkButtons);
+ checkHyperlinkButtons();
+ }
+ };
+
+ this.onToolDone = function () {};
+
+ callback(widget);
+ };
+
+ return EditHyperlinks;
+});
diff --git a/js/3rdparty/webodf/editor/widgets/paragraphAlignment.js b/js/3rdparty/webodf/editor/widgets/paragraphAlignment.js
index ae833b04..afc7958f 100644
--- a/js/3rdparty/webodf/editor/widgets/paragraphAlignment.js
+++ b/js/3rdparty/webodf/editor/widgets/paragraphAlignment.js
@@ -50,7 +50,7 @@ define("webodf/editor/widgets/paragraphAlignment", [
var self = this,
editorSession,
widget = {},
- directParagraphStyler,
+ directFormattingController,
justifyLeft,
justifyCenter,
justifyRight,
@@ -65,7 +65,7 @@ define("webodf/editor/widgets/paragraphAlignment", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconJustifyLeft",
onChange: function () {
- directParagraphStyler.alignParagraphLeft();
+ directFormattingController.alignParagraphLeft();
self.onToolDone();
}
});
@@ -77,7 +77,7 @@ define("webodf/editor/widgets/paragraphAlignment", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconJustifyCenter",
onChange: function () {
- directParagraphStyler.alignParagraphCenter();
+ directFormattingController.alignParagraphCenter();
self.onToolDone();
}
});
@@ -89,7 +89,7 @@ define("webodf/editor/widgets/paragraphAlignment", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconJustifyRight",
onChange: function () {
- directParagraphStyler.alignParagraphRight();
+ directFormattingController.alignParagraphRight();
self.onToolDone();
}
});
@@ -101,7 +101,7 @@ define("webodf/editor/widgets/paragraphAlignment", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconJustifyFull",
onChange: function () {
- directParagraphStyler.alignParagraphJustified();
+ directFormattingController.alignParagraphJustified();
self.onToolDone();
}
});
@@ -112,7 +112,7 @@ define("webodf/editor/widgets/paragraphAlignment", [
showLabel: false,
iconClass: "dijitEditorIcon dijitEditorIconOutdent",
onClick: function () {
- directParagraphStyler.outdent();
+ directFormattingController.outdent();
self.onToolDone();
}
});
@@ -123,7 +123,7 @@ define("webodf/editor/widgets/paragraphAlignment", [
showLabel: false,
iconClass: "dijitEditorIcon dijitEditorIconIndent",
onClick: function () {
- directParagraphStyler.indent();
+ directFormattingController.indent();
self.onToolDone();
}
});
@@ -174,21 +174,21 @@ define("webodf/editor/widgets/paragraphAlignment", [
}
this.setEditorSession = function (session) {
- if (directParagraphStyler) {
- directParagraphStyler.unsubscribe(gui.DirectParagraphStyler.paragraphStylingChanged, updateStyleButtons);
+ if (directFormattingController) {
+ directFormattingController.unsubscribe(gui.DirectFormattingController.paragraphStylingChanged, updateStyleButtons);
}
- directParagraphStyler = session && session.sessionController.getDirectParagraphStyler();
- if (directParagraphStyler) {
- directParagraphStyler.subscribe(gui.DirectParagraphStyler.paragraphStylingChanged, updateStyleButtons);
+ directFormattingController = session && session.sessionController.getDirectFormattingController();
+ if (directFormattingController) {
+ directFormattingController.subscribe(gui.DirectFormattingController.paragraphStylingChanged, updateStyleButtons);
}
widget.children.forEach(function (element) {
- element.setAttribute('disabled', !directParagraphStyler);
+ element.setAttribute('disabled', !directFormattingController);
});
updateStyleButtons({
- isAlignedLeft: directParagraphStyler ? directParagraphStyler.isAlignedLeft() : false,
- isAlignedCenter: directParagraphStyler ? directParagraphStyler.isAlignedCenter() : false,
- isAlignedRight: directParagraphStyler ? directParagraphStyler.isAlignedRight() : false,
- isAlignedJustified: directParagraphStyler ? directParagraphStyler.isAlignedJustified() : false
+ isAlignedLeft: directFormattingController ? directFormattingController.isAlignedLeft() : false,
+ isAlignedCenter: directFormattingController ? directFormattingController.isAlignedCenter() : false,
+ isAlignedRight: directFormattingController ? directFormattingController.isAlignedRight() : false,
+ isAlignedJustified: directFormattingController ? directFormattingController.isAlignedJustified() : false
});
if (editorSession) {
diff --git a/js/3rdparty/webodf/editor/widgets/simpleStyles.js b/js/3rdparty/webodf/editor/widgets/simpleStyles.js
index 10a6a107..00595750 100644
--- a/js/3rdparty/webodf/editor/widgets/simpleStyles.js
+++ b/js/3rdparty/webodf/editor/widgets/simpleStyles.js
@@ -51,7 +51,7 @@ define("webodf/editor/widgets/simpleStyles", [
var self = this,
editorSession,
widget = {},
- directTextStyler,
+ directFormattingController,
boldButton,
italicButton,
underlineButton,
@@ -67,7 +67,7 @@ define("webodf/editor/widgets/simpleStyles", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconBold",
onChange: function (checked) {
- directTextStyler.setBold(checked);
+ directFormattingController.setBold(checked);
self.onToolDone();
}
});
@@ -79,7 +79,7 @@ define("webodf/editor/widgets/simpleStyles", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconItalic",
onChange: function (checked) {
- directTextStyler.setItalic(checked);
+ directFormattingController.setItalic(checked);
self.onToolDone();
}
});
@@ -91,7 +91,7 @@ define("webodf/editor/widgets/simpleStyles", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconUnderline",
onChange: function (checked) {
- directTextStyler.setHasUnderline(checked);
+ directFormattingController.setHasUnderline(checked);
self.onToolDone();
}
});
@@ -103,7 +103,7 @@ define("webodf/editor/widgets/simpleStyles", [
checked: false,
iconClass: "dijitEditorIcon dijitEditorIconStrikethrough",
onChange: function (checked) {
- directTextStyler.setHasStrikethrough(checked);
+ directFormattingController.setHasStrikethrough(checked);
self.onToolDone();
}
});
@@ -117,7 +117,7 @@ define("webodf/editor/widgets/simpleStyles", [
constraints: {min:6, max:96},
intermediateChanges: true,
onChange: function (value) {
- directTextStyler.setFontSize(value);
+ directFormattingController.setFontSize(value);
},
onClick: function () {
self.onToolDone();
@@ -134,7 +134,7 @@ define("webodf/editor/widgets/simpleStyles", [
fontPickerWidget = fontPicker.widget();
fontPickerWidget.setAttribute('disabled', true);
fontPickerWidget.onChange = function(value) {
- directTextStyler.setFontName(value);
+ directFormattingController.setFontName(value);
self.onToolDone();
};
@@ -183,24 +183,24 @@ define("webodf/editor/widgets/simpleStyles", [
}
this.setEditorSession = function(session) {
- if (directTextStyler) {
- directTextStyler.unsubscribe(gui.DirectTextStyler.textStylingChanged, updateStyleButtons);
+ if (directFormattingController) {
+ directFormattingController.unsubscribe(gui.DirectFormattingController.textStylingChanged, updateStyleButtons);
}
- directTextStyler = session && session.sessionController.getDirectTextStyler();
+ directFormattingController = session && session.sessionController.getDirectFormattingController();
fontPicker.setEditorSession(session);
- if (directTextStyler) {
- directTextStyler.subscribe(gui.DirectTextStyler.textStylingChanged, updateStyleButtons);
+ if (directFormattingController) {
+ directFormattingController.subscribe(gui.DirectFormattingController.textStylingChanged, updateStyleButtons);
}
widget.children.forEach(function (element) {
- element.setAttribute('disabled', !directTextStyler);
+ element.setAttribute('disabled', !directFormattingController);
});
updateStyleButtons({
- isBold: directTextStyler ? directTextStyler.isBold() : false,
- isItalic: directTextStyler ? directTextStyler.isItalic() : false,
- hasUnderline: directTextStyler ? directTextStyler.hasUnderline() : false,
- hasStrikeThrough: directTextStyler ? directTextStyler.hasStrikeThrough() : false,
- fontSize: directTextStyler ? directTextStyler.fontSize() : undefined,
- fontName: directTextStyler ? directTextStyler.fontName() : undefined
+ isBold: directFormattingController ? directFormattingController.isBold() : false,
+ isItalic: directFormattingController ? directFormattingController.isItalic() : false,
+ hasUnderline: directFormattingController ? directFormattingController.hasUnderline() : false,
+ hasStrikeThrough: directFormattingController ? directFormattingController.hasStrikeThrough() : false,
+ fontSize: directFormattingController ? directFormattingController.fontSize() : undefined,
+ fontName: directFormattingController ? directFormattingController.fontName() : undefined
});
if (editorSession) {
diff --git a/js/3rdparty/webodf/editor/widgets/undoRedoMenu.js b/js/3rdparty/webodf/editor/widgets/undoRedoMenu.js
index cf1a57cd..e266615e 100644
--- a/js/3rdparty/webodf/editor/widgets/undoRedoMenu.js
+++ b/js/3rdparty/webodf/editor/widgets/undoRedoMenu.js
@@ -39,61 +39,57 @@
/*global define,require*/
define("webodf/editor/widgets/undoRedoMenu",
- ["webodf/editor/EditorSession"],
+ ["webodf/editor/EditorSession", "dijit/form/Button"],
- function (EditorSession) {
+ function (EditorSession, Button) {
"use strict";
return function UndoRedoMenu(callback) {
- var editorSession,
+ var self = this,
+ editorSession,
undoButton,
- redoButton;
+ redoButton,
+ widget = {};
- function makeWidget(callback) {
- require(["dijit/form/Button"], function (Button) {
- var widget = {};
-
- undoButton = new Button({
- label: runtime.tr('Undo'),
- showLabel: false,
- disabled: true, // TODO: get current session state
- iconClass: "dijitEditorIcon dijitEditorIconUndo",
- onClick: function () {
- if (editorSession) {
- editorSession.undo();
- }
- }
- });
-
- redoButton = new Button({
- label: runtime.tr('Redo'),
- showLabel: false,
- disabled: true, // TODO: get current session state
- iconClass: "dijitEditorIcon dijitEditorIconRedo",
- onClick: function () {
- if (editorSession) {
- editorSession.redo();
- }
- }
- });
+ undoButton = new Button({
+ label: runtime.tr('Undo'),
+ showLabel: false,
+ disabled: true, // TODO: get current session state
+ iconClass: "dijitEditorIcon dijitEditorIconUndo",
+ onClick: function () {
+ if (editorSession) {
+ editorSession.undo();
+ self.onToolDone();
+ }
+ }
+ });
- widget.children = [undoButton, redoButton];
- widget.startup = function () {
- widget.children.forEach(function (element) {
- element.startup();
- });
- };
+ redoButton = new Button({
+ label: runtime.tr('Redo'),
+ showLabel: false,
+ disabled: true, // TODO: get current session state
+ iconClass: "dijitEditorIcon dijitEditorIconRedo",
+ onClick: function () {
+ if (editorSession) {
+ editorSession.redo();
+ self.onToolDone();
+ }
+ }
+ });
- widget.placeAt = function (container) {
- widget.children.forEach(function (element) {
- element.placeAt(container);
- });
- return widget;
- };
+ widget.children = [undoButton, redoButton];
+ widget.startup = function () {
+ widget.children.forEach(function (element) {
+ element.startup();
+ });
+ };
- return callback(widget);
+ widget.placeAt = function (container) {
+ widget.children.forEach(function (element) {
+ element.placeAt(container);
});
- }
+ return widget;
+ };
function checkUndoButtons(e) {
if (undoButton) {
@@ -115,9 +111,9 @@ define("webodf/editor/widgets/undoRedoMenu",
}
};
+ this.onToolDone = function () {};
+
// init
- makeWidget(function (widget) {
- return callback(widget);
- });
+ callback(widget);
};
});
diff --git a/js/3rdparty/webodf/editor/widgets/zoomSlider.js b/js/3rdparty/webodf/editor/widgets/zoomSlider.js
index b445211e..a5e1e370 100644
--- a/js/3rdparty/webodf/editor/widgets/zoomSlider.js
+++ b/js/3rdparty/webodf/editor/widgets/zoomSlider.js
@@ -38,24 +38,29 @@
/*global define,require*/
-define("webodf/editor/widgets/zoomSlider", [], function () {
+define("webodf/editor/widgets/zoomSlider", [
+ "webodf/editor/EditorSession"],
+ function (EditorSession) {
"use strict";
return function ZoomSlider(callback) {
var self = this,
editorSession,
- slider;
+ slider,
+ extremeZoomFactor = 4;
+ // The slider zooms from -1 to +1, which corresponds
+ // to zoom levels of 1/extremeZoomFactor to extremeZoomFactor.
function makeWidget(callback) {
require(["dijit/form/HorizontalSlider", "dijit/form/NumberTextBox", "dojo"], function (HorizontalSlider, NumberTextBox, dojo) {
var widget = {};
slider = new HorizontalSlider({
name: 'zoomSlider',
- value: 100,
- minimum: 30,
- maximum: 150,
- discreteValues: 100,
+ value: 0,
+ minimum: -1,
+ maximum: 1,
+ discreteValues: 0.01,
intermediateChanges: true,
style: {
width: '150px',
@@ -66,7 +71,7 @@ define("webodf/editor/widgets/zoomSlider", [], function () {
slider.onChange = function (value) {
if (editorSession) {
- editorSession.getOdfCanvas().setZoomLevel(value / 100.0);
+ editorSession.getOdfCanvas().getZoomHelper().setZoomLevel(Math.pow(extremeZoomFactor, value));
}
self.onToolDone();
};
@@ -75,9 +80,23 @@ define("webodf/editor/widgets/zoomSlider", [], function () {
});
}
+ function updateSlider(zoomLevel) {
+ if (slider) {
+ slider.set('value', Math.log(zoomLevel) / Math.log(extremeZoomFactor), false);
+ }
+ }
+
this.setEditorSession = function(session) {
+ var zoomHelper;
+ if (editorSession) {
+ editorSession.getOdfCanvas().getZoomHelper().unsubscribe(gui.ZoomHelper.signalZoomChanged, updateSlider);
+ }
editorSession = session;
-// if (slider) { slider.setValue(editorSession.getOdfCanvas().getZoomLevel() ); TODO!
+ if (editorSession) {
+ zoomHelper = editorSession.getOdfCanvas().getZoomHelper();
+ zoomHelper.subscribe(gui.ZoomHelper.signalZoomChanged, updateSlider);
+ updateSlider(zoomHelper.getZoomLevel());
+ }
};
this.onToolDone = function () {};
diff --git a/js/3rdparty/webodf/webodf-debug.js b/js/3rdparty/webodf/webodf-debug.js
index 4bb2eff2..fcebfe47 100644
--- a/js/3rdparty/webodf/webodf-debug.js
+++ b/js/3rdparty/webodf/webodf-debug.js
@@ -1,4 +1,4 @@
-var webodf_version = "0.4.2-1579-gfc3a4e6";
+var webodf_version = "0.4.2-2010-ge06842f";
function Runtime() {
}
Runtime.prototype.getVariable = function(name) {
@@ -49,6 +49,10 @@ Runtime.prototype.exit = function(exitCode) {
};
Runtime.prototype.getWindow = function() {
};
+Runtime.prototype.requestAnimationFrame = function(callback) {
+};
+Runtime.prototype.cancelAnimationFrame = function(requestId) {
+};
Runtime.prototype.assert = function(condition, message, callback) {
};
var IS_COMPILED_CODE = true;
@@ -128,14 +132,29 @@ Runtime.getFunctionName = function getFunctionName(f) {
};
function BrowserRuntime(logoutput) {
var self = this, cache = {};
- function utf8ByteArrayFromString(string) {
- var l = string.length, bytearray, i, n, j = 0;
+ function getUtf8LengthForString(string) {
+ var l = string.length, i, n, j = 0;
for(i = 0;i < l;i += 1) {
n = string.charCodeAt(i);
- j += 1 + (n > 128) + (n > 2048)
+ j += 1 + (n > 128) + (n > 2048);
+ if(n > 55040 && n < 57344) {
+ j += 1;
+ i += 1
+ }
+ }
+ return j
+ }
+ function utf8ByteArrayFromString(string, length, addBOM) {
+ var l = string.length, bytearray, i, n, j;
+ bytearray = new Uint8Array(new ArrayBuffer(length));
+ if(addBOM) {
+ bytearray[0] = 239;
+ bytearray[1] = 187;
+ bytearray[2] = 191;
+ j = 3
+ }else {
+ j = 0
}
- bytearray = new Uint8Array(new ArrayBuffer(j));
- j = 0;
for(i = 0;i < l;i += 1) {
n = string.charCodeAt(i);
if(n < 128) {
@@ -147,15 +166,36 @@ function BrowserRuntime(logoutput) {
bytearray[j + 1] = 128 | n & 63;
j += 2
}else {
- bytearray[j] = 224 | n >>> 12 & 15;
- bytearray[j + 1] = 128 | n >>> 6 & 63;
- bytearray[j + 2] = 128 | n & 63;
- j += 3
+ if(n <= 55040 || n >= 57344) {
+ bytearray[j] = 224 | n >>> 12 & 15;
+ bytearray[j + 1] = 128 | n >>> 6 & 63;
+ bytearray[j + 2] = 128 | n & 63;
+ j += 3
+ }else {
+ i += 1;
+ n = (n - 55296 << 10 | string.charCodeAt(i) - 56320) + 65536;
+ bytearray[j] = 240 | n >>> 18 & 7;
+ bytearray[j + 1] = 128 | n >>> 12 & 63;
+ bytearray[j + 2] = 128 | n >>> 6 & 63;
+ bytearray[j + 3] = 128 | n & 63;
+ j += 4
+ }
}
}
}
return bytearray
}
+ function utf8ByteArrayFromXHRString(string, wishLength) {
+ var addBOM = false, length = getUtf8LengthForString(string);
+ if(typeof wishLength === "number") {
+ if(wishLength !== length && wishLength !== length + 3) {
+ return undefined
+ }
+ addBOM = length + 3 === wishLength;
+ length = wishLength
+ }
+ return utf8ByteArrayFromString(string, length, addBOM)
+ }
function byteArrayFromString(string) {
var l = string.length, a = new Uint8Array(new ArrayBuffer(l)), i;
for(i = 0;i < l;i += 1) {
@@ -166,7 +206,7 @@ function BrowserRuntime(logoutput) {
this.byteArrayFromString = function(string, encoding) {
var result;
if(encoding === "utf8") {
- result = utf8ByteArrayFromString(string)
+ result = utf8ByteArrayFromString(string, getUtf8LengthForString(string), false)
}else {
if(encoding !== "binary") {
self.log("unknown encoding: " + encoding)
@@ -228,8 +268,22 @@ function BrowserRuntime(logoutput) {
}
return a
}
+ function stringToBinaryWorkaround(xhr) {
+ var cl, data;
+ cl = xhr.getResponseHeader("Content-Length");
+ if(cl) {
+ cl = parseInt(cl, 10)
+ }
+ if(cl && cl !== xhr.responseText.length) {
+ data = utf8ByteArrayFromXHRString(xhr.responseText, cl)
+ }
+ if(data === undefined) {
+ data = byteArrayFromString(xhr.responseText)
+ }
+ return data
+ }
function handleXHRResult(path, encoding, xhr) {
- var data, r, d, a;
+ var r, d, a, data;
if(xhr.status === 0 && !xhr.responseText) {
r = {err:"File " + path + " is empty.", data:null}
}else {
@@ -247,7 +301,7 @@ function BrowserRuntime(logoutput) {
a = (new VBArray(xhr.responseBody)).toArray();
data = arrayToUint8Array(a)
}else {
- data = self.byteArrayFromString(xhr.responseText, "binary")
+ data = stringToBinaryWorkaround(xhr)
}
}else {
data = xhr.responseText
@@ -468,6 +522,25 @@ function BrowserRuntime(logoutput) {
};
this.getWindow = function() {
return window
+ };
+ this.requestAnimationFrame = function(callback) {
+ var rAF = window.requestAnimationFrame || (window.webkitRequestAnimationFrame || (window.mozRequestAnimationFrame || window.msRequestAnimationFrame)), requestId = 0;
+ if(rAF) {
+ rAF.bind(window);
+ requestId = (rAF)(callback)
+ }else {
+ return setTimeout(callback, 15)
+ }
+ return requestId
+ };
+ this.cancelAnimationFrame = function(requestId) {
+ var cAF = window.cancelAnimationFrame || (window.webkitCancelAnimationFrame || (window.mozCancelAnimationFrame || window.msCancelAnimationFrame));
+ if(cAF) {
+ cAF.bind(window);
+ (cAF)(requestId)
+ }else {
+ clearTimeout(requestId)
+ }
}
}
function NodeJSRuntime() {
@@ -637,6 +710,12 @@ function NodeJSRuntime() {
this.getWindow = function() {
return null
};
+ this.requestAnimationFrame = function(callback) {
+ return setTimeout(callback, 15)
+ };
+ this.cancelAnimationFrame = function(requestId) {
+ clearTimeout(requestId)
+ };
function init() {
var DOMParser = require("xmldom").DOMParser;
parser = new DOMParser;
@@ -821,6 +900,12 @@ function RhinoRuntime() {
this.exit = quit;
this.getWindow = function() {
return null
+ };
+ this.requestAnimationFrame = function(callback) {
+ callback();
+ return 0
+ };
+ this.cancelAnimationFrame = function() {
}
}
Runtime.create = function create() {
@@ -843,162 +928,124 @@ var xmldom = {};
var odf = {};
var ops = {};
(function() {
- var dependencies = {}, loadedFiles = {};
- function loadManifest(dir, manifests) {
+ function loadDependenciesFromManifest(dir, dependencies, expectFail) {
var path = dir + "/manifest.json", content, list, manifest, m;
- if(loadedFiles.hasOwnProperty(path)) {
- return
- }
- loadedFiles[path] = 1;
+ runtime.log("Loading manifest: " + path);
try {
content = runtime.readFileSync(path, "utf-8")
}catch(e) {
- console.log(String(e));
+ if(expectFail) {
+ runtime.log("No loadable manifest found.")
+ }else {
+ console.log(String(e));
+ throw e;
+ }
return
}
list = JSON.parse((content));
manifest = (list);
for(m in manifest) {
if(manifest.hasOwnProperty(m)) {
- manifests[m] = {dir:dir, deps:manifest[m]}
+ dependencies[m] = {dir:dir, deps:manifest[m]}
}
}
}
- function expandPathDependencies(path, manifests, allDeps) {
- var d = manifests[path].deps, deps = {};
- allDeps[path] = deps;
- d.forEach(function(dp) {
- deps[dp] = 1
- });
- d.forEach(function(dp) {
- if(!allDeps[dp]) {
- expandPathDependencies(dp, manifests, allDeps)
- }
- });
- d.forEach(function(dp) {
- Object.keys(allDeps[dp]).forEach(function(k) {
- deps[k] = 1
- })
- })
- }
- function sortDeps(deps, allDeps) {
- var i, sorted = [];
- function add(path, stack) {
- var j, d = allDeps[path];
- if(sorted.indexOf(path) === -1 && stack.indexOf(path) === -1) {
- stack.push(path);
- for(j = 0;j < deps.length;j += 1) {
- if(d[deps[j]]) {
- add(deps[j], stack)
- }
- }
- stack.pop();
- sorted.push(path)
- }
+ function loadDependenciesFromManifests() {
+ var dependencies = [], paths = runtime.libraryPaths(), i;
+ if(runtime.currentDirectory() && paths.indexOf(runtime.currentDirectory()) === -1) {
+ loadDependenciesFromManifest(runtime.currentDirectory(), dependencies, true)
}
- for(i = 0;i < deps.length;i += 1) {
- add(deps[i], [])
+ for(i = 0;i < paths.length;i += 1) {
+ loadDependenciesFromManifest(paths[i], dependencies)
}
- return sorted
+ return dependencies
+ }
+ function getPath(dir, className) {
+ return dir + "/" + className.replace(".", "/") + ".js"
}
- function expandDependencies(manifests) {
- var path, deps, allDeps = {};
- for(path in manifests) {
- if(manifests.hasOwnProperty(path)) {
- expandPathDependencies(path, manifests, allDeps)
+ function getLoadList(classNames, dependencies, isDefined) {
+ var loadList = [], stack = {}, visited = {};
+ function visit(n) {
+ if(visited[n] || isDefined(n)) {
+ return
}
- }
- for(path in manifests) {
- if(manifests.hasOwnProperty(path)) {
- deps = (Object.keys(allDeps[path]));
- manifests[path].deps = sortDeps(deps, allDeps);
- manifests[path].deps.push(path)
+ if(stack[n]) {
+ throw"Circular dependency detected for " + n + ".";
+ }
+ stack[n] = true;
+ if(!dependencies[n]) {
+ throw"Missing dependency information for class " + n + ".";
}
+ var d = dependencies[n], deps = d.deps, i, l = deps.length;
+ for(i = 0;i < l;i += 1) {
+ visit(deps[i])
+ }
+ stack[n] = false;
+ visited[n] = true;
+ loadList.push(getPath(d.dir, n))
}
- dependencies = manifests
+ classNames.forEach(visit);
+ return loadList
}
- function loadManifests() {
- if(Object.keys(dependencies).length > 0) {
- return
- }
- var paths = runtime.libraryPaths(), manifests = {}, i;
- if(runtime.currentDirectory()) {
- loadManifest(runtime.currentDirectory(), manifests)
- }
+ function addContent(path, content) {
+ content += "\n//# sourceURL=" + path;
+ content += "\n//@ sourceURL=" + path;
+ return content
+ }
+ function loadFiles(paths) {
+ var i, content;
for(i = 0;i < paths.length;i += 1) {
- loadManifest(paths[i], manifests)
+ content = runtime.readFileSync(paths[i], "utf-8");
+ content = addContent(paths[i], (content));
+ eval(content)
}
- expandDependencies(manifests)
- }
- function classPath(classname) {
- return classname.replace(".", "/") + ".js"
}
- function getDependencies(classname) {
- var classpath = classPath(classname), deps = [], d = dependencies[classpath].deps, i;
- for(i = 0;i < d.length;i += 1) {
- if(!loadedFiles.hasOwnProperty(d[i])) {
- deps.push(d[i])
- }
+ function loadFilesInBrowser(paths, callback) {
+ var e = document.currentScript || document.documentElement.lastChild, df = document.createDocumentFragment(), script, i;
+ for(i = 0;i < paths.length;i += 1) {
+ script = document.createElement("script");
+ script.type = "text/javascript";
+ script.charset = "utf-8";
+ script.async = false;
+ script.setAttribute("src", paths[i]);
+ df.appendChild(script)
}
- return deps
+ if(callback) {
+ script.onload = callback
+ }
+ e.parentNode.insertBefore(df, e)
}
- function evalArray(paths, contents) {
- var i = 0;
- while(i < paths.length && contents[i] !== undefined) {
- if(contents[i] !== null) {
- eval((contents[i]));
- contents[i] = null
+ var dependencies, packages = {core:core, gui:gui, xmldom:xmldom, odf:odf, ops:ops};
+ function isDefined(classname) {
+ var parts = classname.split("."), i, p = packages, l = parts.length;
+ for(i = 0;i < l;i += 1) {
+ if(!p.hasOwnProperty(parts[i])) {
+ return false
}
- i += 1
+ p = (p[parts[i]])
}
+ return true
}
- function loadFiles(paths) {
- var contents = [], i, p, c, async = false;
- contents.length = paths.length;
- function addContent(pos, path, content) {
- content += "\n//# sourceURL=" + path;
- content += "\n//@ sourceURL=" + path;
- contents[pos] = content
- }
- function loadFile(pos) {
- var path = dependencies[paths[pos]].dir + "/" + paths[pos];
- runtime.readFile(path, "utf8", function(err, content) {
- if(err) {
- throw err;
- }
- if(contents[pos] === undefined) {
- addContent(pos, path, (content))
- }
- })
+ runtime.loadClasses = function(classnames, callback) {
+ if(IS_COMPILED_CODE || classnames.length === 0) {
+ return callback && callback()
}
- if(async) {
- for(i = 0;i < paths.length;i += 1) {
- loadedFiles[paths[i]] = 1;
- loadFile(i)
- }
+ dependencies = dependencies || loadDependenciesFromManifests();
+ classnames = getLoadList(classnames, dependencies, isDefined);
+ if(classnames.length === 0) {
+ return callback && callback()
}
- for(i = paths.length - 1;i >= 0;i -= 1) {
- loadedFiles[paths[i]] = 1;
- if(contents[i] === undefined) {
- p = paths[i];
- p = dependencies[p].dir + "/" + p;
- c = runtime.readFileSync(p, "utf-8");
- addContent(i, p, (c))
+ if(runtime.type() === "BrowserRuntime" && callback) {
+ loadFilesInBrowser(classnames, callback)
+ }else {
+ loadFiles(classnames);
+ if(callback) {
+ callback()
}
}
- evalArray(paths, contents)
- }
- runtime.loadClass = function(classname) {
- if(IS_COMPILED_CODE) {
- return
- }
- var classpath = classPath(classname), paths;
- if(loadedFiles.hasOwnProperty(classpath)) {
- return
- }
- loadManifests();
- paths = getDependencies(classname);
- loadFiles(paths)
+ };
+ runtime.loadClass = function(classname, callback) {
+ runtime.loadClasses([classname], callback)
}
})();
(function() {
@@ -1032,9 +1079,11 @@ var ops = {};
}
var script = argv[0];
runtime.readFile(script, "utf8", function(err, code) {
- var path = "", codestring = (code);
- if(script.indexOf("/") !== -1) {
- path = script.substring(0, script.indexOf("/"))
+ var path = "", pathEndIndex = script.lastIndexOf("/"), codestring = (code);
+ if(pathEndIndex !== -1) {
+ path = script.substring(0, pathEndIndex)
+ }else {
+ path = "."
}
runtime.setCurrentDirectory(path);
function inner_run() {
@@ -1451,11 +1500,13 @@ core.CSSUnits = function CSSUnits() {
(function() {
var browserQuirks;
function getBrowserQuirks() {
- var range, directBoundingRect, rangeBoundingRect, testContainer, testElement, detectedQuirks, window, document;
+ var range, directBoundingRect, rangeBoundingRect, testContainer, testElement, detectedQuirks, window, document, docElement, body, docOverflow, bodyOverflow, bodyHeight, bodyScroll;
if(browserQuirks === undefined) {
window = runtime.getWindow();
document = window && window.document;
- browserQuirks = {rangeBCRIgnoresElementBCR:false, unscaledRangeClientRects:false};
+ docElement = document.documentElement;
+ body = document.body;
+ browserQuirks = {rangeBCRIgnoresElementBCR:false, unscaledRangeClientRects:false, elementBCRIgnoresBodyScroll:false};
if(document) {
testContainer = document.createElement("div");
testContainer.style.position = "absolute";
@@ -1464,7 +1515,7 @@ core.CSSUnits = function CSSUnits() {
testContainer.style["-webkit-transform"] = "scale(2)";
testElement = document.createElement("div");
testContainer.appendChild(testElement);
- document.body.appendChild(testContainer);
+ body.appendChild(testContainer);
range = document.createRange();
range.selectNode(testElement);
browserQuirks.rangeBCRIgnoresElementBCR = range.getClientRects().length === 0;
@@ -1472,8 +1523,23 @@ core.CSSUnits = function CSSUnits() {
directBoundingRect = testElement.getBoundingClientRect();
rangeBoundingRect = range.getBoundingClientRect();
browserQuirks.unscaledRangeClientRects = Math.abs(directBoundingRect.height - rangeBoundingRect.height) > 2;
+ testContainer.style.transform = "";
+ testContainer.style["-webkit-transform"] = "";
+ docOverflow = docElement.style.overflow;
+ bodyOverflow = body.style.overflow;
+ bodyHeight = body.style.height;
+ bodyScroll = body.scrollTop;
+ docElement.style.overflow = "visible";
+ body.style.overflow = "visible";
+ body.style.height = "200%";
+ body.scrollTop = body.scrollHeight;
+ browserQuirks.elementBCRIgnoresBodyScroll = range.getBoundingClientRect().top !== testElement.getBoundingClientRect().top;
+ body.scrollTop = bodyScroll;
+ body.style.height = bodyHeight;
+ body.style.overflow = bodyOverflow;
+ docElement.style.overflow = docOverflow;
range.detach();
- document.body.removeChild(testContainer);
+ body.removeChild(testContainer);
detectedQuirks = Object.keys(browserQuirks).map(function(quirk) {
return quirk + ":" + String(browserQuirks[quirk])
}).join(", ");
@@ -1509,10 +1575,28 @@ core.CSSUnits = function CSSUnits() {
}
return{container:c, offset:offset}
}
+ function getPositionInContainingNode(node, container) {
+ var offset = 0, n;
+ while(node.parentNode !== container) {
+ runtime.assert(node.parentNode !== null, "parent is null");
+ node = (node.parentNode)
+ }
+ n = container.firstChild;
+ while(n !== node) {
+ offset += 1;
+ n = n.nextSibling
+ }
+ return offset
+ }
function splitBoundaries(range) {
- var modifiedNodes = [], end, splitStart, node, text;
+ var modifiedNodes = [], originalEndContainer, resetToContainerLength, end, splitStart, node, text, offset;
if(range.startContainer.nodeType === Node.TEXT_NODE || range.endContainer.nodeType === Node.TEXT_NODE) {
- end = range.endContainer && findStablePoint(range.endContainer, range.endOffset);
+ originalEndContainer = range.endContainer;
+ resetToContainerLength = range.endContainer.nodeType !== Node.TEXT_NODE ? range.endOffset === range.endContainer.childNodes.length : false;
+ end = findStablePoint(range.endContainer, range.endOffset);
+ if(end.container === originalEndContainer) {
+ originalEndContainer = null
+ }
range.setEnd(end.container, end.offset);
node = range.endContainer;
if(range.endOffset !== 0 && node.nodeType === Node.TEXT_NODE) {
@@ -1532,6 +1616,18 @@ core.CSSUnits = function CSSUnits() {
range.setStart(splitStart, 0)
}
}
+ if(originalEndContainer !== null) {
+ node = range.endContainer;
+ while(node.parentNode && node.parentNode !== originalEndContainer) {
+ node = node.parentNode
+ }
+ if(resetToContainerLength) {
+ offset = originalEndContainer.childNodes.length
+ }else {
+ offset = getPositionInContainingNode(node, originalEndContainer)
+ }
+ range.setEnd(originalEndContainer, offset)
+ }
}
return modifiedNodes
}
@@ -1544,26 +1640,43 @@ core.CSSUnits = function CSSUnits() {
return range1.compareBoundaryPoints(Range.END_TO_START, range2) <= 0 && range1.compareBoundaryPoints(Range.START_TO_END, range2) >= 0
}
this.rangesIntersect = rangesIntersect;
- function getNodesInRange(range, nodeFilter) {
- var document = range.startContainer.ownerDocument, elements = [], rangeRoot = range.commonAncestorContainer, root = (rangeRoot.nodeType === Node.TEXT_NODE ? rangeRoot.parentNode : rangeRoot), n, filterResult, treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ALL, nodeFilter, false);
- treeWalker.currentNode = range.startContainer;
- n = range.startContainer;
- while(n) {
- filterResult = nodeFilter(n);
- if(filterResult === NodeFilter.FILTER_ACCEPT) {
- elements.push(n)
+ function maximumOffset(node) {
+ return node.nodeType === Node.TEXT_NODE ? (node).length : node.childNodes.length
+ }
+ function getNodesInRange(range, nodeFilter, whatToShow) {
+ var document = range.startContainer.ownerDocument, elements = [], rangeRoot = range.commonAncestorContainer, root = (rangeRoot.nodeType === Node.TEXT_NODE ? rangeRoot.parentNode : rangeRoot), treeWalker = document.createTreeWalker(root, whatToShow, nodeFilter, false), currentNode, lastNodeInRange, endNodeCompareFlags, comparePositionResult;
+ if(range.endContainer.childNodes[range.endOffset - 1]) {
+ lastNodeInRange = (range.endContainer.childNodes[range.endOffset - 1]);
+ endNodeCompareFlags = Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_POSITION_CONTAINED_BY
+ }else {
+ lastNodeInRange = (range.endContainer);
+ endNodeCompareFlags = Node.DOCUMENT_POSITION_PRECEDING
+ }
+ if(range.startContainer.childNodes[range.startOffset]) {
+ currentNode = (range.startContainer.childNodes[range.startOffset]);
+ treeWalker.currentNode = currentNode
+ }else {
+ if(range.startOffset === maximumOffset(range.startContainer)) {
+ currentNode = (range.startContainer);
+ treeWalker.currentNode = currentNode;
+ treeWalker.lastChild();
+ currentNode = treeWalker.nextNode()
}else {
- if(filterResult === NodeFilter.FILTER_REJECT) {
- break
- }
+ currentNode = (range.startContainer);
+ treeWalker.currentNode = currentNode
}
- n = n.parentNode
}
- elements.reverse();
- n = treeWalker.nextNode();
- while(n) {
- elements.push(n);
- n = treeWalker.nextNode()
+ if(currentNode && nodeFilter(currentNode) === NodeFilter.FILTER_ACCEPT) {
+ elements.push(currentNode)
+ }
+ currentNode = treeWalker.nextNode();
+ while(currentNode) {
+ comparePositionResult = lastNodeInRange.compareDocumentPosition(currentNode);
+ if(comparePositionResult !== 0 && (comparePositionResult & endNodeCompareFlags) === 0) {
+ break
+ }
+ elements.push(currentNode);
+ currentNode = treeWalker.nextNode()
}
return elements
}
@@ -1624,8 +1737,8 @@ core.CSSUnits = function CSSUnits() {
removeUnwantedNodes(node, shouldRemove);
node = next
}
- if(shouldRemove(targetNode)) {
- parent = mergeIntoParent(targetNode)
+ if(parent && shouldRemove(targetNode)) {
+ mergeIntoParent(targetNode)
}
return parent
}
@@ -1640,14 +1753,6 @@ core.CSSUnits = function CSSUnits() {
return e
}
this.getElementsByTagNameNS = getElementsByTagNameNS;
- function rangeIntersectsNode(range, node) {
- var nodeRange = node.ownerDocument.createRange(), result;
- nodeRange.selectNodeContents(node);
- result = rangesIntersect(range, nodeRange);
- nodeRange.detach();
- return result
- }
- this.rangeIntersectsNode = rangeIntersectsNode;
function containsNode(parent, descendant) {
return parent === descendant || (parent).contains((descendant))
}
@@ -1655,19 +1760,6 @@ core.CSSUnits = function CSSUnits() {
function containsNodeForBrokenWebKit(parent, descendant) {
return parent === descendant || Boolean(parent.compareDocumentPosition(descendant) & Node.DOCUMENT_POSITION_CONTAINED_BY)
}
- function getPositionInContainingNode(node, container) {
- var offset = 0, n;
- while(node.parentNode !== container) {
- runtime.assert(node.parentNode !== null, "parent is null");
- node = (node.parentNode)
- }
- n = container.firstChild;
- while(n !== node) {
- offset += 1;
- n = n.nextSibling
- }
- return offset
- }
function comparePoints(c1, o1, c2, o2) {
if(c1 === c2) {
return o2 - o1
@@ -1699,11 +1791,15 @@ core.CSSUnits = function CSSUnits() {
}
this.adaptRangeDifferenceToZoomLevel = adaptRangeDifferenceToZoomLevel;
function getBoundingClientRect(node) {
- var doc = (node.ownerDocument), quirks = getBrowserQuirks(), range, element;
+ var doc = (node.ownerDocument), quirks = getBrowserQuirks(), range, element, rect, body = doc.body;
if(quirks.unscaledRangeClientRects === false || quirks.rangeBCRIgnoresElementBCR) {
if(node.nodeType === Node.ELEMENT_NODE) {
element = (node);
- return element.getBoundingClientRect()
+ rect = element.getBoundingClientRect();
+ if(quirks.elementBCRIgnoresBodyScroll) {
+ return({left:rect.left + body.scrollLeft, right:rect.right + body.scrollLeft, top:rect.top + body.scrollTop, bottom:rect.bottom + body.scrollTop})
+ }
+ return rect
}
}
range = getSharedRange(doc);
@@ -1757,17 +1853,20 @@ core.CSSUnits = function CSSUnits() {
this.getKeyValRepresentationOfNode = getKeyValRepresentationOfNode;
function mapObjOntoNode(node, properties, nsResolver) {
Object.keys(properties).forEach(function(key) {
- var parts = key.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), value = properties[key], element;
- if(typeof value === "object" && Object.keys((value)).length) {
- if(ns) {
- element = (node.getElementsByTagNameNS(ns, localName)[0]) || node.ownerDocument.createElementNS(ns, key)
- }else {
- element = (node.getElementsByTagName(localName)[0]) || node.ownerDocument.createElement(key)
+ var parts = key.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), value = properties[key], valueType = typeof value, element;
+ if(valueType === "object") {
+ if(Object.keys((value)).length) {
+ if(ns) {
+ element = (node.getElementsByTagNameNS(ns, localName)[0]) || node.ownerDocument.createElementNS(ns, key)
+ }else {
+ element = (node.getElementsByTagName(localName)[0]) || node.ownerDocument.createElement(key)
+ }
+ node.appendChild(element);
+ mapObjOntoNode(element, (value), nsResolver)
}
- node.appendChild(element);
- mapObjOntoNode(element, (value), nsResolver)
}else {
if(ns) {
+ runtime.assert(valueType === "number" || valueType === "string", "attempting to map unsupported type '" + valueType + "' (key: " + key + ")");
node.setAttributeNS(ns, key, String(value))
}
}
@@ -1790,6 +1889,139 @@ core.CSSUnits = function CSSUnits() {
};
return core.DomUtils
})();
+core.Cursor = function Cursor(document, memberId) {
+ var cursorns = "urn:webodf:names:cursor", cursorNode = document.createElementNS(cursorns, "cursor"), anchorNode = document.createElementNS(cursorns, "anchor"), forwardSelection, recentlyModifiedNodes = [], selectedRange = (document.createRange()), isCollapsed, domUtils = new core.DomUtils;
+ function putIntoTextNode(node, container, offset) {
+ runtime.assert(Boolean(container), "putCursorIntoTextNode: invalid container");
+ var parent = container.parentNode;
+ runtime.assert(Boolean(parent), "putCursorIntoTextNode: container without parent");
+ runtime.assert(offset >= 0 && offset <= container.length, "putCursorIntoTextNode: offset is out of bounds");
+ if(offset === 0) {
+ parent.insertBefore(node, container)
+ }else {
+ if(offset === container.length) {
+ parent.insertBefore(node, container.nextSibling)
+ }else {
+ container.splitText(offset);
+ parent.insertBefore(node, container.nextSibling)
+ }
+ }
+ }
+ function removeNode(node) {
+ if(node.parentNode) {
+ recentlyModifiedNodes.push(node.previousSibling);
+ recentlyModifiedNodes.push(node.nextSibling);
+ node.parentNode.removeChild(node)
+ }
+ }
+ function putNode(node, container, offset) {
+ if(container.nodeType === Node.TEXT_NODE) {
+ putIntoTextNode(node, (container), offset)
+ }else {
+ if(container.nodeType === Node.ELEMENT_NODE) {
+ container.insertBefore(node, container.childNodes.item(offset))
+ }
+ }
+ recentlyModifiedNodes.push(node.previousSibling);
+ recentlyModifiedNodes.push(node.nextSibling)
+ }
+ function getStartNode() {
+ return forwardSelection ? anchorNode : cursorNode
+ }
+ function getEndNode() {
+ return forwardSelection ? cursorNode : anchorNode
+ }
+ this.getNode = function() {
+ return cursorNode
+ };
+ this.getAnchorNode = function() {
+ return anchorNode.parentNode ? anchorNode : cursorNode
+ };
+ this.getSelectedRange = function() {
+ if(isCollapsed) {
+ selectedRange.setStartBefore(cursorNode);
+ selectedRange.collapse(true)
+ }else {
+ selectedRange.setStartAfter(getStartNode());
+ selectedRange.setEndBefore(getEndNode())
+ }
+ return selectedRange
+ };
+ this.setSelectedRange = function(range, isForwardSelection) {
+ if(selectedRange && selectedRange !== range) {
+ selectedRange.detach()
+ }
+ selectedRange = range;
+ forwardSelection = isForwardSelection !== false;
+ isCollapsed = range.collapsed;
+ if(range.collapsed) {
+ removeNode(anchorNode);
+ removeNode(cursorNode);
+ putNode(cursorNode, (range.startContainer), range.startOffset)
+ }else {
+ removeNode(anchorNode);
+ removeNode(cursorNode);
+ putNode(getEndNode(), (range.endContainer), range.endOffset);
+ putNode(getStartNode(), (range.startContainer), range.startOffset)
+ }
+ recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
+ recentlyModifiedNodes.length = 0
+ };
+ this.hasForwardSelection = function() {
+ return forwardSelection
+ };
+ this.remove = function() {
+ removeNode(cursorNode);
+ recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
+ recentlyModifiedNodes.length = 0
+ };
+ function init() {
+ cursorNode.setAttributeNS(cursorns, "memberId", memberId);
+ anchorNode.setAttributeNS(cursorns, "memberId", memberId)
+ }
+ init()
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+core.Destroyable = function Destroyable() {
+};
+core.Destroyable.prototype.destroy = function(callback) {
+};
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -1839,8 +2071,7 @@ core.EventNotifier = function EventNotifier(eventIds) {
};
this.subscribe = function(eventId, cb) {
runtime.assert(eventListener.hasOwnProperty(eventId), 'tried to subscribe to unknown event "' + eventId + '"');
- eventListener[eventId].push(cb);
- runtime.log('event "' + eventId + '" subscribed.')
+ eventListener[eventId].push(cb)
};
this.unsubscribe = function(eventId, cb) {
var cbIndex;
@@ -1850,7 +2081,6 @@ core.EventNotifier = function EventNotifier(eventIds) {
if(cbIndex !== -1) {
eventListener[eventId].splice(cbIndex, 1)
}
- runtime.log('event "' + eventId + '" unsubscribed.')
};
function init() {
var i, eventId;
@@ -2076,9 +2306,43 @@ core.PositionIterator = function PositionIterator(root, whatToShow, filter, expa
walker.currentNode = currentNode;
return sibling
};
+ function moveToAcceptedNode() {
+ var node = walker.currentNode, filterResult, moveResult;
+ filterResult = nodeFilter(node);
+ if(node !== root) {
+ node = node.parentNode;
+ while(node && node !== root) {
+ if(nodeFilter(node) === FILTER_REJECT) {
+ walker.currentNode = node;
+ filterResult = FILTER_REJECT
+ }
+ node = node.parentNode
+ }
+ }
+ if(filterResult === FILTER_REJECT) {
+ currentPos = 1;
+ moveResult = self.nextPosition()
+ }else {
+ if(filterResult === FILTER_ACCEPT) {
+ moveResult = true
+ }else {
+ moveResult = self.nextPosition()
+ }
+ }
+ if(moveResult) {
+ runtime.assert(nodeFilter(walker.currentNode) === FILTER_ACCEPT, "moveToAcceptedNode did not result in walker being on an accepted node")
+ }
+ return moveResult
+ }
+ this.setPositionBeforeElement = function(element) {
+ runtime.assert(Boolean(element), "setPositionBeforeElement called without element");
+ walker.currentNode = element;
+ currentPos = 0;
+ return moveToAcceptedNode()
+ };
this.setUnfilteredPosition = function(container, offset) {
- var filterResult, node, text;
- runtime.assert(container !== null && container !== undefined, "PositionIterator.setUnfilteredPosition called without container");
+ var text;
+ runtime.assert(Boolean(container), "PositionIterator.setUnfilteredPosition called without container");
walker.currentNode = container;
if(container.nodeType === TEXT_NODE) {
currentPos = offset;
@@ -2098,30 +2362,13 @@ core.PositionIterator = function PositionIterator(root, whatToShow, filter, expa
}
return true
}
- filterResult = nodeFilter(container);
- node = container.parentNode;
- while(node && (node !== root && filterResult === FILTER_ACCEPT)) {
- filterResult = nodeFilter(node);
- if(filterResult !== FILTER_ACCEPT) {
- walker.currentNode = node
- }
- node = node.parentNode
- }
- if(offset < container.childNodes.length && filterResult !== NodeFilter.FILTER_REJECT) {
+ if(offset < container.childNodes.length) {
walker.currentNode = (container.childNodes.item(offset));
- filterResult = nodeFilter(walker.currentNode);
currentPos = 0
}else {
currentPos = 1
}
- if(filterResult === NodeFilter.FILTER_REJECT) {
- currentPos = 1
- }
- if(filterResult !== FILTER_ACCEPT) {
- return self.nextPosition()
- }
- runtime.assert(nodeFilter(walker.currentNode) === FILTER_ACCEPT, "PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set");
- return true
+ return moveToAcceptedNode()
};
this.moveToEnd = function() {
walker.currentNode = root;
@@ -2137,6 +2384,9 @@ core.PositionIterator = function PositionIterator(root, whatToShow, filter, expa
currentPos = 1
}
};
+ this.isBeforeNode = function() {
+ return currentPos === 0
+ };
this.getNodeFilter = function() {
return nodeFilter
};
@@ -2149,7 +2399,7 @@ core.PositionIterator = function PositionIterator(root, whatToShow, filter, expa
}
nodeFilter = (f.acceptNode);
nodeFilter.acceptNode = nodeFilter;
- whatToShow = whatToShow || 4294967295;
+ whatToShow = whatToShow || NodeFilter.SHOW_ALL;
runtime.assert(root.nodeType !== Node.TEXT_NODE, "Internet Explorer doesn't allow tree walker roots to be text nodes");
walker = root.ownerDocument.createTreeWalker(root, whatToShow, nodeFilter, expandEntityReferences);
currentPos = 0;
@@ -2159,6 +2409,29 @@ core.PositionIterator = function PositionIterator(root, whatToShow, filter, expa
}
init()
};
+core.PositionFilter = function PositionFilter() {
+};
+core.PositionFilter.FilterResult = {FILTER_ACCEPT:1, FILTER_REJECT:2, FILTER_SKIP:3};
+core.PositionFilter.prototype.acceptPosition = function(point) {
+};
+(function() {
+ return core.PositionFilter
+})();
+core.PositionFilterChain = function PositionFilterChain() {
+ var filterChain = [], FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
+ this.acceptPosition = function(iterator) {
+ var i;
+ for(i = 0;i < filterChain.length;i += 1) {
+ if(filterChain[i].acceptPosition(iterator) === FILTER_REJECT) {
+ return FILTER_REJECT
+ }
+ }
+ return FILTER_ACCEPT
+ };
+ this.addFilter = function(filterInstance) {
+ filterChain.push(filterInstance)
+ }
+};
core.zip_HuftNode = function() {
this.e = 0;
this.b = 0;
@@ -2780,8 +3053,126 @@ core.ScheduledTask = function ScheduledTask(fn, delay) {
callback()
}
};
-core.NamedFunction;
-core.NamedAsyncFunction;
+/*
+
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+core.StepIterator = function StepIterator(filter, iterator) {
+ var FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, cachedContainer, cachedOffset, cachedFilterResult;
+ function resetCache() {
+ cachedContainer = null;
+ cachedOffset = undefined;
+ cachedFilterResult = undefined
+ }
+ function isStep() {
+ if(cachedFilterResult === undefined) {
+ cachedFilterResult = filter.acceptPosition(iterator) === FILTER_ACCEPT
+ }
+ return(cachedFilterResult)
+ }
+ this.isStep = isStep;
+ function setPosition(newContainer, newOffset) {
+ resetCache();
+ return iterator.setUnfilteredPosition(newContainer, newOffset)
+ }
+ this.setPosition = setPosition;
+ function container() {
+ if(!cachedContainer) {
+ cachedContainer = iterator.container()
+ }
+ return cachedContainer
+ }
+ this.container = container;
+ function offset() {
+ if(cachedOffset === undefined) {
+ cachedOffset = iterator.unfilteredDomOffset()
+ }
+ return(cachedOffset)
+ }
+ this.offset = offset;
+ function nextStep() {
+ resetCache();
+ while(iterator.nextPosition()) {
+ resetCache();
+ if(isStep()) {
+ return true
+ }
+ }
+ return false
+ }
+ this.nextStep = nextStep;
+ function previousStep() {
+ resetCache();
+ while(iterator.previousPosition()) {
+ resetCache();
+ if(isStep()) {
+ return true
+ }
+ }
+ return false
+ }
+ this.previousStep = previousStep;
+ this.roundToClosestStep = function() {
+ var currentContainer = container(), currentOffset = offset(), isAtStep = isStep();
+ if(!isAtStep) {
+ isAtStep = previousStep();
+ if(!isAtStep) {
+ setPosition(currentContainer, currentOffset);
+ isAtStep = nextStep()
+ }
+ }
+ return isAtStep
+ };
+ this.roundToPreviousStep = function() {
+ var isAtStep = isStep();
+ if(!isAtStep) {
+ isAtStep = previousStep()
+ }
+ return isAtStep
+ };
+ this.roundToNextStep = function() {
+ var isAtStep = isStep();
+ if(!isAtStep) {
+ isAtStep = nextStep()
+ }
+ return isAtStep
+ }
+};
+core.TestData;
+core.AsyncTestData;
core.UnitTest = function UnitTest() {
};
core.UnitTest.prototype.setUp = function() {
@@ -2818,17 +3209,61 @@ core.UnitTest.createOdtDocument = function(xml, namespaceMap) {
xmlDoc += "</office:document>";
return runtime.parseXML(xmlDoc)
};
-core.UnitTestRunner = function UnitTestRunner() {
- var failedTests = 0, areObjectsEqual;
+core.UnitTestLogger = function UnitTestLogger() {
+ var messages = [], errors = 0, start = 0, suite = "", test = "";
+ this.startTest = function(suiteName, testName) {
+ messages = [];
+ errors = 0;
+ suite = suiteName;
+ test = testName;
+ start = (new Date).getTime()
+ };
+ this.endTest = function() {
+ var end = (new Date).getTime();
+ return{description:test, suite:[suite, test], success:errors === 0, log:messages, time:end - start}
+ };
+ this.debug = function(msg) {
+ messages.push({category:"debug", message:msg})
+ };
+ this.fail = function(msg) {
+ errors += 1;
+ messages.push({category:"fail", message:msg})
+ };
+ this.pass = function(msg) {
+ messages.push({category:"pass", message:msg})
+ }
+};
+core.UnitTestRunner = function UnitTestRunner(resourcePrefix, logger) {
+ var failedTests = 0, failedTestsOnBeginExpectFail, areObjectsEqual, expectFail = false;
+ this.resourcePrefix = function() {
+ return resourcePrefix
+ };
+ this.beginExpectFail = function() {
+ failedTestsOnBeginExpectFail = failedTests;
+ expectFail = true
+ };
+ this.endExpectFail = function() {
+ var hasNoFailedTests = failedTestsOnBeginExpectFail === failedTests;
+ expectFail = false;
+ failedTests = failedTestsOnBeginExpectFail;
+ if(hasNoFailedTests) {
+ failedTests += 1;
+ logger.fail("Expected at least one failed test, but none registered.")
+ }
+ };
function debug(msg) {
- runtime.log(msg)
+ logger.debug(msg)
}
function testFailed(msg) {
failedTests += 1;
- runtime.log("fail", msg)
+ if(!expectFail) {
+ logger.fail(msg)
+ }else {
+ logger.debug(msg)
+ }
}
function testPassed(msg) {
- runtime.log("pass", msg)
+ logger.pass(msg)
}
function areArraysEqual(a, b) {
var i;
@@ -2917,6 +3352,9 @@ core.UnitTestRunner = function UnitTestRunner() {
if(actual === expected) {
return true
}
+ if(actual === null || expected === null) {
+ return false
+ }
if(typeof expected === "number" && isNaN(expected)) {
return typeof actual === "number" && isNaN(actual)
}
@@ -2925,9 +3363,9 @@ core.UnitTestRunner = function UnitTestRunner() {
}
if(typeof expected === "object" && typeof actual === "object") {
if((expected).constructor === Element || (expected).constructor === Node) {
- return areNodesEqual((expected), (actual))
+ return areNodesEqual((actual), (expected))
}
- return areObjectsEqual((expected), (actual))
+ return areObjectsEqual((actual), (expected))
}
return false
}
@@ -2999,6 +3437,7 @@ core.UnitTestRunner = function UnitTestRunner() {
this.shouldBeNull = shouldBeNull;
this.shouldBeNonNull = shouldBeNonNull;
this.shouldBe = shouldBe;
+ this.testFailed = testFailed;
this.countFailedTests = function() {
return failedTests
};
@@ -3016,12 +3455,32 @@ core.UnitTestRunner = function UnitTestRunner() {
}
};
core.UnitTester = function UnitTester() {
- var failedTests = 0, results = {};
+ var self = this, failedTests = 0, logger = new core.UnitTestLogger, results = {}, inBrowser = runtime.type() === "BrowserRuntime";
+ this.resourcePrefix = "";
function link(text, code) {
return"<span style='color:blue;cursor:pointer' onclick='" + code + "'>" + text + "</span>"
}
+ this.reporter = function(r) {
+ var i, m;
+ if(inBrowser) {
+ runtime.log("<span>Running " + link(r.description, 'runTest("' + r.suite[0] + '","' + r.description + '")') + "</span>")
+ }else {
+ runtime.log("Running " + r.description)
+ }
+ if(!r.success) {
+ for(i = 0;i < r.log.length;i += 1) {
+ m = r.log[i];
+ runtime.log(m.category, m.message)
+ }
+ }
+ };
+ function report(r) {
+ if(self.reporter) {
+ self.reporter(r)
+ }
+ }
this.runTests = function(TestClass, callback, testNames) {
- var testName = Runtime.getFunctionName(TestClass) || "", tname, runner = new core.UnitTestRunner, test = new TestClass(runner), testResults = {}, i, t, tests, lastFailCount, inBrowser = runtime.type() === "BrowserRuntime";
+ var testName = Runtime.getFunctionName(TestClass) || "", tname, runner = new core.UnitTestRunner(self.resourcePrefix, logger), test = new TestClass(runner), testResults = {}, i, t, tests, texpectFail, lastFailCount;
if(results.hasOwnProperty(testName)) {
runtime.log("Test " + testName + " has already run.");
return
@@ -3035,17 +3494,25 @@ core.UnitTester = function UnitTester() {
for(i = 0;i < tests.length;i += 1) {
t = tests[i].f;
tname = tests[i].name;
+ texpectFail = tests[i].expectFail === true;
if(testNames.length && testNames.indexOf(tname) === -1) {
continue
}
- if(inBrowser) {
- runtime.log("<span>Running " + link(tname, 'runTest("' + testName + '","' + tname + '")') + "</span>")
- }else {
- runtime.log("Running " + tname)
- }
lastFailCount = runner.countFailedTests();
test.setUp();
- t();
+ logger.startTest(testName, tname);
+ if(texpectFail) {
+ runner.beginExpectFail()
+ }
+ try {
+ t()
+ }catch(e) {
+ runner.testFailed("Unexpected exception encountered: " + e.toString() + "\n" + e.stack)
+ }
+ if(texpectFail) {
+ runner.endExpectFail()
+ }
+ report(logger.endTest());
test.tearDown();
testResults[tname] = lastFailCount === runner.countFailedTests()
}
@@ -3057,15 +3524,26 @@ core.UnitTester = function UnitTester() {
return
}
t = todo[0].f;
- var fname = todo[0].name;
- runtime.log("Running " + fname);
+ var fname = todo[0].name, expectFail = todo[0].expectFail === true;
lastFailCount = runner.countFailedTests();
- test.setUp();
- t(function() {
- test.tearDown();
- testResults[fname] = lastFailCount === runner.countFailedTests();
+ if(testNames.length && testNames.indexOf(fname) === -1) {
runAsyncTests(todo.slice(1))
- })
+ }else {
+ test.setUp();
+ logger.startTest(testName, fname);
+ if(expectFail) {
+ runner.beginExpectFail()
+ }
+ t(function() {
+ if(expectFail) {
+ runner.endExpectFail()
+ }
+ report(logger.endTest());
+ test.tearDown();
+ testResults[fname] = lastFailCount === runner.countFailedTests();
+ runAsyncTests(todo.slice(1))
+ })
+ }
}
runAsyncTests(test.asyncTests())
};
@@ -3127,10 +3605,6 @@ core.Utils = function Utils() {
Project home: http://www.webodf.org/
*/
-runtime.loadClass("core.RawInflate");
-runtime.loadClass("core.ByteArray");
-runtime.loadClass("core.ByteArrayWriter");
-runtime.loadClass("core.Base64");
core.Zip = function Zip(url, entriesReadCallback) {
var entries, filesize, nEntries, inflate = (new core.RawInflate).inflate, zip = this, base64 = new core.Base64;
function crc32(data) {
@@ -3504,104 +3978,13 @@ core.Zip = function Zip(url, entriesReadCallback) {
}
})
};
-gui.Avatar = function Avatar(parentElement, avatarInitiallyVisible) {
- var self = this, handle, image, pendingImageUrl, displayShown = "block", displayHidden = "none";
- this.setColor = function(color) {
- image.style.borderColor = color
- };
- this.setImageUrl = function(url) {
- if(self.isVisible()) {
- image.src = url
- }else {
- pendingImageUrl = url
- }
- };
- this.isVisible = function() {
- return handle.style.display === displayShown
- };
- this.show = function() {
- if(pendingImageUrl) {
- image.src = pendingImageUrl;
- pendingImageUrl = undefined
- }
- handle.style.display = displayShown
- };
- this.hide = function() {
- handle.style.display = displayHidden
- };
- this.markAsFocussed = function(isFocussed) {
- handle.className = isFocussed ? "active" : ""
- };
- this.destroy = function(callback) {
- parentElement.removeChild(handle);
- callback()
- };
- function init() {
- var document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI;
- handle = (document.createElementNS(htmlns, "div"));
- image = (document.createElementNS(htmlns, "img"));
- image.width = 64;
- image.height = 64;
- handle.appendChild(image);
- handle.style.width = "64px";
- handle.style.height = "70px";
- handle.style.position = "absolute";
- handle.style.top = "-80px";
- handle.style.left = "-34px";
- handle.style.display = avatarInitiallyVisible ? displayShown : displayHidden;
- parentElement.appendChild(handle)
- }
- init()
+xmldom.LSSerializerFilter = function LSSerializerFilter() {
};
-gui.EditInfoHandle = function EditInfoHandle(parentElement) {
- var edits = [], handle, document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI, editinfons = "urn:webodf:names:editinfo";
- function renderEdits() {
- var i, infoDiv, colorSpan, authorSpan, timeSpan;
- handle.innerHTML = "";
- for(i = 0;i < edits.length;i += 1) {
- infoDiv = document.createElementNS(htmlns, "div");
- infoDiv.className = "editInfo";
- colorSpan = document.createElementNS(htmlns, "span");
- colorSpan.className = "editInfoColor";
- colorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
- authorSpan = document.createElementNS(htmlns, "span");
- authorSpan.className = "editInfoAuthor";
- authorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
- timeSpan = document.createElementNS(htmlns, "span");
- timeSpan.className = "editInfoTime";
- timeSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
- timeSpan.innerHTML = edits[i].time;
- infoDiv.appendChild(colorSpan);
- infoDiv.appendChild(authorSpan);
- infoDiv.appendChild(timeSpan);
- handle.appendChild(infoDiv)
- }
- }
- this.setEdits = function(editArray) {
- edits = editArray;
- renderEdits()
- };
- this.show = function() {
- handle.style.display = "block"
- };
- this.hide = function() {
- handle.style.display = "none"
- };
- this.destroy = function(callback) {
- parentElement.removeChild(handle);
- callback()
- };
- function init() {
- handle = (document.createElementNS(htmlns, "div"));
- handle.setAttribute("class", "editInfoHandle");
- handle.style.display = "none";
- parentElement.appendChild(handle)
- }
- init()
+xmldom.LSSerializerFilter.prototype.acceptNode = function(node) {
};
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -3636,69 +4019,21 @@ gui.EditInfoHandle = function EditInfoHandle(parentElement) {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-gui.KeyboardHandler = function KeyboardHandler() {
- var modifier = gui.KeyboardHandler.Modifier, defaultBinding = null, bindings = {};
- function getModifiers(e) {
- var modifiers = modifier.None;
- if(e.metaKey) {
- modifiers |= modifier.Meta
- }
- if(e.ctrlKey) {
- modifiers |= modifier.Ctrl
- }
- if(e.altKey) {
- modifiers |= modifier.Alt
- }
- if(e.shiftKey) {
- modifiers |= modifier.Shift
- }
- return modifiers
- }
- function getKeyCombo(keyCode, modifiers) {
- if(!modifiers) {
- modifiers = modifier.None
- }
- return keyCode + ":" + modifiers
- }
- this.setDefault = function(callback) {
- defaultBinding = callback
- };
- this.bind = function(keyCode, modifiers, callback) {
- var keyCombo = getKeyCombo(keyCode, modifiers);
- runtime.assert(bindings.hasOwnProperty(keyCombo) === false, "tried to overwrite the callback handler of key combo: " + keyCombo);
- bindings[keyCombo] = callback
- };
- this.unbind = function(keyCode, modifiers) {
- var keyCombo = getKeyCombo(keyCode, modifiers);
- delete bindings[keyCombo]
- };
- this.reset = function() {
- defaultBinding = null;
- bindings = {}
- };
- this.handleEvent = function(e) {
- var keyCombo = getKeyCombo(e.keyCode, getModifiers(e)), callback = bindings[keyCombo], handled = false;
- if(callback) {
- handled = callback()
+odf.OdfNodeFilter = function OdfNodeFilter() {
+ this.acceptNode = function(node) {
+ var result;
+ if(node.namespaceURI === "http://www.w3.org/1999/xhtml") {
+ result = NodeFilter.FILTER_SKIP
}else {
- if(defaultBinding !== null) {
- handled = defaultBinding(e)
- }
- }
- if(handled) {
- if(e.preventDefault) {
- e.preventDefault()
+ if(node.namespaceURI && node.namespaceURI.match(/^urn:webodf:/)) {
+ result = NodeFilter.FILTER_REJECT
}else {
- e.returnValue = false
+ result = NodeFilter.FILTER_ACCEPT
}
}
+ return result
}
};
-gui.KeyboardHandler.Modifier = {None:0, Meta:1, Ctrl:2, Alt:4, CtrlAlt:6, Shift:8, MetaShift:9, CtrlShift:10, AltShift:12};
-gui.KeyboardHandler.KeyCode = {Backspace:8, Tab:9, Clear:12, Enter:13, End:35, Home:36, Left:37, Up:38, Right:39, Down:40, Delete:46, A:65, B:66, C:67, D:68, E:69, F:70, G:71, H:72, I:73, J:74, K:75, L:76, M:77, N:78, O:79, P:80, Q:81, R:82, S:83, T:84, U:85, V:86, W:87, X:88, Y:89, Z:90};
-(function() {
- return gui.KeyboardHandler
-})();
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -3768,559 +4103,6 @@ odf.Namespaces.lookupPrefix = function lookupPrefix(namespaceURI) {
return map.hasOwnProperty(namespaceURI) ? map[namespaceURI] : null
};
odf.Namespaces.lookupNamespaceURI.lookupNamespaceURI = odf.Namespaces.lookupNamespaceURI;
-/*
-
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("odf.Namespaces");
-odf.OdfUtils = function OdfUtils() {
- var textns = odf.Namespaces.textns, drawns = odf.Namespaces.drawns, whitespaceOnly = /^\s*$/, domUtils = new core.DomUtils;
- function isImage(e) {
- var name = e && e.localName;
- return name === "image" && e.namespaceURI === drawns
- }
- this.isImage = isImage;
- function isCharacterFrame(e) {
- return e !== null && (e.nodeType === Node.ELEMENT_NODE && (e.localName === "frame" && (e.namespaceURI === drawns && (e).getAttributeNS(textns, "anchor-type") === "as-char")))
- }
- this.isCharacterFrame = isCharacterFrame;
- function isAnnotation(e) {
- var name = e && e.localName;
- return name === "annotation" && e.namespaceURI === odf.Namespaces.officens
- }
- function isAnnotationWrapper(e) {
- var name = e && e.localName;
- return name === "div" && (e).className === "annotationWrapper"
- }
- function isInlineRoot(e) {
- return isAnnotation(e) || isAnnotationWrapper(e)
- }
- this.isInlineRoot = isInlineRoot;
- this.isTextSpan = function(e) {
- var name = e && e.localName;
- return name === "span" && e.namespaceURI === textns
- };
- function isParagraph(e) {
- var name = e && e.localName;
- return(name === "p" || name === "h") && e.namespaceURI === textns
- }
- this.isParagraph = isParagraph;
- function getParagraphElement(node) {
- while(node && !isParagraph(node)) {
- node = node.parentNode
- }
- return node
- }
- this.getParagraphElement = getParagraphElement;
- this.isWithinTrackedChanges = function(node, container) {
- while(node && node !== container) {
- if(node.namespaceURI === textns && node.localName === "tracked-changes") {
- return true
- }
- node = node.parentNode
- }
- return false
- };
- this.isListItem = function(e) {
- var name = e && e.localName;
- return name === "list-item" && e.namespaceURI === textns
- };
- this.isLineBreak = function(e) {
- var name = e && e.localName;
- return name === "line-break" && e.namespaceURI === textns
- };
- function isODFWhitespace(text) {
- return/^[ \t\r\n]+$/.test(text)
- }
- this.isODFWhitespace = isODFWhitespace;
- function isGroupingElement(n) {
- if(n === null || n.nodeType !== Node.ELEMENT_NODE) {
- return false
- }
- var e = (n), localName = e.localName;
- return/^(span|p|h|a|meta)$/.test(localName) && e.namespaceURI === textns || localName === "span" && e.className === "annotationHighlight"
- }
- this.isGroupingElement = isGroupingElement;
- function isCharacterElement(e) {
- var n = e && e.localName, ns, r = false;
- if(n) {
- ns = e.namespaceURI;
- if(ns === textns) {
- r = n === "s" || (n === "tab" || n === "line-break")
- }
- }
- return r
- }
- this.isCharacterElement = isCharacterElement;
- function isAnchoredAsCharacterElement(e) {
- return isCharacterElement(e) || (isCharacterFrame(e) || isInlineRoot(e))
- }
- this.isAnchoredAsCharacterElement = isAnchoredAsCharacterElement;
- function isSpaceElement(e) {
- var n = e && e.localName, ns, r = false;
- if(n) {
- ns = e.namespaceURI;
- if(ns === textns) {
- r = n === "s"
- }
- }
- return r
- }
- this.isSpaceElement = isSpaceElement;
- function firstChild(node) {
- while(node.firstChild !== null && isGroupingElement(node)) {
- node = node.firstChild
- }
- return node
- }
- this.firstChild = firstChild;
- function lastChild(node) {
- while(node.lastChild !== null && isGroupingElement(node)) {
- node = node.lastChild
- }
- return node
- }
- this.lastChild = lastChild;
- function previousNode(node) {
- while(!isParagraph(node) && node.previousSibling === null) {
- node = (node.parentNode)
- }
- return isParagraph(node) ? null : lastChild((node.previousSibling))
- }
- this.previousNode = previousNode;
- function nextNode(node) {
- while(!isParagraph(node) && node.nextSibling === null) {
- node = (node.parentNode)
- }
- return isParagraph(node) ? null : firstChild((node.nextSibling))
- }
- this.nextNode = nextNode;
- function scanLeftForNonSpace(node) {
- var r = false, text;
- while(node) {
- if(node.nodeType === Node.TEXT_NODE) {
- text = (node);
- if(text.length === 0) {
- node = previousNode(text)
- }else {
- return!isODFWhitespace(text.data.substr(text.length - 1, 1))
- }
- }else {
- if(isAnchoredAsCharacterElement(node)) {
- r = isSpaceElement(node) === false;
- node = null
- }else {
- node = previousNode(node)
- }
- }
- }
- return r
- }
- this.scanLeftForNonSpace = scanLeftForNonSpace;
- function lookLeftForCharacter(node) {
- var text, r = 0, tl = 0;
- if(node.nodeType === Node.TEXT_NODE) {
- tl = (node).length
- }
- if(tl > 0) {
- text = (node).data;
- if(!isODFWhitespace(text.substr(tl - 1, 1))) {
- r = 1
- }else {
- if(tl === 1) {
- r = scanLeftForNonSpace(previousNode(node)) ? 2 : 0
- }else {
- r = isODFWhitespace(text.substr(tl - 2, 1)) ? 0 : 2
- }
- }
- }else {
- if(isAnchoredAsCharacterElement(node)) {
- r = 1
- }
- }
- return r
- }
- this.lookLeftForCharacter = lookLeftForCharacter;
- function lookRightForCharacter(node) {
- var r = false, l = 0;
- if(node && node.nodeType === Node.TEXT_NODE) {
- l = (node).length
- }
- if(l > 0) {
- r = !isODFWhitespace((node).data.substr(0, 1))
- }else {
- if(isAnchoredAsCharacterElement(node)) {
- r = true
- }
- }
- return r
- }
- this.lookRightForCharacter = lookRightForCharacter;
- function scanLeftForAnyCharacter(node) {
- var r = false, l;
- node = node && lastChild(node);
- while(node) {
- if(node.nodeType === Node.TEXT_NODE) {
- l = (node).length
- }else {
- l = 0
- }
- if(l > 0 && !isODFWhitespace((node).data)) {
- r = true;
- break
- }
- if(isAnchoredAsCharacterElement(node)) {
- r = true;
- break
- }
- node = previousNode(node)
- }
- return r
- }
- this.scanLeftForAnyCharacter = scanLeftForAnyCharacter;
- function scanRightForAnyCharacter(node) {
- var r = false, l;
- node = node && firstChild(node);
- while(node) {
- if(node.nodeType === Node.TEXT_NODE) {
- l = (node).length
- }else {
- l = 0
- }
- if(l > 0 && !isODFWhitespace((node).data)) {
- r = true;
- break
- }
- if(isAnchoredAsCharacterElement(node)) {
- r = true;
- break
- }
- node = nextNode(node)
- }
- return r
- }
- this.scanRightForAnyCharacter = scanRightForAnyCharacter;
- function isTrailingWhitespace(textnode, offset) {
- if(!isODFWhitespace(textnode.data.substr(offset))) {
- return false
- }
- return!scanRightForAnyCharacter(nextNode(textnode))
- }
- this.isTrailingWhitespace = isTrailingWhitespace;
- function isSignificantWhitespace(textNode, offset) {
- var text = textNode.data, result;
- if(!isODFWhitespace(text[offset])) {
- return false
- }
- if(isAnchoredAsCharacterElement(textNode.parentNode)) {
- return false
- }
- if(offset > 0) {
- if(!isODFWhitespace(text[offset - 1])) {
- result = true
- }
- }else {
- if(scanLeftForNonSpace(previousNode(textNode))) {
- result = true
- }
- }
- if(result === true) {
- return isTrailingWhitespace(textNode, offset) ? false : true
- }
- return false
- }
- this.isSignificantWhitespace = isSignificantWhitespace;
- this.isDowngradableSpaceElement = function(node) {
- if(node.namespaceURI === textns && node.localName === "s") {
- return scanLeftForNonSpace(previousNode(node)) && scanRightForAnyCharacter(nextNode(node))
- }
- return false
- };
- function getFirstNonWhitespaceChild(node) {
- var child = node && node.firstChild;
- while(child && (child.nodeType === Node.TEXT_NODE && whitespaceOnly.test(child.nodeValue))) {
- child = child.nextSibling
- }
- return child
- }
- this.getFirstNonWhitespaceChild = getFirstNonWhitespaceChild;
- function parseLength(length) {
- var re = /(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/, m = re.exec(length);
- if(!m) {
- return null
- }
- return{value:parseFloat(m[1]), unit:m[3]}
- }
- this.parseLength = parseLength;
- function parsePositiveLength(length) {
- var result = parseLength(length);
- if(result && (result.value <= 0 || result.unit === "%")) {
- return null
- }
- return result
- }
- function parseNonNegativeLength(length) {
- var result = parseLength(length);
- if(result && (result.value < 0 || result.unit === "%")) {
- return null
- }
- return result
- }
- this.parseNonNegativeLength = parseNonNegativeLength;
- function parsePercentage(length) {
- var result = parseLength(length);
- if(result && result.unit !== "%") {
- return null
- }
- return result
- }
- function parseFoFontSize(fontSize) {
- return parsePositiveLength(fontSize) || parsePercentage(fontSize)
- }
- this.parseFoFontSize = parseFoFontSize;
- function parseFoLineHeight(lineHeight) {
- return parseNonNegativeLength(lineHeight) || parsePercentage(lineHeight)
- }
- this.parseFoLineHeight = parseFoLineHeight;
- function item(a, i) {
- return a[i]
- }
- function getImpactedParagraphs(range) {
- var i, l, e, outerContainer = (range.commonAncestorContainer), impactedParagraphs = [], filtered = [];
- if(outerContainer.nodeType === Node.ELEMENT_NODE) {
- impactedParagraphs = domUtils.getElementsByTagNameNS(outerContainer, textns, "p").concat(domUtils.getElementsByTagNameNS(outerContainer, textns, "h"))
- }
- while(outerContainer && !isParagraph(outerContainer)) {
- outerContainer = outerContainer.parentNode
- }
- if(outerContainer) {
- impactedParagraphs.push(outerContainer)
- }
- l = impactedParagraphs.length;
- for(i = 0;i < l;i += 1) {
- e = item(impactedParagraphs, i);
- if(domUtils.rangeIntersectsNode(range, e)) {
- filtered.push(e)
- }
- }
- return filtered
- }
- this.getImpactedParagraphs = getImpactedParagraphs;
- function isAcceptedNode(node) {
- switch(node.namespaceURI) {
- case odf.Namespaces.drawns:
- ;
- case odf.Namespaces.svgns:
- ;
- case odf.Namespaces.dr3dns:
- return false;
- case odf.Namespaces.textns:
- switch(node.localName) {
- case "note-body":
- ;
- case "ruby-text":
- return false
- }
- break;
- case odf.Namespaces.officens:
- switch(node.localName) {
- case "annotation":
- ;
- case "binary-data":
- ;
- case "event-listeners":
- return false
- }
- break;
- default:
- switch(node.localName) {
- case "editinfo":
- return false
- }
- break
- }
- return true
- }
- function isSignificantTextContent(textNode) {
- return Boolean(getParagraphElement(textNode) && (!isODFWhitespace(textNode.textContent) || isSignificantWhitespace(textNode, 0)))
- }
- function includeNode(range, nodeRange, includePartial) {
- return includePartial && domUtils.rangesIntersect(range, nodeRange) || domUtils.containsRange(range, nodeRange)
- }
- function getTextNodes(range, includePartial) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), textNodes;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(node.nodeType === Node.TEXT_NODE) {
- if(includeNode(range, nodeRange, includePartial)) {
- return isSignificantTextContent((node)) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
- }
- }else {
- if(domUtils.rangesIntersect(range, nodeRange)) {
- if(isAcceptedNode(node)) {
- return NodeFilter.FILTER_SKIP
- }
- }
- }
- return NodeFilter.FILTER_REJECT
- }
- textNodes = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return textNodes
- }
- this.getTextNodes = getTextNodes;
- this.getTextElements = function(range, includePartial, includeInsignificantWhitespace) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(isCharacterElement(node.parentNode)) {
- return NodeFilter.FILTER_REJECT
- }
- if(node.nodeType === Node.TEXT_NODE) {
- if(includeNode(range, nodeRange, includePartial)) {
- if(includeInsignificantWhitespace || isSignificantTextContent((node))) {
- return NodeFilter.FILTER_ACCEPT
- }
- }
- }else {
- if(isAnchoredAsCharacterElement(node)) {
- if(includeNode(range, nodeRange, includePartial)) {
- return NodeFilter.FILTER_ACCEPT
- }
- }else {
- if(isAcceptedNode(node) || isGroupingElement(node)) {
- return NodeFilter.FILTER_SKIP
- }
- }
- }
- return NodeFilter.FILTER_REJECT
- }
- elements = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return elements
- };
- this.getParagraphElements = function(range) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(isParagraph(node)) {
- if(domUtils.rangesIntersect(range, nodeRange)) {
- return NodeFilter.FILTER_ACCEPT
- }
- }else {
- if(isAcceptedNode(node) || isGroupingElement(node)) {
- return NodeFilter.FILTER_SKIP
- }
- }
- return NodeFilter.FILTER_REJECT
- }
- elements = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return elements
- };
- this.getImageElements = function(range) {
- var document = range.startContainer.ownerDocument, nodeRange = document.createRange(), elements;
- function nodeFilter(node) {
- nodeRange.selectNodeContents(node);
- if(isImage(node) && domUtils.containsRange(range, nodeRange)) {
- return NodeFilter.FILTER_ACCEPT
- }
- return NodeFilter.FILTER_SKIP
- }
- elements = domUtils.getNodesInRange(range, nodeFilter);
- nodeRange.detach();
- return elements
- }
-};
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-ops.Server = function Server() {
-};
-ops.Server.prototype.connect = function(timeout, cb) {
-};
-ops.Server.prototype.networkStatus = function() {
-};
-ops.Server.prototype.login = function(login, password, successCb, failCb) {
-};
-ops.Server.prototype.joinSession = function(userId, sessionId, successCb, failCb) {
-};
-ops.Server.prototype.leaveSession = function(sessionId, memberId, successCb, failCb) {
-};
-ops.Server.prototype.getGenesisUrl = function(sessionId) {
-};
-xmldom.LSSerializerFilter = function LSSerializerFilter() {
-};
-xmldom.LSSerializerFilter.prototype.acceptNode = function(node) {
-};
xmldom.XPathIterator = function XPathIterator() {
};
xmldom.XPathIterator.prototype.next = function() {
@@ -4563,308 +4345,6 @@ function createXPathSingleton() {
return{getODFElementsWithXPath:getODFElementsWithXPath}
}
xmldom.XPath = createXPathSingleton();
-runtime.loadClass("core.DomUtils");
-core.Cursor = function Cursor(document, memberId) {
- var cursorns = "urn:webodf:names:cursor", cursorNode = document.createElementNS(cursorns, "cursor"), anchorNode = document.createElementNS(cursorns, "anchor"), forwardSelection, recentlyModifiedNodes = [], selectedRange = (document.createRange()), isCollapsed, domUtils = new core.DomUtils;
- function putIntoTextNode(node, container, offset) {
- runtime.assert(Boolean(container), "putCursorIntoTextNode: invalid container");
- var parent = container.parentNode;
- runtime.assert(Boolean(parent), "putCursorIntoTextNode: container without parent");
- runtime.assert(offset >= 0 && offset <= container.length, "putCursorIntoTextNode: offset is out of bounds");
- if(offset === 0) {
- parent.insertBefore(node, container)
- }else {
- if(offset === container.length) {
- parent.insertBefore(node, container.nextSibling)
- }else {
- container.splitText(offset);
- parent.insertBefore(node, container.nextSibling)
- }
- }
- }
- function removeNode(node) {
- if(node.parentNode) {
- recentlyModifiedNodes.push(node.previousSibling);
- recentlyModifiedNodes.push(node.nextSibling);
- node.parentNode.removeChild(node)
- }
- }
- function putNode(node, container, offset) {
- if(container.nodeType === Node.TEXT_NODE) {
- putIntoTextNode(node, (container), offset)
- }else {
- if(container.nodeType === Node.ELEMENT_NODE) {
- container.insertBefore(node, container.childNodes.item(offset))
- }
- }
- recentlyModifiedNodes.push(node.previousSibling);
- recentlyModifiedNodes.push(node.nextSibling)
- }
- function getStartNode() {
- return forwardSelection ? anchorNode : cursorNode
- }
- function getEndNode() {
- return forwardSelection ? cursorNode : anchorNode
- }
- this.getNode = function() {
- return cursorNode
- };
- this.getAnchorNode = function() {
- return anchorNode.parentNode ? anchorNode : cursorNode
- };
- this.getSelectedRange = function() {
- if(isCollapsed) {
- selectedRange.setStartBefore(cursorNode);
- selectedRange.collapse(true)
- }else {
- selectedRange.setStartAfter(getStartNode());
- selectedRange.setEndBefore(getEndNode())
- }
- return selectedRange
- };
- this.setSelectedRange = function(range, isForwardSelection) {
- if(selectedRange && selectedRange !== range) {
- selectedRange.detach()
- }
- selectedRange = range;
- forwardSelection = isForwardSelection !== false;
- isCollapsed = range.collapsed;
- if(range.collapsed) {
- removeNode(anchorNode);
- removeNode(cursorNode);
- putNode(cursorNode, (range.startContainer), range.startOffset)
- }else {
- removeNode(anchorNode);
- removeNode(cursorNode);
- putNode(getEndNode(), (range.endContainer), range.endOffset);
- putNode(getStartNode(), (range.startContainer), range.startOffset)
- }
- recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
- recentlyModifiedNodes.length = 0
- };
- this.hasForwardSelection = function() {
- return forwardSelection
- };
- this.remove = function() {
- removeNode(cursorNode);
- recentlyModifiedNodes.forEach(domUtils.normalizeTextNodes);
- recentlyModifiedNodes.length = 0
- };
- function init() {
- cursorNode.setAttributeNS(cursorns, "memberId", memberId);
- anchorNode.setAttributeNS(cursorns, "memberId", memberId)
- }
- init()
-};
-runtime.loadClass("core.PositionIterator");
-core.PositionFilter = function PositionFilter() {
-};
-core.PositionFilter.FilterResult = {FILTER_ACCEPT:1, FILTER_REJECT:2, FILTER_SKIP:3};
-core.PositionFilter.prototype.acceptPosition = function(point) {
-};
-(function() {
- return core.PositionFilter
-})();
-runtime.loadClass("core.PositionFilter");
-core.PositionFilterChain = function PositionFilterChain() {
- var filterChain = {}, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
- this.acceptPosition = function(iterator) {
- var filterName;
- for(filterName in filterChain) {
- if(filterChain.hasOwnProperty(filterName)) {
- if(filterChain[filterName].acceptPosition(iterator) === FILTER_REJECT) {
- return FILTER_REJECT
- }
- }
- }
- return FILTER_ACCEPT
- };
- this.addFilter = function(filterName, filterInstance) {
- filterChain[filterName] = filterInstance
- };
- this.removeFilter = function(filterName) {
- delete filterChain[filterName]
- }
-};
-/*
-
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-gui.AnnotatableCanvas = function AnnotatableCanvas() {
-};
-gui.AnnotatableCanvas.prototype.refreshSize = function() {
-};
-gui.AnnotatableCanvas.prototype.getZoomLevel = function() {
-};
-gui.AnnotatableCanvas.prototype.getSizer = function() {
-};
-gui.AnnotationViewManager = function AnnotationViewManager(canvas, odfFragment, annotationsPane) {
- var annotations = [], doc = odfFragment.ownerDocument, odfUtils = new odf.OdfUtils, CONNECTOR_MARGIN = 30, NOTE_MARGIN = 20, window = runtime.getWindow();
- runtime.assert(Boolean(window), "Expected to be run in an environment which has a global window, like a browser.");
- function wrapAnnotation(annotation) {
- var annotationWrapper = doc.createElement("div"), annotationNote = doc.createElement("div"), connectorHorizontal = doc.createElement("div"), connectorAngular = doc.createElement("div"), removeButton = doc.createElement("div"), annotationNode = annotation.node;
- annotationWrapper.className = "annotationWrapper";
- annotationNode.parentNode.insertBefore(annotationWrapper, annotationNode);
- annotationNote.className = "annotationNote";
- annotationNote.appendChild(annotationNode);
- removeButton.className = "annotationRemoveButton";
- annotationNote.appendChild(removeButton);
- connectorHorizontal.className = "annotationConnector horizontal";
- connectorAngular.className = "annotationConnector angular";
- annotationWrapper.appendChild(annotationNote);
- annotationWrapper.appendChild(connectorHorizontal);
- annotationWrapper.appendChild(connectorAngular)
- }
- function unwrapAnnotation(annotation) {
- var annotationNode = annotation.node, annotationWrapper = annotationNode.parentNode.parentNode;
- if(annotationWrapper.localName === "div") {
- annotationWrapper.parentNode.insertBefore(annotationNode, annotationWrapper);
- annotationWrapper.parentNode.removeChild(annotationWrapper)
- }
- }
- function highlightAnnotation(annotation) {
- var annotationNode = annotation.node, annotationEnd = annotation.end, range = doc.createRange(), textNodes;
- if(annotationEnd) {
- range.setStart(annotationNode, annotationNode.childNodes.length);
- range.setEnd(annotationEnd, 0);
- textNodes = odfUtils.getTextNodes(range, false);
- textNodes.forEach(function(n) {
- var container = doc.createElement("span"), v = annotationNode.getAttributeNS(odf.Namespaces.officens, "name");
- container.className = "annotationHighlight";
- container.setAttribute("annotation", v);
- n.parentNode.insertBefore(container, n);
- container.appendChild(n)
- })
- }
- range.detach()
- }
- function unhighlightAnnotation(annotation) {
- var annotationName = annotation.node.getAttributeNS(odf.Namespaces.officens, "name"), highlightSpans = doc.querySelectorAll('span.annotationHighlight[annotation="' + annotationName + '"]'), i, container;
- for(i = 0;i < highlightSpans.length;i += 1) {
- container = highlightSpans.item(i);
- while(container.firstChild) {
- container.parentNode.insertBefore(container.firstChild, container)
- }
- container.parentNode.removeChild(container)
- }
- }
- function lineDistance(point1, point2) {
- var xs = 0, ys = 0;
- xs = point2.x - point1.x;
- xs = xs * xs;
- ys = point2.y - point1.y;
- ys = ys * ys;
- return Math.sqrt(xs + ys)
- }
- function renderAnnotation(annotation) {
- var annotationNote = annotation.node.parentElement, connectorHorizontal = annotationNote.nextElementSibling, connectorAngular = connectorHorizontal.nextElementSibling, annotationWrapper = annotationNote.parentElement, connectorAngle = 0, previousAnnotation = annotations[annotations.indexOf(annotation) - 1], previousRect, zoomLevel = canvas.getZoomLevel();
- annotationNote.style.left = (annotationsPane.getBoundingClientRect().left - annotationWrapper.getBoundingClientRect().left) / zoomLevel + "px";
- annotationNote.style.width = annotationsPane.getBoundingClientRect().width / zoomLevel + "px";
- connectorHorizontal.style.width = parseFloat(annotationNote.style.left) - CONNECTOR_MARGIN + "px";
- if(previousAnnotation) {
- previousRect = previousAnnotation.node.parentElement.getBoundingClientRect();
- if((annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel <= NOTE_MARGIN) {
- annotationNote.style.top = Math.abs(annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel + NOTE_MARGIN + "px"
- }else {
- annotationNote.style.top = "0px"
- }
- }
- connectorAngular.style.left = connectorHorizontal.getBoundingClientRect().width / zoomLevel + "px";
- connectorAngular.style.width = lineDistance({x:connectorAngular.getBoundingClientRect().left / zoomLevel, y:connectorAngular.getBoundingClientRect().top / zoomLevel}, {x:annotationNote.getBoundingClientRect().left / zoomLevel, y:annotationNote.getBoundingClientRect().top / zoomLevel}) + "px";
- connectorAngle = Math.asin((annotationNote.getBoundingClientRect().top - connectorAngular.getBoundingClientRect().top) / (zoomLevel * parseFloat(connectorAngular.style.width)));
- connectorAngular.style.transform = "rotate(" + connectorAngle + "rad)";
- connectorAngular.style.MozTransform = "rotate(" + connectorAngle + "rad)";
- connectorAngular.style.WebkitTransform = "rotate(" + connectorAngle + "rad)";
- connectorAngular.style.msTransform = "rotate(" + connectorAngle + "rad)"
- }
- function showAnnotationsPane(show) {
- var sizer = canvas.getSizer();
- if(show) {
- annotationsPane.style.display = "inline-block";
- sizer.style.paddingRight = window.getComputedStyle(annotationsPane).width
- }else {
- annotationsPane.style.display = "none";
- sizer.style.paddingRight = 0
- }
- canvas.refreshSize()
- }
- function sortAnnotations() {
- annotations.sort(function(a, b) {
- if(a.node.compareDocumentPosition(b.node) === Node.DOCUMENT_POSITION_FOLLOWING) {
- return-1
- }
- return 1
- })
- }
- function rerenderAnnotations() {
- var i;
- for(i = 0;i < annotations.length;i += 1) {
- renderAnnotation(annotations[i])
- }
- }
- this.rerenderAnnotations = rerenderAnnotations;
- function addAnnotation(annotation) {
- showAnnotationsPane(true);
- annotations.push({node:annotation.node, end:annotation.end});
- sortAnnotations();
- wrapAnnotation(annotation);
- if(annotation.end) {
- highlightAnnotation(annotation)
- }
- rerenderAnnotations()
- }
- this.addAnnotation = addAnnotation;
- function forgetAnnotation(annotation) {
- var index = annotations.indexOf(annotation);
- unwrapAnnotation(annotation);
- unhighlightAnnotation(annotation);
- if(index !== -1) {
- annotations.splice(index, 1)
- }
- if(annotations.length === 0) {
- showAnnotationsPane(false)
- }
- }
- function forgetAnnotations() {
- while(annotations.length) {
- forgetAnnotation(annotations[0])
- }
- }
- this.forgetAnnotations = forgetAnnotations
-};
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -4902,1024 +4382,6 @@ gui.AnnotationViewManager = function AnnotationViewManager(canvas, odfFragment,
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.Cursor");
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("core.PositionIterator");
-runtime.loadClass("core.PositionFilter");
-runtime.loadClass("core.LoopWatchDog");
-runtime.loadClass("odf.OdfUtils");
-gui.SelectionMover = function SelectionMover(cursor, rootNode) {
- var odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, positionIterator, cachedXOffset, timeoutHandle, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
- function getIteratorAtCursor() {
- positionIterator.setUnfilteredPosition(cursor.getNode(), 0);
- return positionIterator
- }
- function getMaximumNodePosition(node) {
- return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
- }
- function getClientRect(clientRectangles, useRightEdge) {
- var rectangle, simplifiedRectangle = null;
- if(clientRectangles && clientRectangles.length > 0) {
- rectangle = useRightEdge ? clientRectangles.item(clientRectangles.length - 1) : clientRectangles.item(0)
- }
- if(rectangle) {
- simplifiedRectangle = {top:rectangle.top, left:useRightEdge ? rectangle.right : rectangle.left, bottom:rectangle.bottom}
- }
- return simplifiedRectangle
- }
- function getVisibleRect(container, offset, range, useRightEdge) {
- var rectangle, nodeType = container.nodeType;
- range.setStart(container, offset);
- range.collapse(!useRightEdge);
- rectangle = getClientRect(range.getClientRects(), useRightEdge === true);
- if(!rectangle && offset > 0) {
- range.setStart(container, offset - 1);
- range.setEnd(container, offset);
- rectangle = getClientRect(range.getClientRects(), true)
- }
- if(!rectangle) {
- if(nodeType === Node.ELEMENT_NODE && (offset > 0 && (container).childNodes.length >= offset)) {
- rectangle = getVisibleRect(container, offset - 1, range, true)
- }else {
- if(container.nodeType === Node.TEXT_NODE && offset > 0) {
- rectangle = getVisibleRect(container, offset - 1, range, true)
- }else {
- if(container.previousSibling) {
- rectangle = getVisibleRect(container.previousSibling, getMaximumNodePosition(container.previousSibling), range, true)
- }else {
- if(container.parentNode && container.parentNode !== rootNode) {
- rectangle = getVisibleRect(container.parentNode, 0, range, false)
- }else {
- range.selectNode(rootNode);
- rectangle = getClientRect(range.getClientRects(), false)
- }
- }
- }
- }
- }
- runtime.assert(Boolean(rectangle), "No visible rectangle found");
- return(rectangle)
- }
- function doMove(positions, extend, move) {
- var left = positions, iterator = getIteratorAtCursor(), initialRect, range = (rootNode.ownerDocument.createRange()), selectionRange = cursor.getSelectedRange().cloneRange(), newRect, horizontalMovement, o, c, isForwardSelection;
- initialRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- while(left > 0 && move()) {
- left -= 1
- }
- if(extend) {
- c = iterator.container();
- o = iterator.unfilteredDomOffset();
- if(domUtils.comparePoints((selectionRange.startContainer), selectionRange.startOffset, c, o) === -1) {
- selectionRange.setStart(c, o);
- isForwardSelection = false
- }else {
- selectionRange.setEnd(c, o)
- }
- }else {
- selectionRange.setStart(iterator.container(), iterator.unfilteredDomOffset());
- selectionRange.collapse(true)
- }
- cursor.setSelectedRange(selectionRange, isForwardSelection);
- iterator = getIteratorAtCursor();
- newRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- horizontalMovement = newRect.top === initialRect.top ? true : false;
- if(horizontalMovement || cachedXOffset === undefined) {
- cachedXOffset = newRect.left
- }
- runtime.clearTimeout(timeoutHandle);
- timeoutHandle = runtime.setTimeout(function() {
- cachedXOffset = undefined
- }, 2E3);
- range.detach();
- return positions - left
- }
- this.movePointForward = function(positions, extend) {
- return doMove(positions, extend || false, positionIterator.nextPosition)
- };
- this.movePointBackward = function(positions, extend) {
- return doMove(positions, extend || false, positionIterator.previousPosition)
- };
- function isPositionWalkable(filter) {
- var iterator = getIteratorAtCursor();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- iterator.setUnfilteredPosition(cursor.getAnchorNode(), 0);
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- return true
- }
- }
- return false
- }
- function countSteps(iterator, steps, filter) {
- var watch = new core.LoopWatchDog(1E4), positions = 0, positionsCount = 0, increment = steps >= 0 ? 1 : -1, delegate = (steps >= 0 ? iterator.nextPosition : iterator.previousPosition);
- while(steps !== 0 && delegate()) {
- watch.check();
- positionsCount += increment;
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps -= increment;
- positions += positionsCount;
- positionsCount = 0
- }
- }
- return positions
- }
- function convertForwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
- var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
- while(stepsFilter1 > 0 && iterator.nextPosition()) {
- watch.check();
- if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
- pendingStepsFilter2 += 1;
- if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
- stepsFilter2 += pendingStepsFilter2;
- pendingStepsFilter2 = 0;
- stepsFilter1 -= 1
- }
- }
- }
- return stepsFilter2
- }
- function convertBackwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
- var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
- while(stepsFilter1 > 0 && iterator.previousPosition()) {
- watch.check();
- if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
- pendingStepsFilter2 += 1;
- if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
- stepsFilter2 += pendingStepsFilter2;
- pendingStepsFilter2 = 0;
- stepsFilter1 -= 1
- }
- }
- }
- return stepsFilter2
- }
- function countStepsPublic(steps, filter) {
- var iterator = getIteratorAtCursor();
- return countSteps(iterator, steps, filter)
- }
- function countPositionsToClosestStep(container, offset, filter) {
- var iterator = getIteratorAtCursor(), paragraphNode = odfUtils.getParagraphElement(iterator.getCurrentNode()), count = 0;
- iterator.setUnfilteredPosition(container, offset);
- if(filter.acceptPosition(iterator) !== FILTER_ACCEPT) {
- count = countSteps(iterator, -1, filter);
- if(count === 0 || paragraphNode && paragraphNode !== odfUtils.getParagraphElement(iterator.getCurrentNode())) {
- iterator.setUnfilteredPosition(container, offset);
- count = countSteps(iterator, 1, filter)
- }
- }
- return count
- }
- function countLineSteps(filter, direction, iterator) {
- var c = iterator.container(), steps = 0, bestContainer = null, bestOffset, bestXDiff = 10, xDiff, bestCount = 0, top, left, lastTop, rect, range = (rootNode.ownerDocument.createRange()), watch = new core.LoopWatchDog(1E4);
- rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
- top = rect.top;
- if(cachedXOffset === undefined) {
- left = rect.left
- }else {
- left = cachedXOffset
- }
- lastTop = top;
- while((direction < 0 ? iterator.previousPosition() : iterator.nextPosition()) === true) {
- watch.check();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps += 1;
- c = iterator.container();
- rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
- if(rect.top !== top) {
- if(rect.top !== lastTop && lastTop !== top) {
- break
- }
- lastTop = rect.top;
- xDiff = Math.abs(left - rect.left);
- if(bestContainer === null || xDiff < bestXDiff) {
- bestContainer = c;
- bestOffset = iterator.unfilteredDomOffset();
- bestXDiff = xDiff;
- bestCount = steps
- }
- }
- }
- }
- if(bestContainer !== null) {
- iterator.setUnfilteredPosition(bestContainer, (bestOffset));
- steps = bestCount
- }else {
- steps = 0
- }
- range.detach();
- return steps
- }
- function countLinesSteps(lines, filter) {
- var iterator = getIteratorAtCursor(), stepCount = 0, steps = 0, direction = lines < 0 ? -1 : 1;
- lines = Math.abs(lines);
- while(lines > 0) {
- stepCount += countLineSteps(filter, direction, iterator);
- if(stepCount === 0) {
- break
- }
- steps += stepCount;
- lines -= 1
- }
- return steps * direction
- }
- function countStepsToLineBoundary(direction, filter) {
- var fnNextPos, increment, lastRect, rect, onSameLine, iterator = getIteratorAtCursor(), paragraphNode = odfUtils.getParagraphElement(iterator.getCurrentNode()), steps = 0, range = (rootNode.ownerDocument.createRange());
- if(direction < 0) {
- fnNextPos = iterator.previousPosition;
- increment = -1
- }else {
- fnNextPos = iterator.nextPosition;
- increment = 1
- }
- lastRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- while(fnNextPos.call(iterator)) {
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- if(odfUtils.getParagraphElement(iterator.getCurrentNode()) !== paragraphNode) {
- break
- }
- rect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
- if(rect.bottom !== lastRect.bottom) {
- onSameLine = rect.top >= lastRect.top && rect.bottom < lastRect.bottom || rect.top <= lastRect.top && rect.bottom > lastRect.bottom;
- if(!onSameLine) {
- break
- }
- }
- steps += increment;
- lastRect = rect
- }
- }
- range.detach();
- return steps
- }
- function countStepsToPosition(targetNode, targetOffset, filter) {
- runtime.assert(targetNode !== null, "SelectionMover.countStepsToPosition called with element===null");
- var iterator = getIteratorAtCursor(), c = iterator.container(), o = iterator.unfilteredDomOffset(), steps = 0, watch = new core.LoopWatchDog(1E4), comparison;
- iterator.setUnfilteredPosition(targetNode, targetOffset);
- while(filter.acceptPosition(iterator) !== FILTER_ACCEPT && iterator.previousPosition()) {
- watch.check()
- }
- targetNode = iterator.container();
- runtime.assert(Boolean(targetNode), "SelectionMover.countStepsToPosition: positionIterator.container() returned null");
- targetOffset = iterator.unfilteredDomOffset();
- iterator.setUnfilteredPosition(c, o);
- while(filter.acceptPosition(iterator) !== FILTER_ACCEPT && iterator.previousPosition()) {
- watch.check()
- }
- comparison = domUtils.comparePoints(targetNode, targetOffset, iterator.container(), iterator.unfilteredDomOffset());
- if(comparison < 0) {
- while(iterator.nextPosition()) {
- watch.check();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps += 1
- }
- if(iterator.container() === targetNode && iterator.unfilteredDomOffset() === targetOffset) {
- return steps
- }
- }
- }else {
- if(comparison > 0) {
- while(iterator.previousPosition()) {
- watch.check();
- if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
- steps -= 1;
- if(iterator.container() === targetNode && iterator.unfilteredDomOffset() === targetOffset) {
- break
- }
- }
- }
- }
- }
- return steps
- }
- this.getStepCounter = function() {
- return{countSteps:countStepsPublic, convertForwardStepsBetweenFilters:convertForwardStepsBetweenFilters, convertBackwardStepsBetweenFilters:convertBackwardStepsBetweenFilters, countLinesSteps:countLinesSteps, countStepsToLineBoundary:countStepsToLineBoundary, countStepsToPosition:countStepsToPosition, isPositionWalkable:isPositionWalkable, countPositionsToNearestStep:countPositionsToClosestStep}
- };
- function init() {
- positionIterator = gui.SelectionMover.createPositionIterator(rootNode);
- var range = rootNode.ownerDocument.createRange();
- range.setStart(positionIterator.container(), positionIterator.unfilteredDomOffset());
- range.collapse(true);
- cursor.setSelectedRange(range)
- }
- init()
-};
-gui.SelectionMover.createPositionIterator = function(rootNode) {
- function CursorFilter() {
- this.acceptNode = function(node) {
- if(!node || (node.namespaceURI === "urn:webodf:names:cursor" || node.namespaceURI === "urn:webodf:names:editinfo")) {
- return NodeFilter.FILTER_REJECT
- }
- return NodeFilter.FILTER_ACCEPT
- }
- }
- var filter = new CursorFilter;
- return new core.PositionIterator(rootNode, 5, filter, false)
-};
-(function() {
- return gui.SelectionMover
-})();
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-odf.OdfNodeFilter = function OdfNodeFilter() {
- this.acceptNode = function(node) {
- var result;
- if(node.namespaceURI === "http://www.w3.org/1999/xhtml") {
- result = NodeFilter.FILTER_SKIP
- }else {
- if(node.namespaceURI && node.namespaceURI.match(/^urn:webodf:/)) {
- result = NodeFilter.FILTER_REJECT
- }else {
- result = NodeFilter.FILTER_ACCEPT
- }
- }
- return result
- }
-};
-/*
-
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("xmldom.XPath");
-runtime.loadClass("core.CSSUnits");
-odf.StyleTreeNode = function StyleTreeNode(element) {
- this.derivedStyles = {};
- this.element = element
-};
-odf.Style2CSS = function Style2CSS() {
- var drawns = odf.Namespaces.drawns, fons = odf.Namespaces.fons, officens = odf.Namespaces.officens, stylens = odf.Namespaces.stylens, svgns = odf.Namespaces.svgns, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns, presentationns = odf.Namespaces.presentationns, familynamespaceprefixes = {"graphic":"draw", "drawing-page":"draw", "paragraph":"text", "presentation":"presentation", "ruby":"text", "section":"text", "table":"table", "table-cell":"table",
- "table-column":"table", "table-row":"table", "text":"text", "list":"text", "page":"office"}, familytagnames = {"graphic":["circle", "connected", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "paragraph":["alphabetical-index-entry-template", "h", "illustration-index-entry-template", "index-source-style", "object-index-entry-template", "p", "table-index-entry-template", "table-of-content-entry-template",
- "user-index-entry-template"], "presentation":["caption", "circle", "connector", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "drawing-page":["caption", "circle", "connector", "control", "page", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "ruby":["ruby", "ruby-text"], "section":["alphabetical-index", "bibliography",
- "illustration-index", "index-title", "object-index", "section", "table-of-content", "table-index", "user-index"], "table":["background", "table"], "table-cell":["body", "covered-table-cell", "even-columns", "even-rows", "first-column", "first-row", "last-column", "last-row", "odd-columns", "odd-rows", "table-cell"], "table-column":["table-column"], "table-row":["table-row"], "text":["a", "index-entry-chapter", "index-entry-link-end", "index-entry-link-start", "index-entry-page-number", "index-entry-span",
- "index-entry-tab-stop", "index-entry-text", "index-title-template", "linenumbering-configuration", "list-level-style-number", "list-level-style-bullet", "outline-level-style", "span"], "list":["list-item"]}, textPropertySimpleMapping = [[fons, "color", "color"], [fons, "background-color", "background-color"], [fons, "font-weight", "font-weight"], [fons, "font-style", "font-style"]], bgImageSimpleMapping = [[stylens, "repeat", "background-repeat"]], paragraphPropertySimpleMapping = [[fons, "background-color",
- "background-color"], [fons, "text-align", "text-align"], [fons, "text-indent", "text-indent"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-left", "margin-left"],
- [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"], [fons, "border", "border"]], graphicPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "min-height", "min-height"], [drawns, "stroke", "border"], [svgns, "stroke-color", "border-color"], [svgns, "stroke-width", "border-width"], [fons, "border", "border"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top",
- "border-top"], [fons, "border-bottom", "border-bottom"]], tablecellPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "border", "border"]], tablecolumnPropertySimpleMapping = [[stylens, "column-width", "width"]], tablerowPropertySimpleMapping = [[stylens, "row-height", "height"], [fons, "keep-together", null]], tablePropertySimpleMapping =
- [[stylens, "width", "width"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageContentPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border", "border"], [fons,
- "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageSizePropertySimpleMapping = [[fons, "page-width", "width"], [fons, "page-height", "height"]], borderPropertyMap = {"border":true, "border-left":true, "border-right":true,
- "border-top":true, "border-bottom":true, "stroke-width":true}, fontFaceDeclsMap = {}, utils = new odf.OdfUtils, documentType, odfRoot, defaultFontSize, xpath = xmldom.XPath, cssUnits = new core.CSSUnits;
- function getStyleMap(stylesnode) {
- var node, name, family, style, stylemap = {};
- if(!stylesnode) {
- return stylemap
- }
- node = stylesnode.firstElementChild;
- while(node) {
- if(node.namespaceURI === stylens && (node.localName === "style" || node.localName === "default-style")) {
- family = node.getAttributeNS(stylens, "family")
- }else {
- if(node.namespaceURI === textns && node.localName === "list-style") {
- family = "list"
- }else {
- if(node.namespaceURI === stylens && (node.localName === "page-layout" || node.localName === "default-page-layout")) {
- family = "page"
- }else {
- family = undefined
- }
- }
- }
- if(family) {
- name = node.getAttributeNS(stylens, "name");
- if(!name) {
- name = ""
- }
- if(stylemap.hasOwnProperty(family)) {
- style = stylemap[family]
- }else {
- stylemap[family] = style = {}
- }
- style[name] = node
- }
- node = node.nextElementSibling
- }
- return stylemap
- }
- function findStyle(stylestree, name) {
- if(stylestree.hasOwnProperty(name)) {
- return stylestree[name]
- }
- var n, style = null;
- for(n in stylestree) {
- if(stylestree.hasOwnProperty(n)) {
- style = findStyle(stylestree[n].derivedStyles, name);
- if(style) {
- break
- }
- }
- }
- return style
- }
- function addStyleToStyleTree(stylename, stylesmap, stylestree) {
- var style, parentname, parentstyle;
- if(!stylesmap.hasOwnProperty(stylename)) {
- return null
- }
- style = new odf.StyleTreeNode(stylesmap[stylename]);
- parentname = style.element.getAttributeNS(stylens, "parent-style-name");
- parentstyle = null;
- if(parentname) {
- parentstyle = findStyle(stylestree, parentname) || addStyleToStyleTree(parentname, stylesmap, stylestree)
- }
- if(parentstyle) {
- parentstyle.derivedStyles[stylename] = style
- }else {
- stylestree[stylename] = style
- }
- delete stylesmap[stylename];
- return style
- }
- function addStyleMapToStyleTree(stylesmap, stylestree) {
- var name;
- for(name in stylesmap) {
- if(stylesmap.hasOwnProperty(name)) {
- addStyleToStyleTree(name, stylesmap, stylestree)
- }
- }
- }
- function createSelector(family, name) {
- var prefix = familynamespaceprefixes[family], namepart, selector;
- if(prefix === undefined) {
- return null
- }
- if(name) {
- namepart = "[" + prefix + '|style-name="' + name + '"]'
- }else {
- namepart = ""
- }
- if(prefix === "presentation") {
- prefix = "draw";
- if(name) {
- namepart = '[presentation|style-name="' + name + '"]'
- }else {
- namepart = ""
- }
- }
- selector = prefix + "|" + familytagnames[family].join(namepart + "," + prefix + "|") + namepart;
- return selector
- }
- function getSelectors(family, name, node) {
- var selectors = [], ss, derivedStyles = node.derivedStyles, n;
- ss = createSelector(family, name);
- if(ss !== null) {
- selectors.push(ss)
- }
- for(n in derivedStyles) {
- if(derivedStyles.hasOwnProperty(n)) {
- ss = getSelectors(family, n, derivedStyles[n]);
- selectors = selectors.concat(ss)
- }
- }
- return selectors
- }
- function getDirectChild(node, ns, name) {
- var e = node && node.firstElementChild;
- while(e) {
- if(e.namespaceURI === ns && e.localName === name) {
- break
- }
- e = e.nextElementSibling
- }
- return e
- }
- function fixBorderWidth(value) {
- var index = value.indexOf(" "), width, theRestOfBorderAttributes;
- if(index !== -1) {
- width = value.substring(0, index);
- theRestOfBorderAttributes = value.substring(index)
- }else {
- width = value;
- theRestOfBorderAttributes = ""
- }
- width = utils.parseLength(width);
- if(width && (width.unit === "pt" && width.value < 0.75)) {
- value = "0.75pt" + theRestOfBorderAttributes
- }
- return value
- }
- function applySimpleMapping(props, mapping) {
- var rule = "", i, r, value;
- for(i = 0;i < mapping.length;i += 1) {
- r = mapping[i];
- value = props.getAttributeNS(r[0], r[1]);
- if(value) {
- value = value.trim();
- if(borderPropertyMap.hasOwnProperty(r[1])) {
- value = fixBorderWidth(value)
- }
- if(r[2]) {
- rule += r[2] + ":" + value + ";"
- }
- }
- }
- return rule
- }
- function getFontSize(styleNode) {
- var props = getDirectChild(styleNode, stylens, "text-properties");
- if(props) {
- return utils.parseFoFontSize(props.getAttributeNS(fons, "font-size"))
- }
- return null
- }
- function getParentStyleNode(styleNode) {
- var parentStyleName = "", parentStyleFamily = "", parentStyleNode = null, xp;
- if(styleNode.localName === "default-style") {
- return null
- }
- parentStyleName = styleNode.getAttributeNS(stylens, "parent-style-name");
- parentStyleFamily = styleNode.getAttributeNS(stylens, "family");
- if(parentStyleName) {
- xp = "//style:*[@style:name='" + parentStyleName + "'][@style:family='" + parentStyleFamily + "']"
- }else {
- xp = "//style:default-style[@style:family='" + parentStyleFamily + "']"
- }
- parentStyleNode = xpath.getODFElementsWithXPath((odfRoot), xp, odf.Namespaces.lookupNamespaceURI)[0];
- return parentStyleNode
- }
- function getTextProperties(props) {
- var rule = "", fontName, fontSize, value, textDecoration = "", fontSizeRule = "", sizeMultiplier = 1, parentStyle;
- rule += applySimpleMapping(props, textPropertySimpleMapping);
- value = props.getAttributeNS(stylens, "text-underline-style");
- if(value === "solid") {
- textDecoration += " underline"
- }
- value = props.getAttributeNS(stylens, "text-line-through-style");
- if(value === "solid") {
- textDecoration += " line-through"
- }
- if(textDecoration.length) {
- textDecoration = "text-decoration:" + textDecoration + ";";
- rule += textDecoration
- }
- fontName = props.getAttributeNS(stylens, "font-name") || props.getAttributeNS(fons, "font-family");
- if(fontName) {
- value = fontFaceDeclsMap[fontName];
- rule += "font-family: " + (value || fontName) + ";"
- }
- parentStyle = props.parentElement;
- fontSize = getFontSize(parentStyle);
- if(!fontSize) {
- return rule
- }
- while(parentStyle) {
- fontSize = getFontSize(parentStyle);
- if(fontSize) {
- if(fontSize.unit !== "%") {
- fontSizeRule = "font-size: " + fontSize.value * sizeMultiplier + fontSize.unit + ";";
- break
- }
- sizeMultiplier *= fontSize.value / 100
- }
- parentStyle = getParentStyleNode(parentStyle)
- }
- if(!fontSizeRule) {
- fontSizeRule = "font-size: " + parseFloat(defaultFontSize) * sizeMultiplier + cssUnits.getUnits(defaultFontSize) + ";"
- }
- rule += fontSizeRule;
- return rule
- }
- function getParagraphProperties(props) {
- var rule = "", bgimage, url, lineHeight;
- rule += applySimpleMapping(props, paragraphPropertySimpleMapping);
- bgimage = getDirectChild(props, stylens, "background-image");
- if(bgimage) {
- url = bgimage.getAttributeNS(xlinkns, "href");
- if(url) {
- rule += "background-image: url('odfkit:" + url + "');";
- rule += applySimpleMapping(bgimage, bgImageSimpleMapping)
- }
- }
- lineHeight = props.getAttributeNS(fons, "line-height");
- if(lineHeight && lineHeight !== "normal") {
- lineHeight = utils.parseFoLineHeight(lineHeight);
- if(lineHeight.unit !== "%") {
- rule += "line-height: " + lineHeight.value + lineHeight.unit + ";"
- }else {
- rule += "line-height: " + lineHeight.value / 100 + ";"
- }
- }
- return rule
- }
- function matchToRgb(m, r, g, b) {
- return r + r + g + g + b + b
- }
- function hexToRgb(hex) {
- var result, shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
- hex = hex.replace(shorthandRegex, matchToRgb);
- result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
- return result ? {r:parseInt(result[1], 16), g:parseInt(result[2], 16), b:parseInt(result[3], 16)} : null
- }
- function isNumber(n) {
- return!isNaN(parseFloat(n))
- }
- function getGraphicProperties(props) {
- var rule = "", alpha, bgcolor, fill;
- rule += applySimpleMapping(props, graphicPropertySimpleMapping);
- alpha = props.getAttributeNS(drawns, "opacity");
- fill = props.getAttributeNS(drawns, "fill");
- bgcolor = props.getAttributeNS(drawns, "fill-color");
- if(fill === "solid" || fill === "hatch") {
- if(bgcolor && bgcolor !== "none") {
- alpha = isNumber(alpha) ? parseFloat(alpha) / 100 : 1;
- bgcolor = hexToRgb(bgcolor);
- if(bgcolor) {
- rule += "background-color: rgba(" + bgcolor.r + "," + bgcolor.g + "," + bgcolor.b + "," + alpha + ");"
- }
- }else {
- rule += "background: none;"
- }
- }else {
- if(fill === "none") {
- rule += "background: none;"
- }
- }
- return rule
- }
- function getDrawingPageProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, graphicPropertySimpleMapping);
- if(props.getAttributeNS(presentationns, "background-visible") === "true") {
- rule += "background: none;"
- }
- return rule
- }
- function getTableCellProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, tablecellPropertySimpleMapping);
- return rule
- }
- function getTableRowProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, tablerowPropertySimpleMapping);
- return rule
- }
- function getTableColumnProperties(props) {
- var rule = "";
- rule += applySimpleMapping(props, tablecolumnPropertySimpleMapping);
- return rule
- }
- function getTableProperties(props) {
- var rule = "", borderModel;
- rule += applySimpleMapping(props, tablePropertySimpleMapping);
- borderModel = props.getAttributeNS(tablens, "border-model");
- if(borderModel === "collapsing") {
- rule += "border-collapse:collapse;"
- }else {
- if(borderModel === "separating") {
- rule += "border-collapse:separate;"
- }
- }
- return rule
- }
- function addStyleRule(sheet, family, name, node) {
- var selectors = getSelectors(family, name, node), selector = selectors.join(","), rule = "", properties;
- properties = getDirectChild(node.element, stylens, "text-properties");
- if(properties) {
- rule += getTextProperties(properties)
- }
- properties = getDirectChild(node.element, stylens, "paragraph-properties");
- if(properties) {
- rule += getParagraphProperties(properties)
- }
- properties = getDirectChild(node.element, stylens, "graphic-properties");
- if(properties) {
- rule += getGraphicProperties(properties)
- }
- properties = getDirectChild(node.element, stylens, "drawing-page-properties");
- if(properties) {
- rule += getDrawingPageProperties(properties)
- }
- properties = getDirectChild(node.element, stylens, "table-cell-properties");
- if(properties) {
- rule += getTableCellProperties(properties)
- }
- properties = getDirectChild(node.element, stylens, "table-row-properties");
- if(properties) {
- rule += getTableRowProperties(properties)
- }
- properties = getDirectChild(node.element, stylens, "table-column-properties");
- if(properties) {
- rule += getTableColumnProperties(properties)
- }
- properties = getDirectChild(node.element, stylens, "table-properties");
- if(properties) {
- rule += getTableProperties(properties)
- }
- if(rule.length === 0) {
- return
- }
- rule = selector + "{" + rule + "}";
- try {
- sheet.insertRule(rule, sheet.cssRules.length)
- }catch(e) {
- throw e;
- }
- }
- function getNumberRule(node) {
- var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix") || "", prefix = node.getAttributeNS(stylens, "num-prefix") || "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content = "";
- if(prefix) {
- content += ' "' + prefix + '"'
- }
- if(stylemap.hasOwnProperty(style)) {
- content += " counter(list, " + stylemap[style] + ")"
- }else {
- if(style) {
- content += ' "' + style + '"'
- }else {
- content += " ''"
- }
- }
- return"content:" + content + ' "' + suffix + '"'
- }
- function getImageRule() {
- return"content: none;"
- }
- function getBulletRule(node) {
- var bulletChar = node.getAttributeNS(textns, "bullet-char");
- return"content: '" + bulletChar + "';"
- }
- function addListStyleRule(sheet, name, node, itemrule) {
- var selector = 'text|list[text|style-name="' + name + '"]', level = node.getAttributeNS(textns, "level"), itemSelector, listItemRule, listLevelProps = getDirectChild(node, stylens, "list-level-properties"), listLevelLabelAlign = getDirectChild(listLevelProps, stylens, "list-level-label-alignment"), bulletIndent, listIndent, bulletWidth, rule;
- if(listLevelLabelAlign) {
- bulletIndent = listLevelLabelAlign.getAttributeNS(fons, "text-indent");
- listIndent = listLevelLabelAlign.getAttributeNS(fons, "margin-left")
- }
- if(!bulletIndent) {
- bulletIndent = "-0.6cm"
- }
- if(bulletIndent.charAt(0) === "-") {
- bulletWidth = bulletIndent.substring(1)
- }else {
- bulletWidth = "-" + bulletIndent
- }
- level = level && parseInt(level, 10);
- while(level > 1) {
- selector += " > text|list-item > text|list";
- level -= 1
- }
- if(listIndent) {
- itemSelector = selector;
- itemSelector += " > text|list-item > *:not(text|list):first-child";
- listItemRule = itemSelector + "{";
- listItemRule += "margin-left:" + listIndent + ";";
- listItemRule += "}";
- try {
- sheet.insertRule(listItemRule, sheet.cssRules.length)
- }catch(e1) {
- runtime.log("cannot load rule: " + listItemRule)
- }
- }
- selector += " > text|list-item > *:not(text|list):first-child:before";
- rule = selector + "{" + itemrule + ";";
- rule += "counter-increment:list;";
- rule += "margin-left:" + bulletIndent + ";";
- rule += "width:" + bulletWidth + ";";
- rule += "display:inline-block}";
- try {
- sheet.insertRule(rule, sheet.cssRules.length)
- }catch(e2) {
- runtime.log("cannot load rule: " + rule)
- }
- }
- function addPageStyleRules(sheet, node) {
- var rule = "", imageProps, url, contentLayoutRule = "", pageSizeRule = "", props = getDirectChild(node, stylens, "page-layout-properties"), stylename, masterStyles, e, masterStyleName;
- if(!props) {
- return
- }
- stylename = node.getAttributeNS(stylens, "name");
- rule += applySimpleMapping(props, pageContentPropertySimpleMapping);
- imageProps = getDirectChild(props, stylens, "background-image");
- if(imageProps) {
- url = imageProps.getAttributeNS(xlinkns, "href");
- if(url) {
- rule += "background-image: url('odfkit:" + url + "');";
- rule += applySimpleMapping(imageProps, bgImageSimpleMapping)
- }
- }
- if(documentType === "presentation") {
- masterStyles = getDirectChild(node.parentNode.parentElement, officens, "master-styles");
- e = masterStyles && masterStyles.firstElementChild;
- while(e) {
- if(e.namespaceURI === stylens && (e.localName === "master-page" && e.getAttributeNS(stylens, "page-layout-name") === stylename)) {
- masterStyleName = e.getAttributeNS(stylens, "name");
- contentLayoutRule = "draw|page[draw|master-page-name=" + masterStyleName + "] {" + rule + "}";
- pageSizeRule = "office|body, draw|page[draw|master-page-name=" + masterStyleName + "] {" + applySimpleMapping(props, pageSizePropertySimpleMapping) + " }";
- try {
- sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
- sheet.insertRule(pageSizeRule, sheet.cssRules.length)
- }catch(e1) {
- throw e1;
- }
- }
- e = e.nextElementSibling
- }
- }else {
- if(documentType === "text") {
- contentLayoutRule = "office|text {" + rule + "}";
- rule = "";
- pageSizeRule = "office|body {" + "width: " + props.getAttributeNS(fons, "page-width") + ";" + "}";
- try {
- sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
- sheet.insertRule(pageSizeRule, sheet.cssRules.length)
- }catch(e2) {
- throw e2;
- }
- }
- }
- }
- function addListStyleRules(sheet, name, node) {
- var n = node.firstChild, e, itemrule;
- while(n) {
- if(n.namespaceURI === textns) {
- e = (n);
- if(n.localName === "list-level-style-number") {
- itemrule = getNumberRule(e);
- addListStyleRule(sheet, name, e, itemrule)
- }else {
- if(n.localName === "list-level-style-image") {
- itemrule = getImageRule();
- addListStyleRule(sheet, name, e, itemrule)
- }else {
- if(n.localName === "list-level-style-bullet") {
- itemrule = getBulletRule(e);
- addListStyleRule(sheet, name, e, itemrule)
- }
- }
- }
- }
- n = n.nextSibling
- }
- }
- function addRule(sheet, family, name, node) {
- if(family === "list") {
- addListStyleRules(sheet, name, node.element)
- }else {
- if(family === "page") {
- addPageStyleRules(sheet, node.element)
- }else {
- addStyleRule(sheet, family, name, node)
- }
- }
- }
- function addRules(sheet, family, name, node) {
- addRule(sheet, family, name, node);
- var n;
- for(n in node.derivedStyles) {
- if(node.derivedStyles.hasOwnProperty(n)) {
- addRules(sheet, family, n, node.derivedStyles[n])
- }
- }
- }
- this.style2css = function(doctype, stylesheet, fontFaceMap, styles, autostyles) {
- var doc, styletree, tree, rule, name, family, stylenodes, styleautonodes;
- while(stylesheet.cssRules.length) {
- stylesheet.deleteRule(stylesheet.cssRules.length - 1)
- }
- doc = null;
- if(styles) {
- doc = styles.ownerDocument;
- odfRoot = styles.parentNode
- }
- if(autostyles) {
- doc = autostyles.ownerDocument;
- odfRoot = autostyles.parentNode
- }
- if(!doc) {
- return
- }
- odf.Namespaces.forEachPrefix(function(prefix, ns) {
- rule = "@namespace " + prefix + " url(" + ns + ");";
- try {
- stylesheet.insertRule(rule, stylesheet.cssRules.length)
- }catch(ignore) {
- }
- });
- fontFaceDeclsMap = fontFaceMap;
- documentType = doctype;
- defaultFontSize = runtime.getWindow().getComputedStyle(document.body, null).getPropertyValue("font-size") || "12pt";
- stylenodes = getStyleMap(styles);
- styleautonodes = getStyleMap(autostyles);
- styletree = {};
- for(family in familynamespaceprefixes) {
- if(familynamespaceprefixes.hasOwnProperty(family)) {
- tree = styletree[family] = {};
- addStyleMapToStyleTree(stylenodes[family], tree);
- addStyleMapToStyleTree(styleautonodes[family], tree);
- for(name in tree) {
- if(tree.hasOwnProperty(name)) {
- addRules(stylesheet, family, name, tree[name])
- }
- }
- }
- }
- }
-};
-/*
-
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("xmldom.XPath");
-runtime.loadClass("odf.Namespaces");
odf.StyleInfo = function StyleInfo() {
var chartns = odf.Namespaces.chartns, dbns = odf.Namespaces.dbns, dr3dns = odf.Namespaces.dr3dns, drawns = odf.Namespaces.drawns, formns = odf.Namespaces.formns, numberns = odf.Namespaces.numberns, officens = odf.Namespaces.officens, presentationns = odf.Namespaces.presentationns, stylens = odf.Namespaces.stylens, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, nsprefixes = {"urn:oasis:names:tc:opendocument:xmlns:chart:1.0":"chart:", "urn:oasis:names:tc:opendocument:xmlns:database:1.0":"db:",
"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0":"dr3d:", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0":"draw:", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0":"fo:", "urn:oasis:names:tc:opendocument:xmlns:form:1.0":"form:", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0":"number:", "urn:oasis:names:tc:opendocument:xmlns:office:1.0":"office:", "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0":"presentation:", "urn:oasis:names:tc:opendocument:xmlns:style:1.0":"style:",
@@ -6259,205 +4721,6 @@ odf.StyleInfo = function StyleInfo() {
this.determineStylesForNode = determineStylesForNode;
elements = inverse()
};
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("odf.OdfUtils");
-odf.TextSerializer = function TextSerializer() {
- var self = this, odfUtils = new odf.OdfUtils;
- function serializeNode(node) {
- var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, nodeType = node.nodeType, child;
- if(accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) {
- child = node.firstChild;
- while(child) {
- s += serializeNode(child);
- child = child.nextSibling
- }
- }
- if(accept === NodeFilter.FILTER_ACCEPT) {
- if(nodeType === Node.ELEMENT_NODE && odfUtils.isParagraph(node)) {
- s += "\n"
- }else {
- if(nodeType === Node.TEXT_NODE && node.textContent) {
- s += node.textContent
- }
- }
- }
- return s
- }
- this.filter = null;
- this.writeToString = function(node) {
- var plainText;
- if(!node) {
- return""
- }
- plainText = serializeNode(node);
- if(plainText[plainText.length - 1] === "\n") {
- plainText = plainText.substr(0, plainText.length - 1)
- }
- return plainText
- }
-};
-/*
-
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("core.PositionFilter");
-runtime.loadClass("odf.OdfUtils");
-ops.TextPositionFilter = function TextPositionFilter(getRootNode) {
- var odfUtils = new odf.OdfUtils, ELEMENT_NODE = Node.ELEMENT_NODE, TEXT_NODE = Node.TEXT_NODE, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
- function checkLeftRight(container, leftNode, rightNode) {
- var r, firstPos, rightOfChar;
- if(leftNode) {
- if(odfUtils.isInlineRoot(leftNode) && odfUtils.isGroupingElement(rightNode)) {
- return FILTER_REJECT
- }
- r = odfUtils.lookLeftForCharacter(leftNode);
- if(r === 1) {
- return FILTER_ACCEPT
- }
- if(r === 2 && (odfUtils.scanRightForAnyCharacter(rightNode) || odfUtils.scanRightForAnyCharacter(odfUtils.nextNode(container)))) {
- return FILTER_ACCEPT
- }
- }
- firstPos = leftNode === null && odfUtils.isParagraph(container);
- rightOfChar = odfUtils.lookRightForCharacter(rightNode);
- if(firstPos) {
- if(rightOfChar) {
- return FILTER_ACCEPT
- }
- return odfUtils.scanRightForAnyCharacter(rightNode) ? FILTER_REJECT : FILTER_ACCEPT
- }
- if(!rightOfChar) {
- return FILTER_REJECT
- }
- leftNode = leftNode || odfUtils.previousNode(container);
- return odfUtils.scanLeftForAnyCharacter(leftNode) ? FILTER_REJECT : FILTER_ACCEPT
- }
- this.acceptPosition = function(iterator) {
- var container = iterator.container(), nodeType = container.nodeType, offset, text, leftChar, rightChar, leftNode, rightNode, r;
- if(nodeType !== ELEMENT_NODE && nodeType !== TEXT_NODE) {
- return FILTER_REJECT
- }
- if(nodeType === TEXT_NODE) {
- if(!odfUtils.isGroupingElement(container.parentNode) || odfUtils.isWithinTrackedChanges(container.parentNode, getRootNode())) {
- return FILTER_REJECT
- }
- offset = iterator.unfilteredDomOffset();
- text = container.data;
- runtime.assert(offset !== text.length, "Unexpected offset.");
- if(offset > 0) {
- leftChar = (text[offset - 1]);
- if(!odfUtils.isODFWhitespace(leftChar)) {
- return FILTER_ACCEPT
- }
- if(offset > 1) {
- leftChar = (text[offset - 2]);
- if(!odfUtils.isODFWhitespace(leftChar)) {
- r = FILTER_ACCEPT
- }else {
- if(!odfUtils.isODFWhitespace(text.substr(0, offset))) {
- return FILTER_REJECT
- }
- }
- }else {
- leftNode = odfUtils.previousNode(container);
- if(odfUtils.scanLeftForNonSpace(leftNode)) {
- r = FILTER_ACCEPT
- }
- }
- if(r === FILTER_ACCEPT) {
- return odfUtils.isTrailingWhitespace((container), offset) ? FILTER_REJECT : FILTER_ACCEPT
- }
- rightChar = (text[offset]);
- if(odfUtils.isODFWhitespace(rightChar)) {
- return FILTER_REJECT
- }
- return odfUtils.scanLeftForAnyCharacter(odfUtils.previousNode(container)) ? FILTER_REJECT : FILTER_ACCEPT
- }
- leftNode = iterator.leftNode();
- rightNode = container;
- container = (container.parentNode);
- r = checkLeftRight(container, leftNode, rightNode)
- }else {
- if(!odfUtils.isGroupingElement(container) || odfUtils.isWithinTrackedChanges(container, getRootNode())) {
- r = FILTER_REJECT
- }else {
- leftNode = iterator.leftNode();
- rightNode = iterator.rightNode();
- r = checkLeftRight(container, leftNode, rightNode)
- }
- }
- return r
- }
-};
if(typeof Object.create !== "function") {
Object["create"] = function(o) {
var F = function() {
@@ -6593,76 +4856,6 @@ xmldom.LSSerializer = function LSSerializer() {
};
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("xmldom.LSSerializer");
-runtime.loadClass("odf.OdfNodeFilter");
-runtime.loadClass("odf.TextSerializer");
-gui.Clipboard = function Clipboard() {
- var xmlSerializer, textSerializer, filter;
- this.setDataFromRange = function(e, range) {
- var result = true, setDataResult, clipboard = e.clipboardData, window = runtime.getWindow(), document = range.startContainer.ownerDocument, fragmentContainer;
- if(!clipboard && window) {
- clipboard = window.clipboardData
- }
- if(clipboard) {
- fragmentContainer = document.createElement("span");
- fragmentContainer.appendChild(range.cloneContents());
- setDataResult = clipboard.setData("text/plain", textSerializer.writeToString(fragmentContainer));
- result = result && setDataResult;
- setDataResult = clipboard.setData("text/html", xmlSerializer.writeToString(fragmentContainer, odf.Namespaces.namespaceMap));
- result = result && setDataResult;
- e.preventDefault()
- }else {
- result = false
- }
- return result
- };
- function init() {
- xmlSerializer = new xmldom.LSSerializer;
- textSerializer = new odf.TextSerializer;
- filter = new odf.OdfNodeFilter;
- xmlSerializer.filter = filter;
- textSerializer.filter = filter
- }
- init()
-};
-/*
-
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
@@ -6698,13 +4891,6 @@ gui.Clipboard = function Clipboard() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.Base64");
-runtime.loadClass("core.Zip");
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("xmldom.LSSerializer");
-runtime.loadClass("odf.StyleInfo");
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("odf.OdfNodeFilter");
(function() {
var styleInfo = new odf.StyleInfo, domUtils = new core.DomUtils, officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", manifestns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", webodfns = "urn:webodf:names:scope", stylens = odf.Namespaces.stylens, nodeorder = ["meta", "settings", "scripts", "font-face-decls", "styles", "automatic-styles", "master-styles", "body"], automaticStylePrefix = (new Date).getTime() + "_webodf_", base64 = new core.Base64, documentStylesScope = "document-styles",
documentContentScope = "document-content";
@@ -6784,6 +4970,9 @@ runtime.loadClass("odf.OdfNodeFilter");
odf.ODFDocumentElement.prototype.styles;
odf.ODFDocumentElement.namespaceURI = officens;
odf.ODFDocumentElement.localName = "document";
+ odf.AnnotationElement = function AnnotationElement() {
+ };
+ odf.AnnotationElement.prototype.annotationEndElement;
odf.OdfPart = function OdfPart(name, mimetype, container, zip) {
var self = this;
this.size = 0;
@@ -6848,6 +5037,43 @@ runtime.loadClass("odf.OdfNodeFilter");
n = next
}
}
+ function linkAnnotationStartAndEndElements(rootElement) {
+ var document = rootElement.ownerDocument, annotationStarts = {}, n, name, annotationStart, nodeIterator = document.createNodeIterator(rootElement, NodeFilter.SHOW_ELEMENT, null, false);
+ n = (nodeIterator.nextNode());
+ while(n) {
+ if(n.namespaceURI === officens) {
+ if(n.localName === "annotation") {
+ name = n.getAttributeNS(officens, "name");
+ if(name) {
+ if(annotationStarts.hasOwnProperty(name)) {
+ runtime.log("Warning: annotation name used more than once with <office:annotation/>: '" + name + "'")
+ }else {
+ annotationStarts[name] = n
+ }
+ }
+ }else {
+ if(n.localName === "annotation-end") {
+ name = n.getAttributeNS(officens, "name");
+ if(name) {
+ if(annotationStarts.hasOwnProperty(name)) {
+ annotationStart = (annotationStarts[name]);
+ if(!annotationStart.annotationEndElement) {
+ annotationStart.annotationEndElement = n
+ }else {
+ runtime.log("Warning: annotation name used more than once with <office:annotation-end/>: '" + name + "'")
+ }
+ }else {
+ runtime.log("Warning: annotation end without an annotation start, name: '" + name + "'")
+ }
+ }else {
+ runtime.log("Warning: annotation end without a name found")
+ }
+ }
+ }
+ }
+ n = (nodeIterator.nextNode())
+ }
+ }
function setAutomaticStylesScope(stylesRootElement, scope) {
var n = stylesRootElement && stylesRootElement.firstChild;
while(n) {
@@ -6994,7 +5220,8 @@ runtime.loadClass("odf.OdfNodeFilter");
root.automaticStyles = getDirectChild(root, officens, "automatic-styles");
root.masterStyles = getDirectChild(root, officens, "master-styles");
root.body = getDirectChild(root, officens, "body");
- root.meta = getDirectChild(root, officens, "meta")
+ root.meta = getDirectChild(root, officens, "meta");
+ linkAnnotationStartAndEndElements(root)
}
function handleFlatXml(xmldoc) {
var root = importRootNode(xmldoc);
@@ -7109,6 +5336,7 @@ runtime.loadClass("odf.OdfNodeFilter");
loadNextComponent(remainingComponents)
})
}else {
+ linkAnnotationStartAndEndElements(self.rootElement);
setState(OdfContainer.DONE)
}
}
@@ -7150,7 +5378,9 @@ runtime.loadClass("odf.OdfNodeFilter");
function serializeSettingsXml() {
var serializer = new xmldom.LSSerializer, s = createDocumentElement("document-settings");
serializer.filter = new odf.OdfNodeFilter;
- s += serializer.writeToString(self.rootElement.settings, odf.Namespaces.namespaceMap);
+ if(self.rootElement.settings.firstElementChild) {
+ s += serializer.writeToString(self.rootElement.settings, odf.Namespaces.namespaceMap)
+ }
s += "</office:document-settings>";
return s
}
@@ -7265,6 +5495,11 @@ runtime.loadClass("odf.OdfNodeFilter");
addToplevelElement("masterStyles", "master-styles");
addToplevelElement("body");
root.body.appendChild(text);
+ partMimetypes["/"] = "application/vnd.oasis.opendocument.text";
+ partMimetypes["settings.xml"] = "text/xml";
+ partMimetypes["meta.xml"] = "text/xml";
+ partMimetypes["styles.xml"] = "text/xml";
+ partMimetypes["content.xml"] = "text/xml";
setState(OdfContainer.DONE);
return emptyzip
}
@@ -7381,9 +5616,959 @@ runtime.loadClass("odf.OdfNodeFilter");
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.Base64");
-runtime.loadClass("xmldom.XPath");
-runtime.loadClass("odf.OdfContainer");
+odf.OdfUtils = function OdfUtils() {
+ var textns = odf.Namespaces.textns, drawns = odf.Namespaces.drawns, xlinkns = odf.Namespaces.xlinkns, whitespaceOnly = /^\s*$/, domUtils = new core.DomUtils;
+ function isImage(e) {
+ var name = e && e.localName;
+ return name === "image" && e.namespaceURI === drawns
+ }
+ this.isImage = isImage;
+ function isCharacterFrame(e) {
+ return e !== null && (e.nodeType === Node.ELEMENT_NODE && (e.localName === "frame" && (e.namespaceURI === drawns && (e).getAttributeNS(textns, "anchor-type") === "as-char")))
+ }
+ this.isCharacterFrame = isCharacterFrame;
+ function isAnnotation(e) {
+ var name = e && e.localName;
+ return name === "annotation" && e.namespaceURI === odf.Namespaces.officens
+ }
+ function isAnnotationWrapper(e) {
+ var name = e && e.localName;
+ return name === "div" && (e).className === "annotationWrapper"
+ }
+ function isInlineRoot(e) {
+ return isAnnotation(e) || isAnnotationWrapper(e)
+ }
+ this.isInlineRoot = isInlineRoot;
+ this.isTextSpan = function(e) {
+ var name = e && e.localName;
+ return name === "span" && e.namespaceURI === textns
+ };
+ function isHyperlink(node) {
+ var name = node && node.localName;
+ return name === "a" && node.namespaceURI === textns
+ }
+ this.isHyperlink = isHyperlink;
+ this.getHyperlinkTarget = function(element) {
+ return element.getAttributeNS(xlinkns, "href")
+ };
+ function isParagraph(e) {
+ var name = e && e.localName;
+ return(name === "p" || name === "h") && e.namespaceURI === textns
+ }
+ this.isParagraph = isParagraph;
+ function getParagraphElement(node) {
+ while(node && !isParagraph(node)) {
+ node = node.parentNode
+ }
+ return(node)
+ }
+ this.getParagraphElement = getParagraphElement;
+ this.isWithinTrackedChanges = function(node, container) {
+ while(node && node !== container) {
+ if(node.namespaceURI === textns && node.localName === "tracked-changes") {
+ return true
+ }
+ node = node.parentNode
+ }
+ return false
+ };
+ this.isListItem = function(e) {
+ var name = e && e.localName;
+ return name === "list-item" && e.namespaceURI === textns
+ };
+ this.isLineBreak = function(e) {
+ var name = e && e.localName;
+ return name === "line-break" && e.namespaceURI === textns
+ };
+ function isODFWhitespace(text) {
+ return/^[ \t\r\n]+$/.test(text)
+ }
+ this.isODFWhitespace = isODFWhitespace;
+ function isGroupingElement(n) {
+ if(n === null || n.nodeType !== Node.ELEMENT_NODE) {
+ return false
+ }
+ var e = (n), localName = e.localName;
+ return/^(span|p|h|a|meta)$/.test(localName) && e.namespaceURI === textns || localName === "span" && e.className === "annotationHighlight"
+ }
+ this.isGroupingElement = isGroupingElement;
+ function isCharacterElement(e) {
+ var n = e && e.localName, ns, r = false;
+ if(n) {
+ ns = e.namespaceURI;
+ if(ns === textns) {
+ r = n === "s" || (n === "tab" || n === "line-break")
+ }
+ }
+ return r
+ }
+ this.isCharacterElement = isCharacterElement;
+ function isAnchoredAsCharacterElement(e) {
+ return isCharacterElement(e) || (isCharacterFrame(e) || isInlineRoot(e))
+ }
+ this.isAnchoredAsCharacterElement = isAnchoredAsCharacterElement;
+ function isSpaceElement(e) {
+ var n = e && e.localName, ns, r = false;
+ if(n) {
+ ns = e.namespaceURI;
+ if(ns === textns) {
+ r = n === "s"
+ }
+ }
+ return r
+ }
+ this.isSpaceElement = isSpaceElement;
+ function firstChild(node) {
+ while(node.firstChild !== null && isGroupingElement(node)) {
+ node = node.firstChild
+ }
+ return node
+ }
+ this.firstChild = firstChild;
+ function lastChild(node) {
+ while(node.lastChild !== null && isGroupingElement(node)) {
+ node = node.lastChild
+ }
+ return node
+ }
+ this.lastChild = lastChild;
+ function previousNode(node) {
+ while(!isParagraph(node) && node.previousSibling === null) {
+ node = (node.parentNode)
+ }
+ return isParagraph(node) ? null : lastChild((node.previousSibling))
+ }
+ this.previousNode = previousNode;
+ function nextNode(node) {
+ while(!isParagraph(node) && node.nextSibling === null) {
+ node = (node.parentNode)
+ }
+ return isParagraph(node) ? null : firstChild((node.nextSibling))
+ }
+ this.nextNode = nextNode;
+ function scanLeftForNonSpace(node) {
+ var r = false, text;
+ while(node) {
+ if(node.nodeType === Node.TEXT_NODE) {
+ text = (node);
+ if(text.length === 0) {
+ node = previousNode(text)
+ }else {
+ return!isODFWhitespace(text.data.substr(text.length - 1, 1))
+ }
+ }else {
+ if(isAnchoredAsCharacterElement(node)) {
+ r = isSpaceElement(node) === false;
+ node = null
+ }else {
+ node = previousNode(node)
+ }
+ }
+ }
+ return r
+ }
+ this.scanLeftForNonSpace = scanLeftForNonSpace;
+ function lookLeftForCharacter(node) {
+ var text, r = 0, tl = 0;
+ if(node.nodeType === Node.TEXT_NODE) {
+ tl = (node).length
+ }
+ if(tl > 0) {
+ text = (node).data;
+ if(!isODFWhitespace(text.substr(tl - 1, 1))) {
+ r = 1
+ }else {
+ if(tl === 1) {
+ r = scanLeftForNonSpace(previousNode(node)) ? 2 : 0
+ }else {
+ r = isODFWhitespace(text.substr(tl - 2, 1)) ? 0 : 2
+ }
+ }
+ }else {
+ if(isAnchoredAsCharacterElement(node)) {
+ r = 1
+ }
+ }
+ return r
+ }
+ this.lookLeftForCharacter = lookLeftForCharacter;
+ function lookRightForCharacter(node) {
+ var r = false, l = 0;
+ if(node && node.nodeType === Node.TEXT_NODE) {
+ l = (node).length
+ }
+ if(l > 0) {
+ r = !isODFWhitespace((node).data.substr(0, 1))
+ }else {
+ if(isAnchoredAsCharacterElement(node)) {
+ r = true
+ }
+ }
+ return r
+ }
+ this.lookRightForCharacter = lookRightForCharacter;
+ function scanLeftForAnyCharacter(node) {
+ var r = false, l;
+ node = node && lastChild(node);
+ while(node) {
+ if(node.nodeType === Node.TEXT_NODE) {
+ l = (node).length
+ }else {
+ l = 0
+ }
+ if(l > 0 && !isODFWhitespace((node).data)) {
+ r = true;
+ break
+ }
+ if(isAnchoredAsCharacterElement(node)) {
+ r = true;
+ break
+ }
+ node = previousNode(node)
+ }
+ return r
+ }
+ this.scanLeftForAnyCharacter = scanLeftForAnyCharacter;
+ function scanRightForAnyCharacter(node) {
+ var r = false, l;
+ node = node && firstChild(node);
+ while(node) {
+ if(node.nodeType === Node.TEXT_NODE) {
+ l = (node).length
+ }else {
+ l = 0
+ }
+ if(l > 0 && !isODFWhitespace((node).data)) {
+ r = true;
+ break
+ }
+ if(isAnchoredAsCharacterElement(node)) {
+ r = true;
+ break
+ }
+ node = nextNode(node)
+ }
+ return r
+ }
+ this.scanRightForAnyCharacter = scanRightForAnyCharacter;
+ function isTrailingWhitespace(textnode, offset) {
+ if(!isODFWhitespace(textnode.data.substr(offset))) {
+ return false
+ }
+ return!scanRightForAnyCharacter(nextNode(textnode))
+ }
+ this.isTrailingWhitespace = isTrailingWhitespace;
+ function isSignificantWhitespace(textNode, offset) {
+ var text = textNode.data, result;
+ if(!isODFWhitespace(text[offset])) {
+ return false
+ }
+ if(isAnchoredAsCharacterElement(textNode.parentNode)) {
+ return false
+ }
+ if(offset > 0) {
+ if(!isODFWhitespace(text[offset - 1])) {
+ result = true
+ }
+ }else {
+ if(scanLeftForNonSpace(previousNode(textNode))) {
+ result = true
+ }
+ }
+ if(result === true) {
+ return isTrailingWhitespace(textNode, offset) ? false : true
+ }
+ return false
+ }
+ this.isSignificantWhitespace = isSignificantWhitespace;
+ this.isDowngradableSpaceElement = function(node) {
+ if(node.namespaceURI === textns && node.localName === "s") {
+ return scanLeftForNonSpace(previousNode(node)) && scanRightForAnyCharacter(nextNode(node))
+ }
+ return false
+ };
+ function getFirstNonWhitespaceChild(node) {
+ var child = node && node.firstChild;
+ while(child && (child.nodeType === Node.TEXT_NODE && whitespaceOnly.test(child.nodeValue))) {
+ child = child.nextSibling
+ }
+ return child
+ }
+ this.getFirstNonWhitespaceChild = getFirstNonWhitespaceChild;
+ function parseLength(length) {
+ var re = /(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/, m = re.exec(length);
+ if(!m) {
+ return null
+ }
+ return{value:parseFloat(m[1]), unit:m[3]}
+ }
+ this.parseLength = parseLength;
+ function parsePositiveLength(length) {
+ var result = parseLength(length);
+ if(result && (result.value <= 0 || result.unit === "%")) {
+ return null
+ }
+ return result
+ }
+ function parseNonNegativeLength(length) {
+ var result = parseLength(length);
+ if(result && (result.value < 0 || result.unit === "%")) {
+ return null
+ }
+ return result
+ }
+ this.parseNonNegativeLength = parseNonNegativeLength;
+ function parsePercentage(length) {
+ var result = parseLength(length);
+ if(result && result.unit !== "%") {
+ return null
+ }
+ return result
+ }
+ function parseFoFontSize(fontSize) {
+ return parsePositiveLength(fontSize) || parsePercentage(fontSize)
+ }
+ this.parseFoFontSize = parseFoFontSize;
+ function parseFoLineHeight(lineHeight) {
+ return parseNonNegativeLength(lineHeight) || parsePercentage(lineHeight)
+ }
+ this.parseFoLineHeight = parseFoLineHeight;
+ function isTextContentContainingNode(node) {
+ switch(node.namespaceURI) {
+ case odf.Namespaces.drawns:
+ ;
+ case odf.Namespaces.svgns:
+ ;
+ case odf.Namespaces.dr3dns:
+ return false;
+ case odf.Namespaces.textns:
+ switch(node.localName) {
+ case "note-body":
+ ;
+ case "ruby-text":
+ return false
+ }
+ break;
+ case odf.Namespaces.officens:
+ switch(node.localName) {
+ case "annotation":
+ ;
+ case "binary-data":
+ ;
+ case "event-listeners":
+ return false
+ }
+ break;
+ default:
+ switch(node.localName) {
+ case "cursor":
+ ;
+ case "editinfo":
+ return false
+ }
+ break
+ }
+ return true
+ }
+ this.isTextContentContainingNode = isTextContentContainingNode;
+ function isSignificantTextContent(textNode) {
+ return Boolean(getParagraphElement(textNode) && (!isODFWhitespace(textNode.textContent) || isSignificantWhitespace(textNode, 0)))
+ }
+ function removePartiallyContainedNodes(range, nodes) {
+ while(nodes.length > 0 && !domUtils.rangeContainsNode(range, (nodes[0]))) {
+ nodes.shift()
+ }
+ while(nodes.length > 0 && !domUtils.rangeContainsNode(range, (nodes[nodes.length - 1]))) {
+ nodes.pop()
+ }
+ }
+ function getTextNodes(range, includePartial) {
+ var textNodes;
+ function nodeFilter(node) {
+ var result = NodeFilter.FILTER_REJECT;
+ if(node.nodeType === Node.TEXT_NODE) {
+ if(isSignificantTextContent((node))) {
+ result = NodeFilter.FILTER_ACCEPT
+ }
+ }else {
+ if(isTextContentContainingNode(node)) {
+ result = NodeFilter.FILTER_SKIP
+ }
+ }
+ return result
+ }
+ textNodes = domUtils.getNodesInRange(range, nodeFilter, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
+ if(!includePartial) {
+ removePartiallyContainedNodes(range, textNodes)
+ }
+ return textNodes
+ }
+ this.getTextNodes = getTextNodes;
+ function getTextElements(range, includePartial, includeInsignificantWhitespace) {
+ var elements;
+ function nodeFilter(node) {
+ var result = NodeFilter.FILTER_REJECT;
+ if(isCharacterElement(node.parentNode) || isInlineRoot(node)) {
+ result = NodeFilter.FILTER_REJECT
+ }else {
+ if(node.nodeType === Node.TEXT_NODE) {
+ if(includeInsignificantWhitespace || isSignificantTextContent((node))) {
+ result = NodeFilter.FILTER_ACCEPT
+ }
+ }else {
+ if(isAnchoredAsCharacterElement(node)) {
+ result = NodeFilter.FILTER_ACCEPT
+ }else {
+ if(isTextContentContainingNode(node) || isGroupingElement(node)) {
+ result = NodeFilter.FILTER_SKIP
+ }
+ }
+ }
+ }
+ return result
+ }
+ elements = domUtils.getNodesInRange(range, nodeFilter, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT);
+ if(!includePartial) {
+ removePartiallyContainedNodes(range, elements)
+ }
+ return elements
+ }
+ this.getTextElements = getTextElements;
+ function prependParentContainers(startContainer, elements, filter) {
+ var container = startContainer;
+ while(container) {
+ if(filter(container)) {
+ if(elements[0] !== container) {
+ elements.unshift(container)
+ }
+ break
+ }
+ if(isInlineRoot(container)) {
+ break
+ }
+ container = container.parentNode
+ }
+ }
+ this.getParagraphElements = function(range) {
+ var elements;
+ function nodeFilter(node) {
+ var result = NodeFilter.FILTER_REJECT;
+ if(isParagraph(node)) {
+ result = NodeFilter.FILTER_ACCEPT
+ }else {
+ if(isTextContentContainingNode(node) || isGroupingElement(node)) {
+ result = NodeFilter.FILTER_SKIP
+ }
+ }
+ return result
+ }
+ elements = domUtils.getNodesInRange(range, nodeFilter, NodeFilter.SHOW_ELEMENT);
+ prependParentContainers((range.startContainer), elements, isParagraph);
+ return elements
+ };
+ this.getImageElements = function(range) {
+ var elements;
+ function nodeFilter(node) {
+ var result = NodeFilter.FILTER_SKIP;
+ if(isImage(node)) {
+ result = NodeFilter.FILTER_ACCEPT
+ }
+ return result
+ }
+ elements = domUtils.getNodesInRange(range, nodeFilter, NodeFilter.SHOW_ELEMENT);
+ prependParentContainers((range.startContainer), elements, isImage);
+ return elements
+ };
+ function getRightNode(container, offset) {
+ var node = container;
+ if(offset < node.childNodes.length - 1) {
+ node = (node.childNodes[offset + 1])
+ }else {
+ while(!node.nextSibling) {
+ node = node.parentNode
+ }
+ node = node.nextSibling
+ }
+ while(node.firstChild) {
+ node = node.firstChild
+ }
+ return node
+ }
+ this.getHyperlinkElements = function(range) {
+ var links = [], newRange = (range.cloneRange()), node, textNodes;
+ if(range.collapsed && range.endContainer.nodeType === Node.ELEMENT_NODE) {
+ node = getRightNode(range.endContainer, range.endOffset);
+ if(node.nodeType === Node.TEXT_NODE) {
+ newRange.setEnd(node, 1)
+ }
+ }
+ textNodes = getTextElements(newRange, true, false);
+ textNodes.forEach(function(node) {
+ var parent = node.parentNode;
+ while(!isParagraph(parent)) {
+ if(isHyperlink(parent) && links.indexOf(parent) === -1) {
+ links.push(parent);
+ break
+ }
+ parent = parent.parentNode
+ }
+ });
+ newRange.detach();
+ return links
+ }
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.AnnotatableCanvas = function AnnotatableCanvas() {
+};
+gui.AnnotatableCanvas.prototype.refreshSize = function() {
+};
+gui.AnnotatableCanvas.prototype.getZoomLevel = function() {
+};
+gui.AnnotatableCanvas.prototype.getSizer = function() {
+};
+gui.AnnotationViewManager = function AnnotationViewManager(canvas, odfFragment, annotationsPane, showAnnotationRemoveButton) {
+ var annotations = [], doc = odfFragment.ownerDocument, odfUtils = new odf.OdfUtils, CONNECTOR_MARGIN = 30, NOTE_MARGIN = 20, window = runtime.getWindow();
+ runtime.assert(Boolean(window), "Expected to be run in an environment which has a global window, like a browser.");
+ function wrapAnnotation(annotation) {
+ var annotationWrapper = doc.createElement("div"), annotationNote = doc.createElement("div"), connectorHorizontal = doc.createElement("div"), connectorAngular = doc.createElement("div"), removeButton;
+ annotationWrapper.className = "annotationWrapper";
+ annotation.parentNode.insertBefore(annotationWrapper, annotation);
+ annotationNote.className = "annotationNote";
+ annotationNote.appendChild(annotation);
+ if(showAnnotationRemoveButton) {
+ removeButton = doc.createElement("div");
+ removeButton.className = "annotationRemoveButton";
+ annotationNote.appendChild(removeButton)
+ }
+ connectorHorizontal.className = "annotationConnector horizontal";
+ connectorAngular.className = "annotationConnector angular";
+ annotationWrapper.appendChild(annotationNote);
+ annotationWrapper.appendChild(connectorHorizontal);
+ annotationWrapper.appendChild(connectorAngular)
+ }
+ function unwrapAnnotation(annotation) {
+ var annotationWrapper = annotation.parentNode.parentNode;
+ if(annotationWrapper.localName === "div") {
+ annotationWrapper.parentNode.insertBefore(annotation, annotationWrapper);
+ annotationWrapper.parentNode.removeChild(annotationWrapper)
+ }
+ }
+ function highlightAnnotation(annotation) {
+ var annotationEnd = annotation.annotationEndElement, range = doc.createRange(), annotationName = annotation.getAttributeNS(odf.Namespaces.officens, "name"), textNodes;
+ if(annotationEnd) {
+ range.setStart(annotation, annotation.childNodes.length);
+ range.setEnd(annotationEnd, 0);
+ textNodes = odfUtils.getTextNodes(range, false);
+ textNodes.forEach(function(n) {
+ var container = doc.createElement("span");
+ container.className = "annotationHighlight";
+ container.setAttribute("annotation", annotationName);
+ n.parentNode.insertBefore(container, n);
+ container.appendChild(n)
+ })
+ }
+ range.detach()
+ }
+ function unhighlightAnnotation(annotation) {
+ var annotationName = annotation.getAttributeNS(odf.Namespaces.officens, "name"), highlightSpans = doc.querySelectorAll('span.annotationHighlight[annotation="' + annotationName + '"]'), i, container;
+ for(i = 0;i < highlightSpans.length;i += 1) {
+ container = highlightSpans.item(i);
+ while(container.firstChild) {
+ container.parentNode.insertBefore(container.firstChild, container)
+ }
+ container.parentNode.removeChild(container)
+ }
+ }
+ function lineDistance(point1, point2) {
+ var xs = 0, ys = 0;
+ xs = point2.x - point1.x;
+ xs = xs * xs;
+ ys = point2.y - point1.y;
+ ys = ys * ys;
+ return Math.sqrt(xs + ys)
+ }
+ function renderAnnotation(annotation) {
+ var annotationNote = (annotation.parentNode), connectorHorizontal = annotationNote.nextElementSibling, connectorAngular = connectorHorizontal.nextElementSibling, annotationWrapper = (annotationNote.parentNode), connectorAngle = 0, previousAnnotation = annotations[annotations.indexOf(annotation) - 1], previousRect, zoomLevel = canvas.getZoomLevel();
+ annotationNote.style.left = (annotationsPane.getBoundingClientRect().left - annotationWrapper.getBoundingClientRect().left) / zoomLevel + "px";
+ annotationNote.style.width = annotationsPane.getBoundingClientRect().width / zoomLevel + "px";
+ connectorHorizontal.style.width = parseFloat(annotationNote.style.left) - CONNECTOR_MARGIN + "px";
+ if(previousAnnotation) {
+ previousRect = (previousAnnotation.parentNode).getBoundingClientRect();
+ if((annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel <= NOTE_MARGIN) {
+ annotationNote.style.top = Math.abs(annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel + NOTE_MARGIN + "px"
+ }else {
+ annotationNote.style.top = "0px"
+ }
+ }
+ connectorAngular.style.left = connectorHorizontal.getBoundingClientRect().width / zoomLevel + "px";
+ connectorAngular.style.width = lineDistance({x:connectorAngular.getBoundingClientRect().left / zoomLevel, y:connectorAngular.getBoundingClientRect().top / zoomLevel}, {x:annotationNote.getBoundingClientRect().left / zoomLevel, y:annotationNote.getBoundingClientRect().top / zoomLevel}) + "px";
+ connectorAngle = Math.asin((annotationNote.getBoundingClientRect().top - connectorAngular.getBoundingClientRect().top) / (zoomLevel * parseFloat(connectorAngular.style.width)));
+ connectorAngular.style.transform = "rotate(" + connectorAngle + "rad)";
+ connectorAngular.style.MozTransform = "rotate(" + connectorAngle + "rad)";
+ connectorAngular.style.WebkitTransform = "rotate(" + connectorAngle + "rad)";
+ connectorAngular.style.msTransform = "rotate(" + connectorAngle + "rad)"
+ }
+ function showAnnotationsPane(show) {
+ var sizer = canvas.getSizer();
+ if(show) {
+ annotationsPane.style.display = "inline-block";
+ sizer.style.paddingRight = window.getComputedStyle(annotationsPane).width
+ }else {
+ annotationsPane.style.display = "none";
+ sizer.style.paddingRight = 0
+ }
+ canvas.refreshSize()
+ }
+ function sortAnnotations() {
+ annotations.sort(function(a, b) {
+ if((a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0) {
+ return-1
+ }
+ return 1
+ })
+ }
+ function rerenderAnnotations() {
+ var i;
+ for(i = 0;i < annotations.length;i += 1) {
+ renderAnnotation(annotations[i])
+ }
+ }
+ this.rerenderAnnotations = rerenderAnnotations;
+ function getMinimumHeightForAnnotationPane() {
+ if(annotationsPane.style.display !== "none" && annotations.length > 0) {
+ return((annotations[annotations.length - 1].parentNode).getBoundingClientRect().bottom - annotationsPane.getBoundingClientRect().top) / canvas.getZoomLevel() + "px"
+ }
+ return null
+ }
+ this.getMinimumHeightForAnnotationPane = getMinimumHeightForAnnotationPane;
+ function addAnnotation(annotation) {
+ showAnnotationsPane(true);
+ annotations.push(annotation);
+ sortAnnotations();
+ wrapAnnotation(annotation);
+ if(annotation.annotationEndElement) {
+ highlightAnnotation(annotation)
+ }
+ rerenderAnnotations()
+ }
+ this.addAnnotation = addAnnotation;
+ function forgetAnnotation(annotation) {
+ var index = annotations.indexOf(annotation);
+ unwrapAnnotation(annotation);
+ unhighlightAnnotation(annotation);
+ if(index !== -1) {
+ annotations.splice(index, 1)
+ }
+ if(annotations.length === 0) {
+ showAnnotationsPane(false)
+ }
+ }
+ function forgetAnnotations() {
+ while(annotations.length) {
+ forgetAnnotation(annotations[0])
+ }
+ }
+ this.forgetAnnotations = forgetAnnotations
+};
+/*
+
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+(function() {
+ function Point(x, y) {
+ var self = this;
+ this.getDistance = function(point) {
+ var xOffset = self.x - point.x, yOffset = self.y - point.y;
+ return Math.sqrt(xOffset * xOffset + yOffset * yOffset)
+ };
+ this.getCenter = function(point) {
+ return new Point((self.x + point.x) / 2, (self.y + point.y) / 2)
+ };
+ this.x;
+ this.y;
+ function init() {
+ self.x = x;
+ self.y = y
+ }
+ init()
+ }
+ gui.ZoomHelper = function() {
+ var zoomableElement, panPoint, previousPanPoint, firstPinchDistance, zoom, previousZoom, maxZoom = 4, offsetParent, events = new core.EventNotifier([gui.ZoomHelper.signalZoomChanged]), gestures = {NONE:0, SCROLL:1, PINCH:2}, currentGesture = gestures.NONE, requiresCustomScrollBars = runtime.getWindow().hasOwnProperty("ontouchstart");
+ function applyCSSTransform(x, y, scale, is3D) {
+ var transformCommand;
+ if(is3D) {
+ transformCommand = "translate3d(" + x + "px, " + y + "px, 0) scale3d(" + scale + ", " + scale + ", 1)"
+ }else {
+ transformCommand = "translate(" + x + "px, " + y + "px) scale(" + scale + ")"
+ }
+ zoomableElement.style.WebkitTransform = transformCommand;
+ zoomableElement.style.MozTransform = transformCommand;
+ zoomableElement.style.msTransform = transformCommand;
+ zoomableElement.style.OTransform = transformCommand;
+ zoomableElement.style.transform = transformCommand
+ }
+ function applyTransform(is3D) {
+ if(is3D) {
+ applyCSSTransform(-panPoint.x, -panPoint.y, zoom, true)
+ }else {
+ applyCSSTransform(0, 0, zoom, true);
+ applyCSSTransform(0, 0, zoom, false)
+ }
+ }
+ function applyFastTransform() {
+ applyTransform(true)
+ }
+ function applyDetailedTransform() {
+ applyTransform(false)
+ }
+ function enableScrollBars(enable) {
+ if(!offsetParent || !requiresCustomScrollBars) {
+ return
+ }
+ var initialOverflow = offsetParent.style.overflow, enabled = offsetParent.classList.contains("customScrollbars");
+ if(enable && enabled || !enable && !enabled) {
+ return
+ }
+ if(enable) {
+ offsetParent.classList.add("customScrollbars");
+ offsetParent.style.overflow = "hidden";
+ runtime.requestAnimationFrame(function() {
+ offsetParent.style.overflow = initialOverflow
+ })
+ }else {
+ offsetParent.classList.remove("customScrollbars")
+ }
+ }
+ function removeScroll() {
+ applyCSSTransform(-panPoint.x, -panPoint.y, zoom, true);
+ offsetParent.scrollLeft = 0;
+ offsetParent.scrollTop = 0;
+ enableScrollBars(false)
+ }
+ function restoreScroll() {
+ applyCSSTransform(0, 0, zoom, true);
+ offsetParent.scrollLeft = panPoint.x;
+ offsetParent.scrollTop = panPoint.y;
+ enableScrollBars(true)
+ }
+ function getPoint(touch) {
+ return new Point(touch.pageX - zoomableElement.offsetLeft, touch.pageY - zoomableElement.offsetTop)
+ }
+ function sanitizePointForPan(point) {
+ return new Point(Math.min(Math.max(point.x, zoomableElement.offsetLeft), (zoomableElement.offsetLeft + zoomableElement.offsetWidth) * zoom - offsetParent.clientWidth), Math.min(Math.max(point.y, zoomableElement.offsetTop), (zoomableElement.offsetTop + zoomableElement.offsetHeight) * zoom - offsetParent.clientHeight))
+ }
+ function processPan(point) {
+ if(previousPanPoint) {
+ panPoint.x -= point.x - previousPanPoint.x;
+ panPoint.y -= point.y - previousPanPoint.y;
+ panPoint = sanitizePointForPan(panPoint)
+ }
+ previousPanPoint = point
+ }
+ function processZoom(zoomPoint, incrementalZoom) {
+ var originalZoom = zoom, actuallyIncrementedZoom, minZoom = Math.min(maxZoom, zoomableElement.offsetParent.clientWidth / zoomableElement.offsetWidth);
+ zoom = previousZoom * incrementalZoom;
+ zoom = Math.min(Math.max(zoom, minZoom), maxZoom);
+ actuallyIncrementedZoom = zoom / originalZoom;
+ panPoint.x += (actuallyIncrementedZoom - 1) * (zoomPoint.x + panPoint.x);
+ panPoint.y += (actuallyIncrementedZoom - 1) * (zoomPoint.y + panPoint.y)
+ }
+ function processPinch(point1, point2) {
+ var zoomPoint = point1.getCenter(point2), pinchDistance = point1.getDistance(point2), incrementalZoom = pinchDistance / firstPinchDistance;
+ processPan(zoomPoint);
+ processZoom(zoomPoint, incrementalZoom)
+ }
+ function prepareGesture(event) {
+ var fingers = event.touches.length, point1 = fingers > 0 ? getPoint(event.touches[0]) : null, point2 = fingers > 1 ? getPoint(event.touches[1]) : null;
+ if(point1 && point2) {
+ firstPinchDistance = point1.getDistance(point2);
+ previousZoom = zoom;
+ previousPanPoint = point1.getCenter(point2);
+ removeScroll();
+ currentGesture = gestures.PINCH
+ }else {
+ if(point1) {
+ previousPanPoint = point1;
+ currentGesture = gestures.SCROLL
+ }
+ }
+ }
+ function processGesture(event) {
+ var fingers = event.touches.length, point1 = fingers > 0 ? getPoint(event.touches[0]) : null, point2 = fingers > 1 ? getPoint(event.touches[1]) : null;
+ if(point1 && point2) {
+ event.preventDefault();
+ if(currentGesture === gestures.SCROLL) {
+ currentGesture = gestures.PINCH;
+ removeScroll();
+ firstPinchDistance = point1.getDistance(point2);
+ return
+ }
+ processPinch(point1, point2);
+ applyFastTransform()
+ }else {
+ if(point1) {
+ if(currentGesture === gestures.PINCH) {
+ currentGesture = gestures.SCROLL;
+ restoreScroll();
+ return
+ }
+ processPan(point1)
+ }
+ }
+ }
+ function sanitizeGesture() {
+ if(currentGesture === gestures.PINCH) {
+ events.emit(gui.ZoomHelper.signalZoomChanged, zoom);
+ restoreScroll();
+ applyDetailedTransform()
+ }
+ currentGesture = gestures.NONE
+ }
+ this.subscribe = function(eventid, cb) {
+ events.subscribe(eventid, cb)
+ };
+ this.unsubscribe = function(eventid, cb) {
+ events.unsubscribe(eventid, cb)
+ };
+ this.getZoomLevel = function() {
+ return zoom
+ };
+ this.setZoomLevel = function(zoomLevel) {
+ if(zoomableElement) {
+ zoom = zoomLevel;
+ applyDetailedTransform();
+ events.emit(gui.ZoomHelper.signalZoomChanged, zoom)
+ }
+ };
+ function registerGestureListeners() {
+ if(offsetParent) {
+ offsetParent.addEventListener("touchstart", (prepareGesture), false);
+ offsetParent.addEventListener("touchmove", (processGesture), false);
+ offsetParent.addEventListener("touchend", (sanitizeGesture), false)
+ }
+ }
+ function unregisterGestureListeners() {
+ if(offsetParent) {
+ offsetParent.removeEventListener("touchstart", (prepareGesture), false);
+ offsetParent.removeEventListener("touchmove", (processGesture), false);
+ offsetParent.removeEventListener("touchend", (sanitizeGesture), false)
+ }
+ }
+ this.destroy = function(callback) {
+ unregisterGestureListeners();
+ enableScrollBars(false);
+ callback()
+ };
+ this.setZoomableElement = function(element) {
+ unregisterGestureListeners();
+ zoomableElement = element;
+ offsetParent = (zoomableElement.offsetParent);
+ applyDetailedTransform();
+ registerGestureListeners();
+ enableScrollBars(true)
+ };
+ function init() {
+ zoom = 1;
+ previousZoom = 1;
+ panPoint = new Point(0, 0)
+ }
+ init()
+ };
+ gui.ZoomHelper.signalZoomChanged = "zoomChanged"
+})();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
(function() {
var xpath = xmldom.XPath, base64 = new core.Base64;
function getEmbeddedFontDeclarations(fontFaceDecls) {
@@ -7496,114 +6681,6 @@ runtime.loadClass("odf.OdfContainer");
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("core.Utils");
-odf.ObjectNameGenerator = function ObjectNameGenerator(odfContainer, memberId) {
- var stylens = odf.Namespaces.stylens, drawns = odf.Namespaces.drawns, xlinkns = odf.Namespaces.xlinkns, domUtils = new core.DomUtils, utils = new core.Utils, memberIdHash = utils.hashString(memberId), styleNameGenerator = null, frameNameGenerator = null, imageNameGenerator = null, existingFrameNames = {}, existingImageNames = {};
- function NameGenerator(prefix, findExistingNames) {
- var reportedNames = {};
- this.generateName = function() {
- var existingNames = findExistingNames(), startIndex = 0, name;
- do {
- name = prefix + startIndex;
- startIndex += 1
- }while(reportedNames[name] || existingNames[name]);
- reportedNames[name] = true;
- return name
- }
- }
- function getAllStyleNames() {
- var styleElements = [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles], styleNames = {};
- function getStyleNames(styleListElement) {
- var e = styleListElement.firstElementChild;
- while(e) {
- if(e.namespaceURI === stylens && e.localName === "style") {
- styleNames[e.getAttributeNS(stylens, "name")] = true
- }
- e = e.nextElementSibling
- }
- }
- styleElements.forEach(getStyleNames);
- return styleNames
- }
- this.generateStyleName = function() {
- if(styleNameGenerator === null) {
- styleNameGenerator = new NameGenerator("auto" + memberIdHash + "_", function() {
- return getAllStyleNames()
- })
- }
- return styleNameGenerator.generateName()
- };
- this.generateFrameName = function() {
- if(frameNameGenerator === null) {
- var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "frame");
- nodes.forEach(function(frame) {
- existingFrameNames[frame.getAttributeNS(drawns, "name")] = true
- });
- frameNameGenerator = new NameGenerator("fr" + memberIdHash + "_", function() {
- return existingFrameNames
- })
- }
- return frameNameGenerator.generateName()
- };
- this.generateImageName = function() {
- if(imageNameGenerator === null) {
- var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "image");
- nodes.forEach(function(image) {
- var path = image.getAttributeNS(xlinkns, "href");
- path = path.substring("Pictures/".length, path.lastIndexOf("."));
- existingImageNames[path] = true
- });
- imageNameGenerator = new NameGenerator("img" + memberIdHash + "_", function() {
- return existingImageNames
- })
- }
- return imageNameGenerator.generateName()
- }
-};
-/*
-
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("core.Utils");
-runtime.loadClass("odf.ObjectNameGenerator");
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("odf.OdfContainer");
-runtime.loadClass("odf.StyleInfo");
-runtime.loadClass("odf.OdfUtils");
odf.Formatting = function Formatting() {
var odfContainer, styleInfo = new odf.StyleInfo, svgns = odf.Namespaces.svgns, stylens = odf.Namespaces.stylens, textns = odf.Namespaces.textns, numberns = odf.Namespaces.numberns, fons = odf.Namespaces.fons, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, utils = new core.Utils, builtInDefaultStyleAttributesByFamily = {"paragraph":{"style:paragraph-properties":{"fo:text-align":"left"}}}, defaultPageFormatSettings = {width:21.001, height:29.7, margin:2, padding:0};
function getSystemDefaultStyleAttributes(styleFamily) {
@@ -7741,11 +6818,9 @@ odf.Formatting = function Formatting() {
propertiesMap = getStyleAttributes(node);
inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
}
- if(includeSystemDefault) {
+ if(includeSystemDefault !== false) {
propertiesMap = getSystemDefaultStyleAttributes(styleFamily);
- if(propertiesMap) {
- inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
- }
+ inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap)
}
return inheritedPropertiesMap
}
@@ -7776,7 +6851,7 @@ odf.Formatting = function Formatting() {
if(nodeStyles) {
appliedStyles.push(nodeStyles)
}
- parent = parent.parentElement
+ parent = (parent.parentNode)
}
function chainStyles(usedStyleMap) {
Object.keys(usedStyleMap).forEach(function(styleFamily) {
@@ -7793,38 +6868,47 @@ odf.Formatting = function Formatting() {
}
return foundContainer ? appliedStyles : undefined
}
+ function isCommonStyleElement(styleNode) {
+ return styleNode.parentNode === odfContainer.rootElement.styles
+ }
function calculateAppliedStyle(styleChain) {
var mergedChildStyle = {orderedStyles:[]};
styleChain.forEach(function(elementStyleSet) {
Object.keys((elementStyleSet)).forEach(function(styleFamily) {
- var styleName = Object.keys(elementStyleSet[styleFamily])[0], styleElement, parentStyle, displayName;
+ var styleName = Object.keys(elementStyleSet[styleFamily])[0], styleSummary = {name:styleName, family:styleFamily, displayName:undefined, isCommonStyle:false}, styleElement, parentStyle;
styleElement = getStyleElement(styleName, styleFamily);
if(styleElement) {
parentStyle = getInheritedStyleAttributes((styleElement));
mergedChildStyle = utils.mergeObjects(parentStyle, mergedChildStyle);
- displayName = styleElement.getAttributeNS(stylens, "display-name")
+ styleSummary.displayName = styleElement.getAttributeNS(stylens, "display-name");
+ styleSummary.isCommonStyle = isCommonStyleElement(styleElement)
}else {
runtime.log("No style element found for '" + styleName + "' of family '" + styleFamily + "'")
}
- mergedChildStyle.orderedStyles.push({name:styleName, family:styleFamily, displayName:displayName})
+ mergedChildStyle.orderedStyles.push(styleSummary)
})
});
return mergedChildStyle
}
- this.getAppliedStyles = function(textNodes) {
+ function getAppliedStyles(nodes, calculatedStylesCache) {
var styleChains = {}, styles = [];
- textNodes.forEach(function(n) {
+ if(!calculatedStylesCache) {
+ calculatedStylesCache = {}
+ }
+ nodes.forEach(function(n) {
buildStyleChain(n, styleChains)
});
Object.keys(styleChains).forEach(function(key) {
- styles.push(calculateAppliedStyle(styleChains[key]))
+ if(!calculatedStylesCache[key]) {
+ calculatedStylesCache[key] = calculateAppliedStyle(styleChains[key])
+ }
+ styles.push(calculatedStylesCache[key])
});
return styles
- };
- this.getAppliedStylesForElement = function(node) {
- var styleChain;
- styleChain = buildStyleChain(node);
- return styleChain ? calculateAppliedStyle(styleChain) : undefined
+ }
+ this.getAppliedStyles = getAppliedStyles;
+ this.getAppliedStylesForElement = function(node, calculatedStylesCache) {
+ return getAppliedStyles([node], calculatedStylesCache)[0]
};
this.updateStyle = function(styleNode, properties) {
var fontName, fontFaceNode;
@@ -7837,16 +6921,13 @@ odf.Formatting = function Formatting() {
odfContainer.rootElement.fontFaceDecls.appendChild(fontFaceNode)
}
};
- function isAutomaticStyleElement(styleNode) {
- return styleNode.parentNode === odfContainer.rootElement.automaticStyles
- }
this.createDerivedStyleObject = function(parentStyleName, family, overrides) {
var originalStyleElement = (getStyleElement(parentStyleName, family)), newStyleObject;
runtime.assert(Boolean(originalStyleElement), "No style element found for '" + parentStyleName + "' of family '" + family + "'");
- if(isAutomaticStyleElement(originalStyleElement)) {
- newStyleObject = getStyleAttributes(originalStyleElement)
- }else {
+ if(isCommonStyleElement(originalStyleElement)) {
newStyleObject = {"style:parent-style-name":parentStyleName}
+ }else {
+ newStyleObject = getStyleAttributes(originalStyleElement)
}
newStyleObject["style:family"] = family;
utils.mergeObjects(newStyleObject, overrides);
@@ -7994,14 +7075,657 @@ odf.Formatting = function Formatting() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("odf.OdfContainer");
-runtime.loadClass("odf.Formatting");
-runtime.loadClass("xmldom.XPath");
-runtime.loadClass("odf.FontLoader");
-runtime.loadClass("odf.Style2CSS");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("gui.AnnotationViewManager");
+odf.StyleTreeNode = function StyleTreeNode(element) {
+ this.derivedStyles = {};
+ this.element = element
+};
+odf.Style2CSS = function Style2CSS() {
+ var drawns = odf.Namespaces.drawns, fons = odf.Namespaces.fons, officens = odf.Namespaces.officens, stylens = odf.Namespaces.stylens, svgns = odf.Namespaces.svgns, tablens = odf.Namespaces.tablens, textns = odf.Namespaces.textns, xlinkns = odf.Namespaces.xlinkns, presentationns = odf.Namespaces.presentationns, familynamespaceprefixes = {"graphic":"draw", "drawing-page":"draw", "paragraph":"text", "presentation":"presentation", "ruby":"text", "section":"text", "table":"table", "table-cell":"table",
+ "table-column":"table", "table-row":"table", "text":"text", "list":"text", "page":"office"}, familytagnames = {"graphic":["circle", "connected", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "paragraph":["alphabetical-index-entry-template", "h", "illustration-index-entry-template", "index-source-style", "object-index-entry-template", "p", "table-index-entry-template", "table-of-content-entry-template",
+ "user-index-entry-template"], "presentation":["caption", "circle", "connector", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "drawing-page":["caption", "circle", "connector", "control", "page", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "ruby":["ruby", "ruby-text"], "section":["alphabetical-index", "bibliography",
+ "illustration-index", "index-title", "object-index", "section", "table-of-content", "table-index", "user-index"], "table":["background", "table"], "table-cell":["body", "covered-table-cell", "even-columns", "even-rows", "first-column", "first-row", "last-column", "last-row", "odd-columns", "odd-rows", "table-cell"], "table-column":["table-column"], "table-row":["table-row"], "text":["a", "index-entry-chapter", "index-entry-link-end", "index-entry-link-start", "index-entry-page-number", "index-entry-span",
+ "index-entry-tab-stop", "index-entry-text", "index-title-template", "linenumbering-configuration", "list-level-style-number", "list-level-style-bullet", "outline-level-style", "span"], "list":["list-item"]}, textPropertySimpleMapping = [[fons, "color", "color"], [fons, "background-color", "background-color"], [fons, "font-weight", "font-weight"], [fons, "font-style", "font-style"]], bgImageSimpleMapping = [[stylens, "repeat", "background-repeat"]], paragraphPropertySimpleMapping = [[fons, "background-color",
+ "background-color"], [fons, "text-align", "text-align"], [fons, "text-indent", "text-indent"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-left", "margin-left"],
+ [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"], [fons, "border", "border"]], graphicPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "min-height", "min-height"], [drawns, "stroke", "border"], [svgns, "stroke-color", "border-color"], [svgns, "stroke-width", "border-width"], [fons, "border", "border"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top",
+ "border-top"], [fons, "border-bottom", "border-bottom"]], tablecellPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "border", "border"]], tablecolumnPropertySimpleMapping = [[stylens, "column-width", "width"]], tablerowPropertySimpleMapping = [[stylens, "row-height", "height"], [fons, "keep-together", null]], tablePropertySimpleMapping =
+ [[stylens, "width", "width"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageContentPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "padding", "padding"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border", "border"], [fons,
+ "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin", "margin"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"]], pageSizePropertySimpleMapping = [[fons, "page-width", "width"], [fons, "page-height", "height"]], borderPropertyMap = {"border":true, "border-left":true, "border-right":true,
+ "border-top":true, "border-bottom":true, "stroke-width":true}, fontFaceDeclsMap = {}, utils = new odf.OdfUtils, documentType, odfRoot, defaultFontSize, xpath = xmldom.XPath, cssUnits = new core.CSSUnits;
+ function getStyleMap(stylesnode) {
+ var node, name, family, style, stylemap = {};
+ if(!stylesnode) {
+ return stylemap
+ }
+ node = stylesnode.firstElementChild;
+ while(node) {
+ if(node.namespaceURI === stylens && (node.localName === "style" || node.localName === "default-style")) {
+ family = node.getAttributeNS(stylens, "family")
+ }else {
+ if(node.namespaceURI === textns && node.localName === "list-style") {
+ family = "list"
+ }else {
+ if(node.namespaceURI === stylens && (node.localName === "page-layout" || node.localName === "default-page-layout")) {
+ family = "page"
+ }else {
+ family = undefined
+ }
+ }
+ }
+ if(family) {
+ name = node.getAttributeNS(stylens, "name");
+ if(!name) {
+ name = ""
+ }
+ if(stylemap.hasOwnProperty(family)) {
+ style = stylemap[family]
+ }else {
+ stylemap[family] = style = {}
+ }
+ style[name] = node
+ }
+ node = node.nextElementSibling
+ }
+ return stylemap
+ }
+ function findStyle(stylestree, name) {
+ if(stylestree.hasOwnProperty(name)) {
+ return stylestree[name]
+ }
+ var n, style = null;
+ for(n in stylestree) {
+ if(stylestree.hasOwnProperty(n)) {
+ style = findStyle(stylestree[n].derivedStyles, name);
+ if(style) {
+ break
+ }
+ }
+ }
+ return style
+ }
+ function addStyleToStyleTree(stylename, stylesmap, stylestree) {
+ var style, parentname, parentstyle;
+ if(!stylesmap.hasOwnProperty(stylename)) {
+ return null
+ }
+ style = new odf.StyleTreeNode(stylesmap[stylename]);
+ parentname = style.element.getAttributeNS(stylens, "parent-style-name");
+ parentstyle = null;
+ if(parentname) {
+ parentstyle = findStyle(stylestree, parentname) || addStyleToStyleTree(parentname, stylesmap, stylestree)
+ }
+ if(parentstyle) {
+ parentstyle.derivedStyles[stylename] = style
+ }else {
+ stylestree[stylename] = style
+ }
+ delete stylesmap[stylename];
+ return style
+ }
+ function addStyleMapToStyleTree(stylesmap, stylestree) {
+ var name;
+ for(name in stylesmap) {
+ if(stylesmap.hasOwnProperty(name)) {
+ addStyleToStyleTree(name, stylesmap, stylestree)
+ }
+ }
+ }
+ function createSelector(family, name) {
+ var prefix = familynamespaceprefixes[family], namepart, selector;
+ if(prefix === undefined) {
+ return null
+ }
+ if(name) {
+ namepart = "[" + prefix + '|style-name="' + name + '"]'
+ }else {
+ namepart = ""
+ }
+ if(prefix === "presentation") {
+ prefix = "draw";
+ if(name) {
+ namepart = '[presentation|style-name="' + name + '"]'
+ }else {
+ namepart = ""
+ }
+ }
+ selector = prefix + "|" + familytagnames[family].join(namepart + "," + prefix + "|") + namepart;
+ return selector
+ }
+ function getSelectors(family, name, node) {
+ var selectors = [], ss, derivedStyles = node.derivedStyles, n;
+ ss = createSelector(family, name);
+ if(ss !== null) {
+ selectors.push(ss)
+ }
+ for(n in derivedStyles) {
+ if(derivedStyles.hasOwnProperty(n)) {
+ ss = getSelectors(family, n, derivedStyles[n]);
+ selectors = selectors.concat(ss)
+ }
+ }
+ return selectors
+ }
+ function getDirectChild(node, ns, name) {
+ var e = node && node.firstElementChild;
+ while(e) {
+ if(e.namespaceURI === ns && e.localName === name) {
+ break
+ }
+ e = e.nextElementSibling
+ }
+ return e
+ }
+ function fixBorderWidth(value) {
+ var index = value.indexOf(" "), width, theRestOfBorderAttributes;
+ if(index !== -1) {
+ width = value.substring(0, index);
+ theRestOfBorderAttributes = value.substring(index)
+ }else {
+ width = value;
+ theRestOfBorderAttributes = ""
+ }
+ width = utils.parseLength(width);
+ if(width && (width.unit === "pt" && width.value < 0.75)) {
+ value = "0.75pt" + theRestOfBorderAttributes
+ }
+ return value
+ }
+ function applySimpleMapping(props, mapping) {
+ var rule = "", i, r, value;
+ for(i = 0;i < mapping.length;i += 1) {
+ r = mapping[i];
+ value = props.getAttributeNS(r[0], r[1]);
+ if(value) {
+ value = value.trim();
+ if(borderPropertyMap.hasOwnProperty(r[1])) {
+ value = fixBorderWidth(value)
+ }
+ if(r[2]) {
+ rule += r[2] + ":" + value + ";"
+ }
+ }
+ }
+ return rule
+ }
+ function getFontSize(styleNode) {
+ var props = getDirectChild(styleNode, stylens, "text-properties");
+ if(props) {
+ return utils.parseFoFontSize(props.getAttributeNS(fons, "font-size"))
+ }
+ return null
+ }
+ function getParentStyleNode(styleNode) {
+ var parentStyleName = "", parentStyleFamily = "", parentStyleNode = null, xp;
+ if(styleNode.localName === "default-style") {
+ return null
+ }
+ parentStyleName = styleNode.getAttributeNS(stylens, "parent-style-name");
+ parentStyleFamily = styleNode.getAttributeNS(stylens, "family");
+ if(parentStyleName) {
+ xp = "//style:*[@style:name='" + parentStyleName + "'][@style:family='" + parentStyleFamily + "']"
+ }else {
+ xp = "//style:default-style[@style:family='" + parentStyleFamily + "']"
+ }
+ parentStyleNode = xpath.getODFElementsWithXPath((odfRoot), xp, odf.Namespaces.lookupNamespaceURI)[0];
+ return parentStyleNode
+ }
+ function getTextProperties(props) {
+ var rule = "", fontName, fontSize, value, textDecoration = "", fontSizeRule = "", sizeMultiplier = 1, parentStyle;
+ rule += applySimpleMapping(props, textPropertySimpleMapping);
+ value = props.getAttributeNS(stylens, "text-underline-style");
+ if(value === "solid") {
+ textDecoration += " underline"
+ }
+ value = props.getAttributeNS(stylens, "text-line-through-style");
+ if(value === "solid") {
+ textDecoration += " line-through"
+ }
+ if(textDecoration.length) {
+ textDecoration = "text-decoration:" + textDecoration + ";";
+ rule += textDecoration
+ }
+ fontName = props.getAttributeNS(stylens, "font-name") || props.getAttributeNS(fons, "font-family");
+ if(fontName) {
+ value = fontFaceDeclsMap[fontName];
+ rule += "font-family: " + (value || fontName) + ";"
+ }
+ parentStyle = (props.parentNode);
+ fontSize = getFontSize(parentStyle);
+ if(!fontSize) {
+ return rule
+ }
+ while(parentStyle) {
+ fontSize = getFontSize(parentStyle);
+ if(fontSize) {
+ if(fontSize.unit !== "%") {
+ fontSizeRule = "font-size: " + fontSize.value * sizeMultiplier + fontSize.unit + ";";
+ break
+ }
+ sizeMultiplier *= fontSize.value / 100
+ }
+ parentStyle = getParentStyleNode(parentStyle)
+ }
+ if(!fontSizeRule) {
+ fontSizeRule = "font-size: " + parseFloat(defaultFontSize) * sizeMultiplier + cssUnits.getUnits(defaultFontSize) + ";"
+ }
+ rule += fontSizeRule;
+ return rule
+ }
+ function getParagraphProperties(props) {
+ var rule = "", bgimage, url, lineHeight;
+ rule += applySimpleMapping(props, paragraphPropertySimpleMapping);
+ bgimage = getDirectChild(props, stylens, "background-image");
+ if(bgimage) {
+ url = bgimage.getAttributeNS(xlinkns, "href");
+ if(url) {
+ rule += "background-image: url('odfkit:" + url + "');";
+ rule += applySimpleMapping(bgimage, bgImageSimpleMapping)
+ }
+ }
+ lineHeight = props.getAttributeNS(fons, "line-height");
+ if(lineHeight && lineHeight !== "normal") {
+ lineHeight = utils.parseFoLineHeight(lineHeight);
+ if(lineHeight.unit !== "%") {
+ rule += "line-height: " + lineHeight.value + lineHeight.unit + ";"
+ }else {
+ rule += "line-height: " + lineHeight.value / 100 + ";"
+ }
+ }
+ return rule
+ }
+ function matchToRgb(m, r, g, b) {
+ return r + r + g + g + b + b
+ }
+ function hexToRgb(hex) {
+ var result, shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ hex = hex.replace(shorthandRegex, matchToRgb);
+ result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {r:parseInt(result[1], 16), g:parseInt(result[2], 16), b:parseInt(result[3], 16)} : null
+ }
+ function isNumber(n) {
+ return!isNaN(parseFloat(n))
+ }
+ function getGraphicProperties(props) {
+ var rule = "", alpha, bgcolor, fill;
+ rule += applySimpleMapping(props, graphicPropertySimpleMapping);
+ alpha = props.getAttributeNS(drawns, "opacity");
+ fill = props.getAttributeNS(drawns, "fill");
+ bgcolor = props.getAttributeNS(drawns, "fill-color");
+ if(fill === "solid" || fill === "hatch") {
+ if(bgcolor && bgcolor !== "none") {
+ alpha = isNumber(alpha) ? parseFloat(alpha) / 100 : 1;
+ bgcolor = hexToRgb(bgcolor);
+ if(bgcolor) {
+ rule += "background-color: rgba(" + bgcolor.r + "," + bgcolor.g + "," + bgcolor.b + "," + alpha + ");"
+ }
+ }else {
+ rule += "background: none;"
+ }
+ }else {
+ if(fill === "none") {
+ rule += "background: none;"
+ }
+ }
+ return rule
+ }
+ function getDrawingPageProperties(props) {
+ var rule = "";
+ rule += applySimpleMapping(props, graphicPropertySimpleMapping);
+ if(props.getAttributeNS(presentationns, "background-visible") === "true") {
+ rule += "background: none;"
+ }
+ return rule
+ }
+ function getTableCellProperties(props) {
+ var rule = "";
+ rule += applySimpleMapping(props, tablecellPropertySimpleMapping);
+ return rule
+ }
+ function getTableRowProperties(props) {
+ var rule = "";
+ rule += applySimpleMapping(props, tablerowPropertySimpleMapping);
+ return rule
+ }
+ function getTableColumnProperties(props) {
+ var rule = "";
+ rule += applySimpleMapping(props, tablecolumnPropertySimpleMapping);
+ return rule
+ }
+ function getTableProperties(props) {
+ var rule = "", borderModel;
+ rule += applySimpleMapping(props, tablePropertySimpleMapping);
+ borderModel = props.getAttributeNS(tablens, "border-model");
+ if(borderModel === "collapsing") {
+ rule += "border-collapse:collapse;"
+ }else {
+ if(borderModel === "separating") {
+ rule += "border-collapse:separate;"
+ }
+ }
+ return rule
+ }
+ function addStyleRule(sheet, family, name, node) {
+ var selectors = getSelectors(family, name, node), selector = selectors.join(","), rule = "", properties;
+ properties = getDirectChild(node.element, stylens, "text-properties");
+ if(properties) {
+ rule += getTextProperties(properties)
+ }
+ properties = getDirectChild(node.element, stylens, "paragraph-properties");
+ if(properties) {
+ rule += getParagraphProperties(properties)
+ }
+ properties = getDirectChild(node.element, stylens, "graphic-properties");
+ if(properties) {
+ rule += getGraphicProperties(properties)
+ }
+ properties = getDirectChild(node.element, stylens, "drawing-page-properties");
+ if(properties) {
+ rule += getDrawingPageProperties(properties)
+ }
+ properties = getDirectChild(node.element, stylens, "table-cell-properties");
+ if(properties) {
+ rule += getTableCellProperties(properties)
+ }
+ properties = getDirectChild(node.element, stylens, "table-row-properties");
+ if(properties) {
+ rule += getTableRowProperties(properties)
+ }
+ properties = getDirectChild(node.element, stylens, "table-column-properties");
+ if(properties) {
+ rule += getTableColumnProperties(properties)
+ }
+ properties = getDirectChild(node.element, stylens, "table-properties");
+ if(properties) {
+ rule += getTableProperties(properties)
+ }
+ if(rule.length === 0) {
+ return
+ }
+ rule = selector + "{" + rule + "}";
+ try {
+ sheet.insertRule(rule, sheet.cssRules.length)
+ }catch(e) {
+ throw e;
+ }
+ }
+ function getNumberRule(node) {
+ var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix") || "", prefix = node.getAttributeNS(stylens, "num-prefix") || "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content = "";
+ if(prefix) {
+ content += ' "' + prefix + '"'
+ }
+ if(stylemap.hasOwnProperty(style)) {
+ content += " counter(list, " + stylemap[style] + ")"
+ }else {
+ if(style) {
+ content += ' "' + style + '"'
+ }else {
+ content += " ''"
+ }
+ }
+ return"content:" + content + ' "' + suffix + '"'
+ }
+ function getImageRule() {
+ return"content: none;"
+ }
+ function getBulletRule(node) {
+ var bulletChar = node.getAttributeNS(textns, "bullet-char");
+ return"content: '" + bulletChar + "';"
+ }
+ function addListStyleRule(sheet, name, node, itemrule) {
+ var selector = 'text|list[text|style-name="' + name + '"]', level = node.getAttributeNS(textns, "level"), itemSelector, listItemRule, listLevelProps = getDirectChild(node, stylens, "list-level-properties"), listLevelLabelAlign = getDirectChild(listLevelProps, stylens, "list-level-label-alignment"), bulletIndent, listIndent, bulletWidth, rule;
+ if(listLevelLabelAlign) {
+ bulletIndent = listLevelLabelAlign.getAttributeNS(fons, "text-indent");
+ listIndent = listLevelLabelAlign.getAttributeNS(fons, "margin-left")
+ }
+ if(!bulletIndent) {
+ bulletIndent = "-0.6cm"
+ }
+ if(bulletIndent.charAt(0) === "-") {
+ bulletWidth = bulletIndent.substring(1)
+ }else {
+ bulletWidth = "-" + bulletIndent
+ }
+ level = level && parseInt(level, 10);
+ while(level > 1) {
+ selector += " > text|list-item > text|list";
+ level -= 1
+ }
+ if(listIndent) {
+ itemSelector = selector;
+ itemSelector += " > text|list-item > *:not(text|list):first-child";
+ listItemRule = itemSelector + "{";
+ listItemRule += "margin-left:" + listIndent + ";";
+ listItemRule += "}";
+ try {
+ sheet.insertRule(listItemRule, sheet.cssRules.length)
+ }catch(e1) {
+ runtime.log("cannot load rule: " + listItemRule)
+ }
+ }
+ selector += " > text|list-item > *:not(text|list):first-child:before";
+ rule = selector + "{" + itemrule + ";";
+ rule += "counter-increment:list;";
+ rule += "margin-left:" + bulletIndent + ";";
+ rule += "width:" + bulletWidth + ";";
+ rule += "display:inline-block}";
+ try {
+ sheet.insertRule(rule, sheet.cssRules.length)
+ }catch(e2) {
+ runtime.log("cannot load rule: " + rule)
+ }
+ }
+ function addPageStyleRules(sheet, node) {
+ var rule = "", imageProps, url, contentLayoutRule = "", pageSizeRule = "", props = getDirectChild(node, stylens, "page-layout-properties"), stylename, masterStyles, e, masterStyleName;
+ if(!props) {
+ return
+ }
+ stylename = node.getAttributeNS(stylens, "name");
+ rule += applySimpleMapping(props, pageContentPropertySimpleMapping);
+ imageProps = getDirectChild(props, stylens, "background-image");
+ if(imageProps) {
+ url = imageProps.getAttributeNS(xlinkns, "href");
+ if(url) {
+ rule += "background-image: url('odfkit:" + url + "');";
+ rule += applySimpleMapping(imageProps, bgImageSimpleMapping)
+ }
+ }
+ if(documentType === "presentation") {
+ masterStyles = getDirectChild((node.parentNode.parentNode), officens, "master-styles");
+ e = masterStyles && masterStyles.firstElementChild;
+ while(e) {
+ if(e.namespaceURI === stylens && (e.localName === "master-page" && e.getAttributeNS(stylens, "page-layout-name") === stylename)) {
+ masterStyleName = e.getAttributeNS(stylens, "name");
+ contentLayoutRule = "draw|page[draw|master-page-name=" + masterStyleName + "] {" + rule + "}";
+ pageSizeRule = "office|body, draw|page[draw|master-page-name=" + masterStyleName + "] {" + applySimpleMapping(props, pageSizePropertySimpleMapping) + " }";
+ try {
+ sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
+ sheet.insertRule(pageSizeRule, sheet.cssRules.length)
+ }catch(e1) {
+ throw e1;
+ }
+ }
+ e = e.nextElementSibling
+ }
+ }else {
+ if(documentType === "text") {
+ contentLayoutRule = "office|text {" + rule + "}";
+ rule = "";
+ pageSizeRule = "office|body {" + "width: " + props.getAttributeNS(fons, "page-width") + ";" + "}";
+ try {
+ sheet.insertRule(contentLayoutRule, sheet.cssRules.length);
+ sheet.insertRule(pageSizeRule, sheet.cssRules.length)
+ }catch(e2) {
+ throw e2;
+ }
+ }
+ }
+ }
+ function addListStyleRules(sheet, name, node) {
+ var n = node.firstChild, e, itemrule;
+ while(n) {
+ if(n.namespaceURI === textns) {
+ e = (n);
+ if(n.localName === "list-level-style-number") {
+ itemrule = getNumberRule(e);
+ addListStyleRule(sheet, name, e, itemrule)
+ }else {
+ if(n.localName === "list-level-style-image") {
+ itemrule = getImageRule();
+ addListStyleRule(sheet, name, e, itemrule)
+ }else {
+ if(n.localName === "list-level-style-bullet") {
+ itemrule = getBulletRule(e);
+ addListStyleRule(sheet, name, e, itemrule)
+ }
+ }
+ }
+ }
+ n = n.nextSibling
+ }
+ }
+ function addRule(sheet, family, name, node) {
+ if(family === "list") {
+ addListStyleRules(sheet, name, node.element)
+ }else {
+ if(family === "page") {
+ addPageStyleRules(sheet, node.element)
+ }else {
+ addStyleRule(sheet, family, name, node)
+ }
+ }
+ }
+ function addRules(sheet, family, name, node) {
+ addRule(sheet, family, name, node);
+ var n;
+ for(n in node.derivedStyles) {
+ if(node.derivedStyles.hasOwnProperty(n)) {
+ addRules(sheet, family, n, node.derivedStyles[n])
+ }
+ }
+ }
+ this.style2css = function(doctype, stylesheet, fontFaceMap, styles, autostyles) {
+ var doc, styletree, tree, rule, name, family, stylenodes, styleautonodes;
+ while(stylesheet.cssRules.length) {
+ stylesheet.deleteRule(stylesheet.cssRules.length - 1)
+ }
+ doc = null;
+ if(styles) {
+ doc = styles.ownerDocument;
+ odfRoot = styles.parentNode
+ }
+ if(autostyles) {
+ doc = autostyles.ownerDocument;
+ odfRoot = autostyles.parentNode
+ }
+ if(!doc) {
+ return
+ }
+ odf.Namespaces.forEachPrefix(function(prefix, ns) {
+ rule = "@namespace " + prefix + " url(" + ns + ");";
+ try {
+ stylesheet.insertRule(rule, stylesheet.cssRules.length)
+ }catch(ignore) {
+ }
+ });
+ fontFaceDeclsMap = fontFaceMap;
+ documentType = doctype;
+ defaultFontSize = runtime.getWindow().getComputedStyle(document.body, null).getPropertyValue("font-size") || "12pt";
+ stylenodes = getStyleMap(styles);
+ styleautonodes = getStyleMap(autostyles);
+ styletree = {};
+ for(family in familynamespaceprefixes) {
+ if(familynamespaceprefixes.hasOwnProperty(family)) {
+ tree = styletree[family] = {};
+ addStyleMapToStyleTree(stylenodes[family], tree);
+ addStyleMapToStyleTree(styleautonodes[family], tree);
+ for(name in tree) {
+ if(tree.hasOwnProperty(name)) {
+ addRules(stylesheet, family, name, tree[name])
+ }
+ }
+ }
+ }
+ }
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.Canvas = function Canvas() {
+};
+ops.Canvas.prototype.getZoomLevel = function() {
+};
+ops.Canvas.prototype.getElement = function() {
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
(function() {
function LoadingQueue() {
var queue = [], taskRunning = false;
@@ -8084,6 +7808,12 @@ runtime.loadClass("gui.AnnotationViewManager");
element.removeChild(element.firstChild)
}
}
+ function clearCSSStyleSheet(style) {
+ var stylesheet = (style.sheet), cssRules = stylesheet.cssRules;
+ while(cssRules.length) {
+ stylesheet.deleteRule(cssRules.length - 1)
+ }
+ }
function handleStyles(odfcontainer, formatting, stylesxmlcss) {
var style2css = new odf.Style2CSS;
style2css.style2css(odfcontainer.getDocumentType(), (stylesxmlcss.sheet), formatting.getFontMap(), odfcontainer.rootElement.styles, odfcontainer.rootElement.automaticStyles)
@@ -8096,20 +7826,21 @@ runtime.loadClass("gui.AnnotationViewManager");
if(!masterPageName) {
return null
}
- var masterStyles = odfContainer.rootElement.masterStyles, masterPageElement = masterStyles.firstElementChild;
- while(masterPageElement) {
- if(masterPageElement.getAttributeNS(stylens, "name") === masterPageName && (masterPageElement.localName === "master-page" && masterPageElement.namespaceURI === stylens)) {
+ var masterStyles = odfContainer.rootElement.masterStyles, masterStylesChild = masterStyles.firstElementChild;
+ while(masterStylesChild) {
+ if(masterStylesChild.getAttributeNS(stylens, "name") === masterPageName && (masterStylesChild.localName === "master-page" && masterStylesChild.namespaceURI === stylens)) {
break
}
+ masterStylesChild = masterStylesChild.nextElementSibling
}
- return masterPageElement
+ return masterStylesChild
}
function dropTemplateDrawFrames(clonedNode) {
var i, element, presentationClass, clonedDrawFrameElements = clonedNode.getElementsByTagNameNS(drawns, "frame");
for(i = 0;i < clonedDrawFrameElements.length;i += 1) {
element = (clonedDrawFrameElements[i]);
presentationClass = element.getAttributeNS(presentationns, "class");
- if(presentationClass && !/^(date-time|footer|header|page-number')$/.test(presentationClass)) {
+ if(presentationClass && !/^(date-time|footer|header|page-number)$/.test(presentationClass)) {
element.parentNode.removeChild(element)
}
}
@@ -8237,39 +7968,6 @@ runtime.loadClass("gui.AnnotationViewManager");
modifyTableCell(node)
}
}
- function modifyLinks(odffragment) {
- var i, links, node;
- function modifyLink(node) {
- var url, clickHandler;
- if(!node.hasAttributeNS(xlinkns, "href")) {
- return
- }
- url = node.getAttributeNS(xlinkns, "href");
- if(url[0] === "#") {
- url = url.substring(1);
- clickHandler = function() {
- var bookmarks = xpath.getODFElementsWithXPath(odffragment, "//text:bookmark-start[@text:name='" + url + "']", odf.Namespaces.lookupNamespaceURI);
- if(bookmarks.length === 0) {
- bookmarks = xpath.getODFElementsWithXPath(odffragment, "//text:bookmark[@text:name='" + url + "']", odf.Namespaces.lookupNamespaceURI)
- }
- if(bookmarks.length > 0) {
- bookmarks[0].scrollIntoView(true)
- }
- return false
- }
- }else {
- clickHandler = function() {
- window.open(url)
- }
- }
- node.onclick = clickHandler
- }
- links = odffragment.getElementsByTagNameNS(textns, "a");
- for(i = 0;i < links.length;i += 1) {
- node = (links.item(i));
- modifyLink(node)
- }
- }
function modifyLineBreakElements(odffragment) {
var document = odffragment.ownerDocument, lineBreakElements = domUtils.getElementsByTagNameNS(odffragment, textns, "line-break");
lineBreakElements.forEach(function(lineBreak) {
@@ -8315,7 +8013,7 @@ runtime.loadClass("gui.AnnotationViewManager");
node = node.firstElementChild
}else {
while(node && (node !== odfbody && !node.nextElementSibling)) {
- node = node.parentElement
+ node = (node.parentNode)
}
if(node && node.nextElementSibling) {
node = node.nextElementSibling
@@ -8497,24 +8195,49 @@ runtime.loadClass("gui.AnnotationViewManager");
}
}
}
+ function findWebODFStyleSheet(head) {
+ var style = head.firstElementChild;
+ while(style && !(style.localName === "style" && style.hasAttribute("webodfcss"))) {
+ style = style.nextElementSibling
+ }
+ return(style)
+ }
function addWebODFStyleSheet(document) {
- var head = (document.getElementsByTagName("head")[0]), style, href;
- if(String(typeof webodf_css) !== "undefined") {
- style = document.createElementNS(head.namespaceURI, "style");
- style.setAttribute("media", "screen, print, handheld, projection");
- style.appendChild(document.createTextNode(webodf_css))
+ var head = (document.getElementsByTagName("head")[0]), css, style, href, count = document.styleSheets.length;
+ style = findWebODFStyleSheet(head);
+ if(style) {
+ count = parseInt(style.getAttribute("webodfcss"), 10);
+ style.setAttribute("webodfcss", count + 1);
+ return style
+ }
+ if(String(typeof webodf_css) === "string") {
+ css = (webodf_css)
}else {
- style = document.createElementNS(head.namespaceURI, "link");
href = "webodf.css";
if(runtime.currentDirectory) {
- href = runtime.currentDirectory() + "/../" + href
+ href = runtime.currentDirectory();
+ if(href.length > 0 && href.substr(-1) !== "/") {
+ href += "/"
+ }
+ href += "../webodf.css"
}
- style.setAttribute("href", href);
- style.setAttribute("rel", "stylesheet")
+ css = (runtime.readFileSync(href, "utf-8"))
}
+ style = (document.createElementNS(head.namespaceURI, "style"));
+ style.setAttribute("media", "screen, print, handheld, projection");
style.setAttribute("type", "text/css");
+ style.setAttribute("webodfcss", "1");
+ style.appendChild(document.createTextNode(css));
head.appendChild(style);
- return(style)
+ return style
+ }
+ function removeWebODFStyleSheet(webodfcss) {
+ var count = parseInt(webodfcss.getAttribute("webodfcss"), 10);
+ if(count === 1) {
+ webodfcss.parentNode.removeChild(webodfcss)
+ }else {
+ webodfcss.setAttribute("count", count - 1)
+ }
}
function addStyleSheet(document) {
var head = (document.getElementsByTagName("head")[0]), style = document.createElementNS(head.namespaceURI, "style"), text = "";
@@ -8531,7 +8254,8 @@ runtime.loadClass("gui.AnnotationViewManager");
odf.OdfCanvas = function OdfCanvas(element) {
runtime.assert(element !== null && element !== undefined, "odf.OdfCanvas constructor needs DOM element");
runtime.assert(element.ownerDocument !== null && element.ownerDocument !== undefined, "odf.OdfCanvas constructor needs DOM");
- var self = this, doc = (element.ownerDocument), odfcontainer, formatting = new odf.Formatting, pageSwitcher, sizer = null, annotationsPane = null, allowAnnotations = false, annotationViewManager = null, webodfcss, fontcss, stylesxmlcss, positioncss, shadowContent, zoomLevel = 1, eventHandlers = {}, loadingQueue = new LoadingQueue;
+ var self = this, doc = (element.ownerDocument), async = new core.Async, odfcontainer, formatting = new odf.Formatting, pageSwitcher, sizer = null, annotationsPane = null, allowAnnotations = false, showAnnotationRemoveButton = false, annotationViewManager = null, webodfcss, fontcss, stylesxmlcss, positioncss, shadowContent, eventHandlers = {}, waitingForDoneTimeoutId, redrawContainerTask, shouldRefreshCss = false, shouldRerenderAnnotations = false, loadingQueue = new LoadingQueue, zoomHelper =
+ new gui.ZoomHelper;
function loadImages(container, odffragment, stylesheet) {
var i, images, node;
function loadImage(name, container, node, stylesheet) {
@@ -8579,34 +8303,46 @@ runtime.loadClass("gui.AnnotationViewManager");
}
}
function fixContainerSize() {
- var odfdoc = sizer.firstChild;
+ var minHeight, odfdoc = sizer.firstChild, zoomLevel = zoomHelper.getZoomLevel();
if(!odfdoc) {
return
}
- if(zoomLevel > 1) {
- sizer.style.MozTransformOrigin = "center top";
- sizer.style.WebkitTransformOrigin = "center top";
- sizer.style.OTransformOrigin = "center top";
- sizer.style.msTransformOrigin = "center top"
- }else {
- sizer.style.MozTransformOrigin = "left top";
- sizer.style.WebkitTransformOrigin = "left top";
- sizer.style.OTransformOrigin = "left top";
- sizer.style.msTransformOrigin = "left top"
- }
- sizer.style.WebkitTransform = "scale(" + zoomLevel + ")";
- sizer.style.MozTransform = "scale(" + zoomLevel + ")";
- sizer.style.OTransform = "scale(" + zoomLevel + ")";
- sizer.style.msTransform = "scale(" + zoomLevel + ")";
+ sizer.style.WebkitTransformOrigin = "0% 0%";
+ sizer.style.MozTransformOrigin = "0% 0%";
+ sizer.style.msTransformOrigin = "0% 0%";
+ sizer.style.OTransformOrigin = "0% 0%";
+ sizer.style.transformOrigin = "0% 0%";
+ if(annotationViewManager) {
+ minHeight = annotationViewManager.getMinimumHeightForAnnotationPane();
+ if(minHeight) {
+ sizer.style.minHeight = minHeight
+ }else {
+ sizer.style.removeProperty("min-height")
+ }
+ }
element.style.width = Math.round(zoomLevel * sizer.offsetWidth) + "px";
element.style.height = Math.round(zoomLevel * sizer.offsetHeight) + "px"
}
+ function redrawContainer() {
+ if(shouldRefreshCss) {
+ handleStyles(odfcontainer, formatting, stylesxmlcss);
+ shouldRefreshCss = false
+ }
+ if(shouldRerenderAnnotations) {
+ if(annotationViewManager) {
+ annotationViewManager.rerenderAnnotations()
+ }
+ shouldRerenderAnnotations = false
+ }
+ fixContainerSize()
+ }
function handleContent(container, odfnode) {
var css = (positioncss.sheet);
clear(element);
sizer = (doc.createElementNS(element.namespaceURI, "div"));
sizer.style.display = "inline-block";
sizer.style.background = "white";
+ sizer.style.setProperty("float", "left", "important");
sizer.appendChild(odfnode);
element.appendChild(sizer);
annotationsPane = (doc.createElementNS(element.namespaceURI, "div"));
@@ -8620,7 +8356,6 @@ runtime.loadClass("gui.AnnotationViewManager");
modifyDrawElements(odfnode.body, css);
cloneMasterPages(container, shadowContent, odfnode.body, css);
modifyTables(odfnode.body, element.namespaceURI);
- modifyLinks(odfnode.body);
modifyLineBreakElements(odfnode.body);
expandSpaceElements(odfnode.body);
expandTabElements(odfnode.body);
@@ -8628,30 +8363,24 @@ runtime.loadClass("gui.AnnotationViewManager");
loadVideos(container, odfnode.body);
loadLists(odfnode.body, css, element.namespaceURI);
sizer.insertBefore(shadowContent, sizer.firstChild);
- fixContainerSize()
+ zoomHelper.setZoomableElement(sizer)
}
function modifyAnnotations(odffragment) {
- var annotationNodes = domUtils.getElementsByTagNameNS(odffragment, officens, "annotation"), annotationEnds = domUtils.getElementsByTagNameNS(odffragment, officens, "annotation-end"), currentAnnotationName, i;
- function matchAnnotationEnd(element) {
- return currentAnnotationName === element.getAttributeNS(officens, "name")
- }
- for(i = 0;i < annotationNodes.length;i += 1) {
- currentAnnotationName = annotationNodes[i].getAttributeNS(officens, "name");
- annotationViewManager.addAnnotation({node:annotationNodes[i], end:annotationEnds.filter(matchAnnotationEnd)[0] || null})
- }
+ var annotationNodes = (domUtils.getElementsByTagNameNS(odffragment, officens, "annotation"));
+ annotationNodes.forEach(annotationViewManager.addAnnotation);
annotationViewManager.rerenderAnnotations()
}
function handleAnnotations(odfnode) {
if(allowAnnotations) {
if(!annotationsPane.parentNode) {
- sizer.appendChild(annotationsPane);
- fixContainerSize()
+ sizer.appendChild(annotationsPane)
}
if(annotationViewManager) {
annotationViewManager.forgetAnnotations()
}
- annotationViewManager = new gui.AnnotationViewManager(self, odfnode.body, annotationsPane);
- modifyAnnotations(odfnode.body)
+ annotationViewManager = new gui.AnnotationViewManager(self, odfnode.body, annotationsPane, showAnnotationRemoveButton);
+ modifyAnnotations(odfnode.body);
+ fixContainerSize()
}else {
if(annotationsPane.parentNode) {
sizer.removeChild(annotationsPane);
@@ -8662,6 +8391,9 @@ runtime.loadClass("gui.AnnotationViewManager");
}
function refreshOdf(suppressEvent) {
function callback() {
+ clearCSSStyleSheet(fontcss);
+ clearCSSStyleSheet(stylesxmlcss);
+ clearCSSStyleSheet(positioncss);
clear(element);
element.style.display = "inline-block";
var odfnode = odfcontainer.rootElement;
@@ -8679,22 +8411,22 @@ runtime.loadClass("gui.AnnotationViewManager");
callback()
}else {
runtime.log("WARNING: refreshOdf called but ODF was not DONE.");
- runtime.setTimeout(function later_cb() {
+ waitingForDoneTimeoutId = runtime.setTimeout(function later_cb() {
if(odfcontainer.state === odf.OdfContainer.DONE) {
callback()
}else {
runtime.log("will be back later...");
- runtime.setTimeout(later_cb, 500)
+ waitingForDoneTimeoutId = runtime.setTimeout(later_cb, 500)
}
}, 100)
}
}
this.refreshCSS = function() {
- handleStyles(odfcontainer, formatting, stylesxmlcss);
- fixContainerSize()
+ shouldRefreshCss = true;
+ redrawContainerTask.trigger()
};
this.refreshSize = function() {
- fixContainerSize()
+ redrawContainerTask.trigger()
};
this.odfContainer = function() {
return odfcontainer
@@ -8738,15 +8470,17 @@ runtime.loadClass("gui.AnnotationViewManager");
};
this.rerenderAnnotations = function() {
if(annotationViewManager) {
- annotationViewManager.rerenderAnnotations()
+ shouldRerenderAnnotations = true;
+ redrawContainerTask.trigger()
}
};
this.getSizer = function() {
- return sizer
+ return(sizer)
};
- this.enableAnnotations = function(allow) {
+ this.enableAnnotations = function(allow, showRemoveButton) {
if(allow !== allowAnnotations) {
allowAnnotations = allow;
+ showAnnotationRemoveButton = showRemoveButton;
if(odfcontainer) {
handleAnnotations(odfcontainer.rootElement)
}
@@ -8754,36 +8488,39 @@ runtime.loadClass("gui.AnnotationViewManager");
};
this.addAnnotation = function(annotation) {
if(annotationViewManager) {
- annotationViewManager.addAnnotation(annotation)
+ annotationViewManager.addAnnotation(annotation);
+ fixContainerSize()
}
};
this.forgetAnnotations = function() {
if(annotationViewManager) {
- annotationViewManager.forgetAnnotations()
+ annotationViewManager.forgetAnnotations();
+ fixContainerSize()
}
};
+ this.getZoomHelper = function() {
+ return zoomHelper
+ };
this.setZoomLevel = function(zoom) {
- zoomLevel = zoom;
- fixContainerSize()
+ zoomHelper.setZoomLevel(zoom)
};
this.getZoomLevel = function() {
- return zoomLevel
+ return zoomHelper.getZoomLevel()
};
this.fitToContainingElement = function(width, height) {
- var realWidth = element.offsetWidth / zoomLevel, realHeight = element.offsetHeight / zoomLevel;
- zoomLevel = width / realWidth;
- if(height / realHeight < zoomLevel) {
- zoomLevel = height / realHeight
+ var zoomLevel = zoomHelper.getZoomLevel(), realWidth = element.offsetWidth / zoomLevel, realHeight = element.offsetHeight / zoomLevel, zoom;
+ zoom = width / realWidth;
+ if(height / realHeight < zoom) {
+ zoom = height / realHeight
}
- fixContainerSize()
+ zoomHelper.setZoomLevel(zoom)
};
this.fitToWidth = function(width) {
- var realWidth = element.offsetWidth / zoomLevel;
- zoomLevel = width / realWidth;
- fixContainerSize()
+ var realWidth = element.offsetWidth / zoomHelper.getZoomLevel();
+ zoomHelper.setZoomLevel(width / realWidth)
};
this.fitSmart = function(width, height) {
- var realWidth, realHeight, newScale;
+ var realWidth, realHeight, newScale, zoomLevel = zoomHelper.getZoomLevel();
realWidth = element.offsetWidth / zoomLevel;
realHeight = element.offsetHeight / zoomLevel;
newScale = width / realWidth;
@@ -8792,13 +8529,11 @@ runtime.loadClass("gui.AnnotationViewManager");
newScale = height / realHeight
}
}
- zoomLevel = Math.min(1, newScale);
- fixContainerSize()
+ zoomHelper.setZoomLevel(Math.min(1, newScale))
};
this.fitToHeight = function(height) {
- var realHeight = element.offsetHeight / zoomLevel;
- zoomLevel = height / realHeight;
- fixContainerSize()
+ var realHeight = element.offsetHeight / zoomHelper.getZoomLevel();
+ zoomHelper.setZoomLevel(height / realHeight)
};
this.showFirstPage = function() {
pageSwitcher.showFirstPage()
@@ -8824,32 +8559,105 @@ runtime.loadClass("gui.AnnotationViewManager");
}
};
this.destroy = function(callback) {
- var head = (doc.getElementsByTagName("head")[0]);
+ var head = (doc.getElementsByTagName("head")[0]), cleanup = [pageSwitcher.destroy, redrawContainerTask.destroy];
+ runtime.clearTimeout(waitingForDoneTimeoutId);
if(annotationsPane && annotationsPane.parentNode) {
annotationsPane.parentNode.removeChild(annotationsPane)
}
- if(sizer) {
- element.removeChild(sizer);
- sizer = null
- }
- head.removeChild(webodfcss);
+ zoomHelper.destroy(function() {
+ if(sizer) {
+ element.removeChild(sizer);
+ sizer = null
+ }
+ });
+ removeWebODFStyleSheet(webodfcss);
head.removeChild(fontcss);
head.removeChild(stylesxmlcss);
head.removeChild(positioncss);
- pageSwitcher.destroy(callback)
+ async.destroyAll(cleanup, callback)
};
function init() {
webodfcss = addWebODFStyleSheet(doc);
pageSwitcher = new PageSwitcher(addStyleSheet(doc));
fontcss = addStyleSheet(doc);
stylesxmlcss = addStyleSheet(doc);
- positioncss = addStyleSheet(doc)
+ positioncss = addStyleSheet(doc);
+ redrawContainerTask = new core.ScheduledTask(redrawContainer, 0);
+ zoomHelper.subscribe(gui.ZoomHelper.signalZoomChanged, fixContainerSize)
}
init()
}
})();
/*
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.MemberProperties = function() {
+ this.fullName;
+ this.color;
+ this.imageUrl
+};
+ops.Member = function Member(memberId, properties) {
+ var props = new ops.MemberProperties;
+ function getMemberId() {
+ return memberId
+ }
+ function getProperties() {
+ return props
+ }
+ function setProperties(newProperties) {
+ Object.keys(newProperties).forEach(function(key) {
+ props[key] = newProperties[key]
+ })
+ }
+ function removeProperties(removedProperties) {
+ Object.keys(removedProperties).forEach(function(key) {
+ if(key !== "fullName" && (key !== "color" && (key !== "imageUrl" && props.hasOwnProperty(key)))) {
+ delete props[key]
+ }
+ })
+ }
+ this.getMemberId = getMemberId;
+ this.getProperties = getProperties;
+ this.setProperties = setProperties;
+ this.removeProperties = removeProperties;
+ function init() {
+ runtime.assert(Boolean(memberId), "No memberId was supplied!");
+ if(!properties.fullName) {
+ properties.fullName = runtime.tr("Unknown Author")
+ }
+ if(!properties.color) {
+ properties.color = "black"
+ }
+ if(!properties.imageUrl) {
+ properties.imageUrl = "avatar-joe.png"
+ }
+ props = properties
+ }
+ init()
+};
+/*
+
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
@@ -8885,109 +8693,194 @@ runtime.loadClass("gui.AnnotationViewManager");
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("core.LoopWatchDog");
-runtime.loadClass("odf.Namespaces");
-odf.TextStyleApplicator = function TextStyleApplicator(objectNameGenerator, formatting, automaticStyles) {
- var domUtils = new core.DomUtils, textns = odf.Namespaces.textns, stylens = odf.Namespaces.stylens, textProperties = "style:text-properties", webodfns = "urn:webodf:names:scope";
- function StyleLookup(info) {
- function compare(expected, actual) {
- if(typeof expected === "object" && typeof actual === "object") {
- return Object.keys(expected).every(function(key) {
- return compare(expected[key], actual[key])
- })
- }
- return expected === actual
+gui.StepCounter;
+gui.SelectionMover = function SelectionMover(cursor, rootNode) {
+ var odfUtils = new odf.OdfUtils, positionIterator, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
+ function getIteratorAtCursor() {
+ positionIterator.setUnfilteredPosition(cursor.getNode(), 0);
+ return positionIterator
+ }
+ function getMaximumNodePosition(node) {
+ return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
+ }
+ function getClientRect(clientRectangles, useRightEdge) {
+ var rectangle, simplifiedRectangle = null;
+ if(clientRectangles && clientRectangles.length > 0) {
+ rectangle = useRightEdge ? clientRectangles.item(clientRectangles.length - 1) : clientRectangles.item(0)
}
- this.isStyleApplied = function(textNode) {
- var appliedStyle = formatting.getAppliedStylesForElement(textNode);
- return compare(info, appliedStyle)
+ if(rectangle) {
+ simplifiedRectangle = {top:rectangle.top, left:useRightEdge ? rectangle.right : rectangle.left, bottom:rectangle.bottom}
}
+ return simplifiedRectangle
}
- function StyleManager(info) {
- var createdStyles = {};
- function createDirectFormat(existingStyleName, document) {
- var derivedStyleInfo, derivedStyleNode;
- derivedStyleInfo = existingStyleName ? formatting.createDerivedStyleObject(existingStyleName, "text", info) : info;
- derivedStyleNode = document.createElementNS(stylens, "style:style");
- formatting.updateStyle(derivedStyleNode, derivedStyleInfo);
- derivedStyleNode.setAttributeNS(stylens, "style:name", objectNameGenerator.generateStyleName());
- derivedStyleNode.setAttributeNS(stylens, "style:family", "text");
- derivedStyleNode.setAttributeNS(webodfns, "scope", "document-content");
- automaticStyles.appendChild(derivedStyleNode);
- return derivedStyleNode
+ function getVisibleRect(container, offset, range, useRightEdge) {
+ var rectangle, nodeType = container.nodeType;
+ range.setStart(container, offset);
+ range.collapse(!useRightEdge);
+ rectangle = getClientRect(range.getClientRects(), useRightEdge === true);
+ if(!rectangle && offset > 0) {
+ range.setStart(container, offset - 1);
+ range.setEnd(container, offset);
+ rectangle = getClientRect(range.getClientRects(), true)
}
- function getDirectStyle(existingStyleName, document) {
- existingStyleName = existingStyleName || "";
- if(!createdStyles.hasOwnProperty(existingStyleName)) {
- createdStyles[existingStyleName] = createDirectFormat(existingStyleName, document)
+ if(!rectangle) {
+ if(nodeType === Node.ELEMENT_NODE && (offset > 0 && (container).childNodes.length >= offset)) {
+ rectangle = getVisibleRect(container, offset - 1, range, true)
+ }else {
+ if(container.nodeType === Node.TEXT_NODE && offset > 0) {
+ rectangle = getVisibleRect(container, offset - 1, range, true)
+ }else {
+ if(container.previousSibling) {
+ rectangle = getVisibleRect(container.previousSibling, getMaximumNodePosition(container.previousSibling), range, true)
+ }else {
+ if(container.parentNode && container.parentNode !== rootNode) {
+ rectangle = getVisibleRect(container.parentNode, 0, range, false)
+ }else {
+ range.selectNode(rootNode);
+ rectangle = getClientRect(range.getClientRects(), false)
+ }
+ }
+ }
}
- return createdStyles[existingStyleName].getAttributeNS(stylens, "name")
}
- this.applyStyleToContainer = function(container) {
- var name = getDirectStyle(container.getAttributeNS(textns, "style-name"), container.ownerDocument);
- container.setAttributeNS(textns, "text:style-name", name)
+ runtime.assert(Boolean(rectangle), "No visible rectangle found");
+ return(rectangle)
+ }
+ function convertForwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
+ var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
+ while(stepsFilter1 > 0 && iterator.nextPosition()) {
+ watch.check();
+ if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
+ pendingStepsFilter2 += 1;
+ if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
+ stepsFilter2 += pendingStepsFilter2;
+ pendingStepsFilter2 = 0;
+ stepsFilter1 -= 1
+ }
+ }
}
+ return stepsFilter2
}
- function isTextSpan(node) {
- return node.localName === "span" && node.namespaceURI === textns
+ function convertBackwardStepsBetweenFilters(stepsFilter1, filter1, filter2) {
+ var iterator = getIteratorAtCursor(), watch = new core.LoopWatchDog(1E4), pendingStepsFilter2 = 0, stepsFilter2 = 0;
+ while(stepsFilter1 > 0 && iterator.previousPosition()) {
+ watch.check();
+ if(filter2.acceptPosition(iterator) === FILTER_ACCEPT) {
+ pendingStepsFilter2 += 1;
+ if(filter1.acceptPosition(iterator) === FILTER_ACCEPT) {
+ stepsFilter2 += pendingStepsFilter2;
+ pendingStepsFilter2 = 0;
+ stepsFilter1 -= 1
+ }
+ }
+ }
+ return stepsFilter2
}
- function moveToNewSpan(startNode, limits) {
- var document = startNode.ownerDocument, originalContainer = (startNode.parentNode), styledContainer, trailingContainer, moveTrailing, node, nextNode, loopGuard = new core.LoopWatchDog(1E4), styledNodes = [];
- if(!isTextSpan(originalContainer)) {
- styledContainer = document.createElementNS(textns, "text:span");
- originalContainer.insertBefore(styledContainer, startNode);
- moveTrailing = false
- }else {
- if(startNode.previousSibling && !domUtils.rangeContainsNode(limits, (originalContainer.firstChild))) {
- styledContainer = originalContainer.cloneNode(false);
- originalContainer.parentNode.insertBefore(styledContainer, originalContainer.nextSibling);
- moveTrailing = true
- }else {
- styledContainer = originalContainer;
- moveTrailing = true
+ function countLineSteps(filter, direction, iterator) {
+ var c = iterator.container(), steps = 0, bestContainer = null, bestOffset, bestXDiff = 10, xDiff, bestCount = 0, top, left, lastTop, rect, range = (rootNode.ownerDocument.createRange()), watch = new core.LoopWatchDog(1E4);
+ rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
+ top = rect.top;
+ left = rect.left;
+ lastTop = top;
+ while((direction < 0 ? iterator.previousPosition() : iterator.nextPosition()) === true) {
+ watch.check();
+ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
+ steps += 1;
+ c = iterator.container();
+ rect = getVisibleRect(c, iterator.unfilteredDomOffset(), range);
+ if(rect.top !== top) {
+ if(rect.top !== lastTop && lastTop !== top) {
+ break
+ }
+ lastTop = rect.top;
+ xDiff = Math.abs(left - rect.left);
+ if(bestContainer === null || xDiff < bestXDiff) {
+ bestContainer = c;
+ bestOffset = iterator.unfilteredDomOffset();
+ bestXDiff = xDiff;
+ bestCount = steps
+ }
+ }
}
}
- styledNodes.push(startNode);
- node = startNode.nextSibling;
- while(node && domUtils.rangeContainsNode(limits, node)) {
- loopGuard.check();
- styledNodes.push(node);
- node = node.nextSibling
+ if(bestContainer !== null) {
+ iterator.setUnfilteredPosition(bestContainer, (bestOffset));
+ steps = bestCount
+ }else {
+ steps = 0
}
- styledNodes.forEach(function(n) {
- if(n.parentNode !== styledContainer) {
- styledContainer.appendChild(n)
+ range.detach();
+ return steps
+ }
+ function countLinesSteps(lines, filter) {
+ var iterator = getIteratorAtCursor(), stepCount = 0, steps = 0, direction = lines < 0 ? -1 : 1;
+ lines = Math.abs(lines);
+ while(lines > 0) {
+ stepCount += countLineSteps(filter, direction, iterator);
+ if(stepCount === 0) {
+ break
}
- });
- if(node && moveTrailing) {
- trailingContainer = styledContainer.cloneNode(false);
- styledContainer.parentNode.insertBefore(trailingContainer, styledContainer.nextSibling);
- while(node) {
- loopGuard.check();
- nextNode = node.nextSibling;
- trailingContainer.appendChild(node);
- node = nextNode
+ steps += stepCount;
+ lines -= 1
+ }
+ return steps * direction
+ }
+ function countStepsToLineBoundary(direction, filter) {
+ var fnNextPos, increment, lastRect, rect, onSameLine, iterator = getIteratorAtCursor(), paragraphNode = odfUtils.getParagraphElement(iterator.getCurrentNode()), steps = 0, range = (rootNode.ownerDocument.createRange());
+ if(direction < 0) {
+ fnNextPos = iterator.previousPosition;
+ increment = -1
+ }else {
+ fnNextPos = iterator.nextPosition;
+ increment = 1
+ }
+ lastRect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
+ while(fnNextPos.call(iterator)) {
+ if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
+ if(odfUtils.getParagraphElement(iterator.getCurrentNode()) !== paragraphNode) {
+ break
+ }
+ rect = getVisibleRect(iterator.container(), iterator.unfilteredDomOffset(), range);
+ if(rect.bottom !== lastRect.bottom) {
+ onSameLine = rect.top >= lastRect.top && rect.bottom < lastRect.bottom || rect.top <= lastRect.top && rect.bottom > lastRect.bottom;
+ if(!onSameLine) {
+ break
+ }
+ }
+ steps += increment;
+ lastRect = rect
}
}
- return(styledContainer)
+ range.detach();
+ return steps
}
- this.applyStyle = function(textNodes, limits, info) {
- var textPropsOnly = {}, isStyled, container, styleCache, styleLookup;
- runtime.assert(info && info.hasOwnProperty(textProperties), "applyStyle without any text properties");
- textPropsOnly[textProperties] = info[textProperties];
- styleCache = new StyleManager(textPropsOnly);
- styleLookup = new StyleLookup(textPropsOnly);
- function apply(n) {
- isStyled = styleLookup.isStyleApplied(n);
- if(isStyled === false) {
- container = moveToNewSpan(n, limits);
- styleCache.applyStyleToContainer(container)
+ this.getStepCounter = function() {
+ return{convertForwardStepsBetweenFilters:convertForwardStepsBetweenFilters, convertBackwardStepsBetweenFilters:convertBackwardStepsBetweenFilters, countLinesSteps:countLinesSteps, countStepsToLineBoundary:countStepsToLineBoundary}
+ };
+ function init() {
+ positionIterator = gui.SelectionMover.createPositionIterator(rootNode);
+ var range = rootNode.ownerDocument.createRange();
+ range.setStart(positionIterator.container(), positionIterator.unfilteredDomOffset());
+ range.collapse(true);
+ cursor.setSelectedRange(range)
+ }
+ init()
+};
+gui.SelectionMover.createPositionIterator = function(rootNode) {
+ function CursorFilter() {
+ this.acceptNode = function(node) {
+ if(!node || (node.namespaceURI === "urn:webodf:names:cursor" || node.namespaceURI === "urn:webodf:names:editinfo")) {
+ return NodeFilter.FILTER_REJECT
}
+ return NodeFilter.FILTER_ACCEPT
}
- textNodes.forEach(apply)
}
+ var filter = new CursorFilter;
+ return new core.PositionIterator(rootNode, 5, filter, false)
};
+(function() {
+ return gui.SelectionMover
+})();
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -9025,1276 +8918,100 @@ odf.TextStyleApplicator = function TextStyleApplicator(objectNameGenerator, form
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("odf.OdfUtils");
-gui.StyleHelper = function StyleHelper(formatting) {
- var odfUtils = new odf.OdfUtils, textns = odf.Namespaces.textns;
- function getAppliedStyles(range) {
- var container, nodes;
- if(range.collapsed) {
- container = range.startContainer;
- if(container.hasChildNodes() && range.startOffset < container.childNodes.length) {
- container = container.childNodes.item(range.startOffset)
- }
- nodes = [container]
- }else {
- nodes = odfUtils.getTextNodes(range, true)
- }
- return formatting.getAppliedStyles(nodes)
- }
- this.getAppliedStyles = getAppliedStyles;
- function hasTextPropertyValue(appliedStyles, propertyName, propertyValue) {
- var hasOtherValue = true, properties, i;
- for(i = 0;i < appliedStyles.length;i += 1) {
- properties = appliedStyles[i]["style:text-properties"];
- hasOtherValue = !properties || properties[propertyName] !== propertyValue;
- if(hasOtherValue) {
- break
- }
- }
- return!hasOtherValue
- }
- this.isBold = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "fo:font-weight", "bold")
- };
- this.isItalic = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "fo:font-style", "italic")
- };
- this.hasUnderline = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "style:text-underline-style", "solid")
- };
- this.hasStrikeThrough = function(appliedStyles) {
- return hasTextPropertyValue(appliedStyles, "style:text-line-through-style", "solid")
- };
- function hasParagraphPropertyValue(range, propertyName, propertyValues) {
- var paragraphStyleName, paragraphStyleElement, paragraphStyleAttributes, properties, nodes = odfUtils.getParagraphElements(range), isStyleChecked = {}, isDefaultParagraphStyleChecked = false;
- function pickDefaultParagraphStyleElement() {
- isDefaultParagraphStyleChecked = true;
- paragraphStyleElement = formatting.getDefaultStyleElement("paragraph");
- if(!paragraphStyleElement) {
- paragraphStyleElement = null
- }
- }
- while(nodes.length > 0) {
- paragraphStyleName = nodes[0].getAttributeNS(textns, "style-name");
- if(paragraphStyleName) {
- if(!isStyleChecked[paragraphStyleName]) {
- paragraphStyleElement = formatting.getStyleElement(paragraphStyleName, "paragraph");
- isStyleChecked[paragraphStyleName] = true;
- if(!paragraphStyleElement && !isDefaultParagraphStyleChecked) {
- pickDefaultParagraphStyleElement()
- }
- }
- }else {
- if(!isDefaultParagraphStyleChecked) {
- pickDefaultParagraphStyleElement()
- }else {
- paragraphStyleElement = undefined
- }
- }
- if(paragraphStyleElement !== undefined) {
- if(paragraphStyleElement === null) {
- paragraphStyleAttributes = formatting.getSystemDefaultStyleAttributes("paragraph")
- }else {
- paragraphStyleAttributes = formatting.getInheritedStyleAttributes((paragraphStyleElement), true)
- }
- properties = paragraphStyleAttributes["style:paragraph-properties"];
- if(properties && propertyValues.indexOf(properties[propertyName]) === -1) {
- return false
- }
- }
- nodes.pop()
- }
- return true
- }
- this.isAlignedLeft = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["left", "start"])
- };
- this.isAlignedCenter = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["center"])
- };
- this.isAlignedRight = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["right", "end"])
- };
- this.isAlignedJustified = function(range) {
- return hasParagraphPropertyValue(range, "fo:text-align", ["justify"])
- }
+ops.Document = function Document() {
};
-core.RawDeflate = function() {
- var zip_WSIZE = 32768, zip_STORED_BLOCK = 0, zip_STATIC_TREES = 1, zip_DYN_TREES = 2, zip_DEFAULT_LEVEL = 6, zip_FULL_SEARCH = true, zip_INBUFSIZ = 32768, zip_INBUF_EXTRA = 64, zip_OUTBUFSIZ = 1024 * 8, zip_window_size = 2 * zip_WSIZE, zip_MIN_MATCH = 3, zip_MAX_MATCH = 258, zip_BITS = 16, zip_LIT_BUFSIZE = 8192, zip_HASH_BITS = 13, zip_DIST_BUFSIZE = zip_LIT_BUFSIZE, zip_HASH_SIZE = 1 << zip_HASH_BITS, zip_HASH_MASK = zip_HASH_SIZE - 1, zip_WMASK = zip_WSIZE - 1, zip_NIL = 0, zip_TOO_FAR = 4096,
- zip_MIN_LOOKAHEAD = zip_MAX_MATCH + zip_MIN_MATCH + 1, zip_MAX_DIST = zip_WSIZE - zip_MIN_LOOKAHEAD, zip_SMALLEST = 1, zip_MAX_BITS = 15, zip_MAX_BL_BITS = 7, zip_LENGTH_CODES = 29, zip_LITERALS = 256, zip_END_BLOCK = 256, zip_L_CODES = zip_LITERALS + 1 + zip_LENGTH_CODES, zip_D_CODES = 30, zip_BL_CODES = 19, zip_REP_3_6 = 16, zip_REPZ_3_10 = 17, zip_REPZ_11_138 = 18, zip_HEAP_SIZE = 2 * zip_L_CODES + 1, zip_H_SHIFT = parseInt((zip_HASH_BITS + zip_MIN_MATCH - 1) / zip_MIN_MATCH, 10), zip_free_queue,
- zip_qhead, zip_qtail, zip_initflag, zip_outbuf = null, zip_outcnt, zip_outoff, zip_complete, zip_window, zip_d_buf, zip_l_buf, zip_prev, zip_bi_buf, zip_bi_valid, zip_block_start, zip_ins_h, zip_hash_head, zip_prev_match, zip_match_available, zip_match_length, zip_prev_length, zip_strstart, zip_match_start, zip_eofile, zip_lookahead, zip_max_chain_length, zip_max_lazy_match, zip_compr_level, zip_good_match, zip_nice_match, zip_dyn_ltree, zip_dyn_dtree, zip_static_ltree, zip_static_dtree, zip_bl_tree,
- zip_l_desc, zip_d_desc, zip_bl_desc, zip_bl_count, zip_heap, zip_heap_len, zip_heap_max, zip_depth, zip_length_code, zip_dist_code, zip_base_length, zip_base_dist, zip_flag_buf, zip_last_lit, zip_last_dist, zip_last_flags, zip_flags, zip_flag_bit, zip_opt_len, zip_static_len, zip_deflate_data, zip_deflate_pos, zip_extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], zip_extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9,
- 9, 10, 10, 11, 11, 12, 12, 13, 13], zip_extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], zip_bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], zip_configuration_table;
- if(zip_LIT_BUFSIZE > zip_INBUFSIZ) {
- runtime.log("error: zip_INBUFSIZ is too small")
- }
- if(zip_WSIZE << 1 > 1 << zip_BITS) {
- runtime.log("error: zip_WSIZE is too large")
- }
- if(zip_HASH_BITS > zip_BITS - 1) {
- runtime.log("error: zip_HASH_BITS is too large")
- }
- if(zip_HASH_BITS < 8 || zip_MAX_MATCH !== 258) {
- runtime.log("error: Code too clever")
- }
- function Zip_DeflateCT() {
- this.fc = 0;
- this.dl = 0
- }
- function Zip_DeflateTreeDesc() {
- this.dyn_tree = null;
- this.static_tree = null;
- this.extra_bits = null;
- this.extra_base = 0;
- this.elems = 0;
- this.max_length = 0;
- this.max_code = 0
- }
- function Zip_DeflateConfiguration(a, b, c, d) {
- this.good_length = a;
- this.max_lazy = b;
- this.nice_length = c;
- this.max_chain = d
- }
- function Zip_DeflateBuffer() {
- this.next = null;
- this.len = 0;
- this.ptr = [];
- this.ptr.length = zip_OUTBUFSIZ;
- this.off = 0
- }
- zip_configuration_table = [new Zip_DeflateConfiguration(0, 0, 0, 0), new Zip_DeflateConfiguration(4, 4, 8, 4), new Zip_DeflateConfiguration(4, 5, 16, 8), new Zip_DeflateConfiguration(4, 6, 32, 32), new Zip_DeflateConfiguration(4, 4, 16, 16), new Zip_DeflateConfiguration(8, 16, 32, 32), new Zip_DeflateConfiguration(8, 16, 128, 128), new Zip_DeflateConfiguration(8, 32, 128, 256), new Zip_DeflateConfiguration(32, 128, 258, 1024), new Zip_DeflateConfiguration(32, 258, 258, 4096)];
- function zip_deflate_start(level) {
- var i;
- if(!level) {
- level = zip_DEFAULT_LEVEL
- }else {
- if(level < 1) {
- level = 1
- }else {
- if(level > 9) {
- level = 9
- }
- }
- }
- zip_compr_level = level;
- zip_initflag = false;
- zip_eofile = false;
- if(zip_outbuf !== null) {
- return
- }
- zip_free_queue = zip_qhead = zip_qtail = null;
- zip_outbuf = [];
- zip_outbuf.length = zip_OUTBUFSIZ;
- zip_window = [];
- zip_window.length = zip_window_size;
- zip_d_buf = [];
- zip_d_buf.length = zip_DIST_BUFSIZE;
- zip_l_buf = [];
- zip_l_buf.length = zip_INBUFSIZ + zip_INBUF_EXTRA;
- zip_prev = [];
- zip_prev.length = 1 << zip_BITS;
- zip_dyn_ltree = [];
- zip_dyn_ltree.length = zip_HEAP_SIZE;
- for(i = 0;i < zip_HEAP_SIZE;i++) {
- zip_dyn_ltree[i] = new Zip_DeflateCT
- }
- zip_dyn_dtree = [];
- zip_dyn_dtree.length = 2 * zip_D_CODES + 1;
- for(i = 0;i < 2 * zip_D_CODES + 1;i++) {
- zip_dyn_dtree[i] = new Zip_DeflateCT
- }
- zip_static_ltree = [];
- zip_static_ltree.length = zip_L_CODES + 2;
- for(i = 0;i < zip_L_CODES + 2;i++) {
- zip_static_ltree[i] = new Zip_DeflateCT
- }
- zip_static_dtree = [];
- zip_static_dtree.length = zip_D_CODES;
- for(i = 0;i < zip_D_CODES;i++) {
- zip_static_dtree[i] = new Zip_DeflateCT
- }
- zip_bl_tree = [];
- zip_bl_tree.length = 2 * zip_BL_CODES + 1;
- for(i = 0;i < 2 * zip_BL_CODES + 1;i++) {
- zip_bl_tree[i] = new Zip_DeflateCT
- }
- zip_l_desc = new Zip_DeflateTreeDesc;
- zip_d_desc = new Zip_DeflateTreeDesc;
- zip_bl_desc = new Zip_DeflateTreeDesc;
- zip_bl_count = [];
- zip_bl_count.length = zip_MAX_BITS + 1;
- zip_heap = [];
- zip_heap.length = 2 * zip_L_CODES + 1;
- zip_depth = [];
- zip_depth.length = 2 * zip_L_CODES + 1;
- zip_length_code = [];
- zip_length_code.length = zip_MAX_MATCH - zip_MIN_MATCH + 1;
- zip_dist_code = [];
- zip_dist_code.length = 512;
- zip_base_length = [];
- zip_base_length.length = zip_LENGTH_CODES;
- zip_base_dist = [];
- zip_base_dist.length = zip_D_CODES;
- zip_flag_buf = [];
- zip_flag_buf.length = parseInt(zip_LIT_BUFSIZE / 8, 10)
- }
- var zip_reuse_queue = function(p) {
- p.next = zip_free_queue;
- zip_free_queue = p
- };
- var zip_new_queue = function() {
- var p;
- if(zip_free_queue !== null) {
- p = zip_free_queue;
- zip_free_queue = zip_free_queue.next
- }else {
- p = new Zip_DeflateBuffer
- }
- p.next = null;
- p.len = p.off = 0;
- return p
- };
- var zip_head1 = function(i) {
- return zip_prev[zip_WSIZE + i]
- };
- var zip_head2 = function(i, val) {
- zip_prev[zip_WSIZE + i] = val;
- return val
- };
- var zip_qoutbuf = function() {
- var q, i;
- if(zip_outcnt !== 0) {
- q = zip_new_queue();
- if(zip_qhead === null) {
- zip_qhead = zip_qtail = q
- }else {
- zip_qtail = zip_qtail.next = q
- }
- q.len = zip_outcnt - zip_outoff;
- for(i = 0;i < q.len;i++) {
- q.ptr[i] = zip_outbuf[zip_outoff + i]
- }
- zip_outcnt = zip_outoff = 0
- }
- };
- var zip_put_byte = function(c) {
- zip_outbuf[zip_outoff + zip_outcnt++] = c;
- if(zip_outoff + zip_outcnt === zip_OUTBUFSIZ) {
- zip_qoutbuf()
- }
- };
- var zip_put_short = function(w) {
- w &= 65535;
- if(zip_outoff + zip_outcnt < zip_OUTBUFSIZ - 2) {
- zip_outbuf[zip_outoff + zip_outcnt++] = w & 255;
- zip_outbuf[zip_outoff + zip_outcnt++] = w >>> 8
- }else {
- zip_put_byte(w & 255);
- zip_put_byte(w >>> 8)
- }
- };
- var zip_INSERT_STRING = function() {
- zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + zip_MIN_MATCH - 1] & 255) & zip_HASH_MASK;
- zip_hash_head = zip_head1(zip_ins_h);
- zip_prev[zip_strstart & zip_WMASK] = zip_hash_head;
- zip_head2(zip_ins_h, zip_strstart)
- };
- var zip_Buf_size = 16;
- var zip_send_bits = function(value, length) {
- if(zip_bi_valid > zip_Buf_size - length) {
- zip_bi_buf |= value << zip_bi_valid;
- zip_put_short(zip_bi_buf);
- zip_bi_buf = value >> zip_Buf_size - zip_bi_valid;
- zip_bi_valid += length - zip_Buf_size
- }else {
- zip_bi_buf |= value << zip_bi_valid;
- zip_bi_valid += length
- }
- };
- var zip_SEND_CODE = function(c, tree) {
- zip_send_bits(tree[c].fc, tree[c].dl)
- };
- var zip_D_CODE = function(dist) {
- return(dist < 256 ? zip_dist_code[dist] : zip_dist_code[256 + (dist >> 7)]) & 255
- };
- var zip_SMALLER = function(tree, n, m) {
- return tree[n].fc < tree[m].fc || tree[n].fc === tree[m].fc && zip_depth[n] <= zip_depth[m]
- };
- var zip_read_buff = function(buff, offset, n) {
- var i;
- for(i = 0;i < n && zip_deflate_pos < zip_deflate_data.length;i++) {
- buff[offset + i] = zip_deflate_data.charCodeAt(zip_deflate_pos++) & 255
- }
- return i
- };
- var zip_fill_window = function() {
- var n, m;
- var more = zip_window_size - zip_lookahead - zip_strstart;
- if(more === -1) {
- more--
- }else {
- if(zip_strstart >= zip_WSIZE + zip_MAX_DIST) {
- for(n = 0;n < zip_WSIZE;n++) {
- zip_window[n] = zip_window[n + zip_WSIZE]
- }
- zip_match_start -= zip_WSIZE;
- zip_strstart -= zip_WSIZE;
- zip_block_start -= zip_WSIZE;
- for(n = 0;n < zip_HASH_SIZE;n++) {
- m = zip_head1(n);
- zip_head2(n, m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL)
- }
- for(n = 0;n < zip_WSIZE;n++) {
- m = zip_prev[n];
- zip_prev[n] = m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL
- }
- more += zip_WSIZE
- }
- }
- if(!zip_eofile) {
- n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more);
- if(n <= 0) {
- zip_eofile = true
- }else {
- zip_lookahead += n
- }
- }
- };
- var zip_lm_init = function() {
- var j;
- for(j = 0;j < zip_HASH_SIZE;j++) {
- zip_prev[zip_WSIZE + j] = 0
- }
- zip_max_lazy_match = zip_configuration_table[zip_compr_level].max_lazy;
- zip_good_match = zip_configuration_table[zip_compr_level].good_length;
- if(!zip_FULL_SEARCH) {
- zip_nice_match = zip_configuration_table[zip_compr_level].nice_length
- }
- zip_max_chain_length = zip_configuration_table[zip_compr_level].max_chain;
- zip_strstart = 0;
- zip_block_start = 0;
- zip_lookahead = zip_read_buff(zip_window, 0, 2 * zip_WSIZE);
- if(zip_lookahead <= 0) {
- zip_eofile = true;
- zip_lookahead = 0;
- return
- }
- zip_eofile = false;
- while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
- zip_fill_window()
- }
- zip_ins_h = 0;
- for(j = 0;j < zip_MIN_MATCH - 1;j++) {
- zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[j] & 255) & zip_HASH_MASK
- }
- };
- var zip_longest_match = function(cur_match) {
- var chain_length = zip_max_chain_length;
- var scanp = zip_strstart;
- var matchp;
- var len;
- var best_len = zip_prev_length;
- var limit = zip_strstart > zip_MAX_DIST ? zip_strstart - zip_MAX_DIST : zip_NIL;
- var strendp = zip_strstart + zip_MAX_MATCH;
- var scan_end1 = zip_window[scanp + best_len - 1];
- var scan_end = zip_window[scanp + best_len];
- if(zip_prev_length >= zip_good_match) {
- chain_length >>= 2
- }
- do {
- matchp = cur_match;
- if(zip_window[matchp + best_len] !== scan_end || (zip_window[matchp + best_len - 1] !== scan_end1 || (zip_window[matchp] !== zip_window[scanp] || zip_window[++matchp] !== zip_window[scanp + 1]))) {
- continue
- }
- scanp += 2;
- matchp++;
- do {
- ++scanp
- }while(zip_window[scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && (zip_window[++scanp] === zip_window[++matchp] && scanp < strendp))))))));
- len = zip_MAX_MATCH - (strendp - scanp);
- scanp = strendp - zip_MAX_MATCH;
- if(len > best_len) {
- zip_match_start = cur_match;
- best_len = len;
- if(zip_FULL_SEARCH) {
- if(len >= zip_MAX_MATCH) {
- break
- }
- }else {
- if(len >= zip_nice_match) {
- break
- }
- }
- scan_end1 = zip_window[scanp + best_len - 1];
- scan_end = zip_window[scanp + best_len]
- }
- cur_match = zip_prev[cur_match & zip_WMASK]
- }while(cur_match > limit && --chain_length !== 0);
- return best_len
- };
- var zip_ct_tally = function(dist, lc) {
- zip_l_buf[zip_last_lit++] = lc;
- if(dist === 0) {
- zip_dyn_ltree[lc].fc++
- }else {
- dist--;
- zip_dyn_ltree[zip_length_code[lc] + zip_LITERALS + 1].fc++;
- zip_dyn_dtree[zip_D_CODE(dist)].fc++;
- zip_d_buf[zip_last_dist++] = dist;
- zip_flags |= zip_flag_bit
- }
- zip_flag_bit <<= 1;
- if((zip_last_lit & 7) === 0) {
- zip_flag_buf[zip_last_flags++] = zip_flags;
- zip_flags = 0;
- zip_flag_bit = 1
- }
- if(zip_compr_level > 2 && (zip_last_lit & 4095) === 0) {
- var out_length = zip_last_lit * 8;
- var in_length = zip_strstart - zip_block_start;
- var dcode;
- for(dcode = 0;dcode < zip_D_CODES;dcode++) {
- out_length += zip_dyn_dtree[dcode].fc * (5 + zip_extra_dbits[dcode])
- }
- out_length >>= 3;
- if(zip_last_dist < parseInt(zip_last_lit / 2, 10) && out_length < parseInt(in_length / 2, 10)) {
- return true
- }
- }
- return zip_last_lit === zip_LIT_BUFSIZE - 1 || zip_last_dist === zip_DIST_BUFSIZE
- };
- var zip_pqdownheap = function(tree, k) {
- var v = zip_heap[k];
- var j = k << 1;
- while(j <= zip_heap_len) {
- if(j < zip_heap_len && zip_SMALLER(tree, zip_heap[j + 1], zip_heap[j])) {
- j++
- }
- if(zip_SMALLER(tree, v, zip_heap[j])) {
- break
- }
- zip_heap[k] = zip_heap[j];
- k = j;
- j <<= 1
- }
- zip_heap[k] = v
- };
- var zip_gen_bitlen = function(desc) {
- var tree = desc.dyn_tree;
- var extra = desc.extra_bits;
- var base = desc.extra_base;
- var max_code = desc.max_code;
- var max_length = desc.max_length;
- var stree = desc.static_tree;
- var h;
- var n, m;
- var bits;
- var xbits;
- var f;
- var overflow = 0;
- for(bits = 0;bits <= zip_MAX_BITS;bits++) {
- zip_bl_count[bits] = 0
- }
- tree[zip_heap[zip_heap_max]].dl = 0;
- for(h = zip_heap_max + 1;h < zip_HEAP_SIZE;h++) {
- n = zip_heap[h];
- bits = tree[tree[n].dl].dl + 1;
- if(bits > max_length) {
- bits = max_length;
- overflow++
- }
- tree[n].dl = bits;
- if(n > max_code) {
- continue
- }
- zip_bl_count[bits]++;
- xbits = 0;
- if(n >= base) {
- xbits = extra[n - base]
- }
- f = tree[n].fc;
- zip_opt_len += f * (bits + xbits);
- if(stree !== null) {
- zip_static_len += f * (stree[n].dl + xbits)
- }
- }
- if(overflow === 0) {
- return
- }
- do {
- bits = max_length - 1;
- while(zip_bl_count[bits] === 0) {
- bits--
- }
- zip_bl_count[bits]--;
- zip_bl_count[bits + 1] += 2;
- zip_bl_count[max_length]--;
- overflow -= 2
- }while(overflow > 0);
- for(bits = max_length;bits !== 0;bits--) {
- n = zip_bl_count[bits];
- while(n !== 0) {
- m = zip_heap[--h];
- if(m > max_code) {
- continue
- }
- if(tree[m].dl !== bits) {
- zip_opt_len += (bits - tree[m].dl) * tree[m].fc;
- tree[m].fc = bits
- }
- n--
- }
- }
- };
- var zip_bi_reverse = function(code, len) {
- var res = 0;
- do {
- res |= code & 1;
- code >>= 1;
- res <<= 1
- }while(--len > 0);
- return res >> 1
- };
- var zip_gen_codes = function(tree, max_code) {
- var next_code = [];
- next_code.length = zip_MAX_BITS + 1;
- var code = 0;
- var bits;
- var n;
- for(bits = 1;bits <= zip_MAX_BITS;bits++) {
- code = code + zip_bl_count[bits - 1] << 1;
- next_code[bits] = code
- }
- var len;
- for(n = 0;n <= max_code;n++) {
- len = tree[n].dl;
- if(len === 0) {
- continue
- }
- tree[n].fc = zip_bi_reverse(next_code[len]++, len)
- }
- };
- var zip_build_tree = function(desc) {
- var tree = desc.dyn_tree;
- var stree = desc.static_tree;
- var elems = desc.elems;
- var n, m;
- var max_code = -1;
- var node = elems;
- zip_heap_len = 0;
- zip_heap_max = zip_HEAP_SIZE;
- for(n = 0;n < elems;n++) {
- if(tree[n].fc !== 0) {
- zip_heap[++zip_heap_len] = max_code = n;
- zip_depth[n] = 0
- }else {
- tree[n].dl = 0
- }
- }
- var xnew;
- while(zip_heap_len < 2) {
- xnew = zip_heap[++zip_heap_len] = max_code < 2 ? ++max_code : 0;
- tree[xnew].fc = 1;
- zip_depth[xnew] = 0;
- zip_opt_len--;
- if(stree !== null) {
- zip_static_len -= stree[xnew].dl
- }
- }
- desc.max_code = max_code;
- for(n = zip_heap_len >> 1;n >= 1;n--) {
- zip_pqdownheap(tree, n)
- }
- do {
- n = zip_heap[zip_SMALLEST];
- zip_heap[zip_SMALLEST] = zip_heap[zip_heap_len--];
- zip_pqdownheap(tree, zip_SMALLEST);
- m = zip_heap[zip_SMALLEST];
- zip_heap[--zip_heap_max] = n;
- zip_heap[--zip_heap_max] = m;
- tree[node].fc = tree[n].fc + tree[m].fc;
- if(zip_depth[n] > zip_depth[m] + 1) {
- zip_depth[node] = zip_depth[n]
- }else {
- zip_depth[node] = zip_depth[m] + 1
- }
- tree[n].dl = tree[m].dl = node;
- zip_heap[zip_SMALLEST] = node++;
- zip_pqdownheap(tree, zip_SMALLEST)
- }while(zip_heap_len >= 2);
- zip_heap[--zip_heap_max] = zip_heap[zip_SMALLEST];
- zip_gen_bitlen(desc);
- zip_gen_codes(tree, max_code)
+ops.Document.prototype.getMemberIds = function() {
+};
+ops.Document.prototype.removeCursor = function(memberid) {
+};
+ops.Document.prototype.getDocumentElement = function() {
+};
+ops.Document.prototype.getRootNode = function() {
+};
+ops.Document.prototype.getDOMDocument = function() {
+};
+ops.Document.prototype.cloneDocumentElement = function() {
+};
+ops.Document.prototype.setDocumentElement = function(element) {
+};
+ops.Document.prototype.subscribe = function(eventid, cb) {
+};
+ops.Document.prototype.unsubscribe = function(eventid, cb) {
+};
+ops.Document.prototype.getCanvas = function() {
+};
+ops.Document.prototype.createRootFilter = function(inputMemberId) {
+};
+ops.Document.signalCursorAdded = "cursor/added";
+ops.Document.signalCursorRemoved = "cursor/removed";
+ops.Document.signalCursorMoved = "cursor/moved";
+ops.Document.signalMemberAdded = "member/added";
+ops.Document.signalMemberUpdated = "member/updated";
+ops.Document.signalMemberRemoved = "member/removed";
+ops.OdtCursor = function OdtCursor(memberId, document) {
+ var self = this, validSelectionTypes = {}, selectionType, selectionMover, cursor, events = new core.EventNotifier([ops.OdtCursor.signalCursorUpdated]);
+ this.removeFromDocument = function() {
+ cursor.remove()
};
- var zip_scan_tree = function(tree, max_code) {
- var n;
- var prevlen = -1;
- var curlen;
- var nextlen = tree[0].dl;
- var count = 0;
- var max_count = 7;
- var min_count = 4;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
- }
- tree[max_code + 1].dl = 65535;
- for(n = 0;n <= max_code;n++) {
- curlen = nextlen;
- nextlen = tree[n + 1].dl;
- if(++count < max_count && curlen === nextlen) {
- continue
- }
- if(count < min_count) {
- zip_bl_tree[curlen].fc += count
- }else {
- if(curlen !== 0) {
- if(curlen !== prevlen) {
- zip_bl_tree[curlen].fc++
- }
- zip_bl_tree[zip_REP_3_6].fc++
- }else {
- if(count <= 10) {
- zip_bl_tree[zip_REPZ_3_10].fc++
- }else {
- zip_bl_tree[zip_REPZ_11_138].fc++
- }
- }
- }
- count = 0;
- prevlen = curlen;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
- }else {
- if(curlen === nextlen) {
- max_count = 6;
- min_count = 3
- }else {
- max_count = 7;
- min_count = 4
- }
- }
- }
+ this.subscribe = function(eventid, cb) {
+ events.subscribe(eventid, cb)
};
- var zip_build_bl_tree = function() {
- var max_blindex;
- zip_scan_tree(zip_dyn_ltree, zip_l_desc.max_code);
- zip_scan_tree(zip_dyn_dtree, zip_d_desc.max_code);
- zip_build_tree(zip_bl_desc);
- for(max_blindex = zip_BL_CODES - 1;max_blindex >= 3;max_blindex--) {
- if(zip_bl_tree[zip_bl_order[max_blindex]].dl !== 0) {
- break
- }
- }
- zip_opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
- return max_blindex
+ this.unsubscribe = function(eventid, cb) {
+ events.unsubscribe(eventid, cb)
};
- var zip_bi_windup = function() {
- if(zip_bi_valid > 8) {
- zip_put_short(zip_bi_buf)
- }else {
- if(zip_bi_valid > 0) {
- zip_put_byte(zip_bi_buf)
- }
- }
- zip_bi_buf = 0;
- zip_bi_valid = 0
- };
- var zip_compress_block = function(ltree, dtree) {
- var dist;
- var lc;
- var lx = 0;
- var dx = 0;
- var fx = 0;
- var flag = 0;
- var code;
- var extra;
- if(zip_last_lit !== 0) {
- do {
- if((lx & 7) === 0) {
- flag = zip_flag_buf[fx++]
- }
- lc = zip_l_buf[lx++] & 255;
- if((flag & 1) === 0) {
- zip_SEND_CODE(lc, ltree)
- }else {
- code = zip_length_code[lc];
- zip_SEND_CODE(code + zip_LITERALS + 1, ltree);
- extra = zip_extra_lbits[code];
- if(extra !== 0) {
- lc -= zip_base_length[code];
- zip_send_bits(lc, extra)
- }
- dist = zip_d_buf[dx++];
- code = zip_D_CODE(dist);
- zip_SEND_CODE(code, dtree);
- extra = zip_extra_dbits[code];
- if(extra !== 0) {
- dist -= zip_base_dist[code];
- zip_send_bits(dist, extra)
- }
- }
- flag >>= 1
- }while(lx < zip_last_lit)
- }
- zip_SEND_CODE(zip_END_BLOCK, ltree)
+ this.getStepCounter = function() {
+ return selectionMover.getStepCounter()
};
- var zip_send_tree = function(tree, max_code) {
- var n;
- var prevlen = -1;
- var curlen;
- var nextlen = tree[0].dl;
- var count = 0;
- var max_count = 7;
- var min_count = 4;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
- }
- for(n = 0;n <= max_code;n++) {
- curlen = nextlen;
- nextlen = tree[n + 1].dl;
- if(++count < max_count && curlen === nextlen) {
- continue
- }
- if(count < min_count) {
- do {
- zip_SEND_CODE(curlen, zip_bl_tree)
- }while(--count !== 0)
- }else {
- if(curlen !== 0) {
- if(curlen !== prevlen) {
- zip_SEND_CODE(curlen, zip_bl_tree);
- count--
- }
- zip_SEND_CODE(zip_REP_3_6, zip_bl_tree);
- zip_send_bits(count - 3, 2)
- }else {
- if(count <= 10) {
- zip_SEND_CODE(zip_REPZ_3_10, zip_bl_tree);
- zip_send_bits(count - 3, 3)
- }else {
- zip_SEND_CODE(zip_REPZ_11_138, zip_bl_tree);
- zip_send_bits(count - 11, 7)
- }
- }
- }
- count = 0;
- prevlen = curlen;
- if(nextlen === 0) {
- max_count = 138;
- min_count = 3
- }else {
- if(curlen === nextlen) {
- max_count = 6;
- min_count = 3
- }else {
- max_count = 7;
- min_count = 4
- }
- }
- }
+ this.getMemberId = function() {
+ return memberId
};
- var zip_send_all_trees = function(lcodes, dcodes, blcodes) {
- var rank;
- zip_send_bits(lcodes - 257, 5);
- zip_send_bits(dcodes - 1, 5);
- zip_send_bits(blcodes - 4, 4);
- for(rank = 0;rank < blcodes;rank++) {
- zip_send_bits(zip_bl_tree[zip_bl_order[rank]].dl, 3)
- }
- zip_send_tree(zip_dyn_ltree, lcodes - 1);
- zip_send_tree(zip_dyn_dtree, dcodes - 1)
+ this.getNode = function() {
+ return cursor.getNode()
};
- var zip_init_block = function() {
- var n;
- for(n = 0;n < zip_L_CODES;n++) {
- zip_dyn_ltree[n].fc = 0
- }
- for(n = 0;n < zip_D_CODES;n++) {
- zip_dyn_dtree[n].fc = 0
- }
- for(n = 0;n < zip_BL_CODES;n++) {
- zip_bl_tree[n].fc = 0
- }
- zip_dyn_ltree[zip_END_BLOCK].fc = 1;
- zip_opt_len = zip_static_len = 0;
- zip_last_lit = zip_last_dist = zip_last_flags = 0;
- zip_flags = 0;
- zip_flag_bit = 1
- };
- var zip_flush_block = function(eof) {
- var opt_lenb, static_lenb;
- var max_blindex;
- var stored_len;
- stored_len = zip_strstart - zip_block_start;
- zip_flag_buf[zip_last_flags] = zip_flags;
- zip_build_tree(zip_l_desc);
- zip_build_tree(zip_d_desc);
- max_blindex = zip_build_bl_tree();
- opt_lenb = zip_opt_len + 3 + 7 >> 3;
- static_lenb = zip_static_len + 3 + 7 >> 3;
- if(static_lenb <= opt_lenb) {
- opt_lenb = static_lenb
- }
- if(stored_len + 4 <= opt_lenb && zip_block_start >= 0) {
- var i;
- zip_send_bits((zip_STORED_BLOCK << 1) + eof, 3);
- zip_bi_windup();
- zip_put_short(stored_len);
- zip_put_short(~stored_len);
- for(i = 0;i < stored_len;i++) {
- zip_put_byte(zip_window[zip_block_start + i])
- }
- }else {
- if(static_lenb === opt_lenb) {
- zip_send_bits((zip_STATIC_TREES << 1) + eof, 3);
- zip_compress_block(zip_static_ltree, zip_static_dtree)
- }else {
- zip_send_bits((zip_DYN_TREES << 1) + eof, 3);
- zip_send_all_trees(zip_l_desc.max_code + 1, zip_d_desc.max_code + 1, max_blindex + 1);
- zip_compress_block(zip_dyn_ltree, zip_dyn_dtree)
- }
- }
- zip_init_block();
- if(eof !== 0) {
- zip_bi_windup()
- }
+ this.getAnchorNode = function() {
+ return cursor.getAnchorNode()
};
- var zip_deflate_fast = function() {
- var flush;
- while(zip_lookahead !== 0 && zip_qhead === null) {
- zip_INSERT_STRING();
- if(zip_hash_head !== zip_NIL && zip_strstart - zip_hash_head <= zip_MAX_DIST) {
- zip_match_length = zip_longest_match(zip_hash_head);
- if(zip_match_length > zip_lookahead) {
- zip_match_length = zip_lookahead
- }
- }
- if(zip_match_length >= zip_MIN_MATCH) {
- flush = zip_ct_tally(zip_strstart - zip_match_start, zip_match_length - zip_MIN_MATCH);
- zip_lookahead -= zip_match_length;
- if(zip_match_length <= zip_max_lazy_match) {
- zip_match_length--;
- do {
- zip_strstart++;
- zip_INSERT_STRING()
- }while(--zip_match_length !== 0);
- zip_strstart++
- }else {
- zip_strstart += zip_match_length;
- zip_match_length = 0;
- zip_ins_h = zip_window[zip_strstart] & 255;
- zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + 1] & 255) & zip_HASH_MASK
- }
- }else {
- flush = zip_ct_tally(0, zip_window[zip_strstart] & 255);
- zip_lookahead--;
- zip_strstart++
- }
- if(flush) {
- zip_flush_block(0);
- zip_block_start = zip_strstart
- }
- while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
- zip_fill_window()
- }
- }
+ this.getSelectedRange = function() {
+ return cursor.getSelectedRange()
};
- var zip_deflate_better = function() {
- var flush;
- while(zip_lookahead !== 0 && zip_qhead === null) {
- zip_INSERT_STRING();
- zip_prev_length = zip_match_length;
- zip_prev_match = zip_match_start;
- zip_match_length = zip_MIN_MATCH - 1;
- if(zip_hash_head !== zip_NIL && (zip_prev_length < zip_max_lazy_match && zip_strstart - zip_hash_head <= zip_MAX_DIST)) {
- zip_match_length = zip_longest_match(zip_hash_head);
- if(zip_match_length > zip_lookahead) {
- zip_match_length = zip_lookahead
- }
- if(zip_match_length === zip_MIN_MATCH && zip_strstart - zip_match_start > zip_TOO_FAR) {
- zip_match_length--
- }
- }
- if(zip_prev_length >= zip_MIN_MATCH && zip_match_length <= zip_prev_length) {
- flush = zip_ct_tally(zip_strstart - 1 - zip_prev_match, zip_prev_length - zip_MIN_MATCH);
- zip_lookahead -= zip_prev_length - 1;
- zip_prev_length -= 2;
- do {
- zip_strstart++;
- zip_INSERT_STRING()
- }while(--zip_prev_length !== 0);
- zip_match_available = 0;
- zip_match_length = zip_MIN_MATCH - 1;
- zip_strstart++;
- if(flush) {
- zip_flush_block(0);
- zip_block_start = zip_strstart
- }
- }else {
- if(zip_match_available !== 0) {
- if(zip_ct_tally(0, zip_window[zip_strstart - 1] & 255)) {
- zip_flush_block(0);
- zip_block_start = zip_strstart
- }
- zip_strstart++;
- zip_lookahead--
- }else {
- zip_match_available = 1;
- zip_strstart++;
- zip_lookahead--
- }
- }
- while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) {
- zip_fill_window()
- }
- }
+ this.setSelectedRange = function(range, isForwardSelection) {
+ cursor.setSelectedRange(range, isForwardSelection);
+ events.emit(ops.OdtCursor.signalCursorUpdated, self)
};
- var zip_ct_init = function() {
- var n;
- var bits;
- var length;
- var code;
- var dist;
- if(zip_static_dtree[0].dl !== 0) {
- return
- }
- zip_l_desc.dyn_tree = zip_dyn_ltree;
- zip_l_desc.static_tree = zip_static_ltree;
- zip_l_desc.extra_bits = zip_extra_lbits;
- zip_l_desc.extra_base = zip_LITERALS + 1;
- zip_l_desc.elems = zip_L_CODES;
- zip_l_desc.max_length = zip_MAX_BITS;
- zip_l_desc.max_code = 0;
- zip_d_desc.dyn_tree = zip_dyn_dtree;
- zip_d_desc.static_tree = zip_static_dtree;
- zip_d_desc.extra_bits = zip_extra_dbits;
- zip_d_desc.extra_base = 0;
- zip_d_desc.elems = zip_D_CODES;
- zip_d_desc.max_length = zip_MAX_BITS;
- zip_d_desc.max_code = 0;
- zip_bl_desc.dyn_tree = zip_bl_tree;
- zip_bl_desc.static_tree = null;
- zip_bl_desc.extra_bits = zip_extra_blbits;
- zip_bl_desc.extra_base = 0;
- zip_bl_desc.elems = zip_BL_CODES;
- zip_bl_desc.max_length = zip_MAX_BL_BITS;
- zip_bl_desc.max_code = 0;
- length = 0;
- for(code = 0;code < zip_LENGTH_CODES - 1;code++) {
- zip_base_length[code] = length;
- for(n = 0;n < 1 << zip_extra_lbits[code];n++) {
- zip_length_code[length++] = code
- }
- }
- zip_length_code[length - 1] = code;
- dist = 0;
- for(code = 0;code < 16;code++) {
- zip_base_dist[code] = dist;
- for(n = 0;n < 1 << zip_extra_dbits[code];n++) {
- zip_dist_code[dist++] = code
- }
- }
- dist >>= 7;
- n = code;
- for(code = n;code < zip_D_CODES;code++) {
- zip_base_dist[code] = dist << 7;
- for(n = 0;n < 1 << zip_extra_dbits[code] - 7;n++) {
- zip_dist_code[256 + dist++] = code
- }
- }
- for(bits = 0;bits <= zip_MAX_BITS;bits++) {
- zip_bl_count[bits] = 0
- }
- n = 0;
- while(n <= 143) {
- zip_static_ltree[n++].dl = 8;
- zip_bl_count[8]++
- }
- while(n <= 255) {
- zip_static_ltree[n++].dl = 9;
- zip_bl_count[9]++
- }
- while(n <= 279) {
- zip_static_ltree[n++].dl = 7;
- zip_bl_count[7]++
- }
- while(n <= 287) {
- zip_static_ltree[n++].dl = 8;
- zip_bl_count[8]++
- }
- zip_gen_codes(zip_static_ltree, zip_L_CODES + 1);
- for(n = 0;n < zip_D_CODES;n++) {
- zip_static_dtree[n].dl = 5;
- zip_static_dtree[n].fc = zip_bi_reverse(n, 5)
- }
- zip_init_block()
+ this.hasForwardSelection = function() {
+ return cursor.hasForwardSelection()
};
- var zip_init_deflate = function() {
- if(zip_eofile) {
- return
- }
- zip_bi_buf = 0;
- zip_bi_valid = 0;
- zip_ct_init();
- zip_lm_init();
- zip_qhead = null;
- zip_outcnt = 0;
- zip_outoff = 0;
- if(zip_compr_level <= 3) {
- zip_prev_length = zip_MIN_MATCH - 1;
- zip_match_length = 0
- }else {
- zip_match_length = zip_MIN_MATCH - 1;
- zip_match_available = 0
- }
- zip_complete = false
+ this.getDocument = function() {
+ return document
};
- var zip_qcopy = function(buff, off, buff_size) {
- var n, i, j, p;
- n = 0;
- while(zip_qhead !== null && n < buff_size) {
- i = buff_size - n;
- if(i > zip_qhead.len) {
- i = zip_qhead.len
- }
- for(j = 0;j < i;j++) {
- buff[off + n + j] = zip_qhead.ptr[zip_qhead.off + j]
- }
- zip_qhead.off += i;
- zip_qhead.len -= i;
- n += i;
- if(zip_qhead.len === 0) {
- p = zip_qhead;
- zip_qhead = zip_qhead.next;
- zip_reuse_queue(p)
- }
- }
- if(n === buff_size) {
- return n
- }
- if(zip_outoff < zip_outcnt) {
- i = buff_size - n;
- if(i > zip_outcnt - zip_outoff) {
- i = zip_outcnt - zip_outoff
- }
- for(j = 0;j < i;j++) {
- buff[off + n + j] = zip_outbuf[zip_outoff + j]
- }
- zip_outoff += i;
- n += i;
- if(zip_outcnt === zip_outoff) {
- zip_outcnt = zip_outoff = 0
- }
- }
- return n
+ this.getSelectionType = function() {
+ return selectionType
};
- var zip_deflate_internal = function(buff, off, buff_size) {
- var n;
- if(!zip_initflag) {
- zip_init_deflate();
- zip_initflag = true;
- if(zip_lookahead === 0) {
- zip_complete = true;
- return 0
- }
- }
- n = zip_qcopy(buff, off, buff_size);
- if(n === buff_size) {
- return buff_size
- }
- if(zip_complete) {
- return n
- }
- if(zip_compr_level <= 3) {
- zip_deflate_fast()
+ this.setSelectionType = function(value) {
+ if(validSelectionTypes.hasOwnProperty(value)) {
+ selectionType = value
}else {
- zip_deflate_better()
- }
- if(zip_lookahead === 0) {
- if(zip_match_available !== 0) {
- zip_ct_tally(0, zip_window[zip_strstart - 1] & 255)
- }
- zip_flush_block(1);
- zip_complete = true
- }
- return n + zip_qcopy(buff, n + off, buff_size - n)
- };
- var zip_deflate = function(str, level) {
- var i, j;
- zip_deflate_data = str;
- zip_deflate_pos = 0;
- if(String(typeof level) === "undefined") {
- level = zip_DEFAULT_LEVEL
- }
- zip_deflate_start(level);
- var buff = new Array(1024);
- var aout = [], cbuf = [];
- i = zip_deflate_internal(buff, 0, buff.length);
- while(i > 0) {
- cbuf.length = i;
- for(j = 0;j < i;j++) {
- cbuf[j] = String.fromCharCode(buff[j])
- }
- aout[aout.length] = cbuf.join("");
- i = zip_deflate_internal(buff, 0, buff.length)
- }
- zip_deflate_data = "";
- return aout.join("")
- };
- this.deflate = zip_deflate
-};
-runtime.loadClass("odf.Namespaces");
-gui.ImageSelector = function ImageSelector(odfCanvas) {
- var svgns = odf.Namespaces.svgns, imageSelectorId = "imageSelector", selectorBorderWidth = 1, squareClassNames = ["topLeft", "topRight", "bottomRight", "bottomLeft", "topMiddle", "rightMiddle", "bottomMiddle", "leftMiddle"], document = odfCanvas.getElement().ownerDocument, hasSelection = false;
- function createSelectorElement() {
- var sizerElement = odfCanvas.getSizer(), selectorElement, squareElement;
- selectorElement = document.createElement("div");
- selectorElement.id = "imageSelector";
- selectorElement.style.borderWidth = selectorBorderWidth + "px";
- sizerElement.appendChild(selectorElement);
- squareClassNames.forEach(function(className) {
- squareElement = document.createElement("div");
- squareElement.className = className;
- selectorElement.appendChild(squareElement)
- });
- return selectorElement
- }
- function getPosition(element, referenceElement) {
- var rect = element.getBoundingClientRect(), refRect = referenceElement.getBoundingClientRect(), zoomLevel = odfCanvas.getZoomLevel();
- return{left:(rect.left - refRect.left) / zoomLevel - selectorBorderWidth, top:(rect.top - refRect.top) / zoomLevel - selectorBorderWidth}
- }
- this.select = function(frameElement) {
- var selectorElement = document.getElementById(imageSelectorId), position;
- if(!selectorElement) {
- selectorElement = createSelectorElement()
- }
- hasSelection = true;
- position = getPosition(frameElement, (selectorElement.parentNode));
- selectorElement.style.display = "block";
- selectorElement.style.left = position.left + "px";
- selectorElement.style.top = position.top + "px";
- selectorElement.style.width = frameElement.getAttributeNS(svgns, "width");
- selectorElement.style.height = frameElement.getAttributeNS(svgns, "height")
- };
- this.clearSelection = function() {
- var selectorElement;
- if(hasSelection) {
- selectorElement = document.getElementById(imageSelectorId);
- if(selectorElement) {
- selectorElement.style.display = "none"
- }
+ runtime.log("Invalid selection type: " + value)
}
- hasSelection = false
};
- this.isSelectorElement = function(node) {
- var selectorElement = document.getElementById(imageSelectorId);
- if(!selectorElement) {
- return false
- }
- return node === selectorElement || node.parentNode === selectorElement
- }
-};
-runtime.loadClass("odf.OdfCanvas");
-odf.CommandLineTools = function CommandLineTools() {
- this.roundTrip = function(inputfilepath, outputfilepath, callback) {
- function onready(odfcontainer) {
- if(odfcontainer.state === odf.OdfContainer.INVALID) {
- return callback("Document " + inputfilepath + " is invalid.")
- }
- if(odfcontainer.state === odf.OdfContainer.DONE) {
- odfcontainer.saveAs(outputfilepath, function(err) {
- callback(err)
- })
- }else {
- callback("Document was not completely loaded.")
- }
- }
- var odfcontainer = new odf.OdfContainer(inputfilepath, onready);
- return odfcontainer
+ this.resetSelectionType = function() {
+ self.setSelectionType(ops.OdtCursor.RangeSelection)
};
- this.render = function(inputfilepath, document, callback) {
- var body = document.getElementsByTagName("body")[0], odfcanvas;
- while(body.firstChild) {
- body.removeChild(body.firstChild)
- }
- odfcanvas = new odf.OdfCanvas(body);
- odfcanvas.addListener("statereadychange", function(err) {
- callback(err)
- });
- odfcanvas.load(inputfilepath)
- }
-};
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-ops.Member = function Member(memberId, properties) {
- var props = {};
- function getMemberId() {
- return memberId
- }
- function getProperties() {
- return props
- }
- function setProperties(newProperties) {
- Object.keys(newProperties).forEach(function(key) {
- props[key] = newProperties[key]
- })
- }
- function removeProperties(removedProperties) {
- delete removedProperties.fullName;
- delete removedProperties.color;
- delete removedProperties.imageUrl;
- Object.keys(removedProperties).forEach(function(key) {
- if(props.hasOwnProperty(key)) {
- delete props[key]
- }
- })
- }
- this.getMemberId = getMemberId;
- this.getProperties = getProperties;
- this.setProperties = setProperties;
- this.removeProperties = removeProperties;
function init() {
- runtime.assert(Boolean(memberId), "No memberId was supplied!");
- if(!properties.fullName) {
- properties.fullName = runtime.tr("Unknown Author")
- }
- if(!properties.color) {
- properties.color = "black"
- }
- if(!properties.imageUrl) {
- properties.imageUrl = "avatar-joe.png"
- }
- props = properties
+ cursor = new core.Cursor(document.getDOMDocument(), memberId);
+ selectionMover = new gui.SelectionMover(cursor, document.getRootNode());
+ validSelectionTypes[ops.OdtCursor.RangeSelection] = true;
+ validSelectionTypes[ops.OdtCursor.RegionSelection] = true;
+ self.resetSelectionType()
}
init()
};
+ops.OdtCursor.RangeSelection = "Range";
+ops.OdtCursor.RegionSelection = "Region";
+ops.OdtCursor.signalCursorUpdated = "cursorUpdated";
+(function() {
+ return ops.OdtCursor
+})();
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -10332,26 +9049,52 @@ ops.Member = function Member(memberId, properties) {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("core.PositionFilter");
-runtime.loadClass("odf.OdfUtils");
+ops.Operation = function Operation() {
+};
+ops.Operation.prototype.init = function(data) {
+};
+ops.Operation.prototype.isEdit;
+ops.Operation.prototype.group;
+ops.Operation.prototype.execute = function(document) {
+};
+ops.Operation.prototype.spec = function() {
+};
+/*
+
+ Copyright (C) 2010-2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
(function() {
- var nextNodeId = 0, PREVIOUS_STEP = 0, NEXT_STEP = 1;
- function StepsCache(rootNode, filter, bucketSize) {
- var coordinatens = "urn:webodf:names:steps", stepToDomPoint = {}, nodeToBookmark = {}, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, basePoint, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
- function ParagraphBookmark(steps, paragraphNode) {
+ var nextNodeId = 0;
+ ops.StepsCache = function StepsCache(rootElement, filter, bucketSize) {
+ var coordinatens = "urn:webodf:names:steps", stepToDomPoint = {}, nodeToBookmark = {}, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, basePoint, lastUndamagedCacheStep, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, verifyCache;
+ function ParagraphBookmark(nodeId, steps, paragraphNode) {
+ this.nodeId = nodeId;
this.steps = steps;
this.node = paragraphNode;
- function positionInContainer(node) {
- var position = 0;
- while(node && node.previousSibling) {
- position += 1;
- node = node.previousSibling
- }
- return position
- }
+ this.nextBookmark = null;
+ this.previousBookmark = null;
this.setIteratorPosition = function(iterator) {
- iterator.setUnfilteredPosition(paragraphNode.parentNode, positionInContainer(paragraphNode));
+ iterator.setPositionBeforeElement(paragraphNode);
do {
if(filter.acceptPosition(iterator) === FILTER_ACCEPT) {
break
@@ -10359,9 +9102,12 @@ runtime.loadClass("odf.OdfUtils");
}while(iterator.nextPosition())
}
}
- function RootBookmark(steps, rootNode) {
+ function RootBookmark(nodeId, steps, rootNode) {
+ this.nodeId = nodeId;
this.steps = steps;
this.node = rootNode;
+ this.nextBookmark = null;
+ this.previousBookmark = null;
this.setIteratorPosition = function(iterator) {
iterator.setUnfilteredPosition(rootNode, 0);
do {
@@ -10371,6 +9117,47 @@ runtime.loadClass("odf.OdfUtils");
}while(iterator.nextPosition())
}
}
+ function inspectBookmarks(bookmark1, bookmark2) {
+ var parts = "[" + bookmark1.nodeId;
+ if(bookmark2) {
+ parts += " => " + bookmark2.nodeId
+ }
+ return parts + "]"
+ }
+ function isUndamagedBookmark(bookmark) {
+ return lastUndamagedCacheStep === undefined || bookmark.steps <= lastUndamagedCacheStep
+ }
+ function verifyCacheImpl() {
+ var bookmark = basePoint, previousBookmark, nextBookmark, documentPosition, loopCheck = new core.LoopWatchDog(0, 1E5);
+ while(bookmark) {
+ loopCheck.check();
+ previousBookmark = bookmark.previousBookmark;
+ if(previousBookmark) {
+ runtime.assert(previousBookmark.nextBookmark === bookmark, "Broken bookmark link to previous @" + inspectBookmarks(previousBookmark, bookmark))
+ }else {
+ runtime.assert(bookmark === basePoint, "Broken bookmark link @" + inspectBookmarks(bookmark));
+ runtime.assert(isUndamagedBookmark(basePoint), "Base point is damaged @" + inspectBookmarks(bookmark))
+ }
+ nextBookmark = bookmark.nextBookmark;
+ if(nextBookmark) {
+ runtime.assert(nextBookmark.previousBookmark === bookmark, "Broken bookmark link to next @" + inspectBookmarks(bookmark, nextBookmark))
+ }
+ if(isUndamagedBookmark(bookmark)) {
+ runtime.assert(domUtils.containsNode(rootElement, bookmark.node), "Disconnected node is being reported as undamaged @" + inspectBookmarks(bookmark));
+ if(previousBookmark) {
+ documentPosition = bookmark.node.compareDocumentPosition(previousBookmark.node);
+ runtime.assert(documentPosition === 0 || (documentPosition & Node.DOCUMENT_POSITION_PRECEDING) !== 0, "Bookmark order with previous does not reflect DOM order @" + inspectBookmarks(previousBookmark, bookmark))
+ }
+ if(nextBookmark) {
+ if(domUtils.containsNode(rootElement, nextBookmark.node)) {
+ documentPosition = bookmark.node.compareDocumentPosition(nextBookmark.node);
+ runtime.assert(documentPosition === 0 || (documentPosition & Node.DOCUMENT_POSITION_FOLLOWING) !== 0, "Bookmark order with next does not reflect DOM order @" + inspectBookmarks(bookmark, nextBookmark))
+ }
+ }
+ }
+ bookmark = bookmark.nextBookmark
+ }
+ }
function getBucket(steps) {
return Math.floor(steps / bucketSize) * bucketSize
}
@@ -10381,11 +9168,15 @@ runtime.loadClass("odf.OdfUtils");
node.removeAttributeNS(coordinatens, "nodeId")
}
function getNodeId(node) {
- return node.nodeType === Node.ELEMENT_NODE && node.getAttributeNS(coordinatens, "nodeId")
+ var id = "";
+ if(node.nodeType === Node.ELEMENT_NODE) {
+ id = (node).getAttributeNS(coordinatens, "nodeId")
+ }
+ return id
}
function setNodeId(node) {
- var nodeId = nextNodeId;
- node.setAttributeNS(coordinatens, "nodeId", nodeId.toString());
+ var nodeId = nextNodeId.toString();
+ node.setAttributeNS(coordinatens, "nodeId", nodeId);
nextNodeId += 1;
return nodeId
}
@@ -10396,159 +9187,258 @@ runtime.loadClass("odf.OdfUtils");
var nodeId = getNodeId(node) || setNodeId(node), existingBookmark;
existingBookmark = nodeToBookmark[nodeId];
if(!existingBookmark) {
- existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node)
+ existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(nodeId, steps, node)
}else {
if(!isValidBookmarkForNode(node, existingBookmark)) {
runtime.log("Cloned node detected. Creating new bookmark");
nodeId = setNodeId(node);
- existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node)
+ existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(nodeId, steps, node)
}else {
existingBookmark.steps = steps
}
}
return existingBookmark
}
- function isFirstPositionInParagraph(node, offset) {
- return offset === 0 && odfUtils.isParagraph(node)
+ function getClosestBookmark(steps) {
+ var cacheBucket, cachePoint, loopGuard = new core.LoopWatchDog(0, 1E4);
+ if(lastUndamagedCacheStep !== undefined && steps > lastUndamagedCacheStep) {
+ steps = lastUndamagedCacheStep
+ }
+ cacheBucket = getBucket(steps);
+ while(!cachePoint && cacheBucket !== 0) {
+ cachePoint = stepToDomPoint[cacheBucket];
+ cacheBucket -= bucketSize
+ }
+ cachePoint = cachePoint || basePoint;
+ while(cachePoint.nextBookmark && cachePoint.nextBookmark.steps <= steps) {
+ loopGuard.check();
+ cachePoint = cachePoint.nextBookmark
+ }
+ return cachePoint
}
- this.updateCache = function(steps, node, offset, isWalkable) {
- var stablePoint, cacheBucket, existingCachePoint, bookmark;
- if(isFirstPositionInParagraph(node, offset)) {
- stablePoint = true;
- if(!isWalkable) {
- steps += 1
- }
- }else {
- if(node.hasChildNodes() && node.childNodes[offset]) {
- node = node.childNodes[offset];
- offset = 0;
- stablePoint = isFirstPositionInParagraph(node, offset);
- if(stablePoint) {
- steps += 1
+ function getUndamagedBookmark(bookmark) {
+ if(lastUndamagedCacheStep !== undefined && bookmark.steps > lastUndamagedCacheStep) {
+ bookmark = getClosestBookmark(lastUndamagedCacheStep)
+ }
+ return bookmark
+ }
+ function removeBookmark(currentBookmark) {
+ if(currentBookmark.previousBookmark) {
+ currentBookmark.previousBookmark.nextBookmark = currentBookmark.nextBookmark
+ }
+ if(currentBookmark.nextBookmark) {
+ currentBookmark.nextBookmark.previousBookmark = currentBookmark.previousBookmark
+ }
+ }
+ function insertBookmark(previousBookmark, newBookmark) {
+ var nextBookmark;
+ if(previousBookmark !== newBookmark && previousBookmark.nextBookmark !== newBookmark) {
+ removeBookmark(newBookmark);
+ nextBookmark = previousBookmark.nextBookmark;
+ newBookmark.nextBookmark = previousBookmark.nextBookmark;
+ newBookmark.previousBookmark = previousBookmark;
+ previousBookmark.nextBookmark = newBookmark;
+ if(nextBookmark) {
+ nextBookmark.previousBookmark = newBookmark
+ }
+ }
+ }
+ function repairCacheUpToStep(currentIteratorStep) {
+ var damagedBookmark, undamagedBookmark, nextBookmark, stepsBucket;
+ if(lastUndamagedCacheStep !== undefined && lastUndamagedCacheStep < currentIteratorStep) {
+ undamagedBookmark = getClosestBookmark(lastUndamagedCacheStep);
+ damagedBookmark = undamagedBookmark.nextBookmark;
+ while(damagedBookmark && damagedBookmark.steps <= currentIteratorStep) {
+ nextBookmark = damagedBookmark.nextBookmark;
+ stepsBucket = getDestinationBucket(damagedBookmark.steps);
+ if(stepToDomPoint[stepsBucket] === damagedBookmark) {
+ delete stepToDomPoint[stepsBucket]
}
+ if(!domUtils.containsNode(rootElement, damagedBookmark.node)) {
+ removeBookmark(damagedBookmark);
+ delete nodeToBookmark[damagedBookmark.nodeId]
+ }else {
+ damagedBookmark.steps = currentIteratorStep + 1
+ }
+ damagedBookmark = nextBookmark
}
+ lastUndamagedCacheStep = currentIteratorStep
+ }else {
+ undamagedBookmark = getClosestBookmark(currentIteratorStep)
}
- if(stablePoint) {
- bookmark = getNodeBookmark(node, steps);
+ return undamagedBookmark
+ }
+ this.updateCache = function(steps, iterator, isStep) {
+ var cacheBucket, existingCachePoint, bookmark, closestPriorBookmark, node = iterator.getCurrentNode();
+ if(iterator.isBeforeNode() && odfUtils.isParagraph(node)) {
+ if(!isStep) {
+ steps += 1
+ }
+ closestPriorBookmark = repairCacheUpToStep(steps);
+ bookmark = getNodeBookmark((node), steps);
+ insertBookmark(closestPriorBookmark, bookmark);
cacheBucket = getDestinationBucket(bookmark.steps);
existingCachePoint = stepToDomPoint[cacheBucket];
if(!existingCachePoint || bookmark.steps > existingCachePoint.steps) {
stepToDomPoint[cacheBucket] = bookmark
}
+ verifyCache()
}
};
this.setToClosestStep = function(steps, iterator) {
- var cacheBucket = getBucket(steps), cachePoint;
- while(!cachePoint && cacheBucket !== 0) {
- cachePoint = stepToDomPoint[cacheBucket];
- cacheBucket -= bucketSize
- }
- cachePoint = cachePoint || basePoint;
+ var cachePoint;
+ verifyCache();
+ cachePoint = getClosestBookmark(steps);
cachePoint.setIteratorPosition(iterator);
return cachePoint.steps
};
- function findBookmarkedAncestor(node, offset) {
- var nodeId, bookmark = null;
- node = node.childNodes[offset] || node;
- while(!bookmark && (node && node !== rootNode)) {
- nodeId = getNodeId(node);
+ function findBookmarkedAncestor(node) {
+ var currentNode = node, nodeId, bookmark = null;
+ while(!bookmark && (currentNode && currentNode !== rootElement)) {
+ nodeId = getNodeId(currentNode);
if(nodeId) {
bookmark = nodeToBookmark[nodeId];
- if(bookmark && !isValidBookmarkForNode(node, bookmark)) {
+ if(bookmark && !isValidBookmarkForNode(currentNode, bookmark)) {
runtime.log("Cloned node detected. Creating new bookmark");
bookmark = null;
- clearNodeId(node)
+ clearNodeId((currentNode))
}
}
- node = node.parentNode
+ currentNode = currentNode.parentNode
}
return bookmark
}
this.setToClosestDomPoint = function(node, offset, iterator) {
- var bookmark;
- if(node === rootNode && offset === 0) {
+ var bookmark, b, key;
+ verifyCache();
+ if(node === rootElement && offset === 0) {
bookmark = basePoint
}else {
- if(node === rootNode && offset === rootNode.childNodes.length) {
- bookmark = Object.keys(stepToDomPoint).map(function(cacheBucket) {
- return stepToDomPoint[cacheBucket]
- }).reduce(function(largestBookmark, bookmark) {
- return bookmark.steps > largestBookmark.steps ? bookmark : largestBookmark
- }, basePoint)
+ if(node === rootElement && offset === rootElement.childNodes.length) {
+ bookmark = basePoint;
+ for(key in stepToDomPoint) {
+ if(stepToDomPoint.hasOwnProperty(key)) {
+ b = stepToDomPoint[key];
+ if(b.steps > bookmark.steps) {
+ bookmark = b
+ }
+ }
+ }
}else {
- bookmark = findBookmarkedAncestor(node, offset);
+ bookmark = findBookmarkedAncestor(node.childNodes.item(offset) || node);
if(!bookmark) {
iterator.setUnfilteredPosition(node, offset);
while(!bookmark && iterator.previousNode()) {
- bookmark = findBookmarkedAncestor(iterator.container(), iterator.unfilteredDomOffset())
+ bookmark = findBookmarkedAncestor(iterator.getCurrentNode())
}
}
}
}
- bookmark = bookmark || basePoint;
+ bookmark = getUndamagedBookmark(bookmark || basePoint);
bookmark.setIteratorPosition(iterator);
return bookmark.steps
};
- this.updateCacheAtPoint = function(inflectionStep, doUpdate) {
- var affectedBookmarks, updatedBuckets = {};
- affectedBookmarks = Object.keys(nodeToBookmark).map(function(nodeId) {
- return nodeToBookmark[nodeId]
- }).filter(function(bookmark) {
- return bookmark.steps > inflectionStep
- });
- affectedBookmarks.forEach(function(bookmark) {
- var originalCacheBucket = getDestinationBucket(bookmark.steps), newCacheBucket, existingBookmark;
- if(domUtils.containsNode(rootNode, bookmark.node)) {
- doUpdate(bookmark);
- newCacheBucket = getDestinationBucket(bookmark.steps);
- existingBookmark = updatedBuckets[newCacheBucket];
- if(!existingBookmark || bookmark.steps > existingBookmark.steps) {
- updatedBuckets[newCacheBucket] = bookmark
- }
- }else {
- delete nodeToBookmark[getNodeId(bookmark.node)]
- }
- if(stepToDomPoint[originalCacheBucket] === bookmark) {
- delete stepToDomPoint[originalCacheBucket]
+ this.damageCacheAfterStep = function(inflectionStep) {
+ if(inflectionStep < 0) {
+ inflectionStep = 0
+ }
+ if(lastUndamagedCacheStep === undefined) {
+ lastUndamagedCacheStep = inflectionStep
+ }else {
+ if(inflectionStep < lastUndamagedCacheStep) {
+ lastUndamagedCacheStep = inflectionStep
}
- });
- Object.keys(updatedBuckets).forEach(function(cacheBucket) {
- stepToDomPoint[cacheBucket] = updatedBuckets[cacheBucket]
- })
+ }
+ verifyCache()
};
function init() {
- basePoint = new RootBookmark(0, rootNode)
+ var rootElementId = getNodeId(rootElement) || setNodeId(rootElement);
+ basePoint = new RootBookmark(rootElementId, 0, rootElement);
+ verifyCache = ops.StepsCache.ENABLE_CACHE_VERIFICATION ? verifyCacheImpl : function() {
+ }
}
init()
+ };
+ ops.StepsCache.ENABLE_CACHE_VERIFICATION = false;
+ ops.StepsCache.Bookmark = function Bookmark() {
+ };
+ ops.StepsCache.Bookmark.prototype.nodeId;
+ ops.StepsCache.Bookmark.prototype.node;
+ ops.StepsCache.Bookmark.prototype.steps;
+ ops.StepsCache.Bookmark.prototype.previousBookmark;
+ ops.StepsCache.Bookmark.prototype.nextBookmark;
+ ops.StepsCache.Bookmark.prototype.setIteratorPosition = function(iterator) {
}
+})();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+(function() {
+ var PREVIOUS_STEP = 0, NEXT_STEP = 1;
ops.StepsTranslator = function StepsTranslator(getRootNode, newIterator, filter, bucketSize) {
- var rootNode = getRootNode(), stepsCache = new StepsCache(rootNode, filter, bucketSize), domUtils = new core.DomUtils, iterator = newIterator(getRootNode()), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
+ var rootNode = getRootNode(), stepsCache = new ops.StepsCache(rootNode, filter, bucketSize), domUtils = new core.DomUtils, iterator = newIterator(getRootNode()), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
function verifyRootNode() {
var currentRootNode = getRootNode();
if(currentRootNode !== rootNode) {
runtime.log("Undo detected. Resetting steps cache");
rootNode = currentRootNode;
- stepsCache = new StepsCache(rootNode, filter, bucketSize);
+ stepsCache = new ops.StepsCache(rootNode, filter, bucketSize);
iterator = newIterator(rootNode)
}
}
this.convertStepsToDomPoint = function(steps) {
- var stepsFromRoot, isWalkable;
+ var stepsFromRoot, isStep;
+ if(isNaN(steps)) {
+ throw new TypeError("Requested steps is not numeric (" + steps + ")");
+ }
if(steps < 0) {
- runtime.log("warn", "Requested steps were negative (" + steps + ")");
- steps = 0
+ throw new RangeError("Requested steps is negative (" + steps + ")");
}
verifyRootNode();
stepsFromRoot = stepsCache.setToClosestStep(steps, iterator);
while(stepsFromRoot < steps && iterator.nextPosition()) {
- isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
- if(isWalkable) {
+ isStep = filter.acceptPosition(iterator) === FILTER_ACCEPT;
+ if(isStep) {
stepsFromRoot += 1
}
- stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
+ stepsCache.updateCache(stepsFromRoot, iterator, isStep)
}
if(stepsFromRoot !== steps) {
- runtime.log("warn", "Requested " + steps + " steps but only " + stepsFromRoot + " are available")
+ throw new RangeError("Requested steps (" + steps + ") exceeds available steps (" + stepsFromRoot + ")");
}
return{node:iterator.container(), offset:iterator.unfilteredDomOffset()}
};
@@ -10575,12 +9465,12 @@ runtime.loadClass("odf.OdfUtils");
return false
}
this.convertDomPointToSteps = function(node, offset, roundDirection) {
- var stepsFromRoot, beforeRoot, destinationNode, destinationOffset, rounding = 0, isWalkable;
+ var stepsFromRoot, beforeRoot, destinationNode, destinationOffset, rounding = 0, isStep;
verifyRootNode();
if(!domUtils.containsNode(rootNode, node)) {
beforeRoot = domUtils.comparePoints(rootNode, 0, node, offset) < 0;
- node = rootNode;
- offset = beforeRoot ? 0 : rootNode.childNodes.length
+ node = (rootNode);
+ offset = beforeRoot ? 0 : (rootNode).childNodes.length
}
iterator.setUnfilteredPosition(node, offset);
if(!roundToPreferredStep(iterator, roundDirection)) {
@@ -10593,448 +9483,163 @@ runtime.loadClass("odf.OdfUtils");
return stepsFromRoot > 0 ? stepsFromRoot - 1 : stepsFromRoot
}
while(!(iterator.container() === destinationNode && iterator.unfilteredDomOffset() === destinationOffset) && iterator.nextPosition()) {
- isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
- if(isWalkable) {
+ isStep = filter.acceptPosition(iterator) === FILTER_ACCEPT;
+ if(isStep) {
stepsFromRoot += 1
}
- stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
+ stepsCache.updateCache(stepsFromRoot, iterator, isStep)
}
return stepsFromRoot + rounding
};
this.prime = function() {
- var stepsFromRoot, isWalkable;
+ var stepsFromRoot, isStep;
verifyRootNode();
stepsFromRoot = stepsCache.setToClosestStep(0, iterator);
while(iterator.nextPosition()) {
- isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT;
- if(isWalkable) {
+ isStep = filter.acceptPosition(iterator) === FILTER_ACCEPT;
+ if(isStep) {
stepsFromRoot += 1
}
- stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable)
+ stepsCache.updateCache(stepsFromRoot, iterator, isStep)
}
};
this.handleStepsInserted = function(eventArgs) {
verifyRootNode();
- stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) {
- bucket.steps += eventArgs.length
- })
+ stepsCache.damageCacheAfterStep(eventArgs.position)
};
this.handleStepsRemoved = function(eventArgs) {
verifyRootNode();
- stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) {
- bucket.steps -= eventArgs.length;
- if(bucket.steps < 0) {
- bucket.steps = 0
- }
- })
+ stepsCache.damageCacheAfterStep(eventArgs.position - 1)
}
};
ops.StepsTranslator.PREVIOUS_STEP = PREVIOUS_STEP;
ops.StepsTranslator.NEXT_STEP = NEXT_STEP;
return ops.StepsTranslator
})();
-xmldom.RNG = {};
-xmldom.RNG.Name;
-xmldom.RNG.Attr;
-xmldom.RNG.Element;
-xmldom.RelaxNGParser = function RelaxNGParser() {
- var self = this, rngns = "http://relaxng.org/ns/structure/1.0", xmlnsns = "http://www.w3.org/2000/xmlns/", start, nsmap = {"http://www.w3.org/XML/1998/namespace":"xml"}, parse;
- function RelaxNGParseError(error, context) {
- this.message = function() {
- if(context) {
- error += context.nodeType === 1 ? " Element " : " Node ";
- error += context.nodeName;
- if(context.nodeValue) {
- error += " with value '" + context.nodeValue + "'"
- }
- error += "."
- }
- return error
- }
- }
- function splitToDuos(e) {
- if(e.e.length <= 2) {
- return e
- }
- var o = {name:e.name, e:e.e.slice(0, 2)};
- return splitToDuos({name:e.name, e:[o].concat(e.e.slice(2))})
- }
- function splitQName(name) {
- var r = name.split(":", 2), prefix = "", i;
- if(r.length === 1) {
- r = ["", r[0]]
- }else {
- prefix = r[0]
- }
- for(i in nsmap) {
- if(nsmap[i] === prefix) {
- r[0] = i
- }
- }
- return r
- }
- function splitQNames(def) {
- var i, l = def.names ? def.names.length : 0, name, localnames = [], namespaces = [];
- for(i = 0;i < l;i += 1) {
- name = splitQName(def.names[i]);
- namespaces[i] = name[0];
- localnames[i] = name[1]
- }
- def.localnames = localnames;
- def.namespaces = namespaces
- }
- function trim(str) {
- str = str.replace(/^\s\s*/, "");
- var ws = /\s/, i = str.length - 1;
- while(ws.test(str.charAt(i))) {
- i -= 1
- }
- return str.slice(0, i + 1)
- }
- function copyAttributes(atts, name, names) {
- var a = {}, i, att;
- for(i = 0;atts && i < atts.length;i += 1) {
- att = (atts.item(i));
- if(!att.namespaceURI) {
- if(att.localName === "name" && (name === "element" || name === "attribute")) {
- names.push(att.value)
- }
- if(att.localName === "name" || (att.localName === "combine" || att.localName === "type")) {
- att.value = trim(att.value)
- }
- a[att.localName] = att.value
- }else {
- if(att.namespaceURI === xmlnsns) {
- nsmap[att.value] = att.localName
- }
- }
- }
- return a
- }
- function parseChildren(c, e, elements, names) {
- var text = "", ce;
- while(c) {
- if(c.nodeType === Node.ELEMENT_NODE && c.namespaceURI === rngns) {
- ce = parse((c), elements, e);
- if(ce) {
- if(ce.name === "name") {
- names.push(nsmap[ce.a.ns] + ":" + ce.text);
- e.push(ce)
- }else {
- if(ce.name === "choice" && (ce.names && ce.names.length)) {
- names = names.concat(ce.names);
- delete ce.names;
- e.push(ce)
- }else {
- e.push(ce)
- }
- }
- }
- }else {
- if(c.nodeType === Node.TEXT_NODE) {
- text += c.nodeValue
- }
- }
- c = c.nextSibling
- }
- return text
- }
- function combineDefines(combine, name, e, siblings) {
- var i, ce;
- for(i = 0;siblings && i < siblings.length;i += 1) {
- ce = siblings[i];
- if(ce.name === "define" && (ce.a && ce.a.name === name)) {
- ce.e = [{name:combine, e:ce.e.concat(e)}];
- return ce
- }
- }
- return null
- }
- parse = function parse(element, elements, siblings) {
- var e = [], a, ce, i, text, name = element.localName, names = [];
- a = copyAttributes(element.attributes, name, names);
- a.combine = a.combine || undefined;
- text = parseChildren(element.firstChild, e, elements, names);
- if(name !== "value" && name !== "param") {
- text = /^\s*([\s\S]*\S)?\s*$/.exec(text)[1]
- }
- if(name === "value" && a.type === undefined) {
- a.type = "token";
- a.datatypeLibrary = ""
- }
- if((name === "attribute" || name === "element") && a.name !== undefined) {
- i = splitQName(a.name);
- e = [{name:"name", text:i[1], a:{ns:i[0]}}].concat(e);
- delete a.name
- }
- if(name === "name" || (name === "nsName" || name === "value")) {
- if(a.ns === undefined) {
- a.ns = ""
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.TextPositionFilter = function TextPositionFilter(getRootNode) {
+ var odfUtils = new odf.OdfUtils, ELEMENT_NODE = Node.ELEMENT_NODE, TEXT_NODE = Node.TEXT_NODE, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT;
+ function checkLeftRight(container, leftNode, rightNode) {
+ var r, firstPos, rightOfChar;
+ if(leftNode) {
+ if(odfUtils.isInlineRoot(leftNode) && odfUtils.isGroupingElement(rightNode)) {
+ return FILTER_REJECT
}
- }else {
- delete a.ns
- }
- if(name === "name") {
- i = splitQName(text);
- a.ns = i[0];
- text = i[1]
- }
- if(e.length > 1 && (name === "define" || (name === "oneOrMore" || (name === "zeroOrMore" || (name === "optional" || (name === "list" || name === "mixed")))))) {
- e = [{name:"group", e:splitToDuos({name:"group", e:e}).e}]
- }
- if(e.length > 2 && name === "element") {
- e = [e[0]].concat({name:"group", e:splitToDuos({name:"group", e:e.slice(1)}).e})
- }
- if(e.length === 1 && name === "attribute") {
- e.push({name:"text", text:text})
- }
- if(e.length === 1 && (name === "choice" || (name === "group" || name === "interleave"))) {
- name = e[0].name;
- names = e[0].names;
- a = e[0].a;
- text = e[0].text;
- e = e[0].e
- }else {
- if(e.length > 2 && (name === "choice" || (name === "group" || name === "interleave"))) {
- e = splitToDuos({name:name, e:e}).e
+ r = odfUtils.lookLeftForCharacter(leftNode);
+ if(r === 1) {
+ return FILTER_ACCEPT
}
- }
- if(name === "mixed") {
- name = "interleave";
- e = [e[0], {name:"text"}]
- }
- if(name === "optional") {
- name = "choice";
- e = [e[0], {name:"empty"}]
- }
- if(name === "zeroOrMore") {
- name = "choice";
- e = [{name:"oneOrMore", e:[e[0]]}, {name:"empty"}]
- }
- if(name === "define" && a.combine) {
- ce = combineDefines(a.combine, a.name, e, siblings);
- if(ce) {
- return null
+ if(r === 2 && (odfUtils.scanRightForAnyCharacter(rightNode) || odfUtils.scanRightForAnyCharacter(odfUtils.nextNode(container)))) {
+ return FILTER_ACCEPT
}
}
- ce = {name:name};
- if(e && e.length > 0) {
- ce.e = e
- }
- for(i in a) {
- if(a.hasOwnProperty(i)) {
- ce.a = a;
- break
+ firstPos = leftNode === null && odfUtils.isParagraph(container);
+ rightOfChar = odfUtils.lookRightForCharacter(rightNode);
+ if(firstPos) {
+ if(rightOfChar) {
+ return FILTER_ACCEPT
}
+ return odfUtils.scanRightForAnyCharacter(rightNode) ? FILTER_REJECT : FILTER_ACCEPT
}
- if(text !== undefined) {
- ce.text = text
- }
- if(names && names.length > 0) {
- ce.names = names
- }
- if(name === "element") {
- ce.id = elements.length;
- elements.push(ce);
- ce = {name:"elementref", id:ce.id}
+ if(!rightOfChar) {
+ return FILTER_REJECT
}
- return ce
- };
- function resolveDefines(def, defines) {
- var i = 0, e, defs, end, name = def.name;
- while(def.e && i < def.e.length) {
- e = def.e[i];
- if(e.name === "ref") {
- defs = defines[e.a.name];
- if(!defs) {
- throw e.a.name + " was not defined.";
- }
- end = def.e.slice(i + 1);
- def.e = def.e.slice(0, i);
- def.e = def.e.concat(defs.e);
- def.e = def.e.concat(end)
- }else {
- i += 1;
- resolveDefines(e, defines)
- }
+ leftNode = leftNode || odfUtils.previousNode(container);
+ return odfUtils.scanLeftForAnyCharacter(leftNode) ? FILTER_REJECT : FILTER_ACCEPT
+ }
+ this.acceptPosition = function(iterator) {
+ var container = iterator.container(), nodeType = container.nodeType, offset, text, leftChar, rightChar, leftNode, rightNode, r;
+ if(nodeType !== ELEMENT_NODE && nodeType !== TEXT_NODE) {
+ return FILTER_REJECT
}
- e = def.e;
- if(name === "choice") {
- if(!e || (!e[1] || e[1].name === "empty")) {
- if(!e || (!e[0] || e[0].name === "empty")) {
- delete def.e;
- def.name = "empty"
- }else {
- e[1] = e[0];
- e[0] = {name:"empty"}
- }
+ if(nodeType === TEXT_NODE) {
+ if(!odfUtils.isGroupingElement(container.parentNode) || odfUtils.isWithinTrackedChanges(container.parentNode, getRootNode())) {
+ return FILTER_REJECT
}
- }
- if(name === "group" || name === "interleave") {
- if(e[0].name === "empty") {
- if(e[1].name === "empty") {
- delete def.e;
- def.name = "empty"
- }else {
- name = def.name = e[1].name;
- def.names = e[1].names;
- e = def.e = e[1].e
- }
- }else {
- if(e[1].name === "empty") {
- name = def.name = e[0].name;
- def.names = e[0].names;
- e = def.e = e[0].e
+ offset = iterator.unfilteredDomOffset();
+ text = container.data;
+ runtime.assert(offset !== text.length, "Unexpected offset.");
+ if(offset > 0) {
+ leftChar = (text[offset - 1]);
+ if(!odfUtils.isODFWhitespace(leftChar)) {
+ return FILTER_ACCEPT
}
- }
- }
- if(name === "oneOrMore" && e[0].name === "empty") {
- delete def.e;
- def.name = "empty"
- }
- if(name === "attribute") {
- splitQNames(def)
- }
- if(name === "interleave") {
- if(e[0].name === "interleave") {
- if(e[1].name === "interleave") {
- e = def.e = e[0].e.concat(e[1].e)
+ if(offset > 1) {
+ leftChar = (text[offset - 2]);
+ if(!odfUtils.isODFWhitespace(leftChar)) {
+ r = FILTER_ACCEPT
+ }else {
+ if(!odfUtils.isODFWhitespace(text.substr(0, offset))) {
+ return FILTER_REJECT
+ }
+ }
}else {
- e = def.e = [e[1]].concat(e[0].e)
- }
- }else {
- if(e[1].name === "interleave") {
- e = def.e = [e[0]].concat(e[1].e)
+ leftNode = odfUtils.previousNode(container);
+ if(odfUtils.scanLeftForNonSpace(leftNode)) {
+ r = FILTER_ACCEPT
+ }
}
- }
- }
- }
- function resolveElements(def, elements) {
- var i = 0, e;
- while(def.e && i < def.e.length) {
- e = def.e[i];
- if(e.name === "elementref") {
- e.id = e.id || 0;
- def.e[i] = elements[e.id]
- }else {
- if(e.name !== "element") {
- resolveElements(e, elements)
+ if(r === FILTER_ACCEPT) {
+ return odfUtils.isTrailingWhitespace((container), offset) ? FILTER_REJECT : FILTER_ACCEPT
}
- }
- i += 1
- }
- }
- function main(dom, callback) {
- var elements = [], grammar = parse(dom && dom.documentElement, elements, undefined), i, e, defines = {};
- for(i = 0;i < grammar.e.length;i += 1) {
- e = grammar.e[i];
- if(e.name === "define") {
- defines[e.a.name] = e
- }else {
- if(e.name === "start") {
- start = e
+ rightChar = (text[offset]);
+ if(odfUtils.isODFWhitespace(rightChar)) {
+ return FILTER_REJECT
}
+ return odfUtils.scanLeftForAnyCharacter(odfUtils.previousNode(container)) ? FILTER_REJECT : FILTER_ACCEPT
}
- }
- if(!start) {
- return[new RelaxNGParseError("No Relax NG start element was found.")]
- }
- resolveDefines(start, defines);
- for(i in defines) {
- if(defines.hasOwnProperty(i)) {
- resolveDefines(defines[i], defines)
- }
- }
- for(i = 0;i < elements.length;i += 1) {
- resolveDefines(elements[i], defines)
- }
- if(callback) {
- self.rootPattern = callback(start.e[0], elements)
- }
- resolveElements(start, elements);
- for(i = 0;i < elements.length;i += 1) {
- resolveElements(elements[i], elements)
- }
- self.start = start;
- self.elements = elements;
- self.nsmap = nsmap;
- return null
- }
- this.parseRelaxNGDOM = main
-};
-runtime.loadClass("core.Cursor");
-runtime.loadClass("gui.SelectionMover");
-ops.OdtCursor = function OdtCursor(memberId, odtDocument) {
- var self = this, validSelectionTypes = {}, selectionType, selectionMover, cursor;
- this.removeFromOdtDocument = function() {
- cursor.remove()
- };
- this.move = function(number, extend) {
- var moved = 0;
- if(number > 0) {
- moved = selectionMover.movePointForward(number, extend)
+ leftNode = iterator.leftNode();
+ rightNode = container;
+ container = (container.parentNode);
+ r = checkLeftRight(container, leftNode, rightNode)
}else {
- if(number <= 0) {
- moved = -selectionMover.movePointBackward(-number, extend)
+ if(!odfUtils.isGroupingElement(container) || odfUtils.isWithinTrackedChanges(container, getRootNode())) {
+ r = FILTER_REJECT
+ }else {
+ leftNode = iterator.leftNode();
+ rightNode = iterator.rightNode();
+ r = checkLeftRight(container, leftNode, rightNode)
}
}
- self.handleUpdate();
- return moved
- };
- this.handleUpdate = function() {
- };
- this.getStepCounter = function() {
- return selectionMover.getStepCounter()
- };
- this.getMemberId = function() {
- return memberId
- };
- this.getNode = function() {
- return cursor.getNode()
- };
- this.getAnchorNode = function() {
- return cursor.getAnchorNode()
- };
- this.getSelectedRange = function() {
- return cursor.getSelectedRange()
- };
- this.setSelectedRange = function(range, isForwardSelection) {
- cursor.setSelectedRange(range, isForwardSelection);
- self.handleUpdate()
- };
- this.hasForwardSelection = function() {
- return cursor.hasForwardSelection()
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.getSelectionType = function() {
- return selectionType
- };
- this.setSelectionType = function(value) {
- if(validSelectionTypes.hasOwnProperty(value)) {
- selectionType = value
- }else {
- runtime.log("Invalid selection type: " + value)
- }
- };
- this.resetSelectionType = function() {
- self.setSelectionType(ops.OdtCursor.RangeSelection)
- };
- function init() {
- cursor = new core.Cursor(odtDocument.getDOM(), memberId);
- selectionMover = new gui.SelectionMover(cursor, odtDocument.getRootNode());
- validSelectionTypes[ops.OdtCursor.RangeSelection] = true;
- validSelectionTypes[ops.OdtCursor.RegionSelection] = true;
- self.resetSelectionType()
+ return r
}
- init()
};
-ops.OdtCursor.RangeSelection = "Range";
-ops.OdtCursor.RegionSelection = "Region";
-(function() {
- return ops.OdtCursor
-})();
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -11072,27 +9677,39 @@ ops.OdtCursor.RegionSelection = "Region";
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.EventNotifier");
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("gui.SelectionMover");
-runtime.loadClass("core.PositionFilterChain");
-runtime.loadClass("ops.StepsTranslator");
-runtime.loadClass("ops.TextPositionFilter");
-runtime.loadClass("ops.Member");
ops.OdtDocument = function OdtDocument(odfCanvas) {
- var self = this, odfUtils, domUtils, cursors = {}, members = {}, eventNotifier = new core.EventNotifier([ops.OdtDocument.signalMemberAdded, ops.OdtDocument.signalMemberUpdated, ops.OdtDocument.signalMemberRemoved, ops.OdtDocument.signalCursorAdded, ops.OdtDocument.signalCursorRemoved, ops.OdtDocument.signalCursorMoved, ops.OdtDocument.signalParagraphChanged, ops.OdtDocument.signalParagraphStyleModified, ops.OdtDocument.signalCommonStyleCreated, ops.OdtDocument.signalCommonStyleDeleted, ops.OdtDocument.signalTableAdded,
- ops.OdtDocument.signalOperationExecuted, ops.OdtDocument.signalUndoStackChanged, ops.OdtDocument.signalStepsInserted, ops.OdtDocument.signalStepsRemoved]), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT, filter, stepsTranslator, lastEditingOp, unsupportedMetadataRemoved = false;
+ var self = this, odfUtils, domUtils, cursors = {}, members = {}, eventNotifier = new core.EventNotifier([ops.Document.signalMemberAdded, ops.Document.signalMemberUpdated, ops.Document.signalMemberRemoved, ops.Document.signalCursorAdded, ops.Document.signalCursorRemoved, ops.Document.signalCursorMoved, ops.OdtDocument.signalParagraphChanged, ops.OdtDocument.signalParagraphStyleModified, ops.OdtDocument.signalCommonStyleCreated, ops.OdtDocument.signalCommonStyleDeleted, ops.OdtDocument.signalTableAdded,
+ ops.OdtDocument.signalOperationStart, ops.OdtDocument.signalOperationEnd, ops.OdtDocument.signalProcessingBatchStart, ops.OdtDocument.signalProcessingBatchEnd, ops.OdtDocument.signalUndoStackChanged, ops.OdtDocument.signalStepsInserted, ops.OdtDocument.signalStepsRemoved]), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT, filter, stepsTranslator, lastEditingOp, unsupportedMetadataRemoved = false;
function getRootNode() {
var element = odfCanvas.odfContainer().getContentElement(), localName = element && element.localName;
runtime.assert(localName === "text", "Unsupported content element type '" + localName + "' for OdtDocument");
return element
}
- function getDOM() {
- return(getRootNode().ownerDocument)
+ this.getDocumentElement = function() {
+ return odfCanvas.odfContainer().rootElement
+ };
+ this.getDOMDocument = function() {
+ return(this.getDocumentElement().ownerDocument)
+ };
+ this.cloneDocumentElement = function() {
+ var rootElement = self.getDocumentElement(), annotationViewManager = odfCanvas.getAnnotationViewManager(), initialDoc;
+ if(annotationViewManager) {
+ annotationViewManager.forgetAnnotations()
+ }
+ initialDoc = rootElement.cloneNode(true);
+ odfCanvas.refreshAnnotations();
+ return initialDoc
+ };
+ this.setDocumentElement = function(documentElement) {
+ var odfContainer = odfCanvas.odfContainer();
+ odfContainer.setRootElement(documentElement);
+ odfCanvas.setOdfContainer(odfContainer, true);
+ odfCanvas.refreshCSS()
+ };
+ function getDOMDocument() {
+ return(self.getDocumentElement().ownerDocument)
}
- this.getDOM = getDOM;
+ this.getDOMDocument = getDOMDocument;
function isRoot(node) {
if(node.namespaceURI === odf.Namespaces.officens && node.localName === "text" || node.namespaceURI === odf.Namespaces.officens && node.localName === "annotation") {
return true
@@ -11120,6 +9737,19 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
return FILTER_REJECT
}
}
+ function createStepIterator(container, offset, filters, subTree) {
+ var positionIterator = gui.SelectionMover.createPositionIterator(subTree), filterOrChain, stepIterator;
+ if(filters.length === 1) {
+ filterOrChain = filters[0]
+ }else {
+ filterOrChain = new core.PositionFilterChain;
+ filters.forEach(filterOrChain.addFilter)
+ }
+ stepIterator = new core.StepIterator(filterOrChain, positionIterator);
+ stepIterator.setPosition(container, offset);
+ return stepIterator
+ }
+ this.createStepIterator = createStepIterator;
function getIteratorAtPosition(position) {
var iterator = gui.SelectionMover.createPositionIterator(getRootNode()), point = stepsTranslator.convertStepsToDomPoint(position);
iterator.setUnfilteredPosition(point.node, point.offset);
@@ -11130,18 +9760,18 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
return stepsTranslator.convertDomPointToSteps(node, offset, roundDirection)
};
this.convertDomToCursorRange = function(selection, constraint) {
- var point1, point2, anchorConstraint = constraint(selection.anchorNode, selection.anchorOffset), focusConstraint;
+ var point1, point2, anchorConstraint = constraint && constraint(selection.anchorNode, selection.anchorOffset), focusConstraint;
point1 = stepsTranslator.convertDomPointToSteps(selection.anchorNode, selection.anchorOffset, anchorConstraint);
if(!constraint && (selection.anchorNode === selection.focusNode && selection.anchorOffset === selection.focusOffset)) {
point2 = point1
}else {
- focusConstraint = constraint(selection.focusNode, selection.focusOffset);
+ focusConstraint = constraint && constraint(selection.focusNode, selection.focusOffset);
point2 = stepsTranslator.convertDomPointToSteps(selection.focusNode, selection.focusOffset, focusConstraint)
}
return{position:point1, length:point2 - point1}
};
this.convertCursorToDomRange = function(position, length) {
- var range = getDOM().createRange(), point1, point2;
+ var range = getDOMDocument().createRange(), point1, point2;
point1 = stepsTranslator.convertStepsToDomPoint(position);
if(length) {
point2 = stepsTranslator.convertStepsToDomPoint(position + length);
@@ -11158,7 +9788,7 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
return range
};
function getTextNodeAtStep(steps, memberid) {
- var iterator = getIteratorAtPosition(steps), node = iterator.container(), lastTextNode, nodeOffset = 0, cursorNode = null;
+ var iterator = getIteratorAtPosition(steps), node = iterator.container(), lastTextNode, nodeOffset = 0, cursorNode = null, text;
if(node.nodeType === Node.TEXT_NODE) {
lastTextNode = (node);
nodeOffset = (iterator.unfilteredDomOffset());
@@ -11166,12 +9796,12 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
if(nodeOffset > 0) {
lastTextNode = lastTextNode.splitText(nodeOffset)
}
- lastTextNode.parentNode.insertBefore(getDOM().createTextNode(""), lastTextNode);
+ lastTextNode.parentNode.insertBefore(getDOMDocument().createTextNode(""), lastTextNode);
lastTextNode = (lastTextNode.previousSibling);
nodeOffset = 0
}
}else {
- lastTextNode = getDOM().createTextNode("");
+ lastTextNode = getDOMDocument().createTextNode("");
nodeOffset = 0;
node.insertBefore(lastTextNode, iterator.rightNode())
}
@@ -11182,7 +9812,7 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
cursorNode.parentNode.insertBefore(cursorNode.nextSibling, cursorNode)
}
if(lastTextNode.length > 0 && lastTextNode.nextSibling !== cursorNode) {
- lastTextNode = getDOM().createTextNode("");
+ lastTextNode = getDOMDocument().createTextNode("");
nodeOffset = 0
}
cursorNode.parentNode.insertBefore(lastTextNode, cursorNode)
@@ -11193,14 +9823,16 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
}
}
while(lastTextNode.previousSibling && lastTextNode.previousSibling.nodeType === Node.TEXT_NODE) {
- lastTextNode.previousSibling.appendData(lastTextNode.data);
- nodeOffset = (lastTextNode.previousSibling.length);
- lastTextNode = (lastTextNode.previousSibling);
+ text = (lastTextNode.previousSibling);
+ text.appendData(lastTextNode.data);
+ nodeOffset = text.length;
+ lastTextNode = text;
lastTextNode.parentNode.removeChild(lastTextNode.nextSibling)
}
while(lastTextNode.nextSibling && lastTextNode.nextSibling.nodeType === Node.TEXT_NODE) {
- lastTextNode.appendData(lastTextNode.nextSibling.data);
- lastTextNode.parentNode.removeChild(lastTextNode.nextSibling)
+ text = (lastTextNode.nextSibling);
+ lastTextNode.appendData(text.data);
+ lastTextNode.parentNode.removeChild(text)
}
return{textNode:lastTextNode, offset:nodeOffset}
}
@@ -11217,7 +9849,7 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
function getParagraphStyleAttributes(styleName) {
var node = getParagraphStyleElement(styleName);
if(node) {
- return odfCanvas.getFormatting().getInheritedStyleAttributes(node)
+ return odfCanvas.getFormatting().getInheritedStyleAttributes(node, false)
}
return null
}
@@ -11237,13 +9869,20 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
}
function upgradeWhitespaceToElement(textNode, offset) {
runtime.assert(textNode.data[offset] === " ", "upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");
- var space = textNode.ownerDocument.createElementNS(odf.Namespaces.textns, "text:s");
+ var space = textNode.ownerDocument.createElementNS(odf.Namespaces.textns, "text:s"), container = textNode.parentNode, adjacentNode = textNode;
space.appendChild(textNode.ownerDocument.createTextNode(" "));
- textNode.deleteData(offset, 1);
- if(offset > 0) {
- textNode = (textNode.splitText(offset))
+ if(textNode.length === 1) {
+ container.replaceChild(space, textNode)
+ }else {
+ textNode.deleteData(offset, 1);
+ if(offset > 0) {
+ if(offset < textNode.length) {
+ textNode.splitText(offset)
+ }
+ adjacentNode = textNode.nextSibling
+ }
+ container.insertBefore(space, adjacentNode)
}
- textNode.parentNode.insertBefore(space, textNode);
return space
}
function upgradeWhitespacesAtPosition(position) {
@@ -11253,7 +9892,7 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
for(i = -1;i <= 1;i += 1) {
container = iterator.container();
offset = iterator.unfilteredDomOffset();
- if(container.nodeType === Node.TEXT_NODE && (container.data[offset] === " " && odfUtils.isSignificantWhitespace(container, offset))) {
+ if(container.nodeType === Node.TEXT_NODE && (container.data[offset] === " " && odfUtils.isSignificantWhitespace((container), offset))) {
container = upgradeWhitespaceToElement((container), offset);
iterator.moveToEndOfNode(container)
}
@@ -11265,12 +9904,12 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
var iterator = getIteratorAtPosition(position), container, offset, firstSpaceElementChild, lastSpaceElementChild;
container = iterator.container();
offset = iterator.unfilteredDomOffset();
- while(!odfUtils.isSpaceElement(container) && container.childNodes[offset]) {
- container = container.childNodes[offset];
+ while(!odfUtils.isSpaceElement(container) && container.childNodes.item(offset)) {
+ container = (container.childNodes.item(offset));
offset = 0
}
if(container.nodeType === Node.TEXT_NODE) {
- container = container.parentNode
+ container = (container.parentNode)
}
if(odfUtils.isDowngradableSpaceElement(container)) {
firstSpaceElementChild = container.firstChild;
@@ -11286,50 +9925,46 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
this.getParagraphElement = getParagraphElement;
this.getParagraphStyleAttributes = getParagraphStyleAttributes;
this.getTextNodeAtStep = getTextNodeAtStep;
+ function paragraphOrRoot(container, offset, root) {
+ var node = container.childNodes.item(offset) || container, paragraph = getParagraphElement(node);
+ if(paragraph && domUtils.containsNode(root, paragraph)) {
+ return(paragraph)
+ }
+ return root
+ }
this.fixCursorPositions = function() {
- var rootConstrainedFilter = new core.PositionFilterChain;
- rootConstrainedFilter.addFilter("BaseFilter", filter);
Object.keys(cursors).forEach(function(memberId) {
- var cursor = cursors[memberId], stepCounter = cursor.getStepCounter(), stepsSelectionLength, positionsToAdjustFocus, positionsToAdjustAnchor, positionsToAnchor, cursorMoved = false;
- rootConstrainedFilter.addFilter("RootFilter", self.createRootFilter(memberId));
- stepsSelectionLength = stepCounter.countStepsToPosition(cursor.getAnchorNode(), 0, rootConstrainedFilter);
- if(!stepCounter.isPositionWalkable(rootConstrainedFilter)) {
+ var cursor = cursors[memberId], root = getRoot(cursor.getNode()), rootFilter = self.createRootFilter(root), subTree, startPoint, endPoint, selectedRange, cursorMoved = false;
+ selectedRange = cursor.getSelectedRange();
+ subTree = paragraphOrRoot((selectedRange.startContainer), selectedRange.startOffset, root);
+ startPoint = createStepIterator((selectedRange.startContainer), selectedRange.startOffset, [filter, rootFilter], subTree);
+ if(!selectedRange.collapsed) {
+ subTree = paragraphOrRoot((selectedRange.endContainer), selectedRange.endOffset, root);
+ endPoint = createStepIterator((selectedRange.endContainer), selectedRange.endOffset, [filter, rootFilter], subTree)
+ }else {
+ endPoint = startPoint
+ }
+ if(!startPoint.isStep() || !endPoint.isStep()) {
cursorMoved = true;
- positionsToAdjustFocus = stepCounter.countPositionsToNearestStep(cursor.getNode(), 0, rootConstrainedFilter);
- positionsToAdjustAnchor = stepCounter.countPositionsToNearestStep(cursor.getAnchorNode(), 0, rootConstrainedFilter);
- cursor.move(positionsToAdjustFocus);
- if(stepsSelectionLength !== 0) {
- if(positionsToAdjustAnchor > 0) {
- stepsSelectionLength += 1
- }
- if(positionsToAdjustFocus > 0) {
- stepsSelectionLength -= 1
- }
- positionsToAnchor = stepCounter.countSteps(stepsSelectionLength, rootConstrainedFilter);
- cursor.move(positionsToAnchor);
- cursor.move(-positionsToAnchor, true)
- }
+ runtime.assert(startPoint.roundToClosestStep(), "No walkable step found for cursor owned by " + memberId);
+ selectedRange.setStart(startPoint.container(), startPoint.offset());
+ runtime.assert(endPoint.roundToClosestStep(), "No walkable step found for cursor owned by " + memberId);
+ selectedRange.setEnd(endPoint.container(), endPoint.offset())
}else {
- if(stepsSelectionLength === 0) {
- cursorMoved = true;
- cursor.move(0)
+ if(startPoint.container() === endPoint.container() && startPoint.offset() === endPoint.offset()) {
+ if(!selectedRange.collapsed || cursor.getAnchorNode() !== cursor.getNode()) {
+ cursorMoved = true;
+ selectedRange.setStart(startPoint.container(), startPoint.offset());
+ selectedRange.collapse(true)
+ }
}
}
if(cursorMoved) {
- self.emit(ops.OdtDocument.signalCursorMoved, cursor)
+ cursor.setSelectedRange(selectedRange, cursor.hasForwardSelection());
+ self.emit(ops.Document.signalCursorMoved, cursor)
}
- rootConstrainedFilter.removeFilter("RootFilter")
})
};
- this.getDistanceFromCursor = function(memberid, node, offset) {
- var cursor = cursors[memberid], focusPosition, targetPosition;
- runtime.assert(node !== null && node !== undefined, "OdtDocument.getDistanceFromCursor called without node");
- if(cursor) {
- focusPosition = stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0);
- targetPosition = stepsTranslator.convertDomPointToSteps(node, offset)
- }
- return targetPosition - focusPosition
- };
this.getCursorPosition = function(memberid) {
var cursor = cursors[memberid];
return cursor ? stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0) : 0
@@ -11348,6 +9983,9 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
this.getOdfCanvas = function() {
return odfCanvas
};
+ this.getCanvas = function() {
+ return odfCanvas
+ };
this.getRootNode = getRootNode;
this.addMember = function(member) {
runtime.assert(members[member.getMemberId()] === undefined, "This member already exists");
@@ -11362,36 +10000,36 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
this.getCursor = function(memberid) {
return cursors[memberid]
};
- this.getCursors = function() {
+ this.getMemberIds = function() {
var list = [], i;
for(i in cursors) {
if(cursors.hasOwnProperty(i)) {
- list.push(cursors[i])
+ list.push(cursors[i].getMemberId())
}
}
return list
};
this.addCursor = function(cursor) {
runtime.assert(Boolean(cursor), "OdtDocument::addCursor without cursor");
- var distanceToFirstTextNode = cursor.getStepCounter().countSteps(1, filter), memberid = cursor.getMemberId();
+ var memberid = cursor.getMemberId(), initialSelection = self.convertCursorToDomRange(0, 0);
runtime.assert(typeof memberid === "string", "OdtDocument::addCursor has cursor without memberid");
runtime.assert(!cursors[memberid], "OdtDocument::addCursor is adding a duplicate cursor with memberid " + memberid);
- cursor.move(distanceToFirstTextNode);
+ cursor.setSelectedRange(initialSelection, true);
cursors[memberid] = cursor
};
this.removeCursor = function(memberid) {
var cursor = cursors[memberid];
if(cursor) {
- cursor.removeFromOdtDocument();
+ cursor.removeFromDocument();
delete cursors[memberid];
- self.emit(ops.OdtDocument.signalCursorRemoved, memberid);
+ self.emit(ops.Document.signalCursorRemoved, memberid);
return true
}
return false
};
this.moveCursor = function(memberid, position, length, selectionType) {
var cursor = cursors[memberid], selectionRange = self.convertCursorToDomRange(position, length);
- if(cursor && selectionRange) {
+ if(cursor) {
cursor.setSelectedRange(selectionRange, length >= 0);
cursor.setSelectionType(selectionType || ops.OdtCursor.RangeSelection)
}
@@ -11424,22 +10062,19 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
stepsTranslator = new ops.StepsTranslator(getRootNode, gui.SelectionMover.createPositionIterator, filter, 500);
eventNotifier.subscribe(ops.OdtDocument.signalStepsInserted, stepsTranslator.handleStepsInserted);
eventNotifier.subscribe(ops.OdtDocument.signalStepsRemoved, stepsTranslator.handleStepsRemoved);
- eventNotifier.subscribe(ops.OdtDocument.signalOperationExecuted, handleOperationExecuted)
+ eventNotifier.subscribe(ops.OdtDocument.signalOperationEnd, handleOperationExecuted)
}
init()
};
-ops.OdtDocument.signalMemberAdded = "member/added";
-ops.OdtDocument.signalMemberUpdated = "member/updated";
-ops.OdtDocument.signalMemberRemoved = "member/removed";
-ops.OdtDocument.signalCursorAdded = "cursor/added";
-ops.OdtDocument.signalCursorRemoved = "cursor/removed";
-ops.OdtDocument.signalCursorMoved = "cursor/moved";
ops.OdtDocument.signalParagraphChanged = "paragraph/changed";
ops.OdtDocument.signalTableAdded = "table/added";
ops.OdtDocument.signalCommonStyleCreated = "style/created";
ops.OdtDocument.signalCommonStyleDeleted = "style/deleted";
ops.OdtDocument.signalParagraphStyleModified = "paragraphstyle/modified";
-ops.OdtDocument.signalOperationExecuted = "operation/executed";
+ops.OdtDocument.signalOperationStart = "operation/start";
+ops.OdtDocument.signalOperationEnd = "operation/end";
+ops.OdtDocument.signalProcessingBatchStart = "router/batchstart";
+ops.OdtDocument.signalProcessingBatchEnd = "router/batchend";
ops.OdtDocument.signalUndoStackChanged = "undo/changed";
ops.OdtDocument.signalStepsInserted = "steps/inserted";
ops.OdtDocument.signalStepsRemoved = "steps/removed";
@@ -11483,1415 +10118,6 @@ ops.OdtDocument.signalStepsRemoved = "steps/removed";
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.Operation = function Operation() {
-};
-ops.Operation.prototype.init = function(data) {
-};
-ops.Operation.prototype.isEdit;
-ops.Operation.prototype.execute = function(odtDocument) {
-};
-ops.Operation.prototype.spec = function() {
-};
-runtime.loadClass("xmldom.RelaxNGParser");
-xmldom.RelaxNGItem;
-xmldom.RelaxNG = function RelaxNG() {
- var xmlnsns = "http://www.w3.org/2000/xmlns/", createChoice, createInterleave, createGroup, createAfter, createOneOrMore, createValue, createAttribute, createNameClass, createData, makePattern, applyAfter, childDeriv, rootPattern, notAllowed = {type:"notAllowed", nullable:false, hash:"notAllowed", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() {
- return notAllowed
- }, startTagOpenDeriv:function() {
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return notAllowed
- }, endTagDeriv:function() {
- return notAllowed
- }}, empty = {type:"empty", nullable:true, hash:"empty", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() {
- return notAllowed
- }, startTagOpenDeriv:function() {
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return empty
- }, endTagDeriv:function() {
- return notAllowed
- }}, text = {type:"text", nullable:true, hash:"text", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() {
- return text
- }, startTagOpenDeriv:function() {
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return text
- }, endTagDeriv:function() {
- return notAllowed
- }};
- function memoize0arg(func) {
- function f() {
- var cache;
- function g() {
- if(cache === undefined) {
- cache = func()
- }
- return cache
- }
- return g
- }
- return f()
- }
- function memoize1arg(type, func) {
- function f() {
- var cache = {}, cachecount = 0;
- function g(a) {
- var ahash = a.hash || a.toString(), v;
- if(cache.hasOwnProperty(ahash)) {
- return cache[ahash]
- }
- cache[ahash] = v = func(a);
- v.hash = type + cachecount.toString();
- cachecount += 1;
- return v
- }
- return g
- }
- return f()
- }
- function memoizeNode(func) {
- function f() {
- var cache = {};
- function g(node) {
- var v, m;
- if(!cache.hasOwnProperty(node.localName)) {
- cache[node.localName] = m = {}
- }else {
- m = cache[node.localName];
- v = m[node.namespaceURI];
- if(v !== undefined) {
- return v
- }
- }
- m[node.namespaceURI] = v = func(node);
- return v
- }
- return g
- }
- return f()
- }
- function memoize2arg(type, fastfunc, func) {
- function f() {
- var cache = {}, cachecount = 0;
- function g(a, b) {
- var v = fastfunc && fastfunc(a, b), ahash, bhash, m;
- if(v !== undefined) {
- return v
- }
- ahash = a.hash || a.toString();
- bhash = b.hash || b.toString();
- if(!cache.hasOwnProperty(ahash)) {
- cache[ahash] = m = {}
- }else {
- m = cache[ahash];
- if(m.hasOwnProperty(bhash)) {
- return m[bhash]
- }
- }
- m[bhash] = v = func(a, b);
- v.hash = type + cachecount.toString();
- cachecount += 1;
- return v
- }
- return g
- }
- return f()
- }
- function unorderedMemoize2arg(type, fastfunc, func) {
- function f() {
- var cache = {}, cachecount = 0;
- function g(a, b) {
- var v = fastfunc && fastfunc(a, b), ahash, bhash, hash, m;
- if(v !== undefined) {
- return v
- }
- ahash = a.hash || a.toString();
- bhash = b.hash || b.toString();
- if(ahash < bhash) {
- hash = ahash;
- ahash = bhash;
- bhash = hash;
- hash = a;
- a = b;
- b = hash
- }
- if(!cache.hasOwnProperty(ahash)) {
- cache[ahash] = m = {}
- }else {
- m = cache[ahash];
- if(m.hasOwnProperty(bhash)) {
- return m[bhash]
- }
- }
- m[bhash] = v = func(a, b);
- v.hash = type + cachecount.toString();
- cachecount += 1;
- return v
- }
- return g
- }
- return f()
- }
- function getUniqueLeaves(leaves, pattern) {
- if(pattern.p1.type === "choice") {
- getUniqueLeaves(leaves, pattern.p1)
- }else {
- leaves[pattern.p1.hash] = pattern.p1
- }
- if(pattern.p2.type === "choice") {
- getUniqueLeaves(leaves, pattern.p2)
- }else {
- leaves[pattern.p2.hash] = pattern.p2
- }
- }
- createChoice = memoize2arg("choice", function(p1, p2) {
- if(p1 === notAllowed) {
- return p2
- }
- if(p2 === notAllowed) {
- return p1
- }
- if(p1 === p2) {
- return p1
- }
- }, function(p1, p2) {
- function makeChoice(p1, p2) {
- return{type:"choice", nullable:p1.nullable || p2.nullable, hash:undefined, nc:undefined, p:undefined, p1:p1, p2:p2, textDeriv:function(context, text) {
- return createChoice(p1.textDeriv(context, text), p2.textDeriv(context, text))
- }, startTagOpenDeriv:memoizeNode(function(node) {
- return createChoice(p1.startTagOpenDeriv(node), p2.startTagOpenDeriv(node))
- }), attDeriv:function(context, attribute) {
- return createChoice(p1.attDeriv(context, attribute), p2.attDeriv(context, attribute))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createChoice(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
- }), endTagDeriv:memoize0arg(function() {
- return createChoice(p1.endTagDeriv(), p2.endTagDeriv())
- })}
- }
- var leaves = {}, i;
- getUniqueLeaves(leaves, {p1:p1, p2:p2});
- p1 = undefined;
- p2 = undefined;
- for(i in leaves) {
- if(leaves.hasOwnProperty(i)) {
- if(p1 === undefined) {
- p1 = leaves[i]
- }else {
- if(p2 === undefined) {
- p2 = leaves[i]
- }else {
- p2 = createChoice(p2, leaves[i])
- }
- }
- }
- }
- return makeChoice(p1, p2)
- });
- createInterleave = unorderedMemoize2arg("interleave", function(p1, p2) {
- if(p1 === notAllowed || p2 === notAllowed) {
- return notAllowed
- }
- if(p1 === empty) {
- return p2
- }
- if(p2 === empty) {
- return p1
- }
- }, function(p1, p2) {
- return{type:"interleave", nullable:p1.nullable && p2.nullable, hash:undefined, p1:p1, p2:p2, textDeriv:function(context, text) {
- return createChoice(createInterleave(p1.textDeriv(context, text), p2), createInterleave(p1, p2.textDeriv(context, text)))
- }, startTagOpenDeriv:memoizeNode(function(node) {
- return createChoice(applyAfter(function(p) {
- return createInterleave(p, p2)
- }, p1.startTagOpenDeriv(node)), applyAfter(function(p) {
- return createInterleave(p1, p)
- }, p2.startTagOpenDeriv(node)))
- }), attDeriv:function(context, attribute) {
- return createChoice(createInterleave(p1.attDeriv(context, attribute), p2), createInterleave(p1, p2.attDeriv(context, attribute)))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createInterleave(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
- }), endTagDeriv:undefined}
- });
- createGroup = memoize2arg("group", function(p1, p2) {
- if(p1 === notAllowed || p2 === notAllowed) {
- return notAllowed
- }
- if(p1 === empty) {
- return p2
- }
- if(p2 === empty) {
- return p1
- }
- }, function(p1, p2) {
- return{type:"group", p1:p1, p2:p2, nullable:p1.nullable && p2.nullable, textDeriv:function(context, text) {
- var p = createGroup(p1.textDeriv(context, text), p2);
- if(p1.nullable) {
- return createChoice(p, p2.textDeriv(context, text))
- }
- return p
- }, startTagOpenDeriv:function(node) {
- var x = applyAfter(function(p) {
- return createGroup(p, p2)
- }, p1.startTagOpenDeriv(node));
- if(p1.nullable) {
- return createChoice(x, p2.startTagOpenDeriv(node))
- }
- return x
- }, attDeriv:function(context, attribute) {
- return createChoice(createGroup(p1.attDeriv(context, attribute), p2), createGroup(p1, p2.attDeriv(context, attribute)))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createGroup(p1.startTagCloseDeriv(), p2.startTagCloseDeriv())
- })}
- });
- createAfter = memoize2arg("after", function(p1, p2) {
- if(p1 === notAllowed || p2 === notAllowed) {
- return notAllowed
- }
- }, function(p1, p2) {
- return{type:"after", p1:p1, p2:p2, nullable:false, textDeriv:function(context, text) {
- return createAfter(p1.textDeriv(context, text), p2)
- }, startTagOpenDeriv:memoizeNode(function(node) {
- return applyAfter(function(p) {
- return createAfter(p, p2)
- }, p1.startTagOpenDeriv(node))
- }), attDeriv:function(context, attribute) {
- return createAfter(p1.attDeriv(context, attribute), p2)
- }, startTagCloseDeriv:memoize0arg(function() {
- return createAfter(p1.startTagCloseDeriv(), p2)
- }), endTagDeriv:memoize0arg(function() {
- return p1.nullable ? p2 : notAllowed
- })}
- });
- createOneOrMore = memoize1arg("oneormore", function(p) {
- if(p === notAllowed) {
- return notAllowed
- }
- return{type:"oneOrMore", p:p, nullable:p.nullable, textDeriv:function(context, text) {
- return createGroup(p.textDeriv(context, text), createChoice(this, empty))
- }, startTagOpenDeriv:function(node) {
- var oneOrMore = this;
- return applyAfter(function(pf) {
- return createGroup(pf, createChoice(oneOrMore, empty))
- }, p.startTagOpenDeriv(node))
- }, attDeriv:function(context, attribute) {
- var oneOrMore = this;
- return createGroup(p.attDeriv(context, attribute), createChoice(oneOrMore, empty))
- }, startTagCloseDeriv:memoize0arg(function() {
- return createOneOrMore(p.startTagCloseDeriv())
- })}
- });
- function createElement(nc, p) {
- return{type:"element", nc:nc, nullable:false, textDeriv:function() {
- return notAllowed
- }, startTagOpenDeriv:function(node) {
- if(nc.contains(node)) {
- return createAfter(p, empty)
- }
- return notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return this
- }}
- }
- function valueMatch(context, pattern, text) {
- return pattern.nullable && /^\s+$/.test(text) || pattern.textDeriv(context, text).nullable
- }
- createAttribute = memoize2arg("attribute", undefined, function(nc, p) {
- return{type:"attribute", nullable:false, hash:undefined, nc:nc, p:p, p1:undefined, p2:undefined, textDeriv:undefined, startTagOpenDeriv:undefined, attDeriv:function(context, attribute) {
- if(nc.contains(attribute) && valueMatch(context, p, attribute.nodeValue)) {
- return empty
- }
- return notAllowed
- }, startTagCloseDeriv:function() {
- return notAllowed
- }, endTagDeriv:undefined}
- });
- function createList() {
- return{type:"list", nullable:false, hash:"list", textDeriv:function() {
- return empty
- }}
- }
- createValue = memoize1arg("value", function(value) {
- return{type:"value", nullable:false, value:value, textDeriv:function(context, text) {
- return text === value ? empty : notAllowed
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return this
- }}
- });
- createData = memoize1arg("data", function(type) {
- return{type:"data", nullable:false, dataType:type, textDeriv:function() {
- return empty
- }, attDeriv:function() {
- return notAllowed
- }, startTagCloseDeriv:function() {
- return this
- }}
- });
- applyAfter = function applyAfter(f, p) {
- var result;
- if(p.type === "after") {
- result = createAfter(p.p1, f(p.p2))
- }else {
- if(p.type === "choice") {
- result = createChoice(applyAfter(f, p.p1), applyAfter(f, p.p2))
- }else {
- result = p
- }
- }
- return result
- };
- function attsDeriv(context, pattern, attributes, position) {
- if(pattern === notAllowed) {
- return notAllowed
- }
- if(position >= attributes.length) {
- return pattern
- }
- if(position === 0) {
- position = 0
- }
- var a = attributes.item(position);
- while(a.namespaceURI === xmlnsns) {
- position += 1;
- if(position >= attributes.length) {
- return pattern
- }
- a = attributes.item(position)
- }
- a = attsDeriv(context, pattern.attDeriv(context, attributes.item(position)), attributes, position + 1);
- return a
- }
- function childrenDeriv(context, pattern, walker) {
- var element = walker.currentNode, childNode = walker.firstChild(), childNodes = [], i, p;
- while(childNode) {
- if(childNode.nodeType === Node.ELEMENT_NODE) {
- childNodes.push(childNode)
- }else {
- if(childNode.nodeType === Node.TEXT_NODE && !/^\s*$/.test(childNode.nodeValue)) {
- childNodes.push(childNode.nodeValue)
- }
- }
- childNode = walker.nextSibling()
- }
- if(childNodes.length === 0) {
- childNodes = [""]
- }
- p = pattern;
- for(i = 0;p !== notAllowed && i < childNodes.length;i += 1) {
- childNode = childNodes[i];
- if(typeof childNode === "string") {
- if(/^\s*$/.test(childNode)) {
- p = createChoice(p, p.textDeriv(context, childNode))
- }else {
- p = p.textDeriv(context, childNode)
- }
- }else {
- walker.currentNode = childNode;
- p = childDeriv(context, p, walker)
- }
- }
- walker.currentNode = element;
- return p
- }
- childDeriv = function childDeriv(context, pattern, walker) {
- var childNode = walker.currentNode, p;
- p = pattern.startTagOpenDeriv(childNode);
- p = attsDeriv(context, p, childNode.attributes, 0);
- p = p.startTagCloseDeriv();
- p = childrenDeriv(context, p, walker);
- p = p.endTagDeriv();
- return p
- };
- function addNames(name, ns, pattern) {
- if(pattern.e[0].a) {
- name.push(pattern.e[0].text);
- ns.push(pattern.e[0].a.ns)
- }else {
- addNames(name, ns, pattern.e[0])
- }
- if(pattern.e[1].a) {
- name.push(pattern.e[1].text);
- ns.push(pattern.e[1].a.ns)
- }else {
- addNames(name, ns, pattern.e[1])
- }
- }
- createNameClass = function createNameClass(pattern) {
- var name, ns, hash, i, result;
- if(pattern.name === "name") {
- name = pattern.text;
- ns = pattern.a.ns;
- result = {name:name, ns:ns, hash:"{" + ns + "}" + name, contains:function(node) {
- return node.namespaceURI === ns && node.localName === name
- }}
- }else {
- if(pattern.name === "choice") {
- name = [];
- ns = [];
- addNames(name, ns, pattern);
- hash = "";
- for(i = 0;i < name.length;i += 1) {
- hash += "{" + ns[i] + "}" + name[i] + ","
- }
- result = {hash:hash, contains:function(node) {
- var j;
- for(j = 0;j < name.length;j += 1) {
- if(name[j] === node.localName && ns[j] === node.namespaceURI) {
- return true
- }
- }
- return false
- }}
- }else {
- result = {hash:"anyName", contains:function() {
- return true
- }}
- }
- }
- return result
- };
- function resolveElement(pattern, elements) {
- var element, p, i, hash;
- hash = "element" + pattern.id.toString();
- p = elements[pattern.id] = {hash:hash};
- element = createElement(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements));
- for(i in element) {
- if(element.hasOwnProperty(i)) {
- p[i] = element[i]
- }
- }
- return p
- }
- makePattern = function makePattern(pattern, elements) {
- var p, i;
- if(pattern.name === "elementref") {
- p = pattern.id || 0;
- pattern = elements[p];
- if(pattern.name !== undefined) {
- return resolveElement(pattern, elements)
- }
- return pattern
- }
- switch(pattern.name) {
- case "empty":
- return empty;
- case "notAllowed":
- return notAllowed;
- case "text":
- return text;
- case "choice":
- return createChoice(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements));
- case "interleave":
- p = makePattern(pattern.e[0], elements);
- for(i = 1;i < pattern.e.length;i += 1) {
- p = createInterleave(p, makePattern(pattern.e[i], elements))
- }
- return p;
- case "group":
- return createGroup(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements));
- case "oneOrMore":
- return createOneOrMore(makePattern(pattern.e[0], elements));
- case "attribute":
- return createAttribute(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements));
- case "value":
- return createValue(pattern.text);
- case "data":
- p = pattern.a && pattern.a.type;
- if(p === undefined) {
- p = ""
- }
- return createData(p);
- case "list":
- return createList()
- }
- throw"No support for " + pattern.name;
- };
- this.makePattern = function(pattern, elements) {
- var copy = {}, i;
- for(i in elements) {
- if(elements.hasOwnProperty(i)) {
- copy[i] = elements[i]
- }
- }
- i = makePattern(pattern, copy);
- return i
- };
- this.validate = function validate(walker, callback) {
- var errors;
- walker.currentNode = walker.root;
- errors = childDeriv(null, rootPattern, walker);
- if(!errors.nullable) {
- runtime.log("Error in Relax NG validation: " + errors);
- callback(["Error in Relax NG validation: " + errors])
- }else {
- callback(null)
- }
- };
- this.init = function init(rootPattern1) {
- rootPattern = rootPattern1
- }
-};
-runtime.loadClass("xmldom.RelaxNGParser");
-xmldom.RelaxNG2 = function RelaxNG2() {
- var start, validateNonEmptyPattern, nsmap;
- function RelaxNGParseError(error, context) {
- this.message = function() {
- if(context) {
- error += context.nodeType === Node.ELEMENT_NODE ? " Element " : " Node ";
- error += context.nodeName;
- if(context.nodeValue) {
- error += " with value '" + context.nodeValue + "'"
- }
- error += "."
- }
- return error
- }
- }
- function validateOneOrMore(elementdef, walker, element) {
- var node, i = 0, err;
- do {
- node = walker.currentNode;
- err = validateNonEmptyPattern(elementdef.e[0], walker, element);
- i += 1
- }while(!err && node !== walker.currentNode);
- if(i > 1) {
- walker.currentNode = node;
- return null
- }
- return err
- }
- function qName(node) {
- return nsmap[node.namespaceURI] + ":" + node.localName
- }
- function isWhitespace(node) {
- return node && (node.nodeType === Node.TEXT_NODE && /^\s+$/.test(node.nodeValue))
- }
- function validatePattern(elementdef, walker, element, data) {
- if(elementdef.name === "empty") {
- return null
- }
- return validateNonEmptyPattern(elementdef, walker, element, data)
- }
- function validateAttribute(elementdef, walker, element) {
- if(elementdef.e.length !== 2) {
- throw"Attribute with wrong # of elements: " + elementdef.e.length;
- }
- var att, a, l = elementdef.localnames.length, i;
- for(i = 0;i < l;i += 1) {
- a = element.getAttributeNS(elementdef.namespaces[i], elementdef.localnames[i]);
- if(a === "" && !element.hasAttributeNS(elementdef.namespaces[i], elementdef.localnames[i])) {
- a = undefined
- }
- if(att !== undefined && a !== undefined) {
- return[new RelaxNGParseError("Attribute defined too often.", element)]
- }
- att = a
- }
- if(att === undefined) {
- return[new RelaxNGParseError("Attribute not found: " + elementdef.names, element)]
- }
- return validatePattern(elementdef.e[1], walker, element, att)
- }
- function validateTop(elementdef, walker, element) {
- return validatePattern(elementdef, walker, element)
- }
- function validateElement(elementdef, walker) {
- if(elementdef.e.length !== 2) {
- throw"Element with wrong # of elements: " + elementdef.e.length;
- }
- var node = walker.currentNode, type = node ? node.nodeType : 0, error = null;
- while(type > Node.ELEMENT_NODE) {
- if(type !== Node.COMMENT_NODE && (type !== Node.TEXT_NODE || !/^\s+$/.test(walker.currentNode.nodeValue))) {
- return[new RelaxNGParseError("Not allowed node of type " + type + ".")]
- }
- node = walker.nextSibling();
- type = node ? node.nodeType : 0
- }
- if(!node) {
- return[new RelaxNGParseError("Missing element " + elementdef.names)]
- }
- if(elementdef.names && elementdef.names.indexOf(qName(node)) === -1) {
- return[new RelaxNGParseError("Found " + node.nodeName + " instead of " + elementdef.names + ".", node)]
- }
- if(walker.firstChild()) {
- error = validateTop(elementdef.e[1], walker, node);
- while(walker.nextSibling()) {
- type = walker.currentNode.nodeType;
- if(!isWhitespace(walker.currentNode) && type !== Node.COMMENT_NODE) {
- return[new RelaxNGParseError("Spurious content.", walker.currentNode)]
- }
- }
- if(walker.parentNode() !== node) {
- return[new RelaxNGParseError("Implementation error.")]
- }
- }else {
- error = validateTop(elementdef.e[1], walker, node)
- }
- node = walker.nextSibling();
- return error
- }
- function validateChoice(elementdef, walker, element, data) {
- if(elementdef.e.length !== 2) {
- throw"Choice with wrong # of options: " + elementdef.e.length;
- }
- var node = walker.currentNode, err;
- if(elementdef.e[0].name === "empty") {
- err = validateNonEmptyPattern(elementdef.e[1], walker, element, data);
- if(err) {
- walker.currentNode = node
- }
- return null
- }
- err = validatePattern(elementdef.e[0], walker, element, data);
- if(err) {
- walker.currentNode = node;
- err = validateNonEmptyPattern(elementdef.e[1], walker, element, data)
- }
- return err
- }
- function validateInterleave(elementdef, walker, element) {
- var l = elementdef.e.length, n = [l], err, i, todo = l, donethisround, node, subnode, e;
- while(todo > 0) {
- donethisround = 0;
- node = walker.currentNode;
- for(i = 0;i < l;i += 1) {
- subnode = walker.currentNode;
- if(n[i] !== true && n[i] !== subnode) {
- e = elementdef.e[i];
- err = validateNonEmptyPattern(e, walker, element);
- if(err) {
- walker.currentNode = subnode;
- if(n[i] === undefined) {
- n[i] = false
- }
- }else {
- if(subnode === walker.currentNode || (e.name === "oneOrMore" || e.name === "choice" && (e.e[0].name === "oneOrMore" || e.e[1].name === "oneOrMore"))) {
- donethisround += 1;
- n[i] = subnode
- }else {
- donethisround += 1;
- n[i] = true
- }
- }
- }
- }
- if(node === walker.currentNode && donethisround === todo) {
- return null
- }
- if(donethisround === 0) {
- for(i = 0;i < l;i += 1) {
- if(n[i] === false) {
- return[new RelaxNGParseError("Interleave does not match.", element)]
- }
- }
- return null
- }
- todo = 0;
- for(i = 0;i < l;i += 1) {
- if(n[i] !== true) {
- todo += 1
- }
- }
- }
- return null
- }
- function validateGroup(elementdef, walker, element) {
- if(elementdef.e.length !== 2) {
- throw"Group with wrong # of members: " + elementdef.e.length;
- }
- return validateNonEmptyPattern(elementdef.e[0], walker, element) || validateNonEmptyPattern(elementdef.e[1], walker, element)
- }
- function validateText(elementdef, walker, element) {
- var node = walker.currentNode, type = node ? node.nodeType : 0;
- while(node !== element && type !== 3) {
- if(type === 1) {
- return[new RelaxNGParseError("Element not allowed here.", node)]
- }
- node = walker.nextSibling();
- type = node ? node.nodeType : 0
- }
- walker.nextSibling();
- return null
- }
- validateNonEmptyPattern = function validateNonEmptyPattern(elementdef, walker, element, data) {
- var name = elementdef.name, err = null;
- if(name === "text") {
- err = validateText(elementdef, walker, element)
- }else {
- if(name === "data") {
- err = null
- }else {
- if(name === "value") {
- if(data !== elementdef.text) {
- err = [new RelaxNGParseError("Wrong value, should be '" + elementdef.text + "', not '" + data + "'", element)]
- }
- }else {
- if(name === "list") {
- err = null
- }else {
- if(name === "attribute") {
- err = validateAttribute(elementdef, walker, element)
- }else {
- if(name === "element") {
- err = validateElement(elementdef, walker)
- }else {
- if(name === "oneOrMore") {
- err = validateOneOrMore(elementdef, walker, element)
- }else {
- if(name === "choice") {
- err = validateChoice(elementdef, walker, element, data)
- }else {
- if(name === "group") {
- err = validateGroup(elementdef, walker, element)
- }else {
- if(name === "interleave") {
- err = validateInterleave(elementdef, walker, element)
- }else {
- throw name + " not allowed in nonEmptyPattern.";
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return err
- };
- this.validate = function validate(walker, callback) {
- walker.currentNode = walker.root;
- var errors = validatePattern(start.e[0], walker, (walker.root));
- callback(errors)
- };
- this.init = function init(start1, nsmap1) {
- start = start1;
- nsmap = nsmap1
- }
-};
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("gui.Avatar");
-runtime.loadClass("ops.OdtCursor");
-gui.Caret = function Caret(cursor, avatarInitiallyVisible, blinkOnRangeSelect) {
- var MIN_CARET_HEIGHT_PX = 8, DEFAULT_CARET_TOP = "5%", DEFAULT_CARET_HEIGHT = "1em", span, avatar, cursorNode, isShown = true, shouldBlink = false, blinking = false, blinkTimeout, domUtils = new core.DomUtils;
- function blink(reset) {
- if(!shouldBlink || !cursorNode.parentNode) {
- return
- }
- if(!blinking || reset) {
- if(reset && blinkTimeout !== undefined) {
- runtime.clearTimeout(blinkTimeout)
- }
- blinking = true;
- span.style.opacity = reset || span.style.opacity === "0" ? "1" : "0";
- blinkTimeout = runtime.setTimeout(function() {
- blinking = false;
- blink(false)
- }, 500)
- }
- }
- function getCaretClientRectWithMargin(caretElement, margin) {
- var caretRect = caretElement.getBoundingClientRect();
- return{left:caretRect.left - margin.left, top:caretRect.top - margin.top, right:caretRect.right + margin.right, bottom:caretRect.bottom + margin.bottom}
- }
- function length(node) {
- return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
- }
- function verticalOverlap(cursorNode, rangeRect) {
- var cursorRect = cursorNode.getBoundingClientRect(), intersectTop = 0, intersectBottom = 0;
- if(cursorRect && rangeRect) {
- intersectTop = Math.max(cursorRect.top, rangeRect.top);
- intersectBottom = Math.min(cursorRect.bottom, rangeRect.bottom)
- }
- return intersectBottom - intersectTop
- }
- function getSelectionRect() {
- var range = cursor.getSelectedRange().cloneRange(), node = cursor.getNode(), nextRectangle, selectionRectangle = null, nodeLength;
- if(node.previousSibling) {
- nodeLength = length(node.previousSibling);
- range.setStart(node.previousSibling, nodeLength > 0 ? nodeLength - 1 : 0);
- range.setEnd(node.previousSibling, nodeLength);
- nextRectangle = range.getBoundingClientRect();
- if(nextRectangle && nextRectangle.height) {
- selectionRectangle = nextRectangle
- }
- }
- if(node.nextSibling) {
- range.setStart(node.nextSibling, 0);
- range.setEnd(node.nextSibling, length(node.nextSibling) > 0 ? 1 : 0);
- nextRectangle = range.getBoundingClientRect();
- if(nextRectangle && nextRectangle.height) {
- if(!selectionRectangle || verticalOverlap(node, nextRectangle) > verticalOverlap(node, selectionRectangle)) {
- selectionRectangle = nextRectangle
- }
- }
- }
- return selectionRectangle
- }
- function handleUpdate() {
- var selectionRect = getSelectionRect(), zoomLevel = cursor.getOdtDocument().getOdfCanvas().getZoomLevel(), caretRect;
- if(isShown && cursor.getSelectionType() === ops.OdtCursor.RangeSelection) {
- span.style.visibility = "visible"
- }else {
- span.style.visibility = "hidden"
- }
- if(selectionRect) {
- span.style.top = "0";
- caretRect = domUtils.getBoundingClientRect(span);
- if(selectionRect.height < MIN_CARET_HEIGHT_PX) {
- selectionRect = {top:selectionRect.top - (MIN_CARET_HEIGHT_PX - selectionRect.height) / 2, height:MIN_CARET_HEIGHT_PX}
- }
- span.style.height = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.height, zoomLevel) + "px";
- span.style.top = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.top - caretRect.top, zoomLevel) + "px"
- }else {
- span.style.height = DEFAULT_CARET_HEIGHT;
- span.style.top = DEFAULT_CARET_TOP
- }
- }
- this.handleUpdate = handleUpdate;
- this.refreshCursorBlinking = function() {
- if(blinkOnRangeSelect || cursor.getSelectedRange().collapsed) {
- shouldBlink = true;
- blink(true)
- }else {
- shouldBlink = false;
- span.style.opacity = "0"
- }
- };
- this.setFocus = function() {
- shouldBlink = true;
- avatar.markAsFocussed(true);
- blink(true)
- };
- this.removeFocus = function() {
- shouldBlink = false;
- avatar.markAsFocussed(false);
- span.style.opacity = "1"
- };
- this.show = function() {
- isShown = true;
- handleUpdate();
- avatar.markAsFocussed(true)
- };
- this.hide = function() {
- isShown = false;
- handleUpdate();
- avatar.markAsFocussed(false)
- };
- this.setAvatarImageUrl = function(url) {
- avatar.setImageUrl(url)
- };
- this.setColor = function(newColor) {
- span.style.borderColor = newColor;
- avatar.setColor(newColor)
- };
- this.getCursor = function() {
- return cursor
- };
- this.getFocusElement = function() {
- return span
- };
- this.toggleHandleVisibility = function() {
- if(avatar.isVisible()) {
- avatar.hide()
- }else {
- avatar.show()
- }
- };
- this.showHandle = function() {
- avatar.show()
- };
- this.hideHandle = function() {
- avatar.hide()
- };
- this.ensureVisible = function() {
- var canvasElement = cursor.getOdtDocument().getOdfCanvas().getElement(), canvasContainerElement = canvasElement.parentNode, caretRect, canvasContainerRect, horizontalMargin = canvasContainerElement.offsetWidth - canvasContainerElement.clientWidth + 5, verticalMargin = canvasContainerElement.offsetHeight - canvasContainerElement.clientHeight + 5;
- caretRect = getCaretClientRectWithMargin(span, {top:verticalMargin, left:horizontalMargin, bottom:verticalMargin, right:horizontalMargin});
- canvasContainerRect = canvasContainerElement.getBoundingClientRect();
- if(caretRect.top < canvasContainerRect.top) {
- canvasContainerElement.scrollTop -= canvasContainerRect.top - caretRect.top
- }else {
- if(caretRect.bottom > canvasContainerRect.bottom) {
- canvasContainerElement.scrollTop += caretRect.bottom - canvasContainerRect.bottom
- }
- }
- if(caretRect.left < canvasContainerRect.left) {
- canvasContainerElement.scrollLeft -= canvasContainerRect.left - caretRect.left
- }else {
- if(caretRect.right > canvasContainerRect.right) {
- canvasContainerElement.scrollLeft += caretRect.right - canvasContainerRect.right
- }
- }
- handleUpdate()
- };
- this.destroy = function(callback) {
- avatar.destroy(function(err) {
- if(err) {
- callback(err)
- }else {
- cursorNode.removeChild(span);
- callback()
- }
- })
- };
- function init() {
- var dom = cursor.getOdtDocument().getDOM(), htmlns = dom.documentElement.namespaceURI;
- span = (dom.createElementNS(htmlns, "span"));
- span.style.top = DEFAULT_CARET_TOP;
- cursorNode = cursor.getNode();
- cursorNode.appendChild(span);
- avatar = new gui.Avatar(cursorNode, avatarInitiallyVisible);
- handleUpdate()
- }
- init()
-};
-gui.EventManager = function EventManager(odtDocument) {
- var window = (runtime.getWindow()), bindToDirectHandler = {"beforecut":true, "beforepaste":true}, bindToWindow, eventTrap;
- function getCanvasElement() {
- return odtDocument.getOdfCanvas().getElement()
- }
- function EventDelegate() {
- var self = this, recentEvents = [];
- this.handlers = [];
- this.isSubscribed = false;
- this.handleEvent = function(e) {
- if(recentEvents.indexOf(e) === -1) {
- recentEvents.push(e);
- self.handlers.forEach(function(handler) {
- handler(e)
- });
- runtime.setTimeout(function() {
- recentEvents.splice(recentEvents.indexOf(e), 1)
- }, 0)
- }
- }
- }
- function WindowScrollState(window) {
- var x = window.scrollX, y = window.scrollY;
- this.restore = function() {
- if(window.scrollX !== x || window.scrollY !== y) {
- window.scrollTo(x, y)
- }
- }
- }
- function ElementScrollState(element) {
- var top = element.scrollTop, left = element.scrollLeft;
- this.restore = function() {
- if(element.scrollTop !== top || element.scrollLeft !== left) {
- element.scrollTop = top;
- element.scrollLeft = left
- }
- }
- }
- function listenEvent(eventTarget, eventType, eventHandler) {
- var onVariant = "on" + eventType, bound = false;
- if(eventTarget.attachEvent) {
- bound = eventTarget.attachEvent(onVariant, eventHandler)
- }
- if(!bound && eventTarget.addEventListener) {
- eventTarget.addEventListener(eventType, eventHandler, false);
- bound = true
- }
- if((!bound || bindToDirectHandler[eventType]) && eventTarget.hasOwnProperty(onVariant)) {
- eventTarget[onVariant] = eventHandler
- }
- }
- function removeEvent(eventTarget, eventType, eventHandler) {
- var onVariant = "on" + eventType;
- if(eventTarget.detachEvent) {
- eventTarget.detachEvent(onVariant, eventHandler)
- }
- if(eventTarget.removeEventListener) {
- eventTarget.removeEventListener(eventType, eventHandler, false)
- }
- if(eventTarget[onVariant] === eventHandler) {
- eventTarget[onVariant] = null
- }
- }
- this.subscribe = function(eventName, handler) {
- var delegate = bindToWindow[eventName], canvasElement = getCanvasElement();
- if(delegate) {
- delegate.handlers.push(handler);
- if(!delegate.isSubscribed) {
- delegate.isSubscribed = true;
- listenEvent((window), eventName, delegate.handleEvent);
- listenEvent(canvasElement, eventName, delegate.handleEvent);
- listenEvent(eventTrap, eventName, delegate.handleEvent)
- }
- }else {
- listenEvent(canvasElement, eventName, handler)
- }
- };
- this.unsubscribe = function(eventName, handler) {
- var delegate = bindToWindow[eventName], handlerIndex = delegate && delegate.handlers.indexOf(handler), canvasElement = getCanvasElement();
- if(delegate) {
- if(handlerIndex !== -1) {
- delegate.handlers.splice(handlerIndex, 1)
- }
- }else {
- removeEvent(canvasElement, eventName, handler)
- }
- };
- function hasFocus() {
- return odtDocument.getDOM().activeElement === getCanvasElement()
- }
- function findScrollableParent(element) {
- while(element && (!element.scrollTop && !element.scrollLeft)) {
- element = (element.parentNode)
- }
- if(element) {
- return new ElementScrollState(element)
- }
- return new WindowScrollState(window)
- }
- this.focus = function() {
- var scrollParent, canvasElement = getCanvasElement(), selection = window.getSelection();
- if(!hasFocus()) {
- scrollParent = findScrollableParent(canvasElement);
- canvasElement.focus();
- if(scrollParent) {
- scrollParent.restore()
- }
- }
- if(selection && selection.extend) {
- if(eventTrap.parentNode !== canvasElement) {
- canvasElement.appendChild(eventTrap)
- }
- selection.collapse(eventTrap.firstChild, 0);
- selection.extend(eventTrap, eventTrap.childNodes.length)
- }
- };
- function init() {
- var canvasElement = getCanvasElement(), doc = canvasElement.ownerDocument;
- runtime.assert(Boolean(window), "EventManager requires a window object to operate correctly");
- bindToWindow = {"mousedown":new EventDelegate, "mouseup":new EventDelegate, "focus":new EventDelegate};
- eventTrap = doc.createElement("div");
- eventTrap.id = "eventTrap";
- eventTrap.setAttribute("contenteditable", "true");
- eventTrap.style.position = "absolute";
- eventTrap.style.left = "-10000px";
- eventTrap.appendChild(doc.createTextNode("dummy content"));
- canvasElement.appendChild(eventTrap)
- }
- init()
-};
-runtime.loadClass("gui.SelectionMover");
-gui.ShadowCursor = function ShadowCursor(odtDocument) {
- var selectedRange = (odtDocument.getDOM().createRange()), forwardSelection = true;
- this.removeFromOdtDocument = function() {
- };
- this.getMemberId = function() {
- return gui.ShadowCursor.ShadowCursorMemberId
- };
- this.getSelectedRange = function() {
- return selectedRange
- };
- this.setSelectedRange = function(range, isForwardSelection) {
- selectedRange = range;
- forwardSelection = isForwardSelection !== false
- };
- this.hasForwardSelection = function() {
- return forwardSelection
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.getSelectionType = function() {
- return ops.OdtCursor.RangeSelection
- };
- function init() {
- selectedRange.setStart(odtDocument.getRootNode(), 0)
- }
- init()
-};
-gui.ShadowCursor.ShadowCursorMemberId = "";
-(function() {
- return gui.ShadowCursor
-})();
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-gui.UndoManager = function UndoManager() {
-};
-gui.UndoManager.prototype.subscribe = function(signal, callback) {
-};
-gui.UndoManager.prototype.unsubscribe = function(signal, callback) {
-};
-gui.UndoManager.prototype.setOdtDocument = function(newDocument) {
-};
-gui.UndoManager.prototype.saveInitialState = function() {
-};
-gui.UndoManager.prototype.resetInitialState = function() {
-};
-gui.UndoManager.prototype.setPlaybackFunction = function(playback_func) {
-};
-gui.UndoManager.prototype.hasUndoStates = function() {
-};
-gui.UndoManager.prototype.hasRedoStates = function() {
-};
-gui.UndoManager.prototype.moveForward = function(states) {
-};
-gui.UndoManager.prototype.moveBackward = function(states) {
-};
-gui.UndoManager.prototype.onOperationExecuted = function(op) {
-};
-gui.UndoManager.signalUndoStackChanged = "undoStackChanged";
-gui.UndoManager.signalUndoStateCreated = "undoStateCreated";
-gui.UndoManager.signalUndoStateModified = "undoStateModified";
-(function() {
- return gui.UndoManager
-})();
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-gui.UndoStateRules = function UndoStateRules() {
- function getOpType(op) {
- return op.spec().optype
- }
- this.getOpType = getOpType;
- function getOpPosition(op) {
- return op.spec().position
- }
- function isEditOperation(op) {
- return op.isEdit
- }
- this.isEditOperation = isEditOperation;
- function canAggregateOperation(optype) {
- switch(optype) {
- case "RemoveText":
- ;
- case "InsertText":
- return true;
- default:
- return false
- }
- }
- function isSameDirectionOfTravel(recentEditOps, thisOp) {
- var existing1 = getOpPosition(recentEditOps[recentEditOps.length - 2]), existing2 = getOpPosition(recentEditOps[recentEditOps.length - 1]), thisPos = getOpPosition(thisOp), direction = existing2 - existing1;
- return existing2 === thisPos - direction
- }
- function isContinuousOperation(recentEditOps, thisOp) {
- var optype = getOpType(thisOp);
- if(canAggregateOperation(optype) && optype === getOpType(recentEditOps[0])) {
- if(recentEditOps.length === 1) {
- return true
- }
- if(isSameDirectionOfTravel(recentEditOps, thisOp)) {
- return true
- }
- }
- return false
- }
- function isPartOfOperationSet(operation, lastOperations) {
- if(isEditOperation(operation)) {
- if(lastOperations.length === 0) {
- return true
- }
- return isEditOperation(lastOperations[lastOperations.length - 1]) && isContinuousOperation(lastOperations.filter(isEditOperation), operation)
- }
- return true
- }
- this.isPartOfOperationSet = isPartOfOperationSet
-};
-/*
-
- Copyright (C) 2012 KO GmbH <aditya.bhatt@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-ops.EditInfo = function EditInfo(container, odtDocument) {
- var editInfoNode, editHistory = {};
- function sortEdits() {
- var arr = [], memberid;
- for(memberid in editHistory) {
- if(editHistory.hasOwnProperty(memberid)) {
- arr.push({"memberid":memberid, "time":editHistory[memberid].time})
- }
- }
- arr.sort(function(a, b) {
- return a.time - b.time
- });
- return arr
- }
- this.getNode = function() {
- return editInfoNode
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.getEdits = function() {
- return editHistory
- };
- this.getSortedEdits = function() {
- return sortEdits()
- };
- this.addEdit = function(memberid, timestamp) {
- editHistory[memberid] = {time:timestamp}
- };
- this.clearEdits = function() {
- editHistory = {}
- };
- this.destroy = function(callback) {
- if(container.parentNode) {
- container.removeChild(editInfoNode)
- }
- callback()
- };
- function init() {
- var editInfons = "urn:webodf:names:editinfo", dom = odtDocument.getDOM();
- editInfoNode = dom.createElementNS(editInfons, "editinfo");
- container.insertBefore(editInfoNode, container.firstChild)
- }
- init()
-};
-/*
-
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("core.DomUtils");
ops.OpAddAnnotation = function OpAddAnnotation() {
var memberid, timestamp, position, length, name, doc;
this.init = function(data) {
@@ -12902,9 +10128,10 @@ ops.OpAddAnnotation = function OpAddAnnotation() {
name = data.name
};
this.isEdit = true;
+ this.group = undefined;
function createAnnotationNode(odtDocument, date) {
var annotationNode, creatorNode, dateNode, listNode, listItemNode, paragraphNode;
- annotationNode = doc.createElementNS(odf.Namespaces.officens, "office:annotation");
+ annotationNode = (doc.createElementNS(odf.Namespaces.officens, "office:annotation"));
annotationNode.setAttributeNS(odf.Namespaces.officens, "office:name", name);
creatorNode = doc.createElementNS(odf.Namespaces.dcns, "dc:creator");
creatorNode.setAttributeNS("urn:webodf:names:editinfo", "editinfo:memberid", memberid);
@@ -12941,28 +10168,23 @@ ops.OpAddAnnotation = function OpAddAnnotation() {
}
}
}
- this.execute = function(odtDocument) {
- var annotation = {}, cursor = odtDocument.getCursor(memberid), selectedRange, paragraphElement, domUtils = new core.DomUtils;
- doc = odtDocument.getDOM();
- annotation.node = createAnnotationNode(odtDocument, new Date(timestamp));
- if(!annotation.node) {
- return false
- }
+ this.execute = function(document) {
+ var odtDocument = (document), annotation, annotationEnd, cursor = odtDocument.getCursor(memberid), selectedRange, paragraphElement, domUtils = new core.DomUtils;
+ doc = odtDocument.getDOMDocument();
+ annotation = createAnnotationNode(odtDocument, new Date(timestamp));
if(length) {
- annotation.end = createAnnotationEnd();
- if(!annotation.end) {
- return false
- }
- insertNodeAtPosition(odtDocument, annotation.end, position + length)
+ annotationEnd = createAnnotationEnd();
+ annotation.annotationEndElement = annotationEnd;
+ insertNodeAtPosition(odtDocument, annotationEnd, position + length)
}
- insertNodeAtPosition(odtDocument, annotation.node, position);
+ insertNodeAtPosition(odtDocument, annotation, position);
odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:length});
if(cursor) {
selectedRange = doc.createRange();
- paragraphElement = domUtils.getElementsByTagNameNS(annotation.node, odf.Namespaces.textns, "p")[0];
+ paragraphElement = domUtils.getElementsByTagNameNS(annotation, odf.Namespaces.textns, "p")[0];
selectedRange.selectNodeContents(paragraphElement);
- cursor.setSelectedRange(selectedRange);
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
+ cursor.setSelectedRange(selectedRange, false);
+ odtDocument.emit(ops.Document.signalCursorMoved, cursor)
}
odtDocument.getOdfCanvas().addAnnotation(annotation);
odtDocument.fixCursorPositions();
@@ -12972,6 +10194,8 @@ ops.OpAddAnnotation = function OpAddAnnotation() {
return{optype:"AddAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length, name:name}
}
};
+ops.OpAddAnnotation.Spec;
+ops.OpAddAnnotation.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13016,20 +10240,23 @@ ops.OpAddCursor = function OpAddCursor() {
timestamp = data.timestamp
};
this.isEdit = false;
- this.execute = function(odtDocument) {
- var cursor = odtDocument.getCursor(memberid);
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), cursor = odtDocument.getCursor(memberid);
if(cursor) {
return false
}
cursor = new ops.OdtCursor(memberid, odtDocument);
odtDocument.addCursor(cursor);
- odtDocument.emit(ops.OdtDocument.signalCursorAdded, cursor);
+ odtDocument.emit(ops.Document.signalCursorAdded, cursor);
return true
};
this.spec = function() {
return{optype:"AddCursor", memberid:memberid, timestamp:timestamp}
}
};
+ops.OpAddCursor.Spec;
+ops.OpAddCursor.InitSpec;
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -13054,7 +10281,6 @@ ops.OpAddCursor = function OpAddCursor() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.Member");
ops.OpAddMember = function OpAddMember() {
var memberid, timestamp, setProperties;
this.init = function(data) {
@@ -13063,19 +10289,23 @@ ops.OpAddMember = function OpAddMember() {
setProperties = data.setProperties
};
this.isEdit = false;
- this.execute = function(odtDocument) {
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), member;
if(odtDocument.getMember(memberid)) {
return false
}
- var member = new ops.Member(memberid, setProperties);
+ member = new ops.Member(memberid, setProperties);
odtDocument.addMember(member);
- odtDocument.emit(ops.OdtDocument.signalMemberAdded, member);
+ odtDocument.emit(ops.Document.signalMemberAdded, member);
return true
};
this.spec = function() {
return{optype:"AddMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties}
}
};
+ops.OpAddMember.Spec;
+ops.OpAddMember.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13113,7 +10343,6 @@ ops.OpAddMember = function OpAddMember() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");
ops.OpAddStyle = function OpAddStyle() {
var memberid, timestamp, styleName, styleFamily, isAutomaticStyle, setProperties, stylens = odf.Namespaces.stylens;
this.init = function(data) {
@@ -13125,8 +10354,9 @@ ops.OpAddStyle = function OpAddStyle() {
setProperties = data.setProperties
};
this.isEdit = true;
- this.execute = function(odtDocument) {
- var odfContainer = odtDocument.getOdfCanvas().odfContainer(), formatting = odtDocument.getFormatting(), dom = odtDocument.getDOM(), styleNode = dom.createElementNS(stylens, "style:style");
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), odfContainer = odtDocument.getOdfCanvas().odfContainer(), formatting = odtDocument.getFormatting(), dom = odtDocument.getDOMDocument(), styleNode = dom.createElementNS(stylens, "style:style");
if(!styleNode) {
return false
}
@@ -13151,6 +10381,245 @@ ops.OpAddStyle = function OpAddStyle() {
}
};
ops.OpAddStyle.Spec;
+ops.OpAddStyle.InitSpec;
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+odf.ObjectNameGenerator = function ObjectNameGenerator(odfContainer, memberId) {
+ var stylens = odf.Namespaces.stylens, drawns = odf.Namespaces.drawns, xlinkns = odf.Namespaces.xlinkns, domUtils = new core.DomUtils, utils = new core.Utils, memberIdHash = utils.hashString(memberId), styleNameGenerator = null, frameNameGenerator = null, imageNameGenerator = null, existingFrameNames = {}, existingImageNames = {};
+ function NameGenerator(prefix, findExistingNames) {
+ var reportedNames = {};
+ this.generateName = function() {
+ var existingNames = findExistingNames(), startIndex = 0, name;
+ do {
+ name = prefix + startIndex;
+ startIndex += 1
+ }while(reportedNames[name] || existingNames[name]);
+ reportedNames[name] = true;
+ return name
+ }
+ }
+ function getAllStyleNames() {
+ var styleElements = [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles], styleNames = {};
+ function getStyleNames(styleListElement) {
+ var e = styleListElement.firstElementChild;
+ while(e) {
+ if(e.namespaceURI === stylens && e.localName === "style") {
+ styleNames[e.getAttributeNS(stylens, "name")] = true
+ }
+ e = e.nextElementSibling
+ }
+ }
+ styleElements.forEach(getStyleNames);
+ return styleNames
+ }
+ this.generateStyleName = function() {
+ if(styleNameGenerator === null) {
+ styleNameGenerator = new NameGenerator("auto" + memberIdHash + "_", function() {
+ return getAllStyleNames()
+ })
+ }
+ return styleNameGenerator.generateName()
+ };
+ this.generateFrameName = function() {
+ if(frameNameGenerator === null) {
+ var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "frame");
+ nodes.forEach(function(frame) {
+ existingFrameNames[frame.getAttributeNS(drawns, "name")] = true
+ });
+ frameNameGenerator = new NameGenerator("fr" + memberIdHash + "_", function() {
+ return existingFrameNames
+ })
+ }
+ return frameNameGenerator.generateName()
+ };
+ this.generateImageName = function() {
+ if(imageNameGenerator === null) {
+ var nodes = domUtils.getElementsByTagNameNS(odfContainer.rootElement.body, drawns, "image");
+ nodes.forEach(function(image) {
+ var path = image.getAttributeNS(xlinkns, "href");
+ path = path.substring("Pictures/".length, path.lastIndexOf("."));
+ existingImageNames[path] = true
+ });
+ imageNameGenerator = new NameGenerator("img" + memberIdHash + "_", function() {
+ return existingImageNames
+ })
+ }
+ return imageNameGenerator.generateName()
+ }
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+odf.TextStyleApplicator = function TextStyleApplicator(objectNameGenerator, formatting, automaticStyles) {
+ var domUtils = new core.DomUtils, textns = odf.Namespaces.textns, stylens = odf.Namespaces.stylens, textProperties = "style:text-properties", webodfns = "urn:webodf:names:scope";
+ function StyleLookup(info) {
+ var cachedAppliedStyles = {};
+ function compare(expected, actual) {
+ if(typeof expected === "object" && typeof actual === "object") {
+ return Object.keys(expected).every(function(key) {
+ return compare(expected[key], actual[key])
+ })
+ }
+ return expected === actual
+ }
+ this.isStyleApplied = function(textNode) {
+ var appliedStyle = formatting.getAppliedStylesForElement(textNode, cachedAppliedStyles);
+ return compare(info, appliedStyle)
+ }
+ }
+ function StyleManager(info) {
+ var createdStyles = {};
+ function createDirectFormat(existingStyleName, document) {
+ var derivedStyleInfo, derivedStyleNode;
+ derivedStyleInfo = existingStyleName ? formatting.createDerivedStyleObject(existingStyleName, "text", info) : info;
+ derivedStyleNode = document.createElementNS(stylens, "style:style");
+ formatting.updateStyle(derivedStyleNode, derivedStyleInfo);
+ derivedStyleNode.setAttributeNS(stylens, "style:name", objectNameGenerator.generateStyleName());
+ derivedStyleNode.setAttributeNS(stylens, "style:family", "text");
+ derivedStyleNode.setAttributeNS(webodfns, "scope", "document-content");
+ automaticStyles.appendChild(derivedStyleNode);
+ return derivedStyleNode
+ }
+ function getDirectStyle(existingStyleName, document) {
+ existingStyleName = existingStyleName || "";
+ if(!createdStyles.hasOwnProperty(existingStyleName)) {
+ createdStyles[existingStyleName] = createDirectFormat(existingStyleName, document)
+ }
+ return createdStyles[existingStyleName].getAttributeNS(stylens, "name")
+ }
+ this.applyStyleToContainer = function(container) {
+ var name = getDirectStyle(container.getAttributeNS(textns, "style-name"), container.ownerDocument);
+ container.setAttributeNS(textns, "text:style-name", name)
+ }
+ }
+ function isTextSpan(node) {
+ return node.localName === "span" && node.namespaceURI === textns
+ }
+ function moveToNewSpan(startNode, limits) {
+ var document = startNode.ownerDocument, originalContainer = (startNode.parentNode), styledContainer, trailingContainer, moveTrailing, node, nextNode, loopGuard = new core.LoopWatchDog(1E4), styledNodes = [];
+ if(!isTextSpan(originalContainer)) {
+ styledContainer = document.createElementNS(textns, "text:span");
+ originalContainer.insertBefore(styledContainer, startNode);
+ moveTrailing = false
+ }else {
+ if(startNode.previousSibling && !domUtils.rangeContainsNode(limits, (originalContainer.firstChild))) {
+ styledContainer = originalContainer.cloneNode(false);
+ originalContainer.parentNode.insertBefore(styledContainer, originalContainer.nextSibling);
+ moveTrailing = true
+ }else {
+ styledContainer = originalContainer;
+ moveTrailing = true
+ }
+ }
+ styledNodes.push(startNode);
+ node = startNode.nextSibling;
+ while(node && domUtils.rangeContainsNode(limits, node)) {
+ loopGuard.check();
+ styledNodes.push(node);
+ node = node.nextSibling
+ }
+ styledNodes.forEach(function(n) {
+ if(n.parentNode !== styledContainer) {
+ styledContainer.appendChild(n)
+ }
+ });
+ if(node && moveTrailing) {
+ trailingContainer = styledContainer.cloneNode(false);
+ styledContainer.parentNode.insertBefore(trailingContainer, styledContainer.nextSibling);
+ while(node) {
+ loopGuard.check();
+ nextNode = node.nextSibling;
+ trailingContainer.appendChild(node);
+ node = nextNode
+ }
+ }
+ return(styledContainer)
+ }
+ this.applyStyle = function(textNodes, limits, info) {
+ var textPropsOnly = {}, isStyled, container, styleCache, styleLookup;
+ runtime.assert(info && info.hasOwnProperty(textProperties), "applyStyle without any text properties");
+ textPropsOnly[textProperties] = info[textProperties];
+ styleCache = new StyleManager(textPropsOnly);
+ styleLookup = new StyleLookup(textPropsOnly);
+ function apply(n) {
+ isStyled = styleLookup.isStyleApplied(n);
+ if(isStyled === false) {
+ container = moveToNewSpan(n, limits);
+ styleCache.applyStyleToContainer(container)
+ }
+ }
+ textNodes.forEach(apply)
+ }
+};
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13188,9 +10657,6 @@ ops.OpAddStyle.Spec;
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("odf.TextStyleApplicator");
ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
var memberid, timestamp, position, length, setProperties, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils;
this.init = function(data) {
@@ -13201,6 +10667,7 @@ ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
setProperties = data.setProperties
};
this.isEdit = true;
+ this.group = undefined;
function applyStyle(odtDocument, range, info) {
var odfCanvas = odtDocument.getOdfCanvas(), odfContainer = odfCanvas.odfContainer(), nextTextNodes = domUtils.splitBoundaries(range), textNodes = odfUtils.getTextNodes(range, false), limits, textStyles;
limits = {startContainer:range.startContainer, startOffset:range.startOffset, endContainer:range.endContainer, endOffset:range.endOffset};
@@ -13208,8 +10675,8 @@ ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
textStyles.applyStyle(textNodes, limits, info);
nextTextNodes.forEach(domUtils.normalizeTextNodes)
}
- this.execute = function(odtDocument) {
- var range = odtDocument.convertCursorToDomRange(position, length), impactedParagraphs = odfUtils.getImpactedParagraphs(range);
+ this.execute = function(document) {
+ var odtDocument = (document), range = odtDocument.convertCursorToDomRange(position, length), impactedParagraphs = odfUtils.getParagraphElements(range);
applyStyle(odtDocument, range, setProperties);
range.detach();
odtDocument.getOdfCanvas().refreshCSS();
@@ -13225,6 +10692,100 @@ ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
}
};
ops.OpApplyDirectStyling.Spec;
+ops.OpApplyDirectStyling.InitSpec;
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OpApplyHyperlink = function OpApplyHyperlink() {
+ var memberid, timestamp, position, length, hyperlink, domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils;
+ this.init = function(data) {
+ memberid = data.memberid;
+ timestamp = data.timestamp;
+ position = data.position;
+ length = data.length;
+ hyperlink = data.hyperlink
+ };
+ this.isEdit = true;
+ this.group = undefined;
+ function createHyperlink(document, hyperlink) {
+ var node = document.createElementNS(odf.Namespaces.textns, "text:a");
+ node.setAttributeNS(odf.Namespaces.xlinkns, "xlink:type", "simple");
+ node.setAttributeNS(odf.Namespaces.xlinkns, "xlink:href", hyperlink);
+ return node
+ }
+ function isPartOfLink(node) {
+ while(node) {
+ if(odfUtils.isHyperlink(node)) {
+ return true
+ }
+ node = node.parentNode
+ }
+ return false
+ }
+ this.execute = function(document) {
+ var odtDocument = (document), ownerDocument = odtDocument.getDOMDocument(), range = odtDocument.convertCursorToDomRange(position, length), boundaryNodes = domUtils.splitBoundaries(range), modifiedParagraphs = [], textNodes = odfUtils.getTextNodes(range, false);
+ if(textNodes.length === 0) {
+ return false
+ }
+ textNodes.forEach(function(node) {
+ var linkNode, paragraph = odfUtils.getParagraphElement(node);
+ runtime.assert(isPartOfLink(node) === false, "The given range should not contain any link.");
+ linkNode = createHyperlink(ownerDocument, hyperlink);
+ node.parentNode.insertBefore(linkNode, node);
+ linkNode.appendChild(node);
+ if(modifiedParagraphs.indexOf(paragraph) === -1) {
+ modifiedParagraphs.push(paragraph)
+ }
+ });
+ boundaryNodes.forEach(domUtils.normalizeTextNodes);
+ range.detach();
+ odtDocument.getOdfCanvas().refreshSize();
+ odtDocument.getOdfCanvas().rerenderAnnotations();
+ modifiedParagraphs.forEach(function(paragraph) {
+ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraph, memberId:memberid, timeStamp:timestamp})
+ });
+ return true
+ };
+ this.spec = function() {
+ return{optype:"ApplyHyperlink", memberid:memberid, timestamp:timestamp, position:position, length:length, hyperlink:hyperlink}
+ }
+};
+ops.OpApplyHyperlink.Spec;
+ops.OpApplyHyperlink.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13275,6 +10836,7 @@ ops.OpInsertImage = function OpInsertImage() {
frameName = data.frameName
};
this.isEdit = true;
+ this.group = undefined;
function createFrameElement(document) {
var imageNode = document.createElementNS(drawns, "draw:image"), frameNode = document.createElementNS(drawns, "draw:frame");
imageNode.setAttributeNS(xlinkns, "xlink:href", filename);
@@ -13289,15 +10851,15 @@ ops.OpInsertImage = function OpInsertImage() {
frameNode.appendChild(imageNode);
return frameNode
}
- this.execute = function(odtDocument) {
- var odfCanvas = odtDocument.getOdfCanvas(), domPosition = odtDocument.getTextNodeAtStep(position, memberid), textNode, refNode, paragraphElement, frameElement;
+ this.execute = function(document) {
+ var odtDocument = (document), odfCanvas = odtDocument.getOdfCanvas(), domPosition = odtDocument.getTextNodeAtStep(position, memberid), textNode, refNode, paragraphElement, frameElement;
if(!domPosition) {
return false
}
textNode = domPosition.textNode;
paragraphElement = odtDocument.getParagraphElement(textNode);
refNode = domPosition.offset !== textNode.length ? textNode.splitText(domPosition.offset) : textNode.nextSibling;
- frameElement = createFrameElement(odtDocument.getDOM());
+ frameElement = createFrameElement(odtDocument.getDOMDocument());
textNode.parentNode.insertBefore(frameElement, refNode);
odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:1});
if(textNode.length === 0) {
@@ -13313,6 +10875,8 @@ ops.OpInsertImage = function OpInsertImage() {
return{optype:"InsertImage", memberid:memberid, timestamp:timestamp, filename:filename, position:position, frameWidth:frameWidth, frameHeight:frameHeight, frameStyleName:frameStyleName, frameName:frameName}
}
};
+ops.OpInsertImage.Spec;
+ops.OpInsertImage.InitSpec;
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -13364,6 +10928,7 @@ ops.OpInsertTable = function OpInsertTable() {
tableCellStyleMatrix = data.tableCellStyleMatrix
};
this.isEdit = true;
+ this.group = undefined;
function getCellStyleName(row, column) {
var rowStyles;
if(tableCellStyleMatrix.length === 1) {
@@ -13429,10 +10994,10 @@ ops.OpInsertTable = function OpInsertTable() {
}
return tableNode
}
- this.execute = function(odtDocument) {
- var domPosition = odtDocument.getTextNodeAtStep(position), rootNode = odtDocument.getRootNode(), previousSibling, tableNode;
+ this.execute = function(document) {
+ var odtDocument = (document), domPosition = odtDocument.getTextNodeAtStep(position), rootNode = odtDocument.getRootNode(), previousSibling, tableNode;
if(domPosition) {
- tableNode = createTableNode(odtDocument.getDOM());
+ tableNode = createTableNode(odtDocument.getDOMDocument());
previousSibling = odtDocument.getParagraphElement(domPosition.textNode);
rootNode.insertBefore(tableNode, previousSibling.nextSibling);
odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:initialColumns * initialRows + 1});
@@ -13447,6 +11012,8 @@ ops.OpInsertTable = function OpInsertTable() {
return{optype:"InsertTable", memberid:memberid, timestamp:timestamp, position:position, initialRows:initialRows, initialColumns:initialColumns, tableName:tableName, tableStyleName:tableStyleName, tableColumnStyleName:tableColumnStyleName, tableCellStyleMatrix:tableCellStyleMatrix}
}
};
+ops.OpInsertTable.Spec;
+ops.OpInsertTable.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13485,7 +11052,7 @@ ops.OpInsertTable = function OpInsertTable() {
@source: https://github.com/kogmbh/WebODF/
*/
ops.OpInsertText = function OpInsertText() {
- var space = " ", tab = "\t", memberid, timestamp, position, text, moveCursor;
+ var space = " ", tab = "\t", memberid, timestamp, position, moveCursor, text;
this.init = function(data) {
memberid = data.memberid;
timestamp = data.timestamp;
@@ -13494,6 +11061,7 @@ ops.OpInsertText = function OpInsertText() {
moveCursor = data.moveCursor === "true" || data.moveCursor === true
};
this.isEdit = true;
+ this.group = undefined;
function triggerLayoutInWebkit(textNode) {
var parent = textNode.parentNode, next = textNode.nextSibling;
parent.removeChild(textNode);
@@ -13502,8 +11070,8 @@ ops.OpInsertText = function OpInsertText() {
function requiresSpaceElement(text, index) {
return text[index] === space && (index === 0 || (index === text.length - 1 || text[index - 1] === space))
}
- this.execute = function(odtDocument) {
- var domPosition, previousNode, parentElement, nextNode = null, ownerDocument = odtDocument.getDOM(), paragraphElement, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", toInsertIndex = 0, spaceTag, spaceElement, cursor = odtDocument.getCursor(memberid), i;
+ this.execute = function(document) {
+ var odtDocument = (document), domPosition, previousNode, parentElement, nextNode = null, ownerDocument = odtDocument.getDOMDocument(), paragraphElement, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", toInsertIndex = 0, spaceTag, spaceElement, cursor = odtDocument.getCursor(memberid), i;
function insertTextNode(toInsertText) {
parentElement.insertBefore(ownerDocument.createTextNode(toInsertText), nextNode)
}
@@ -13512,7 +11080,7 @@ ops.OpInsertText = function OpInsertText() {
if(domPosition) {
previousNode = domPosition.textNode;
nextNode = previousNode.nextSibling;
- parentElement = previousNode.parentNode;
+ parentElement = (previousNode.parentNode);
paragraphElement = odtDocument.getParagraphElement(previousNode);
for(i = 0;i < text.length;i += 1) {
if(requiresSpaceElement(text, i) || text[i] === tab) {
@@ -13549,7 +11117,7 @@ ops.OpInsertText = function OpInsertText() {
odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:text.length});
if(cursor && moveCursor) {
odtDocument.moveCursor(memberid, position + text.length, 0);
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
+ odtDocument.emit(ops.Document.signalCursorMoved, cursor)
}
if(position > 0) {
if(position > 1) {
@@ -13572,6 +11140,7 @@ ops.OpInsertText = function OpInsertText() {
}
};
ops.OpInsertText.Spec;
+ops.OpInsertText.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13619,15 +11188,16 @@ ops.OpMoveCursor = function OpMoveCursor() {
selectionType = data.selectionType || ops.OdtCursor.RangeSelection
};
this.isEdit = false;
- this.execute = function(odtDocument) {
- var cursor = odtDocument.getCursor(memberid), selectedRange;
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), cursor = odtDocument.getCursor(memberid), selectedRange;
if(!cursor) {
return false
}
selectedRange = odtDocument.convertCursorToDomRange(position, length);
cursor.setSelectedRange(selectedRange, length >= 0);
cursor.setSelectionType(selectionType);
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor);
+ odtDocument.emit(ops.Document.signalCursorMoved, cursor);
return true
};
this.spec = function() {
@@ -13635,6 +11205,7 @@ ops.OpMoveCursor = function OpMoveCursor() {
}
};
ops.OpMoveCursor.Spec;
+ops.OpMoveCursor.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13672,8 +11243,6 @@ ops.OpMoveCursor.Spec;
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("core.DomUtils");
ops.OpRemoveAnnotation = function OpRemoveAnnotation() {
var memberid, timestamp, position, length, domUtils;
this.init = function(data) {
@@ -13684,26 +11253,23 @@ ops.OpRemoveAnnotation = function OpRemoveAnnotation() {
domUtils = new core.DomUtils
};
this.isEdit = true;
- this.execute = function(odtDocument) {
- var iterator = odtDocument.getIteratorAtPosition(position), container = iterator.container(), annotationName, annotationNode, annotationEnd, cursors;
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), iterator = odtDocument.getIteratorAtPosition(position), container = iterator.container(), annotationNode, annotationEnd;
while(!(container.namespaceURI === odf.Namespaces.officens && container.localName === "annotation")) {
container = container.parentNode
}
if(container === null) {
return false
}
- annotationNode = container;
- annotationName = annotationNode.getAttributeNS(odf.Namespaces.officens, "name");
- if(annotationName) {
- annotationEnd = domUtils.getElementsByTagNameNS(odtDocument.getRootNode(), odf.Namespaces.officens, "annotation-end").filter(function(element) {
- return annotationName === element.getAttributeNS(odf.Namespaces.officens, "name")
- })[0] || null
- }
+ annotationNode = (container);
+ annotationEnd = annotationNode.annotationEndElement;
odtDocument.getOdfCanvas().forgetAnnotations();
- cursors = domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "cursor");
- while(cursors.length) {
- annotationNode.parentNode.insertBefore(cursors.pop(), annotationNode)
+ function insert(node) {
+ (annotationNode).parentNode.insertBefore(node, annotationNode)
}
+ domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "cursor").forEach(insert);
+ domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "anchor").forEach(insert);
annotationNode.parentNode.removeChild(annotationNode);
if(annotationEnd) {
annotationEnd.parentNode.removeChild(annotationEnd)
@@ -13717,6 +11283,8 @@ ops.OpRemoveAnnotation = function OpRemoveAnnotation() {
return{optype:"RemoveAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length}
}
};
+ops.OpRemoveAnnotation.Spec;
+ops.OpRemoveAnnotation.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13762,7 +11330,9 @@ ops.OpRemoveBlob = function OpRemoveBlob() {
filename = data.filename
};
this.isEdit = true;
- this.execute = function(odtDocument) {
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document);
odtDocument.getOdfCanvas().odfContainer().removeBlob(filename);
return true
};
@@ -13770,6 +11340,8 @@ ops.OpRemoveBlob = function OpRemoveBlob() {
return{optype:"RemoveBlob", memberid:memberid, timestamp:timestamp, filename:filename}
}
};
+ops.OpRemoveBlob.Spec;
+ops.OpRemoveBlob.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13814,7 +11386,9 @@ ops.OpRemoveCursor = function OpRemoveCursor() {
timestamp = data.timestamp
};
this.isEdit = false;
- this.execute = function(odtDocument) {
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document);
if(!odtDocument.removeCursor(memberid)) {
return false
}
@@ -13825,6 +11399,70 @@ ops.OpRemoveCursor = function OpRemoveCursor() {
}
};
ops.OpRemoveCursor.Spec;
+ops.OpRemoveCursor.InitSpec;
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OpRemoveHyperlink = function OpRemoveHyperlink() {
+ var memberid, timestamp, position, length, domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils;
+ this.init = function(data) {
+ memberid = data.memberid;
+ timestamp = data.timestamp;
+ position = data.position;
+ length = data.length
+ };
+ this.isEdit = true;
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), range = odtDocument.convertCursorToDomRange(position, length), links = odfUtils.getHyperlinkElements(range), node;
+ runtime.assert(links.length === 1, "The given range should only contain a single link.");
+ node = domUtils.mergeIntoParent((links[0]));
+ range.detach();
+ odtDocument.getOdfCanvas().refreshSize();
+ odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:odfUtils.getParagraphElement(node), memberId:memberid, timeStamp:timestamp});
+ odtDocument.getOdfCanvas().rerenderAnnotations();
+ return true
+ };
+ this.spec = function() {
+ return{optype:"RemoveHyperlink", memberid:memberid, timestamp:timestamp, position:position, length:length}
+ }
+};
+ops.OpRemoveHyperlink.Spec;
+ops.OpRemoveHyperlink.InitSpec;
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -13849,7 +11487,6 @@ ops.OpRemoveCursor.Spec;
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.Member");
ops.OpRemoveMember = function OpRemoveMember() {
var memberid, timestamp;
this.init = function(data) {
@@ -13857,18 +11494,22 @@ ops.OpRemoveMember = function OpRemoveMember() {
timestamp = parseInt(data.timestamp, 10)
};
this.isEdit = false;
- this.execute = function(odtDocument) {
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document);
if(!odtDocument.getMember(memberid)) {
return false
}
odtDocument.removeMember(memberid);
- odtDocument.emit(ops.OdtDocument.signalMemberRemoved, memberid);
+ odtDocument.emit(ops.Document.signalMemberRemoved, memberid);
return true
};
this.spec = function() {
return{optype:"RemoveMember", memberid:memberid, timestamp:timestamp}
}
};
+ops.OpRemoveMember.Spec;
+ops.OpRemoveMember.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13915,8 +11556,9 @@ ops.OpRemoveStyle = function OpRemoveStyle() {
styleFamily = data.styleFamily
};
this.isEdit = true;
- this.execute = function(odtDocument) {
- var styleNode = odtDocument.getStyleElement(styleName, styleFamily);
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), styleNode = odtDocument.getStyleElement(styleName, styleFamily);
if(!styleNode) {
return false
}
@@ -13930,6 +11572,7 @@ ops.OpRemoveStyle = function OpRemoveStyle() {
}
};
ops.OpRemoveStyle.Spec;
+ops.OpRemoveStyle.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -13967,9 +11610,6 @@ ops.OpRemoveStyle.Spec;
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("core.DomUtils");
ops.OpRemoveText = function OpRemoveText() {
var memberid, timestamp, position, length, odfUtils, domUtils, editinfons = "urn:webodf:names:editinfo", odfNodeNamespaceMap = {};
this.init = function(data) {
@@ -13995,6 +11635,7 @@ ops.OpRemoveText = function OpRemoveText() {
odfNodeNamespaceMap[odf.Namespaces.textns] = true
};
this.isEdit = true;
+ this.group = undefined;
function CollapsingRules(rootNode) {
function isOdfNode(node) {
return odfNodeNamespaceMap.hasOwnProperty(node.namespaceURI)
@@ -14031,7 +11672,7 @@ ops.OpRemoveText = function OpRemoveText() {
}else {
parent = domUtils.removeUnwantedNodes(targetNode, shouldRemove)
}
- if(isCollapsibleContainer(parent)) {
+ if(parent && isCollapsibleContainer(parent)) {
return mergeChildrenIntoParent(parent)
}
return parent
@@ -14039,19 +11680,18 @@ ops.OpRemoveText = function OpRemoveText() {
this.mergeChildrenIntoParent = mergeChildrenIntoParent
}
function mergeParagraphs(first, second, collapseRules) {
- var child, mergeForward = false, destination = first, source = second, secondParent, insertionPoint = null;
+ var child, destination = first, source = second, secondParent, insertionPoint = null;
if(collapseRules.isEmpty(first)) {
- mergeForward = true;
if(second.parentNode !== first.parentNode) {
secondParent = second.parentNode;
first.parentNode.insertBefore(second, first.nextSibling)
}
source = first;
destination = second;
- insertionPoint = destination.getElementsByTagNameNS(editinfons, "editinfo")[0] || destination.firstChild
+ insertionPoint = destination.getElementsByTagNameNS(editinfons, "editinfo").item(0) || destination.firstChild
}
- while(source.hasChildNodes()) {
- child = mergeForward ? source.lastChild : source.firstChild;
+ while(source.firstChild) {
+ child = source.firstChild;
source.removeChild(child);
if(child.localName !== "editinfo") {
destination.insertBefore(child, insertionPoint)
@@ -14063,8 +11703,8 @@ ops.OpRemoveText = function OpRemoveText() {
collapseRules.mergeChildrenIntoParent(source);
return destination
}
- this.execute = function(odtDocument) {
- var paragraphElement, destinationParagraph, range, textNodes, paragraphs, cursor = odtDocument.getCursor(memberid), collapseRules = new CollapsingRules(odtDocument.getRootNode());
+ this.execute = function(document) {
+ var odtDocument = (document), paragraphElement, destinationParagraph, range, textNodes, paragraphs, cursor = odtDocument.getCursor(memberid), collapseRules = new CollapsingRules(odtDocument.getRootNode());
odtDocument.upgradeWhitespacesAtPosition(position);
odtDocument.upgradeWhitespacesAtPosition(position + length);
range = odtDocument.convertCursorToDomRange(position, length);
@@ -14076,9 +11716,10 @@ ops.OpRemoveText = function OpRemoveText() {
textNodes.forEach(function(element) {
collapseRules.mergeChildrenIntoParent(element)
});
- destinationParagraph = paragraphs.reduce(function(destination, paragraph) {
+ function merge(destination, paragraph) {
return mergeParagraphs(destination, paragraph, collapseRules)
- });
+ }
+ destinationParagraph = paragraphs.reduce(merge);
odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position:position, length:length});
odtDocument.downgradeWhitespacesAtPosition(position);
odtDocument.fixCursorPositions();
@@ -14086,7 +11727,7 @@ ops.OpRemoveText = function OpRemoveText() {
odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:destinationParagraph || paragraphElement, memberId:memberid, timeStamp:timestamp});
if(cursor) {
cursor.resetSelectionType();
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
+ odtDocument.emit(ops.Document.signalCursorMoved, cursor)
}
odtDocument.getOdfCanvas().rerenderAnnotations();
return true
@@ -14096,6 +11737,7 @@ ops.OpRemoveText = function OpRemoveText() {
}
};
ops.OpRemoveText.Spec;
+ops.OpRemoveText.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -14143,7 +11785,9 @@ ops.OpSetBlob = function OpSetBlob() {
content = data.content
};
this.isEdit = true;
- this.execute = function(odtDocument) {
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document);
odtDocument.getOdfCanvas().odfContainer().setBlob(filename, mimetype, content);
return true
};
@@ -14151,6 +11795,8 @@ ops.OpSetBlob = function OpSetBlob() {
return{optype:"SetBlob", memberid:memberid, timestamp:timestamp, filename:filename, mimetype:mimetype, content:content}
}
};
+ops.OpSetBlob.Spec;
+ops.OpSetBlob.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -14197,8 +11843,9 @@ ops.OpSetParagraphStyle = function OpSetParagraphStyle() {
styleName = data.styleName
};
this.isEdit = true;
- this.execute = function(odtDocument) {
- var iterator, paragraphNode;
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), iterator, paragraphNode;
iterator = odtDocument.getIteratorAtPosition(position);
paragraphNode = odtDocument.getParagraphElement(iterator.container());
if(paragraphNode) {
@@ -14219,6 +11866,7 @@ ops.OpSetParagraphStyle = function OpSetParagraphStyle() {
}
};
ops.OpSetParagraphStyle.Spec;
+ops.OpSetParagraphStyle.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -14266,8 +11914,9 @@ ops.OpSplitParagraph = function OpSplitParagraph() {
odfUtils = new odf.OdfUtils
};
this.isEdit = true;
- this.execute = function(odtDocument) {
- var domPosition, paragraphNode, targetNode, node, splitNode, splitChildNode, keptChildNode, cursor = odtDocument.getCursor(memberid);
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), domPosition, paragraphNode, targetNode, node, splitNode, splitChildNode, keptChildNode, cursor = odtDocument.getCursor(memberid);
odtDocument.upgradeWhitespacesAtPosition(position);
domPosition = odtDocument.getTextNodeAtStep(position);
if(!domPosition) {
@@ -14314,7 +11963,7 @@ ops.OpSplitParagraph = function OpSplitParagraph() {
splitChildNode = splitNode
}
if(odfUtils.isListItem(splitChildNode)) {
- splitChildNode = splitChildNode.childNodes[0]
+ splitChildNode = splitChildNode.childNodes.item(0)
}
if(domPosition.textNode.length === 0) {
domPosition.textNode.parentNode.removeChild(domPosition.textNode)
@@ -14322,7 +11971,7 @@ ops.OpSplitParagraph = function OpSplitParagraph() {
odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:1});
if(cursor && moveCursor) {
odtDocument.moveCursor(memberid, position + 1, 0);
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor)
+ odtDocument.emit(ops.Document.signalCursorMoved, cursor)
}
odtDocument.fixCursorPositions();
odtDocument.getOdfCanvas().refreshSize();
@@ -14336,6 +11985,7 @@ ops.OpSplitParagraph = function OpSplitParagraph() {
}
};
ops.OpSplitParagraph.Spec;
+ops.OpSplitParagraph.InitSpec;
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -14360,10 +12010,8 @@ ops.OpSplitParagraph.Spec;
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.Member");
-runtime.loadClass("xmldom.XPath");
ops.OpUpdateMember = function OpUpdateMember() {
- var memberid, timestamp, setProperties, removedProperties, doc;
+ var memberid, timestamp, setProperties, removedProperties;
this.init = function(data) {
memberid = data.memberid;
timestamp = parseInt(data.timestamp, 10);
@@ -14371,7 +12019,8 @@ ops.OpUpdateMember = function OpUpdateMember() {
removedProperties = data.removedProperties
};
this.isEdit = false;
- function updateCreators() {
+ this.group = undefined;
+ function updateCreators(doc) {
var xpath = xmldom.XPath, xp = "//dc:creator[@editinfo:memberid='" + memberid + "']", creators = xpath.getODFElementsWithXPath(doc.getRootNode(), xp, function(prefix) {
if(prefix === "editinfo") {
return"urn:webodf:names:editinfo"
@@ -14382,9 +12031,8 @@ ops.OpUpdateMember = function OpUpdateMember() {
creators[i].textContent = setProperties.fullName
}
}
- this.execute = function(odtDocument) {
- doc = odtDocument;
- var member = odtDocument.getMember(memberid);
+ this.execute = function(document) {
+ var odtDocument = (document), member = odtDocument.getMember(memberid);
if(!member) {
return false
}
@@ -14394,16 +12042,18 @@ ops.OpUpdateMember = function OpUpdateMember() {
if(setProperties) {
member.setProperties(setProperties);
if(setProperties.fullName) {
- updateCreators()
+ updateCreators(odtDocument)
}
}
- odtDocument.emit(ops.OdtDocument.signalMemberUpdated, member);
+ odtDocument.emit(ops.Document.signalMemberUpdated, member);
return true
};
this.spec = function() {
return{optype:"UpdateMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties, removedProperties:removedProperties}
}
};
+ops.OpUpdateMember.Spec;
+ops.OpUpdateMember.InitSpec;
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -14437,21 +12087,10 @@ ops.OpUpdateMetadata = function OpUpdateMetadata() {
removedProperties = data.removedProperties
};
this.isEdit = true;
- this.execute = function(odtDocument) {
- var odfContainer = odtDocument.getOdfCanvas().odfContainer(), removedPropertiesArray = [], blockedProperties = ["dc:date", "dc:creator", "meta:editing-cycles"];
- if(setProperties) {
- blockedProperties.forEach(function(el) {
- if(setProperties[el]) {
- return false
- }
- })
- }
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), odfContainer = odtDocument.getOdfCanvas().odfContainer(), removedPropertiesArray = [];
if(removedProperties) {
- blockedProperties.forEach(function(el) {
- if(removedPropertiesArray.indexOf(el) !== -1) {
- return false
- }
- });
removedPropertiesArray = removedProperties.attributes.split(",")
}
odfContainer.setMetadata(setProperties, removedPropertiesArray);
@@ -14461,6 +12100,8 @@ ops.OpUpdateMetadata = function OpUpdateMetadata() {
return{optype:"UpdateMetadata", memberid:memberid, timestamp:timestamp, setProperties:setProperties, removedProperties:removedProperties}
}
};
+ops.OpUpdateMetadata.Spec;
+ops.OpUpdateMetadata.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -14498,14 +12139,13 @@ ops.OpUpdateMetadata = function OpUpdateMetadata() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");
ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() {
var memberid, timestamp, styleName, setProperties, removedProperties, paragraphPropertiesName = "style:paragraph-properties", textPropertiesName = "style:text-properties", stylens = odf.Namespaces.stylens;
function removedAttributesFromStyleNode(node, removedAttributeNames) {
var i, attributeNameParts, attributeNameList = removedAttributeNames ? removedAttributeNames.split(",") : [];
for(i = 0;i < attributeNameList.length;i += 1) {
attributeNameParts = attributeNameList[i].split(":");
- node.removeAttributeNS(odf.Namespaces.lookupNamespaceURI(attributeNameParts[0]), attributeNameParts[1])
+ node.removeAttributeNS((odf.Namespaces.lookupNamespaceURI(attributeNameParts[0])), attributeNameParts[1])
}
}
this.init = function(data) {
@@ -14516,28 +12156,31 @@ ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() {
removedProperties = data.removedProperties
};
this.isEdit = true;
- this.execute = function(odtDocument) {
- var formatting = odtDocument.getFormatting(), styleNode, paragraphPropertiesNode, textPropertiesNode;
+ this.group = undefined;
+ this.execute = function(document) {
+ var odtDocument = (document), formatting = odtDocument.getFormatting(), styleNode, object, paragraphPropertiesNode, textPropertiesNode;
if(styleName !== "") {
styleNode = odtDocument.getParagraphStyleElement(styleName)
}else {
styleNode = formatting.getDefaultStyleElement("paragraph")
}
if(styleNode) {
- paragraphPropertiesNode = styleNode.getElementsByTagNameNS(stylens, "paragraph-properties")[0];
- textPropertiesNode = styleNode.getElementsByTagNameNS(stylens, "text-properties")[0];
+ paragraphPropertiesNode = (styleNode.getElementsByTagNameNS(stylens, "paragraph-properties").item(0));
+ textPropertiesNode = (styleNode.getElementsByTagNameNS(stylens, "text-properties").item(0));
if(setProperties) {
formatting.updateStyle(styleNode, setProperties)
}
if(removedProperties) {
- if(removedProperties[paragraphPropertiesName]) {
- removedAttributesFromStyleNode(paragraphPropertiesNode, removedProperties[paragraphPropertiesName].attributes);
+ object = (removedProperties[paragraphPropertiesName]);
+ if(paragraphPropertiesNode && object) {
+ removedAttributesFromStyleNode(paragraphPropertiesNode, object.attributes);
if(paragraphPropertiesNode.attributes.length === 0) {
styleNode.removeChild(paragraphPropertiesNode)
}
}
- if(removedProperties[textPropertiesName]) {
- removedAttributesFromStyleNode(textPropertiesNode, removedProperties[textPropertiesName].attributes);
+ object = (removedProperties[textPropertiesName]);
+ if(textPropertiesNode && object) {
+ removedAttributesFromStyleNode(textPropertiesNode, object.attributes);
if(textPropertiesNode.attributes.length === 0) {
styleNode.removeChild(textPropertiesNode)
}
@@ -14556,6 +12199,7 @@ ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() {
}
};
ops.OpUpdateParagraphStyle.Spec;
+ops.OpUpdateParagraphStyle.InitSpec;
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -14593,48 +12237,22 @@ ops.OpUpdateParagraphStyle.Spec;
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.OpAddMember");
-runtime.loadClass("ops.OpUpdateMember");
-runtime.loadClass("ops.OpRemoveMember");
-runtime.loadClass("ops.OpAddCursor");
-runtime.loadClass("ops.OpApplyDirectStyling");
-runtime.loadClass("ops.OpRemoveCursor");
-runtime.loadClass("ops.OpMoveCursor");
-runtime.loadClass("ops.OpSetBlob");
-runtime.loadClass("ops.OpRemoveBlob");
-runtime.loadClass("ops.OpInsertImage");
-runtime.loadClass("ops.OpInsertTable");
-runtime.loadClass("ops.OpInsertText");
-runtime.loadClass("ops.OpRemoveText");
-runtime.loadClass("ops.OpSplitParagraph");
-runtime.loadClass("ops.OpSetParagraphStyle");
-runtime.loadClass("ops.OpUpdateParagraphStyle");
-runtime.loadClass("ops.OpAddStyle");
-runtime.loadClass("ops.OpRemoveStyle");
-runtime.loadClass("ops.OpAddAnnotation");
-runtime.loadClass("ops.OpRemoveAnnotation");
-runtime.loadClass("ops.OpUpdateMetadata");
ops.OperationFactory = function OperationFactory() {
var specs;
this.register = function(specName, specConstructor) {
specs[specName] = specConstructor
};
this.create = function(spec) {
- var op = null, specConstructor = specs[spec.optype];
- if(specConstructor) {
- op = specConstructor(spec);
+ var op = null, Constructor = specs[spec.optype];
+ if(Constructor) {
+ op = new Constructor;
op.init(spec)
}
return op
};
- function constructor(OperationType) {
- return function() {
- return new OperationType
- }
- }
function init() {
- specs = {AddMember:constructor(ops.OpAddMember), UpdateMember:constructor(ops.OpUpdateMember), RemoveMember:constructor(ops.OpRemoveMember), AddCursor:constructor(ops.OpAddCursor), ApplyDirectStyling:constructor(ops.OpApplyDirectStyling), SetBlob:constructor(ops.OpSetBlob), RemoveBlob:constructor(ops.OpRemoveBlob), InsertImage:constructor(ops.OpInsertImage), InsertTable:constructor(ops.OpInsertTable), InsertText:constructor(ops.OpInsertText), RemoveText:constructor(ops.OpRemoveText), SplitParagraph:constructor(ops.OpSplitParagraph),
- SetParagraphStyle:constructor(ops.OpSetParagraphStyle), UpdateParagraphStyle:constructor(ops.OpUpdateParagraphStyle), AddStyle:constructor(ops.OpAddStyle), RemoveStyle:constructor(ops.OpRemoveStyle), MoveCursor:constructor(ops.OpMoveCursor), RemoveCursor:constructor(ops.OpRemoveCursor), AddAnnotation:constructor(ops.OpAddAnnotation), RemoveAnnotation:constructor(ops.OpRemoveAnnotation), UpdateMetadata:constructor(ops.OpUpdateMetadata)}
+ specs = {AddMember:ops.OpAddMember, UpdateMember:ops.OpUpdateMember, RemoveMember:ops.OpRemoveMember, AddCursor:ops.OpAddCursor, ApplyDirectStyling:ops.OpApplyDirectStyling, SetBlob:ops.OpSetBlob, RemoveBlob:ops.OpRemoveBlob, InsertImage:ops.OpInsertImage, InsertTable:ops.OpInsertTable, InsertText:ops.OpInsertText, RemoveText:ops.OpRemoveText, SplitParagraph:ops.OpSplitParagraph, SetParagraphStyle:ops.OpSetParagraphStyle, UpdateParagraphStyle:ops.OpUpdateParagraphStyle, AddStyle:ops.OpAddStyle,
+ RemoveStyle:ops.OpRemoveStyle, MoveCursor:ops.OpMoveCursor, RemoveCursor:ops.OpRemoveCursor, AddAnnotation:ops.OpAddAnnotation, RemoveAnnotation:ops.OpRemoveAnnotation, UpdateMetadata:ops.OpUpdateMetadata, ApplyHyperlink:ops.OpApplyHyperlink, RemoveHyperlink:ops.OpRemoveHyperlink}
}
init()
};
@@ -14693,688 +12311,8 @@ ops.OperationRouter.prototype.hasLocalUnsyncedOps = function() {
};
ops.OperationRouter.prototype.hasSessionHostConnection = function() {
};
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-ops.OperationTransformMatrix = function OperationTransformMatrix() {
- function invertMoveCursorSpecRange(moveCursorSpec) {
- moveCursorSpec.position = moveCursorSpec.position + moveCursorSpec.length;
- moveCursorSpec.length *= -1
- }
- function invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec) {
- var isBackwards = moveCursorSpec.length < 0;
- if(isBackwards) {
- invertMoveCursorSpecRange(moveCursorSpec)
- }
- return isBackwards
- }
- function getStyleReferencingAttributes(setProperties, styleName) {
- var attributes = [];
- if(setProperties) {
- ["style:parent-style-name", "style:next-style-name"].forEach(function(attributeName) {
- if(setProperties[attributeName] === styleName) {
- attributes.push(attributeName)
- }
- })
- }
- return attributes
- }
- function dropStyleReferencingAttributes(setProperties, deletedStyleName) {
- if(setProperties) {
- ["style:parent-style-name", "style:next-style-name"].forEach(function(attributeName) {
- if(setProperties[attributeName] === deletedStyleName) {
- delete setProperties[attributeName]
- }
- })
- }
- }
- function cloneOpspec(opspec) {
- var result = {};
- Object.keys(opspec).forEach(function(key) {
- if(typeof opspec[key] === "object") {
- result[key] = cloneOpspec(opspec[key])
- }else {
- result[key] = opspec[key]
- }
- });
- return result
- }
- function dropOverruledAndUnneededAttributes(minorSetProperties, minorRemovedProperties, majorSetProperties, majorRemovedProperties) {
- var value, i, name, majorChanged = false, minorChanged = false, overrulingPropertyValue, removedPropertyNames, majorRemovedPropertyNames = majorRemovedProperties && majorRemovedProperties.attributes ? majorRemovedProperties.attributes.split(",") : [];
- if(minorSetProperties && (majorSetProperties || majorRemovedPropertyNames.length > 0)) {
- Object.keys(minorSetProperties).forEach(function(key) {
- value = minorSetProperties[key];
- if(typeof value !== "object") {
- overrulingPropertyValue = majorSetProperties && majorSetProperties[key];
- if(overrulingPropertyValue !== undefined) {
- delete minorSetProperties[key];
- minorChanged = true;
- if(overrulingPropertyValue === value) {
- delete majorSetProperties[key];
- majorChanged = true
- }
- }else {
- if(majorRemovedPropertyNames && majorRemovedPropertyNames.indexOf(key) !== -1) {
- delete minorSetProperties[key];
- minorChanged = true
- }
- }
- }
- })
- }
- if(minorRemovedProperties && (minorRemovedProperties.attributes && (majorSetProperties || majorRemovedPropertyNames.length > 0))) {
- removedPropertyNames = minorRemovedProperties.attributes.split(",");
- for(i = 0;i < removedPropertyNames.length;i += 1) {
- name = removedPropertyNames[i];
- if(majorSetProperties && majorSetProperties[name] !== undefined || majorRemovedPropertyNames && majorRemovedPropertyNames.indexOf(name) !== -1) {
- removedPropertyNames.splice(i, 1);
- i -= 1;
- minorChanged = true
- }
- }
- if(removedPropertyNames.length > 0) {
- minorRemovedProperties.attributes = removedPropertyNames.join(",")
- }else {
- delete minorRemovedProperties.attributes
- }
- }
- return{majorChanged:majorChanged, minorChanged:minorChanged}
- }
- function hasProperties(properties) {
- var key;
- for(key in properties) {
- if(properties.hasOwnProperty(key)) {
- return true
- }
- }
- return false
- }
- function hasRemovedProperties(properties) {
- var key;
- for(key in properties) {
- if(properties.hasOwnProperty(key)) {
- if(key !== "attributes" || properties.attributes.length > 0) {
- return true
- }
- }
- }
- return false
- }
- function dropOverruledAndUnneededProperties(minorOpspec, majorOpspec, propertiesName) {
- var minorSP = minorOpspec.setProperties ? minorOpspec.setProperties[propertiesName] : null, minorRP = minorOpspec.removedProperties ? minorOpspec.removedProperties[propertiesName] : null, majorSP = majorOpspec.setProperties ? majorOpspec.setProperties[propertiesName] : null, majorRP = majorOpspec.removedProperties ? majorOpspec.removedProperties[propertiesName] : null, result;
- result = dropOverruledAndUnneededAttributes(minorSP, minorRP, majorSP, majorRP);
- if(minorSP && !hasProperties(minorSP)) {
- delete minorOpspec.setProperties[propertiesName]
- }
- if(minorRP && !hasRemovedProperties(minorRP)) {
- delete minorOpspec.removedProperties[propertiesName]
- }
- if(majorSP && !hasProperties(majorSP)) {
- delete majorOpspec.setProperties[propertiesName]
- }
- if(majorRP && !hasRemovedProperties(majorRP)) {
- delete majorOpspec.removedProperties[propertiesName]
- }
- return result
- }
- function transformAddStyleRemoveStyle(addStyleSpec, removeStyleSpec) {
- var setAttributes, helperOpspec, addStyleSpecResult = [addStyleSpec], removeStyleSpecResult = [removeStyleSpec];
- if(addStyleSpec.styleFamily === removeStyleSpec.styleFamily) {
- setAttributes = getStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName);
- if(setAttributes.length > 0) {
- helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:addStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
- removeStyleSpecResult.unshift(helperOpspec)
- }
- dropStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName)
- }
- return{opSpecsA:addStyleSpecResult, opSpecsB:removeStyleSpecResult}
- }
- function transformApplyDirectStylingApplyDirectStyling(applyDirectStylingSpecA, applyDirectStylingSpecB, hasAPriority) {
- var majorSpec, minorSpec, majorSpecResult, minorSpecResult, majorSpecEnd, minorSpecEnd, dropResult, originalMajorSpec, originalMinorSpec, helperOpspecBefore, helperOpspecAfter, applyDirectStylingSpecAResult = [applyDirectStylingSpecA], applyDirectStylingSpecBResult = [applyDirectStylingSpecB];
- if(!(applyDirectStylingSpecA.position + applyDirectStylingSpecA.length <= applyDirectStylingSpecB.position || applyDirectStylingSpecA.position >= applyDirectStylingSpecB.position + applyDirectStylingSpecB.length)) {
- majorSpec = hasAPriority ? applyDirectStylingSpecA : applyDirectStylingSpecB;
- minorSpec = hasAPriority ? applyDirectStylingSpecB : applyDirectStylingSpecA;
- if(applyDirectStylingSpecA.position !== applyDirectStylingSpecB.position || applyDirectStylingSpecA.length !== applyDirectStylingSpecB.length) {
- originalMajorSpec = cloneOpspec(majorSpec);
- originalMinorSpec = cloneOpspec(minorSpec)
- }
- dropResult = dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:text-properties");
- if(dropResult.majorChanged || dropResult.minorChanged) {
- majorSpecResult = [];
- minorSpecResult = [];
- majorSpecEnd = majorSpec.position + majorSpec.length;
- minorSpecEnd = minorSpec.position + minorSpec.length;
- if(minorSpec.position < majorSpec.position) {
- if(dropResult.minorChanged) {
- helperOpspecBefore = cloneOpspec((originalMinorSpec));
- helperOpspecBefore.length = majorSpec.position - minorSpec.position;
- minorSpecResult.push(helperOpspecBefore);
- minorSpec.position = majorSpec.position;
- minorSpec.length = minorSpecEnd - minorSpec.position
- }
- }else {
- if(majorSpec.position < minorSpec.position) {
- if(dropResult.majorChanged) {
- helperOpspecBefore = cloneOpspec((originalMajorSpec));
- helperOpspecBefore.length = minorSpec.position - majorSpec.position;
- majorSpecResult.push(helperOpspecBefore);
- majorSpec.position = minorSpec.position;
- majorSpec.length = majorSpecEnd - majorSpec.position
- }
- }
- }
- if(minorSpecEnd > majorSpecEnd) {
- if(dropResult.minorChanged) {
- helperOpspecAfter = originalMinorSpec;
- helperOpspecAfter.position = majorSpecEnd;
- helperOpspecAfter.length = minorSpecEnd - majorSpecEnd;
- minorSpecResult.push(helperOpspecAfter);
- minorSpec.length = majorSpecEnd - minorSpec.position
- }
- }else {
- if(majorSpecEnd > minorSpecEnd) {
- if(dropResult.majorChanged) {
- helperOpspecAfter = originalMajorSpec;
- helperOpspecAfter.position = minorSpecEnd;
- helperOpspecAfter.length = majorSpecEnd - minorSpecEnd;
- majorSpecResult.push(helperOpspecAfter);
- majorSpec.length = minorSpecEnd - majorSpec.position
- }
- }
- }
- if(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) {
- majorSpecResult.push(majorSpec)
- }
- if(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) {
- minorSpecResult.push(minorSpec)
- }
- if(hasAPriority) {
- applyDirectStylingSpecAResult = majorSpecResult;
- applyDirectStylingSpecBResult = minorSpecResult
- }else {
- applyDirectStylingSpecAResult = minorSpecResult;
- applyDirectStylingSpecBResult = majorSpecResult
- }
- }
- }
- return{opSpecsA:applyDirectStylingSpecAResult, opSpecsB:applyDirectStylingSpecBResult}
- }
- function transformApplyDirectStylingInsertText(applyDirectStylingSpec, insertTextSpec) {
- if(insertTextSpec.position <= applyDirectStylingSpec.position) {
- applyDirectStylingSpec.position += insertTextSpec.text.length
- }else {
- if(insertTextSpec.position <= applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
- applyDirectStylingSpec.length += insertTextSpec.text.length
- }
- }
- return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[insertTextSpec]}
- }
- function transformApplyDirectStylingRemoveText(applyDirectStylingSpec, removeTextSpec) {
- var applyDirectStylingSpecEnd = applyDirectStylingSpec.position + applyDirectStylingSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, applyDirectStylingSpecResult = [applyDirectStylingSpec], removeTextSpecResult = [removeTextSpec];
- if(removeTextSpecEnd <= applyDirectStylingSpec.position) {
- applyDirectStylingSpec.position -= removeTextSpec.length
- }else {
- if(removeTextSpec.position < applyDirectStylingSpecEnd) {
- if(applyDirectStylingSpec.position < removeTextSpec.position) {
- if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
- applyDirectStylingSpec.length -= removeTextSpec.length
- }else {
- applyDirectStylingSpec.length = removeTextSpec.position - applyDirectStylingSpec.position
- }
- }else {
- applyDirectStylingSpec.position = removeTextSpec.position;
- if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
- applyDirectStylingSpec.length = applyDirectStylingSpecEnd - removeTextSpecEnd
- }else {
- applyDirectStylingSpecResult = []
- }
- }
- }
- }
- return{opSpecsA:applyDirectStylingSpecResult, opSpecsB:removeTextSpecResult}
- }
- function transformApplyDirectStylingSplitParagraph(applyDirectStylingSpec, splitParagraphSpec) {
- if(splitParagraphSpec.position < applyDirectStylingSpec.position) {
- applyDirectStylingSpec.position += 1
- }else {
- if(splitParagraphSpec.position < applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
- applyDirectStylingSpec.length += 1
- }
- }
- return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[splitParagraphSpec]}
- }
- function transformInsertTextInsertText(insertTextSpecA, insertTextSpecB, hasAPriority) {
- if(insertTextSpecA.position < insertTextSpecB.position) {
- insertTextSpecB.position += insertTextSpecA.text.length
- }else {
- if(insertTextSpecA.position > insertTextSpecB.position) {
- insertTextSpecA.position += insertTextSpecB.text.length
- }else {
- if(hasAPriority) {
- insertTextSpecB.position += insertTextSpecA.text.length
- }else {
- insertTextSpecA.position += insertTextSpecB.text.length
- }
- }
- }
- return{opSpecsA:[insertTextSpecA], opSpecsB:[insertTextSpecB]}
- }
- function transformInsertTextMoveCursor(insertTextSpec, moveCursorSpec) {
- var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
- if(insertTextSpec.position < moveCursorSpec.position) {
- moveCursorSpec.position += insertTextSpec.text.length
- }else {
- if(insertTextSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
- moveCursorSpec.length += insertTextSpec.text.length
- }
- }
- if(isMoveCursorSpecRangeInverted) {
- invertMoveCursorSpecRange(moveCursorSpec)
- }
- return{opSpecsA:[insertTextSpec], opSpecsB:[moveCursorSpec]}
- }
- function transformInsertTextRemoveText(insertTextSpec, removeTextSpec) {
- var helperOpspec, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, insertTextSpecResult = [insertTextSpec], removeTextSpecResult = [removeTextSpec];
- if(removeTextSpecEnd <= insertTextSpec.position) {
- insertTextSpec.position -= removeTextSpec.length
- }else {
- if(insertTextSpec.position <= removeTextSpec.position) {
- removeTextSpec.position += insertTextSpec.text.length
- }else {
- removeTextSpec.length = insertTextSpec.position - removeTextSpec.position;
- helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:insertTextSpec.position + insertTextSpec.text.length, length:removeTextSpecEnd - insertTextSpec.position};
- removeTextSpecResult.unshift(helperOpspec);
- insertTextSpec.position = removeTextSpec.position
- }
- }
- return{opSpecsA:insertTextSpecResult, opSpecsB:removeTextSpecResult}
- }
- function transformInsertTextSplitParagraph(insertTextSpec, splitParagraphSpec, hasAPriority) {
- if(insertTextSpec.position < splitParagraphSpec.position) {
- splitParagraphSpec.position += insertTextSpec.text.length
- }else {
- if(insertTextSpec.position > splitParagraphSpec.position) {
- insertTextSpec.position += 1
- }else {
- if(hasAPriority) {
- splitParagraphSpec.position += insertTextSpec.text.length
- }else {
- insertTextSpec.position += 1
- }
- return null
- }
- }
- return{opSpecsA:[insertTextSpec], opSpecsB:[splitParagraphSpec]}
- }
- function transformUpdateParagraphStyleUpdateParagraphStyle(updateParagraphStyleSpecA, updateParagraphStyleSpecB, hasAPriority) {
- var majorSpec, minorSpec, updateParagraphStyleSpecAResult = [updateParagraphStyleSpecA], updateParagraphStyleSpecBResult = [updateParagraphStyleSpecB];
- if(updateParagraphStyleSpecA.styleName === updateParagraphStyleSpecB.styleName) {
- majorSpec = hasAPriority ? updateParagraphStyleSpecA : updateParagraphStyleSpecB;
- minorSpec = hasAPriority ? updateParagraphStyleSpecB : updateParagraphStyleSpecA;
- dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:paragraph-properties");
- dropOverruledAndUnneededProperties(minorSpec, majorSpec, "style:text-properties");
- dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, minorSpec.removedProperties || null, majorSpec.setProperties || null, majorSpec.removedProperties || null);
- if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
- if(hasAPriority) {
- updateParagraphStyleSpecAResult = []
- }else {
- updateParagraphStyleSpecBResult = []
- }
- }
- if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
- if(hasAPriority) {
- updateParagraphStyleSpecBResult = []
- }else {
- updateParagraphStyleSpecAResult = []
- }
- }
- }
- return{opSpecsA:updateParagraphStyleSpecAResult, opSpecsB:updateParagraphStyleSpecBResult}
- }
- function transformUpdateMetadataUpdateMetadata(updateMetadataSpecA, updateMetadataSpecB, hasAPriority) {
- var majorSpec, minorSpec, updateMetadataSpecAResult = [updateMetadataSpecA], updateMetadataSpecBResult = [updateMetadataSpecB];
- majorSpec = hasAPriority ? updateMetadataSpecA : updateMetadataSpecB;
- minorSpec = hasAPriority ? updateMetadataSpecB : updateMetadataSpecA;
- dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, minorSpec.removedProperties || null, majorSpec.setProperties || null, majorSpec.removedProperties || null);
- if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
- if(hasAPriority) {
- updateMetadataSpecAResult = []
- }else {
- updateMetadataSpecBResult = []
- }
- }
- if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
- if(hasAPriority) {
- updateMetadataSpecBResult = []
- }else {
- updateMetadataSpecAResult = []
- }
- }
- return{opSpecsA:updateMetadataSpecAResult, opSpecsB:updateMetadataSpecBResult}
- }
- function transformSplitParagraphSplitParagraph(splitParagraphSpecA, splitParagraphSpecB, hasAPriority) {
- if(splitParagraphSpecA.position < splitParagraphSpecB.position) {
- splitParagraphSpecB.position += 1
- }else {
- if(splitParagraphSpecA.position > splitParagraphSpecB.position) {
- splitParagraphSpecA.position += 1
- }else {
- if(splitParagraphSpecA.position === splitParagraphSpecB.position) {
- if(hasAPriority) {
- splitParagraphSpecB.position += 1
- }else {
- splitParagraphSpecA.position += 1
- }
- }
- }
- }
- return{opSpecsA:[splitParagraphSpecA], opSpecsB:[splitParagraphSpecB]}
- }
- function transformMoveCursorRemoveCursor(moveCursorSpec, removeCursorSpec) {
- var isSameCursorRemoved = moveCursorSpec.memberid === removeCursorSpec.memberid;
- return{opSpecsA:isSameCursorRemoved ? [] : [moveCursorSpec], opSpecsB:[removeCursorSpec]}
- }
- function transformMoveCursorRemoveText(moveCursorSpec, removeTextSpec) {
- var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec), moveCursorSpecEnd = moveCursorSpec.position + moveCursorSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length;
- if(removeTextSpecEnd <= moveCursorSpec.position) {
- moveCursorSpec.position -= removeTextSpec.length
- }else {
- if(removeTextSpec.position < moveCursorSpecEnd) {
- if(moveCursorSpec.position < removeTextSpec.position) {
- if(removeTextSpecEnd < moveCursorSpecEnd) {
- moveCursorSpec.length -= removeTextSpec.length
- }else {
- moveCursorSpec.length = removeTextSpec.position - moveCursorSpec.position
- }
- }else {
- moveCursorSpec.position = removeTextSpec.position;
- if(removeTextSpecEnd < moveCursorSpecEnd) {
- moveCursorSpec.length = moveCursorSpecEnd - removeTextSpecEnd
- }else {
- moveCursorSpec.length = 0
- }
- }
- }
- }
- if(isMoveCursorSpecRangeInverted) {
- invertMoveCursorSpecRange(moveCursorSpec)
- }
- return{opSpecsA:[moveCursorSpec], opSpecsB:[removeTextSpec]}
- }
- function transformMoveCursorSplitParagraph(moveCursorSpec, splitParagraphSpec) {
- var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
- if(splitParagraphSpec.position < moveCursorSpec.position) {
- moveCursorSpec.position += 1
- }else {
- if(splitParagraphSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
- moveCursorSpec.length += 1
- }
- }
- if(isMoveCursorSpecRangeInverted) {
- invertMoveCursorSpecRange(moveCursorSpec)
- }
- return{opSpecsA:[moveCursorSpec], opSpecsB:[splitParagraphSpec]}
- }
- function transformRemoveCursorRemoveCursor(removeCursorSpecA, removeCursorSpecB) {
- var isSameMemberid = removeCursorSpecA.memberid === removeCursorSpecB.memberid;
- return{opSpecsA:isSameMemberid ? [] : [removeCursorSpecA], opSpecsB:isSameMemberid ? [] : [removeCursorSpecB]}
- }
- function transformRemoveStyleRemoveStyle(removeStyleSpecA, removeStyleSpecB) {
- var isSameStyle = removeStyleSpecA.styleName === removeStyleSpecB.styleName && removeStyleSpecA.styleFamily === removeStyleSpecB.styleFamily;
- return{opSpecsA:isSameStyle ? [] : [removeStyleSpecA], opSpecsB:isSameStyle ? [] : [removeStyleSpecB]}
- }
- function transformRemoveStyleSetParagraphStyle(removeStyleSpec, setParagraphStyleSpec) {
- var helperOpspec, removeStyleSpecResult = [removeStyleSpec], setParagraphStyleSpecResult = [setParagraphStyleSpec];
- if(removeStyleSpec.styleFamily === "paragraph" && removeStyleSpec.styleName === setParagraphStyleSpec.styleName) {
- helperOpspec = {optype:"SetParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, position:setParagraphStyleSpec.position, styleName:""};
- removeStyleSpecResult.unshift(helperOpspec);
- setParagraphStyleSpec.styleName = ""
- }
- return{opSpecsA:removeStyleSpecResult, opSpecsB:setParagraphStyleSpecResult}
- }
- function transformRemoveStyleUpdateParagraphStyle(removeStyleSpec, updateParagraphStyleSpec) {
- var setAttributes, helperOpspec, removeStyleSpecResult = [removeStyleSpec], updateParagraphStyleSpecResult = [updateParagraphStyleSpec];
- if(removeStyleSpec.styleFamily === "paragraph") {
- setAttributes = getStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName);
- if(setAttributes.length > 0) {
- helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:updateParagraphStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
- removeStyleSpecResult.unshift(helperOpspec)
- }
- if(removeStyleSpec.styleName === updateParagraphStyleSpec.styleName) {
- updateParagraphStyleSpecResult = []
- }else {
- dropStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName)
- }
- }
- return{opSpecsA:removeStyleSpecResult, opSpecsB:updateParagraphStyleSpecResult}
- }
- function transformRemoveTextRemoveText(removeTextSpecA, removeTextSpecB) {
- var removeTextSpecAEnd = removeTextSpecA.position + removeTextSpecA.length, removeTextSpecBEnd = removeTextSpecB.position + removeTextSpecB.length, removeTextSpecAResult = [removeTextSpecA], removeTextSpecBResult = [removeTextSpecB];
- if(removeTextSpecBEnd <= removeTextSpecA.position) {
- removeTextSpecA.position -= removeTextSpecB.length
- }else {
- if(removeTextSpecAEnd <= removeTextSpecB.position) {
- removeTextSpecB.position -= removeTextSpecA.length
- }else {
- if(removeTextSpecB.position < removeTextSpecAEnd) {
- if(removeTextSpecA.position < removeTextSpecB.position) {
- if(removeTextSpecBEnd < removeTextSpecAEnd) {
- removeTextSpecA.length = removeTextSpecA.length - removeTextSpecB.length
- }else {
- removeTextSpecA.length = removeTextSpecB.position - removeTextSpecA.position
- }
- if(removeTextSpecAEnd < removeTextSpecBEnd) {
- removeTextSpecB.position = removeTextSpecA.position;
- removeTextSpecB.length = removeTextSpecBEnd - removeTextSpecAEnd
- }else {
- removeTextSpecBResult = []
- }
- }else {
- if(removeTextSpecAEnd < removeTextSpecBEnd) {
- removeTextSpecB.length = removeTextSpecB.length - removeTextSpecA.length
- }else {
- if(removeTextSpecB.position < removeTextSpecA.position) {
- removeTextSpecB.length = removeTextSpecA.position - removeTextSpecB.position
- }else {
- removeTextSpecBResult = []
- }
- }
- if(removeTextSpecBEnd < removeTextSpecAEnd) {
- removeTextSpecA.position = removeTextSpecB.position;
- removeTextSpecA.length = removeTextSpecAEnd - removeTextSpecBEnd
- }else {
- removeTextSpecAResult = []
- }
- }
- }
- }
- }
- return{opSpecsA:removeTextSpecAResult, opSpecsB:removeTextSpecBResult}
- }
- function transformRemoveTextSplitParagraph(removeTextSpec, splitParagraphSpec) {
- var removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, helperOpspec, removeTextSpecResult = [removeTextSpec], splitParagraphSpecResult = [splitParagraphSpec];
- if(splitParagraphSpec.position <= removeTextSpec.position) {
- removeTextSpec.position += 1
- }else {
- if(splitParagraphSpec.position < removeTextSpecEnd) {
- removeTextSpec.length = splitParagraphSpec.position - removeTextSpec.position;
- helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:splitParagraphSpec.position + 1, length:removeTextSpecEnd - splitParagraphSpec.position};
- removeTextSpecResult.unshift(helperOpspec)
- }
- }
- if(removeTextSpec.position + removeTextSpec.length <= splitParagraphSpec.position) {
- splitParagraphSpec.position -= removeTextSpec.length
- }else {
- if(removeTextSpec.position < splitParagraphSpec.position) {
- splitParagraphSpec.position = removeTextSpec.position
- }
- }
- return{opSpecsA:removeTextSpecResult, opSpecsB:splitParagraphSpecResult}
- }
- function passUnchanged(opSpecA, opSpecB) {
- return{opSpecsA:[opSpecA], opSpecsB:[opSpecB]}
- }
- var transformations = {"AddCursor":{"AddCursor":passUnchanged, "AddMember":passUnchanged, "AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "AddMember":{"AddStyle":passUnchanged,
- "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "AddStyle":{"AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":transformAddStyleRemoveStyle,
- "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "ApplyDirectStyling":{"ApplyDirectStyling":transformApplyDirectStylingApplyDirectStyling, "InsertText":transformApplyDirectStylingInsertText, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformApplyDirectStylingRemoveText, "SetParagraphStyle":passUnchanged,
- "SplitParagraph":transformApplyDirectStylingSplitParagraph, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "InsertText":{"InsertText":transformInsertTextInsertText, "MoveCursor":transformInsertTextMoveCursor, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformInsertTextRemoveText, "SplitParagraph":transformInsertTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged},
- "MoveCursor":{"MoveCursor":passUnchanged, "RemoveCursor":transformMoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformMoveCursorRemoveText, "SetParagraphStyle":passUnchanged, "SplitParagraph":transformMoveCursorSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveCursor":{"RemoveCursor":transformRemoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged,
- "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveMember":{"RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveStyle":{"RemoveStyle":transformRemoveStyleRemoveStyle, "RemoveText":passUnchanged, "SetParagraphStyle":transformRemoveStyleSetParagraphStyle,
- "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":transformRemoveStyleUpdateParagraphStyle}, "RemoveText":{"RemoveText":transformRemoveTextRemoveText, "SplitParagraph":transformRemoveTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "SetParagraphStyle":{"UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "SplitParagraph":{"SplitParagraph":transformSplitParagraphSplitParagraph,
- "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMember":{"UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMetadata":{"UpdateMetadata":transformUpdateMetadataUpdateMetadata, "UpdateParagraphStyle":passUnchanged}, "UpdateParagraphStyle":{"UpdateParagraphStyle":transformUpdateParagraphStyleUpdateParagraphStyle}};
- this.passUnchanged = passUnchanged;
- this.extendTransformations = function(moreTransformations) {
- Object.keys(moreTransformations).forEach(function(optypeA) {
- var moreTransformationsOptypeAMap = moreTransformations[optypeA], optypeAMap, isExtendingOptypeAMap = transformations.hasOwnProperty(optypeA);
- runtime.log((isExtendingOptypeAMap ? "Extending" : "Adding") + " map for optypeA: " + optypeA);
- if(!isExtendingOptypeAMap) {
- transformations[optypeA] = {}
- }
- optypeAMap = transformations[optypeA];
- Object.keys(moreTransformationsOptypeAMap).forEach(function(optypeB) {
- var isOverwritingOptypeBEntry = optypeAMap.hasOwnProperty(optypeB);
- runtime.assert(optypeA <= optypeB, "Wrong order:" + optypeA + ", " + optypeB);
- runtime.log(" " + (isOverwritingOptypeBEntry ? "Overwriting" : "Adding") + " entry for optypeB: " + optypeB);
- optypeAMap[optypeB] = moreTransformationsOptypeAMap[optypeB]
- })
- })
- };
- this.transformOpspecVsOpspec = function(opSpecA, opSpecB) {
- var isOptypeAAlphaNumericSmaller = opSpecA.optype <= opSpecB.optype, helper, transformationFunctionMap, transformationFunction, result;
- runtime.log("Crosstransforming:");
- runtime.log(runtime.toJson(opSpecA));
- runtime.log(runtime.toJson(opSpecB));
- if(!isOptypeAAlphaNumericSmaller) {
- helper = opSpecA;
- opSpecA = opSpecB;
- opSpecB = helper
- }
- transformationFunctionMap = transformations[opSpecA.optype];
- transformationFunction = transformationFunctionMap && transformationFunctionMap[opSpecB.optype];
- if(transformationFunction) {
- result = transformationFunction(opSpecA, opSpecB, !isOptypeAAlphaNumericSmaller);
- if(!isOptypeAAlphaNumericSmaller && result !== null) {
- result = {opSpecsA:result.opSpecsB, opSpecsB:result.opSpecsA}
- }
- }else {
- result = null
- }
- runtime.log("result:");
- if(result) {
- runtime.log(runtime.toJson(result.opSpecsA));
- runtime.log(runtime.toJson(result.opSpecsB))
- }else {
- runtime.log("null")
- }
- return result
- }
-};
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("ops.OperationFactory");
-runtime.loadClass("ops.OperationTransformMatrix");
-ops.OperationTransformer = function OperationTransformer() {
- var operationFactory, operationTransformMatrix = new ops.OperationTransformMatrix;
- function operations(opspecs) {
- var ops = [];
- opspecs.forEach(function(opspec) {
- ops.push(operationFactory.create(opspec))
- });
- return ops
- }
- function transformOpVsOp(opSpecA, opSpecB) {
- return operationTransformMatrix.transformOpspecVsOpspec(opSpecA, opSpecB)
- }
- function transformOpListVsOp(opSpecsA, opSpecB) {
- var transformResult, transformListResult, transformedOpspecsA = [], transformedOpspecsB = [];
- while(opSpecsA.length > 0 && opSpecB) {
- transformResult = transformOpVsOp(opSpecsA.shift(), (opSpecB));
- if(!transformResult) {
- return null
- }
- transformedOpspecsA = transformedOpspecsA.concat(transformResult.opSpecsA);
- if(transformResult.opSpecsB.length === 0) {
- transformedOpspecsA = transformedOpspecsA.concat(opSpecsA);
- opSpecB = null;
- break
- }
- while(transformResult.opSpecsB.length > 1) {
- transformListResult = transformOpListVsOp(opSpecsA, transformResult.opSpecsB.shift());
- if(!transformListResult) {
- return null
- }
- transformedOpspecsB = transformedOpspecsB.concat(transformListResult.opSpecsB);
- opSpecsA = transformListResult.opSpecsA
- }
- opSpecB = transformResult.opSpecsB.pop()
- }
- if(opSpecB) {
- transformedOpspecsB.push(opSpecB)
- }
- return{opSpecsA:transformedOpspecsA, opSpecsB:transformedOpspecsB}
- }
- this.setOperationFactory = function(f) {
- operationFactory = f
- };
- this.getOperationTransformMatrix = function() {
- return operationTransformMatrix
- };
- this.transform = function(opSpecsA, opSpecsB) {
- var transformResult, transformedOpspecsB = [];
- while(opSpecsB.length > 0) {
- transformResult = transformOpListVsOp(opSpecsA, opSpecsB.shift());
- if(!transformResult) {
- return null
- }
- opSpecsA = transformResult.opSpecsA;
- transformedOpspecsB = transformedOpspecsB.concat(transformResult.opSpecsB)
- }
- return{opsA:operations(opSpecsA), opsB:operations(transformedOpspecsB)}
- }
-};
+ops.OperationRouter.signalProcessingBatchStart = "router/batchstart";
+ops.OperationRouter.signalProcessingBatchEnd = "router/batchend";
/*
Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
@@ -15413,7 +12351,7 @@ ops.OperationTransformer = function OperationTransformer() {
@source: https://github.com/kogmbh/WebODF/
*/
ops.TrivialOperationRouter = function TrivialOperationRouter() {
- var operationFactory, playbackFunction;
+ var events = new core.EventNotifier([ops.OperationRouter.signalProcessingBatchStart, ops.OperationRouter.signalProcessingBatchEnd]), operationFactory, playbackFunction, groupIdentifier = 0;
this.setOperationFactory = function(f) {
operationFactory = f
};
@@ -15421,19 +12359,25 @@ ops.TrivialOperationRouter = function TrivialOperationRouter() {
playbackFunction = playback_func
};
this.push = function(operations) {
+ groupIdentifier += 1;
+ events.emit(ops.OperationRouter.signalProcessingBatchStart, {});
operations.forEach(function(op) {
var timedOp, opspec = op.spec();
opspec.timestamp = (new Date).getTime();
timedOp = operationFactory.create(opspec);
+ timedOp.group = "g" + groupIdentifier;
playbackFunction(timedOp)
- })
+ });
+ events.emit(ops.OperationRouter.signalProcessingBatchEnd, {})
};
this.close = function(cb) {
cb()
};
this.subscribe = function(eventId, cb) {
+ events.subscribe(eventId, cb)
};
this.unsubscribe = function(eventId, cb) {
+ events.unsubscribe(eventId, cb)
};
this.hasLocalUnsyncedOps = function() {
return false
@@ -15479,97 +12423,61 @@ ops.TrivialOperationRouter = function TrivialOperationRouter() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.EditInfo");
-runtime.loadClass("gui.EditInfoHandle");
-gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
- var self = this, editInfoNode, handle, marker, editinfons = "urn:webodf:names:editinfo", decay1, decay2, decayTimeStep = 1E4;
- function applyDecay(opacity, delay) {
- return runtime.setTimeout(function() {
- marker.style.opacity = opacity
- }, delay)
- }
- function deleteDecay(timer) {
- runtime.clearTimeout(timer)
+ops.Session = function Session(odfCanvas) {
+ var self = this, operationFactory = new ops.OperationFactory, odtDocument = new ops.OdtDocument(odfCanvas), operationRouter = null;
+ function forwardBatchStart(args) {
+ odtDocument.emit(ops.OdtDocument.signalProcessingBatchStart, args)
}
- function setLastAuthor(memberid) {
- marker.setAttributeNS(editinfons, "editinfo:memberid", memberid)
+ function forwardBatchEnd(args) {
+ odtDocument.emit(ops.OdtDocument.signalProcessingBatchEnd, args)
}
- this.addEdit = function(memberid, timestamp) {
- var age = Date.now() - timestamp;
- editInfo.addEdit(memberid, timestamp);
- handle.setEdits(editInfo.getSortedEdits());
- setLastAuthor(memberid);
- if(decay1) {
- deleteDecay(decay1)
- }
- if(decay2) {
- deleteDecay(decay2)
- }
- if(age < decayTimeStep) {
- applyDecay(1, 0);
- decay1 = applyDecay(0.5, decayTimeStep - age);
- decay2 = applyDecay(0.2, decayTimeStep * 2 - age)
- }else {
- if(age >= decayTimeStep && age < decayTimeStep * 2) {
- applyDecay(0.5, 0);
- decay2 = applyDecay(0.2, decayTimeStep * 2 - age)
- }else {
- applyDecay(0.2, 0)
- }
+ this.setOperationFactory = function(opFactory) {
+ operationFactory = opFactory;
+ if(operationRouter) {
+ operationRouter.setOperationFactory(operationFactory)
}
};
- this.getEdits = function() {
- return editInfo.getEdits()
- };
- this.clearEdits = function() {
- editInfo.clearEdits();
- handle.setEdits([]);
- if(marker.hasAttributeNS(editinfons, "editinfo:memberid")) {
- marker.removeAttributeNS(editinfons, "editinfo:memberid")
+ this.setOperationRouter = function(opRouter) {
+ if(operationRouter) {
+ operationRouter.unsubscribe(ops.OperationRouter.signalProcessingBatchStart, forwardBatchStart);
+ operationRouter.unsubscribe(ops.OperationRouter.signalProcessingBatchEnd, forwardBatchEnd)
}
+ operationRouter = opRouter;
+ operationRouter.subscribe(ops.OperationRouter.signalProcessingBatchStart, forwardBatchStart);
+ operationRouter.subscribe(ops.OperationRouter.signalProcessingBatchEnd, forwardBatchEnd);
+ opRouter.setPlaybackFunction(function(op) {
+ odtDocument.emit(ops.OdtDocument.signalOperationStart, op);
+ if(op.execute(odtDocument)) {
+ odtDocument.emit(ops.OdtDocument.signalOperationEnd, op);
+ return true
+ }
+ return false
+ });
+ opRouter.setOperationFactory(operationFactory)
};
- this.getEditInfo = function() {
- return editInfo
- };
- this.show = function() {
- marker.style.display = "block"
- };
- this.hide = function() {
- self.hideHandle();
- marker.style.display = "none"
+ this.getOperationFactory = function() {
+ return operationFactory
};
- this.showHandle = function() {
- handle.show()
+ this.getOdtDocument = function() {
+ return odtDocument
};
- this.hideHandle = function() {
- handle.hide()
+ this.enqueue = function(ops) {
+ operationRouter.push(ops)
};
- this.destroy = function(callback) {
- editInfoNode.removeChild(marker);
- handle.destroy(function(err) {
+ this.close = function(callback) {
+ operationRouter.close(function(err) {
if(err) {
callback(err)
}else {
- editInfo.destroy(callback)
+ odtDocument.close(callback)
}
})
};
+ this.destroy = function(callback) {
+ odtDocument.destroy(callback)
+ };
function init() {
- var dom = editInfo.getOdtDocument().getDOM(), htmlns = dom.documentElement.namespaceURI;
- marker = dom.createElementNS(htmlns, "div");
- marker.setAttribute("class", "editInfoMarker");
- marker.onmouseover = function() {
- self.showHandle()
- };
- marker.onmouseout = function() {
- self.hideHandle()
- };
- editInfoNode = editInfo.getNode();
- editInfoNode.appendChild(marker);
- handle = new gui.EditInfoHandle(editInfoNode);
- if(!initialVisibility) {
- self.hide()
- }
+ self.setOperationRouter(new ops.TrivialOperationRouter)
}
init()
};
@@ -15578,347 +12486,379 @@ gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
+ This file is part of WebODF.
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
- This license applies to this entire compilation.
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
@licend
+
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-gui.PlainTextPasteboard = function PlainTextPasteboard(odtDocument, inputMemberId) {
- function createOp(op, data) {
- op.init(data);
- return op
- }
- this.createPasteOps = function(data) {
- var originalCursorPosition = odtDocument.getCursorPosition(inputMemberId), cursorPosition = originalCursorPosition, operations = [], paragraphs;
- paragraphs = data.replace(/\r/g, "").split("\n");
- paragraphs.forEach(function(text) {
- operations.push(createOp(new ops.OpSplitParagraph, {memberid:inputMemberId, position:cursorPosition, moveCursor:true}));
- cursorPosition += 1;
- operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text, moveCursor:true}));
- cursorPosition += text.length
- });
- operations.push(createOp(new ops.OpRemoveText, {memberid:inputMemberId, position:originalCursorPosition, length:1}));
- return operations
- }
-};
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("odf.OdfNodeFilter");
-runtime.loadClass("gui.SelectionMover");
-gui.SelectionView = function SelectionView(cursor) {
- var odtDocument = cursor.getOdtDocument(), documentRoot, root, doc = odtDocument.getDOM(), overlayTop = doc.createElement("div"), overlayMiddle = doc.createElement("div"), overlayBottom = doc.createElement("div"), odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, isVisible = true, positionIterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT;
- function addOverlays() {
- var newDocumentRoot = odtDocument.getRootNode();
- if(documentRoot !== newDocumentRoot) {
- documentRoot = newDocumentRoot;
- root = (documentRoot.parentNode.parentNode.parentNode);
- root.appendChild(overlayTop);
- root.appendChild(overlayMiddle);
- root.appendChild(overlayBottom)
+gui.AnnotationController = function AnnotationController(session, inputMemberId) {
+ var odtDocument = session.getOdtDocument(), isAnnotatable = false, eventNotifier = new core.EventNotifier([gui.AnnotationController.annotatableChanged]), officens = odf.Namespaces.officens;
+ function isWithinAnnotation(node, container) {
+ while(node && node !== container) {
+ if(node.namespaceURI === officens && node.localName === "annotation") {
+ return true
+ }
+ node = node.parentNode
}
+ return false
}
- function setRect(div, rect) {
- div.style.left = rect.left + "px";
- div.style.top = rect.top + "px";
- div.style.width = rect.width + "px";
- div.style.height = rect.height + "px"
- }
- function showOverlays(choice) {
- var display;
- isVisible = choice;
- display = choice === true ? "block" : "none";
- overlayTop.style.display = overlayMiddle.style.display = overlayBottom.style.display = display
+ function updatedCachedValues() {
+ var cursor = odtDocument.getCursor(inputMemberId), cursorNode = cursor && cursor.getNode(), newIsAnnotatable = false;
+ if(cursorNode) {
+ newIsAnnotatable = !isWithinAnnotation(cursorNode, odtDocument.getRootNode())
+ }
+ if(newIsAnnotatable !== isAnnotatable) {
+ isAnnotatable = newIsAnnotatable;
+ eventNotifier.emit(gui.AnnotationController.annotatableChanged, isAnnotatable)
+ }
}
- function translateRect(rect) {
- var rootRect = domUtils.getBoundingClientRect(root), zoomLevel = odtDocument.getOdfCanvas().getZoomLevel(), resultRect = {};
- resultRect.top = domUtils.adaptRangeDifferenceToZoomLevel(rect.top - rootRect.top, zoomLevel);
- resultRect.left = domUtils.adaptRangeDifferenceToZoomLevel(rect.left - rootRect.left, zoomLevel);
- resultRect.bottom = domUtils.adaptRangeDifferenceToZoomLevel(rect.bottom - rootRect.top, zoomLevel);
- resultRect.right = domUtils.adaptRangeDifferenceToZoomLevel(rect.right - rootRect.left, zoomLevel);
- resultRect.width = domUtils.adaptRangeDifferenceToZoomLevel(rect.width, zoomLevel);
- resultRect.height = domUtils.adaptRangeDifferenceToZoomLevel(rect.height, zoomLevel);
- return resultRect
+ function onCursorAdded(cursor) {
+ if(cursor.getMemberId() === inputMemberId) {
+ updatedCachedValues()
+ }
}
- function isRangeVisible(range) {
- var bcr = range.getBoundingClientRect();
- return Boolean(bcr && bcr.height !== 0)
+ function onCursorRemoved(memberId) {
+ if(memberId === inputMemberId) {
+ updatedCachedValues()
+ }
}
- function lastVisibleRect(range, nodes) {
- var nextNodeIndex = nodes.length - 1, node = nodes[nextNodeIndex], startOffset = range.endContainer === node ? range.endOffset : node.length || node.childNodes.length, endOffset = startOffset;
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset);
- while(!isRangeVisible(range)) {
- if(node.nodeType === Node.ELEMENT_NODE && startOffset > 0) {
- startOffset = 0
- }else {
- if(node.nodeType === Node.TEXT_NODE && startOffset > 0) {
- startOffset -= 1
- }else {
- if(nodes[nextNodeIndex]) {
- node = nodes[nextNodeIndex];
- nextNodeIndex -= 1;
- startOffset = endOffset = node.length || node.childNodes.length
- }else {
- return false
- }
- }
- }
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset)
+ function onCursorMoved(cursor) {
+ if(cursor.getMemberId() === inputMemberId) {
+ updatedCachedValues()
}
- return true
}
- function firstVisibleRect(range, nodes) {
- var nextNodeIndex = 0, node = nodes[nextNodeIndex], startOffset = range.startContainer === node ? range.startOffset : 0, endOffset = startOffset;
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset);
- while(!isRangeVisible(range)) {
- if(node.nodeType === Node.ELEMENT_NODE && endOffset < node.childNodes.length) {
- endOffset = node.childNodes.length
- }else {
- if(node.nodeType === Node.TEXT_NODE && endOffset < node.length) {
- endOffset += 1
- }else {
- if(nodes[nextNodeIndex]) {
- node = nodes[nextNodeIndex];
- nextNodeIndex += 1;
- startOffset = endOffset = 0
- }else {
- return false
- }
- }
- }
- range.setStart(node, startOffset);
- range.setEnd(node, endOffset)
+ this.isAnnotatable = function() {
+ return isAnnotatable
+ };
+ this.addAnnotation = function() {
+ var op = new ops.OpAddAnnotation, selection = odtDocument.getCursorSelection(inputMemberId), length = selection.length, position = selection.position;
+ if(!isAnnotatable) {
+ return
}
- return true
+ position = length >= 0 ? position : position + length;
+ length = Math.abs(length);
+ op.init({memberid:inputMemberId, position:position, length:length, name:inputMemberId + Date.now()});
+ session.enqueue([op])
+ };
+ this.removeAnnotation = function(annotationNode) {
+ var startStep, endStep, op, moveCursor;
+ startStep = odtDocument.convertDomPointToCursorStep(annotationNode, 0) + 1;
+ endStep = odtDocument.convertDomPointToCursorStep(annotationNode, annotationNode.childNodes.length);
+ op = new ops.OpRemoveAnnotation;
+ op.init({memberid:inputMemberId, position:startStep, length:endStep - startStep});
+ moveCursor = new ops.OpMoveCursor;
+ moveCursor.init({memberid:inputMemberId, position:startStep > 0 ? startStep - 1 : startStep, length:0});
+ session.enqueue([op, moveCursor])
+ };
+ this.subscribe = function(eventid, cb) {
+ eventNotifier.subscribe(eventid, cb)
+ };
+ this.unsubscribe = function(eventid, cb) {
+ eventNotifier.unsubscribe(eventid, cb)
+ };
+ this.destroy = function(callback) {
+ odtDocument.unsubscribe(ops.Document.signalCursorAdded, onCursorAdded);
+ odtDocument.unsubscribe(ops.Document.signalCursorRemoved, onCursorRemoved);
+ odtDocument.unsubscribe(ops.Document.signalCursorMoved, onCursorMoved);
+ callback()
+ };
+ function init() {
+ odtDocument.subscribe(ops.Document.signalCursorAdded, onCursorAdded);
+ odtDocument.subscribe(ops.Document.signalCursorRemoved, onCursorRemoved);
+ odtDocument.subscribe(ops.Document.signalCursorMoved, onCursorMoved);
+ updatedCachedValues()
}
- function getExtremeRanges(range) {
- var nodes = odfUtils.getTextElements(range, true, false), firstRange = (range.cloneRange()), lastRange = (range.cloneRange()), fillerRange = range.cloneRange();
- if(!nodes.length) {
- return null
+ init()
+};
+gui.AnnotationController.annotatableChanged = "annotatable/changed";
+(function() {
+ return gui.AnnotationController
+})();
+gui.Avatar = function Avatar(parentElement, avatarInitiallyVisible) {
+ var self = this, handle, image, pendingImageUrl, displayShown = "block", displayHidden = "none";
+ this.setColor = function(color) {
+ image.style.borderColor = color
+ };
+ this.setImageUrl = function(url) {
+ if(self.isVisible()) {
+ image.src = url
+ }else {
+ pendingImageUrl = url
}
- if(!firstVisibleRect(firstRange, nodes)) {
- return null
+ };
+ this.isVisible = function() {
+ return handle.style.display === displayShown
+ };
+ this.show = function() {
+ if(pendingImageUrl) {
+ image.src = pendingImageUrl;
+ pendingImageUrl = undefined
}
- if(!lastVisibleRect(lastRange, nodes)) {
- return null
+ handle.style.display = displayShown
+ };
+ this.hide = function() {
+ handle.style.display = displayHidden
+ };
+ this.markAsFocussed = function(isFocussed) {
+ if(isFocussed) {
+ handle.classList.add("active")
+ }else {
+ handle.classList.remove("active")
}
- fillerRange.setStart(firstRange.startContainer, firstRange.startOffset);
- fillerRange.setEnd(lastRange.endContainer, lastRange.endOffset);
- return{firstRange:firstRange, lastRange:lastRange, fillerRange:fillerRange}
+ };
+ this.destroy = function(callback) {
+ parentElement.removeChild(handle);
+ callback()
+ };
+ function init() {
+ var document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI;
+ handle = (document.createElementNS(htmlns, "div"));
+ image = (document.createElementNS(htmlns, "img"));
+ image.width = 64;
+ image.height = 64;
+ handle.appendChild(image);
+ handle.style.width = "64px";
+ handle.style.height = "70px";
+ handle.style.position = "absolute";
+ handle.style.top = "-80px";
+ handle.style.left = "-34px";
+ handle.style.display = avatarInitiallyVisible ? displayShown : displayHidden;
+ handle.className = "handle";
+ parentElement.appendChild(handle)
}
- function getBoundingRect(rect1, rect2) {
- var resultRect = {};
- resultRect.top = Math.min(rect1.top, rect2.top);
- resultRect.left = Math.min(rect1.left, rect2.left);
- resultRect.right = Math.max(rect1.right, rect2.right);
- resultRect.bottom = Math.max(rect1.bottom, rect2.bottom);
- resultRect.width = resultRect.right - resultRect.left;
- resultRect.height = resultRect.bottom - resultRect.top;
- return resultRect
+ init()
+};
+gui.Caret = function Caret(cursor, avatarInitiallyVisible, blinkOnRangeSelect) {
+ var MIN_CARET_HEIGHT_PX = 8, DEFAULT_CARET_TOP = "5%", DEFAULT_CARET_HEIGHT = "1em", BLINK_PERIOD_MS = 500, span, avatar, cursorNode, overlayElement, domUtils = new core.DomUtils, async = new core.Async, redrawTask, blinkTask, shouldResetBlink = false, shouldCheckCaretVisibility = false, shouldUpdateCaretSize = false, state = {isFocused:false, isShown:true, visibility:"hidden"}, lastState = {isFocused:!state.isFocused, isShown:!state.isShown, visibility:"hidden"};
+ function blinkCaret() {
+ span.style.opacity = span.style.opacity === "0" ? "1" : "0";
+ blinkTask.trigger()
}
- function checkAndGrowOrCreateRect(originalRect, newRect) {
- if(newRect && (newRect.width > 0 && newRect.height > 0)) {
- if(!originalRect) {
- originalRect = newRect
- }else {
- originalRect = getBoundingRect(originalRect, newRect)
- }
+ function getCaretClientRectWithMargin(caretElement, margin) {
+ var caretRect = caretElement.getBoundingClientRect();
+ return{left:caretRect.left - margin.left, top:caretRect.top - margin.top, right:caretRect.right + margin.right, bottom:caretRect.bottom + margin.bottom}
+ }
+ function length(node) {
+ return node.nodeType === Node.TEXT_NODE ? node.textContent.length : node.childNodes.length
+ }
+ function verticalOverlap(cursorNode, rangeRect) {
+ var cursorRect = cursorNode.getBoundingClientRect(), intersectTop = 0, intersectBottom = 0;
+ if(cursorRect && rangeRect) {
+ intersectTop = Math.max(cursorRect.top, rangeRect.top);
+ intersectBottom = Math.min(cursorRect.bottom, rangeRect.bottom)
}
- return originalRect
+ return intersectBottom - intersectTop
}
- function getFillerRect(fillerRange) {
- var containerNode = fillerRange.commonAncestorContainer, firstNode = (fillerRange.startContainer), lastNode = (fillerRange.endContainer), firstOffset = fillerRange.startOffset, lastOffset = fillerRange.endOffset, currentNode, lastMeasuredNode, firstSibling, lastSibling, grownRect = null, currentRect, range = doc.createRange(), rootFilter, odfNodeFilter = new odf.OdfNodeFilter, treeWalker;
- function acceptNode(node) {
- positionIterator.setUnfilteredPosition(node, 0);
- if(odfNodeFilter.acceptNode(node) === FILTER_ACCEPT && rootFilter.acceptPosition(positionIterator) === FILTER_ACCEPT) {
- return FILTER_ACCEPT
+ function getSelectionRect() {
+ var range = cursor.getSelectedRange().cloneRange(), node = cursor.getNode(), nextRectangle, selectionRectangle = null, nodeLength;
+ if(node.previousSibling) {
+ nodeLength = length(node.previousSibling);
+ range.setStart(node.previousSibling, nodeLength > 0 ? nodeLength - 1 : 0);
+ range.setEnd(node.previousSibling, nodeLength);
+ nextRectangle = range.getBoundingClientRect();
+ if(nextRectangle && nextRectangle.height) {
+ selectionRectangle = nextRectangle
}
- return FILTER_REJECT
}
- function getRectFromNodeAfterFiltering(node) {
- var rect = null;
- if(acceptNode(node) === FILTER_ACCEPT) {
- rect = domUtils.getBoundingClientRect(node)
+ if(node.nextSibling) {
+ range.setStart(node.nextSibling, 0);
+ range.setEnd(node.nextSibling, length(node.nextSibling) > 0 ? 1 : 0);
+ nextRectangle = range.getBoundingClientRect();
+ if(nextRectangle && nextRectangle.height) {
+ if(!selectionRectangle || verticalOverlap(node, nextRectangle) > verticalOverlap(node, selectionRectangle)) {
+ selectionRectangle = nextRectangle
+ }
}
- return rect
}
- if(firstNode === containerNode || lastNode === containerNode) {
- range = fillerRange.cloneRange();
- grownRect = range.getBoundingClientRect();
- range.detach();
- return grownRect
- }
- firstSibling = firstNode;
- while(firstSibling.parentNode !== containerNode) {
- firstSibling = firstSibling.parentNode
- }
- lastSibling = lastNode;
- while(lastSibling.parentNode !== containerNode) {
- lastSibling = lastSibling.parentNode
- }
- rootFilter = odtDocument.createRootFilter(firstNode);
- currentNode = firstSibling.nextSibling;
- while(currentNode && currentNode !== lastSibling) {
- currentRect = getRectFromNodeAfterFiltering(currentNode);
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
- currentNode = currentNode.nextSibling
- }
- if(odfUtils.isParagraph(firstSibling)) {
- grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(firstSibling))
+ return selectionRectangle
+ }
+ function updateCaretHeightAndPosition() {
+ var selectionRect = getSelectionRect(), canvas = (cursor.getDocument().getCanvas()), zoomLevel = canvas.getZoomLevel(), rootRect = domUtils.getBoundingClientRect(canvas.getSizer()), caretRect, caretStyle;
+ if(selectionRect) {
+ span.style.top = "0";
+ caretRect = domUtils.getBoundingClientRect(span);
+ if(selectionRect.height < MIN_CARET_HEIGHT_PX) {
+ selectionRect = {top:selectionRect.top - (MIN_CARET_HEIGHT_PX - selectionRect.height) / 2, height:MIN_CARET_HEIGHT_PX}
+ }
+ span.style.height = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.height, zoomLevel) + "px";
+ span.style.top = domUtils.adaptRangeDifferenceToZoomLevel(selectionRect.top - caretRect.top, zoomLevel) + "px"
}else {
- if(firstSibling.nodeType === Node.TEXT_NODE) {
- currentNode = firstSibling;
- range.setStart(currentNode, firstOffset);
- range.setEnd(currentNode, currentNode === lastSibling ? lastOffset : currentNode.length);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
+ span.style.height = DEFAULT_CARET_HEIGHT;
+ span.style.top = DEFAULT_CARET_TOP
+ }
+ if(overlayElement) {
+ caretStyle = runtime.getWindow().getComputedStyle(span, null);
+ caretRect = domUtils.getBoundingClientRect(span);
+ overlayElement.style.bottom = domUtils.adaptRangeDifferenceToZoomLevel(rootRect.bottom - caretRect.bottom, zoomLevel) + "px";
+ overlayElement.style.left = domUtils.adaptRangeDifferenceToZoomLevel(caretRect.right - rootRect.left, zoomLevel) + "px";
+ if(caretStyle.font) {
+ overlayElement.style.font = caretStyle.font
}else {
- treeWalker = doc.createTreeWalker(firstSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
- currentNode = treeWalker.currentNode = firstNode;
- while(currentNode && currentNode !== lastNode) {
- range.setStart(currentNode, firstOffset);
- range.setEnd(currentNode, currentNode.length);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
- lastMeasuredNode = currentNode;
- firstOffset = 0;
- currentNode = treeWalker.nextNode()
- }
+ overlayElement.style.fontStyle = caretStyle.fontStyle;
+ overlayElement.style.fontVariant = caretStyle.fontVariant;
+ overlayElement.style.fontWeight = caretStyle.fontWeight;
+ overlayElement.style.fontSize = caretStyle.fontSize;
+ overlayElement.style.lineHeight = caretStyle.lineHeight;
+ overlayElement.style.fontFamily = caretStyle.fontFamily
}
}
- if(!lastMeasuredNode) {
- lastMeasuredNode = firstNode
+ }
+ function ensureVisible() {
+ var canvasElement = cursor.getDocument().getCanvas().getElement(), canvasContainerElement = (canvasElement.parentNode), caretRect, canvasContainerRect, horizontalMargin = canvasContainerElement.offsetWidth - canvasContainerElement.clientWidth + 5, verticalMargin = canvasContainerElement.offsetHeight - canvasContainerElement.clientHeight + 5;
+ caretRect = getCaretClientRectWithMargin(span, {top:verticalMargin, left:horizontalMargin, bottom:verticalMargin, right:horizontalMargin});
+ canvasContainerRect = canvasContainerElement.getBoundingClientRect();
+ if(caretRect.top < canvasContainerRect.top) {
+ canvasContainerElement.scrollTop -= canvasContainerRect.top - caretRect.top
+ }else {
+ if(caretRect.bottom > canvasContainerRect.bottom) {
+ canvasContainerElement.scrollTop += caretRect.bottom - canvasContainerRect.bottom
+ }
}
- if(odfUtils.isParagraph(lastSibling)) {
- grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(lastSibling))
+ if(caretRect.left < canvasContainerRect.left) {
+ canvasContainerElement.scrollLeft -= canvasContainerRect.left - caretRect.left
}else {
- if(lastSibling.nodeType === Node.TEXT_NODE) {
- currentNode = lastSibling;
- range.setStart(currentNode, currentNode === firstSibling ? firstOffset : 0);
- range.setEnd(currentNode, lastOffset);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
- }else {
- treeWalker = doc.createTreeWalker(lastSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
- currentNode = treeWalker.currentNode = lastNode;
- while(currentNode && currentNode !== lastMeasuredNode) {
- range.setStart(currentNode, 0);
- range.setEnd(currentNode, lastOffset);
- currentRect = range.getBoundingClientRect();
- grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
- currentNode = treeWalker.previousNode();
- if(currentNode) {
- lastOffset = currentNode.length
- }
- }
+ if(caretRect.right > canvasContainerRect.right) {
+ canvasContainerElement.scrollLeft += caretRect.right - canvasContainerRect.right
}
}
- return grownRect
}
- function getCollapsedRectOfTextRange(range, useRightEdge) {
- var clientRect = range.getBoundingClientRect(), collapsedRect = {};
- collapsedRect.width = 0;
- collapsedRect.top = clientRect.top;
- collapsedRect.bottom = clientRect.bottom;
- collapsedRect.height = clientRect.height;
- collapsedRect.left = collapsedRect.right = useRightEdge ? clientRect.right : clientRect.left;
- return collapsedRect
+ function hasStateChanged(property) {
+ return lastState[property] !== state[property]
}
- function repositionOverlays(selectedRange) {
- var extremes = getExtremeRanges(selectedRange), firstRange, lastRange, fillerRange, firstRect, fillerRect, lastRect;
- if(selectedRange.collapsed || !extremes) {
- showOverlays(false)
+ function saveState() {
+ Object.keys(state).forEach(function(key) {
+ lastState[key] = state[key]
+ })
+ }
+ function updateCaret() {
+ if(state.isShown === false || (cursor.getSelectionType() !== ops.OdtCursor.RangeSelection || !blinkOnRangeSelect && !cursor.getSelectedRange().collapsed)) {
+ state.visibility = "hidden";
+ span.style.visibility = "hidden";
+ blinkTask.cancel()
}else {
- showOverlays(true);
- firstRange = extremes.firstRange;
- lastRange = extremes.lastRange;
- fillerRange = extremes.fillerRange;
- firstRect = translateRect(getCollapsedRectOfTextRange(firstRange, false));
- lastRect = translateRect(getCollapsedRectOfTextRange(lastRange, true));
- fillerRect = getFillerRect(fillerRange);
- if(!fillerRect) {
- fillerRect = getBoundingRect(firstRect, lastRect)
+ state.visibility = "visible";
+ span.style.visibility = "visible";
+ if(state.isFocused === false) {
+ span.style.opacity = "1";
+ blinkTask.cancel()
}else {
- fillerRect = translateRect(fillerRect)
+ if(shouldResetBlink || hasStateChanged("visibility")) {
+ span.style.opacity = "1";
+ blinkTask.cancel()
+ }
+ blinkTask.trigger()
}
- setRect(overlayTop, {left:firstRect.left, top:firstRect.top, width:Math.max(0, fillerRect.width - (firstRect.left - fillerRect.left)), height:firstRect.height});
- if(lastRect.top === firstRect.top || lastRect.bottom === firstRect.bottom) {
- overlayMiddle.style.display = overlayBottom.style.display = "none"
- }else {
- setRect(overlayBottom, {left:fillerRect.left, top:lastRect.top, width:Math.max(0, lastRect.right - fillerRect.left), height:lastRect.height});
- setRect(overlayMiddle, {left:fillerRect.left, top:firstRect.top + firstRect.height, width:Math.max(0, parseFloat(overlayTop.style.left) + parseFloat(overlayTop.style.width) - parseFloat(overlayBottom.style.left)), height:Math.max(0, lastRect.top - firstRect.bottom)})
+ if(shouldUpdateCaretSize || (shouldCheckCaretVisibility || hasStateChanged("visibility"))) {
+ updateCaretHeightAndPosition()
+ }
+ if(shouldCheckCaretVisibility) {
+ ensureVisible()
}
- firstRange.detach();
- lastRange.detach();
- fillerRange.detach()
}
- }
- function rerender() {
- addOverlays();
- if(cursor.getSelectionType() === ops.OdtCursor.RangeSelection) {
- showOverlays(true);
- repositionOverlays(cursor.getSelectedRange())
- }else {
- showOverlays(false)
+ if(hasStateChanged("isFocused")) {
+ avatar.markAsFocussed(state.isFocused)
}
+ saveState();
+ shouldResetBlink = false;
+ shouldCheckCaretVisibility = false;
+ shouldUpdateCaretSize = false
}
- this.rerender = rerender;
- this.show = rerender;
+ this.handleUpdate = function() {
+ shouldUpdateCaretSize = true;
+ if(state.visibility !== "hidden") {
+ state.visibility = "hidden";
+ span.style.visibility = "hidden"
+ }
+ redrawTask.trigger()
+ };
+ this.refreshCursorBlinking = function() {
+ shouldResetBlink = true;
+ redrawTask.trigger()
+ };
+ this.setFocus = function() {
+ state.isFocused = true;
+ redrawTask.trigger()
+ };
+ this.removeFocus = function() {
+ state.isFocused = false;
+ redrawTask.trigger()
+ };
+ this.show = function() {
+ state.isShown = true;
+ redrawTask.trigger()
+ };
this.hide = function() {
- showOverlays(false)
+ state.isShown = false;
+ redrawTask.trigger()
};
- this.visible = function() {
- return isVisible
+ this.setAvatarImageUrl = function(url) {
+ avatar.setImageUrl(url)
};
- function handleCursorMove(movedCursor) {
- if(movedCursor === cursor) {
- rerender()
+ this.setColor = function(newColor) {
+ span.style.borderColor = newColor;
+ avatar.setColor(newColor)
+ };
+ this.getCursor = function() {
+ return cursor
+ };
+ this.getFocusElement = function() {
+ return span
+ };
+ this.toggleHandleVisibility = function() {
+ if(avatar.isVisible()) {
+ avatar.hide()
+ }else {
+ avatar.show()
}
+ };
+ this.showHandle = function() {
+ avatar.show()
+ };
+ this.hideHandle = function() {
+ avatar.hide()
+ };
+ this.setOverlayElement = function(element) {
+ overlayElement = element;
+ shouldUpdateCaretSize = true;
+ redrawTask.trigger()
+ };
+ this.ensureVisible = function() {
+ shouldCheckCaretVisibility = true;
+ redrawTask.trigger()
+ };
+ function destroy(callback) {
+ cursorNode.removeChild(span);
+ callback()
}
this.destroy = function(callback) {
- root.removeChild(overlayTop);
- root.removeChild(overlayMiddle);
- root.removeChild(overlayBottom);
- cursor.getOdtDocument().unsubscribe(ops.OdtDocument.signalCursorMoved, handleCursorMove);
- callback()
+ var cleanup = [redrawTask.destroy, blinkTask.destroy, avatar.destroy, destroy];
+ async.destroyAll(cleanup, callback)
};
function init() {
- var editinfons = "urn:webodf:names:editinfo", memberid = cursor.getMemberId();
- addOverlays();
- overlayTop.setAttributeNS(editinfons, "editinfo:memberid", memberid);
- overlayMiddle.setAttributeNS(editinfons, "editinfo:memberid", memberid);
- overlayBottom.setAttributeNS(editinfons, "editinfo:memberid", memberid);
- overlayTop.className = overlayMiddle.className = overlayBottom.className = "selectionOverlay";
- cursor.getOdtDocument().subscribe(ops.OdtDocument.signalCursorMoved, handleCursorMove)
+ var dom = cursor.getDocument().getDOMDocument(), htmlns = dom.documentElement.namespaceURI;
+ span = (dom.createElementNS(htmlns, "span"));
+ span.className = "caret";
+ span.style.top = DEFAULT_CARET_TOP;
+ cursorNode = cursor.getNode();
+ cursorNode.appendChild(span);
+ avatar = new gui.Avatar(cursorNode, avatarInitiallyVisible);
+ redrawTask = new core.ScheduledTask(updateCaret, 0);
+ blinkTask = new core.ScheduledTask(blinkCaret, BLINK_PERIOD_MS);
+ redrawTask.triggerImmediate()
}
init()
};
@@ -15959,72 +12899,84 @@ gui.SelectionView = function SelectionView(cursor) {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("gui.SelectionView");
-gui.SelectionViewManager = function SelectionViewManager() {
- var selectionViews = {};
- function getSelectionView(memberId) {
- return selectionViews.hasOwnProperty(memberId) ? selectionViews[memberId] : null
- }
- this.getSelectionView = getSelectionView;
- function getSelectionViews() {
- return Object.keys(selectionViews).map(function(memberid) {
- return selectionViews[memberid]
- })
- }
- this.getSelectionViews = getSelectionViews;
- function removeSelectionView(memberId) {
- if(selectionViews.hasOwnProperty(memberId)) {
- selectionViews[memberId].destroy(function() {
- });
- delete selectionViews[memberId]
+odf.TextSerializer = function TextSerializer() {
+ var self = this, odfUtils = new odf.OdfUtils;
+ function serializeNode(node) {
+ var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, nodeType = node.nodeType, child;
+ if((accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) && odfUtils.isTextContentContainingNode(node)) {
+ child = node.firstChild;
+ while(child) {
+ s += serializeNode(child);
+ child = child.nextSibling
+ }
}
- }
- this.removeSelectionView = removeSelectionView;
- function hideSelectionView(memberId) {
- if(selectionViews.hasOwnProperty(memberId)) {
- selectionViews[memberId].hide()
+ if(accept === NodeFilter.FILTER_ACCEPT) {
+ if(nodeType === Node.ELEMENT_NODE && odfUtils.isParagraph(node)) {
+ s += "\n"
+ }else {
+ if(nodeType === Node.TEXT_NODE && node.textContent) {
+ s += node.textContent
+ }
+ }
}
+ return s
}
- this.hideSelectionView = hideSelectionView;
- function showSelectionView(memberId) {
- if(selectionViews.hasOwnProperty(memberId)) {
- selectionViews[memberId].show()
+ this.filter = null;
+ this.writeToString = function(node) {
+ var plainText;
+ if(!node) {
+ return""
}
+ plainText = serializeNode(node);
+ if(plainText[plainText.length - 1] === "\n") {
+ plainText = plainText.substr(0, plainText.length - 1)
+ }
+ return plainText
}
- this.showSelectionView = showSelectionView;
- this.rerenderSelectionViews = function() {
- Object.keys(selectionViews).forEach(function(memberId) {
- if(selectionViews[memberId].visible()) {
- selectionViews[memberId].rerender()
- }
- })
- };
- this.registerCursor = function(cursor, virtualSelectionsInitiallyVisible) {
- var memberId = cursor.getMemberId(), selectionView = new gui.SelectionView(cursor);
- if(virtualSelectionsInitiallyVisible) {
- selectionView.show()
- }else {
- selectionView.hide()
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.MimeDataExporter = function MimeDataExporter() {
+ var textSerializer, filter;
+ this.exportRangeToDataTransfer = function(dataTransfer, range) {
+ var document = range.startContainer.ownerDocument, serializedFragment, fragmentContainer;
+ fragmentContainer = document.createElement("span");
+ fragmentContainer.appendChild(range.cloneContents());
+ serializedFragment = textSerializer.writeToString(fragmentContainer);
+ try {
+ dataTransfer.setData("text/plain", serializedFragment)
+ }catch(e) {
+ dataTransfer.setData("Text", serializedFragment)
}
- selectionViews[memberId] = selectionView;
- return selectionView
};
- this.destroy = function(callback) {
- var selectionViewArray = getSelectionViews();
- (function destroySelectionView(i, err) {
- if(err) {
- callback(err)
- }else {
- if(i < selectionViewArray.length) {
- selectionViewArray[i].destroy(function(err) {
- destroySelectionView(i + 1, err)
- })
- }else {
- callback()
- }
- }
- })(0, undefined)
+ function init() {
+ textSerializer = new odf.TextSerializer;
+ filter = new odf.OdfNodeFilter;
+ textSerializer.filter = filter
}
+ init()
};
/*
@@ -16063,170 +13015,25 @@ gui.SelectionViewManager = function SelectionViewManager() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("gui.UndoManager");
-runtime.loadClass("gui.UndoStateRules");
-gui.TrivialUndoManager = function TrivialUndoManager(defaultRules) {
- var self = this, cursorns = "urn:webodf:names:cursor", domUtils = new core.DomUtils, initialDoc, initialState = [], playFunc, odtDocument, currentUndoState = [], undoStates = [], redoStates = [], eventNotifier = new core.EventNotifier([gui.UndoManager.signalUndoStackChanged, gui.UndoManager.signalUndoStateCreated, gui.UndoManager.signalUndoStateModified, gui.TrivialUndoManager.signalDocumentRootReplaced]), undoRules = defaultRules || new gui.UndoStateRules;
- function emitStackChange() {
- eventNotifier.emit(gui.UndoManager.signalUndoStackChanged, {undoAvailable:self.hasUndoStates(), redoAvailable:self.hasRedoStates()})
- }
- function mostRecentUndoState() {
- return undoStates[undoStates.length - 1]
- }
- function completeCurrentUndoState() {
- if(currentUndoState !== initialState && currentUndoState !== mostRecentUndoState()) {
- undoStates.push(currentUndoState)
- }
- }
- function removeNode(node) {
- var sibling = node.previousSibling || node.nextSibling;
- node.parentNode.removeChild(node);
- domUtils.normalizeTextNodes(sibling)
- }
- function removeCursors(root) {
- domUtils.getElementsByTagNameNS(root, cursorns, "cursor").forEach(removeNode);
- domUtils.getElementsByTagNameNS(root, cursorns, "anchor").forEach(removeNode)
- }
- function values(obj) {
- return Object.keys(obj).map(function(key) {
- return obj[key]
- })
- }
- function extractCursorStates(undoStates) {
- var addCursor = {}, moveCursor = {}, requiredAddOps = {}, remainingAddOps, operations = undoStates.pop();
- odtDocument.getCursors().forEach(function(cursor) {
- requiredAddOps[cursor.getMemberId()] = true
- });
- remainingAddOps = Object.keys(requiredAddOps).length;
- function processOp(op) {
- var spec = op.spec();
- if(!requiredAddOps[spec.memberid]) {
- return
- }
- switch(spec.optype) {
- case "AddCursor":
- if(!addCursor[spec.memberid]) {
- addCursor[spec.memberid] = op;
- delete requiredAddOps[spec.memberid];
- remainingAddOps -= 1
- }
- break;
- case "MoveCursor":
- if(!moveCursor[spec.memberid]) {
- moveCursor[spec.memberid] = op
- }
- break
- }
- }
- while(operations && remainingAddOps > 0) {
- operations.reverse();
- operations.forEach(processOp);
- operations = undoStates.pop()
- }
- return values(addCursor).concat(values(moveCursor))
- }
- this.subscribe = function(signal, callback) {
- eventNotifier.subscribe(signal, callback)
- };
- this.unsubscribe = function(signal, callback) {
- eventNotifier.unsubscribe(signal, callback)
- };
- this.hasUndoStates = function() {
- return undoStates.length > 0
- };
- this.hasRedoStates = function() {
- return redoStates.length > 0
- };
- this.setOdtDocument = function(newDocument) {
- odtDocument = newDocument
- };
- this.resetInitialState = function() {
- undoStates.length = 0;
- redoStates.length = 0;
- initialState.length = 0;
- currentUndoState.length = 0;
- initialDoc = null;
- emitStackChange()
- };
- this.saveInitialState = function() {
- var odfContainer = odtDocument.getOdfCanvas().odfContainer(), annotationViewManager = odtDocument.getOdfCanvas().getAnnotationViewManager();
- if(annotationViewManager) {
- annotationViewManager.forgetAnnotations()
+gui.Clipboard = function Clipboard(mimeDataExporter) {
+ this.setDataFromRange = function(e, range) {
+ var result, clipboard = e.clipboardData, window = runtime.getWindow();
+ if(!clipboard && window) {
+ clipboard = window.clipboardData
}
- initialDoc = odfContainer.rootElement.cloneNode(true);
- odtDocument.getOdfCanvas().refreshAnnotations();
- removeCursors(initialDoc);
- completeCurrentUndoState();
- undoStates.unshift(initialState);
- currentUndoState = initialState = extractCursorStates(undoStates);
- undoStates.length = 0;
- redoStates.length = 0;
- emitStackChange()
- };
- this.setPlaybackFunction = function(playback_func) {
- playFunc = playback_func
- };
- this.onOperationExecuted = function(op) {
- redoStates.length = 0;
- if(undoRules.isEditOperation(op) && currentUndoState === initialState || !undoRules.isPartOfOperationSet(op, currentUndoState)) {
- completeCurrentUndoState();
- currentUndoState = [op];
- undoStates.push(currentUndoState);
- eventNotifier.emit(gui.UndoManager.signalUndoStateCreated, {operations:currentUndoState});
- emitStackChange()
+ if(clipboard) {
+ result = true;
+ mimeDataExporter.exportRangeToDataTransfer((clipboard), range);
+ e.preventDefault()
}else {
- currentUndoState.push(op);
- eventNotifier.emit(gui.UndoManager.signalUndoStateModified, {operations:currentUndoState})
- }
- };
- this.moveForward = function(states) {
- var moved = 0, redoOperations;
- while(states && redoStates.length) {
- redoOperations = redoStates.pop();
- undoStates.push(redoOperations);
- redoOperations.forEach(playFunc);
- states -= 1;
- moved += 1
- }
- if(moved) {
- currentUndoState = mostRecentUndoState();
- emitStackChange()
- }
- return moved
- };
- this.moveBackward = function(states) {
- var odfCanvas = odtDocument.getOdfCanvas(), odfContainer = odfCanvas.odfContainer(), moved = 0;
- while(states && undoStates.length) {
- redoStates.push(undoStates.pop());
- states -= 1;
- moved += 1
- }
- if(moved) {
- odfContainer.setRootElement(initialDoc.cloneNode(true));
- odfCanvas.setOdfContainer(odfContainer, true);
- eventNotifier.emit(gui.TrivialUndoManager.signalDocumentRootReplaced, {});
- odtDocument.getCursors().forEach(function(cursor) {
- odtDocument.removeCursor(cursor.getMemberId())
- });
- initialState.forEach(playFunc);
- undoStates.forEach(function(ops) {
- ops.forEach(playFunc)
- });
- odfCanvas.refreshCSS();
- currentUndoState = mostRecentUndoState() || initialState;
- emitStackChange()
+ result = false
}
- return moved
+ return result
}
};
-gui.TrivialUndoManager.signalDocumentRootReplaced = "documentRootReplaced";
-(function() {
- return gui.TrivialUndoManager
-})();
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2014 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -16261,167 +13068,54 @@ gui.TrivialUndoManager.signalDocumentRootReplaced = "documentRootReplaced";
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.TrivialOperationRouter");
-runtime.loadClass("ops.OperationFactory");
-runtime.loadClass("ops.OdtDocument");
-ops.Session = function Session(odfCanvas) {
- var self = this, operationFactory = new ops.OperationFactory, odtDocument = new ops.OdtDocument(odfCanvas), operationRouter = null;
- this.setOperationFactory = function(opFactory) {
- operationFactory = opFactory;
- if(operationRouter) {
- operationRouter.setOperationFactory(operationFactory)
- }
- };
- this.setOperationRouter = function(opRouter) {
- operationRouter = opRouter;
- opRouter.setPlaybackFunction(function(op) {
- if(op.execute(odtDocument)) {
- odtDocument.emit(ops.OdtDocument.signalOperationExecuted, op);
- return true
- }
- return false
- });
- opRouter.setOperationFactory(operationFactory)
- };
- this.getOperationFactory = function() {
- return operationFactory
- };
- this.getOdtDocument = function() {
- return odtDocument
- };
- this.enqueue = function(ops) {
- operationRouter.push(ops)
- };
- this.close = function(callback) {
- operationRouter.close(function(err) {
- if(err) {
- callback(err)
- }else {
- odtDocument.close(callback)
- }
- })
- };
- this.destroy = function(callback) {
- odtDocument.destroy(callback)
- };
- function init() {
- self.setOperationRouter(new ops.TrivialOperationRouter)
- }
- init()
-};
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- This file is part of WebODF.
-
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
-
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
-
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("core.EventNotifier");
-runtime.loadClass("core.PositionFilter");
-runtime.loadClass("ops.Session");
-runtime.loadClass("ops.OpAddAnnotation");
-runtime.loadClass("ops.OpRemoveAnnotation");
-runtime.loadClass("gui.SelectionMover");
-gui.AnnotationController = function AnnotationController(session, inputMemberId) {
- var odtDocument = session.getOdtDocument(), isAnnotatable = false, eventNotifier = new core.EventNotifier([gui.AnnotationController.annotatableChanged]), officens = odf.Namespaces.officens;
- function isWithinAnnotation(node, container) {
- while(node && node !== container) {
- if(node.namespaceURI === officens && node.localName === "annotation") {
- return true
- }
- node = node.parentNode
- }
- return false
- }
- function updatedCachedValues() {
- var cursor = odtDocument.getCursor(inputMemberId), cursorNode = cursor && cursor.getNode(), newIsAnnotatable = false;
- if(cursorNode) {
- newIsAnnotatable = !isWithinAnnotation(cursorNode, odtDocument.getRootNode())
- }
- if(newIsAnnotatable !== isAnnotatable) {
- isAnnotatable = newIsAnnotatable;
- eventNotifier.emit(gui.AnnotationController.annotatableChanged, isAnnotatable)
- }
- }
- function onCursorAdded(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
+gui.StyleSummary = function StyleSummary(styles) {
+ var propertyValues = {};
+ function getPropertyValues(section, propertyName) {
+ var cacheKey = section + "|" + propertyName, values;
+ if(!propertyValues.hasOwnProperty(cacheKey)) {
+ values = [];
+ styles.forEach(function(style) {
+ var styleSection = style[section], value = styleSection && styleSection[propertyName];
+ if(values.indexOf(value) === -1) {
+ values.push(value)
+ }
+ });
+ propertyValues[cacheKey] = values
}
+ return propertyValues[cacheKey]
}
- function onCursorRemoved(memberId) {
- if(memberId === inputMemberId) {
- updatedCachedValues()
+ this.getPropertyValues = getPropertyValues;
+ function lazilyLoaded(section, propertyName, acceptedPropertyValues) {
+ return function() {
+ var existingPropertyValues = getPropertyValues(section, propertyName);
+ return acceptedPropertyValues.length >= existingPropertyValues.length && existingPropertyValues.every(function(v) {
+ return acceptedPropertyValues.indexOf(v) !== -1
+ })
}
}
- function onCursorMoved(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
- }
+ function getCommonValue(section, propertyName) {
+ var values = getPropertyValues(section, propertyName);
+ return values.length === 1 ? values[0] : undefined
}
- this.isAnnotatable = function() {
- return isAnnotatable
- };
- this.addAnnotation = function() {
- var op = new ops.OpAddAnnotation, selection = odtDocument.getCursorSelection(inputMemberId), length = selection.length, position = selection.position;
- if(!isAnnotatable) {
- return
- }
- position = length >= 0 ? position : position + length;
- length = Math.abs(length);
- op.init({memberid:inputMemberId, position:position, length:length, name:inputMemberId + Date.now()});
- session.enqueue([op])
- };
- this.removeAnnotation = function(annotationNode) {
- var startStep, endStep, op, moveCursor;
- startStep = odtDocument.convertDomPointToCursorStep(annotationNode, 0) + 1;
- endStep = odtDocument.convertDomPointToCursorStep(annotationNode, annotationNode.childNodes.length);
- op = new ops.OpRemoveAnnotation;
- op.init({memberid:inputMemberId, position:startStep, length:endStep - startStep});
- moveCursor = new ops.OpMoveCursor;
- moveCursor.init({memberid:inputMemberId, position:startStep > 0 ? startStep - 1 : startStep, length:0});
- session.enqueue([op, moveCursor])
- };
- this.subscribe = function(eventid, cb) {
- eventNotifier.subscribe(eventid, cb)
- };
- this.unsubscribe = function(eventid, cb) {
- eventNotifier.unsubscribe(eventid, cb)
- };
- this.destroy = function(callback) {
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- callback()
+ this.getCommonValue = getCommonValue;
+ this.isBold = lazilyLoaded("style:text-properties", "fo:font-weight", ["bold"]);
+ this.isItalic = lazilyLoaded("style:text-properties", "fo:font-style", ["italic"]);
+ this.hasUnderline = lazilyLoaded("style:text-properties", "style:text-underline-style", ["solid"]);
+ this.hasStrikeThrough = lazilyLoaded("style:text-properties", "style:text-line-through-style", ["solid"]);
+ this.fontSize = function() {
+ var stringFontSize = getCommonValue("style:text-properties", "fo:font-size");
+ return(stringFontSize && parseFloat(stringFontSize))
};
- function init() {
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- updatedCachedValues()
- }
- init()
+ this.fontName = function() {
+ return getCommonValue("style:text-properties", "style:font-name")
+ };
+ this.isAlignedLeft = lazilyLoaded("style:paragraph-properties", "fo:text-align", ["left", "start"]);
+ this.isAlignedCenter = lazilyLoaded("style:paragraph-properties", "fo:text-align", ["center"]);
+ this.isAlignedRight = lazilyLoaded("style:paragraph-properties", "fo:text-align", ["right", "end"]);
+ this.isAlignedJustified = lazilyLoaded("style:paragraph-properties", "fo:text-align", ["justify"]);
+ this.text = {isBold:this.isBold, isItalic:this.isItalic, hasUnderline:this.hasUnderline, hasStrikeThrough:this.hasStrikeThrough, fontSize:this.fontSize, fontName:this.fontName};
+ this.paragraph = {isAlignedLeft:this.isAlignedLeft, isAlignedCenter:this.isAlignedCenter, isAlignedRight:this.isAlignedRight, isAlignedJustified:this.isAlignedJustified}
};
-gui.AnnotationController.annotatableChanged = "annotatable/changed";
-(function() {
- return gui.AnnotationController
-})();
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -16459,86 +13153,214 @@ gui.AnnotationController.annotatableChanged = "annotatable/changed";
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.EventNotifier");
-runtime.loadClass("core.Utils");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("ops.OpAddStyle");
-runtime.loadClass("ops.OpSetParagraphStyle");
-runtime.loadClass("gui.StyleHelper");
-gui.DirectParagraphStyler = function DirectParagraphStyler(session, inputMemberId, objectNameGenerator) {
- var odtDocument = session.getOdtDocument(), utils = new core.Utils, odfUtils = new odf.OdfUtils, styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), eventNotifier = new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]), isAlignedLeftValue, isAlignedCenterValue, isAlignedRightValue, isAlignedJustifiedValue;
- function updatedCachedValues() {
- var cursor = odtDocument.getCursor(inputMemberId), range = cursor && cursor.getSelectedRange(), diffMap;
- function noteChange(oldValue, newValue, id) {
- if(oldValue !== newValue) {
- if(diffMap === undefined) {
- diffMap = {}
- }
- diffMap[id] = newValue
+gui.DirectFormattingController = function DirectFormattingController(session, inputMemberId, objectNameGenerator, directParagraphStylingEnabled) {
+ var self = this, odtDocument = session.getOdtDocument(), utils = new core.Utils, odfUtils = new odf.OdfUtils, eventNotifier = new core.EventNotifier([gui.DirectFormattingController.textStylingChanged, gui.DirectFormattingController.paragraphStylingChanged]), textns = odf.Namespaces.textns, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, directCursorStyleProperties, selectionAppliedStyles = [], selectionStylesSummary = new gui.StyleSummary(selectionAppliedStyles);
+ function getNodes(range) {
+ var container, nodes;
+ if(range.collapsed) {
+ container = range.startContainer;
+ if(container.hasChildNodes() && range.startOffset < container.childNodes.length) {
+ container = container.childNodes.item(range.startOffset)
}
- return newValue
- }
- isAlignedLeftValue = noteChange(isAlignedLeftValue, range ? styleHelper.isAlignedLeft(range) : false, "isAlignedLeft");
- isAlignedCenterValue = noteChange(isAlignedCenterValue, range ? styleHelper.isAlignedCenter(range) : false, "isAlignedCenter");
- isAlignedRightValue = noteChange(isAlignedRightValue, range ? styleHelper.isAlignedRight(range) : false, "isAlignedRight");
- isAlignedJustifiedValue = noteChange(isAlignedJustifiedValue, range ? styleHelper.isAlignedJustified(range) : false, "isAlignedJustified");
- if(diffMap) {
- eventNotifier.emit(gui.DirectParagraphStyler.paragraphStylingChanged, diffMap)
+ nodes = [container]
+ }else {
+ nodes = odfUtils.getTextNodes(range, true)
}
+ return nodes
}
- function onCursorAdded(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
+ function getSelectionAppliedStyles() {
+ var cursor = odtDocument.getCursor(inputMemberId), range = cursor && cursor.getSelectedRange(), nodes = range ? getNodes(range) : [], selectionStyles = odtDocument.getFormatting().getAppliedStyles(nodes);
+ if(selectionStyles[0] && directCursorStyleProperties) {
+ selectionStyles[0] = utils.mergeObjects(selectionStyles[0], (directCursorStyleProperties))
}
+ return selectionStyles
}
- function onCursorRemoved(memberId) {
- if(memberId === inputMemberId) {
- updatedCachedValues()
+ function createDiff(oldSummary, newSummary) {
+ var diffMap = {};
+ Object.keys(oldSummary).forEach(function(funcName) {
+ var oldValue = oldSummary[funcName](), newValue = newSummary[funcName]();
+ if(oldValue !== newValue) {
+ diffMap[funcName] = newValue
+ }
+ });
+ return diffMap
+ }
+ function updateSelectionStylesInfo() {
+ var textStyleDiff, paragraphStyleDiff, newSelectionStylesSummary;
+ selectionAppliedStyles = getSelectionAppliedStyles();
+ newSelectionStylesSummary = new gui.StyleSummary(selectionAppliedStyles);
+ textStyleDiff = createDiff(selectionStylesSummary.text, newSelectionStylesSummary.text);
+ paragraphStyleDiff = createDiff(selectionStylesSummary.paragraph, newSelectionStylesSummary.paragraph);
+ selectionStylesSummary = newSelectionStylesSummary;
+ if(Object.keys(textStyleDiff).length > 0) {
+ eventNotifier.emit(gui.DirectFormattingController.textStylingChanged, textStyleDiff)
+ }
+ if(Object.keys(paragraphStyleDiff).length > 0) {
+ eventNotifier.emit(gui.DirectFormattingController.paragraphStylingChanged, paragraphStyleDiff)
}
}
- function onCursorMoved(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
+ function onCursorEvent(cursorOrId) {
+ var cursorMemberId = typeof cursorOrId === "string" ? cursorOrId : cursorOrId.getMemberId();
+ if(cursorMemberId === inputMemberId) {
+ updateSelectionStylesInfo()
}
}
function onParagraphStyleModified() {
- updatedCachedValues()
+ updateSelectionStylesInfo()
}
function onParagraphChanged(args) {
- var cursor = odtDocument.getCursor(inputMemberId);
- if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) {
- updatedCachedValues()
+ var cursor = odtDocument.getCursor(inputMemberId), p = args.paragraphElement;
+ if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === p) {
+ updateSelectionStylesInfo()
+ }
+ }
+ function toggle(predicate, toggleMethod) {
+ toggleMethod(!predicate());
+ return true
+ }
+ function formatTextSelection(textProperties) {
+ var selection = odtDocument.getCursorSelection(inputMemberId), op, properties = {"style:text-properties":textProperties};
+ if(selection.length !== 0) {
+ op = new ops.OpApplyDirectStyling;
+ op.init({memberid:inputMemberId, position:selection.position, length:selection.length, setProperties:properties});
+ session.enqueue([op])
+ }else {
+ directCursorStyleProperties = utils.mergeObjects(directCursorStyleProperties || {}, properties);
+ updateSelectionStylesInfo()
+ }
+ }
+ this.formatTextSelection = formatTextSelection;
+ function applyTextPropertyToSelection(propertyName, propertyValue) {
+ var textProperties = {};
+ textProperties[propertyName] = propertyValue;
+ formatTextSelection(textProperties)
+ }
+ this.createCursorStyleOp = function(position, length, useCachedStyle) {
+ var styleOp = null, properties = useCachedStyle ? selectionAppliedStyles[0] : directCursorStyleProperties;
+ if(properties && properties["style:text-properties"]) {
+ styleOp = new ops.OpApplyDirectStyling;
+ styleOp.init({memberid:inputMemberId, position:position, length:length, setProperties:{"style:text-properties":properties["style:text-properties"]}});
+ directCursorStyleProperties = null;
+ updateSelectionStylesInfo()
+ }
+ return styleOp
+ };
+ function clearCursorStyle(op) {
+ var spec = op.spec();
+ if(directCursorStyleProperties && spec.memberid === inputMemberId) {
+ if(spec.optype !== "SplitParagraph") {
+ directCursorStyleProperties = null;
+ updateSelectionStylesInfo()
+ }
}
}
+ function setBold(checked) {
+ var value = checked ? "bold" : "normal";
+ applyTextPropertyToSelection("fo:font-weight", value)
+ }
+ this.setBold = setBold;
+ function setItalic(checked) {
+ var value = checked ? "italic" : "normal";
+ applyTextPropertyToSelection("fo:font-style", value)
+ }
+ this.setItalic = setItalic;
+ function setHasUnderline(checked) {
+ var value = checked ? "solid" : "none";
+ applyTextPropertyToSelection("style:text-underline-style", value)
+ }
+ this.setHasUnderline = setHasUnderline;
+ function setHasStrikethrough(checked) {
+ var value = checked ? "solid" : "none";
+ applyTextPropertyToSelection("style:text-line-through-style", value)
+ }
+ this.setHasStrikethrough = setHasStrikethrough;
+ function setFontSize(value) {
+ applyTextPropertyToSelection("fo:font-size", value + "pt")
+ }
+ this.setFontSize = setFontSize;
+ function setFontName(value) {
+ applyTextPropertyToSelection("style:font-name", value)
+ }
+ this.setFontName = setFontName;
+ this.getAppliedStyles = function() {
+ return selectionAppliedStyles
+ };
+ this.toggleBold = toggle.bind(self, function() {
+ return selectionStylesSummary.isBold()
+ }, setBold);
+ this.toggleItalic = toggle.bind(self, function() {
+ return selectionStylesSummary.isItalic()
+ }, setItalic);
+ this.toggleUnderline = toggle.bind(self, function() {
+ return selectionStylesSummary.hasUnderline()
+ }, setHasUnderline);
+ this.toggleStrikethrough = toggle.bind(self, function() {
+ return selectionStylesSummary.hasStrikeThrough()
+ }, setHasStrikethrough);
+ this.isBold = function() {
+ return selectionStylesSummary.isBold()
+ };
+ this.isItalic = function() {
+ return selectionStylesSummary.isItalic()
+ };
+ this.hasUnderline = function() {
+ return selectionStylesSummary.hasUnderline()
+ };
+ this.hasStrikeThrough = function() {
+ return selectionStylesSummary.hasStrikeThrough()
+ };
+ this.fontSize = function() {
+ return selectionStylesSummary.fontSize()
+ };
+ this.fontName = function() {
+ return selectionStylesSummary.fontName()
+ };
this.isAlignedLeft = function() {
- return isAlignedLeftValue
+ return selectionStylesSummary.isAlignedLeft()
};
this.isAlignedCenter = function() {
- return isAlignedCenterValue
+ return selectionStylesSummary.isAlignedCenter()
};
this.isAlignedRight = function() {
- return isAlignedRightValue
+ return selectionStylesSummary.isAlignedRight()
};
this.isAlignedJustified = function() {
- return isAlignedJustifiedValue
+ return selectionStylesSummary.isAlignedJustified()
};
function roundUp(step) {
return step === ops.StepsTranslator.NEXT_STEP
}
+ function getOwnProperty(obj, key) {
+ return obj.hasOwnProperty(key) ? obj[key] : undefined
+ }
function applyParagraphDirectStyling(applyDirectStyling) {
- var range = odtDocument.getCursor(inputMemberId).getSelectedRange(), paragraphs = odfUtils.getParagraphElements(range), formatting = odtDocument.getFormatting();
+ var range = odtDocument.getCursor(inputMemberId).getSelectedRange(), paragraphs = odfUtils.getParagraphElements(range), formatting = odtDocument.getFormatting(), operations = [], derivedStyleNames = {}, defaultStyleName;
paragraphs.forEach(function(paragraph) {
- var paragraphStartPoint = odtDocument.convertDomPointToCursorStep(paragraph, 0, roundUp), paragraphStyleName = paragraph.getAttributeNS(odf.Namespaces.textns, "style-name"), newParagraphStyleName = objectNameGenerator.generateStyleName(), opAddStyle, opSetParagraphStyle, paragraphProperties;
+ var paragraphStartPoint = odtDocument.convertDomPointToCursorStep(paragraph, 0, roundUp), paragraphStyleName = paragraph.getAttributeNS(odf.Namespaces.textns, "style-name"), newParagraphStyleName, opAddStyle, opSetParagraphStyle, paragraphProperties;
if(paragraphStyleName) {
- paragraphProperties = formatting.createDerivedStyleObject(paragraphStyleName, "paragraph", {})
+ newParagraphStyleName = getOwnProperty(derivedStyleNames, paragraphStyleName)
+ }else {
+ newParagraphStyleName = defaultStyleName
+ }
+ if(!newParagraphStyleName) {
+ newParagraphStyleName = objectNameGenerator.generateStyleName();
+ if(paragraphStyleName) {
+ derivedStyleNames[paragraphStyleName] = newParagraphStyleName;
+ paragraphProperties = formatting.createDerivedStyleObject(paragraphStyleName, "paragraph", {})
+ }else {
+ defaultStyleName = newParagraphStyleName;
+ paragraphProperties = {}
+ }
+ paragraphProperties = applyDirectStyling(paragraphProperties);
+ opAddStyle = new ops.OpAddStyle;
+ opAddStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName.toString(), styleFamily:"paragraph", isAutomaticStyle:true, setProperties:paragraphProperties});
+ operations.push(opAddStyle)
}
- paragraphProperties = applyDirectStyling(paragraphProperties || {});
- opAddStyle = new ops.OpAddStyle;
- opAddStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName, styleFamily:"paragraph", isAutomaticStyle:true, setProperties:paragraphProperties});
opSetParagraphStyle = new ops.OpSetParagraphStyle;
- opSetParagraphStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName, position:paragraphStartPoint});
- session.enqueue([opAddStyle, opSetParagraphStyle])
- })
+ opSetParagraphStyle.init({memberid:inputMemberId, styleName:newParagraphStyleName.toString(), position:paragraphStartPoint});
+ operations.push(opSetParagraphStyle)
+ });
+ session.enqueue(operations)
}
function applySimpleParagraphDirectStyling(styleOverrides) {
applyParagraphDirectStyling(function(paragraphStyle) {
@@ -16565,7 +13387,13 @@ gui.DirectParagraphStyler = function DirectParagraphStyler(session, inputMemberI
return true
};
function modifyParagraphIndent(direction, paragraphStyle) {
- var tabStopDistance = odtDocument.getFormatting().getDefaultTabStopDistance(), paragraphProperties = paragraphStyle["style:paragraph-properties"], indentValue = paragraphProperties && paragraphProperties["fo:margin-left"], indent = indentValue && odfUtils.parseLength(indentValue), newIndent;
+ var tabStopDistance = odtDocument.getFormatting().getDefaultTabStopDistance(), paragraphProperties = paragraphStyle["style:paragraph-properties"], indentValue, indent, newIndent;
+ if(paragraphProperties) {
+ indentValue = paragraphProperties["fo:margin-left"];
+ if(indentValue) {
+ indent = odfUtils.parseLength(indentValue)
+ }
+ }
if(indent && indent.unit === tabStopDistance.unit) {
newIndent = indent.value + direction * tabStopDistance.value + indent.unit
}else {
@@ -16581,6 +13409,70 @@ gui.DirectParagraphStyler = function DirectParagraphStyler(session, inputMemberI
applyParagraphDirectStyling(modifyParagraphIndent.bind(null, -1));
return true
};
+ function isSelectionAtTheEndOfLastParagraph(range, paragraphNode) {
+ var iterator = gui.SelectionMover.createPositionIterator(paragraphNode), rootConstrainedFilter = new core.PositionFilterChain;
+ rootConstrainedFilter.addFilter(odtDocument.getPositionFilter());
+ rootConstrainedFilter.addFilter(odtDocument.createRootFilter(inputMemberId));
+ iterator.setUnfilteredPosition((range.endContainer), range.endOffset);
+ while(iterator.nextPosition()) {
+ if(rootConstrainedFilter.acceptPosition(iterator) === FILTER_ACCEPT) {
+ return odtDocument.getParagraphElement(iterator.getCurrentNode()) !== paragraphNode
+ }
+ }
+ return true
+ }
+ function isTextStyleDifferentFromFirstParagraph(range, paragraphNode) {
+ var textNodes = getNodes(range), textStyle = odtDocument.getFormatting().getAppliedStyles(textNodes)[0], paragraphStyle = odtDocument.getFormatting().getAppliedStylesForElement(paragraphNode);
+ if(!textStyle || (textStyle["style:family"] !== "text" || !textStyle["style:text-properties"])) {
+ return false
+ }
+ if(!paragraphStyle || !paragraphStyle["style:text-properties"]) {
+ return true
+ }
+ textStyle = (textStyle["style:text-properties"]);
+ paragraphStyle = (paragraphStyle["style:text-properties"]);
+ return!Object.keys(textStyle).every(function(key) {
+ return textStyle[key] === paragraphStyle[key]
+ })
+ }
+ this.createParagraphStyleOps = function(position) {
+ var cursor = odtDocument.getCursor(inputMemberId), range = cursor.getSelectedRange(), operations = [], op, startNode, endNode, paragraphNode, properties, parentStyleName, styleName;
+ if(cursor.hasForwardSelection()) {
+ startNode = cursor.getAnchorNode();
+ endNode = cursor.getNode()
+ }else {
+ startNode = cursor.getNode();
+ endNode = cursor.getAnchorNode()
+ }
+ paragraphNode = (odtDocument.getParagraphElement(endNode));
+ runtime.assert(Boolean(paragraphNode), "DirectFormattingController: Cursor outside paragraph");
+ if(!isSelectionAtTheEndOfLastParagraph(range, paragraphNode)) {
+ return operations
+ }
+ if(endNode !== startNode) {
+ paragraphNode = (odtDocument.getParagraphElement(startNode))
+ }
+ if(!directCursorStyleProperties && !isTextStyleDifferentFromFirstParagraph(range, paragraphNode)) {
+ return operations
+ }
+ properties = selectionAppliedStyles[0];
+ if(!properties) {
+ return operations
+ }
+ parentStyleName = paragraphNode.getAttributeNS(textns, "style-name");
+ if(parentStyleName) {
+ properties = {"style:text-properties":properties["style:text-properties"]};
+ properties = odtDocument.getFormatting().createDerivedStyleObject(parentStyleName, "paragraph", properties)
+ }
+ styleName = objectNameGenerator.generateStyleName();
+ op = new ops.OpAddStyle;
+ op.init({memberid:inputMemberId, styleName:styleName, styleFamily:"paragraph", isAutomaticStyle:true, setProperties:properties});
+ operations.push(op);
+ op = new ops.OpSetParagraphStyle;
+ op.init({memberid:inputMemberId, styleName:styleName, position:position});
+ operations.push(op);
+ return operations
+ };
this.subscribe = function(eventid, cb) {
eventNotifier.subscribe(eventid, cb)
};
@@ -16588,270 +13480,352 @@ gui.DirectParagraphStyler = function DirectParagraphStyler(session, inputMemberI
eventNotifier.unsubscribe(eventid, cb)
};
this.destroy = function(callback) {
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
+ odtDocument.unsubscribe(ops.Document.signalCursorAdded, onCursorEvent);
+ odtDocument.unsubscribe(ops.Document.signalCursorRemoved, onCursorEvent);
+ odtDocument.unsubscribe(ops.Document.signalCursorMoved, onCursorEvent);
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
+ odtDocument.unsubscribe(ops.OdtDocument.signalOperationEnd, clearCursorStyle);
callback()
};
+ function emptyFunction() {
+ }
function init() {
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
+ odtDocument.subscribe(ops.Document.signalCursorAdded, onCursorEvent);
+ odtDocument.subscribe(ops.Document.signalCursorRemoved, onCursorEvent);
+ odtDocument.subscribe(ops.Document.signalCursorMoved, onCursorEvent);
odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- updatedCachedValues()
+ odtDocument.subscribe(ops.OdtDocument.signalOperationEnd, clearCursorStyle);
+ updateSelectionStylesInfo();
+ if(!directParagraphStylingEnabled) {
+ self.alignParagraphCenter = emptyFunction;
+ self.alignParagraphJustified = emptyFunction;
+ self.alignParagraphLeft = emptyFunction;
+ self.alignParagraphRight = emptyFunction;
+ self.createParagraphStyleOps = function() {
+ return[]
+ };
+ self.indent = emptyFunction;
+ self.outdent = emptyFunction
+ }
}
init()
};
-gui.DirectParagraphStyler.paragraphStylingChanged = "paragraphStyling/changed";
+gui.DirectFormattingController.textStylingChanged = "textStyling/changed";
+gui.DirectFormattingController.paragraphStylingChanged = "paragraphStyling/changed";
(function() {
- return gui.DirectParagraphStyler
+ return gui.DirectFormattingController
})();
-/*
-
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
-
- @licstart
- The JavaScript code in this page is free software: you can redistribute it
- and/or modify it under the terms of the GNU Affero General Public License
- (GNU AGPL) as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version. The code is distributed
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this code. If not, see <http://www.gnu.org/licenses/>.
-
- As additional permission under GNU AGPL version 3 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU GPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- As a special exception to the AGPL, any HTML file which merely makes function
- calls to this code, and for that purpose includes it by reference shall be
- deemed a separate work for copyright law purposes. In addition, the copyright
- holders of this code give you permission to combine this code with free
- software libraries that are released under the GNU LGPL. You may copy and
- distribute such a system following the terms of the GNU AGPL for this code
- and the LGPL for the libraries. If you modify this code, you may extend this
- exception to your version of the code, but you are not obligated to do so.
- If you do not wish to do so, delete this exception statement from your
- version.
-
- This license applies to this entire compilation.
- @licend
- @source: http://www.webodf.org/
- @source: https://github.com/kogmbh/WebODF/
-*/
-runtime.loadClass("core.EventNotifier");
-runtime.loadClass("core.Utils");
-runtime.loadClass("ops.OpApplyDirectStyling");
-runtime.loadClass("gui.StyleHelper");
-gui.DirectTextStyler = function DirectTextStyler(session, inputMemberId) {
- var self = this, utils = new core.Utils, odtDocument = session.getOdtDocument(), styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), eventNotifier = new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]), directCursorStyleProperties, currentSelectionStyles = [], isBoldValue = false, isItalicValue = false, hasUnderlineValue = false, hasStrikeThroughValue = false, fontSizeValue, fontNameValue;
- function get(obj, keys) {
- var i = 0, key = keys[i];
- while(key && obj) {
- obj = obj[key];
- i += 1;
- key = keys[i]
- }
- return keys.length === i ? obj : undefined
- }
- function getCommonValue(objArray, keys) {
- var value = get(objArray[0], keys);
- return objArray.every(function(obj) {
- return value === get(obj, keys)
- }) ? value : undefined
- }
- function getAppliedStyles() {
- var cursor = odtDocument.getCursor(inputMemberId), range = cursor && cursor.getSelectedRange(), selectionStyles = range && styleHelper.getAppliedStyles(range) || [];
- if(selectionStyles[0] && directCursorStyleProperties) {
- selectionStyles[0] = utils.mergeObjects(selectionStyles[0], (directCursorStyleProperties))
+gui.HyperlinkClickHandler = function HyperlinkClickHandler(getRootNode) {
+ var webodfns = "urn:webodf:names:helper", links = "links", inactive = "inactive", None = gui.HyperlinkClickHandler.Modifier.None, Ctrl = gui.HyperlinkClickHandler.Modifier.Ctrl, Meta = gui.HyperlinkClickHandler.Modifier.Meta, odfUtils = new odf.OdfUtils, xpath = xmldom.XPath, modifier = None;
+ function getHyperlinkElement(node) {
+ while(node !== null) {
+ if(odfUtils.isHyperlink(node)) {
+ return(node)
+ }
+ if(odfUtils.isParagraph(node)) {
+ break
+ }
+ node = node.parentNode
}
- return selectionStyles
+ return null
}
- function updatedCachedValues() {
- var fontSize, diffMap;
- currentSelectionStyles = getAppliedStyles();
- function noteChange(oldValue, newValue, id) {
- if(oldValue !== newValue) {
- if(diffMap === undefined) {
- diffMap = {}
- }
- diffMap[id] = newValue
+ this.handleClick = function(e) {
+ var target = e.target || e.srcElement, modifierPressed, linkElement, url, rootNode, bookmarks;
+ if(e.ctrlKey) {
+ modifierPressed = Ctrl
+ }else {
+ if(e.metaKey) {
+ modifierPressed = Meta
}
- return newValue
}
- isBoldValue = noteChange(isBoldValue, currentSelectionStyles ? styleHelper.isBold(currentSelectionStyles) : false, "isBold");
- isItalicValue = noteChange(isItalicValue, currentSelectionStyles ? styleHelper.isItalic(currentSelectionStyles) : false, "isItalic");
- hasUnderlineValue = noteChange(hasUnderlineValue, currentSelectionStyles ? styleHelper.hasUnderline(currentSelectionStyles) : false, "hasUnderline");
- hasStrikeThroughValue = noteChange(hasStrikeThroughValue, currentSelectionStyles ? styleHelper.hasStrikeThrough(currentSelectionStyles) : false, "hasStrikeThrough");
- fontSize = currentSelectionStyles && getCommonValue(currentSelectionStyles, ["style:text-properties", "fo:font-size"]);
- fontSizeValue = noteChange(fontSizeValue, fontSize && parseFloat(fontSize), "fontSize");
- fontNameValue = noteChange(fontNameValue, currentSelectionStyles && getCommonValue(currentSelectionStyles, ["style:text-properties", "style:font-name"]), "fontName");
- if(diffMap) {
- eventNotifier.emit(gui.DirectTextStyler.textStylingChanged, diffMap)
+ if(modifier !== None && modifier !== modifierPressed) {
+ return
}
- }
- function onCursorAdded(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
+ linkElement = getHyperlinkElement((target));
+ if(!linkElement) {
+ return
}
- }
- function onCursorRemoved(memberId) {
- if(memberId === inputMemberId) {
- updatedCachedValues()
+ url = odfUtils.getHyperlinkTarget(linkElement);
+ if(url === "") {
+ return
}
- }
- function onCursorMoved(cursor) {
- if(cursor.getMemberId() === inputMemberId) {
- updatedCachedValues()
+ if(url[0] === "#") {
+ url = url.substring(1);
+ rootNode = (getRootNode());
+ bookmarks = xpath.getODFElementsWithXPath(rootNode, "//text:bookmark-start[@text:name='" + url + "']", odf.Namespaces.lookupNamespaceURI);
+ if(bookmarks.length === 0) {
+ bookmarks = xpath.getODFElementsWithXPath(rootNode, "//text:bookmark[@text:name='" + url + "']", odf.Namespaces.lookupNamespaceURI)
+ }
+ if(bookmarks.length > 0) {
+ bookmarks[0].scrollIntoView(true)
+ }
+ }else {
+ runtime.getWindow().open(url)
}
- }
- function onParagraphStyleModified() {
- updatedCachedValues()
- }
- function onParagraphChanged(args) {
- var cursor = odtDocument.getCursor(inputMemberId);
- if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) {
- updatedCachedValues()
+ if(e.preventDefault) {
+ e.preventDefault()
+ }else {
+ e.returnValue = false
}
+ };
+ function showPointerCursor() {
+ getRootNode().removeAttributeNS(webodfns, links)
}
- function toggle(predicate, toggleMethod) {
- var cursor = odtDocument.getCursor(inputMemberId), appliedStyles;
- if(!cursor) {
- return false
- }
- appliedStyles = styleHelper.getAppliedStyles(cursor.getSelectedRange());
- toggleMethod(!predicate(appliedStyles));
- return true
+ this.showPointerCursor = showPointerCursor;
+ function showTextCursor() {
+ getRootNode().setAttributeNS(webodfns, links, inactive)
}
- function formatTextSelection(textProperties) {
- var selection = odtDocument.getCursorSelection(inputMemberId), op, properties = {"style:text-properties":textProperties};
- if(selection.length !== 0) {
- op = new ops.OpApplyDirectStyling;
- op.init({memberid:inputMemberId, position:selection.position, length:selection.length, setProperties:properties});
- session.enqueue([op])
+ this.showTextCursor = showTextCursor;
+ this.setModifier = function(value) {
+ modifier = value;
+ if(modifier !== None) {
+ showTextCursor()
}else {
- directCursorStyleProperties = utils.mergeObjects(directCursorStyleProperties || {}, properties);
- updatedCachedValues()
+ showPointerCursor()
}
}
- this.formatTextSelection = formatTextSelection;
- function applyTextPropertyToSelection(propertyName, propertyValue) {
- var textProperties = {};
- textProperties[propertyName] = propertyValue;
- formatTextSelection(textProperties)
+};
+gui.HyperlinkClickHandler.Modifier = {None:0, Ctrl:1, Meta:2};
+gui.HyperlinkController = function HyperlinkController(session, inputMemberId) {
+ var odfUtils = new odf.OdfUtils, odtDocument = session.getOdtDocument();
+ function addHyperlink(hyperlink, insertionText) {
+ var selection = odtDocument.getCursorSelection(inputMemberId), op = new ops.OpApplyHyperlink, operations = [];
+ if(selection.length === 0 || insertionText) {
+ insertionText = insertionText || hyperlink;
+ op = new ops.OpInsertText;
+ op.init({memberid:inputMemberId, position:selection.position, text:insertionText});
+ selection.length = insertionText.length;
+ operations.push(op)
+ }
+ op = new ops.OpApplyHyperlink;
+ op.init({memberid:inputMemberId, position:selection.position, length:selection.length, hyperlink:hyperlink});
+ operations.push(op);
+ session.enqueue(operations)
}
- this.createCursorStyleOp = function(position, length) {
- var styleOp = null;
- if(directCursorStyleProperties) {
- styleOp = new ops.OpApplyDirectStyling;
- styleOp.init({memberid:inputMemberId, position:position, length:length, setProperties:directCursorStyleProperties});
- directCursorStyleProperties = null;
- updatedCachedValues()
+ this.addHyperlink = addHyperlink;
+ function removeHyperlinks() {
+ var iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), selectedRange = odtDocument.getCursor(inputMemberId).getSelectedRange(), links = odfUtils.getHyperlinkElements(selectedRange), removeEntireLink = selectedRange.collapsed && links.length === 1, domRange = odtDocument.getDOMDocument().createRange(), operations = [], cursorRange, firstLink, lastLink, offset, op;
+ if(links.length === 0) {
+ return
}
- return styleOp
- };
- function clearCursorStyle(op) {
- var spec = op.spec();
- if(directCursorStyleProperties && spec.memberid === inputMemberId) {
- if(spec.optype !== "SplitParagraph") {
- directCursorStyleProperties = null;
- updatedCachedValues()
+ links.forEach(function(link) {
+ domRange.selectNodeContents(link);
+ cursorRange = odtDocument.convertDomToCursorRange({anchorNode:(domRange.startContainer), anchorOffset:domRange.startOffset, focusNode:(domRange.endContainer), focusOffset:domRange.endOffset});
+ op = new ops.OpRemoveHyperlink;
+ op.init({memberid:inputMemberId, position:cursorRange.position, length:cursorRange.length});
+ operations.push(op)
+ });
+ if(!removeEntireLink) {
+ firstLink = (links[0]);
+ if(selectedRange.comparePoint(firstLink, 0) === -1) {
+ domRange.setStart(firstLink, 0);
+ domRange.setEnd(selectedRange.startContainer, selectedRange.startOffset);
+ cursorRange = odtDocument.convertDomToCursorRange({anchorNode:(domRange.startContainer), anchorOffset:domRange.startOffset, focusNode:(domRange.endContainer), focusOffset:domRange.endOffset});
+ if(cursorRange.length > 0) {
+ op = new ops.OpApplyHyperlink;
+ (op).init({memberid:inputMemberId, position:cursorRange.position, length:cursorRange.length, hyperlink:odfUtils.getHyperlinkTarget(firstLink)});
+ operations.push(op)
+ }
+ }
+ lastLink = (links[links.length - 1]);
+ iterator.moveToEndOfNode(lastLink);
+ offset = iterator.unfilteredDomOffset();
+ if(selectedRange.comparePoint(lastLink, offset) === 1) {
+ domRange.setStart(selectedRange.endContainer, selectedRange.endOffset);
+ domRange.setEnd(lastLink, offset);
+ cursorRange = odtDocument.convertDomToCursorRange({anchorNode:(domRange.startContainer), anchorOffset:domRange.startOffset, focusNode:(domRange.endContainer), focusOffset:domRange.endOffset});
+ if(cursorRange.length > 0) {
+ op = new ops.OpApplyHyperlink;
+ (op).init({memberid:inputMemberId, position:cursorRange.position, length:cursorRange.length, hyperlink:odfUtils.getHyperlinkTarget(lastLink)});
+ operations.push(op)
+ }
}
}
+ session.enqueue(operations);
+ domRange.detach()
}
- function setBold(checked) {
- var value = checked ? "bold" : "normal";
- applyTextPropertyToSelection("fo:font-weight", value)
- }
- this.setBold = setBold;
- function setItalic(checked) {
- var value = checked ? "italic" : "normal";
- applyTextPropertyToSelection("fo:font-style", value)
+ this.removeHyperlinks = removeHyperlinks
+};
+gui.EventManager = function EventManager(odtDocument) {
+ var window = (runtime.getWindow()), bindToDirectHandler = {"beforecut":true, "beforepaste":true}, bindToWindow = {"mousedown":true, "mouseup":true, "focus":true}, eventDelegates = {}, eventTrap, canvasElement = odtDocument.getCanvas().getElement();
+ function EventDelegate() {
+ var self = this, recentEvents = [];
+ this.filters = [];
+ this.handlers = [];
+ this.handleEvent = function(e) {
+ if(recentEvents.indexOf(e) === -1) {
+ recentEvents.push(e);
+ if(self.filters.every(function(filter) {
+ return filter(e)
+ })) {
+ self.handlers.forEach(function(handler) {
+ handler(e)
+ })
+ }
+ runtime.setTimeout(function() {
+ recentEvents.splice(recentEvents.indexOf(e), 1)
+ }, 0)
+ }
+ }
}
- this.setItalic = setItalic;
- function setHasUnderline(checked) {
- var value = checked ? "solid" : "none";
- applyTextPropertyToSelection("style:text-underline-style", value)
+ function WindowScrollState(window) {
+ var x = window.scrollX, y = window.scrollY;
+ this.restore = function() {
+ if(window.scrollX !== x || window.scrollY !== y) {
+ window.scrollTo(x, y)
+ }
+ }
}
- this.setHasUnderline = setHasUnderline;
- function setHasStrikethrough(checked) {
- var value = checked ? "solid" : "none";
- applyTextPropertyToSelection("style:text-line-through-style", value)
+ function ElementScrollState(element) {
+ var top = element.scrollTop, left = element.scrollLeft;
+ this.restore = function() {
+ if(element.scrollTop !== top || element.scrollLeft !== left) {
+ element.scrollTop = top;
+ element.scrollLeft = left
+ }
+ }
}
- this.setHasStrikethrough = setHasStrikethrough;
- function setFontSize(value) {
- applyTextPropertyToSelection("fo:font-size", value + "pt")
+ function listenEvent(eventTarget, eventType, eventHandler) {
+ var onVariant = "on" + eventType, bound = false;
+ if(eventTarget.attachEvent) {
+ eventTarget.attachEvent(onVariant, eventHandler);
+ bound = true
+ }
+ if(!bound && eventTarget.addEventListener) {
+ eventTarget.addEventListener(eventType, eventHandler, false);
+ bound = true
+ }
+ if((!bound || bindToDirectHandler[eventType]) && eventTarget.hasOwnProperty(onVariant)) {
+ eventTarget[onVariant] = eventHandler
+ }
}
- this.setFontSize = setFontSize;
- function setFontName(value) {
- applyTextPropertyToSelection("style:font-name", value)
+ function getDelegateForEvent(eventName, shouldCreate) {
+ var delegate = eventDelegates[eventName] || null;
+ if(!delegate && shouldCreate) {
+ delegate = eventDelegates[eventName] = new EventDelegate;
+ if(bindToWindow[eventName]) {
+ listenEvent(window, eventName, delegate.handleEvent)
+ }
+ listenEvent(eventTrap, eventName, delegate.handleEvent);
+ listenEvent(canvasElement, eventName, delegate.handleEvent)
+ }
+ return delegate
}
- this.setFontName = setFontName;
- this.getAppliedStyles = function() {
- return currentSelectionStyles
+ this.addFilter = function(eventName, filter) {
+ var delegate = getDelegateForEvent(eventName, true);
+ delegate.filters.push(filter)
};
- this.toggleBold = toggle.bind(self, styleHelper.isBold, setBold);
- this.toggleItalic = toggle.bind(self, styleHelper.isItalic, setItalic);
- this.toggleUnderline = toggle.bind(self, styleHelper.hasUnderline, setHasUnderline);
- this.toggleStrikethrough = toggle.bind(self, styleHelper.hasStrikeThrough, setHasStrikethrough);
- this.isBold = function() {
- return isBoldValue
- };
- this.isItalic = function() {
- return isItalicValue
+ this.removeFilter = function(eventName, filter) {
+ var delegate = getDelegateForEvent(eventName, true), index = delegate.filters.indexOf(filter);
+ if(index !== -1) {
+ delegate.filters.splice(index, 1)
+ }
};
- this.hasUnderline = function() {
- return hasUnderlineValue
+ this.subscribe = function(eventName, handler) {
+ var delegate = getDelegateForEvent(eventName, true);
+ delegate.handlers.push(handler)
};
- this.hasStrikeThrough = function() {
- return hasStrikeThroughValue
+ this.unsubscribe = function(eventName, handler) {
+ var delegate = getDelegateForEvent(eventName, false), handlerIndex = delegate && delegate.handlers.indexOf(handler);
+ if(delegate && handlerIndex !== -1) {
+ delegate.handlers.splice(handlerIndex, 1)
+ }
};
- this.fontSize = function() {
- return fontSizeValue
+ function hasFocus() {
+ return odtDocument.getDOMDocument().activeElement === eventTrap
+ }
+ this.hasFocus = hasFocus;
+ function findScrollableParents(element) {
+ var scrollParents = [];
+ while(element) {
+ if(element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight) {
+ scrollParents.push(new ElementScrollState(element))
+ }
+ element = (element.parentNode)
+ }
+ scrollParents.push(new WindowScrollState(window));
+ return scrollParents
+ }
+ this.focus = function() {
+ var scrollParents;
+ if(!hasFocus()) {
+ scrollParents = findScrollableParents(eventTrap);
+ eventTrap.focus();
+ scrollParents.forEach(function(scrollParent) {
+ scrollParent.restore()
+ })
+ }
};
- this.fontName = function() {
- return fontNameValue
+ this.getEventTrap = function() {
+ return eventTrap
};
- this.subscribe = function(eventid, cb) {
- eventNotifier.subscribe(eventid, cb)
+ this.blur = function() {
+ if(hasFocus()) {
+ eventTrap.blur()
+ }
};
- this.unsubscribe = function(eventid, cb) {
- eventNotifier.unsubscribe(eventid, cb)
+ this.destroy = function(callback) {
+ eventTrap.parentNode.removeChild(eventTrap);
+ callback()
};
+ function init() {
+ var sizerElement = odtDocument.getOdfCanvas().getSizer(), doc = sizerElement.ownerDocument;
+ runtime.assert(Boolean(window), "EventManager requires a window object to operate correctly");
+ eventTrap = (doc.createElement("input"));
+ eventTrap.id = "eventTrap";
+ eventTrap.setAttribute("tabindex", -1);
+ sizerElement.appendChild(eventTrap)
+ }
+ init()
+};
+/*
+
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.IOSSafariSupport = function(eventManager) {
+ var window = runtime.getWindow(), eventTrap = eventManager.getEventTrap();
+ function suppressFocusScrollIfKeyboardOpen() {
+ if(window.innerHeight !== window.outerHeight) {
+ eventTrap.style.display = "none";
+ runtime.requestAnimationFrame(function() {
+ eventTrap.style.display = "block"
+ })
+ }
+ }
this.destroy = function(callback) {
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle);
+ eventManager.unsubscribe("focus", suppressFocusScrollIfKeyboardOpen);
+ eventTrap.removeAttribute("autocapitalize");
callback()
};
function init() {
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle);
- updatedCachedValues()
+ eventManager.subscribe("focus", suppressFocusScrollIfKeyboardOpen);
+ eventTrap.setAttribute("autocapitalize", "off")
}
init()
};
-gui.DirectTextStyler.textStylingChanged = "textStyling/changed";
-(function() {
- return gui.DirectTextStyler
-})();
-runtime.loadClass("odf.Namespaces");
-runtime.loadClass("odf.ObjectNameGenerator");
-gui.ImageManager = function ImageManager(session, inputMemberId, objectNameGenerator) {
+gui.ImageController = function ImageController(session, inputMemberId, objectNameGenerator) {
var cmPerPixel = 0.0264583333333334, fileExtensionByMimetype = {"image/gif":".gif", "image/jpeg":".jpg", "image/png":".png"}, textns = odf.Namespaces.textns, odtDocument = session.getOdtDocument(), formatting = odtDocument.getFormatting(), paragraphStyleToPageContentSizeMap = {};
function createAddGraphicsStyleOp(name) {
var op = new ops.OpAddStyle;
@@ -16913,6 +13887,313 @@ gui.ImageManager = function ImageManager(session, inputMemberId, objectNameGener
insertImageInternal(mimetype, content, newSize.width, newSize.height)
}
};
+gui.ImageSelector = function ImageSelector(odfCanvas) {
+ var svgns = odf.Namespaces.svgns, imageSelectorId = "imageSelector", selectorBorderWidth = 1, squareClassNames = ["topLeft", "topRight", "bottomRight", "bottomLeft", "topMiddle", "rightMiddle", "bottomMiddle", "leftMiddle"], document = odfCanvas.getElement().ownerDocument, hasSelection = false;
+ function createSelectorElement() {
+ var sizerElement = odfCanvas.getSizer(), selectorElement = (document.createElement("div"));
+ selectorElement.id = "imageSelector";
+ selectorElement.style.borderWidth = selectorBorderWidth + "px";
+ sizerElement.appendChild(selectorElement);
+ function createDiv(className) {
+ var squareElement = document.createElement("div");
+ squareElement.className = className;
+ selectorElement.appendChild(squareElement)
+ }
+ squareClassNames.forEach(createDiv);
+ return selectorElement
+ }
+ function getPosition(element, referenceElement) {
+ var rect = element.getBoundingClientRect(), refRect = referenceElement.getBoundingClientRect(), zoomLevel = odfCanvas.getZoomLevel();
+ return{left:(rect.left - refRect.left) / zoomLevel - selectorBorderWidth, top:(rect.top - refRect.top) / zoomLevel - selectorBorderWidth}
+ }
+ this.select = function(frameElement) {
+ var selectorElement = document.getElementById(imageSelectorId), position;
+ if(!selectorElement) {
+ selectorElement = createSelectorElement()
+ }
+ hasSelection = true;
+ position = getPosition(frameElement, (selectorElement.parentNode));
+ selectorElement.style.display = "block";
+ selectorElement.style.left = position.left + "px";
+ selectorElement.style.top = position.top + "px";
+ selectorElement.style.width = frameElement.getAttributeNS(svgns, "width");
+ selectorElement.style.height = frameElement.getAttributeNS(svgns, "height")
+ };
+ this.clearSelection = function() {
+ var selectorElement;
+ if(hasSelection) {
+ selectorElement = document.getElementById(imageSelectorId);
+ if(selectorElement) {
+ selectorElement.style.display = "none"
+ }
+ }
+ hasSelection = false
+ };
+ this.isSelectorElement = function(node) {
+ var selectorElement = document.getElementById(imageSelectorId);
+ if(!selectorElement) {
+ return false
+ }
+ return node === selectorElement || node.parentNode === selectorElement
+ }
+};
+(function() {
+ function DetectSafariCompositionError(eventManager) {
+ var lastCompositionValue, suppressedKeyPress = false;
+ function suppressIncorrectKeyPress(e) {
+ suppressedKeyPress = e.which && String.fromCharCode(e.which) === lastCompositionValue;
+ lastCompositionValue = undefined;
+ return suppressedKeyPress === false
+ }
+ function clearSuppression() {
+ suppressedKeyPress = false
+ }
+ function trapComposedValue(e) {
+ lastCompositionValue = e.data;
+ suppressedKeyPress = false
+ }
+ function init() {
+ eventManager.subscribe("textInput", clearSuppression);
+ eventManager.subscribe("compositionend", trapComposedValue);
+ eventManager.addFilter("keypress", suppressIncorrectKeyPress)
+ }
+ this.destroy = function(callback) {
+ eventManager.unsubscribe("textInput", clearSuppression);
+ eventManager.unsubscribe("compositionend", trapComposedValue);
+ eventManager.removeFilter("keypress", suppressIncorrectKeyPress);
+ callback()
+ };
+ init()
+ }
+ gui.InputMethodEditor = function InputMethodEditor(inputMemberId, eventManager) {
+ var cursorns = "urn:webodf:names:cursor", localCursor = null, eventTrap = eventManager.getEventTrap(), doc = (eventTrap.ownerDocument), compositionElement, async = new core.Async, FAKE_CONTENT = "b", processUpdates, pendingEvent = false, pendingData = "", events = new core.EventNotifier([gui.InputMethodEditor.signalCompositionStart, gui.InputMethodEditor.signalCompositionEnd]), lastCompositionData, filters = [], cleanup, isEditable = false;
+ this.subscribe = events.subscribe;
+ this.unsubscribe = events.unsubscribe;
+ function setCursorComposing(state) {
+ if(localCursor) {
+ if(state) {
+ localCursor.getNode().setAttributeNS(cursorns, "composing", "true")
+ }else {
+ localCursor.getNode().removeAttributeNS(cursorns, "composing");
+ compositionElement.textContent = ""
+ }
+ }
+ }
+ function flushEvent() {
+ if(pendingEvent) {
+ pendingEvent = false;
+ setCursorComposing(false);
+ events.emit(gui.InputMethodEditor.signalCompositionEnd, {data:pendingData});
+ pendingData = ""
+ }
+ }
+ function addCompositionData(data) {
+ pendingEvent = true;
+ pendingData += data;
+ processUpdates.trigger()
+ }
+ function resetWindowSelection() {
+ flushEvent();
+ if(localCursor && localCursor.getSelectedRange().collapsed) {
+ eventTrap.value = ""
+ }else {
+ eventTrap.value = FAKE_CONTENT
+ }
+ eventTrap.setSelectionRange(0, eventTrap.value.length)
+ }
+ function compositionStart() {
+ lastCompositionData = undefined;
+ processUpdates.cancel();
+ setCursorComposing(true);
+ if(!pendingEvent) {
+ events.emit(gui.InputMethodEditor.signalCompositionStart, {data:""})
+ }
+ }
+ function compositionEnd(e) {
+ lastCompositionData = e.data;
+ addCompositionData(e.data)
+ }
+ function textInput(e) {
+ if(e.data !== lastCompositionData) {
+ addCompositionData(e.data)
+ }
+ lastCompositionData = undefined
+ }
+ function synchronizeCompositionText() {
+ compositionElement.textContent = eventTrap.value
+ }
+ this.registerCursor = function(cursor) {
+ if(cursor.getMemberId() === inputMemberId) {
+ localCursor = cursor;
+ localCursor.getNode().appendChild(compositionElement);
+ eventManager.subscribe("input", synchronizeCompositionText);
+ eventManager.subscribe("compositionupdate", synchronizeCompositionText)
+ }
+ };
+ this.removeCursor = function(memberid) {
+ if(localCursor && memberid === inputMemberId) {
+ localCursor.getNode().removeChild(compositionElement);
+ eventManager.unsubscribe("input", synchronizeCompositionText);
+ eventManager.unsubscribe("compositionupdate", synchronizeCompositionText);
+ localCursor = null
+ }
+ };
+ function suppressFocus() {
+ eventManager.blur();
+ eventTrap.setAttribute("disabled", true)
+ }
+ function synchronizeEventStatus() {
+ var hasFocus = eventManager.hasFocus();
+ if(hasFocus) {
+ eventManager.blur()
+ }
+ if(isEditable) {
+ eventTrap.removeAttribute("disabled")
+ }else {
+ eventTrap.setAttribute("disabled", true)
+ }
+ if(hasFocus) {
+ eventManager.focus()
+ }
+ }
+ this.setEditing = function(editable) {
+ isEditable = editable;
+ synchronizeEventStatus()
+ };
+ this.destroy = function(callback) {
+ eventManager.unsubscribe("compositionstart", compositionStart);
+ eventManager.unsubscribe("compositionend", compositionEnd);
+ eventManager.unsubscribe("textInput", textInput);
+ eventManager.unsubscribe("keypress", flushEvent);
+ eventManager.unsubscribe("mousedown", suppressFocus);
+ eventManager.unsubscribe("mouseup", synchronizeEventStatus);
+ eventManager.unsubscribe("focus", resetWindowSelection);
+ async.destroyAll(cleanup, callback)
+ };
+ function init() {
+ eventManager.subscribe("compositionstart", compositionStart);
+ eventManager.subscribe("compositionend", compositionEnd);
+ eventManager.subscribe("textInput", textInput);
+ eventManager.subscribe("keypress", flushEvent);
+ eventManager.subscribe("mousedown", suppressFocus);
+ eventManager.subscribe("mouseup", synchronizeEventStatus);
+ eventManager.subscribe("focus", resetWindowSelection);
+ filters.push(new DetectSafariCompositionError(eventManager));
+ function getDestroy(filter) {
+ return filter.destroy
+ }
+ cleanup = filters.map(getDestroy);
+ compositionElement = doc.createElement("span");
+ compositionElement.setAttribute("id", "composer");
+ processUpdates = new core.ScheduledTask(resetWindowSelection, 1);
+ cleanup.push(processUpdates.destroy)
+ }
+ init()
+ };
+ gui.InputMethodEditor.signalCompositionStart = "input/compositionstart";
+ gui.InputMethodEditor.signalCompositionEnd = "input/compositionend";
+ return gui.InputMethodEditor
+})();
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.KeyboardHandler = function KeyboardHandler() {
+ var modifier = gui.KeyboardHandler.Modifier, defaultBinding = null, bindings = {};
+ function getModifiers(e) {
+ var modifiers = modifier.None;
+ if(e.metaKey) {
+ modifiers |= modifier.Meta
+ }
+ if(e.ctrlKey) {
+ modifiers |= modifier.Ctrl
+ }
+ if(e.altKey) {
+ modifiers |= modifier.Alt
+ }
+ if(e.shiftKey) {
+ modifiers |= modifier.Shift
+ }
+ return modifiers
+ }
+ function getKeyCombo(keyCode, modifiers) {
+ if(!modifiers) {
+ modifiers = modifier.None
+ }
+ return keyCode + ":" + modifiers
+ }
+ this.setDefault = function(callback) {
+ defaultBinding = callback
+ };
+ this.bind = function(keyCode, modifiers, callback, overwrite) {
+ var keyCombo = getKeyCombo(keyCode, modifiers);
+ runtime.assert(overwrite || bindings.hasOwnProperty(keyCombo) === false, "tried to overwrite the callback handler of key combo: " + keyCombo);
+ bindings[keyCombo] = callback
+ };
+ this.unbind = function(keyCode, modifiers) {
+ var keyCombo = getKeyCombo(keyCode, modifiers);
+ delete bindings[keyCombo]
+ };
+ this.reset = function() {
+ defaultBinding = null;
+ bindings = {}
+ };
+ this.handleEvent = function(e) {
+ var keyCombo = getKeyCombo(e.keyCode, getModifiers(e)), callback = bindings[keyCombo], handled = false;
+ if(callback) {
+ handled = callback()
+ }else {
+ if(defaultBinding !== null) {
+ handled = defaultBinding(e)
+ }
+ }
+ if(handled) {
+ if(e.preventDefault) {
+ e.preventDefault()
+ }else {
+ e.returnValue = false
+ }
+ }
+ }
+};
+gui.KeyboardHandler.Modifier = {None:0, Meta:1, Ctrl:2, Alt:4, CtrlAlt:6, Shift:8, MetaShift:9, CtrlShift:10, AltShift:12};
+gui.KeyboardHandler.KeyCode = {Backspace:8, Tab:9, Clear:12, Enter:13, Ctrl:17, End:35, Home:36, Left:37, Up:38, Right:39, Down:40, Delete:46, A:65, B:66, C:67, D:68, E:69, F:70, G:71, H:72, I:73, J:74, K:75, L:76, M:77, N:78, O:79, P:80, Q:81, R:82, S:83, T:84, U:85, V:86, W:87, X:88, Y:89, Z:90, LeftMeta:91, MetaInMozilla:224};
+(function() {
+ return gui.KeyboardHandler
+})();
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -16950,8 +14231,505 @@ gui.ImageManager = function ImageManager(session, inputMemberId, objectNameGener
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.PositionFilter");
-gui.TextManipulator = function TextManipulator(session, inputMemberId, directStyleOp) {
+gui.PlainTextPasteboard = function PlainTextPasteboard(odtDocument, inputMemberId) {
+ function createOp(op, data) {
+ op.init(data);
+ return op
+ }
+ this.createPasteOps = function(data) {
+ var originalCursorPosition = odtDocument.getCursorPosition(inputMemberId), cursorPosition = originalCursorPosition, operations = [], paragraphs;
+ paragraphs = data.replace(/\r/g, "").split("\n");
+ paragraphs.forEach(function(text) {
+ operations.push(createOp(new ops.OpSplitParagraph, {memberid:inputMemberId, position:cursorPosition, moveCursor:true}));
+ cursorPosition += 1;
+ operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text, moveCursor:true}));
+ cursorPosition += text.length
+ });
+ operations.push(createOp(new ops.OpRemoveText, {memberid:inputMemberId, position:originalCursorPosition, length:1}));
+ return operations
+ }
+};
+/*
+
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+odf.WordBoundaryFilter = function WordBoundaryFilter(odtDocument, includeWhitespace) {
+ var TEXT_NODE = Node.TEXT_NODE, ELEMENT_NODE = Node.ELEMENT_NODE, odfUtils = new odf.OdfUtils, punctuation = /[!-#%-*,-\/:-;?-@\[-\]_{}\u00a1\u00ab\u00b7\u00bb\u00bf;\u00b7\u055a-\u055f\u0589-\u058a\u05be\u05c0\u05c3\u05c6\u05f3-\u05f4\u0609-\u060a\u060c-\u060d\u061b\u061e-\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0964-\u0965\u0970\u0df4\u0e4f\u0e5a-\u0e5b\u0f04-\u0f12\u0f3a-\u0f3d\u0f85\u0fd0-\u0fd4\u104a-\u104f\u10fb\u1361-\u1368\u166d-\u166e\u169b-\u169c\u16eb-\u16ed\u1735-\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u180a\u1944-\u1945\u19de-\u19df\u1a1e-\u1a1f\u1b5a-\u1b60\u1c3b-\u1c3f\u1c7e-\u1c7f\u2000-\u206e\u207d-\u207e\u208d-\u208e\u3008-\u3009\u2768-\u2775\u27c5-\u27c6\u27e6-\u27ef\u2983-\u2998\u29d8-\u29db\u29fc-\u29fd\u2cf9-\u2cfc\u2cfe-\u2cff\u2e00-\u2e7e\u3000-\u303f\u30a0\u30fb\ua60d-\ua60f\ua673\ua67e\ua874-\ua877\ua8ce-\ua8cf\ua92e-\ua92f\ua95f\uaa5c-\uaa5f\ufd3e-\ufd3f\ufe10-\ufe19\ufe30-\ufe52\ufe54-\ufe61\ufe63\ufe68\ufe6a-\ufe6b\uff01-\uff03\uff05-\uff0a\uff0c-\uff0f\uff1a-\uff1b\uff1f-\uff20\uff3b-\uff3d\uff3f\uff5b\uff5d\uff5f-\uff65]|\ud800[\udd00-\udd01\udf9f\udfd0]|\ud802[\udd1f\udd3f\ude50-\ude58]|\ud809[\udc00-\udc7e]/,
+ spacing = /\s/, FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT, FILTER_REJECT = core.PositionFilter.FilterResult.FILTER_REJECT, TRAILING = odf.WordBoundaryFilter.IncludeWhitespace.TRAILING, LEADING = odf.WordBoundaryFilter.IncludeWhitespace.LEADING, NeighborType = {NO_NEIGHBOUR:0, SPACE_CHAR:1, PUNCTUATION_CHAR:2, WORD_CHAR:3, OTHER:4};
+ function findHigherNeighborNode(node, direction, nodeFilter) {
+ var neighboringNode = null, rootNode = odtDocument.getRootNode(), unfilteredCandidate;
+ while(node !== rootNode && (node !== null && neighboringNode === null)) {
+ unfilteredCandidate = direction < 0 ? node.previousSibling : node.nextSibling;
+ if(nodeFilter(unfilteredCandidate) === NodeFilter.FILTER_ACCEPT) {
+ neighboringNode = unfilteredCandidate
+ }
+ node = node.parentNode
+ }
+ return neighboringNode
+ }
+ function typeOfNeighbor(node, getOffset) {
+ var neighboringChar;
+ if(node === null) {
+ return NeighborType.NO_NEIGHBOUR
+ }
+ if(odfUtils.isCharacterElement(node)) {
+ return NeighborType.SPACE_CHAR
+ }
+ if(node.nodeType === TEXT_NODE || (odfUtils.isTextSpan(node) || odfUtils.isHyperlink(node))) {
+ neighboringChar = node.textContent.charAt(getOffset());
+ if(spacing.test(neighboringChar)) {
+ return NeighborType.SPACE_CHAR
+ }
+ if(punctuation.test(neighboringChar)) {
+ return NeighborType.PUNCTUATION_CHAR
+ }
+ return NeighborType.WORD_CHAR
+ }
+ return NeighborType.OTHER
+ }
+ this.acceptPosition = function(iterator) {
+ var container = iterator.container(), leftNode = iterator.leftNode(), rightNode = iterator.rightNode(), getRightCharOffset = iterator.unfilteredDomOffset, getLeftCharOffset = function() {
+ return iterator.unfilteredDomOffset() - 1
+ }, leftNeighborType, rightNeighborType;
+ if(container.nodeType === ELEMENT_NODE) {
+ if(rightNode === null) {
+ rightNode = findHigherNeighborNode(container, 1, iterator.getNodeFilter())
+ }
+ if(leftNode === null) {
+ leftNode = findHigherNeighborNode(container, -1, iterator.getNodeFilter())
+ }
+ }
+ if(container !== rightNode) {
+ getRightCharOffset = function() {
+ return 0
+ }
+ }
+ if(container !== leftNode && leftNode !== null) {
+ getLeftCharOffset = function() {
+ return leftNode.textContent.length - 1
+ }
+ }
+ leftNeighborType = typeOfNeighbor(leftNode, getLeftCharOffset);
+ rightNeighborType = typeOfNeighbor(rightNode, getRightCharOffset);
+ if(leftNeighborType === NeighborType.WORD_CHAR && rightNeighborType === NeighborType.WORD_CHAR || (leftNeighborType === NeighborType.PUNCTUATION_CHAR && rightNeighborType === NeighborType.PUNCTUATION_CHAR || (includeWhitespace === TRAILING && (leftNeighborType !== NeighborType.NO_NEIGHBOUR && rightNeighborType === NeighborType.SPACE_CHAR) || includeWhitespace === LEADING && (leftNeighborType === NeighborType.SPACE_CHAR && rightNeighborType !== NeighborType.NO_NEIGHBOUR)))) {
+ return FILTER_REJECT
+ }
+ return FILTER_ACCEPT
+ }
+};
+odf.WordBoundaryFilter.IncludeWhitespace = {None:0, TRAILING:1, LEADING:2};
+(function() {
+ return odf.WordBoundaryFilter
+})();
+gui.SelectionController = function SelectionController(session, inputMemberId) {
+ var odtDocument = session.getOdtDocument(), domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, baseFilter = odtDocument.getPositionFilter(), keyboardMovementsFilter = new core.PositionFilterChain, rootFilter = odtDocument.createRootFilter(inputMemberId), TRAILING_SPACE = odf.WordBoundaryFilter.IncludeWhitespace.TRAILING, LEADING_SPACE = odf.WordBoundaryFilter.IncludeWhitespace.LEADING;
+ function createKeyboardStepIterator() {
+ var cursor = odtDocument.getCursor(inputMemberId), node = cursor.getNode();
+ return odtDocument.createStepIterator(node, 0, [baseFilter, rootFilter], odtDocument.getRootElement(node))
+ }
+ function createWordBoundaryStepIterator(node, offset, includeWhitespace) {
+ var wordBoundaryFilter = new odf.WordBoundaryFilter(odtDocument, includeWhitespace);
+ return odtDocument.createStepIterator(node, offset, [baseFilter, rootFilter, wordBoundaryFilter], odtDocument.getRootElement(node))
+ }
+ function constrain(lookup) {
+ return function(originalNode) {
+ var originalContainer = lookup(originalNode);
+ return function(step, node) {
+ return lookup(node) === originalContainer
+ }
+ }
+ }
+ function selectionToRange(selection) {
+ var hasForwardSelection = domUtils.comparePoints((selection.anchorNode), selection.anchorOffset, (selection.focusNode), selection.focusOffset) >= 0, range = selection.focusNode.ownerDocument.createRange();
+ if(hasForwardSelection) {
+ range.setStart(selection.anchorNode, selection.anchorOffset);
+ range.setEnd(selection.focusNode, selection.focusOffset)
+ }else {
+ range.setStart(selection.focusNode, selection.focusOffset);
+ range.setEnd(selection.anchorNode, selection.anchorOffset)
+ }
+ return{range:range, hasForwardSelection:hasForwardSelection}
+ }
+ this.selectionToRange = selectionToRange;
+ function rangeToSelection(range, hasForwardSelection) {
+ if(hasForwardSelection) {
+ return{anchorNode:(range.startContainer), anchorOffset:range.startOffset, focusNode:(range.endContainer), focusOffset:range.endOffset}
+ }
+ return{anchorNode:(range.endContainer), anchorOffset:range.endOffset, focusNode:(range.startContainer), focusOffset:range.startOffset}
+ }
+ this.rangeToSelection = rangeToSelection;
+ function createOpMoveCursor(position, length, selectionType) {
+ var op = new ops.OpMoveCursor;
+ op.init({memberid:inputMemberId, position:position, length:length || 0, selectionType:selectionType});
+ return op
+ }
+ function selectImage(frameNode) {
+ var frameRoot = odtDocument.getRootElement(frameNode), frameRootFilter = odtDocument.createRootFilter(frameRoot), stepIterator = odtDocument.createStepIterator(frameNode, 0, [frameRootFilter, odtDocument.getPositionFilter()], frameRoot), anchorNode, anchorOffset, newSelection, op;
+ if(!stepIterator.roundToPreviousStep()) {
+ runtime.assert(false, "No walkable position before frame")
+ }
+ anchorNode = stepIterator.container();
+ anchorOffset = stepIterator.offset();
+ stepIterator.setPosition(frameNode, frameNode.childNodes.length);
+ if(!stepIterator.roundToNextStep()) {
+ runtime.assert(false, "No walkable position after frame")
+ }
+ newSelection = odtDocument.convertDomToCursorRange({anchorNode:anchorNode, anchorOffset:anchorOffset, focusNode:stepIterator.container(), focusOffset:stepIterator.offset()});
+ op = createOpMoveCursor(newSelection.position, newSelection.length, ops.OdtCursor.RegionSelection);
+ session.enqueue([op])
+ }
+ this.selectImage = selectImage;
+ function expandToWordBoundaries(range) {
+ var stepIterator;
+ stepIterator = createWordBoundaryStepIterator((range.startContainer), range.startOffset, TRAILING_SPACE);
+ if(stepIterator.roundToPreviousStep()) {
+ range.setStart(stepIterator.container(), stepIterator.offset())
+ }
+ stepIterator = createWordBoundaryStepIterator((range.endContainer), range.endOffset, LEADING_SPACE);
+ if(stepIterator.roundToNextStep()) {
+ range.setEnd(stepIterator.container(), stepIterator.offset())
+ }
+ }
+ this.expandToWordBoundaries = expandToWordBoundaries;
+ function expandToParagraphBoundaries(range) {
+ var paragraphs = odfUtils.getParagraphElements(range), startParagraph = paragraphs[0], endParagraph = paragraphs[paragraphs.length - 1];
+ if(startParagraph) {
+ range.setStart(startParagraph, 0)
+ }
+ if(endParagraph) {
+ if(odfUtils.isParagraph(range.endContainer) && range.endOffset === 0) {
+ range.setEndBefore(endParagraph)
+ }else {
+ range.setEnd(endParagraph, endParagraph.childNodes.length)
+ }
+ }
+ }
+ this.expandToParagraphBoundaries = expandToParagraphBoundaries;
+ function selectRange(range, hasForwardSelection, clickCount) {
+ var canvasElement = odtDocument.getOdfCanvas().getElement(), validSelection, startInsideCanvas, endInsideCanvas, existingSelection, newSelection, op;
+ startInsideCanvas = domUtils.containsNode(canvasElement, range.startContainer);
+ endInsideCanvas = domUtils.containsNode(canvasElement, range.endContainer);
+ if(!startInsideCanvas && !endInsideCanvas) {
+ return
+ }
+ if(startInsideCanvas && endInsideCanvas) {
+ if(clickCount === 2) {
+ expandToWordBoundaries(range)
+ }else {
+ if(clickCount >= 3) {
+ expandToParagraphBoundaries(range)
+ }
+ }
+ }
+ validSelection = rangeToSelection(range, hasForwardSelection);
+ newSelection = odtDocument.convertDomToCursorRange(validSelection, constrain(odfUtils.getParagraphElement));
+ existingSelection = odtDocument.getCursorSelection(inputMemberId);
+ if(newSelection.position !== existingSelection.position || newSelection.length !== existingSelection.length) {
+ op = createOpMoveCursor(newSelection.position, newSelection.length, ops.OdtCursor.RangeSelection);
+ session.enqueue([op])
+ }
+ }
+ this.selectRange = selectRange;
+ function extendCursorByAdjustment(lengthAdjust) {
+ var selection = odtDocument.getCursorSelection(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter(), newLength;
+ if(lengthAdjust !== 0) {
+ if(lengthAdjust > 0) {
+ lengthAdjust = stepCounter.convertForwardStepsBetweenFilters(lengthAdjust, keyboardMovementsFilter, baseFilter)
+ }else {
+ lengthAdjust = -stepCounter.convertBackwardStepsBetweenFilters(-lengthAdjust, keyboardMovementsFilter, baseFilter)
+ }
+ newLength = selection.length + lengthAdjust;
+ session.enqueue([createOpMoveCursor(selection.position, newLength)])
+ }
+ }
+ function extendSelection(advanceIterator) {
+ var stepIterator = createKeyboardStepIterator(), anchorNode = odtDocument.getCursor(inputMemberId).getAnchorNode(), newSelection;
+ if(advanceIterator(stepIterator)) {
+ newSelection = odtDocument.convertDomToCursorRange({anchorNode:anchorNode, anchorOffset:0, focusNode:stepIterator.container(), focusOffset:stepIterator.offset()});
+ session.enqueue([createOpMoveCursor(newSelection.position, newSelection.length)])
+ }
+ }
+ function moveCursorByAdjustment(positionAdjust) {
+ var position = odtDocument.getCursorPosition(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter();
+ if(positionAdjust !== 0) {
+ positionAdjust = positionAdjust > 0 ? stepCounter.convertForwardStepsBetweenFilters(positionAdjust, keyboardMovementsFilter, baseFilter) : -stepCounter.convertBackwardStepsBetweenFilters(-positionAdjust, keyboardMovementsFilter, baseFilter);
+ position = position + positionAdjust;
+ session.enqueue([createOpMoveCursor(position, 0)])
+ }
+ }
+ function moveCursor(advanceIterator) {
+ var stepIterator = createKeyboardStepIterator(), position;
+ if(advanceIterator(stepIterator)) {
+ position = odtDocument.convertDomPointToCursorStep(stepIterator.container(), stepIterator.offset());
+ session.enqueue([createOpMoveCursor(position, 0)])
+ }
+ }
+ function moveCursorToLeft() {
+ moveCursor(function(iterator) {
+ return iterator.previousStep()
+ });
+ return true
+ }
+ this.moveCursorToLeft = moveCursorToLeft;
+ function moveCursorToRight() {
+ moveCursor(function(iterator) {
+ return iterator.nextStep()
+ });
+ return true
+ }
+ this.moveCursorToRight = moveCursorToRight;
+ function extendSelectionToLeft() {
+ extendSelection(function(iterator) {
+ return iterator.previousStep()
+ });
+ return true
+ }
+ this.extendSelectionToLeft = extendSelectionToLeft;
+ function extendSelectionToRight() {
+ extendSelection(function(iterator) {
+ return iterator.nextStep()
+ });
+ return true
+ }
+ this.extendSelectionToRight = extendSelectionToRight;
+ function moveCursorByLine(direction, extend) {
+ var paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()), steps;
+ runtime.assert(Boolean(paragraphNode), "SelectionController: Cursor outside paragraph");
+ steps = odtDocument.getCursor(inputMemberId).getStepCounter().countLinesSteps(direction, keyboardMovementsFilter);
+ if(extend) {
+ extendCursorByAdjustment(steps)
+ }else {
+ moveCursorByAdjustment(steps)
+ }
+ }
+ function moveCursorUp() {
+ moveCursorByLine(-1, false);
+ return true
+ }
+ this.moveCursorUp = moveCursorUp;
+ function moveCursorDown() {
+ moveCursorByLine(1, false);
+ return true
+ }
+ this.moveCursorDown = moveCursorDown;
+ function extendSelectionUp() {
+ moveCursorByLine(-1, true);
+ return true
+ }
+ this.extendSelectionUp = extendSelectionUp;
+ function extendSelectionDown() {
+ moveCursorByLine(1, true);
+ return true
+ }
+ this.extendSelectionDown = extendSelectionDown;
+ function moveCursorToLineBoundary(direction, extend) {
+ var steps = odtDocument.getCursor(inputMemberId).getStepCounter().countStepsToLineBoundary(direction, keyboardMovementsFilter);
+ if(extend) {
+ extendCursorByAdjustment(steps)
+ }else {
+ moveCursorByAdjustment(steps)
+ }
+ }
+ function moveCursorByWord(direction, extend) {
+ var cursor = odtDocument.getCursor(inputMemberId), newSelection = rangeToSelection(cursor.getSelectedRange(), cursor.hasForwardSelection()), newCursorSelection, selectionUpdated, stepIterator = createWordBoundaryStepIterator(newSelection.focusNode, newSelection.focusOffset, TRAILING_SPACE);
+ if(direction >= 0) {
+ selectionUpdated = stepIterator.nextStep()
+ }else {
+ selectionUpdated = stepIterator.previousStep()
+ }
+ if(selectionUpdated) {
+ newSelection.focusNode = stepIterator.container();
+ newSelection.focusOffset = stepIterator.offset();
+ if(!extend) {
+ newSelection.anchorNode = newSelection.focusNode;
+ newSelection.anchorOffset = newSelection.focusOffset
+ }
+ newCursorSelection = odtDocument.convertDomToCursorRange(newSelection);
+ session.enqueue([createOpMoveCursor(newCursorSelection.position, newCursorSelection.length)])
+ }
+ }
+ function moveCursorBeforeWord() {
+ moveCursorByWord(-1, false);
+ return true
+ }
+ this.moveCursorBeforeWord = moveCursorBeforeWord;
+ function moveCursorPastWord() {
+ moveCursorByWord(1, false);
+ return true
+ }
+ this.moveCursorPastWord = moveCursorPastWord;
+ function extendSelectionBeforeWord() {
+ moveCursorByWord(-1, true);
+ return true
+ }
+ this.extendSelectionBeforeWord = extendSelectionBeforeWord;
+ function extendSelectionPastWord() {
+ moveCursorByWord(1, true);
+ return true
+ }
+ this.extendSelectionPastWord = extendSelectionPastWord;
+ function moveCursorToLineStart() {
+ moveCursorToLineBoundary(-1, false);
+ return true
+ }
+ this.moveCursorToLineStart = moveCursorToLineStart;
+ function moveCursorToLineEnd() {
+ moveCursorToLineBoundary(1, false);
+ return true
+ }
+ this.moveCursorToLineEnd = moveCursorToLineEnd;
+ function extendSelectionToLineStart() {
+ moveCursorToLineBoundary(-1, true);
+ return true
+ }
+ this.extendSelectionToLineStart = extendSelectionToLineStart;
+ function extendSelectionToLineEnd() {
+ moveCursorToLineBoundary(1, true);
+ return true
+ }
+ this.extendSelectionToLineEnd = extendSelectionToLineEnd;
+ function extendCursorToNodeBoundary(direction, getContainmentNode) {
+ var cursor = odtDocument.getCursor(inputMemberId), node = getContainmentNode(cursor.getNode()), selection = rangeToSelection(cursor.getSelectedRange(), cursor.hasForwardSelection()), newCursorSelection;
+ runtime.assert(Boolean(node), "SelectionController: Cursor outside root");
+ if(direction < 0) {
+ selection.focusNode = (node);
+ selection.focusOffset = 0
+ }else {
+ selection.focusNode = (node);
+ selection.focusOffset = node.childNodes.length
+ }
+ newCursorSelection = odtDocument.convertDomToCursorRange(selection, constrain(getContainmentNode));
+ session.enqueue([createOpMoveCursor(newCursorSelection.position, newCursorSelection.length)])
+ }
+ function extendSelectionToParagraphStart() {
+ extendCursorToNodeBoundary(-1, odtDocument.getParagraphElement);
+ return true
+ }
+ this.extendSelectionToParagraphStart = extendSelectionToParagraphStart;
+ function extendSelectionToParagraphEnd() {
+ extendCursorToNodeBoundary(1, odtDocument.getParagraphElement);
+ return true
+ }
+ this.extendSelectionToParagraphEnd = extendSelectionToParagraphEnd;
+ function moveCursorToRootBoundary(direction) {
+ var cursor = odtDocument.getCursor(inputMemberId), root = odtDocument.getRootElement(cursor.getNode()), newPosition;
+ runtime.assert(Boolean(root), "SelectionController: Cursor outside root");
+ if(direction < 0) {
+ newPosition = odtDocument.convertDomPointToCursorStep(root, 0, function(step) {
+ return step === ops.StepsTranslator.NEXT_STEP
+ })
+ }else {
+ newPosition = odtDocument.convertDomPointToCursorStep(root, root.childNodes.length)
+ }
+ session.enqueue([createOpMoveCursor(newPosition, 0)]);
+ return true
+ }
+ function moveCursorToDocumentStart() {
+ moveCursorToRootBoundary(-1);
+ return true
+ }
+ this.moveCursorToDocumentStart = moveCursorToDocumentStart;
+ function moveCursorToDocumentEnd() {
+ moveCursorToRootBoundary(1);
+ return true
+ }
+ this.moveCursorToDocumentEnd = moveCursorToDocumentEnd;
+ function extendSelectionToDocumentStart() {
+ extendCursorToNodeBoundary(-1, odtDocument.getRootElement);
+ return true
+ }
+ this.extendSelectionToDocumentStart = extendSelectionToDocumentStart;
+ function extendSelectionToDocumentEnd() {
+ extendCursorToNodeBoundary(1, odtDocument.getRootElement);
+ return true
+ }
+ this.extendSelectionToDocumentEnd = extendSelectionToDocumentEnd;
+ function extendSelectionToEntireDocument() {
+ var cursor = odtDocument.getCursor(inputMemberId), root = odtDocument.getRootElement(cursor.getNode()), newSelection, newCursorSelection;
+ runtime.assert(Boolean(root), "SelectionController: Cursor outside root");
+ newSelection = {anchorNode:root, anchorOffset:0, focusNode:root, focusOffset:root.childNodes.length};
+ newCursorSelection = odtDocument.convertDomToCursorRange(newSelection, constrain(odtDocument.getRootElement));
+ session.enqueue([createOpMoveCursor(newCursorSelection.position, newCursorSelection.length)]);
+ return true
+ }
+ this.extendSelectionToEntireDocument = extendSelectionToEntireDocument;
+ function init() {
+ keyboardMovementsFilter.addFilter(baseFilter);
+ keyboardMovementsFilter.addFilter(odtDocument.createRootFilter(inputMemberId))
+ }
+ init()
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.TextController = function TextController(session, inputMemberId, directStyleOp, paragraphStyleOps) {
var odtDocument = session.getOdtDocument(), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
function createOpRemoveSelection(selection) {
var op = new ops.OpRemoveText;
@@ -16966,7 +14744,7 @@ gui.TextManipulator = function TextManipulator(session, inputMemberId, directSty
return selection
}
this.enqueueParagraphSplittingOps = function() {
- var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, operations = [];
+ var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, operations = [], styleOps;
if(selection.length > 0) {
op = createOpRemoveSelection(selection);
operations.push(op)
@@ -16974,13 +14752,17 @@ gui.TextManipulator = function TextManipulator(session, inputMemberId, directSty
op = new ops.OpSplitParagraph;
op.init({memberid:inputMemberId, position:selection.position, moveCursor:true});
operations.push(op);
+ if(paragraphStyleOps) {
+ styleOps = paragraphStyleOps(selection.position + 1);
+ operations = operations.concat(styleOps)
+ }
session.enqueue(operations);
return true
};
function hasPositionInDirection(cursorNode, forward) {
var rootConstrainedFilter = new core.PositionFilterChain, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootElement(cursorNode)), nextPosition = (forward ? iterator.nextPosition : iterator.previousPosition);
- rootConstrainedFilter.addFilter("BaseFilter", odtDocument.getPositionFilter());
- rootConstrainedFilter.addFilter("RootFilter", odtDocument.createRootFilter(inputMemberId));
+ rootConstrainedFilter.addFilter(odtDocument.getPositionFilter());
+ rootConstrainedFilter.addFilter(odtDocument.createRootFilter(inputMemberId));
iterator.setUnfilteredPosition(cursorNode, 0);
while(nextPosition()) {
if(rootConstrainedFilter.acceptPosition(iterator) === FILTER_ACCEPT) {
@@ -17026,16 +14808,17 @@ gui.TextManipulator = function TextManipulator(session, inputMemberId, directSty
return true
};
function insertText(text) {
- var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, stylingOp, operations = [];
+ var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, stylingOp, operations = [], useCachedStyle = false;
if(selection.length > 0) {
op = createOpRemoveSelection(selection);
- operations.push(op)
+ operations.push(op);
+ useCachedStyle = true
}
op = new ops.OpInsertText;
op.init({memberid:inputMemberId, position:selection.position, text:text, moveCursor:true});
operations.push(op);
if(directStyleOp) {
- stylingOp = directStyleOp(selection.position, text.length);
+ stylingOp = directStyleOp(selection.position, text.length, useCachedStyle);
if(stylingOp) {
operations.push(stylingOp)
}
@@ -17045,37 +14828,88 @@ gui.TextManipulator = function TextManipulator(session, inputMemberId, directSty
this.insertText = insertText
};
(function() {
- return gui.TextManipulator
+ return gui.TextController
})();
-runtime.loadClass("core.DomUtils");
-runtime.loadClass("core.Async");
-runtime.loadClass("core.ScheduledTask");
-runtime.loadClass("odf.OdfUtils");
-runtime.loadClass("odf.ObjectNameGenerator");
-runtime.loadClass("ops.OdtCursor");
-runtime.loadClass("ops.OpAddCursor");
-runtime.loadClass("ops.OpRemoveCursor");
-runtime.loadClass("gui.Clipboard");
-runtime.loadClass("gui.DirectTextStyler");
-runtime.loadClass("gui.DirectParagraphStyler");
-runtime.loadClass("gui.KeyboardHandler");
-runtime.loadClass("gui.ImageManager");
-runtime.loadClass("gui.ImageSelector");
-runtime.loadClass("gui.TextManipulator");
-runtime.loadClass("gui.AnnotationController");
-runtime.loadClass("gui.EventManager");
-runtime.loadClass("gui.PlainTextPasteboard");
-gui.SessionController = function() {
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.UndoManager = function UndoManager() {
+};
+gui.UndoManager.prototype.subscribe = function(signal, callback) {
+};
+gui.UndoManager.prototype.unsubscribe = function(signal, callback) {
+};
+gui.UndoManager.prototype.setDocument = function(newDocument) {
+};
+gui.UndoManager.prototype.setInitialState = function() {
+};
+gui.UndoManager.prototype.initialize = function() {
+};
+gui.UndoManager.prototype.purgeInitialState = function() {
+};
+gui.UndoManager.prototype.setPlaybackFunction = function(playback_func) {
+};
+gui.UndoManager.prototype.hasUndoStates = function() {
+};
+gui.UndoManager.prototype.hasRedoStates = function() {
+};
+gui.UndoManager.prototype.moveForward = function(states) {
+};
+gui.UndoManager.prototype.moveBackward = function(states) {
+};
+gui.UndoManager.prototype.onOperationExecuted = function(op) {
+};
+gui.UndoManager.signalUndoStackChanged = "undoStackChanged";
+gui.UndoManager.signalUndoStateCreated = "undoStateCreated";
+gui.UndoManager.signalUndoStateModified = "undoStateModified";
+(function() {
+ return gui.UndoManager
+})();
+(function() {
var FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT;
gui.SessionController = function SessionController(session, inputMemberId, shadowCursor, args) {
- var window = (runtime.getWindow()), odtDocument = session.getOdtDocument(), async = new core.Async, domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, clipboard = new gui.Clipboard, keyDownHandler = new gui.KeyboardHandler, keyPressHandler = new gui.KeyboardHandler, keyboardMovementsFilter = new core.PositionFilterChain, baseFilter = odtDocument.getPositionFilter(), clickStartedWithinContainer = false, objectNameGenerator = new odf.ObjectNameGenerator(odtDocument.getOdfCanvas().odfContainer(),
- inputMemberId), isMouseMoved = false, mouseDownRootFilter = null, undoManager = null, eventManager = new gui.EventManager(odtDocument), annotationController = new gui.AnnotationController(session, inputMemberId), directTextStyler = new gui.DirectTextStyler(session, inputMemberId), directParagraphStyler = args && args.directParagraphStylingEnabled ? new gui.DirectParagraphStyler(session, inputMemberId, objectNameGenerator) : null, createCursorStyleOp = (directTextStyler.createCursorStyleOp), textManipulator =
- new gui.TextManipulator(session, inputMemberId, createCursorStyleOp), imageManager = new gui.ImageManager(session, inputMemberId, objectNameGenerator), imageSelector = new gui.ImageSelector(odtDocument.getOdfCanvas()), shadowCursorIterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), drawShadowCursorTask, redrawRegionSelectionTask, pasteHandler = new gui.PlainTextPasteboard(odtDocument, inputMemberId), clickCount = 0;
+ var window = (runtime.getWindow()), odtDocument = session.getOdtDocument(), async = new core.Async, domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, mimeDataExporter = new gui.MimeDataExporter, clipboard = new gui.Clipboard(mimeDataExporter), keyDownHandler = new gui.KeyboardHandler, keyPressHandler = new gui.KeyboardHandler, keyUpHandler = new gui.KeyboardHandler, clickStartedWithinCanvas = false, objectNameGenerator = new odf.ObjectNameGenerator(odtDocument.getOdfCanvas().odfContainer(),
+ inputMemberId), isMouseMoved = false, mouseDownRootFilter = null, handleMouseClickTimeoutId, undoManager = null, eventManager = new gui.EventManager(odtDocument), annotationController = new gui.AnnotationController(session, inputMemberId), directFormattingController = new gui.DirectFormattingController(session, inputMemberId, objectNameGenerator, args.directParagraphStylingEnabled), createCursorStyleOp = (directFormattingController.createCursorStyleOp), createParagraphStyleOps = (directFormattingController.createParagraphStyleOps),
+ textController = new gui.TextController(session, inputMemberId, createCursorStyleOp, createParagraphStyleOps), imageController = new gui.ImageController(session, inputMemberId, objectNameGenerator), imageSelector = new gui.ImageSelector(odtDocument.getOdfCanvas()), shadowCursorIterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), drawShadowCursorTask, redrawRegionSelectionTask, pasteHandler = new gui.PlainTextPasteboard(odtDocument, inputMemberId), inputMethodEditor =
+ new gui.InputMethodEditor(inputMemberId, eventManager), clickCount = 0, hyperlinkClickHandler = new gui.HyperlinkClickHandler(odtDocument.getRootNode), hyperlinkController = new gui.HyperlinkController(session, inputMemberId), selectionController = new gui.SelectionController(session, inputMemberId), modifier = gui.KeyboardHandler.Modifier, keyCode = gui.KeyboardHandler.KeyCode, isMacOS = window.navigator.appVersion.toLowerCase().indexOf("mac") !== -1, isIOS = ["iPad", "iPod", "iPhone"].indexOf(window.navigator.platform) !==
+ -1, iOSSafariSupport;
runtime.assert(window !== null, "Expected to be run in an environment which has a global window, like a browser.");
- keyboardMovementsFilter.addFilter("BaseFilter", baseFilter);
- keyboardMovementsFilter.addFilter("RootFilter", odtDocument.createRootFilter(inputMemberId));
function getTarget(e) {
- return e.target || e.srcElement
+ return(e.target) || (e.srcElement || null)
}
function cancelEvent(event) {
if(event.preventDefault) {
@@ -17084,19 +14918,11 @@ gui.SessionController = function() {
event.returnValue = false
}
}
- function dummyHandler(e) {
- cancelEvent(e)
- }
- function createOpMoveCursor(position, length, selectionType) {
- var op = new ops.OpMoveCursor;
- op.init({memberid:inputMemberId, position:position, length:length || 0, selectionType:selectionType});
- return op
- }
function caretPositionFromPoint(x, y) {
- var doc = odtDocument.getDOM(), c, result = null;
+ var doc = odtDocument.getDOMDocument(), c, result = null;
if(doc.caretRangeFromPoint) {
c = doc.caretRangeFromPoint(x, y);
- result = {container:c.startContainer, offset:c.startOffset}
+ result = {container:(c.startContainer), offset:c.startOffset}
}else {
if(doc.caretPositionFromPoint) {
c = doc.caretPositionFromPoint(x, y);
@@ -17107,260 +14933,6 @@ gui.SessionController = function() {
}
return result
}
- function expandToWordBoundaries(range) {
- var alphaNumeric = /[A-Za-z0-9]/, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), currentNode, c;
- iterator.setUnfilteredPosition((range.startContainer), range.startOffset);
- while(iterator.previousPosition()) {
- currentNode = iterator.getCurrentNode();
- if(currentNode.nodeType === Node.TEXT_NODE) {
- c = currentNode.data[iterator.unfilteredDomOffset()];
- if(!alphaNumeric.test(c)) {
- break
- }
- }else {
- if(!odfUtils.isTextSpan(currentNode)) {
- break
- }
- }
- range.setStart(iterator.container(), iterator.unfilteredDomOffset())
- }
- iterator.setUnfilteredPosition((range.endContainer), range.endOffset);
- do {
- currentNode = iterator.getCurrentNode();
- if(currentNode.nodeType === Node.TEXT_NODE) {
- c = currentNode.data[iterator.unfilteredDomOffset()];
- if(!alphaNumeric.test(c)) {
- break
- }
- }else {
- if(!odfUtils.isTextSpan(currentNode)) {
- break
- }
- }
- }while(iterator.nextPosition());
- range.setEnd(iterator.container(), iterator.unfilteredDomOffset())
- }
- function expandToParagraphBoundaries(range) {
- var startParagraph = odtDocument.getParagraphElement(range.startContainer), endParagraph = odtDocument.getParagraphElement(range.endContainer);
- if(startParagraph) {
- range.setStart(startParagraph, 0)
- }
- if(endParagraph) {
- if(odfUtils.isParagraph(range.endContainer) && range.endOffset === 0) {
- range.setEndBefore(endParagraph)
- }else {
- range.setEnd(endParagraph, endParagraph.childNodes.length)
- }
- }
- }
- function selectImage(frameNode) {
- var stepsToAnchor = odtDocument.getDistanceFromCursor(inputMemberId, frameNode, 0), stepsToFocus = stepsToAnchor !== null ? stepsToAnchor + 1 : null, oldPosition, op;
- if(stepsToFocus || stepsToAnchor) {
- oldPosition = odtDocument.getCursorPosition(inputMemberId);
- op = createOpMoveCursor(oldPosition + stepsToAnchor, stepsToFocus - stepsToAnchor, ops.OdtCursor.RegionSelection);
- session.enqueue([op])
- }
- eventManager.focus()
- }
- function selectionToRange(selection) {
- var hasForwardSelection = domUtils.comparePoints((selection.anchorNode), selection.anchorOffset, (selection.focusNode), selection.focusOffset) >= 0, range = selection.focusNode.ownerDocument.createRange();
- if(hasForwardSelection) {
- range.setStart(selection.anchorNode, selection.anchorOffset);
- range.setEnd(selection.focusNode, selection.focusOffset)
- }else {
- range.setStart(selection.focusNode, selection.focusOffset);
- range.setEnd(selection.anchorNode, selection.anchorOffset)
- }
- return{range:range, hasForwardSelection:hasForwardSelection}
- }
- function rangeToSelection(range, hasForwardSelection) {
- if(hasForwardSelection) {
- return{anchorNode:(range.startContainer), anchorOffset:range.startOffset, focusNode:(range.endContainer), focusOffset:range.endOffset}
- }
- return{anchorNode:(range.endContainer), anchorOffset:range.endOffset, focusNode:(range.startContainer), focusOffset:range.startOffset}
- }
- function constrain(lookup) {
- return function(originalNode) {
- var originalContainer = lookup(originalNode);
- return function(step, node) {
- return lookup(node) === originalContainer
- }
- }
- }
- function selectRange(range, hasForwardSelection, clickCount) {
- var canvasElement = odtDocument.getOdfCanvas().getElement(), validSelection, startInsideCanvas, endInsideCanvas, existingSelection, newSelection, op;
- startInsideCanvas = domUtils.containsNode(canvasElement, range.startContainer);
- endInsideCanvas = domUtils.containsNode(canvasElement, range.endContainer);
- if(!startInsideCanvas && !endInsideCanvas) {
- return
- }
- if(startInsideCanvas && endInsideCanvas) {
- if(clickCount === 2) {
- expandToWordBoundaries(range)
- }else {
- if(clickCount >= 3) {
- expandToParagraphBoundaries(range)
- }
- }
- }
- validSelection = rangeToSelection(range, hasForwardSelection);
- newSelection = odtDocument.convertDomToCursorRange(validSelection, constrain(odfUtils.getParagraphElement));
- existingSelection = odtDocument.getCursorSelection(inputMemberId);
- if(newSelection.position !== existingSelection.position || newSelection.length !== existingSelection.length) {
- op = createOpMoveCursor(newSelection.position, newSelection.length, ops.OdtCursor.RangeSelection);
- session.enqueue([op])
- }
- }
- this.selectRange = selectRange;
- function extendCursorByAdjustment(lengthAdjust) {
- var selection = odtDocument.getCursorSelection(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter(), newLength;
- if(lengthAdjust !== 0) {
- lengthAdjust = lengthAdjust > 0 ? stepCounter.convertForwardStepsBetweenFilters(lengthAdjust, keyboardMovementsFilter, baseFilter) : -stepCounter.convertBackwardStepsBetweenFilters(-lengthAdjust, keyboardMovementsFilter, baseFilter);
- newLength = selection.length + lengthAdjust;
- session.enqueue([createOpMoveCursor(selection.position, newLength)])
- }
- }
- function moveCursorByAdjustment(positionAdjust) {
- var position = odtDocument.getCursorPosition(inputMemberId), stepCounter = odtDocument.getCursor(inputMemberId).getStepCounter();
- if(positionAdjust !== 0) {
- positionAdjust = positionAdjust > 0 ? stepCounter.convertForwardStepsBetweenFilters(positionAdjust, keyboardMovementsFilter, baseFilter) : -stepCounter.convertBackwardStepsBetweenFilters(-positionAdjust, keyboardMovementsFilter, baseFilter);
- position = position + positionAdjust;
- session.enqueue([createOpMoveCursor(position, 0)])
- }
- }
- function moveCursorToLeft() {
- moveCursorByAdjustment(-1);
- return true
- }
- this.moveCursorToLeft = moveCursorToLeft;
- function moveCursorToRight() {
- moveCursorByAdjustment(1);
- return true
- }
- function extendSelectionToLeft() {
- extendCursorByAdjustment(-1);
- return true
- }
- function extendSelectionToRight() {
- extendCursorByAdjustment(1);
- return true
- }
- function moveCursorByLine(direction, extend) {
- var paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()), steps;
- runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
- steps = odtDocument.getCursor(inputMemberId).getStepCounter().countLinesSteps(direction, keyboardMovementsFilter);
- if(extend) {
- extendCursorByAdjustment(steps)
- }else {
- moveCursorByAdjustment(steps)
- }
- }
- function moveCursorUp() {
- moveCursorByLine(-1, false);
- return true
- }
- function moveCursorDown() {
- moveCursorByLine(1, false);
- return true
- }
- function extendSelectionUp() {
- moveCursorByLine(-1, true);
- return true
- }
- function extendSelectionDown() {
- moveCursorByLine(1, true);
- return true
- }
- function moveCursorToLineBoundary(direction, extend) {
- var steps = odtDocument.getCursor(inputMemberId).getStepCounter().countStepsToLineBoundary(direction, keyboardMovementsFilter);
- if(extend) {
- extendCursorByAdjustment(steps)
- }else {
- moveCursorByAdjustment(steps)
- }
- }
- function moveCursorToLineStart() {
- moveCursorToLineBoundary(-1, false);
- return true
- }
- function moveCursorToLineEnd() {
- moveCursorToLineBoundary(1, false);
- return true
- }
- function extendSelectionToLineStart() {
- moveCursorToLineBoundary(-1, true);
- return true
- }
- function extendSelectionToLineEnd() {
- moveCursorToLineBoundary(1, true);
- return true
- }
- function extendSelectionToParagraphStart() {
- var paragraphNode = (odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode())), iterator, node, steps;
- runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
- steps = odtDocument.getDistanceFromCursor(inputMemberId, paragraphNode, 0);
- iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
- iterator.setUnfilteredPosition(paragraphNode, 0);
- while(steps === 0 && iterator.previousPosition()) {
- node = iterator.getCurrentNode();
- if(odfUtils.isParagraph(node)) {
- steps = odtDocument.getDistanceFromCursor(inputMemberId, node, 0)
- }
- }
- extendCursorByAdjustment(steps);
- return true
- }
- function extendSelectionToParagraphEnd() {
- var paragraphNode = (odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode())), iterator, node, steps;
- runtime.assert(Boolean(paragraphNode), "SessionController: Cursor outside paragraph");
- iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
- iterator.moveToEndOfNode(paragraphNode);
- steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset());
- while(steps === 0 && iterator.nextPosition()) {
- node = iterator.getCurrentNode();
- if(odfUtils.isParagraph(node)) {
- iterator.moveToEndOfNode(node);
- steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset())
- }
- }
- extendCursorByAdjustment(steps);
- return true
- }
- function moveCursorToDocumentBoundary(direction, extend) {
- var iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), steps;
- if(direction > 0) {
- iterator.moveToEnd()
- }
- steps = odtDocument.getDistanceFromCursor(inputMemberId, iterator.container(), iterator.unfilteredDomOffset());
- if(extend) {
- extendCursorByAdjustment(steps)
- }else {
- moveCursorByAdjustment(steps)
- }
- }
- this.moveCursorToDocumentBoundary = moveCursorToDocumentBoundary;
- function moveCursorToDocumentStart() {
- moveCursorToDocumentBoundary(-1, false);
- return true
- }
- function moveCursorToDocumentEnd() {
- moveCursorToDocumentBoundary(1, false);
- return true
- }
- function extendSelectionToDocumentStart() {
- moveCursorToDocumentBoundary(-1, true);
- return true
- }
- function extendSelectionToDocumentEnd() {
- moveCursorToDocumentBoundary(1, true);
- return true
- }
- function extendSelectionToEntireDocument() {
- var rootNode = odtDocument.getRootNode(), lastWalkableStep = odtDocument.convertDomPointToCursorStep(rootNode, rootNode.childNodes.length);
- session.enqueue([createOpMoveCursor(0, lastWalkableStep)]);
- return true
- }
- this.extendSelectionToEntireDocument = extendSelectionToEntireDocument;
function redrawRegionSelection() {
var cursor = odtDocument.getCursor(inputMemberId), imageElement;
if(cursor && cursor.getSelectionType() === ops.OdtCursor.RegionSelection) {
@@ -17388,7 +14960,7 @@ gui.SessionController = function() {
return
}
if(clipboard.setDataFromRange(e, selectedRange)) {
- textManipulator.removeCurrentSelection()
+ textController.removeCurrentSelection()
}else {
runtime.log("Cut operation failed")
}
@@ -17417,7 +14989,7 @@ gui.SessionController = function() {
}
}
if(plainText) {
- textManipulator.removeCurrentSelection();
+ textController.removeCurrentSelection();
session.enqueue(pasteHandler.createPasteOps(plainText))
}
cancelEvent(e)
@@ -17434,37 +15006,51 @@ gui.SessionController = function() {
odtDocument.emit(ops.OdtDocument.signalUndoStackChanged, e)
}
function undo() {
+ var eventTrap = eventManager.getEventTrap(), sizer, hadFocusBefore;
if(undoManager) {
+ hadFocusBefore = eventManager.hasFocus();
undoManager.moveBackward(1);
- redrawRegionSelectionTask.trigger();
+ sizer = odtDocument.getOdfCanvas().getSizer();
+ if(!domUtils.containsNode(sizer, eventTrap)) {
+ sizer.appendChild(eventTrap);
+ if(hadFocusBefore) {
+ eventManager.focus()
+ }
+ }
return true
}
return false
}
+ this.undo = undo;
function redo() {
+ var hadFocusBefore;
if(undoManager) {
+ hadFocusBefore = eventManager.hasFocus();
undoManager.moveForward(1);
- redrawRegionSelectionTask.trigger();
+ if(hadFocusBefore) {
+ eventManager.focus()
+ }
return true
}
return false
}
+ this.redo = redo;
function updateShadowCursor() {
- var selection = window.getSelection(), selectionRange = selection.rangeCount > 0 && selectionToRange(selection);
- if(clickStartedWithinContainer && selectionRange) {
+ var selection = window.getSelection(), selectionRange = selection.rangeCount > 0 && selectionController.selectionToRange(selection);
+ if(clickStartedWithinCanvas && selectionRange) {
isMouseMoved = true;
imageSelector.clearSelection();
shadowCursorIterator.setUnfilteredPosition((selection.focusNode), selection.focusOffset);
if(mouseDownRootFilter.acceptPosition(shadowCursorIterator) === FILTER_ACCEPT) {
if(clickCount === 2) {
- expandToWordBoundaries(selectionRange.range)
+ selectionController.expandToWordBoundaries(selectionRange.range)
}else {
if(clickCount >= 3) {
- expandToParagraphBoundaries(selectionRange.range)
+ selectionController.expandToParagraphBoundaries(selectionRange.range)
}
}
shadowCursor.setSelectedRange(selectionRange.range, selectionRange.hasForwardSelection);
- odtDocument.emit(ops.OdtDocument.signalCursorMoved, shadowCursor)
+ odtDocument.emit(ops.Document.signalCursorMoved, shadowCursor)
}
}
}
@@ -17480,16 +15066,15 @@ gui.SessionController = function() {
}
}else {
selection.removeAllRanges();
- selection.addRange(range.cloneRange());
- (odtDocument.getOdfCanvas().getElement()).setActive()
+ selection.addRange(range.cloneRange())
}
}
function handleMouseDown(e) {
var target = getTarget(e), cursor = odtDocument.getCursor(inputMemberId);
- clickStartedWithinContainer = target && domUtils.containsNode(odtDocument.getOdfCanvas().getElement(), target);
- if(clickStartedWithinContainer) {
+ clickStartedWithinCanvas = target !== null && domUtils.containsNode(odtDocument.getOdfCanvas().getElement(), target);
+ if(clickStartedWithinCanvas) {
isMouseMoved = false;
- mouseDownRootFilter = odtDocument.createRootFilter(target);
+ mouseDownRootFilter = odtDocument.createRootFilter((target));
clickCount = e.detail;
if(cursor && e.shiftKey) {
window.getSelection().collapse(cursor.getAnchorNode(), 0)
@@ -17507,111 +15092,263 @@ gui.SessionController = function() {
}
return null
}
+ function getNextWalkablePosition(node) {
+ var root = odtDocument.getRootElement(node), rootFilter = odtDocument.createRootFilter(root), stepIterator = odtDocument.createStepIterator(node, 0, [rootFilter, odtDocument.getPositionFilter()], root);
+ stepIterator.setPosition(node, node.childNodes.length);
+ if(!stepIterator.roundToNextStep()) {
+ return null
+ }
+ return{container:stepIterator.container(), offset:stepIterator.offset()}
+ }
+ function moveByMouseClickEvent(event) {
+ var selection = mutableSelection(window.getSelection()), position, selectionRange, rect, frameNode;
+ if(!selection.anchorNode && !selection.focusNode) {
+ position = caretPositionFromPoint(event.clientX, event.clientY);
+ if(position) {
+ selection.anchorNode = (position.container);
+ selection.anchorOffset = position.offset;
+ selection.focusNode = selection.anchorNode;
+ selection.focusOffset = selection.anchorOffset
+ }
+ }
+ if(odfUtils.isImage(selection.focusNode) && (selection.focusOffset === 0 && odfUtils.isCharacterFrame(selection.focusNode.parentNode))) {
+ frameNode = (selection.focusNode.parentNode);
+ rect = frameNode.getBoundingClientRect();
+ if(event.clientX > rect.right) {
+ position = getNextWalkablePosition(frameNode);
+ if(position) {
+ selection.anchorNode = selection.focusNode = position.container;
+ selection.anchorOffset = selection.focusOffset = position.offset
+ }
+ }
+ }else {
+ if(odfUtils.isImage(selection.focusNode.firstChild) && (selection.focusOffset === 1 && odfUtils.isCharacterFrame(selection.focusNode))) {
+ position = getNextWalkablePosition(selection.focusNode);
+ if(position) {
+ selection.anchorNode = selection.focusNode = position.container;
+ selection.anchorOffset = selection.focusOffset = position.offset
+ }
+ }
+ }
+ if(selection.anchorNode && selection.focusNode) {
+ selectionRange = selectionController.selectionToRange(selection);
+ selectionController.selectRange(selectionRange.range, selectionRange.hasForwardSelection, event.detail)
+ }
+ eventManager.focus()
+ }
function handleMouseClickEvent(event) {
- var target = getTarget(event), eventDetails = {detail:event.detail, clientX:event.clientX, clientY:event.clientY, target:target};
+ var target = getTarget(event), range, wasCollapsed, frameNode, pos;
drawShadowCursorTask.processRequests();
- if(odfUtils.isImage(target) && odfUtils.isCharacterFrame(target.parentNode)) {
- selectImage(target.parentNode);
+ if(odfUtils.isImage(target) && (odfUtils.isCharacterFrame(target.parentNode) && window.getSelection().isCollapsed)) {
+ selectionController.selectImage((target.parentNode));
eventManager.focus()
}else {
- if(clickStartedWithinContainer && !imageSelector.isSelectorElement(target)) {
- if(isMouseMoved) {
- selectRange(shadowCursor.getSelectedRange(), shadowCursor.hasForwardSelection(), event.detail);
- eventManager.focus()
- }else {
- runtime.setTimeout(function() {
- var selection = mutableSelection(window.getSelection()), selectionRange, caretPos;
- if(!selection.anchorNode && !selection.focusNode) {
- caretPos = caretPositionFromPoint(eventDetails.clientX, eventDetails.clientY);
- if(caretPos) {
- selection.anchorNode = (caretPos.container);
- selection.anchorOffset = caretPos.offset;
- selection.focusNode = selection.anchorNode;
- selection.focusOffset = selection.anchorOffset
+ if(imageSelector.isSelectorElement(target)) {
+ eventManager.focus()
+ }else {
+ if(clickStartedWithinCanvas) {
+ if(isMouseMoved) {
+ range = shadowCursor.getSelectedRange();
+ wasCollapsed = range.collapsed;
+ if(odfUtils.isImage(range.endContainer) && (range.endOffset === 0 && odfUtils.isCharacterFrame(range.endContainer.parentNode))) {
+ frameNode = (range.endContainer.parentNode);
+ pos = getNextWalkablePosition(frameNode);
+ if(pos) {
+ range.setEnd(pos.container, pos.offset);
+ if(wasCollapsed) {
+ range.collapse(false)
+ }
}
}
- if(selection.anchorNode && selection.focusNode) {
- selectionRange = selectionToRange(selection);
- selectRange(selectionRange.range, selectionRange.hasForwardSelection, eventDetails.detail)
- }
+ selectionController.selectRange(range, shadowCursor.hasForwardSelection(), event.detail);
eventManager.focus()
- }, 0)
+ }else {
+ if(isIOS) {
+ moveByMouseClickEvent(event)
+ }else {
+ handleMouseClickTimeoutId = runtime.setTimeout(function() {
+ moveByMouseClickEvent(event)
+ }, 0)
+ }
+ }
}
}
}
clickCount = 0;
- clickStartedWithinContainer = false;
+ clickStartedWithinCanvas = false;
isMouseMoved = false
}
+ function handleDragStart(e) {
+ var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange();
+ if(selectedRange.collapsed) {
+ return
+ }
+ mimeDataExporter.exportRangeToDataTransfer((e.dataTransfer), selectedRange)
+ }
function handleDragEnd() {
- if(clickStartedWithinContainer) {
+ if(clickStartedWithinCanvas) {
eventManager.focus()
}
clickCount = 0;
- clickStartedWithinContainer = false;
+ clickStartedWithinCanvas = false;
isMouseMoved = false
}
function handleContextMenu(e) {
handleMouseClickEvent(e)
}
function handleMouseUp(event) {
- var target = getTarget(event), annotationNode = null;
+ var target = (getTarget(event)), annotationNode = null;
if(target.className === "annotationRemoveButton") {
- annotationNode = domUtils.getElementsByTagNameNS(target.parentNode, odf.Namespaces.officens, "annotation")[0];
- annotationController.removeAnnotation(annotationNode)
+ annotationNode = domUtils.getElementsByTagNameNS((target.parentNode), odf.Namespaces.officens, "annotation")[0];
+ annotationController.removeAnnotation(annotationNode);
+ eventManager.focus()
}else {
handleMouseClickEvent(event)
}
}
+ function insertNonEmptyData(e) {
+ var input = e.data;
+ if(input) {
+ textController.insertText(input)
+ }
+ }
+ function returnTrue(fn) {
+ return function() {
+ fn();
+ return true
+ }
+ }
+ function rangeSelectionOnly(fn) {
+ return function(e) {
+ var selectionType = odtDocument.getCursor(inputMemberId).getSelectionType();
+ if(selectionType === ops.OdtCursor.RangeSelection) {
+ return fn(e)
+ }
+ return true
+ }
+ }
+ function insertLocalCursor() {
+ runtime.assert(session.getOdtDocument().getCursor(inputMemberId) === undefined, "Inserting local cursor a second time.");
+ var op = new ops.OpAddCursor;
+ op.init({memberid:inputMemberId});
+ session.enqueue([op]);
+ eventManager.focus()
+ }
+ this.insertLocalCursor = insertLocalCursor;
+ function removeLocalCursor() {
+ runtime.assert(session.getOdtDocument().getCursor(inputMemberId) !== undefined, "Removing local cursor without inserting before.");
+ var op = new ops.OpRemoveCursor;
+ op.init({memberid:inputMemberId});
+ session.enqueue([op])
+ }
+ this.removeLocalCursor = removeLocalCursor;
this.startEditing = function() {
- var op;
- odtDocument.getOdfCanvas().getElement().classList.add("virtualSelections");
- eventManager.subscribe("keydown", keyDownHandler.handleEvent);
- eventManager.subscribe("keypress", keyPressHandler.handleEvent);
- eventManager.subscribe("keyup", dummyHandler);
+ inputMethodEditor.subscribe(gui.InputMethodEditor.signalCompositionStart, textController.removeCurrentSelection);
+ inputMethodEditor.subscribe(gui.InputMethodEditor.signalCompositionEnd, insertNonEmptyData);
eventManager.subscribe("beforecut", handleBeforeCut);
eventManager.subscribe("cut", handleCut);
- eventManager.subscribe("copy", handleCopy);
eventManager.subscribe("beforepaste", handleBeforePaste);
eventManager.subscribe("paste", handlePaste);
- eventManager.subscribe("mousedown", handleMouseDown);
- eventManager.subscribe("mousemove", drawShadowCursorTask.trigger);
- eventManager.subscribe("mouseup", handleMouseUp);
- eventManager.subscribe("contextmenu", handleContextMenu);
- eventManager.subscribe("dragend", handleDragEnd);
- odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, redrawRegionSelectionTask.trigger);
- odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack);
- op = new ops.OpAddCursor;
- op.init({memberid:inputMemberId});
- session.enqueue([op]);
+ window.addEventListener("focus", hyperlinkClickHandler.showTextCursor, false);
if(undoManager) {
- undoManager.saveInitialState()
+ undoManager.initialize()
+ }
+ inputMethodEditor.setEditing(true);
+ hyperlinkClickHandler.setModifier(isMacOS ? gui.HyperlinkClickHandler.Modifier.Meta : gui.HyperlinkClickHandler.Modifier.Ctrl);
+ keyDownHandler.bind(keyCode.Backspace, modifier.None, returnTrue(textController.removeTextByBackspaceKey), true);
+ keyDownHandler.bind(keyCode.Delete, modifier.None, textController.removeTextByDeleteKey);
+ keyDownHandler.bind(keyCode.Tab, modifier.None, rangeSelectionOnly(function() {
+ textController.insertText("\t");
+ return true
+ }));
+ if(isMacOS) {
+ keyDownHandler.bind(keyCode.Clear, modifier.None, textController.removeCurrentSelection);
+ keyDownHandler.bind(keyCode.B, modifier.Meta, rangeSelectionOnly(directFormattingController.toggleBold));
+ keyDownHandler.bind(keyCode.I, modifier.Meta, rangeSelectionOnly(directFormattingController.toggleItalic));
+ keyDownHandler.bind(keyCode.U, modifier.Meta, rangeSelectionOnly(directFormattingController.toggleUnderline));
+ keyDownHandler.bind(keyCode.L, modifier.MetaShift, rangeSelectionOnly(directFormattingController.alignParagraphLeft));
+ keyDownHandler.bind(keyCode.E, modifier.MetaShift, rangeSelectionOnly(directFormattingController.alignParagraphCenter));
+ keyDownHandler.bind(keyCode.R, modifier.MetaShift, rangeSelectionOnly(directFormattingController.alignParagraphRight));
+ keyDownHandler.bind(keyCode.J, modifier.MetaShift, rangeSelectionOnly(directFormattingController.alignParagraphJustified));
+ keyDownHandler.bind(keyCode.C, modifier.MetaShift, annotationController.addAnnotation);
+ keyDownHandler.bind(keyCode.Z, modifier.Meta, undo);
+ keyDownHandler.bind(keyCode.Z, modifier.MetaShift, redo);
+ keyDownHandler.bind(keyCode.LeftMeta, modifier.Meta, hyperlinkClickHandler.showPointerCursor);
+ keyDownHandler.bind(keyCode.MetaInMozilla, modifier.Meta, hyperlinkClickHandler.showPointerCursor);
+ keyUpHandler.bind(keyCode.LeftMeta, modifier.None, hyperlinkClickHandler.showTextCursor);
+ keyUpHandler.bind(keyCode.MetaInMozilla, modifier.None, hyperlinkClickHandler.showTextCursor)
+ }else {
+ keyDownHandler.bind(keyCode.B, modifier.Ctrl, rangeSelectionOnly(directFormattingController.toggleBold));
+ keyDownHandler.bind(keyCode.I, modifier.Ctrl, rangeSelectionOnly(directFormattingController.toggleItalic));
+ keyDownHandler.bind(keyCode.U, modifier.Ctrl, rangeSelectionOnly(directFormattingController.toggleUnderline));
+ keyDownHandler.bind(keyCode.L, modifier.CtrlShift, rangeSelectionOnly(directFormattingController.alignParagraphLeft));
+ keyDownHandler.bind(keyCode.E, modifier.CtrlShift, rangeSelectionOnly(directFormattingController.alignParagraphCenter));
+ keyDownHandler.bind(keyCode.R, modifier.CtrlShift, rangeSelectionOnly(directFormattingController.alignParagraphRight));
+ keyDownHandler.bind(keyCode.J, modifier.CtrlShift, rangeSelectionOnly(directFormattingController.alignParagraphJustified));
+ keyDownHandler.bind(keyCode.C, modifier.CtrlAlt, annotationController.addAnnotation);
+ keyDownHandler.bind(keyCode.Z, modifier.Ctrl, undo);
+ keyDownHandler.bind(keyCode.Z, modifier.CtrlShift, redo);
+ keyDownHandler.bind(keyCode.Ctrl, modifier.Ctrl, hyperlinkClickHandler.showPointerCursor);
+ keyUpHandler.bind(keyCode.Ctrl, modifier.None, hyperlinkClickHandler.showTextCursor)
}
+ function handler(e) {
+ var text = stringFromKeyPress(e);
+ if(text && !(e.altKey || (e.ctrlKey || e.metaKey))) {
+ textController.insertText(text);
+ return true
+ }
+ return false
+ }
+ keyPressHandler.setDefault(rangeSelectionOnly(handler));
+ keyPressHandler.bind(keyCode.Enter, modifier.None, rangeSelectionOnly(textController.enqueueParagraphSplittingOps))
};
this.endEditing = function() {
- var op;
- op = new ops.OpRemoveCursor;
- op.init({memberid:inputMemberId});
- session.enqueue([op]);
- if(undoManager) {
- undoManager.resetInitialState()
- }
- odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack);
- odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, redrawRegionSelectionTask.trigger);
- eventManager.unsubscribe("keydown", keyDownHandler.handleEvent);
- eventManager.unsubscribe("keypress", keyPressHandler.handleEvent);
- eventManager.unsubscribe("keyup", dummyHandler);
+ inputMethodEditor.unsubscribe(gui.InputMethodEditor.signalCompositionStart, textController.removeCurrentSelection);
+ inputMethodEditor.unsubscribe(gui.InputMethodEditor.signalCompositionEnd, insertNonEmptyData);
eventManager.unsubscribe("cut", handleCut);
eventManager.unsubscribe("beforecut", handleBeforeCut);
- eventManager.unsubscribe("copy", handleCopy);
eventManager.unsubscribe("paste", handlePaste);
eventManager.unsubscribe("beforepaste", handleBeforePaste);
- eventManager.unsubscribe("mousemove", drawShadowCursorTask.trigger);
- eventManager.unsubscribe("mousedown", handleMouseDown);
- eventManager.unsubscribe("mouseup", handleMouseUp);
- eventManager.unsubscribe("contextmenu", handleContextMenu);
- eventManager.unsubscribe("dragend", handleDragEnd);
- odtDocument.getOdfCanvas().getElement().classList.remove("virtualSelections")
+ window.removeEventListener("focus", hyperlinkClickHandler.showTextCursor, false);
+ inputMethodEditor.setEditing(false);
+ hyperlinkClickHandler.setModifier(gui.HyperlinkClickHandler.Modifier.None);
+ keyDownHandler.bind(keyCode.Backspace, modifier.None, function() {
+ return true
+ }, true);
+ keyDownHandler.unbind(keyCode.Delete, modifier.None);
+ keyDownHandler.unbind(keyCode.Tab, modifier.None);
+ if(isMacOS) {
+ keyDownHandler.unbind(keyCode.Clear, modifier.None);
+ keyDownHandler.unbind(keyCode.B, modifier.Meta);
+ keyDownHandler.unbind(keyCode.I, modifier.Meta);
+ keyDownHandler.unbind(keyCode.U, modifier.Meta);
+ keyDownHandler.unbind(keyCode.L, modifier.MetaShift);
+ keyDownHandler.unbind(keyCode.E, modifier.MetaShift);
+ keyDownHandler.unbind(keyCode.R, modifier.MetaShift);
+ keyDownHandler.unbind(keyCode.J, modifier.MetaShift);
+ keyDownHandler.unbind(keyCode.C, modifier.MetaShift);
+ keyDownHandler.unbind(keyCode.Z, modifier.Meta);
+ keyDownHandler.unbind(keyCode.Z, modifier.MetaShift);
+ keyDownHandler.unbind(keyCode.LeftMeta, modifier.Meta);
+ keyDownHandler.unbind(keyCode.MetaInMozilla, modifier.Meta);
+ keyUpHandler.unbind(keyCode.LeftMeta, modifier.None);
+ keyUpHandler.unbind(keyCode.MetaInMozilla, modifier.None)
+ }else {
+ keyDownHandler.unbind(keyCode.B, modifier.Ctrl);
+ keyDownHandler.unbind(keyCode.I, modifier.Ctrl);
+ keyDownHandler.unbind(keyCode.U, modifier.Ctrl);
+ keyDownHandler.unbind(keyCode.L, modifier.CtrlShift);
+ keyDownHandler.unbind(keyCode.E, modifier.CtrlShift);
+ keyDownHandler.unbind(keyCode.R, modifier.CtrlShift);
+ keyDownHandler.unbind(keyCode.J, modifier.CtrlShift);
+ keyDownHandler.unbind(keyCode.C, modifier.CtrlAlt);
+ keyDownHandler.unbind(keyCode.Z, modifier.Ctrl);
+ keyDownHandler.unbind(keyCode.Z, modifier.CtrlShift);
+ keyDownHandler.unbind(keyCode.Ctrl, modifier.Ctrl);
+ keyUpHandler.unbind(keyCode.Ctrl, modifier.None)
+ }
+ keyPressHandler.setDefault(null);
+ keyPressHandler.unbind(keyCode.Enter, modifier.None)
};
this.getInputMemberId = function() {
return inputMemberId
@@ -17625,10 +15362,8 @@ gui.SessionController = function() {
}
undoManager = manager;
if(undoManager) {
- undoManager.setOdtDocument(odtDocument);
- undoManager.setPlaybackFunction(function(op) {
- op.execute(odtDocument)
- });
+ undoManager.setDocument(odtDocument);
+ undoManager.setPlaybackFunction(session.enqueue);
undoManager.subscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange)
}
};
@@ -17638,17 +15373,20 @@ gui.SessionController = function() {
this.getAnnotationController = function() {
return annotationController
};
- this.getDirectTextStyler = function() {
- return directTextStyler
+ this.getDirectFormattingController = function() {
+ return directFormattingController
+ };
+ this.getHyperlinkController = function() {
+ return hyperlinkController
};
- this.getDirectParagraphStyler = function() {
- return directParagraphStyler
+ this.getImageController = function() {
+ return imageController
};
- this.getImageManager = function() {
- return imageManager
+ this.getSelectionController = function() {
+ return selectionController
};
- this.getTextManipulator = function() {
- return textManipulator
+ this.getTextController = function() {
+ return textController
};
this.getEventManager = function() {
return eventManager
@@ -17656,114 +15394,100 @@ gui.SessionController = function() {
this.getKeyboardHandlers = function() {
return{keydown:keyDownHandler, keypress:keyPressHandler}
};
+ function destroy(callback) {
+ eventManager.unsubscribe("keydown", keyDownHandler.handleEvent);
+ eventManager.unsubscribe("keypress", keyPressHandler.handleEvent);
+ eventManager.unsubscribe("keyup", keyUpHandler.handleEvent);
+ eventManager.unsubscribe("copy", handleCopy);
+ eventManager.unsubscribe("mousedown", handleMouseDown);
+ eventManager.unsubscribe("mousemove", drawShadowCursorTask.trigger);
+ eventManager.unsubscribe("mouseup", handleMouseUp);
+ eventManager.unsubscribe("contextmenu", handleContextMenu);
+ eventManager.unsubscribe("dragstart", handleDragStart);
+ eventManager.unsubscribe("dragend", handleDragEnd);
+ eventManager.unsubscribe("click", hyperlinkClickHandler.handleClick);
+ odtDocument.unsubscribe(ops.OdtDocument.signalOperationEnd, redrawRegionSelectionTask.trigger);
+ odtDocument.unsubscribe(ops.Document.signalCursorAdded, inputMethodEditor.registerCursor);
+ odtDocument.unsubscribe(ops.Document.signalCursorRemoved, inputMethodEditor.removeCursor);
+ odtDocument.unsubscribe(ops.OdtDocument.signalOperationEnd, updateUndoStack);
+ callback()
+ }
this.destroy = function(callback) {
- var destroyCallbacks = [drawShadowCursorTask.destroy, directTextStyler.destroy];
- if(directParagraphStyler) {
- destroyCallbacks.push(directParagraphStyler.destroy)
+ var destroyCallbacks = [];
+ if(iOSSafariSupport) {
+ destroyCallbacks.push(iOSSafariSupport.destroy)
}
+ destroyCallbacks = destroyCallbacks.concat([drawShadowCursorTask.destroy, redrawRegionSelectionTask.destroy, directFormattingController.destroy, inputMethodEditor.destroy, eventManager.destroy, destroy]);
+ runtime.clearTimeout(handleMouseClickTimeoutId);
async.destroyAll(destroyCallbacks, callback)
};
- function returnTrue(fn) {
- return function() {
- fn();
- return true
- }
- }
- function rangeSelectionOnly(fn) {
- return function(e) {
- var selectionType = odtDocument.getCursor(inputMemberId).getSelectionType();
- if(selectionType === ops.OdtCursor.RangeSelection) {
- return fn(e)
- }
- return true
- }
- }
function init() {
- var isMacOS = window.navigator.appVersion.toLowerCase().indexOf("mac") !== -1, modifier = gui.KeyboardHandler.Modifier, keyCode = gui.KeyboardHandler.KeyCode;
drawShadowCursorTask = new core.ScheduledTask(updateShadowCursor, 0);
redrawRegionSelectionTask = new core.ScheduledTask(redrawRegionSelection, 0);
- keyDownHandler.bind(keyCode.Tab, modifier.None, rangeSelectionOnly(function() {
- textManipulator.insertText("\t");
- return true
- }));
- keyDownHandler.bind(keyCode.Left, modifier.None, rangeSelectionOnly(moveCursorToLeft));
- keyDownHandler.bind(keyCode.Right, modifier.None, rangeSelectionOnly(moveCursorToRight));
- keyDownHandler.bind(keyCode.Up, modifier.None, rangeSelectionOnly(moveCursorUp));
- keyDownHandler.bind(keyCode.Down, modifier.None, rangeSelectionOnly(moveCursorDown));
- keyDownHandler.bind(keyCode.Backspace, modifier.None, returnTrue(textManipulator.removeTextByBackspaceKey));
- keyDownHandler.bind(keyCode.Delete, modifier.None, textManipulator.removeTextByDeleteKey);
- keyDownHandler.bind(keyCode.Left, modifier.Shift, rangeSelectionOnly(extendSelectionToLeft));
- keyDownHandler.bind(keyCode.Right, modifier.Shift, rangeSelectionOnly(extendSelectionToRight));
- keyDownHandler.bind(keyCode.Up, modifier.Shift, rangeSelectionOnly(extendSelectionUp));
- keyDownHandler.bind(keyCode.Down, modifier.Shift, rangeSelectionOnly(extendSelectionDown));
- keyDownHandler.bind(keyCode.Home, modifier.None, rangeSelectionOnly(moveCursorToLineStart));
- keyDownHandler.bind(keyCode.End, modifier.None, rangeSelectionOnly(moveCursorToLineEnd));
- keyDownHandler.bind(keyCode.Home, modifier.Ctrl, rangeSelectionOnly(moveCursorToDocumentStart));
- keyDownHandler.bind(keyCode.End, modifier.Ctrl, rangeSelectionOnly(moveCursorToDocumentEnd));
- keyDownHandler.bind(keyCode.Home, modifier.Shift, rangeSelectionOnly(extendSelectionToLineStart));
- keyDownHandler.bind(keyCode.End, modifier.Shift, rangeSelectionOnly(extendSelectionToLineEnd));
- keyDownHandler.bind(keyCode.Up, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToParagraphStart));
- keyDownHandler.bind(keyCode.Down, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToParagraphEnd));
- keyDownHandler.bind(keyCode.Home, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToDocumentStart));
- keyDownHandler.bind(keyCode.End, modifier.CtrlShift, rangeSelectionOnly(extendSelectionToDocumentEnd));
+ keyDownHandler.bind(keyCode.Left, modifier.None, rangeSelectionOnly(selectionController.moveCursorToLeft));
+ keyDownHandler.bind(keyCode.Right, modifier.None, rangeSelectionOnly(selectionController.moveCursorToRight));
+ keyDownHandler.bind(keyCode.Up, modifier.None, rangeSelectionOnly(selectionController.moveCursorUp));
+ keyDownHandler.bind(keyCode.Down, modifier.None, rangeSelectionOnly(selectionController.moveCursorDown));
+ keyDownHandler.bind(keyCode.Left, modifier.Shift, rangeSelectionOnly(selectionController.extendSelectionToLeft));
+ keyDownHandler.bind(keyCode.Right, modifier.Shift, rangeSelectionOnly(selectionController.extendSelectionToRight));
+ keyDownHandler.bind(keyCode.Up, modifier.Shift, rangeSelectionOnly(selectionController.extendSelectionUp));
+ keyDownHandler.bind(keyCode.Down, modifier.Shift, rangeSelectionOnly(selectionController.extendSelectionDown));
+ keyDownHandler.bind(keyCode.Home, modifier.None, rangeSelectionOnly(selectionController.moveCursorToLineStart));
+ keyDownHandler.bind(keyCode.End, modifier.None, rangeSelectionOnly(selectionController.moveCursorToLineEnd));
+ keyDownHandler.bind(keyCode.Home, modifier.Ctrl, rangeSelectionOnly(selectionController.moveCursorToDocumentStart));
+ keyDownHandler.bind(keyCode.End, modifier.Ctrl, rangeSelectionOnly(selectionController.moveCursorToDocumentEnd));
+ keyDownHandler.bind(keyCode.Home, modifier.Shift, rangeSelectionOnly(selectionController.extendSelectionToLineStart));
+ keyDownHandler.bind(keyCode.End, modifier.Shift, rangeSelectionOnly(selectionController.extendSelectionToLineEnd));
+ keyDownHandler.bind(keyCode.Up, modifier.CtrlShift, rangeSelectionOnly(selectionController.extendSelectionToParagraphStart));
+ keyDownHandler.bind(keyCode.Down, modifier.CtrlShift, rangeSelectionOnly(selectionController.extendSelectionToParagraphEnd));
+ keyDownHandler.bind(keyCode.Home, modifier.CtrlShift, rangeSelectionOnly(selectionController.extendSelectionToDocumentStart));
+ keyDownHandler.bind(keyCode.End, modifier.CtrlShift, rangeSelectionOnly(selectionController.extendSelectionToDocumentEnd));
if(isMacOS) {
- keyDownHandler.bind(keyCode.Clear, modifier.None, textManipulator.removeCurrentSelection);
- keyDownHandler.bind(keyCode.Left, modifier.Meta, rangeSelectionOnly(moveCursorToLineStart));
- keyDownHandler.bind(keyCode.Right, modifier.Meta, rangeSelectionOnly(moveCursorToLineEnd));
- keyDownHandler.bind(keyCode.Home, modifier.Meta, rangeSelectionOnly(moveCursorToDocumentStart));
- keyDownHandler.bind(keyCode.End, modifier.Meta, rangeSelectionOnly(moveCursorToDocumentEnd));
- keyDownHandler.bind(keyCode.Left, modifier.MetaShift, rangeSelectionOnly(extendSelectionToLineStart));
- keyDownHandler.bind(keyCode.Right, modifier.MetaShift, rangeSelectionOnly(extendSelectionToLineEnd));
- keyDownHandler.bind(keyCode.Up, modifier.AltShift, rangeSelectionOnly(extendSelectionToParagraphStart));
- keyDownHandler.bind(keyCode.Down, modifier.AltShift, rangeSelectionOnly(extendSelectionToParagraphEnd));
- keyDownHandler.bind(keyCode.Up, modifier.MetaShift, rangeSelectionOnly(extendSelectionToDocumentStart));
- keyDownHandler.bind(keyCode.Down, modifier.MetaShift, rangeSelectionOnly(extendSelectionToDocumentEnd));
- keyDownHandler.bind(keyCode.A, modifier.Meta, rangeSelectionOnly(extendSelectionToEntireDocument));
- keyDownHandler.bind(keyCode.B, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleBold));
- keyDownHandler.bind(keyCode.I, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleItalic));
- keyDownHandler.bind(keyCode.U, modifier.Meta, rangeSelectionOnly(directTextStyler.toggleUnderline));
- if(directParagraphStyler) {
- keyDownHandler.bind(keyCode.L, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphLeft));
- keyDownHandler.bind(keyCode.E, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphCenter));
- keyDownHandler.bind(keyCode.R, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphRight));
- keyDownHandler.bind(keyCode.J, modifier.MetaShift, rangeSelectionOnly(directParagraphStyler.alignParagraphJustified))
- }
- if(annotationController) {
- keyDownHandler.bind(keyCode.C, modifier.MetaShift, annotationController.addAnnotation)
- }
- keyDownHandler.bind(keyCode.Z, modifier.Meta, undo);
- keyDownHandler.bind(keyCode.Z, modifier.MetaShift, redo)
+ keyDownHandler.bind(keyCode.Left, modifier.Alt, rangeSelectionOnly(selectionController.moveCursorBeforeWord));
+ keyDownHandler.bind(keyCode.Right, modifier.Alt, rangeSelectionOnly(selectionController.moveCursorPastWord));
+ keyDownHandler.bind(keyCode.Left, modifier.Meta, rangeSelectionOnly(selectionController.moveCursorToLineStart));
+ keyDownHandler.bind(keyCode.Right, modifier.Meta, rangeSelectionOnly(selectionController.moveCursorToLineEnd));
+ keyDownHandler.bind(keyCode.Home, modifier.Meta, rangeSelectionOnly(selectionController.moveCursorToDocumentStart));
+ keyDownHandler.bind(keyCode.End, modifier.Meta, rangeSelectionOnly(selectionController.moveCursorToDocumentEnd));
+ keyDownHandler.bind(keyCode.Left, modifier.AltShift, rangeSelectionOnly(selectionController.extendSelectionBeforeWord));
+ keyDownHandler.bind(keyCode.Right, modifier.AltShift, rangeSelectionOnly(selectionController.extendSelectionPastWord));
+ keyDownHandler.bind(keyCode.Left, modifier.MetaShift, rangeSelectionOnly(selectionController.extendSelectionToLineStart));
+ keyDownHandler.bind(keyCode.Right, modifier.MetaShift, rangeSelectionOnly(selectionController.extendSelectionToLineEnd));
+ keyDownHandler.bind(keyCode.Up, modifier.AltShift, rangeSelectionOnly(selectionController.extendSelectionToParagraphStart));
+ keyDownHandler.bind(keyCode.Down, modifier.AltShift, rangeSelectionOnly(selectionController.extendSelectionToParagraphEnd));
+ keyDownHandler.bind(keyCode.Up, modifier.MetaShift, rangeSelectionOnly(selectionController.extendSelectionToDocumentStart));
+ keyDownHandler.bind(keyCode.Down, modifier.MetaShift, rangeSelectionOnly(selectionController.extendSelectionToDocumentEnd));
+ keyDownHandler.bind(keyCode.A, modifier.Meta, rangeSelectionOnly(selectionController.extendSelectionToEntireDocument))
}else {
- keyDownHandler.bind(keyCode.A, modifier.Ctrl, rangeSelectionOnly(extendSelectionToEntireDocument));
- keyDownHandler.bind(keyCode.B, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleBold));
- keyDownHandler.bind(keyCode.I, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleItalic));
- keyDownHandler.bind(keyCode.U, modifier.Ctrl, rangeSelectionOnly(directTextStyler.toggleUnderline));
- if(directParagraphStyler) {
- keyDownHandler.bind(keyCode.L, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphLeft));
- keyDownHandler.bind(keyCode.E, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphCenter));
- keyDownHandler.bind(keyCode.R, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphRight));
- keyDownHandler.bind(keyCode.J, modifier.CtrlShift, rangeSelectionOnly(directParagraphStyler.alignParagraphJustified))
- }
- if(annotationController) {
- keyDownHandler.bind(keyCode.C, modifier.CtrlAlt, annotationController.addAnnotation)
- }
- keyDownHandler.bind(keyCode.Z, modifier.Ctrl, undo);
- keyDownHandler.bind(keyCode.Z, modifier.CtrlShift, redo)
+ keyDownHandler.bind(keyCode.Left, modifier.Ctrl, rangeSelectionOnly(selectionController.moveCursorBeforeWord));
+ keyDownHandler.bind(keyCode.Right, modifier.Ctrl, rangeSelectionOnly(selectionController.moveCursorPastWord));
+ keyDownHandler.bind(keyCode.Left, modifier.CtrlShift, rangeSelectionOnly(selectionController.extendSelectionBeforeWord));
+ keyDownHandler.bind(keyCode.Right, modifier.CtrlShift, rangeSelectionOnly(selectionController.extendSelectionPastWord));
+ keyDownHandler.bind(keyCode.A, modifier.Ctrl, rangeSelectionOnly(selectionController.extendSelectionToEntireDocument))
}
- keyPressHandler.setDefault(rangeSelectionOnly(function(e) {
- var text = stringFromKeyPress(e);
- if(text && !(e.altKey || (e.ctrlKey || e.metaKey))) {
- textManipulator.insertText(text);
- return true
- }
- return false
- }));
- keyPressHandler.bind(keyCode.Enter, modifier.None, rangeSelectionOnly(textManipulator.enqueueParagraphSplittingOps))
+ if(isIOS) {
+ iOSSafariSupport = new gui.IOSSafariSupport(eventManager)
+ }
+ eventManager.subscribe("keydown", keyDownHandler.handleEvent);
+ eventManager.subscribe("keypress", keyPressHandler.handleEvent);
+ eventManager.subscribe("keyup", keyUpHandler.handleEvent);
+ eventManager.subscribe("copy", handleCopy);
+ eventManager.subscribe("mousedown", handleMouseDown);
+ eventManager.subscribe("mousemove", drawShadowCursorTask.trigger);
+ eventManager.subscribe("mouseup", handleMouseUp);
+ eventManager.subscribe("contextmenu", handleContextMenu);
+ eventManager.subscribe("dragstart", handleDragStart);
+ eventManager.subscribe("dragend", handleDragEnd);
+ eventManager.subscribe("click", hyperlinkClickHandler.handleClick);
+ odtDocument.subscribe(ops.OdtDocument.signalOperationEnd, redrawRegionSelectionTask.trigger);
+ odtDocument.subscribe(ops.Document.signalCursorAdded, inputMethodEditor.registerCursor);
+ odtDocument.subscribe(ops.Document.signalCursorRemoved, inputMethodEditor.removeCursor);
+ odtDocument.subscribe(ops.OdtDocument.signalOperationEnd, updateUndoStack)
}
init()
};
return gui.SessionController
-}();
+})();
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -17801,9 +15525,8 @@ gui.SessionController = function() {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("gui.Caret");
gui.CaretManager = function CaretManager(sessionController) {
- var carets = {}, window = runtime.getWindow(), scrollIntoViewScheduled = false;
+ var carets = {}, async = new core.Async, window = runtime.getWindow(), ensureCaretVisibleTimeoutId, scrollIntoViewScheduled = false;
function getCaret(memberId) {
return carets.hasOwnProperty(memberId) ? carets[memberId] : null
}
@@ -17812,14 +15535,13 @@ gui.CaretManager = function CaretManager(sessionController) {
return carets[memberid]
})
}
- function getCanvasElement() {
- return sessionController.getSession().getOdtDocument().getOdfCanvas().getElement()
- }
function removeCaret(memberId) {
- if(memberId === sessionController.getInputMemberId()) {
- getCanvasElement().removeAttribute("tabindex")
+ var caret = carets[memberId];
+ if(caret) {
+ caret.destroy(function() {
+ });
+ delete carets[memberId]
}
- delete carets[memberId]
}
function refreshLocalCaretBlinking(cursor) {
var caret, memberId = cursor.getMemberId();
@@ -17843,7 +15565,7 @@ gui.CaretManager = function CaretManager(sessionController) {
caret.handleUpdate();
if(!scrollIntoViewScheduled) {
scrollIntoViewScheduled = true;
- runtime.setTimeout(executeEnsureCaretVisible, 50)
+ ensureCaretVisibleTimeoutId = runtime.setTimeout(executeEnsureCaretVisible, 50)
}
}
}
@@ -17877,49 +15599,39 @@ gui.CaretManager = function CaretManager(sessionController) {
}
}
this.registerCursor = function(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect) {
- var memberid = cursor.getMemberId(), caret = new gui.Caret(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect);
+ var memberid = cursor.getMemberId(), caret = new gui.Caret(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect), eventManager = sessionController.getEventManager();
carets[memberid] = caret;
if(memberid === sessionController.getInputMemberId()) {
runtime.log("Starting to track input on new cursor of " + memberid);
- cursor.handleUpdate = scheduleCaretVisibilityCheck;
- getCanvasElement().setAttribute("tabindex", -1);
- sessionController.getEventManager().focus()
+ cursor.subscribe(ops.OdtCursor.signalCursorUpdated, scheduleCaretVisibilityCheck);
+ caret.setOverlayElement(eventManager.getEventTrap())
}else {
- cursor.handleUpdate = caret.handleUpdate
+ cursor.subscribe(ops.OdtCursor.signalCursorUpdated, caret.handleUpdate)
}
return caret
};
this.getCaret = getCaret;
this.getCarets = getCarets;
this.destroy = function(callback) {
- var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager(), caretArray = getCarets();
+ var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager(), caretCleanup = getCarets().map(function(caret) {
+ return caret.destroy
+ });
+ runtime.clearTimeout(ensureCaretVisibleTimeoutId);
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
+ odtDocument.unsubscribe(ops.Document.signalCursorMoved, refreshLocalCaretBlinking);
+ odtDocument.unsubscribe(ops.Document.signalCursorRemoved, removeCaret);
eventManager.unsubscribe("focus", focusLocalCaret);
eventManager.unsubscribe("blur", blurLocalCaret);
window.removeEventListener("focus", showLocalCaret, false);
window.removeEventListener("blur", hideLocalCaret, false);
- (function destroyCaret(i, err) {
- if(err) {
- callback(err)
- }else {
- if(i < caretArray.length) {
- caretArray[i].destroy(function(err) {
- destroyCaret(i + 1, err)
- })
- }else {
- callback()
- }
- }
- })(0, undefined);
- carets = {}
+ carets = {};
+ async.destroyAll(caretCleanup, callback)
};
function init() {
var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager();
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
+ odtDocument.subscribe(ops.Document.signalCursorMoved, refreshLocalCaretBlinking);
+ odtDocument.subscribe(ops.Document.signalCursorRemoved, removeCaret);
eventManager.subscribe("focus", focusLocalCaret);
eventManager.subscribe("blur", blurLocalCaret);
window.addEventListener("focus", showLocalCaret, false);
@@ -17927,6 +15639,406 @@ gui.CaretManager = function CaretManager(sessionController) {
}
init()
};
+gui.EditInfoHandle = function EditInfoHandle(parentElement) {
+ var edits = [], handle, document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI, editinfons = "urn:webodf:names:editinfo";
+ function renderEdits() {
+ var i, infoDiv, colorSpan, authorSpan, timeSpan;
+ handle.innerHTML = "";
+ for(i = 0;i < edits.length;i += 1) {
+ infoDiv = document.createElementNS(htmlns, "div");
+ infoDiv.className = "editInfo";
+ colorSpan = document.createElementNS(htmlns, "span");
+ colorSpan.className = "editInfoColor";
+ colorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
+ authorSpan = document.createElementNS(htmlns, "span");
+ authorSpan.className = "editInfoAuthor";
+ authorSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
+ timeSpan = document.createElementNS(htmlns, "span");
+ timeSpan.className = "editInfoTime";
+ timeSpan.setAttributeNS(editinfons, "editinfo:memberid", edits[i].memberid);
+ timeSpan.innerHTML = edits[i].time;
+ infoDiv.appendChild(colorSpan);
+ infoDiv.appendChild(authorSpan);
+ infoDiv.appendChild(timeSpan);
+ handle.appendChild(infoDiv)
+ }
+ }
+ this.setEdits = function(editArray) {
+ edits = editArray;
+ renderEdits()
+ };
+ this.show = function() {
+ handle.style.display = "block"
+ };
+ this.hide = function() {
+ handle.style.display = "none"
+ };
+ this.destroy = function(callback) {
+ parentElement.removeChild(handle);
+ callback()
+ };
+ function init() {
+ handle = (document.createElementNS(htmlns, "div"));
+ handle.setAttribute("class", "editInfoHandle");
+ handle.style.display = "none";
+ parentElement.appendChild(handle)
+ }
+ init()
+};
+/*
+
+ Copyright (C) 2012 KO GmbH <aditya.bhatt@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.EditInfo = function EditInfo(container, odtDocument) {
+ var editInfoNode, editHistory = {};
+ function sortEdits() {
+ var arr = [], memberid;
+ for(memberid in editHistory) {
+ if(editHistory.hasOwnProperty(memberid)) {
+ arr.push({"memberid":memberid, "time":editHistory[memberid].time})
+ }
+ }
+ arr.sort(function(a, b) {
+ return a.time - b.time
+ });
+ return arr
+ }
+ this.getNode = function() {
+ return editInfoNode
+ };
+ this.getOdtDocument = function() {
+ return odtDocument
+ };
+ this.getEdits = function() {
+ return editHistory
+ };
+ this.getSortedEdits = function() {
+ return sortEdits()
+ };
+ this.addEdit = function(memberid, timestamp) {
+ editHistory[memberid] = {time:timestamp}
+ };
+ this.clearEdits = function() {
+ editHistory = {}
+ };
+ this.destroy = function(callback) {
+ if(container.parentNode) {
+ container.removeChild(editInfoNode)
+ }
+ callback()
+ };
+ function init() {
+ var editInfons = "urn:webodf:names:editinfo", dom = odtDocument.getDOMDocument();
+ editInfoNode = dom.createElementNS(editInfons, "editinfo");
+ container.insertBefore(editInfoNode, container.firstChild)
+ }
+ init()
+};
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
+ var self = this, editInfoNode, handle, marker, editinfons = "urn:webodf:names:editinfo", decayTimer0, decayTimer1, decayTimer2, decayTimeStep = 1E4;
+ function applyDecay(opacity, delay) {
+ return runtime.setTimeout(function() {
+ marker.style.opacity = opacity
+ }, delay)
+ }
+ function deleteDecay(timerId) {
+ runtime.clearTimeout(timerId)
+ }
+ function setLastAuthor(memberid) {
+ marker.setAttributeNS(editinfons, "editinfo:memberid", memberid)
+ }
+ this.addEdit = function(memberid, timestamp) {
+ var age = Date.now() - timestamp;
+ editInfo.addEdit(memberid, timestamp);
+ handle.setEdits(editInfo.getSortedEdits());
+ setLastAuthor(memberid);
+ deleteDecay(decayTimer1);
+ deleteDecay(decayTimer2);
+ if(age < decayTimeStep) {
+ decayTimer0 = applyDecay(1, 0);
+ decayTimer1 = applyDecay(0.5, decayTimeStep - age);
+ decayTimer2 = applyDecay(0.2, decayTimeStep * 2 - age)
+ }else {
+ if(age >= decayTimeStep && age < decayTimeStep * 2) {
+ decayTimer0 = applyDecay(0.5, 0);
+ decayTimer2 = applyDecay(0.2, decayTimeStep * 2 - age)
+ }else {
+ decayTimer0 = applyDecay(0.2, 0)
+ }
+ }
+ };
+ this.getEdits = function() {
+ return editInfo.getEdits()
+ };
+ this.clearEdits = function() {
+ editInfo.clearEdits();
+ handle.setEdits([]);
+ if(marker.hasAttributeNS(editinfons, "editinfo:memberid")) {
+ marker.removeAttributeNS(editinfons, "editinfo:memberid")
+ }
+ };
+ this.getEditInfo = function() {
+ return editInfo
+ };
+ this.show = function() {
+ marker.style.display = "block"
+ };
+ this.hide = function() {
+ self.hideHandle();
+ marker.style.display = "none"
+ };
+ this.showHandle = function() {
+ handle.show()
+ };
+ this.hideHandle = function() {
+ handle.hide()
+ };
+ this.destroy = function(callback) {
+ deleteDecay(decayTimer0);
+ deleteDecay(decayTimer1);
+ deleteDecay(decayTimer2);
+ editInfoNode.removeChild(marker);
+ handle.destroy(function(err) {
+ if(err) {
+ callback(err)
+ }else {
+ editInfo.destroy(callback)
+ }
+ })
+ };
+ function init() {
+ var dom = editInfo.getOdtDocument().getDOMDocument(), htmlns = dom.documentElement.namespaceURI;
+ marker = (dom.createElementNS(htmlns, "div"));
+ marker.setAttribute("class", "editInfoMarker");
+ marker.onmouseover = function() {
+ self.showHandle()
+ };
+ marker.onmouseout = function() {
+ self.hideHandle()
+ };
+ editInfoNode = editInfo.getNode();
+ editInfoNode.appendChild(marker);
+ handle = new gui.EditInfoHandle(editInfoNode);
+ if(!initialVisibility) {
+ self.hide()
+ }
+ }
+ init()
+};
+gui.ShadowCursor = function ShadowCursor(document) {
+ var selectedRange = (document.getDOMDocument().createRange()), forwardSelection = true;
+ this.removeFromDocument = function() {
+ };
+ this.getMemberId = function() {
+ return gui.ShadowCursor.ShadowCursorMemberId
+ };
+ this.getSelectedRange = function() {
+ return selectedRange
+ };
+ this.setSelectedRange = function(range, isForwardSelection) {
+ selectedRange = range;
+ forwardSelection = isForwardSelection !== false
+ };
+ this.hasForwardSelection = function() {
+ return forwardSelection
+ };
+ this.getDocument = function() {
+ return document
+ };
+ this.getSelectionType = function() {
+ return ops.OdtCursor.RangeSelection
+ };
+ function init() {
+ selectedRange.setStart(document.getRootNode(), 0)
+ }
+ init()
+};
+gui.ShadowCursor.ShadowCursorMemberId = "";
+(function() {
+ return gui.ShadowCursor
+})();
+gui.SelectionView = function SelectionView(cursor) {
+};
+gui.SelectionView.prototype.rerender = function() {
+};
+gui.SelectionView.prototype.show = function() {
+};
+gui.SelectionView.prototype.hide = function() {
+};
+gui.SelectionView.prototype.destroy = function(callback) {
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.SelectionViewManager = function SelectionViewManager(SelectionView) {
+ var selectionViews = {};
+ function getSelectionView(memberId) {
+ return selectionViews.hasOwnProperty(memberId) ? selectionViews[memberId] : null
+ }
+ this.getSelectionView = getSelectionView;
+ function getSelectionViews() {
+ return Object.keys(selectionViews).map(function(memberid) {
+ return selectionViews[memberid]
+ })
+ }
+ this.getSelectionViews = getSelectionViews;
+ function removeSelectionView(memberId) {
+ if(selectionViews.hasOwnProperty(memberId)) {
+ selectionViews[memberId].destroy(function() {
+ });
+ delete selectionViews[memberId]
+ }
+ }
+ this.removeSelectionView = removeSelectionView;
+ function hideSelectionView(memberId) {
+ if(selectionViews.hasOwnProperty(memberId)) {
+ selectionViews[memberId].hide()
+ }
+ }
+ this.hideSelectionView = hideSelectionView;
+ function showSelectionView(memberId) {
+ if(selectionViews.hasOwnProperty(memberId)) {
+ selectionViews[memberId].show()
+ }
+ }
+ this.showSelectionView = showSelectionView;
+ this.rerenderSelectionViews = function() {
+ Object.keys(selectionViews).forEach(function(memberId) {
+ selectionViews[memberId].rerender()
+ })
+ };
+ this.registerCursor = function(cursor, virtualSelectionsInitiallyVisible) {
+ var memberId = cursor.getMemberId(), selectionView = new SelectionView(cursor);
+ if(virtualSelectionsInitiallyVisible) {
+ selectionView.show()
+ }else {
+ selectionView.hide()
+ }
+ selectionViews[memberId] = selectionView;
+ return selectionView
+ };
+ this.destroy = function(callback) {
+ var selectionViewArray = getSelectionViews();
+ function destroySelectionView(i, err) {
+ if(err) {
+ callback(err)
+ }else {
+ if(i < selectionViewArray.length) {
+ selectionViewArray[i].destroy(function(err) {
+ destroySelectionView(i + 1, err)
+ })
+ }else {
+ callback()
+ }
+ }
+ }
+ destroySelectionView(0, undefined)
+ }
+};
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -17964,27 +16076,24 @@ gui.CaretManager = function CaretManager(sessionController) {
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("gui.Caret");
-runtime.loadClass("ops.EditInfo");
-runtime.loadClass("gui.EditInfoMarker");
gui.SessionViewOptions = function() {
this.editInfoMarkersInitiallyVisible = true;
this.caretAvatarsInitiallyVisible = true;
this.caretBlinksOnRangeSelect = true
};
-gui.SessionView = function() {
+(function() {
function configOption(userValue, defaultValue) {
return userValue !== undefined ? Boolean(userValue) : defaultValue
}
- function SessionView(viewOptions, localMemberId, session, caretManager, selectionViewManager) {
- var avatarInfoStyles, editInfons = "urn:webodf:names:editinfo", editInfoMap = {}, showEditInfoMarkers = configOption(viewOptions.editInfoMarkersInitiallyVisible, true), showCaretAvatars = configOption(viewOptions.caretAvatarsInitiallyVisible, true), blinkOnRangeSelect = configOption(viewOptions.caretBlinksOnRangeSelect, true), rerenderIntervalId, rerenderSelectionViews = false, RERENDER_INTERVAL = 200;
+ gui.SessionView = function SessionView(viewOptions, localMemberId, session, caretManager, selectionViewManager) {
+ var avatarInfoStyles, editInfons = "urn:webodf:names:editinfo", editInfoMap = {}, showEditInfoMarkers = configOption(viewOptions.editInfoMarkersInitiallyVisible, true), showCaretAvatars = configOption(viewOptions.caretAvatarsInitiallyVisible, true), blinkOnRangeSelect = configOption(viewOptions.caretBlinksOnRangeSelect, true);
function createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) {
return nodeName + '[editinfo|memberid="' + memberId + '"]' + pseudoClass
}
function getAvatarInfoStyle(nodeName, memberId, pseudoClass) {
var node = avatarInfoStyles.firstChild, nodeMatch = createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) + "{";
while(node) {
- if(node.nodeType === Node.TEXT_NODE && node.data.indexOf(nodeMatch) === 0) {
+ if(node.nodeType === Node.TEXT_NODE && (node).data.indexOf(nodeMatch) === 0) {
return node
}
node = node.nextSibling
@@ -18004,18 +16113,18 @@ gui.SessionView = function() {
setStyle("span.editInfoColor", "{ background-color: " + color + "; }", "");
setStyle("span.editInfoAuthor", '{ content: "' + name + '"; }', ":before");
setStyle("dc|creator", "{ background-color: " + color + "; }", "");
- setStyle("div.selectionOverlay", "{ background-color: " + color + ";}", "")
+ setStyle(".selectionOverlay", "{ fill: " + color + "; stroke: " + color + ";}", "")
}
function highlightEdit(element, memberId, timestamp) {
- var editInfo, editInfoMarker, id = "", editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0];
+ var editInfo, editInfoMarker, id = "", editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo").item(0);
if(editInfoNode) {
- id = editInfoNode.getAttributeNS(editInfons, "id");
+ id = (editInfoNode).getAttributeNS(editInfons, "id");
editInfoMarker = editInfoMap[id]
}else {
id = Math.random().toString();
editInfo = new ops.EditInfo(element, session.getOdtDocument());
editInfoMarker = new gui.EditInfoMarker(editInfo, showEditInfoMarkers);
- editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0];
+ editInfoNode = (element.getElementsByTagNameNS(editInfons, "editinfo").item(0));
editInfoNode.setAttributeNS(editInfons, "id", id);
editInfoMap[id] = editInfoMarker
}
@@ -18123,34 +16232,19 @@ gui.SessionView = function() {
function onParagraphChanged(info) {
highlightEdit(info.paragraphElement, info.memberId, info.timeStamp)
}
- function requestRerenderOfSelectionViews() {
- rerenderSelectionViews = true
- }
- function startRerenderLoop() {
- rerenderIntervalId = runtime.getWindow().setInterval(function() {
- if(rerenderSelectionViews) {
- selectionViewManager.rerenderSelectionViews();
- rerenderSelectionViews = false
- }
- }, RERENDER_INTERVAL)
- }
- function stopRerenderLoop() {
- runtime.getWindow().clearInterval(rerenderIntervalId)
- }
this.destroy = function(callback) {
var odtDocument = session.getOdtDocument(), editInfoArray = Object.keys(editInfoMap).map(function(keyname) {
return editInfoMap[keyname]
});
- odtDocument.unsubscribe(ops.OdtDocument.signalMemberAdded, renderMemberData);
- odtDocument.unsubscribe(ops.OdtDocument.signalMemberUpdated, renderMemberData);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
+ odtDocument.unsubscribe(ops.Document.signalMemberAdded, renderMemberData);
+ odtDocument.unsubscribe(ops.Document.signalMemberUpdated, renderMemberData);
+ odtDocument.unsubscribe(ops.Document.signalCursorAdded, onCursorAdded);
+ odtDocument.unsubscribe(ops.Document.signalCursorRemoved, onCursorRemoved);
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, requestRerenderOfSelectionViews);
- odtDocument.unsubscribe(ops.OdtDocument.signalTableAdded, requestRerenderOfSelectionViews);
- odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, requestRerenderOfSelectionViews);
- stopRerenderLoop();
+ odtDocument.unsubscribe(ops.Document.signalCursorMoved, onCursorMoved);
+ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, selectionViewManager.rerenderSelectionViews);
+ odtDocument.unsubscribe(ops.OdtDocument.signalTableAdded, selectionViewManager.rerenderSelectionViews);
+ odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, selectionViewManager.rerenderSelectionViews);
avatarInfoStyles.parentNode.removeChild(avatarInfoStyles);
(function destroyEditInfo(i, err) {
if(err) {
@@ -18167,18 +16261,17 @@ gui.SessionView = function() {
})(0, undefined)
};
function init() {
- var odtDocument = session.getOdtDocument(), head = document.getElementsByTagName("head")[0];
- odtDocument.subscribe(ops.OdtDocument.signalMemberAdded, renderMemberData);
- odtDocument.subscribe(ops.OdtDocument.signalMemberUpdated, renderMemberData);
- odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
- odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
+ var odtDocument = session.getOdtDocument(), head = document.getElementsByTagName("head").item(0);
+ odtDocument.subscribe(ops.Document.signalMemberAdded, renderMemberData);
+ odtDocument.subscribe(ops.Document.signalMemberUpdated, renderMemberData);
+ odtDocument.subscribe(ops.Document.signalCursorAdded, onCursorAdded);
+ odtDocument.subscribe(ops.Document.signalCursorRemoved, onCursorRemoved);
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
- odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
- startRerenderLoop();
- odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, requestRerenderOfSelectionViews);
- odtDocument.subscribe(ops.OdtDocument.signalTableAdded, requestRerenderOfSelectionViews);
- odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, requestRerenderOfSelectionViews);
- avatarInfoStyles = document.createElementNS(head.namespaceURI, "style");
+ odtDocument.subscribe(ops.Document.signalCursorMoved, onCursorMoved);
+ odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, selectionViewManager.rerenderSelectionViews);
+ odtDocument.subscribe(ops.OdtDocument.signalTableAdded, selectionViewManager.rerenderSelectionViews);
+ odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, selectionViewManager.rerenderSelectionViews);
+ avatarInfoStyles = (document.createElementNS(head.namespaceURI, "style"));
avatarInfoStyles.type = "text/css";
avatarInfoStyles.media = "screen, print, handheld, projection";
avatarInfoStyles.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));
@@ -18187,7 +16280,1395 @@ gui.SessionView = function() {
}
init()
}
- return SessionView
-}();
-var webodf_css = "@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0);\n@namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0);\n@namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0);\n@namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0);\n@namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0);\n@namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0);\n@namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0);\n@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0);\n@namespace webodfhelper url(urn:webodf:names:helper);\n@namespace cursor url(urn:webodf:names:cursor);\n@namespace editinfo url(urn:webodf:names:editinfo);\n@namespace annotation url(urn:webodf:names:annotation);\n@namespace dc url(http://purl.org/dc/elements/1.1/);\n\noffice|document > *, office|document-content > * {\n display: none;\n}\noffice|body, office|document {\n display: inline-block;\n position: relative;\n}\n\ntext|p, text|h {\n display: block;\n padding: 0;\n margin: 0;\n line-height: normal;\n position: relative;\n min-height: 1.3em; /* prevent empty paragraphs and headings from collapsing if they are empty */\n}\n*[webodfhelper|containsparagraphanchor] {\n position: relative;\n}\ntext|s {\n white-space: pre;\n}\ntext|tab {\n display: inline;\n white-space: pre;\n}\ntext|tracked-changes {\n /*Consumers that do not support change tracking, should ignore changes.*/\n display: none;\n}\noffice|binary-data {\n display: none;\n}\noffice|text {\n display: block;\n text-align: left;\n overflow: visible;\n word-wrap: break-word;\n}\n\noffice|text::selection {\n /** Let's not draw selection highlight that overflows into the office|text\n * node when selecting content across several paragraphs\n */\n background: transparent;\n}\n\n.virtualSelections office|document *::selection {\n background: transparent;\n}\n.virtualSelections office|document *::-moz-selection {\n background: transparent;\n}\n\noffice|text * draw|text-box {\n/** only for text documents */\n display: block;\n border: 1px solid #d3d3d3;\n}\noffice|spreadsheet {\n display: block;\n border-collapse: collapse;\n empty-cells: show;\n font-family: sans-serif;\n font-size: 10pt;\n text-align: left;\n page-break-inside: avoid;\n overflow: hidden;\n}\noffice|presentation {\n display: inline-block;\n text-align: left;\n}\n#shadowContent {\n display: inline-block;\n text-align: left;\n}\ndraw|page {\n display: block;\n position: relative;\n overflow: hidden;\n}\npresentation|notes, presentation|footer-decl, presentation|date-time-decl {\n display: none;\n}\n@media print {\n draw|page {\n border: 1pt solid black;\n page-break-inside: avoid;\n }\n presentation|notes {\n /*TODO*/\n }\n}\noffice|spreadsheet text|p {\n border: 0px;\n padding: 1px;\n margin: 0px;\n}\noffice|spreadsheet table|table {\n margin: 3px;\n}\noffice|spreadsheet table|table:after {\n /* show sheet name the end of the sheet */\n /*content: attr(table|name);*/ /* gives parsing error in opera */\n}\noffice|spreadsheet table|table-row {\n counter-increment: row;\n}\noffice|spreadsheet table|table-row:before {\n width: 3em;\n background: #cccccc;\n border: 1px solid black;\n text-align: center;\n content: counter(row);\n display: table-cell;\n}\noffice|spreadsheet table|table-cell {\n border: 1px solid #cccccc;\n}\ntable|table {\n display: table;\n}\ndraw|frame table|table {\n width: 100%;\n height: 100%;\n background: white;\n}\ntable|table-header-rows {\n display: table-header-group;\n}\ntable|table-row {\n display: table-row;\n}\ntable|table-column {\n display: table-column;\n}\ntable|table-cell {\n width: 0.889in;\n display: table-cell;\n word-break: break-all; /* prevent long words from extending out the table cell */\n}\ndraw|frame {\n display: block;\n}\ndraw|image {\n display: block;\n width: 100%;\n height: 100%;\n top: 0px;\n left: 0px;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n -moz-background-size: 100% 100%;\n}\n/* only show the first image in frame */\ndraw|frame > draw|image:nth-of-type(n+2) {\n display: none;\n}\ntext|list:before {\n display: none;\n content:\"\";\n}\ntext|list {\n counter-reset: list;\n}\ntext|list-item {\n display: block;\n}\ntext|number {\n display:none;\n}\n\ntext|a {\n color: blue;\n text-decoration: underline;\n cursor: pointer;\n}\ntext|note-citation {\n vertical-align: super;\n font-size: smaller;\n}\ntext|note-body {\n display: none;\n}\ntext|note:hover text|note-citation {\n background: #dddddd;\n}\ntext|note:hover text|note-body {\n display: block;\n left:1em;\n max-width: 80%;\n position: absolute;\n background: #ffffaa;\n}\nsvg|title, svg|desc {\n display: none;\n}\nvideo {\n width: 100%;\n height: 100%\n}\n\n/* below set up the cursor */\ncursor|cursor {\n display: inline;\n width: 0px;\n height: 1em;\n /* making the position relative enables the avatar to use\n the cursor as reference for its absolute position */\n position: relative;\n z-index: 1;\n}\ncursor|cursor > span {\n /* IMPORTANT: when changing these values ensure DEFAULT_CARET_TOP and DEFAULT_CARET_HEIGHT\n in Caret.js remain in sync */\n display: inline;\n position: absolute;\n top: 5%; /* push down the caret; 0px can do the job, 5% looks better, 10% is a bit over */\n height: 1em;\n border-left: 2px solid black;\n outline: none;\n}\n\ncursor|cursor > div {\n padding: 3px;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n border: none !important;\n border-radius: 5px;\n opacity: 0.3;\n}\n\ncursor|cursor > div > img {\n border-radius: 5px;\n}\n\ncursor|cursor > div.active {\n opacity: 0.8;\n}\n\ncursor|cursor > div:after {\n content: ' ';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 43%;\n}\n\n\n.editInfoMarker {\n position: absolute;\n width: 10px;\n height: 100%;\n left: -20px;\n opacity: 0.8;\n top: 0;\n border-radius: 5px;\n background-color: transparent;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n}\n.editInfoMarker:hover {\n box-shadow: 0px 0px 8px rgba(0, 0, 0, 1);\n}\n\n.editInfoHandle {\n position: absolute;\n background-color: black;\n padding: 5px;\n border-radius: 5px;\n opacity: 0.8;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n bottom: 100%;\n margin-bottom: 10px;\n z-index: 3;\n left: -25px;\n}\n.editInfoHandle:after {\n content: ' ';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 5px;\n}\n.editInfo {\n font-family: sans-serif;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n color: white;\n width: 100%;\n height: 12pt;\n}\n.editInfoColor {\n float: left;\n width: 10pt;\n height: 10pt;\n border: 1px solid white;\n}\n.editInfoAuthor {\n float: left;\n margin-left: 5pt;\n font-size: 10pt;\n text-align: left;\n height: 12pt;\n line-height: 12pt;\n}\n.editInfoTime {\n float: right;\n margin-left: 30pt;\n font-size: 8pt;\n font-style: italic;\n color: yellow;\n height: 12pt;\n line-height: 12pt;\n}\n\n.annotationWrapper {\n display: inline;\n position: relative;\n}\n\n.annotationRemoveButton:before {\n content: '\u00d7';\n color: white;\n padding: 5px;\n line-height: 1em;\n}\n\n.annotationRemoveButton {\n width: 20px;\n height: 20px;\n border-radius: 10px;\n background-color: black;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n position: absolute;\n top: -10px;\n left: -10px;\n z-index: 3;\n text-align: center;\n font-family: sans-serif;\n font-style: normal;\n font-weight: normal;\n text-decoration: none;\n font-size: 15px;\n}\n.annotationRemoveButton:hover {\n cursor: pointer;\n box-shadow: 0px 0px 5px rgba(0, 0, 0, 1);\n}\n\n.annotationNote {\n width: 4cm;\n position: absolute;\n display: inline;\n z-index: 10;\n}\n.annotationNote > office|annotation {\n display: block;\n text-align: left;\n}\n\n.annotationConnector {\n position: absolute;\n display: inline;\n z-index: 2;\n border-top: 1px dashed brown;\n}\n.annotationConnector.angular {\n -moz-transform-origin: left top;\n -webkit-transform-origin: left top;\n -ms-transform-origin: left top;\n transform-origin: left top;\n}\n.annotationConnector.horizontal {\n left: 0;\n}\n.annotationConnector.horizontal:before {\n content: '';\n display: inline;\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: brown transparent transparent transparent;\n top: -1px;\n left: -5px;\n}\n\noffice|annotation {\n width: 100%;\n height: 100%;\n display: none;\n background: rgb(198, 238, 184);\n background: -moz-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -webkit-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -o-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -ms-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: linear-gradient(180deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n box-shadow: 0 3px 4px -3px #ccc;\n}\n\noffice|annotation > dc|creator {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n color: white;\n background-color: brown;\n padding: 4px;\n}\noffice|annotation > dc|date {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n border: 4px solid transparent;\n}\noffice|annotation > text|list {\n display: block;\n padding: 5px;\n}\n\n/* This is very temporary CSS. This must go once\n * we start bundling webodf-default ODF styles for annotations.\n */\noffice|annotation text|p {\n font-size: 10pt;\n color: black;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n font-family: sans-serif;\n}\n\ndc|*::selection {\n background: transparent;\n}\ndc|*::-moz-selection {\n background: transparent;\n}\n\n#annotationsPane {\n background-color: #EAEAEA;\n width: 4cm;\n height: 100%;\n display: none;\n position: absolute;\n outline: 1px solid #ccc;\n}\n\n.annotationHighlight {\n background-color: yellow;\n position: relative;\n}\n\n.selectionOverlay {\n position: absolute;\n z-index: 15;\n opacity: 0.2;\n pointer-events: none;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n}\n\n#imageSelector {\n display: none;\n position: absolute;\n border-style: solid;\n border-color: black;\n}\n\n#imageSelector > div {\n width: 5px;\n height: 5px;\n display: block;\n position: absolute;\n border: 1px solid black;\n background-color: #ffffff;\n}\n\n#imageSelector > .topLeft {\n top: -4px;\n left: -4px;\n}\n\n#imageSelector > .topRight {\n top: -4px;\n right: -4px;\n}\n\n#imageSelector > .bottomRight {\n right: -4px;\n bottom: -4px;\n}\n\n#imageSelector > .bottomLeft {\n bottom: -4px;\n left: -4px;\n}\n\n#imageSelector > .topMiddle {\n top: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .rightMiddle {\n top: 50%;\n right: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n\n#imageSelector > .bottomMiddle {\n bottom: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .leftMiddle {\n top: 50%;\n left: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n";
+})();
+gui.SvgSelectionView = function SvgSelectionView(cursor) {
+ var document = cursor.getDocument(), documentRoot, root, doc = document.getDOMDocument(), async = new core.Async, svgns = "http://www.w3.org/2000/svg", overlay = doc.createElementNS(svgns, "svg"), polygon = doc.createElementNS(svgns, "polygon"), odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils, isVisible = true, positionIterator = gui.SelectionMover.createPositionIterator(document.getRootNode()), FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT, renderTask;
+ function addOverlay() {
+ var newDocumentRoot = document.getRootNode();
+ if(documentRoot !== newDocumentRoot) {
+ documentRoot = newDocumentRoot;
+ root = (documentRoot.parentNode.parentNode.parentNode);
+ root.appendChild(overlay);
+ overlay.setAttribute("class", "selectionOverlay");
+ overlay.appendChild(polygon)
+ }
+ }
+ function translateRect(rect) {
+ var rootRect = domUtils.getBoundingClientRect(root), zoomLevel = document.getCanvas().getZoomLevel(), resultRect = {};
+ resultRect.top = domUtils.adaptRangeDifferenceToZoomLevel(rect.top - rootRect.top, zoomLevel);
+ resultRect.left = domUtils.adaptRangeDifferenceToZoomLevel(rect.left - rootRect.left, zoomLevel);
+ resultRect.bottom = domUtils.adaptRangeDifferenceToZoomLevel(rect.bottom - rootRect.top, zoomLevel);
+ resultRect.right = domUtils.adaptRangeDifferenceToZoomLevel(rect.right - rootRect.left, zoomLevel);
+ resultRect.width = domUtils.adaptRangeDifferenceToZoomLevel(rect.width, zoomLevel);
+ resultRect.height = domUtils.adaptRangeDifferenceToZoomLevel(rect.height, zoomLevel);
+ return resultRect
+ }
+ function isRangeVisible(range) {
+ var bcr = range.getBoundingClientRect();
+ return Boolean(bcr && bcr.height !== 0)
+ }
+ function lastVisibleRect(range, nodes) {
+ var nextNodeIndex = nodes.length - 1, node = nodes[nextNodeIndex], startOffset, endOffset;
+ if(range.endContainer === node) {
+ startOffset = range.endOffset
+ }else {
+ if(node.nodeType === Node.TEXT_NODE) {
+ startOffset = node.length
+ }else {
+ startOffset = node.childNodes.length
+ }
+ }
+ endOffset = startOffset;
+ range.setStart(node, startOffset);
+ range.setEnd(node, endOffset);
+ while(!isRangeVisible(range)) {
+ if(node.nodeType === Node.ELEMENT_NODE && startOffset > 0) {
+ startOffset = 0
+ }else {
+ if(node.nodeType === Node.TEXT_NODE && startOffset > 0) {
+ startOffset -= 1
+ }else {
+ if(nodes[nextNodeIndex]) {
+ node = nodes[nextNodeIndex];
+ nextNodeIndex -= 1;
+ startOffset = endOffset = node.length || node.childNodes.length
+ }else {
+ return false
+ }
+ }
+ }
+ range.setStart(node, startOffset);
+ range.setEnd(node, endOffset)
+ }
+ return true
+ }
+ function firstVisibleRect(range, nodes) {
+ var nextNodeIndex = 0, node = nodes[nextNodeIndex], startOffset = range.startContainer === node ? range.startOffset : 0, endOffset = startOffset;
+ range.setStart(node, startOffset);
+ range.setEnd(node, endOffset);
+ while(!isRangeVisible(range)) {
+ if(node.nodeType === Node.ELEMENT_NODE && endOffset < node.childNodes.length) {
+ endOffset = node.childNodes.length
+ }else {
+ if(node.nodeType === Node.TEXT_NODE && endOffset < node.length) {
+ endOffset += 1
+ }else {
+ if(nodes[nextNodeIndex]) {
+ node = nodes[nextNodeIndex];
+ nextNodeIndex += 1;
+ startOffset = endOffset = 0
+ }else {
+ return false
+ }
+ }
+ }
+ range.setStart(node, startOffset);
+ range.setEnd(node, endOffset)
+ }
+ return true
+ }
+ function getExtremeRanges(range) {
+ var nodes = odfUtils.getTextElements(range, true, false), firstRange = (range.cloneRange()), lastRange = (range.cloneRange()), fillerRange = range.cloneRange();
+ if(!nodes.length) {
+ return null
+ }
+ if(!firstVisibleRect(firstRange, nodes)) {
+ return null
+ }
+ if(!lastVisibleRect(lastRange, nodes)) {
+ return null
+ }
+ fillerRange.setStart(firstRange.startContainer, firstRange.startOffset);
+ fillerRange.setEnd(lastRange.endContainer, lastRange.endOffset);
+ return{firstRange:firstRange, lastRange:lastRange, fillerRange:fillerRange}
+ }
+ function getBoundingRect(rect1, rect2) {
+ var resultRect = {};
+ resultRect.top = Math.min(rect1.top, rect2.top);
+ resultRect.left = Math.min(rect1.left, rect2.left);
+ resultRect.right = Math.max(rect1.right, rect2.right);
+ resultRect.bottom = Math.max(rect1.bottom, rect2.bottom);
+ resultRect.width = resultRect.right - resultRect.left;
+ resultRect.height = resultRect.bottom - resultRect.top;
+ return resultRect
+ }
+ function checkAndGrowOrCreateRect(originalRect, newRect) {
+ if(newRect && (newRect.width > 0 && newRect.height > 0)) {
+ if(!originalRect) {
+ originalRect = newRect
+ }else {
+ originalRect = getBoundingRect(originalRect, newRect)
+ }
+ }
+ return originalRect
+ }
+ function getFillerRect(fillerRange) {
+ var containerNode = fillerRange.commonAncestorContainer, firstNode = (fillerRange.startContainer), lastNode = (fillerRange.endContainer), firstOffset = fillerRange.startOffset, lastOffset = fillerRange.endOffset, currentNode, lastMeasuredNode, firstSibling, lastSibling, grownRect = null, currentRect, range = doc.createRange(), rootFilter, odfNodeFilter = new odf.OdfNodeFilter, treeWalker;
+ function acceptNode(node) {
+ positionIterator.setUnfilteredPosition(node, 0);
+ if(odfNodeFilter.acceptNode(node) === FILTER_ACCEPT && rootFilter.acceptPosition(positionIterator) === FILTER_ACCEPT) {
+ return FILTER_ACCEPT
+ }
+ return FILTER_REJECT
+ }
+ function getRectFromNodeAfterFiltering(node) {
+ var rect = null;
+ if(acceptNode(node) === FILTER_ACCEPT) {
+ rect = domUtils.getBoundingClientRect(node)
+ }
+ return rect
+ }
+ if(firstNode === containerNode || lastNode === containerNode) {
+ range = fillerRange.cloneRange();
+ grownRect = range.getBoundingClientRect();
+ range.detach();
+ return grownRect
+ }
+ firstSibling = firstNode;
+ while(firstSibling.parentNode !== containerNode) {
+ firstSibling = firstSibling.parentNode
+ }
+ lastSibling = lastNode;
+ while(lastSibling.parentNode !== containerNode) {
+ lastSibling = lastSibling.parentNode
+ }
+ rootFilter = document.createRootFilter(firstNode);
+ currentNode = firstSibling.nextSibling;
+ while(currentNode && currentNode !== lastSibling) {
+ currentRect = getRectFromNodeAfterFiltering(currentNode);
+ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
+ currentNode = currentNode.nextSibling
+ }
+ if(odfUtils.isParagraph(firstSibling)) {
+ grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(firstSibling))
+ }else {
+ if(firstSibling.nodeType === Node.TEXT_NODE) {
+ currentNode = firstSibling;
+ range.setStart(currentNode, firstOffset);
+ range.setEnd(currentNode, currentNode === lastSibling ? lastOffset : (currentNode).length);
+ currentRect = range.getBoundingClientRect();
+ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
+ }else {
+ treeWalker = doc.createTreeWalker(firstSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
+ currentNode = treeWalker.currentNode = firstNode;
+ while(currentNode && currentNode !== lastNode) {
+ range.setStart(currentNode, firstOffset);
+ range.setEnd(currentNode, (currentNode).length);
+ currentRect = range.getBoundingClientRect();
+ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
+ lastMeasuredNode = currentNode;
+ firstOffset = 0;
+ currentNode = treeWalker.nextNode()
+ }
+ }
+ }
+ if(!lastMeasuredNode) {
+ lastMeasuredNode = firstNode
+ }
+ if(odfUtils.isParagraph(lastSibling)) {
+ grownRect = checkAndGrowOrCreateRect(grownRect, domUtils.getBoundingClientRect(lastSibling))
+ }else {
+ if(lastSibling.nodeType === Node.TEXT_NODE) {
+ currentNode = lastSibling;
+ range.setStart(currentNode, currentNode === firstSibling ? firstOffset : 0);
+ range.setEnd(currentNode, lastOffset);
+ currentRect = range.getBoundingClientRect();
+ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect)
+ }else {
+ treeWalker = doc.createTreeWalker(lastSibling, NodeFilter.SHOW_TEXT, acceptNode, false);
+ currentNode = treeWalker.currentNode = lastNode;
+ while(currentNode && currentNode !== lastMeasuredNode) {
+ range.setStart(currentNode, 0);
+ range.setEnd(currentNode, lastOffset);
+ currentRect = range.getBoundingClientRect();
+ grownRect = checkAndGrowOrCreateRect(grownRect, currentRect);
+ currentNode = treeWalker.previousNode();
+ if(currentNode) {
+ lastOffset = (currentNode).length
+ }
+ }
+ }
+ }
+ return grownRect
+ }
+ function getCollapsedRectOfTextRange(range, useRightEdge) {
+ var clientRect = range.getBoundingClientRect(), collapsedRect = {};
+ collapsedRect.width = 0;
+ collapsedRect.top = clientRect.top;
+ collapsedRect.bottom = clientRect.bottom;
+ collapsedRect.height = clientRect.height;
+ collapsedRect.left = collapsedRect.right = useRightEdge ? clientRect.right : clientRect.left;
+ return collapsedRect
+ }
+ function setPoints(points) {
+ var pointsString = "", i;
+ for(i = 0;i < points.length;i += 1) {
+ pointsString += points[i].x + "," + points[i].y + " "
+ }
+ polygon.setAttribute("points", pointsString)
+ }
+ function repositionOverlays(selectedRange) {
+ var extremes = getExtremeRanges(selectedRange), firstRange, lastRange, fillerRange, firstRect, fillerRect, lastRect, left, right, top, bottom;
+ if(extremes) {
+ firstRange = extremes.firstRange;
+ lastRange = extremes.lastRange;
+ fillerRange = extremes.fillerRange;
+ firstRect = translateRect(getCollapsedRectOfTextRange(firstRange, false));
+ lastRect = translateRect(getCollapsedRectOfTextRange(lastRange, true));
+ fillerRect = getFillerRect(fillerRange);
+ if(!fillerRect) {
+ fillerRect = getBoundingRect(firstRect, lastRect)
+ }else {
+ fillerRect = translateRect(fillerRect)
+ }
+ left = fillerRect.left;
+ right = firstRect.left + Math.max(0, fillerRect.width - (firstRect.left - fillerRect.left));
+ top = Math.min(firstRect.top, lastRect.top);
+ bottom = lastRect.top + lastRect.height;
+ setPoints([{x:firstRect.left, y:top + firstRect.height}, {x:firstRect.left, y:top}, {x:right, y:top}, {x:right, y:bottom - lastRect.height}, {x:lastRect.right, y:bottom - lastRect.height}, {x:lastRect.right, y:bottom}, {x:left, y:bottom}, {x:left, y:top + firstRect.height}, {x:firstRect.left, y:top + firstRect.height}]);
+ firstRange.detach();
+ lastRange.detach();
+ fillerRange.detach()
+ }
+ return Boolean(extremes)
+ }
+ function rerender() {
+ var range = cursor.getSelectedRange(), shouldShow;
+ shouldShow = isVisible && (cursor.getSelectionType() === ops.OdtCursor.RangeSelection && !range.collapsed);
+ if(shouldShow) {
+ addOverlay();
+ shouldShow = repositionOverlays(range)
+ }
+ if(shouldShow) {
+ overlay.style.display = "block"
+ }else {
+ overlay.style.display = "none"
+ }
+ }
+ this.rerender = function() {
+ if(isVisible) {
+ renderTask.trigger()
+ }
+ };
+ this.show = function() {
+ isVisible = true;
+ renderTask.trigger()
+ };
+ this.hide = function() {
+ isVisible = false;
+ renderTask.trigger()
+ };
+ function handleCursorMove(movedCursor) {
+ if(isVisible && movedCursor === cursor) {
+ renderTask.trigger()
+ }
+ }
+ function destroy(callback) {
+ root.removeChild(overlay);
+ cursor.getDocument().unsubscribe(ops.Document.signalCursorMoved, handleCursorMove);
+ callback()
+ }
+ this.destroy = function(callback) {
+ async.destroyAll([renderTask.destroy, destroy], callback)
+ };
+ function init() {
+ var editinfons = "urn:webodf:names:editinfo", memberid = cursor.getMemberId();
+ renderTask = new core.ScheduledTask(rerender, 0);
+ addOverlay();
+ overlay.setAttributeNS(editinfons, "editinfo:memberid", memberid);
+ cursor.getDocument().subscribe(ops.Document.signalCursorMoved, handleCursorMove)
+ }
+ init()
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.UndoStateRules = function UndoStateRules() {
+ function ReverseIterator(array, predicate) {
+ var index = array.length;
+ this.previous = function() {
+ for(index = index - 1;index >= 0;index -= 1) {
+ if(predicate(array[index])) {
+ return array[index]
+ }
+ }
+ return null
+ }
+ }
+ function getOpType(op) {
+ return op.spec().optype
+ }
+ function getOpPosition(op) {
+ var key = "position", spec = op.spec(), value;
+ if(spec.hasOwnProperty(key)) {
+ value = (spec[key])
+ }
+ return value
+ }
+ function isEditOperation(op) {
+ return op.isEdit
+ }
+ this.isEditOperation = isEditOperation;
+ function canAggregateOperation(op) {
+ switch(getOpType(op)) {
+ case "RemoveText":
+ ;
+ case "InsertText":
+ return true;
+ default:
+ return false
+ }
+ }
+ function isSameDirectionOfTravel(thisOp, lastEditOp, secondLastEditOp) {
+ var thisPosition = getOpPosition(thisOp), lastPosition = getOpPosition(lastEditOp), secondLastPosition = getOpPosition(secondLastEditOp), diffLastToSecondLast = lastPosition - secondLastPosition, diffThisToLast = thisPosition - lastPosition;
+ return diffThisToLast === diffLastToSecondLast
+ }
+ function isAdjacentOperation(thisOp, lastEditOp) {
+ var positionDifference = getOpPosition(thisOp) - getOpPosition(lastEditOp);
+ return positionDifference === 0 || Math.abs(positionDifference) === 1
+ }
+ function continuesOperations(thisOp, lastEditOp, secondLastEditOp) {
+ if(!secondLastEditOp) {
+ return isAdjacentOperation(thisOp, lastEditOp)
+ }
+ return isSameDirectionOfTravel(thisOp, lastEditOp, secondLastEditOp)
+ }
+ function continuesMostRecentEditOperation(thisOp, recentOperations) {
+ var thisOpType = getOpType(thisOp), editOpsFinder = new ReverseIterator(recentOperations, isEditOperation), lastEditOp = editOpsFinder.previous();
+ runtime.assert(Boolean(lastEditOp), "No edit operations found in state");
+ if(thisOpType === getOpType((lastEditOp))) {
+ return continuesOperations(thisOp, (lastEditOp), editOpsFinder.previous())
+ }
+ return false
+ }
+ function continuesMostRecentEditGroup(thisOp, recentOperations) {
+ var thisOpType = getOpType(thisOp), editOpsFinder = new ReverseIterator(recentOperations, isEditOperation), candidateOp = editOpsFinder.previous(), lastEditOp, secondLastEditOp = null, inspectedGroupsCount, groupId;
+ runtime.assert(Boolean(candidateOp), "No edit operations found in state");
+ groupId = candidateOp.group;
+ runtime.assert(groupId !== undefined, "Operation has no group");
+ inspectedGroupsCount = 1;
+ while(candidateOp && candidateOp.group === groupId) {
+ if(thisOpType === getOpType(candidateOp)) {
+ lastEditOp = candidateOp;
+ break
+ }
+ candidateOp = editOpsFinder.previous()
+ }
+ if(lastEditOp) {
+ candidateOp = editOpsFinder.previous();
+ while(candidateOp) {
+ if(candidateOp.group !== groupId) {
+ if(inspectedGroupsCount === 2) {
+ break
+ }
+ groupId = candidateOp.group;
+ inspectedGroupsCount += 1
+ }
+ if(thisOpType === getOpType(candidateOp)) {
+ secondLastEditOp = candidateOp;
+ break
+ }
+ candidateOp = editOpsFinder.previous()
+ }
+ return continuesOperations(thisOp, (lastEditOp), secondLastEditOp)
+ }
+ return false
+ }
+ function isPartOfOperationSet(operation, recentOperations) {
+ var areOperationsGrouped = operation.group !== undefined, lastOperation;
+ if(!isEditOperation(operation)) {
+ return true
+ }
+ if(recentOperations.length === 0) {
+ return true
+ }
+ lastOperation = recentOperations[recentOperations.length - 1];
+ if(areOperationsGrouped && operation.group === lastOperation.group) {
+ return true
+ }
+ if(canAggregateOperation(operation) && recentOperations.some(isEditOperation)) {
+ if(areOperationsGrouped) {
+ return continuesMostRecentEditGroup(operation, recentOperations)
+ }
+ return continuesMostRecentEditOperation(operation, recentOperations)
+ }
+ return false
+ }
+ this.isPartOfOperationSet = isPartOfOperationSet
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+gui.TrivialUndoManager = function TrivialUndoManager(defaultRules) {
+ var self = this, cursorns = "urn:webodf:names:cursor", domUtils = new core.DomUtils, initialDoc, initialState = [], playFunc, document, currentUndoState = [], undoStates = [], redoStates = [], eventNotifier = new core.EventNotifier([gui.UndoManager.signalUndoStackChanged, gui.UndoManager.signalUndoStateCreated, gui.UndoManager.signalUndoStateModified, gui.TrivialUndoManager.signalDocumentRootReplaced]), undoRules = defaultRules || new gui.UndoStateRules, isExecutingOps = false;
+ function executeOperations(operations) {
+ if(operations.length > 0) {
+ isExecutingOps = true;
+ playFunc(operations);
+ isExecutingOps = false
+ }
+ }
+ function emitStackChange() {
+ eventNotifier.emit(gui.UndoManager.signalUndoStackChanged, {undoAvailable:self.hasUndoStates(), redoAvailable:self.hasRedoStates()})
+ }
+ function mostRecentUndoState() {
+ return undoStates[undoStates.length - 1]
+ }
+ function completeCurrentUndoState() {
+ if(currentUndoState !== initialState && currentUndoState !== mostRecentUndoState()) {
+ undoStates.push(currentUndoState)
+ }
+ }
+ function removeNode(node) {
+ var sibling = node.previousSibling || node.nextSibling;
+ node.parentNode.removeChild(node);
+ domUtils.normalizeTextNodes(sibling)
+ }
+ function removeCursors(root) {
+ domUtils.getElementsByTagNameNS(root, cursorns, "cursor").forEach(removeNode);
+ domUtils.getElementsByTagNameNS(root, cursorns, "anchor").forEach(removeNode)
+ }
+ function values(obj) {
+ return Object.keys(obj).map(function(key) {
+ return obj[key]
+ })
+ }
+ function extractCursorStates(undoStates) {
+ var addCursor = {}, moveCursor = {}, requiredAddOps = {}, remainingAddOps, operations = undoStates.pop();
+ document.getMemberIds().forEach(function(memberid) {
+ requiredAddOps[memberid] = true
+ });
+ remainingAddOps = Object.keys(requiredAddOps).length;
+ function processOp(op) {
+ var spec = op.spec();
+ if(!requiredAddOps[spec.memberid]) {
+ return
+ }
+ switch(spec.optype) {
+ case "AddCursor":
+ if(!addCursor[spec.memberid]) {
+ addCursor[spec.memberid] = op;
+ delete requiredAddOps[spec.memberid];
+ remainingAddOps -= 1
+ }
+ break;
+ case "MoveCursor":
+ if(!moveCursor[spec.memberid]) {
+ moveCursor[spec.memberid] = op
+ }
+ break
+ }
+ }
+ while(operations && remainingAddOps > 0) {
+ operations.reverse();
+ operations.forEach(processOp);
+ operations = undoStates.pop()
+ }
+ return values(addCursor).concat(values(moveCursor))
+ }
+ this.subscribe = function(signal, callback) {
+ eventNotifier.subscribe(signal, callback)
+ };
+ this.unsubscribe = function(signal, callback) {
+ eventNotifier.unsubscribe(signal, callback)
+ };
+ this.hasUndoStates = function() {
+ return undoStates.length > 0
+ };
+ this.hasRedoStates = function() {
+ return redoStates.length > 0
+ };
+ this.setDocument = function(newDocument) {
+ document = newDocument
+ };
+ this.purgeInitialState = function() {
+ undoStates.length = 0;
+ redoStates.length = 0;
+ initialState.length = 0;
+ currentUndoState.length = 0;
+ initialDoc = null;
+ emitStackChange()
+ };
+ function setInitialState() {
+ initialDoc = document.cloneDocumentElement();
+ removeCursors(initialDoc);
+ completeCurrentUndoState();
+ currentUndoState = initialState = extractCursorStates([initialState].concat(undoStates));
+ undoStates.length = 0;
+ redoStates.length = 0;
+ emitStackChange()
+ }
+ this.setInitialState = setInitialState;
+ this.initialize = function() {
+ if(!initialDoc) {
+ setInitialState()
+ }
+ };
+ this.setPlaybackFunction = function(playback_func) {
+ playFunc = playback_func
+ };
+ this.onOperationExecuted = function(op) {
+ if(isExecutingOps) {
+ return
+ }
+ if(undoRules.isEditOperation(op) && (currentUndoState === initialState || redoStates.length > 0) || !undoRules.isPartOfOperationSet(op, currentUndoState)) {
+ redoStates.length = 0;
+ completeCurrentUndoState();
+ currentUndoState = [op];
+ undoStates.push(currentUndoState);
+ eventNotifier.emit(gui.UndoManager.signalUndoStateCreated, {operations:currentUndoState});
+ emitStackChange()
+ }else {
+ currentUndoState.push(op);
+ eventNotifier.emit(gui.UndoManager.signalUndoStateModified, {operations:currentUndoState})
+ }
+ };
+ this.moveForward = function(states) {
+ var moved = 0, redoOperations;
+ while(states && redoStates.length) {
+ redoOperations = redoStates.pop();
+ undoStates.push(redoOperations);
+ executeOperations(redoOperations);
+ states -= 1;
+ moved += 1
+ }
+ if(moved) {
+ currentUndoState = mostRecentUndoState();
+ emitStackChange()
+ }
+ return moved
+ };
+ this.moveBackward = function(states) {
+ var moved = 0;
+ while(states && undoStates.length) {
+ redoStates.push(undoStates.pop());
+ states -= 1;
+ moved += 1
+ }
+ if(moved) {
+ document.setDocumentElement((initialDoc.cloneNode(true)));
+ eventNotifier.emit(gui.TrivialUndoManager.signalDocumentRootReplaced, {});
+ document.getMemberIds().forEach(function(memberid) {
+ document.removeCursor(memberid)
+ });
+ executeOperations(initialState);
+ undoStates.forEach(executeOperations);
+ currentUndoState = mostRecentUndoState() || initialState;
+ emitStackChange()
+ }
+ return moved
+ }
+};
+gui.TrivialUndoManager.signalDocumentRootReplaced = "documentRootReplaced";
+(function() {
+ return gui.TrivialUndoManager
+})();
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OperationTransformMatrix = function OperationTransformMatrix() {
+ function invertMoveCursorSpecRange(moveCursorSpec) {
+ moveCursorSpec.position = moveCursorSpec.position + moveCursorSpec.length;
+ moveCursorSpec.length *= -1
+ }
+ function invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec) {
+ var isBackwards = moveCursorSpec.length < 0;
+ if(isBackwards) {
+ invertMoveCursorSpecRange(moveCursorSpec)
+ }
+ return isBackwards
+ }
+ function getStyleReferencingAttributes(setProperties, styleName) {
+ var attributes = [];
+ function check(attributeName) {
+ if(setProperties[attributeName] === styleName) {
+ attributes.push(attributeName)
+ }
+ }
+ if(setProperties) {
+ ["style:parent-style-name", "style:next-style-name"].forEach(check)
+ }
+ return attributes
+ }
+ function dropStyleReferencingAttributes(setProperties, deletedStyleName) {
+ function del(attributeName) {
+ if(setProperties[attributeName] === deletedStyleName) {
+ delete setProperties[attributeName]
+ }
+ }
+ if(setProperties) {
+ ["style:parent-style-name", "style:next-style-name"].forEach(del)
+ }
+ }
+ function cloneOpspec(opspec) {
+ var result = {};
+ Object.keys(opspec).forEach(function(key) {
+ if(typeof opspec[key] === "object") {
+ result[key] = cloneOpspec(opspec[key])
+ }else {
+ result[key] = opspec[key]
+ }
+ });
+ return result
+ }
+ function dropOverruledAndUnneededAttributes(minorSetProperties, minorRemovedProperties, majorSetProperties, majorRemovedProperties) {
+ var i, name, majorChanged = false, minorChanged = false, removedPropertyNames, majorRemovedPropertyNames = [];
+ if(majorRemovedProperties && majorRemovedProperties.attributes) {
+ majorRemovedPropertyNames = majorRemovedProperties.attributes.split(",")
+ }
+ if(minorSetProperties && (majorSetProperties || majorRemovedPropertyNames.length > 0)) {
+ Object.keys(minorSetProperties).forEach(function(key) {
+ var value = minorSetProperties[key], overrulingPropertyValue;
+ if(typeof value !== "object") {
+ if(majorSetProperties) {
+ overrulingPropertyValue = majorSetProperties[key]
+ }
+ if(overrulingPropertyValue !== undefined) {
+ delete minorSetProperties[key];
+ minorChanged = true;
+ if(overrulingPropertyValue === value) {
+ delete majorSetProperties[key];
+ majorChanged = true
+ }
+ }else {
+ if(majorRemovedPropertyNames.indexOf(key) !== -1) {
+ delete minorSetProperties[key];
+ minorChanged = true
+ }
+ }
+ }
+ })
+ }
+ if(minorRemovedProperties && (minorRemovedProperties.attributes && (majorSetProperties || majorRemovedPropertyNames.length > 0))) {
+ removedPropertyNames = minorRemovedProperties.attributes.split(",");
+ for(i = 0;i < removedPropertyNames.length;i += 1) {
+ name = removedPropertyNames[i];
+ if(majorSetProperties && majorSetProperties[name] !== undefined || majorRemovedPropertyNames && majorRemovedPropertyNames.indexOf(name) !== -1) {
+ removedPropertyNames.splice(i, 1);
+ i -= 1;
+ minorChanged = true
+ }
+ }
+ if(removedPropertyNames.length > 0) {
+ minorRemovedProperties.attributes = removedPropertyNames.join(",")
+ }else {
+ delete minorRemovedProperties.attributes
+ }
+ }
+ return{majorChanged:majorChanged, minorChanged:minorChanged}
+ }
+ function hasProperties(properties) {
+ var key;
+ for(key in properties) {
+ if(properties.hasOwnProperty(key)) {
+ return true
+ }
+ }
+ return false
+ }
+ function hasRemovedProperties(properties) {
+ var key;
+ for(key in properties) {
+ if(properties.hasOwnProperty(key)) {
+ if(key !== "attributes" || properties.attributes.length > 0) {
+ return true
+ }
+ }
+ }
+ return false
+ }
+ function dropOverruledAndUnneededProperties(minorSet, minorRem, majorSet, majorRem, propertiesName) {
+ var minorSP = minorSet ? minorSet[propertiesName] : null, minorRP = minorRem ? minorRem[propertiesName] : null, majorSP = majorSet ? majorSet[propertiesName] : null, majorRP = majorRem ? majorRem[propertiesName] : null, result;
+ result = dropOverruledAndUnneededAttributes(minorSP, minorRP, majorSP, majorRP);
+ if(minorSP && !hasProperties(minorSP)) {
+ delete minorSet[propertiesName]
+ }
+ if(minorRP && !hasRemovedProperties(minorRP)) {
+ delete minorRem[propertiesName]
+ }
+ if(majorSP && !hasProperties(majorSP)) {
+ delete majorSet[propertiesName]
+ }
+ if(majorRP && !hasRemovedProperties(majorRP)) {
+ delete majorRem[propertiesName]
+ }
+ return result
+ }
+ function transformAddStyleRemoveStyle(addStyleSpec, removeStyleSpec) {
+ var setAttributes, helperOpspec, addStyleSpecResult = [addStyleSpec], removeStyleSpecResult = [removeStyleSpec];
+ if(addStyleSpec.styleFamily === removeStyleSpec.styleFamily) {
+ setAttributes = getStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName);
+ if(setAttributes.length > 0) {
+ helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:addStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
+ removeStyleSpecResult.unshift(helperOpspec)
+ }
+ dropStyleReferencingAttributes(addStyleSpec.setProperties, removeStyleSpec.styleName)
+ }
+ return{opSpecsA:addStyleSpecResult, opSpecsB:removeStyleSpecResult}
+ }
+ function transformApplyDirectStylingApplyDirectStyling(applyDirectStylingSpecA, applyDirectStylingSpecB, hasAPriority) {
+ var majorSpec, minorSpec, majorSpecResult, minorSpecResult, majorSpecEnd, minorSpecEnd, dropResult, originalMajorSpec, originalMinorSpec, helperOpspecBefore, helperOpspecAfter, applyDirectStylingSpecAResult = [applyDirectStylingSpecA], applyDirectStylingSpecBResult = [applyDirectStylingSpecB];
+ if(!(applyDirectStylingSpecA.position + applyDirectStylingSpecA.length <= applyDirectStylingSpecB.position || applyDirectStylingSpecA.position >= applyDirectStylingSpecB.position + applyDirectStylingSpecB.length)) {
+ majorSpec = hasAPriority ? applyDirectStylingSpecA : applyDirectStylingSpecB;
+ minorSpec = hasAPriority ? applyDirectStylingSpecB : applyDirectStylingSpecA;
+ if(applyDirectStylingSpecA.position !== applyDirectStylingSpecB.position || applyDirectStylingSpecA.length !== applyDirectStylingSpecB.length) {
+ originalMajorSpec = cloneOpspec(majorSpec);
+ originalMinorSpec = cloneOpspec(minorSpec)
+ }
+ dropResult = dropOverruledAndUnneededProperties(minorSpec.setProperties, null, majorSpec.setProperties, null, "style:text-properties");
+ if(dropResult.majorChanged || dropResult.minorChanged) {
+ majorSpecResult = [];
+ minorSpecResult = [];
+ majorSpecEnd = majorSpec.position + majorSpec.length;
+ minorSpecEnd = minorSpec.position + minorSpec.length;
+ if(minorSpec.position < majorSpec.position) {
+ if(dropResult.minorChanged) {
+ helperOpspecBefore = cloneOpspec((originalMinorSpec));
+ helperOpspecBefore.length = majorSpec.position - minorSpec.position;
+ minorSpecResult.push(helperOpspecBefore);
+ minorSpec.position = majorSpec.position;
+ minorSpec.length = minorSpecEnd - minorSpec.position
+ }
+ }else {
+ if(majorSpec.position < minorSpec.position) {
+ if(dropResult.majorChanged) {
+ helperOpspecBefore = cloneOpspec((originalMajorSpec));
+ helperOpspecBefore.length = minorSpec.position - majorSpec.position;
+ majorSpecResult.push(helperOpspecBefore);
+ majorSpec.position = minorSpec.position;
+ majorSpec.length = majorSpecEnd - majorSpec.position
+ }
+ }
+ }
+ if(minorSpecEnd > majorSpecEnd) {
+ if(dropResult.minorChanged) {
+ helperOpspecAfter = originalMinorSpec;
+ helperOpspecAfter.position = majorSpecEnd;
+ helperOpspecAfter.length = minorSpecEnd - majorSpecEnd;
+ minorSpecResult.push(helperOpspecAfter);
+ minorSpec.length = majorSpecEnd - minorSpec.position
+ }
+ }else {
+ if(majorSpecEnd > minorSpecEnd) {
+ if(dropResult.majorChanged) {
+ helperOpspecAfter = originalMajorSpec;
+ helperOpspecAfter.position = minorSpecEnd;
+ helperOpspecAfter.length = majorSpecEnd - minorSpecEnd;
+ majorSpecResult.push(helperOpspecAfter);
+ majorSpec.length = minorSpecEnd - majorSpec.position
+ }
+ }
+ }
+ if(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) {
+ majorSpecResult.push(majorSpec)
+ }
+ if(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) {
+ minorSpecResult.push(minorSpec)
+ }
+ if(hasAPriority) {
+ applyDirectStylingSpecAResult = majorSpecResult;
+ applyDirectStylingSpecBResult = minorSpecResult
+ }else {
+ applyDirectStylingSpecAResult = minorSpecResult;
+ applyDirectStylingSpecBResult = majorSpecResult
+ }
+ }
+ }
+ return{opSpecsA:applyDirectStylingSpecAResult, opSpecsB:applyDirectStylingSpecBResult}
+ }
+ function transformApplyDirectStylingInsertText(applyDirectStylingSpec, insertTextSpec) {
+ if(insertTextSpec.position <= applyDirectStylingSpec.position) {
+ applyDirectStylingSpec.position += insertTextSpec.text.length
+ }else {
+ if(insertTextSpec.position <= applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
+ applyDirectStylingSpec.length += insertTextSpec.text.length
+ }
+ }
+ return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[insertTextSpec]}
+ }
+ function transformApplyDirectStylingRemoveText(applyDirectStylingSpec, removeTextSpec) {
+ var applyDirectStylingSpecEnd = applyDirectStylingSpec.position + applyDirectStylingSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, applyDirectStylingSpecResult = [applyDirectStylingSpec], removeTextSpecResult = [removeTextSpec];
+ if(removeTextSpecEnd <= applyDirectStylingSpec.position) {
+ applyDirectStylingSpec.position -= removeTextSpec.length
+ }else {
+ if(removeTextSpec.position < applyDirectStylingSpecEnd) {
+ if(applyDirectStylingSpec.position < removeTextSpec.position) {
+ if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
+ applyDirectStylingSpec.length -= removeTextSpec.length
+ }else {
+ applyDirectStylingSpec.length = removeTextSpec.position - applyDirectStylingSpec.position
+ }
+ }else {
+ applyDirectStylingSpec.position = removeTextSpec.position;
+ if(removeTextSpecEnd < applyDirectStylingSpecEnd) {
+ applyDirectStylingSpec.length = applyDirectStylingSpecEnd - removeTextSpecEnd
+ }else {
+ applyDirectStylingSpecResult = []
+ }
+ }
+ }
+ }
+ return{opSpecsA:applyDirectStylingSpecResult, opSpecsB:removeTextSpecResult}
+ }
+ function transformApplyDirectStylingSplitParagraph(applyDirectStylingSpec, splitParagraphSpec) {
+ if(splitParagraphSpec.position < applyDirectStylingSpec.position) {
+ applyDirectStylingSpec.position += 1
+ }else {
+ if(splitParagraphSpec.position < applyDirectStylingSpec.position + applyDirectStylingSpec.length) {
+ applyDirectStylingSpec.length += 1
+ }
+ }
+ return{opSpecsA:[applyDirectStylingSpec], opSpecsB:[splitParagraphSpec]}
+ }
+ function transformInsertTextInsertText(insertTextSpecA, insertTextSpecB, hasAPriority) {
+ if(insertTextSpecA.position < insertTextSpecB.position) {
+ insertTextSpecB.position += insertTextSpecA.text.length
+ }else {
+ if(insertTextSpecA.position > insertTextSpecB.position) {
+ insertTextSpecA.position += insertTextSpecB.text.length
+ }else {
+ if(hasAPriority) {
+ insertTextSpecB.position += insertTextSpecA.text.length
+ }else {
+ insertTextSpecA.position += insertTextSpecB.text.length
+ }
+ }
+ }
+ return{opSpecsA:[insertTextSpecA], opSpecsB:[insertTextSpecB]}
+ }
+ function transformInsertTextMoveCursor(insertTextSpec, moveCursorSpec) {
+ var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
+ if(insertTextSpec.position < moveCursorSpec.position) {
+ moveCursorSpec.position += insertTextSpec.text.length
+ }else {
+ if(insertTextSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
+ moveCursorSpec.length += insertTextSpec.text.length
+ }
+ }
+ if(isMoveCursorSpecRangeInverted) {
+ invertMoveCursorSpecRange(moveCursorSpec)
+ }
+ return{opSpecsA:[insertTextSpec], opSpecsB:[moveCursorSpec]}
+ }
+ function transformInsertTextRemoveText(insertTextSpec, removeTextSpec) {
+ var helperOpspec, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, insertTextSpecResult = [insertTextSpec], removeTextSpecResult = [removeTextSpec];
+ if(removeTextSpecEnd <= insertTextSpec.position) {
+ insertTextSpec.position -= removeTextSpec.length
+ }else {
+ if(insertTextSpec.position <= removeTextSpec.position) {
+ removeTextSpec.position += insertTextSpec.text.length
+ }else {
+ removeTextSpec.length = insertTextSpec.position - removeTextSpec.position;
+ helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:insertTextSpec.position + insertTextSpec.text.length, length:removeTextSpecEnd - insertTextSpec.position};
+ removeTextSpecResult.unshift(helperOpspec);
+ insertTextSpec.position = removeTextSpec.position
+ }
+ }
+ return{opSpecsA:insertTextSpecResult, opSpecsB:removeTextSpecResult}
+ }
+ function transformInsertTextSplitParagraph(insertTextSpec, splitParagraphSpec, hasAPriority) {
+ if(insertTextSpec.position < splitParagraphSpec.position) {
+ splitParagraphSpec.position += insertTextSpec.text.length
+ }else {
+ if(insertTextSpec.position > splitParagraphSpec.position) {
+ insertTextSpec.position += 1
+ }else {
+ if(hasAPriority) {
+ splitParagraphSpec.position += insertTextSpec.text.length
+ }else {
+ insertTextSpec.position += 1
+ }
+ return null
+ }
+ }
+ return{opSpecsA:[insertTextSpec], opSpecsB:[splitParagraphSpec]}
+ }
+ function transformUpdateParagraphStyleUpdateParagraphStyle(updateParagraphStyleSpecA, updateParagraphStyleSpecB, hasAPriority) {
+ var majorSpec, minorSpec, updateParagraphStyleSpecAResult = [updateParagraphStyleSpecA], updateParagraphStyleSpecBResult = [updateParagraphStyleSpecB];
+ if(updateParagraphStyleSpecA.styleName === updateParagraphStyleSpecB.styleName) {
+ majorSpec = hasAPriority ? updateParagraphStyleSpecA : updateParagraphStyleSpecB;
+ minorSpec = hasAPriority ? updateParagraphStyleSpecB : updateParagraphStyleSpecA;
+ dropOverruledAndUnneededProperties(minorSpec.setProperties, minorSpec.removedProperties, majorSpec.setProperties, majorSpec.removedProperties, "style:paragraph-properties");
+ dropOverruledAndUnneededProperties(minorSpec.setProperties, minorSpec.removedProperties, majorSpec.setProperties, majorSpec.removedProperties, "style:text-properties");
+ dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, (minorSpec.removedProperties) || null, majorSpec.setProperties || null, (majorSpec.removedProperties) || null);
+ if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
+ if(hasAPriority) {
+ updateParagraphStyleSpecAResult = []
+ }else {
+ updateParagraphStyleSpecBResult = []
+ }
+ }
+ if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
+ if(hasAPriority) {
+ updateParagraphStyleSpecBResult = []
+ }else {
+ updateParagraphStyleSpecAResult = []
+ }
+ }
+ }
+ return{opSpecsA:updateParagraphStyleSpecAResult, opSpecsB:updateParagraphStyleSpecBResult}
+ }
+ function transformUpdateMetadataUpdateMetadata(updateMetadataSpecA, updateMetadataSpecB, hasAPriority) {
+ var majorSpec, minorSpec, updateMetadataSpecAResult = [updateMetadataSpecA], updateMetadataSpecBResult = [updateMetadataSpecB];
+ majorSpec = hasAPriority ? updateMetadataSpecA : updateMetadataSpecB;
+ minorSpec = hasAPriority ? updateMetadataSpecB : updateMetadataSpecA;
+ dropOverruledAndUnneededAttributes(minorSpec.setProperties || null, minorSpec.removedProperties || null, majorSpec.setProperties || null, majorSpec.removedProperties || null);
+ if(!(majorSpec.setProperties && hasProperties(majorSpec.setProperties)) && !(majorSpec.removedProperties && hasRemovedProperties(majorSpec.removedProperties))) {
+ if(hasAPriority) {
+ updateMetadataSpecAResult = []
+ }else {
+ updateMetadataSpecBResult = []
+ }
+ }
+ if(!(minorSpec.setProperties && hasProperties(minorSpec.setProperties)) && !(minorSpec.removedProperties && hasRemovedProperties(minorSpec.removedProperties))) {
+ if(hasAPriority) {
+ updateMetadataSpecBResult = []
+ }else {
+ updateMetadataSpecAResult = []
+ }
+ }
+ return{opSpecsA:updateMetadataSpecAResult, opSpecsB:updateMetadataSpecBResult}
+ }
+ function transformSplitParagraphSplitParagraph(splitParagraphSpecA, splitParagraphSpecB, hasAPriority) {
+ if(splitParagraphSpecA.position < splitParagraphSpecB.position) {
+ splitParagraphSpecB.position += 1
+ }else {
+ if(splitParagraphSpecA.position > splitParagraphSpecB.position) {
+ splitParagraphSpecA.position += 1
+ }else {
+ if(splitParagraphSpecA.position === splitParagraphSpecB.position) {
+ if(hasAPriority) {
+ splitParagraphSpecB.position += 1
+ }else {
+ splitParagraphSpecA.position += 1
+ }
+ }
+ }
+ }
+ return{opSpecsA:[splitParagraphSpecA], opSpecsB:[splitParagraphSpecB]}
+ }
+ function transformMoveCursorRemoveCursor(moveCursorSpec, removeCursorSpec) {
+ var isSameCursorRemoved = moveCursorSpec.memberid === removeCursorSpec.memberid;
+ return{opSpecsA:isSameCursorRemoved ? [] : [moveCursorSpec], opSpecsB:[removeCursorSpec]}
+ }
+ function transformMoveCursorRemoveText(moveCursorSpec, removeTextSpec) {
+ var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec), moveCursorSpecEnd = moveCursorSpec.position + moveCursorSpec.length, removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length;
+ if(removeTextSpecEnd <= moveCursorSpec.position) {
+ moveCursorSpec.position -= removeTextSpec.length
+ }else {
+ if(removeTextSpec.position < moveCursorSpecEnd) {
+ if(moveCursorSpec.position < removeTextSpec.position) {
+ if(removeTextSpecEnd < moveCursorSpecEnd) {
+ moveCursorSpec.length -= removeTextSpec.length
+ }else {
+ moveCursorSpec.length = removeTextSpec.position - moveCursorSpec.position
+ }
+ }else {
+ moveCursorSpec.position = removeTextSpec.position;
+ if(removeTextSpecEnd < moveCursorSpecEnd) {
+ moveCursorSpec.length = moveCursorSpecEnd - removeTextSpecEnd
+ }else {
+ moveCursorSpec.length = 0
+ }
+ }
+ }
+ }
+ if(isMoveCursorSpecRangeInverted) {
+ invertMoveCursorSpecRange(moveCursorSpec)
+ }
+ return{opSpecsA:[moveCursorSpec], opSpecsB:[removeTextSpec]}
+ }
+ function transformMoveCursorSplitParagraph(moveCursorSpec, splitParagraphSpec) {
+ var isMoveCursorSpecRangeInverted = invertMoveCursorSpecRangeOnNegativeLength(moveCursorSpec);
+ if(splitParagraphSpec.position < moveCursorSpec.position) {
+ moveCursorSpec.position += 1
+ }else {
+ if(splitParagraphSpec.position < moveCursorSpec.position + moveCursorSpec.length) {
+ moveCursorSpec.length += 1
+ }
+ }
+ if(isMoveCursorSpecRangeInverted) {
+ invertMoveCursorSpecRange(moveCursorSpec)
+ }
+ return{opSpecsA:[moveCursorSpec], opSpecsB:[splitParagraphSpec]}
+ }
+ function transformRemoveCursorRemoveCursor(removeCursorSpecA, removeCursorSpecB) {
+ var isSameMemberid = removeCursorSpecA.memberid === removeCursorSpecB.memberid;
+ return{opSpecsA:isSameMemberid ? [] : [removeCursorSpecA], opSpecsB:isSameMemberid ? [] : [removeCursorSpecB]}
+ }
+ function transformRemoveStyleRemoveStyle(removeStyleSpecA, removeStyleSpecB) {
+ var isSameStyle = removeStyleSpecA.styleName === removeStyleSpecB.styleName && removeStyleSpecA.styleFamily === removeStyleSpecB.styleFamily;
+ return{opSpecsA:isSameStyle ? [] : [removeStyleSpecA], opSpecsB:isSameStyle ? [] : [removeStyleSpecB]}
+ }
+ function transformRemoveStyleSetParagraphStyle(removeStyleSpec, setParagraphStyleSpec) {
+ var helperOpspec, removeStyleSpecResult = [removeStyleSpec], setParagraphStyleSpecResult = [setParagraphStyleSpec];
+ if(removeStyleSpec.styleFamily === "paragraph" && removeStyleSpec.styleName === setParagraphStyleSpec.styleName) {
+ helperOpspec = {optype:"SetParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, position:setParagraphStyleSpec.position, styleName:""};
+ removeStyleSpecResult.unshift(helperOpspec);
+ setParagraphStyleSpec.styleName = ""
+ }
+ return{opSpecsA:removeStyleSpecResult, opSpecsB:setParagraphStyleSpecResult}
+ }
+ function transformRemoveStyleUpdateParagraphStyle(removeStyleSpec, updateParagraphStyleSpec) {
+ var setAttributes, helperOpspec, removeStyleSpecResult = [removeStyleSpec], updateParagraphStyleSpecResult = [updateParagraphStyleSpec];
+ if(removeStyleSpec.styleFamily === "paragraph") {
+ setAttributes = getStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName);
+ if(setAttributes.length > 0) {
+ helperOpspec = {optype:"UpdateParagraphStyle", memberid:removeStyleSpec.memberid, timestamp:removeStyleSpec.timestamp, styleName:updateParagraphStyleSpec.styleName, removedProperties:{attributes:setAttributes.join(",")}};
+ removeStyleSpecResult.unshift(helperOpspec)
+ }
+ if(removeStyleSpec.styleName === updateParagraphStyleSpec.styleName) {
+ updateParagraphStyleSpecResult = []
+ }else {
+ dropStyleReferencingAttributes(updateParagraphStyleSpec.setProperties, removeStyleSpec.styleName)
+ }
+ }
+ return{opSpecsA:removeStyleSpecResult, opSpecsB:updateParagraphStyleSpecResult}
+ }
+ function transformRemoveTextRemoveText(removeTextSpecA, removeTextSpecB) {
+ var removeTextSpecAEnd = removeTextSpecA.position + removeTextSpecA.length, removeTextSpecBEnd = removeTextSpecB.position + removeTextSpecB.length, removeTextSpecAResult = [removeTextSpecA], removeTextSpecBResult = [removeTextSpecB];
+ if(removeTextSpecBEnd <= removeTextSpecA.position) {
+ removeTextSpecA.position -= removeTextSpecB.length
+ }else {
+ if(removeTextSpecAEnd <= removeTextSpecB.position) {
+ removeTextSpecB.position -= removeTextSpecA.length
+ }else {
+ if(removeTextSpecB.position < removeTextSpecAEnd) {
+ if(removeTextSpecA.position < removeTextSpecB.position) {
+ if(removeTextSpecBEnd < removeTextSpecAEnd) {
+ removeTextSpecA.length = removeTextSpecA.length - removeTextSpecB.length
+ }else {
+ removeTextSpecA.length = removeTextSpecB.position - removeTextSpecA.position
+ }
+ if(removeTextSpecAEnd < removeTextSpecBEnd) {
+ removeTextSpecB.position = removeTextSpecA.position;
+ removeTextSpecB.length = removeTextSpecBEnd - removeTextSpecAEnd
+ }else {
+ removeTextSpecBResult = []
+ }
+ }else {
+ if(removeTextSpecAEnd < removeTextSpecBEnd) {
+ removeTextSpecB.length = removeTextSpecB.length - removeTextSpecA.length
+ }else {
+ if(removeTextSpecB.position < removeTextSpecA.position) {
+ removeTextSpecB.length = removeTextSpecA.position - removeTextSpecB.position
+ }else {
+ removeTextSpecBResult = []
+ }
+ }
+ if(removeTextSpecBEnd < removeTextSpecAEnd) {
+ removeTextSpecA.position = removeTextSpecB.position;
+ removeTextSpecA.length = removeTextSpecAEnd - removeTextSpecBEnd
+ }else {
+ removeTextSpecAResult = []
+ }
+ }
+ }
+ }
+ }
+ return{opSpecsA:removeTextSpecAResult, opSpecsB:removeTextSpecBResult}
+ }
+ function transformRemoveTextSplitParagraph(removeTextSpec, splitParagraphSpec) {
+ var removeTextSpecEnd = removeTextSpec.position + removeTextSpec.length, helperOpspec, removeTextSpecResult = [removeTextSpec], splitParagraphSpecResult = [splitParagraphSpec];
+ if(splitParagraphSpec.position <= removeTextSpec.position) {
+ removeTextSpec.position += 1
+ }else {
+ if(splitParagraphSpec.position < removeTextSpecEnd) {
+ removeTextSpec.length = splitParagraphSpec.position - removeTextSpec.position;
+ helperOpspec = {optype:"RemoveText", memberid:removeTextSpec.memberid, timestamp:removeTextSpec.timestamp, position:splitParagraphSpec.position + 1, length:removeTextSpecEnd - splitParagraphSpec.position};
+ removeTextSpecResult.unshift(helperOpspec)
+ }
+ }
+ if(removeTextSpec.position + removeTextSpec.length <= splitParagraphSpec.position) {
+ splitParagraphSpec.position -= removeTextSpec.length
+ }else {
+ if(removeTextSpec.position < splitParagraphSpec.position) {
+ splitParagraphSpec.position = removeTextSpec.position
+ }
+ }
+ return{opSpecsA:removeTextSpecResult, opSpecsB:splitParagraphSpecResult}
+ }
+ function passUnchanged(opSpecA, opSpecB) {
+ return{opSpecsA:[opSpecA], opSpecsB:[opSpecB]}
+ }
+ var transformations;
+ transformations = {"AddCursor":{"AddCursor":passUnchanged, "AddMember":passUnchanged, "AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "AddMember":{"AddStyle":passUnchanged,
+ "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "AddStyle":{"AddStyle":passUnchanged, "ApplyDirectStyling":passUnchanged, "InsertText":passUnchanged, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":transformAddStyleRemoveStyle,
+ "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "ApplyDirectStyling":{"ApplyDirectStyling":transformApplyDirectStylingApplyDirectStyling, "InsertText":transformApplyDirectStylingInsertText, "MoveCursor":passUnchanged, "RemoveCursor":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformApplyDirectStylingRemoveText, "SetParagraphStyle":passUnchanged,
+ "SplitParagraph":transformApplyDirectStylingSplitParagraph, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "InsertText":{"InsertText":transformInsertTextInsertText, "MoveCursor":transformInsertTextMoveCursor, "RemoveCursor":passUnchanged, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformInsertTextRemoveText, "SplitParagraph":transformInsertTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged},
+ "MoveCursor":{"MoveCursor":passUnchanged, "RemoveCursor":transformMoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged, "RemoveText":transformMoveCursorRemoveText, "SetParagraphStyle":passUnchanged, "SplitParagraph":transformMoveCursorSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveCursor":{"RemoveCursor":transformRemoveCursorRemoveCursor, "RemoveMember":passUnchanged, "RemoveStyle":passUnchanged,
+ "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveMember":{"RemoveStyle":passUnchanged, "RemoveText":passUnchanged, "SetParagraphStyle":passUnchanged, "SplitParagraph":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "RemoveStyle":{"RemoveStyle":transformRemoveStyleRemoveStyle, "RemoveText":passUnchanged, "SetParagraphStyle":transformRemoveStyleSetParagraphStyle,
+ "SplitParagraph":passUnchanged, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":transformRemoveStyleUpdateParagraphStyle}, "RemoveText":{"RemoveText":transformRemoveTextRemoveText, "SplitParagraph":transformRemoveTextSplitParagraph, "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "SetParagraphStyle":{"UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "SplitParagraph":{"SplitParagraph":transformSplitParagraphSplitParagraph,
+ "UpdateMember":passUnchanged, "UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMember":{"UpdateMetadata":passUnchanged, "UpdateParagraphStyle":passUnchanged}, "UpdateMetadata":{"UpdateMetadata":transformUpdateMetadataUpdateMetadata, "UpdateParagraphStyle":passUnchanged}, "UpdateParagraphStyle":{"UpdateParagraphStyle":transformUpdateParagraphStyleUpdateParagraphStyle}};
+ this.passUnchanged = passUnchanged;
+ this.extendTransformations = function(moreTransformations) {
+ Object.keys(moreTransformations).forEach(function(optypeA) {
+ var moreTransformationsOptypeAMap = moreTransformations[optypeA], optypeAMap, isExtendingOptypeAMap = transformations.hasOwnProperty(optypeA);
+ runtime.log((isExtendingOptypeAMap ? "Extending" : "Adding") + " map for optypeA: " + optypeA);
+ if(!isExtendingOptypeAMap) {
+ transformations[optypeA] = {}
+ }
+ optypeAMap = transformations[optypeA];
+ Object.keys(moreTransformationsOptypeAMap).forEach(function(optypeB) {
+ var isOverwritingOptypeBEntry = optypeAMap.hasOwnProperty(optypeB);
+ runtime.assert(optypeA <= optypeB, "Wrong order:" + optypeA + ", " + optypeB);
+ runtime.log(" " + (isOverwritingOptypeBEntry ? "Overwriting" : "Adding") + " entry for optypeB: " + optypeB);
+ optypeAMap[optypeB] = moreTransformationsOptypeAMap[optypeB]
+ })
+ })
+ };
+ this.transformOpspecVsOpspec = function(opSpecA, opSpecB) {
+ var isOptypeAAlphaNumericSmaller = opSpecA.optype <= opSpecB.optype, helper, transformationFunctionMap, transformationFunction, result;
+ runtime.log("Crosstransforming:");
+ runtime.log(runtime.toJson(opSpecA));
+ runtime.log(runtime.toJson(opSpecB));
+ if(!isOptypeAAlphaNumericSmaller) {
+ helper = opSpecA;
+ opSpecA = opSpecB;
+ opSpecB = helper
+ }
+ transformationFunctionMap = transformations[opSpecA.optype];
+ transformationFunction = transformationFunctionMap && transformationFunctionMap[opSpecB.optype];
+ if(transformationFunction) {
+ result = transformationFunction(opSpecA, opSpecB, !isOptypeAAlphaNumericSmaller);
+ if(!isOptypeAAlphaNumericSmaller && result !== null) {
+ result = {opSpecsA:result.opSpecsB, opSpecsB:result.opSpecsA}
+ }
+ }else {
+ result = null
+ }
+ runtime.log("result:");
+ if(result) {
+ runtime.log(runtime.toJson(result.opSpecsA));
+ runtime.log(runtime.toJson(result.opSpecsB))
+ }else {
+ runtime.log("null")
+ }
+ return result
+ }
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OperationTransformer = function OperationTransformer() {
+ var operationFactory, operationTransformMatrix = new ops.OperationTransformMatrix;
+ function operations(opspecs) {
+ var ops = [];
+ opspecs.forEach(function(opspec) {
+ ops.push(operationFactory.create(opspec))
+ });
+ return ops
+ }
+ function transformOpVsOp(opSpecA, opSpecB) {
+ return operationTransformMatrix.transformOpspecVsOpspec(opSpecA, opSpecB)
+ }
+ function transformOpListVsOp(opSpecsA, opSpecB) {
+ var transformResult, transformListResult, transformedOpspecsA = [], transformedOpspecsB = [];
+ while(opSpecsA.length > 0 && opSpecB) {
+ transformResult = transformOpVsOp(opSpecsA.shift(), opSpecB);
+ if(!transformResult) {
+ return null
+ }
+ transformedOpspecsA = transformedOpspecsA.concat(transformResult.opSpecsA);
+ if(transformResult.opSpecsB.length === 0) {
+ transformedOpspecsA = transformedOpspecsA.concat(opSpecsA);
+ opSpecB = null;
+ break
+ }
+ while(transformResult.opSpecsB.length > 1) {
+ transformListResult = transformOpListVsOp(opSpecsA, transformResult.opSpecsB.shift());
+ if(!transformListResult) {
+ return null
+ }
+ transformedOpspecsB = transformedOpspecsB.concat(transformListResult.opSpecsB);
+ opSpecsA = transformListResult.opSpecsA
+ }
+ opSpecB = transformResult.opSpecsB.pop()
+ }
+ if(opSpecB) {
+ transformedOpspecsB.push(opSpecB)
+ }
+ return{opSpecsA:transformedOpspecsA, opSpecsB:transformedOpspecsB}
+ }
+ this.setOperationFactory = function(f) {
+ operationFactory = f
+ };
+ this.getOperationTransformMatrix = function() {
+ return operationTransformMatrix
+ };
+ this.transform = function(opSpecsA, opSpecsB) {
+ var transformResult, transformedOpspecsB = [];
+ while(opSpecsB.length > 0) {
+ transformResult = transformOpListVsOp(opSpecsA, opSpecsB.shift());
+ if(!transformResult) {
+ return null
+ }
+ opSpecsA = transformResult.opSpecsA;
+ transformedOpspecsB = transformedOpspecsB.concat(transformResult.opSpecsB)
+ }
+ return{opsA:operations(opSpecsA), opsB:operations(transformedOpspecsB)}
+ }
+};
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.Server = function Server() {
+};
+ops.Server.prototype.connect = function(timeout, cb) {
+};
+ops.Server.prototype.networkStatus = function() {
+};
+ops.Server.prototype.login = function(login, password, successCb, failCb) {
+};
+ops.Server.prototype.joinSession = function(userId, sessionId, successCb, failCb) {
+};
+ops.Server.prototype.leaveSession = function(sessionId, memberId, successCb, failCb) {
+};
+ops.Server.prototype.getGenesisUrl = function(sessionId) {
+};
+var webodf_css = '@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0);\n@namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0);\n@namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0);\n@namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0);\n@namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0);\n@namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0);\n@namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0);\n@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0);\n@namespace webodfhelper url(urn:webodf:names:helper);\n@namespace cursor url(urn:webodf:names:cursor);\n@namespace editinfo url(urn:webodf:names:editinfo);\n@namespace annotation url(urn:webodf:names:annotation);\n@namespace dc url(http://purl.org/dc/elements/1.1/);\n@namespace svgns url(http://www.w3.org/2000/svg);\n\noffice|document > *, office|document-content > * {\n display: none;\n}\noffice|body, office|document {\n display: inline-block;\n position: relative;\n}\n\ntext|p, text|h {\n display: block;\n padding: 0;\n margin: 0;\n line-height: normal;\n position: relative;\n min-height: 1.3em; /* prevent empty paragraphs and headings from collapsing if they are empty */\n}\n*[webodfhelper|containsparagraphanchor] {\n position: relative;\n}\ntext|s {\n white-space: pre;\n}\ntext|tab {\n display: inline;\n white-space: pre;\n}\ntext|tracked-changes {\n /*Consumers that do not support change tracking, should ignore changes.*/\n display: none;\n}\noffice|binary-data {\n display: none;\n}\noffice|text {\n display: block;\n text-align: left;\n overflow: visible;\n word-wrap: break-word;\n}\n\noffice|text::selection {\n /** Let\'s not draw selection highlight that overflows into the office|text\n * node when selecting content across several paragraphs\n */\n background: transparent;\n}\n\noffice|document *::selection {\n background: transparent;\n}\noffice|document *::-moz-selection {\n background: transparent;\n}\n\noffice|text * draw|text-box {\n/** only for text documents */\n display: block;\n border: 1px solid #d3d3d3;\n}\ndraw|frame {\n /** make sure frames are above the main body. */\n z-index: 1;\n}\noffice|spreadsheet {\n display: block;\n border-collapse: collapse;\n empty-cells: show;\n font-family: sans-serif;\n font-size: 10pt;\n text-align: left;\n page-break-inside: avoid;\n overflow: hidden;\n}\noffice|presentation {\n display: inline-block;\n text-align: left;\n}\n#shadowContent {\n display: inline-block;\n text-align: left;\n}\ndraw|page {\n display: block;\n position: relative;\n overflow: hidden;\n}\npresentation|notes, presentation|footer-decl, presentation|date-time-decl {\n display: none;\n}\n@media print {\n draw|page {\n border: 1pt solid black;\n page-break-inside: avoid;\n }\n presentation|notes {\n /*TODO*/\n }\n}\noffice|spreadsheet text|p {\n border: 0px;\n padding: 1px;\n margin: 0px;\n}\noffice|spreadsheet table|table {\n margin: 3px;\n}\noffice|spreadsheet table|table:after {\n /* show sheet name the end of the sheet */\n /*content: attr(table|name);*/ /* gives parsing error in opera */\n}\noffice|spreadsheet table|table-row {\n counter-increment: row;\n}\noffice|spreadsheet table|table-row:before {\n width: 3em;\n background: #cccccc;\n border: 1px solid black;\n text-align: center;\n content: counter(row);\n display: table-cell;\n}\noffice|spreadsheet table|table-cell {\n border: 1px solid #cccccc;\n}\ntable|table {\n display: table;\n}\ndraw|frame table|table {\n width: 100%;\n height: 100%;\n background: white;\n}\ntable|table-header-rows {\n display: table-header-group;\n}\ntable|table-row {\n display: table-row;\n}\ntable|table-column {\n display: table-column;\n}\ntable|table-cell {\n width: 0.889in;\n display: table-cell;\n word-break: break-all; /* prevent long words from extending out the table cell */\n}\ndraw|frame {\n display: block;\n}\ndraw|image {\n display: block;\n width: 100%;\n height: 100%;\n top: 0px;\n left: 0px;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n -moz-background-size: 100% 100%;\n}\n/* only show the first image in frame */\ndraw|frame > draw|image:nth-of-type(n+2) {\n display: none;\n}\ntext|list:before {\n display: none;\n content:"";\n}\ntext|list {\n counter-reset: list;\n}\ntext|list-item {\n display: block;\n}\ntext|number {\n display:none;\n}\n\ntext|a {\n color: blue;\n text-decoration: underline;\n cursor: pointer;\n}\noffice|text[webodfhelper|links="inactive"] text|a {\n cursor: text;\n}\ntext|note-citation {\n vertical-align: super;\n font-size: smaller;\n}\ntext|note-body {\n display: none;\n}\ntext|note:hover text|note-citation {\n background: #dddddd;\n}\ntext|note:hover text|note-body {\n display: block;\n left:1em;\n max-width: 80%;\n position: absolute;\n background: #ffffaa;\n}\nsvg|title, svg|desc {\n display: none;\n}\nvideo {\n width: 100%;\n height: 100%\n}\n\n/* below set up the cursor */\ncursor|cursor {\n display: inline;\n width: 0;\n height: 1em;\n /* making the position relative enables the avatar to use\n the cursor as reference for its absolute position */\n position: relative;\n z-index: 1;\n pointer-events: none;\n}\n\ncursor|cursor > .caret {\n /* IMPORTANT: when changing these values ensure DEFAULT_CARET_TOP and DEFAULT_CARET_HEIGHT\n in Caret.js remain in sync */\n display: inline;\n position: absolute;\n top: 5%; /* push down the caret; 0px can do the job, 5% looks better, 10% is a bit over */\n height: 1em;\n border-left: 2px solid black;\n outline: none;\n}\n\ncursor|cursor > .handle {\n padding: 3px;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n border: none !important;\n border-radius: 5px;\n opacity: 0.3;\n}\n\ncursor|cursor > .handle > img {\n border-radius: 5px;\n}\n\ncursor|cursor > .handle.active {\n opacity: 0.8;\n}\n\ncursor|cursor > .handle:after {\n content: \' \';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 43%;\n}\n\n/** Input Method Editor input pane & behaviours */\n/* not within a cursor */\n#eventTrap {\n height: auto;\n display: block;\n position: absolute;\n width: 1px;\n outline: none;\n opacity: 0;\n color: rgba(255, 255, 255, 0); /* hide the blinking caret by setting the colour to fully transparent */\n overflow: hidden; /* The overflow visibility is used to hide and show characters being entered */\n pointer-events: none;\n}\n\n/* within a cursor */\ncursor|cursor > #composer {\n text-decoration: underline;\n}\n\ncursor|cursor[cursor|composing="true"] > #composer {\n display: inline-block;\n height: auto;\n width: auto;\n}\n\ncursor|cursor[cursor|composing="true"] {\n display: inline-block;\n width: auto;\n height: inherit;\n}\n\ncursor|cursor[cursor|composing="true"] > .caret {\n /* during composition, the caret should be pushed along by the composition text, inline with the text */\n position: static;\n /* as it is now part of an inline-block, it will no longer need correct to top or height values to align properly */\n height: auto !important;\n top: auto !important;\n}\n\neditinfo|editinfo {\n /* Empty or invisible display:inline elements respond very badly to mouse selection.\n Inline blocks are much more reliably selectable in Chrome & friends */\n display: inline-block;\n}\n\n.editInfoMarker {\n position: absolute;\n width: 10px;\n height: 100%;\n left: -20px;\n opacity: 0.8;\n top: 0;\n border-radius: 5px;\n background-color: transparent;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n}\n.editInfoMarker:hover {\n box-shadow: 0px 0px 8px rgba(0, 0, 0, 1);\n}\n\n.editInfoHandle {\n position: absolute;\n background-color: black;\n padding: 5px;\n border-radius: 5px;\n opacity: 0.8;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n bottom: 100%;\n margin-bottom: 10px;\n z-index: 3;\n left: -25px;\n}\n.editInfoHandle:after {\n content: \' \';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 5px;\n}\n.editInfo {\n font-family: sans-serif;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n color: white;\n width: 100%;\n height: 12pt;\n}\n.editInfoColor {\n float: left;\n width: 10pt;\n height: 10pt;\n border: 1px solid white;\n}\n.editInfoAuthor {\n float: left;\n margin-left: 5pt;\n font-size: 10pt;\n text-align: left;\n height: 12pt;\n line-height: 12pt;\n}\n.editInfoTime {\n float: right;\n margin-left: 30pt;\n font-size: 8pt;\n font-style: italic;\n color: yellow;\n height: 12pt;\n line-height: 12pt;\n}\n\n.annotationWrapper {\n display: inline;\n position: relative;\n}\n\n.annotationRemoveButton:before {\n content: \'\u00d7\';\n color: white;\n padding: 5px;\n line-height: 1em;\n}\n\n.annotationRemoveButton {\n width: 20px;\n height: 20px;\n border-radius: 10px;\n background-color: black;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n position: absolute;\n top: -10px;\n left: -10px;\n z-index: 3;\n text-align: center;\n font-family: sans-serif;\n font-style: normal;\n font-weight: normal;\n text-decoration: none;\n font-size: 15px;\n}\n.annotationRemoveButton:hover {\n cursor: pointer;\n box-shadow: 0px 0px 5px rgba(0, 0, 0, 1);\n}\n\n.annotationNote {\n width: 4cm;\n position: absolute;\n display: inline;\n z-index: 10;\n}\n.annotationNote > office|annotation {\n display: block;\n text-align: left;\n}\n\n.annotationConnector {\n position: absolute;\n display: inline;\n z-index: 2;\n border-top: 1px dashed brown;\n}\n.annotationConnector.angular {\n -moz-transform-origin: left top;\n -webkit-transform-origin: left top;\n -ms-transform-origin: left top;\n transform-origin: left top;\n}\n.annotationConnector.horizontal {\n left: 0;\n}\n.annotationConnector.horizontal:before {\n content: \'\';\n display: inline;\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: brown transparent transparent transparent;\n top: -1px;\n left: -5px;\n}\n\noffice|annotation {\n width: 100%;\n height: 100%;\n display: none;\n background: rgb(198, 238, 184);\n background: -moz-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -webkit-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -o-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -ms-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: linear-gradient(180deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n box-shadow: 0 3px 4px -3px #ccc;\n}\n\noffice|annotation > dc|creator {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n color: white;\n background-color: brown;\n padding: 4px;\n}\noffice|annotation > dc|date {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n border: 4px solid transparent;\n color: black;\n}\noffice|annotation > text|list {\n display: block;\n padding: 5px;\n}\n\n/* This is very temporary CSS. This must go once\n * we start bundling webodf-default ODF styles for annotations.\n */\noffice|annotation text|p {\n font-size: 10pt;\n color: black;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n font-family: sans-serif;\n}\n\ndc|*::selection {\n background: transparent;\n}\ndc|*::-moz-selection {\n background: transparent;\n}\n\n#annotationsPane {\n background-color: #EAEAEA;\n width: 4cm;\n height: 100%;\n display: none;\n position: absolute;\n outline: 1px solid #ccc;\n}\n\n.annotationHighlight {\n background-color: yellow;\n position: relative;\n}\n\n.selectionOverlay {\n position: absolute;\n pointer-events: none;\n top: 0;\n left: 0;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 15;\n}\n.selectionOverlay > polygon {\n fill-opacity: 0.3;\n stroke-opacity: 0.8;\n stroke-width: 1;\n fill-rule: evenodd;\n}\n\n#imageSelector {\n display: none;\n position: absolute;\n border-style: solid;\n border-color: black;\n}\n\n#imageSelector > div {\n width: 5px;\n height: 5px;\n display: block;\n position: absolute;\n border: 1px solid black;\n background-color: #ffffff;\n}\n\n#imageSelector > .topLeft {\n top: -4px;\n left: -4px;\n}\n\n#imageSelector > .topRight {\n top: -4px;\n right: -4px;\n}\n\n#imageSelector > .bottomRight {\n right: -4px;\n bottom: -4px;\n}\n\n#imageSelector > .bottomLeft {\n bottom: -4px;\n left: -4px;\n}\n\n#imageSelector > .topMiddle {\n top: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .rightMiddle {\n top: 50%;\n right: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n\n#imageSelector > .bottomMiddle {\n bottom: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .leftMiddle {\n top: 50%;\n left: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n\ndiv.customScrollbars::-webkit-scrollbar\n{\n width: 8px;\n height: 8px;\n background-color: transparent;\n}\n\ndiv.customScrollbars::-webkit-scrollbar-track\n{\n background-color: transparent;\n}\n\ndiv.customScrollbars::-webkit-scrollbar-thumb\n{\n background-color: #444;\n border-radius: 4px;\n}\n';
diff --git a/js/3rdparty/webodf/webodf.js b/js/3rdparty/webodf/webodf.js
index 688b4a12..2690b0fd 100644
--- a/js/3rdparty/webodf/webodf.js
+++ b/js/3rdparty/webodf/webodf.js
@@ -1,55 +1,57 @@
// Input 0
-var webodf_version="0.4.2-1579-gfc3a4e6";
+var webodf_version="0.4.2-2010-ge06842f";
// Input 1
-function Runtime(){}Runtime.prototype.getVariable=function(g){};Runtime.prototype.toJson=function(g){};Runtime.prototype.fromJson=function(g){};Runtime.prototype.byteArrayFromString=function(g,l){};Runtime.prototype.byteArrayToString=function(g,l){};Runtime.prototype.read=function(g,l,f,p){};Runtime.prototype.readFile=function(g,l,f){};Runtime.prototype.readFileSync=function(g,l){};Runtime.prototype.loadXML=function(g,l){};Runtime.prototype.writeFile=function(g,l,f){};
-Runtime.prototype.isFile=function(g,l){};Runtime.prototype.getFileSize=function(g,l){};Runtime.prototype.deleteFile=function(g,l){};Runtime.prototype.log=function(g,l){};Runtime.prototype.setTimeout=function(g,l){};Runtime.prototype.clearTimeout=function(g){};Runtime.prototype.libraryPaths=function(){};Runtime.prototype.currentDirectory=function(){};Runtime.prototype.setCurrentDirectory=function(g){};Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};
-Runtime.prototype.parseXML=function(g){};Runtime.prototype.exit=function(g){};Runtime.prototype.getWindow=function(){};Runtime.prototype.assert=function(g,l,f){};var IS_COMPILED_CODE=!0;
-Runtime.byteArrayToString=function(g,l){function f(f){var h="",d,m=f.length;for(d=0;d<m;d+=1)h+=String.fromCharCode(f[d]&255);return h}function p(f){var h="",d,m=f.length,c=[],e,a,b,q;for(d=0;d<m;d+=1)e=f[d],128>e?c.push(e):(d+=1,a=f[d],194<=e&&224>e?c.push((e&31)<<6|a&63):(d+=1,b=f[d],224<=e&&240>e?c.push((e&15)<<12|(a&63)<<6|b&63):(d+=1,q=f[d],240<=e&&245>e&&(e=(e&7)<<18|(a&63)<<12|(b&63)<<6|q&63,e-=65536,c.push((e>>10)+55296,(e&1023)+56320))))),1E3===c.length&&(h+=String.fromCharCode.apply(null,
-c),c.length=0);return h+String.fromCharCode.apply(null,c)}var r;"utf8"===l?r=p(g):("binary"!==l&&this.log("Unsupported encoding: "+l),r=f(g));return r};Runtime.getVariable=function(g){try{return eval(g)}catch(l){}};Runtime.toJson=function(g){return JSON.stringify(g)};Runtime.fromJson=function(g){return JSON.parse(g)};Runtime.getFunctionName=function(g){return void 0===g.name?(g=/function\s+(\w+)/.exec(g))&&g[1]:g.name};
-function BrowserRuntime(g){function l(d,m){var c,e,a;void 0!==m?a=d:m=d;g?(e=g.ownerDocument,a&&(c=e.createElement("span"),c.className=a,c.appendChild(e.createTextNode(a)),g.appendChild(c),g.appendChild(e.createTextNode(" "))),c=e.createElement("span"),0<m.length&&"<"===m[0]?c.innerHTML=m:c.appendChild(e.createTextNode(m)),g.appendChild(c),g.appendChild(e.createElement("br"))):console&&console.log(m);"alert"===a&&alert(m)}function f(d,m,c){if(0!==c.status||c.responseText)if(200===c.status||0===c.status){if(c.response&&
-"string"!==typeof c.response)"binary"===m?(m=c.response,m=new Uint8Array(m)):m=String(c.response);else if("binary"===m)if(null!==c.responseBody&&"undefined"!==String(typeof VBArray)){m=(new VBArray(c.responseBody)).toArray();c=m.length;var e,a=new Uint8Array(new ArrayBuffer(c));for(e=0;e<c;e+=1)a[e]=m[e];m=a}else m=n.byteArrayFromString(c.responseText,"binary");else m=c.responseText;h[d]=m;d={err:null,data:m}}else d={err:c.responseText||c.statusText,data:null};else d={err:"File "+d+" is empty.",data:null};
-return d}function p(d,m,c){var e=new XMLHttpRequest;e.open("GET",d,c);e.overrideMimeType&&("binary"!==m?e.overrideMimeType("text/plain; charset="+m):e.overrideMimeType("text/plain; charset=x-user-defined"));return e}function r(d,m,c){function e(){var b;4===a.readyState&&(b=f(d,m,a),c(b.err,b.data))}if(h.hasOwnProperty(d))c(null,h[d]);else{var a=p(d,m,!0);a.onreadystatechange=e;try{a.send(null)}catch(b){c(b.message,null)}}}var n=this,h={};this.byteArrayFromString=function(d,m){var c;if("utf8"===m){c=
-d.length;var e,a,b,q=0;for(a=0;a<c;a+=1)b=d.charCodeAt(a),q+=1+(128<b)+(2048<b);e=new Uint8Array(new ArrayBuffer(q));for(a=q=0;a<c;a+=1)b=d.charCodeAt(a),128>b?(e[q]=b,q+=1):2048>b?(e[q]=192|b>>>6,e[q+1]=128|b&63,q+=2):(e[q]=224|b>>>12&15,e[q+1]=128|b>>>6&63,e[q+2]=128|b&63,q+=3)}else for("binary"!==m&&n.log("unknown encoding: "+m),c=d.length,e=new Uint8Array(new ArrayBuffer(c)),a=0;a<c;a+=1)e[a]=d.charCodeAt(a)&255;return c=e};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;
-this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=r;this.read=function(d,m,c,e){r(d,"binary",function(a,b){var q=null;if(b){if("string"===typeof b)throw"This should not happen.";q=b.subarray(m,m+c)}e(a,q)})};this.readFileSync=function(d,m){var c=p(d,m,!1),e;try{c.send(null);e=f(d,m,c);if(e.err)throw e.err;if(null===e.data)throw"No data read from "+d+".";}catch(a){throw a;}return e.data};this.writeFile=function(d,m,c){h[d]=m;var e=new XMLHttpRequest,a;e.open("PUT",d,!0);e.onreadystatechange=
-function(){4===e.readyState&&(0!==e.status||e.responseText?200<=e.status&&300>e.status||0===e.status?c(null):c("Status "+String(e.status)+": "+e.responseText||e.statusText):c("File "+d+" is empty."))};a=m.buffer&&!e.sendAsBinary?m.buffer:n.byteArrayToString(m,"binary");try{e.sendAsBinary?e.sendAsBinary(a):e.send(a)}catch(b){n.log("HUH? "+b+" "+m),c(b.message)}};this.deleteFile=function(d,m){delete h[d];var c=new XMLHttpRequest;c.open("DELETE",d,!0);c.onreadystatechange=function(){4===c.readyState&&
-(200>c.status&&300<=c.status?m(c.responseText):m(null))};c.send(null)};this.loadXML=function(d,m){var c=new XMLHttpRequest;c.open("GET",d,!0);c.overrideMimeType&&c.overrideMimeType("text/xml");c.onreadystatechange=function(){4===c.readyState&&(0!==c.status||c.responseText?200===c.status||0===c.status?m(null,c.responseXML):m(c.responseText,null):m("File "+d+" is empty.",null))};try{c.send(null)}catch(e){m(e.message,null)}};this.isFile=function(d,m){n.getFileSize(d,function(c){m(-1!==c)})};this.getFileSize=
-function(d,m){if(h.hasOwnProperty(d)&&"string"!==typeof h[d])m(h[d].length);else{var c=new XMLHttpRequest;c.open("HEAD",d,!0);c.onreadystatechange=function(){if(4===c.readyState){var e=c.getResponseHeader("Content-Length");e?m(parseInt(e,10)):r(d,"binary",function(a,b){a?m(-1):m(b.length)})}};c.send(null)}};this.log=l;this.assert=function(d,m,c){if(!d)throw l("alert","ASSERTION FAILED:\n"+m),c&&c(),m;};this.setTimeout=function(d,m){return setTimeout(function(){d()},m)};this.clearTimeout=function(d){clearTimeout(d)};
-this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.currentDirectory=function(){return""};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML=function(d){return(new DOMParser).parseFromString(d,"text/xml")};this.exit=function(d){l("Calling exit with code "+String(d)+", but exit() is not implemented.")};this.getWindow=function(){return window}}
-function NodeJSRuntime(){function g(d){var c=d.length,e,a=new Uint8Array(new ArrayBuffer(c));for(e=0;e<c;e+=1)a[e]=d[e];return a}function l(d,c,e){function a(a,c){if(a)return e(a,null);if(!c)return e("No data for "+d+".",null);if("string"===typeof c)return e(a,c);e(a,g(c))}d=r.resolve(n,d);"binary"!==c?p.readFile(d,c,a):p.readFile(d,null,a)}var f=this,p=require("fs"),r=require("path"),n="",h,d;this.byteArrayFromString=function(d,c){var e=new Buffer(d,c),a,b=e.length,q=new Uint8Array(new ArrayBuffer(b));
-for(a=0;a<b;a+=1)q[a]=e[a];return q};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=l;this.loadXML=function(d,c){l(d,"utf-8",function(e,a){if(e)return c(e,null);if(!a)return c("No data for "+d+".",null);c(null,f.parseXML(a))})};this.writeFile=function(d,c,e){c=new Buffer(c);d=r.resolve(n,d);p.writeFile(d,c,"binary",function(a){e(a||null)})};this.deleteFile=function(d,c){d=r.resolve(n,d);
-p.unlink(d,c)};this.read=function(d,c,e,a){d=r.resolve(n,d);p.open(d,"r+",666,function(b,q){if(b)a(b,null);else{var k=new Buffer(e);p.read(q,k,0,e,c,function(b){p.close(q);a(b,g(k))})}})};this.readFileSync=function(d,c){var e;e=p.readFileSync(d,"binary"===c?null:c);if(null===e)throw"File "+d+" could not be read.";"binary"===c&&(e=g(e));return e};this.isFile=function(d,c){d=r.resolve(n,d);p.stat(d,function(e,a){c(!e&&a.isFile())})};this.getFileSize=function(d,c){d=r.resolve(n,d);p.stat(d,function(e,
-a){e?c(-1):c(a.size)})};this.log=function(d,c){var e;void 0!==c?e=d:c=d;"alert"===e&&process.stderr.write("\n!!!!! ALERT !!!!!\n");process.stderr.write(c+"\n");"alert"===e&&process.stderr.write("!!!!! ALERT !!!!!\n")};this.assert=function(d,c,e){d||(process.stderr.write("ASSERTION FAILED: "+c),e&&e())};this.setTimeout=function(d,c){return setTimeout(function(){d()},c)};this.clearTimeout=function(d){clearTimeout(d)};this.libraryPaths=function(){return[__dirname]};this.setCurrentDirectory=function(d){n=
-d};this.currentDirectory=function(){return n};this.type=function(){return"NodeJSRuntime"};this.getDOMImplementation=function(){return d};this.parseXML=function(d){return h.parseFromString(d,"text/xml")};this.exit=process.exit;this.getWindow=function(){return null};h=new (require("xmldom").DOMParser);d=f.parseXML("<a/>").implementation}
-function RhinoRuntime(){function g(d,h){var c;void 0!==h?c=d:h=d;"alert"===c&&print("\n!!!!! ALERT !!!!!");print(h);"alert"===c&&print("!!!!! ALERT !!!!!")}var l=this,f={},p=f.javax.xml.parsers.DocumentBuilderFactory.newInstance(),r,n,h="";p.setValidating(!1);p.setNamespaceAware(!0);p.setExpandEntityReferences(!1);p.setSchema(null);n=f.org.xml.sax.EntityResolver({resolveEntity:function(d,h){var c=new f.java.io.FileReader(h);return new f.org.xml.sax.InputSource(c)}});r=p.newDocumentBuilder();r.setEntityResolver(n);
-this.byteArrayFromString=function(d,h){var c,e=d.length,a=new Uint8Array(new ArrayBuffer(e));for(c=0;c<e;c+=1)a[c]=d.charCodeAt(c)&255;return a};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.loadXML=function(d,h){var c=new f.java.io.File(d),e=null;try{e=r.parse(c)}catch(a){return print(a),h(a,null)}h(null,e)};this.readFile=function(d,m,c){h&&(d=h+"/"+d);var e=new f.java.io.File(d),a="binary"===m?
-"latin1":m;e.isFile()?((d=readFile(d,a))&&"binary"===m&&(d=l.byteArrayFromString(d,"binary")),c(null,d)):c(d+" is not a file.",null)};this.writeFile=function(d,m,c){h&&(d=h+"/"+d);d=new f.java.io.FileOutputStream(d);var e,a=m.length;for(e=0;e<a;e+=1)d.write(m[e]);d.close();c(null)};this.deleteFile=function(d,m){h&&(d=h+"/"+d);var c=new f.java.io.File(d),e=d+Math.random(),e=new f.java.io.File(e);c.rename(e)?(e.deleteOnExit(),m(null)):m("Could not delete "+d)};this.read=function(d,m,c,e){h&&(d=h+"/"+
-d);var a;a=d;var b="binary";(new f.java.io.File(a)).isFile()?("binary"===b&&(b="latin1"),a=readFile(a,b)):a=null;a?e(null,this.byteArrayFromString(a.substring(m,m+c),"binary")):e("Cannot read "+d,null)};this.readFileSync=function(d,h){if(!h)return"";var c=readFile(d,h);if(null===c)throw"File could not be read.";return c};this.isFile=function(d,m){h&&(d=h+"/"+d);var c=new f.java.io.File(d);m(c.isFile())};this.getFileSize=function(d,m){h&&(d=h+"/"+d);var c=new f.java.io.File(d);m(c.length())};this.log=
-g;this.assert=function(d,h,c){d||(g("alert","ASSERTION FAILED: "+h),c&&c())};this.setTimeout=function(d){d();return 0};this.clearTimeout=function(){};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(d){h=d};this.currentDirectory=function(){return h};this.type=function(){return"RhinoRuntime"};this.getDOMImplementation=function(){return r.getDOMImplementation()};this.parseXML=function(d){d=new f.java.io.StringReader(d);d=new f.org.xml.sax.InputSource(d);return r.parse(d)};
-this.exit=quit;this.getWindow=function(){return null}}Runtime.create=function(){return"undefined"!==String(typeof window)?new BrowserRuntime(window.document.getElementById("logoutput")):"undefined"!==String(typeof require)?new NodeJSRuntime:new RhinoRuntime};var runtime=Runtime.create(),core={},gui={},xmldom={},odf={},ops={};
-(function(){function g(h,d){var f=h+"/manifest.json",c,e;if(!n.hasOwnProperty(f)){n[f]=1;try{c=runtime.readFileSync(f,"utf-8")}catch(a){console.log(String(a));return}f=JSON.parse(c);for(e in f)f.hasOwnProperty(e)&&(d[e]={dir:h,deps:f[e]})}}function l(h,d,f){var c=d[h].deps,e={};f[h]=e;c.forEach(function(a){e[a]=1});c.forEach(function(a){f[a]||l(a,d,f)});c.forEach(function(a){Object.keys(f[a]).forEach(function(a){e[a]=1})})}function f(h,d){function f(a,b){var c,k=d[a];if(-1===e.indexOf(a)&&-1===b.indexOf(a)){b.push(a);
-for(c=0;c<h.length;c+=1)k[h[c]]&&f(h[c],b);b.pop();e.push(a)}}var c,e=[];for(c=0;c<h.length;c+=1)f(h[c],[]);return e}function p(h,d){for(var f=0;f<h.length&&void 0!==d[f];)null!==d[f]&&(eval(d[f]),d[f]=null),f+=1}var r={},n={};runtime.loadClass=function(h){if(!IS_COMPILED_CODE){var d=h.replace(".","/")+".js";if(!n.hasOwnProperty(d)){if(!(0<Object.keys(r).length)){var m=runtime.libraryPaths(),d={},c;runtime.currentDirectory()&&g(runtime.currentDirectory(),d);for(c=0;c<m.length;c+=1)g(m[c],d);var e;
-c={};for(e in d)d.hasOwnProperty(e)&&l(e,d,c);for(e in d)d.hasOwnProperty(e)&&(m=Object.keys(c[e]),d[e].deps=f(m,c),d[e].deps.push(e));r=d}e=h.replace(".","/")+".js";h=[];e=r[e].deps;for(d=0;d<e.length;d+=1)n.hasOwnProperty(e[d])||h.push(e[d]);e=[];e.length=h.length;for(d=h.length-1;0<=d;d-=1)n[h[d]]=1,void 0===e[d]&&(m=h[d],m=r[m].dir+"/"+m,c=runtime.readFileSync(m,"utf-8"),c+="\n//# sourceURL="+m,c+="\n//@ sourceURL="+m,e[d]=c);p(h,e)}}}})();
-(function(){var g=function(g){return g};runtime.getTranslator=function(){return g};runtime.setTranslator=function(l){g=l};runtime.tr=function(l){var f=g(l);return f&&"string"===String(typeof f)?f:l}})();
-(function(g){function l(f){if(f.length){var g=f[0];runtime.readFile(g,"utf8",function(l,n){function h(){var c;(c=eval(m))&&runtime.exit(c)}var d="",m=n;-1!==g.indexOf("/")&&(d=g.substring(0,g.indexOf("/")));runtime.setCurrentDirectory(d);l?(runtime.log(l),runtime.exit(1)):null===m?(runtime.log("No code found for "+g),runtime.exit(1)):h.apply(null,f)})}}g=g?Array.prototype.slice.call(g):[];"NodeJSRuntime"===runtime.type()?l(process.argv.slice(2)):"RhinoRuntime"===runtime.type()?l(g):l(g.slice(1))})("undefined"!==
+function Runtime(){}Runtime.prototype.getVariable=function(k){};Runtime.prototype.toJson=function(k){};Runtime.prototype.fromJson=function(k){};Runtime.prototype.byteArrayFromString=function(k,h){};Runtime.prototype.byteArrayToString=function(k,h){};Runtime.prototype.read=function(k,h,b,p){};Runtime.prototype.readFile=function(k,h,b){};Runtime.prototype.readFileSync=function(k,h){};Runtime.prototype.loadXML=function(k,h){};Runtime.prototype.writeFile=function(k,h,b){};
+Runtime.prototype.isFile=function(k,h){};Runtime.prototype.getFileSize=function(k,h){};Runtime.prototype.deleteFile=function(k,h){};Runtime.prototype.log=function(k,h){};Runtime.prototype.setTimeout=function(k,h){};Runtime.prototype.clearTimeout=function(k){};Runtime.prototype.libraryPaths=function(){};Runtime.prototype.currentDirectory=function(){};Runtime.prototype.setCurrentDirectory=function(k){};Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};
+Runtime.prototype.parseXML=function(k){};Runtime.prototype.exit=function(k){};Runtime.prototype.getWindow=function(){};Runtime.prototype.requestAnimationFrame=function(k){};Runtime.prototype.cancelAnimationFrame=function(k){};Runtime.prototype.assert=function(k,h,b){};var IS_COMPILED_CODE=!0;
+Runtime.byteArrayToString=function(k,h){function b(b){var g="",q,d=b.length;for(q=0;q<d;q+=1)g+=String.fromCharCode(b[q]&255);return g}function p(b){var g="",q,d=b.length,l=[],f,c,a,m;for(q=0;q<d;q+=1)f=b[q],128>f?l.push(f):(q+=1,c=b[q],194<=f&&224>f?l.push((f&31)<<6|c&63):(q+=1,a=b[q],224<=f&&240>f?l.push((f&15)<<12|(c&63)<<6|a&63):(q+=1,m=b[q],240<=f&&245>f&&(f=(f&7)<<18|(c&63)<<12|(a&63)<<6|m&63,f-=65536,l.push((f>>10)+55296,(f&1023)+56320))))),1E3===l.length&&(g+=String.fromCharCode.apply(null,
+l),l.length=0);return g+String.fromCharCode.apply(null,l)}var d;"utf8"===h?d=p(k):("binary"!==h&&this.log("Unsupported encoding: "+h),d=b(k));return d};Runtime.getVariable=function(k){try{return eval(k)}catch(h){}};Runtime.toJson=function(k){return JSON.stringify(k)};Runtime.fromJson=function(k){return JSON.parse(k)};Runtime.getFunctionName=function(k){return void 0===k.name?(k=/function\s+(\w+)/.exec(k))&&k[1]:k.name};
+function BrowserRuntime(k){function h(f){var c=f.length,a,m,e=0;for(a=0;a<c;a+=1)m=f.charCodeAt(a),e+=1+(128<m)+(2048<m),55040<m&&57344>m&&(e+=1,a+=1);return e}function b(f,c,a){var m=f.length,e,b;c=new Uint8Array(new ArrayBuffer(c));a?(c[0]=239,c[1]=187,c[2]=191,b=3):b=0;for(a=0;a<m;a+=1)e=f.charCodeAt(a),128>e?(c[b]=e,b+=1):2048>e?(c[b]=192|e>>>6,c[b+1]=128|e&63,b+=2):55040>=e||57344<=e?(c[b]=224|e>>>12&15,c[b+1]=128|e>>>6&63,c[b+2]=128|e&63,b+=3):(a+=1,e=(e-55296<<10|f.charCodeAt(a)-56320)+65536,
+c[b]=240|e>>>18&7,c[b+1]=128|e>>>12&63,c[b+2]=128|e>>>6&63,c[b+3]=128|e&63,b+=4);return c}function p(f){var c=f.length,a=new Uint8Array(new ArrayBuffer(c)),m;for(m=0;m<c;m+=1)a[m]=f.charCodeAt(m)&255;return a}function d(f,c){var a,m,e;void 0!==c?e=f:c=f;k?(m=k.ownerDocument,e&&(a=m.createElement("span"),a.className=e,a.appendChild(m.createTextNode(e)),k.appendChild(a),k.appendChild(m.createTextNode(" "))),a=m.createElement("span"),0<c.length&&"<"===c[0]?a.innerHTML=c:a.appendChild(m.createTextNode(c)),
+k.appendChild(a),k.appendChild(m.createElement("br"))):console&&console.log(c);"alert"===e&&alert(c)}function n(f,c,a){if(0!==a.status||a.responseText)if(200===a.status||0===a.status){if(a.response&&"string"!==typeof a.response)"binary"===c?(a=a.response,a=new Uint8Array(a)):a=String(a.response);else if("binary"===c)if(null!==a.responseBody&&"undefined"!==String(typeof VBArray)){a=(new VBArray(a.responseBody)).toArray();var m=a.length,e=new Uint8Array(new ArrayBuffer(m));for(c=0;c<m;c+=1)e[c]=a[c];
+a=e}else{(c=a.getResponseHeader("Content-Length"))&&(c=parseInt(c,10));if(c&&c!==a.responseText.length)a:{var m=a.responseText,e=!1,q=h(m);if("number"===typeof c){if(c!==q&&c!==q+3){m=void 0;break a}e=q+3===c;q=c}m=b(m,q,e)}void 0===m&&(m=p(a.responseText));a=m}else a=a.responseText;l[f]=a;f={err:null,data:a}}else f={err:a.responseText||a.statusText,data:null};else f={err:"File "+f+" is empty.",data:null};return f}function g(f,c,a){var m=new XMLHttpRequest;m.open("GET",f,a);m.overrideMimeType&&("binary"!==
+c?m.overrideMimeType("text/plain; charset="+c):m.overrideMimeType("text/plain; charset=x-user-defined"));return m}function q(f,c,a){function m(){var m;4===e.readyState&&(m=n(f,c,e),a(m.err,m.data))}if(l.hasOwnProperty(f))a(null,l[f]);else{var e=g(f,c,!0);e.onreadystatechange=m;try{e.send(null)}catch(b){a(b.message,null)}}}var r=this,l={};this.byteArrayFromString=function(f,c){var a;"utf8"===c?a=b(f,h(f),!1):("binary"!==c&&r.log("unknown encoding: "+c),a=p(f));return a};this.byteArrayToString=Runtime.byteArrayToString;
+this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=q;this.read=function(f,c,a,m){q(f,"binary",function(e,f){var b=null;if(f){if("string"===typeof f)throw"This should not happen.";b=f.subarray(c,c+a)}m(e,b)})};this.readFileSync=function(f,c){var a=g(f,c,!1),m;try{a.send(null);m=n(f,c,a);if(m.err)throw m.err;if(null===m.data)throw"No data read from "+f+".";}catch(e){throw e;}return m.data};this.writeFile=function(f,c,a){l[f]=c;var m=new XMLHttpRequest,
+e;m.open("PUT",f,!0);m.onreadystatechange=function(){4===m.readyState&&(0!==m.status||m.responseText?200<=m.status&&300>m.status||0===m.status?a(null):a("Status "+String(m.status)+": "+m.responseText||m.statusText):a("File "+f+" is empty."))};e=c.buffer&&!m.sendAsBinary?c.buffer:r.byteArrayToString(c,"binary");try{m.sendAsBinary?m.sendAsBinary(e):m.send(e)}catch(b){r.log("HUH? "+b+" "+c),a(b.message)}};this.deleteFile=function(f,c){delete l[f];var a=new XMLHttpRequest;a.open("DELETE",f,!0);a.onreadystatechange=
+function(){4===a.readyState&&(200>a.status&&300<=a.status?c(a.responseText):c(null))};a.send(null)};this.loadXML=function(f,c){var a=new XMLHttpRequest;a.open("GET",f,!0);a.overrideMimeType&&a.overrideMimeType("text/xml");a.onreadystatechange=function(){4===a.readyState&&(0!==a.status||a.responseText?200===a.status||0===a.status?c(null,a.responseXML):c(a.responseText,null):c("File "+f+" is empty.",null))};try{a.send(null)}catch(m){c(m.message,null)}};this.isFile=function(f,c){r.getFileSize(f,function(a){c(-1!==
+a)})};this.getFileSize=function(f,c){if(l.hasOwnProperty(f)&&"string"!==typeof l[f])c(l[f].length);else{var a=new XMLHttpRequest;a.open("HEAD",f,!0);a.onreadystatechange=function(){if(4===a.readyState){var m=a.getResponseHeader("Content-Length");m?c(parseInt(m,10)):q(f,"binary",function(a,f){a?c(-1):c(f.length)})}};a.send(null)}};this.log=d;this.assert=function(f,c,a){if(!f)throw d("alert","ASSERTION FAILED:\n"+c),a&&a(),c;};this.setTimeout=function(f,c){return setTimeout(function(){f()},c)};this.clearTimeout=
+function(f){clearTimeout(f)};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.currentDirectory=function(){return""};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML=function(f){return(new DOMParser).parseFromString(f,"text/xml")};this.exit=function(f){d("Calling exit with code "+String(f)+", but exit() is not implemented.")};this.getWindow=function(){return window};this.requestAnimationFrame=
+function(f){var c=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,a=0;if(c)c.bind(window),a=c(f);else return setTimeout(f,15);return a};this.cancelAnimationFrame=function(f){var c=window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.msCancelAnimationFrame;c?(c.bind(window),c(f)):clearTimeout(f)}}
+function NodeJSRuntime(){function k(b){var l=b.length,f,c=new Uint8Array(new ArrayBuffer(l));for(f=0;f<l;f+=1)c[f]=b[f];return c}function h(b,l,f){function c(a,c){if(a)return f(a,null);if(!c)return f("No data for "+b+".",null);if("string"===typeof c)return f(a,c);f(a,k(c))}b=d.resolve(n,b);"binary"!==l?p.readFile(b,l,c):p.readFile(b,null,c)}var b=this,p=require("fs"),d=require("path"),n="",g,q;this.byteArrayFromString=function(b,l){var f=new Buffer(b,l),c,a=f.length,m=new Uint8Array(new ArrayBuffer(a));
+for(c=0;c<a;c+=1)m[c]=f[c];return m};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=h;this.loadXML=function(q,l){h(q,"utf-8",function(f,c){if(f)return l(f,null);if(!c)return l("No data for "+q+".",null);l(null,b.parseXML(c))})};this.writeFile=function(b,l,f){l=new Buffer(l);b=d.resolve(n,b);p.writeFile(b,l,"binary",function(c){f(c||null)})};this.deleteFile=function(b,l){b=d.resolve(n,b);
+p.unlink(b,l)};this.read=function(b,l,f,c){b=d.resolve(n,b);p.open(b,"r+",666,function(a,m){if(a)c(a,null);else{var e=new Buffer(f);p.read(m,e,0,f,l,function(a){p.close(m);c(a,k(e))})}})};this.readFileSync=function(b,l){var f;f=p.readFileSync(b,"binary"===l?null:l);if(null===f)throw"File "+b+" could not be read.";"binary"===l&&(f=k(f));return f};this.isFile=function(b,l){b=d.resolve(n,b);p.stat(b,function(f,c){l(!f&&c.isFile())})};this.getFileSize=function(b,l){b=d.resolve(n,b);p.stat(b,function(f,
+c){f?l(-1):l(c.size)})};this.log=function(b,l){var f;void 0!==l?f=b:l=b;"alert"===f&&process.stderr.write("\n!!!!! ALERT !!!!!\n");process.stderr.write(l+"\n");"alert"===f&&process.stderr.write("!!!!! ALERT !!!!!\n")};this.assert=function(b,l,f){b||(process.stderr.write("ASSERTION FAILED: "+l),f&&f())};this.setTimeout=function(b,l){return setTimeout(function(){b()},l)};this.clearTimeout=function(b){clearTimeout(b)};this.libraryPaths=function(){return[__dirname]};this.setCurrentDirectory=function(b){n=
+b};this.currentDirectory=function(){return n};this.type=function(){return"NodeJSRuntime"};this.getDOMImplementation=function(){return q};this.parseXML=function(b){return g.parseFromString(b,"text/xml")};this.exit=process.exit;this.getWindow=function(){return null};this.requestAnimationFrame=function(b){return setTimeout(b,15)};this.cancelAnimationFrame=function(b){clearTimeout(b)};g=new (require("xmldom").DOMParser);q=b.parseXML("<a/>").implementation}
+function RhinoRuntime(){function k(b,g){var l;void 0!==g?l=b:g=b;"alert"===l&&print("\n!!!!! ALERT !!!!!");print(g);"alert"===l&&print("!!!!! ALERT !!!!!")}var h=this,b={},p=b.javax.xml.parsers.DocumentBuilderFactory.newInstance(),d,n,g="";p.setValidating(!1);p.setNamespaceAware(!0);p.setExpandEntityReferences(!1);p.setSchema(null);n=b.org.xml.sax.EntityResolver({resolveEntity:function(q,g){var l=new b.java.io.FileReader(g);return new b.org.xml.sax.InputSource(l)}});d=p.newDocumentBuilder();d.setEntityResolver(n);
+this.byteArrayFromString=function(b,g){var l,f=b.length,c=new Uint8Array(new ArrayBuffer(f));for(l=0;l<f;l+=1)c[l]=b.charCodeAt(l)&255;return c};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.loadXML=function(q,g){var l=new b.java.io.File(q),f=null;try{f=d.parse(l)}catch(c){return print(c),g(c,null)}g(null,f)};this.readFile=function(q,d,l){g&&(q=g+"/"+q);var f=new b.java.io.File(q),c="binary"===d?
+"latin1":d;f.isFile()?((q=readFile(q,c))&&"binary"===d&&(q=h.byteArrayFromString(q,"binary")),l(null,q)):l(q+" is not a file.",null)};this.writeFile=function(q,d,l){g&&(q=g+"/"+q);q=new b.java.io.FileOutputStream(q);var f,c=d.length;for(f=0;f<c;f+=1)q.write(d[f]);q.close();l(null)};this.deleteFile=function(q,d){g&&(q=g+"/"+q);var l=new b.java.io.File(q),f=q+Math.random(),f=new b.java.io.File(f);l.rename(f)?(f.deleteOnExit(),d(null)):d("Could not delete "+q)};this.read=function(q,d,l,f){g&&(q=g+"/"+
+q);var c;c=q;var a="binary";(new b.java.io.File(c)).isFile()?("binary"===a&&(a="latin1"),c=readFile(c,a)):c=null;c?f(null,this.byteArrayFromString(c.substring(d,d+l),"binary")):f("Cannot read "+q,null)};this.readFileSync=function(b,d){if(!d)return"";var l=readFile(b,d);if(null===l)throw"File could not be read.";return l};this.isFile=function(d,h){g&&(d=g+"/"+d);var l=new b.java.io.File(d);h(l.isFile())};this.getFileSize=function(d,h){g&&(d=g+"/"+d);var l=new b.java.io.File(d);h(l.length())};this.log=
+k;this.assert=function(b,d,l){b||(k("alert","ASSERTION FAILED: "+d),l&&l())};this.setTimeout=function(b){b();return 0};this.clearTimeout=function(){};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(b){g=b};this.currentDirectory=function(){return g};this.type=function(){return"RhinoRuntime"};this.getDOMImplementation=function(){return d.getDOMImplementation()};this.parseXML=function(g){g=new b.java.io.StringReader(g);g=new b.org.xml.sax.InputSource(g);return d.parse(g)};
+this.exit=quit;this.getWindow=function(){return null};this.requestAnimationFrame=function(b){b();return 0};this.cancelAnimationFrame=function(){}}Runtime.create=function(){return"undefined"!==String(typeof window)?new BrowserRuntime(window.document.getElementById("logoutput")):"undefined"!==String(typeof require)?new NodeJSRuntime:new RhinoRuntime};var runtime=Runtime.create(),core={},gui={},xmldom={},odf={},ops={};
+(function(){function k(b,d,l){var f=b+"/manifest.json",c,a;runtime.log("Loading manifest: "+f);try{c=runtime.readFileSync(f,"utf-8")}catch(m){if(l)runtime.log("No loadable manifest found.");else throw console.log(String(m)),m;return}l=JSON.parse(c);for(a in l)l.hasOwnProperty(a)&&(d[a]={dir:b,deps:l[a]})}function h(b,d,l){function f(e){if(!m[e]&&!l(e)){if(a[e])throw"Circular dependency detected for "+e+".";a[e]=!0;if(!d[e])throw"Missing dependency information for class "+e+".";var b=d[e],g=b.deps,
+h,q=g.length;for(h=0;h<q;h+=1)f(g[h]);a[e]=!1;m[e]=!0;c.push(b.dir+"/"+e.replace(".","/")+".js")}}var c=[],a={},m={};b.forEach(f);return c}function b(b,d){return d=d+("\n//# sourceURL="+b)+("\n//@ sourceURL="+b)}function p(d){var g,l;for(g=0;g<d.length;g+=1)l=runtime.readFileSync(d[g],"utf-8"),l=b(d[g],l),eval(l)}function d(b){b=b.split(".");var d,l=g,f=b.length;for(d=0;d<f;d+=1){if(!l.hasOwnProperty(b[d]))return!1;l=l[b[d]]}return!0}var n,g={core:core,gui:gui,xmldom:xmldom,odf:odf,ops:ops};runtime.loadClasses=
+function(b,g){if(IS_COMPILED_CODE||0===b.length)return g&&g();var l;if(!(l=n)){l=[];var f=runtime.libraryPaths(),c;runtime.currentDirectory()&&-1===f.indexOf(runtime.currentDirectory())&&k(runtime.currentDirectory(),l,!0);for(c=0;c<f.length;c+=1)k(f[c],l)}n=l;b=h(b,n,d);if(0===b.length)return g&&g();if("BrowserRuntime"===runtime.type()&&g){l=b;f=document.currentScript||document.documentElement.lastChild;c=document.createDocumentFragment();var a,m;for(m=0;m<l.length;m+=1)a=document.createElement("script"),
+a.type="text/javascript",a.charset="utf-8",a.async=!1,a.setAttribute("src",l[m]),c.appendChild(a);g&&(a.onload=g);f.parentNode.insertBefore(c,f)}else p(b),g&&g()};runtime.loadClass=function(b,d){runtime.loadClasses([b],d)}})();(function(){var k=function(h){return h};runtime.getTranslator=function(){return k};runtime.setTranslator=function(h){k=h};runtime.tr=function(h){var b=k(h);return b&&"string"===String(typeof b)?b:h}})();
+(function(k){function h(b){if(b.length){var h=b[0];runtime.readFile(h,"utf8",function(d,n){function g(){var b;(b=eval(k))&&runtime.exit(b)}var q="",q=h.lastIndexOf("/"),k=n,q=-1!==q?h.substring(0,q):".";runtime.setCurrentDirectory(q);d?(runtime.log(d),runtime.exit(1)):null===k?(runtime.log("No code found for "+h),runtime.exit(1)):g.apply(null,b)})}}k=k?Array.prototype.slice.call(k):[];"NodeJSRuntime"===runtime.type()?h(process.argv.slice(2)):"RhinoRuntime"===runtime.type()?h(k):h(k.slice(1))})("undefined"!==
String(typeof arguments)&&arguments);
// Input 2
-core.Async=function(){this.forEach=function(g,l,f){function p(d){h!==n&&(d?(h=n,f(d)):(h+=1,h===n&&f(null)))}var r,n=g.length,h=0;for(r=0;r<n;r+=1)l(g[r],p)};this.destroyAll=function(g,l){function f(p,r){if(r)l(r);else if(p<g.length)g[p](function(g){f(p+1,g)});else l()}f(0,void 0)}};
+core.Async=function(){this.forEach=function(k,h,b){function p(d){g!==n&&(d?(g=n,b(d)):(g+=1,g===n&&b(null)))}var d,n=k.length,g=0;for(d=0;d<n;d+=1)h(k[d],p)};this.destroyAll=function(k,h){function b(p,d){if(d)h(d);else if(p<k.length)k[p](function(d){b(p+1,d)});else h()}b(0,void 0)}};
// Input 3
-function makeBase64(){function g(a){var b,c=a.length,e=new Uint8Array(new ArrayBuffer(c));for(b=0;b<c;b+=1)e[b]=a.charCodeAt(b)&255;return e}function l(a){var b,c="",e,q=a.length-2;for(e=0;e<q;e+=3)b=a[e]<<16|a[e+1]<<8|a[e+2],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>18],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>12&63],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6&63],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b&
-63];e===q+1?(b=a[e]<<4,c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b&63],c+="=="):e===q&&(b=a[e]<<10|a[e+1]<<2,c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>12],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6&63],c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b&63],c+="=");return c}function f(a){a=a.replace(/[^A-Za-z0-9+\/]+/g,
-"");var b=a.length,c=new Uint8Array(new ArrayBuffer(3*b)),e=a.length%4,q=0,d,f;for(d=0;d<b;d+=4)f=(k[a.charAt(d)]||0)<<18|(k[a.charAt(d+1)]||0)<<12|(k[a.charAt(d+2)]||0)<<6|(k[a.charAt(d+3)]||0),c[q]=f>>16,c[q+1]=f>>8&255,c[q+2]=f&255,q+=3;b=3*b-[0,0,2,1][e];return c.subarray(0,b)}function p(a){var b,c,e=a.length,q=0,k=new Uint8Array(new ArrayBuffer(3*e));for(b=0;b<e;b+=1)c=a[b],128>c?k[q++]=c:(2048>c?k[q++]=192|c>>>6:(k[q++]=224|c>>>12&15,k[q++]=128|c>>>6&63),k[q++]=128|c&63);return k.subarray(0,
-q)}function r(a){var b,c,e,q,k=a.length,d=new Uint8Array(new ArrayBuffer(k)),f=0;for(b=0;b<k;b+=1)c=a[b],128>c?d[f++]=c:(b+=1,e=a[b],224>c?d[f++]=(c&31)<<6|e&63:(b+=1,q=a[b],d[f++]=(c&15)<<12|(e&63)<<6|q&63));return d.subarray(0,f)}function n(a){return l(g(a))}function h(a){return String.fromCharCode.apply(String,f(a))}function d(a){return r(g(a))}function m(a){a=r(a);for(var b="",c=0;c<a.length;)b+=String.fromCharCode.apply(String,a.subarray(c,c+45E3)),c+=45E3;return b}function c(a,b,c){var e,q,
-k,d="";for(k=b;k<c;k+=1)b=a.charCodeAt(k)&255,128>b?d+=String.fromCharCode(b):(k+=1,e=a.charCodeAt(k)&255,224>b?d+=String.fromCharCode((b&31)<<6|e&63):(k+=1,q=a.charCodeAt(k)&255,d+=String.fromCharCode((b&15)<<12|(e&63)<<6|q&63)));return d}function e(a,b){function e(){var d=k+1E5;d>a.length&&(d=a.length);q+=c(a,k,d);k=d;d=k===a.length;b(q,d)&&!d&&runtime.setTimeout(e,0)}var q="",k=0;1E5>a.length?b(c(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),e())}function a(a){return p(g(a))}function b(a){return String.fromCharCode.apply(String,
-p(a))}function q(a){return String.fromCharCode.apply(String,p(g(a)))}var k=function(a){var b={},c,e;c=0;for(e=a.length;c<e;c+=1)b[a.charAt(c)]=c;return b}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),t,A,w=runtime.getWindow(),x,v;w&&w.btoa?(x=w.btoa,t=function(a){return x(q(a))}):(x=n,t=function(b){return l(a(b))});w&&w.atob?(v=w.atob,A=function(a){a=v(a);return c(a,0,a.length)}):(v=h,A=function(a){return m(f(a))});core.Base64=function(){this.convertByteArrayToBase64=this.convertUTF8ArrayToBase64=
-l;this.convertBase64ToByteArray=this.convertBase64ToUTF8Array=f;this.convertUTF16ArrayToByteArray=this.convertUTF16ArrayToUTF8Array=p;this.convertByteArrayToUTF16Array=this.convertUTF8ArrayToUTF16Array=r;this.convertUTF8StringToBase64=n;this.convertBase64ToUTF8String=h;this.convertUTF8StringToUTF16Array=d;this.convertByteArrayToUTF16String=this.convertUTF8ArrayToUTF16String=m;this.convertUTF8StringToUTF16String=e;this.convertUTF16StringToByteArray=this.convertUTF16StringToUTF8Array=a;this.convertUTF16ArrayToUTF8String=
-b;this.convertUTF16StringToUTF8String=q;this.convertUTF16StringToBase64=t;this.convertBase64ToUTF16String=A;this.fromBase64=h;this.toBase64=n;this.atob=v;this.btoa=x;this.utob=q;this.btou=e;this.encode=t;this.encodeURI=function(a){return t(a).replace(/[+\/]/g,function(a){return"+"===a?"-":"_"}).replace(/\\=+$/,"")};this.decode=function(a){return A(a.replace(/[\-_]/g,function(a){return"-"===a?"+":"/"}))};return this};return core.Base64}core.Base64=makeBase64();
+function makeBase64(){function k(a){var c,e=a.length,f=new Uint8Array(new ArrayBuffer(e));for(c=0;c<e;c+=1)f[c]=a.charCodeAt(c)&255;return f}function h(a){var c,e="",f,b=a.length-2;for(f=0;f<b;f+=3)c=a[f]<<16|a[f+1]<<8|a[f+2],e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>18],e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>12&63],e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6&63],e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c&
+63];f===b+1?(c=a[f]<<4,e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6],e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c&63],e+="=="):f===b&&(c=a[f]<<10|a[f+1]<<2,e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>12],e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6&63],e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c&63],e+="=");return e}function b(a){a=a.replace(/[^A-Za-z0-9+\/]+/g,
+"");var c=a.length,f=new Uint8Array(new ArrayBuffer(3*c)),b=a.length%4,m=0,d,g;for(d=0;d<c;d+=4)g=(e[a.charAt(d)]||0)<<18|(e[a.charAt(d+1)]||0)<<12|(e[a.charAt(d+2)]||0)<<6|(e[a.charAt(d+3)]||0),f[m]=g>>16,f[m+1]=g>>8&255,f[m+2]=g&255,m+=3;c=3*c-[0,0,2,1][b];return f.subarray(0,c)}function p(a){var c,e,f=a.length,b=0,m=new Uint8Array(new ArrayBuffer(3*f));for(c=0;c<f;c+=1)e=a[c],128>e?m[b++]=e:(2048>e?m[b++]=192|e>>>6:(m[b++]=224|e>>>12&15,m[b++]=128|e>>>6&63),m[b++]=128|e&63);return m.subarray(0,
+b)}function d(a){var c,e,f,b,m=a.length,d=new Uint8Array(new ArrayBuffer(m)),g=0;for(c=0;c<m;c+=1)e=a[c],128>e?d[g++]=e:(c+=1,f=a[c],224>e?d[g++]=(e&31)<<6|f&63:(c+=1,b=a[c],d[g++]=(e&15)<<12|(f&63)<<6|b&63));return d.subarray(0,g)}function n(a){return h(k(a))}function g(a){return String.fromCharCode.apply(String,b(a))}function q(a){return d(k(a))}function r(a){a=d(a);for(var c="",e=0;e<a.length;)c+=String.fromCharCode.apply(String,a.subarray(e,e+45E3)),e+=45E3;return c}function l(a,c,e){var f,b,
+m,d="";for(m=c;m<e;m+=1)c=a.charCodeAt(m)&255,128>c?d+=String.fromCharCode(c):(m+=1,f=a.charCodeAt(m)&255,224>c?d+=String.fromCharCode((c&31)<<6|f&63):(m+=1,b=a.charCodeAt(m)&255,d+=String.fromCharCode((c&15)<<12|(f&63)<<6|b&63)));return d}function f(a,c){function e(){var m=b+1E5;m>a.length&&(m=a.length);f+=l(a,b,m);b=m;m=b===a.length;c(f,m)&&!m&&runtime.setTimeout(e,0)}var f="",b=0;1E5>a.length?c(l(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),e())}function c(a){return p(k(a))}function a(a){return String.fromCharCode.apply(String,
+p(a))}function m(a){return String.fromCharCode.apply(String,p(k(a)))}var e=function(a){var c={},e,f;e=0;for(f=a.length;e<f;e+=1)c[a.charAt(e)]=e;return c}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),t,w,z=runtime.getWindow(),x,v;z&&z.btoa?(x=z.btoa,t=function(a){return x(m(a))}):(x=n,t=function(a){return h(c(a))});z&&z.atob?(v=z.atob,w=function(a){a=v(a);return l(a,0,a.length)}):(v=g,w=function(a){return r(b(a))});core.Base64=function(){this.convertByteArrayToBase64=this.convertUTF8ArrayToBase64=
+h;this.convertBase64ToByteArray=this.convertBase64ToUTF8Array=b;this.convertUTF16ArrayToByteArray=this.convertUTF16ArrayToUTF8Array=p;this.convertByteArrayToUTF16Array=this.convertUTF8ArrayToUTF16Array=d;this.convertUTF8StringToBase64=n;this.convertBase64ToUTF8String=g;this.convertUTF8StringToUTF16Array=q;this.convertByteArrayToUTF16String=this.convertUTF8ArrayToUTF16String=r;this.convertUTF8StringToUTF16String=f;this.convertUTF16StringToByteArray=this.convertUTF16StringToUTF8Array=c;this.convertUTF16ArrayToUTF8String=
+a;this.convertUTF16StringToUTF8String=m;this.convertUTF16StringToBase64=t;this.convertBase64ToUTF16String=w;this.fromBase64=g;this.toBase64=n;this.atob=v;this.btoa=x;this.utob=m;this.btou=f;this.encode=t;this.encodeURI=function(a){return t(a).replace(/[+\/]/g,function(a){return"+"===a?"-":"_"}).replace(/\\=+$/,"")};this.decode=function(a){return w(a.replace(/[\-_]/g,function(a){return"-"===a?"+":"/"}))};return this};return core.Base64}core.Base64=makeBase64();
// Input 4
-core.ByteArray=function(g){this.pos=0;this.data=g;this.readUInt32LE=function(){this.pos+=4;var g=this.data,f=this.pos;return g[--f]<<24|g[--f]<<16|g[--f]<<8|g[--f]};this.readUInt16LE=function(){this.pos+=2;var g=this.data,f=this.pos;return g[--f]<<8|g[--f]}};
+core.ByteArray=function(k){this.pos=0;this.data=k;this.readUInt32LE=function(){this.pos+=4;var h=this.data,b=this.pos;return h[--b]<<24|h[--b]<<16|h[--b]<<8|h[--b]};this.readUInt16LE=function(){this.pos+=2;var h=this.data,b=this.pos;return h[--b]<<8|h[--b]}};
// Input 5
-core.ByteArrayWriter=function(g){function l(f){f>r-p&&(r=Math.max(2*r,p+f),f=new Uint8Array(new ArrayBuffer(r)),f.set(n),n=f)}var f=this,p=0,r=1024,n=new Uint8Array(new ArrayBuffer(r));this.appendByteArrayWriter=function(h){f.appendByteArray(h.getByteArray())};this.appendByteArray=function(f){var d=f.length;l(d);n.set(f,p);p+=d};this.appendArray=function(f){var d=f.length;l(d);n.set(f,p);p+=d};this.appendUInt16LE=function(h){f.appendArray([h&255,h>>8&255])};this.appendUInt32LE=function(h){f.appendArray([h&
-255,h>>8&255,h>>16&255,h>>24&255])};this.appendString=function(h){f.appendByteArray(runtime.byteArrayFromString(h,g))};this.getLength=function(){return p};this.getByteArray=function(){var f=new Uint8Array(new ArrayBuffer(p));f.set(n.subarray(0,p));return f}};
+core.ByteArrayWriter=function(k){function h(b){b>d-p&&(d=Math.max(2*d,p+b),b=new Uint8Array(new ArrayBuffer(d)),b.set(n),n=b)}var b=this,p=0,d=1024,n=new Uint8Array(new ArrayBuffer(d));this.appendByteArrayWriter=function(d){b.appendByteArray(d.getByteArray())};this.appendByteArray=function(b){var d=b.length;h(d);n.set(b,p);p+=d};this.appendArray=function(b){var d=b.length;h(d);n.set(b,p);p+=d};this.appendUInt16LE=function(d){b.appendArray([d&255,d>>8&255])};this.appendUInt32LE=function(d){b.appendArray([d&
+255,d>>8&255,d>>16&255,d>>24&255])};this.appendString=function(d){b.appendByteArray(runtime.byteArrayFromString(d,k))};this.getLength=function(){return p};this.getByteArray=function(){var b=new Uint8Array(new ArrayBuffer(p));b.set(n.subarray(0,p));return b}};
// Input 6
-core.CSSUnits=function(){var g=this,l={"in":1,cm:2.54,mm:25.4,pt:72,pc:12};this.convert=function(f,g,r){return f*l[r]/l[g]};this.convertMeasure=function(f,l){var r,n;f&&l?(r=parseFloat(f),n=f.replace(r.toString(),""),r=g.convert(r,n,l).toString()):r="";return r};this.getUnits=function(f){return f.substr(f.length-2,f.length)}};
+core.CSSUnits=function(){var k=this,h={"in":1,cm:2.54,mm:25.4,pt:72,pc:12};this.convert=function(b,k,d){return b*h[d]/h[k]};this.convertMeasure=function(b,h){var d,n;b&&h?(d=parseFloat(b),n=b.replace(d.toString(),""),d=k.convert(d,n,h).toString()):d="";return d};this.getUnits=function(b){return b.substr(b.length-2,b.length)}};
// Input 7
/*
@@ -88,18 +90,65 @@ core.CSSUnits=function(){var g=this,l={"in":1,cm:2.54,mm:25.4,pt:72,pc:12};this.
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-(function(){function g(){var f,g,r,n,h;void 0===l&&(h=(f=runtime.getWindow())&&f.document,l={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1},h&&(n=h.createElement("div"),n.style.position="absolute",n.style.left="-99999px",n.style.transform="scale(2)",n.style["-webkit-transform"]="scale(2)",g=h.createElement("div"),n.appendChild(g),h.body.appendChild(n),f=h.createRange(),f.selectNode(g),l.rangeBCRIgnoresElementBCR=0===f.getClientRects().length,g.appendChild(h.createTextNode("Rect transform test")),
-g=g.getBoundingClientRect(),r=f.getBoundingClientRect(),l.unscaledRangeClientRects=2<Math.abs(g.height-r.height),f.detach(),h.body.removeChild(n),f=Object.keys(l).map(function(d){return d+":"+String(l[d])}).join(", "),runtime.log("Detected browser quirks - "+f)));return l}var l;core.DomUtils=function(){function f(a,b){return 0>=a.compareBoundaryPoints(Range.START_TO_START,b)&&0<=a.compareBoundaryPoints(Range.END_TO_END,b)}function l(a,b){return 0>=a.compareBoundaryPoints(Range.END_TO_START,b)&&0<=
-a.compareBoundaryPoints(Range.START_TO_END,b)}function r(a,b){var c=null;a.nodeType===Node.TEXT_NODE&&(0===a.length?(a.parentNode.removeChild(a),b.nodeType===Node.TEXT_NODE&&(c=b)):(b.nodeType===Node.TEXT_NODE&&(a.appendData(b.data),b.parentNode.removeChild(b)),c=a));return c}function n(a){for(var b=a.parentNode;a.firstChild;)b.insertBefore(a.firstChild,a);b.removeChild(a);return b}function h(a,b){for(var c=a.parentNode,e=a.firstChild,d;e;)d=e.nextSibling,h(e,b),e=d;b(a)&&(c=n(a));return c}function d(a,
-b){return a===b||Boolean(a.compareDocumentPosition(b)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function m(a,b){for(var c=0,e;a.parentNode!==b;)runtime.assert(null!==a.parentNode,"parent is null"),a=a.parentNode;for(e=b.firstChild;e!==a;)c+=1,e=e.nextSibling;return c}function c(a,b,e){Object.keys(b).forEach(function(k){var d=k.split(":"),f=d[1],h=e(d[0]),d=b[k];"object"===typeof d&&Object.keys(d).length?(k=h?a.getElementsByTagNameNS(h,f)[0]||a.ownerDocument.createElementNS(h,k):a.getElementsByTagName(f)[0]||
-a.ownerDocument.createElement(k),a.appendChild(k),c(k,d,e)):h&&a.setAttributeNS(h,k,String(d))})}var e=null;this.splitBoundaries=function(a){var b=[],c,e;if(a.startContainer.nodeType===Node.TEXT_NODE||a.endContainer.nodeType===Node.TEXT_NODE){if(c=a.endContainer){c=a.endOffset;e=a.endContainer;if(c<e.childNodes.length)for(e=e.childNodes.item(c),c=0;e.firstChild;)e=e.firstChild;else for(;e.lastChild;)e=e.lastChild,c=e.nodeType===Node.TEXT_NODE?e.textContent.length:e.childNodes.length;c={container:e,
-offset:c}}a.setEnd(c.container,c.offset);c=a.endContainer;0!==a.endOffset&&c.nodeType===Node.TEXT_NODE&&(e=c,a.endOffset!==e.length&&(b.push(e.splitText(a.endOffset)),b.push(e)));c=a.startContainer;0!==a.startOffset&&c.nodeType===Node.TEXT_NODE&&(e=c,a.startOffset!==e.length&&(c=e.splitText(a.startOffset),b.push(e),b.push(c),a.setStart(c,0)))}return b};this.containsRange=f;this.rangesIntersect=l;this.getNodesInRange=function(a,b){for(var c=[],e=a.commonAncestorContainer,d,f=a.startContainer.ownerDocument.createTreeWalker(e.nodeType===
-Node.TEXT_NODE?e.parentNode:e,NodeFilter.SHOW_ALL,b,!1),e=f.currentNode=a.startContainer;e;){d=b(e);if(d===NodeFilter.FILTER_ACCEPT)c.push(e);else if(d===NodeFilter.FILTER_REJECT)break;e=e.parentNode}c.reverse();for(e=f.nextNode();e;)c.push(e),e=f.nextNode();return c};this.normalizeTextNodes=function(a){a&&a.nextSibling&&(a=r(a,a.nextSibling));a&&a.previousSibling&&r(a.previousSibling,a)};this.rangeContainsNode=function(a,b){var c=b.ownerDocument.createRange(),e=b.ownerDocument.createRange(),d;c.setStart(a.startContainer,
-a.startOffset);c.setEnd(a.endContainer,a.endOffset);e.selectNodeContents(b);d=f(c,e);c.detach();e.detach();return d};this.mergeIntoParent=n;this.removeUnwantedNodes=h;this.getElementsByTagNameNS=function(a,b,c){var e=[];a=a.getElementsByTagNameNS(b,c);e.length=c=a.length;for(b=0;b<c;b+=1)e[b]=a.item(b);return e};this.rangeIntersectsNode=function(a,b){var c=b.ownerDocument.createRange(),e;c.selectNodeContents(b);e=l(a,c);c.detach();return e};this.containsNode=function(a,b){return a===b||a.contains(b)};
-this.comparePoints=function(a,b,c,e){if(a===c)return e-b;var d=a.compareDocumentPosition(c);2===d?d=-1:4===d?d=1:10===d?(b=m(a,c),d=b<e?1:-1):(e=m(c,a),d=e<b?-1:1);return d};this.adaptRangeDifferenceToZoomLevel=function(a,b){return g().unscaledRangeClientRects?a:a/b};this.getBoundingClientRect=function(a){var b=a.ownerDocument,c=g();if((!1===c.unscaledRangeClientRects||c.rangeBCRIgnoresElementBCR)&&a.nodeType===Node.ELEMENT_NODE)return a.getBoundingClientRect();var d;e?d=e:e=d=b.createRange();b=d;
-b.selectNode(a);return b.getBoundingClientRect()};this.mapKeyValObjOntoNode=function(a,b,c){Object.keys(b).forEach(function(e){var d=e.split(":"),f=d[1],d=c(d[0]),h=b[e];d?(f=a.getElementsByTagNameNS(d,f)[0],f||(f=a.ownerDocument.createElementNS(d,e),a.appendChild(f)),f.textContent=h):runtime.log("Key ignored: "+e)})};this.removeKeyElementsFromNode=function(a,b,c){b.forEach(function(b){var e=b.split(":"),d=e[1];(e=c(e[0]))?(d=a.getElementsByTagNameNS(e,d)[0])?d.parentNode.removeChild(d):runtime.log("Element for "+
-b+" not found."):runtime.log("Property Name ignored: "+b)})};this.getKeyValRepresentationOfNode=function(a,b){for(var c={},e=a.firstElementChild,d;e;){if(d=b(e.namespaceURI))c[d+":"+e.localName]=e.textContent;e=e.nextElementSibling}return c};this.mapObjOntoNode=c;(function(a){var b,c;c=runtime.getWindow();null!==c&&(b=c.navigator.appVersion.toLowerCase(),c=-1===b.indexOf("chrome")&&(-1!==b.indexOf("applewebkit")||-1!==b.indexOf("safari")),b=b.indexOf("msie"),c||b)&&(a.containsNode=d)})(this)};return core.DomUtils})();
+(function(){function k(){var b,k,d,n,g,q,r,l,f;void 0===h&&(k=(b=runtime.getWindow())&&b.document,q=k.documentElement,r=k.body,h={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1,elementBCRIgnoresBodyScroll:!1},k&&(n=k.createElement("div"),n.style.position="absolute",n.style.left="-99999px",n.style.transform="scale(2)",n.style["-webkit-transform"]="scale(2)",g=k.createElement("div"),n.appendChild(g),r.appendChild(n),b=k.createRange(),b.selectNode(g),h.rangeBCRIgnoresElementBCR=0===b.getClientRects().length,
+g.appendChild(k.createTextNode("Rect transform test")),k=g.getBoundingClientRect(),d=b.getBoundingClientRect(),h.unscaledRangeClientRects=2<Math.abs(k.height-d.height),n.style.transform="",n.style["-webkit-transform"]="",k=q.style.overflow,d=r.style.overflow,l=r.style.height,f=r.scrollTop,q.style.overflow="visible",r.style.overflow="visible",r.style.height="200%",r.scrollTop=r.scrollHeight,h.elementBCRIgnoresBodyScroll=b.getBoundingClientRect().top!==g.getBoundingClientRect().top,r.scrollTop=f,r.style.height=
+l,r.style.overflow=d,q.style.overflow=k,b.detach(),r.removeChild(n),b=Object.keys(h).map(function(c){return c+":"+String(h[c])}).join(", "),runtime.log("Detected browser quirks - "+b)));return h}var h;core.DomUtils=function(){function b(f,c){for(var a=0,b;f.parentNode!==c;)runtime.assert(null!==f.parentNode,"parent is null"),f=f.parentNode;for(b=c.firstChild;b!==f;)a+=1,b=b.nextSibling;return a}function h(f,c){return 0>=f.compareBoundaryPoints(Range.START_TO_START,c)&&0<=f.compareBoundaryPoints(Range.END_TO_END,
+c)}function d(f,c){var a=null;f.nodeType===Node.TEXT_NODE&&(0===f.length?(f.parentNode.removeChild(f),c.nodeType===Node.TEXT_NODE&&(a=c)):(c.nodeType===Node.TEXT_NODE&&(f.appendData(c.data),c.parentNode.removeChild(c)),a=f));return a}function n(f){for(var c=f.parentNode;f.firstChild;)c.insertBefore(f.firstChild,f);c.removeChild(f);return c}function g(f,c){for(var a=f.parentNode,b=f.firstChild,e;b;)e=b.nextSibling,g(b,c),b=e;a&&c(f)&&n(f);return a}function q(b,c){return b===c||Boolean(b.compareDocumentPosition(c)&
+Node.DOCUMENT_POSITION_CONTAINED_BY)}function r(b,c,a){Object.keys(c).forEach(function(m){var e=m.split(":"),d=e[1],l=a(e[0]),e=c[m],g=typeof e;"object"===g?Object.keys(e).length&&(m=l?b.getElementsByTagNameNS(l,d)[0]||b.ownerDocument.createElementNS(l,m):b.getElementsByTagName(d)[0]||b.ownerDocument.createElement(m),b.appendChild(m),r(m,e,a)):l&&(runtime.assert("number"===g||"string"===g,"attempting to map unsupported type '"+g+"' (key: "+m+")"),b.setAttributeNS(l,m,String(e)))})}var l=null;this.splitBoundaries=
+function(f){var c,a=[],m,e,d;if(f.startContainer.nodeType===Node.TEXT_NODE||f.endContainer.nodeType===Node.TEXT_NODE){m=f.endContainer;e=f.endContainer.nodeType!==Node.TEXT_NODE?f.endOffset===f.endContainer.childNodes.length:!1;d=f.endOffset;c=f.endContainer;if(d<c.childNodes.length)for(c=c.childNodes.item(d),d=0;c.firstChild;)c=c.firstChild;else for(;c.lastChild;)c=c.lastChild,d=c.nodeType===Node.TEXT_NODE?c.textContent.length:c.childNodes.length;c===m&&(m=null);f.setEnd(c,d);d=f.endContainer;0!==
+f.endOffset&&d.nodeType===Node.TEXT_NODE&&(c=d,f.endOffset!==c.length&&(a.push(c.splitText(f.endOffset)),a.push(c)));d=f.startContainer;0!==f.startOffset&&d.nodeType===Node.TEXT_NODE&&(c=d,f.startOffset!==c.length&&(d=c.splitText(f.startOffset),a.push(c),a.push(d),f.setStart(d,0)));if(null!==m){for(d=f.endContainer;d.parentNode&&d.parentNode!==m;)d=d.parentNode;e=e?m.childNodes.length:b(d,m);f.setEnd(m,e)}}return a};this.containsRange=h;this.rangesIntersect=function(b,c){return 0>=b.compareBoundaryPoints(Range.END_TO_START,
+c)&&0<=b.compareBoundaryPoints(Range.START_TO_END,c)};this.getNodesInRange=function(b,c,a){var m=[],e=b.commonAncestorContainer;a=b.startContainer.ownerDocument.createTreeWalker(e.nodeType===Node.TEXT_NODE?e.parentNode:e,a,c,!1);var d;b.endContainer.childNodes[b.endOffset-1]?(e=b.endContainer.childNodes[b.endOffset-1],d=Node.DOCUMENT_POSITION_PRECEDING|Node.DOCUMENT_POSITION_CONTAINED_BY):(e=b.endContainer,d=Node.DOCUMENT_POSITION_PRECEDING);b.startContainer.childNodes[b.startOffset]?(b=b.startContainer.childNodes[b.startOffset],
+a.currentNode=b):b.startOffset===(b.startContainer.nodeType===Node.TEXT_NODE?b.startContainer.length:b.startContainer.childNodes.length)?(b=b.startContainer,a.currentNode=b,a.lastChild(),b=a.nextNode()):(b=b.startContainer,a.currentNode=b);b&&c(b)===NodeFilter.FILTER_ACCEPT&&m.push(b);for(b=a.nextNode();b;){c=e.compareDocumentPosition(b);if(0!==c&&0===(c&d))break;m.push(b);b=a.nextNode()}return m};this.normalizeTextNodes=function(b){b&&b.nextSibling&&(b=d(b,b.nextSibling));b&&b.previousSibling&&d(b.previousSibling,
+b)};this.rangeContainsNode=function(b,c){var a=c.ownerDocument.createRange(),m=c.ownerDocument.createRange(),e;a.setStart(b.startContainer,b.startOffset);a.setEnd(b.endContainer,b.endOffset);m.selectNodeContents(c);e=h(a,m);a.detach();m.detach();return e};this.mergeIntoParent=n;this.removeUnwantedNodes=g;this.getElementsByTagNameNS=function(b,c,a){var m=[];b=b.getElementsByTagNameNS(c,a);m.length=a=b.length;for(c=0;c<a;c+=1)m[c]=b.item(c);return m};this.containsNode=function(b,c){return b===c||b.contains(c)};
+this.comparePoints=function(f,c,a,m){if(f===a)return m-c;var e=f.compareDocumentPosition(a);2===e?e=-1:4===e?e=1:10===e?(c=b(f,a),e=c<m?1:-1):(m=b(a,f),e=m<c?-1:1);return e};this.adaptRangeDifferenceToZoomLevel=function(b,c){return k().unscaledRangeClientRects?b:b/c};this.getBoundingClientRect=function(b){var c=b.ownerDocument,a=k(),m=c.body;if((!1===a.unscaledRangeClientRects||a.rangeBCRIgnoresElementBCR)&&b.nodeType===Node.ELEMENT_NODE)return b=b.getBoundingClientRect(),a.elementBCRIgnoresBodyScroll?
+{left:b.left+m.scrollLeft,right:b.right+m.scrollLeft,top:b.top+m.scrollTop,bottom:b.bottom+m.scrollTop}:b;var e;l?e=l:l=e=c.createRange();a=e;a.selectNode(b);return a.getBoundingClientRect()};this.mapKeyValObjOntoNode=function(b,c,a){Object.keys(c).forEach(function(m){var e=m.split(":"),d=e[1],e=a(e[0]),l=c[m];e?(d=b.getElementsByTagNameNS(e,d)[0],d||(d=b.ownerDocument.createElementNS(e,m),b.appendChild(d)),d.textContent=l):runtime.log("Key ignored: "+m)})};this.removeKeyElementsFromNode=function(b,
+c,a){c.forEach(function(c){var e=c.split(":"),d=e[1];(e=a(e[0]))?(d=b.getElementsByTagNameNS(e,d)[0])?d.parentNode.removeChild(d):runtime.log("Element for "+c+" not found."):runtime.log("Property Name ignored: "+c)})};this.getKeyValRepresentationOfNode=function(b,c){for(var a={},m=b.firstElementChild,e;m;){if(e=c(m.namespaceURI))a[e+":"+m.localName]=m.textContent;m=m.nextElementSibling}return a};this.mapObjOntoNode=r;(function(b){var c,a;a=runtime.getWindow();null!==a&&(c=a.navigator.appVersion.toLowerCase(),
+a=-1===c.indexOf("chrome")&&(-1!==c.indexOf("applewebkit")||-1!==c.indexOf("safari")),c=c.indexOf("msie"),a||c)&&(b.containsNode=q)})(this)};return core.DomUtils})();
// Input 8
+core.Cursor=function(k,h){function b(c){c.parentNode&&(q.push(c.previousSibling),q.push(c.nextSibling),c.parentNode.removeChild(c))}function p(c,a,b){if(a.nodeType===Node.TEXT_NODE){runtime.assert(Boolean(a),"putCursorIntoTextNode: invalid container");var e=a.parentNode;runtime.assert(Boolean(e),"putCursorIntoTextNode: container without parent");runtime.assert(0<=b&&b<=a.length,"putCursorIntoTextNode: offset is out of bounds");0===b?e.insertBefore(c,a):(b!==a.length&&a.splitText(b),e.insertBefore(c,
+a.nextSibling))}else a.nodeType===Node.ELEMENT_NODE&&a.insertBefore(c,a.childNodes.item(b));q.push(c.previousSibling);q.push(c.nextSibling)}var d=k.createElementNS("urn:webodf:names:cursor","cursor"),n=k.createElementNS("urn:webodf:names:cursor","anchor"),g,q=[],r=k.createRange(),l,f=new core.DomUtils;this.getNode=function(){return d};this.getAnchorNode=function(){return n.parentNode?n:d};this.getSelectedRange=function(){l?(r.setStartBefore(d),r.collapse(!0)):(r.setStartAfter(g?n:d),r.setEndBefore(g?
+d:n));return r};this.setSelectedRange=function(c,a){r&&r!==c&&r.detach();r=c;g=!1!==a;(l=c.collapsed)?(b(n),b(d),p(d,c.startContainer,c.startOffset)):(b(n),b(d),p(g?d:n,c.endContainer,c.endOffset),p(g?n:d,c.startContainer,c.startOffset));q.forEach(f.normalizeTextNodes);q.length=0};this.hasForwardSelection=function(){return g};this.remove=function(){b(d);q.forEach(f.normalizeTextNodes);q.length=0};d.setAttributeNS("urn:webodf:names:cursor","memberId",h);n.setAttributeNS("urn:webodf:names:cursor","memberId",
+h)};
+// Input 9
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+core.Destroyable=function(){};core.Destroyable.prototype.destroy=function(k){};
+// Input 10
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -137,9 +186,9 @@ b+" not found."):runtime.log("Property Name ignored: "+b)})};this.getKeyValRepre
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-core.EventNotifier=function(g){var l={};this.emit=function(f,g){var r,n;runtime.assert(l.hasOwnProperty(f),'unknown event fired "'+f+'"');n=l[f];for(r=0;r<n.length;r+=1)n[r](g)};this.subscribe=function(f,g){runtime.assert(l.hasOwnProperty(f),'tried to subscribe to unknown event "'+f+'"');l[f].push(g);runtime.log('event "'+f+'" subscribed.')};this.unsubscribe=function(f,g){var r;runtime.assert(l.hasOwnProperty(f),'tried to unsubscribe from unknown event "'+f+'"');r=l[f].indexOf(g);runtime.assert(-1!==
-r,'tried to unsubscribe unknown callback from event "'+f+'"');-1!==r&&l[f].splice(r,1);runtime.log('event "'+f+'" unsubscribed.')};(function(){var f,p;for(f=0;f<g.length;f+=1)p=g[f],runtime.assert(!l.hasOwnProperty(p),'Duplicated event ids: "'+p+'" registered more than once.'),l[p]=[]})()};
-// Input 9
+core.EventNotifier=function(k){var h={};this.emit=function(b,k){var d,n;runtime.assert(h.hasOwnProperty(b),'unknown event fired "'+b+'"');n=h[b];for(d=0;d<n.length;d+=1)n[d](k)};this.subscribe=function(b,k){runtime.assert(h.hasOwnProperty(b),'tried to subscribe to unknown event "'+b+'"');h[b].push(k)};this.unsubscribe=function(b,k){var d;runtime.assert(h.hasOwnProperty(b),'tried to unsubscribe from unknown event "'+b+'"');d=h[b].indexOf(k);runtime.assert(-1!==d,'tried to unsubscribe unknown callback from event "'+
+b+'"');-1!==d&&h[b].splice(d,1)};(function(){var b,p;for(b=0;b<k.length;b+=1)p=k[b],runtime.assert(!h.hasOwnProperty(p),'Duplicated event ids: "'+p+'" registered more than once.'),h[p]=[]})()};
+// Input 11
/*
Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
@@ -177,46 +226,93 @@ r,'tried to unsubscribe unknown callback from event "'+f+'"');-1!==r&&l[f].splic
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-core.LoopWatchDog=function(g,l){var f=Date.now(),p=0;this.check=function(){var r;if(g&&(r=Date.now(),r-f>g))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0<l&&(p+=1,p>l))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}};
-// Input 10
-core.PositionIterator=function(g,l,f,p){function r(){this.acceptNode=function(a){return!a||a.nodeType===b&&0===a.length?t:k}}function n(a){this.acceptNode=function(c){return!c||c.nodeType===b&&0===c.length?t:a.acceptNode(c)}}function h(){var a=c.currentNode,d=a.nodeType;e=d===b?a.length-1:d===q?1:0}function d(){if(null===c.previousSibling()){if(!c.parentNode()||c.currentNode===g)return c.firstChild(),!1;e=0}else h();return!0}var m=this,c,e,a,b=Node.TEXT_NODE,q=Node.ELEMENT_NODE,k=NodeFilter.FILTER_ACCEPT,
-t=NodeFilter.FILTER_REJECT;this.nextPosition=function(){var a=c.currentNode,d=a.nodeType;if(a===g)return!1;if(0===e&&d===q)null===c.firstChild()&&(e=1);else if(d===b&&e+1<a.length)e+=1;else if(null!==c.nextSibling())e=0;else if(c.parentNode())e=1;else return!1;return!0};this.previousPosition=function(){var a=!0,q=c.currentNode;0===e?a=d():q.nodeType===b?e-=1:null!==c.lastChild()?h():q===g?a=!1:e=0;return a};this.previousNode=d;this.container=function(){var a=c.currentNode,d=a.nodeType;0===e&&d!==
-b&&(a=a.parentNode);return a};this.rightNode=function(){var d=c.currentNode,f=d.nodeType;if(f===b&&e===d.length)for(d=d.nextSibling;d&&a(d)!==k;)d=d.nextSibling;else f===q&&1===e&&(d=null);return d};this.leftNode=function(){var b=c.currentNode;if(0===e)for(b=b.previousSibling;b&&a(b)!==k;)b=b.previousSibling;else if(b.nodeType===q)for(b=b.lastChild;b&&a(b)!==k;)b=b.previousSibling;return b};this.getCurrentNode=function(){return c.currentNode};this.unfilteredDomOffset=function(){if(c.currentNode.nodeType===
-b)return e;for(var a=0,d=c.currentNode,d=1===e?d.lastChild:d.previousSibling;d;)a+=1,d=d.previousSibling;return a};this.getPreviousSibling=function(){var a=c.currentNode,b=c.previousSibling();c.currentNode=a;return b};this.getNextSibling=function(){var a=c.currentNode,b=c.nextSibling();c.currentNode=a;return b};this.setUnfilteredPosition=function(d,q){var f,h;runtime.assert(null!==d&&void 0!==d,"PositionIterator.setUnfilteredPosition called without container");c.currentNode=d;if(d.nodeType===b)return e=
-q,runtime.assert(q<=d.length,"Error in setPosition: "+q+" > "+d.length),runtime.assert(0<=q,"Error in setPosition: "+q+" < 0"),q===d.length&&(c.nextSibling()?e=0:c.parentNode()?e=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid.")),!0;f=a(d);for(h=d.parentNode;h&&h!==g&&f===k;)f=a(h),f!==k&&(c.currentNode=h),h=h.parentNode;q<d.childNodes.length&&f!==NodeFilter.FILTER_REJECT?(c.currentNode=d.childNodes.item(q),f=a(c.currentNode),e=0):e=1;f===NodeFilter.FILTER_REJECT&&(e=1);if(f!==
-k)return m.nextPosition();runtime.assert(a(c.currentNode)===k,"PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set");return!0};this.moveToEnd=function(){c.currentNode=g;e=1};this.moveToEndOfNode=function(a){a.nodeType===b?m.setUnfilteredPosition(a,a.length):(c.currentNode=a,e=1)};this.getNodeFilter=function(){return a};a=(f?new n(f):new r).acceptNode;a.acceptNode=a;l=l||4294967295;runtime.assert(g.nodeType!==Node.TEXT_NODE,"Internet Explorer doesn't allow tree walker roots to be text nodes");
-c=g.ownerDocument.createTreeWalker(g,l,a,p);e=0;null===c.firstChild()&&(e=1)};
-// Input 11
-core.zip_HuftNode=function(){this.n=this.b=this.e=0;this.t=null};core.zip_HuftList=function(){this.list=this.next=null};
-core.RawInflate=function(){function g(a,b,c,e,d,q){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var f=Array(this.BMAX+1),k,h,I,g,m,s,l,n=Array(this.BMAX+1),r,p,v,t=new core.zip_HuftNode,W=Array(this.BMAX);g=Array(this.N_MAX);var u,y=Array(this.BMAX+1),z,Q,B;B=this.root=null;for(m=0;m<f.length;m++)f[m]=0;for(m=0;m<n.length;m++)n[m]=0;for(m=0;m<W.length;m++)W[m]=null;for(m=0;m<g.length;m++)g[m]=0;for(m=0;m<y.length;m++)y[m]=0;k=256<b?a[256]:this.BMAX;r=a;p=0;m=b;do f[r[p]]++,p++;
-while(0<--m);if(f[0]===b)this.root=null,this.status=this.m=0;else{for(s=1;s<=this.BMAX&&0===f[s];s++);l=s;q<s&&(q=s);for(m=this.BMAX;0!==m&&0===f[m];m--);I=m;q>m&&(q=m);for(z=1<<s;s<m;s++,z<<=1)if(z-=f[s],0>z){this.status=2;this.m=q;return}z-=f[m];if(0>z)this.status=2,this.m=q;else{f[m]+=z;y[1]=s=0;r=f;p=1;for(v=2;0<--m;)s+=r[p++],y[v++]=s;r=a;m=p=0;do s=r[p++],0!==s&&(g[y[s]++]=m);while(++m<b);b=y[I];y[0]=m=0;r=g;p=0;g=-1;u=n[0]=0;v=null;Q=0;for(l=l-1+1;l<=I;l++)for(a=f[l];0<a--;){for(;l>u+n[1+g];){u+=
-n[1+g];g++;Q=I-u;Q=Q>q?q:Q;s=l-u;h=1<<s;if(h>a+1)for(h-=a+1,v=l;++s<Q;){h<<=1;if(h<=f[++v])break;h-=f[v]}u+s>k&&u<k&&(s=k-u);Q=1<<s;n[1+g]=s;v=Array(Q);for(h=0;h<Q;h++)v[h]=new core.zip_HuftNode;B=null===B?this.root=new core.zip_HuftList:B.next=new core.zip_HuftList;B.next=null;B.list=v;W[g]=v;0<g&&(y[g]=m,t.b=n[g],t.e=16+s,t.t=v,s=(m&(1<<u)-1)>>u-n[g],W[g-1][s].e=t.e,W[g-1][s].b=t.b,W[g-1][s].n=t.n,W[g-1][s].t=t.t)}t.b=l-u;p>=b?t.e=99:r[p]<c?(t.e=256>r[p]?16:15,t.n=r[p++]):(t.e=d[r[p]-c],t.n=e[r[p++]-
-c]);h=1<<l-u;for(s=m>>u;s<Q;s+=h)v[s].e=t.e,v[s].b=t.b,v[s].n=t.n,v[s].t=t.t;for(s=1<<l-1;0!==(m&s);s>>=1)m^=s;for(m^=s;(m&(1<<u)-1)!==y[g];)u-=n[g],g--}this.m=n[1];this.status=0!==z&&1!==I?1:0}}}function l(c){for(;b<c;){var e=a,d;d=s.length===H?-1:s[H++];a=e|d<<b;b+=8}}function f(b){return a&y[b]}function p(c){a>>=c;b-=c}function r(a,b,c){var e,k,I;if(0===c)return 0;for(I=0;;){l(v);k=w.list[f(v)];for(e=k.e;16<e;){if(99===e)return-1;p(k.b);e-=16;l(e);k=k.t[f(e)];e=k.e}p(k.b);if(16===e)d&=32767,a[b+
-I++]=h[d++]=k.n;else{if(15===e)break;l(e);t=k.n+f(e);p(e);l(u);k=x.list[f(u)];for(e=k.e;16<e;){if(99===e)return-1;p(k.b);e-=16;l(e);k=k.t[f(e)];e=k.e}p(k.b);l(e);A=d-k.n-f(e);for(p(e);0<t&&I<c;)t--,A&=32767,d&=32767,a[b+I++]=h[d++]=h[A++]}if(I===c)return c}q=-1;return I}function n(a,b,c){var e,d,q,k,h,m,s,n=Array(316);for(e=0;e<n.length;e++)n[e]=0;l(5);m=257+f(5);p(5);l(5);s=1+f(5);p(5);l(4);e=4+f(4);p(4);if(286<m||30<s)return-1;for(d=0;d<e;d++)l(3),n[Q[d]]=f(3),p(3);for(d=e;19>d;d++)n[Q[d]]=0;v=
-7;d=new g(n,19,19,null,null,v);if(0!==d.status)return-1;w=d.root;v=d.m;k=m+s;for(e=q=0;e<k;)if(l(v),h=w.list[f(v)],d=h.b,p(d),d=h.n,16>d)n[e++]=q=d;else if(16===d){l(2);d=3+f(2);p(2);if(e+d>k)return-1;for(;0<d--;)n[e++]=q}else{17===d?(l(3),d=3+f(3),p(3)):(l(7),d=11+f(7),p(7));if(e+d>k)return-1;for(;0<d--;)n[e++]=0;q=0}v=9;d=new g(n,m,257,B,L,v);0===v&&(d.status=1);if(0!==d.status)return-1;w=d.root;v=d.m;for(e=0;e<s;e++)n[e]=n[e+m];u=6;d=new g(n,s,0,I,W,u);x=d.root;u=d.m;return 0===u&&257<m||0!==d.status?
--1:r(a,b,c)}var h=[],d,m=null,c,e,a,b,q,k,t,A,w,x,v,u,s,H,y=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],B=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],L=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],I=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],W=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],Q=[16,17,18,0,8,7,9,6,
-10,5,11,4,12,3,13,2,14,1,15],z;this.inflate=function(y,Q){h.length=65536;b=a=d=0;q=-1;k=!1;t=A=0;w=null;s=y;H=0;var G=new Uint8Array(new ArrayBuffer(Q));a:for(var Z=0,O;Z<Q&&(!k||-1!==q);){if(0<t){if(0!==q)for(;0<t&&Z<Q;)t--,A&=32767,d&=32767,G[0+Z]=h[d]=h[A],Z+=1,d+=1,A+=1;else{for(;0<t&&Z<Q;)t-=1,d&=32767,l(8),G[0+Z]=h[d]=f(8),Z+=1,d+=1,p(8);0===t&&(q=-1)}if(Z===Q)break}if(-1===q){if(k)break;l(1);0!==f(1)&&(k=!0);p(1);l(2);q=f(2);p(2);w=null;t=0}switch(q){case 0:O=G;var aa=0+Z,J=Q-Z,F=void 0,F=
-b&7;p(F);l(16);F=f(16);p(16);l(16);if(F!==(~a&65535))O=-1;else{p(16);t=F;for(F=0;0<t&&F<J;)t--,d&=32767,l(8),O[aa+F++]=h[d++]=f(8),p(8);0===t&&(q=-1);O=F}break;case 1:if(null!==w)O=r(G,0+Z,Q-Z);else b:{O=G;aa=0+Z;J=Q-Z;if(null===m){for(var C=void 0,F=Array(288),C=void 0,C=0;144>C;C++)F[C]=8;for(C=144;256>C;C++)F[C]=9;for(C=256;280>C;C++)F[C]=7;for(C=280;288>C;C++)F[C]=8;e=7;C=new g(F,288,257,B,L,e);if(0!==C.status){alert("HufBuild error: "+C.status);O=-1;break b}m=C.root;e=C.m;for(C=0;30>C;C++)F[C]=
-5;z=5;C=new g(F,30,0,I,W,z);if(1<C.status){m=null;alert("HufBuild error: "+C.status);O=-1;break b}c=C.root;z=C.m}w=m;x=c;v=e;u=z;O=r(O,aa,J)}break;case 2:O=null!==w?r(G,0+Z,Q-Z):n(G,0+Z,Q-Z);break;default:O=-1}if(-1===O)break a;Z+=O}s=new Uint8Array(new ArrayBuffer(0));return G}};
+core.LoopWatchDog=function(k,h){var b=Date.now(),p=0;this.check=function(){var d;if(k&&(d=Date.now(),d-b>k))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0<h&&(p+=1,p>h))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}};
// Input 12
-core.ScheduledTask=function(g,l){function f(){n&&(runtime.clearTimeout(r),n=!1)}function p(){f();g.apply(void 0,h);h=null}var r,n=!1,h=[];this.trigger=function(){h=Array.prototype.slice.call(arguments);n||(n=!0,r=runtime.setTimeout(p,l))};this.triggerImmediate=function(){h=Array.prototype.slice.call(arguments);p()};this.processRequests=function(){n&&p()};this.cancel=f;this.destroy=function(d){f();d()}};
+core.PositionIterator=function(k,h,b,p){function d(){this.acceptNode=function(a){return!a||a.nodeType===m&&0===a.length?w:t}}function n(a){this.acceptNode=function(c){return!c||c.nodeType===m&&0===c.length?w:a.acceptNode(c)}}function g(){var a=f.currentNode,b=a.nodeType;c=b===m?a.length-1:b===e?1:0}function q(){if(null===f.previousSibling()){if(!f.parentNode()||f.currentNode===k)return f.firstChild(),!1;c=0}else g();return!0}function r(){var b=f.currentNode,e;e=a(b);if(b!==k)for(b=b.parentNode;b&&
+b!==k;)a(b)===w&&(f.currentNode=b,e=w),b=b.parentNode;e===w?(c=1,b=l.nextPosition()):b=e===t?!0:l.nextPosition();b&&runtime.assert(a(f.currentNode)===t,"moveToAcceptedNode did not result in walker being on an accepted node");return b}var l=this,f,c,a,m=Node.TEXT_NODE,e=Node.ELEMENT_NODE,t=NodeFilter.FILTER_ACCEPT,w=NodeFilter.FILTER_REJECT;this.nextPosition=function(){var a=f.currentNode,b=a.nodeType;if(a===k)return!1;if(0===c&&b===e)null===f.firstChild()&&(c=1);else if(b===m&&c+1<a.length)c+=1;else if(null!==
+f.nextSibling())c=0;else if(f.parentNode())c=1;else return!1;return!0};this.previousPosition=function(){var a=!0,b=f.currentNode;0===c?a=q():b.nodeType===m?c-=1:null!==f.lastChild()?g():b===k?a=!1:c=0;return a};this.previousNode=q;this.container=function(){var a=f.currentNode,b=a.nodeType;0===c&&b!==m&&(a=a.parentNode);return a};this.rightNode=function(){var b=f.currentNode,d=b.nodeType;if(d===m&&c===b.length)for(b=b.nextSibling;b&&a(b)!==t;)b=b.nextSibling;else d===e&&1===c&&(b=null);return b};this.leftNode=
+function(){var b=f.currentNode;if(0===c)for(b=b.previousSibling;b&&a(b)!==t;)b=b.previousSibling;else if(b.nodeType===e)for(b=b.lastChild;b&&a(b)!==t;)b=b.previousSibling;return b};this.getCurrentNode=function(){return f.currentNode};this.unfilteredDomOffset=function(){if(f.currentNode.nodeType===m)return c;for(var a=0,b=f.currentNode,b=1===c?b.lastChild:b.previousSibling;b;)a+=1,b=b.previousSibling;return a};this.getPreviousSibling=function(){var a=f.currentNode,c=f.previousSibling();f.currentNode=
+a;return c};this.getNextSibling=function(){var a=f.currentNode,c=f.nextSibling();f.currentNode=a;return c};this.setPositionBeforeElement=function(a){runtime.assert(Boolean(a),"setPositionBeforeElement called without element");f.currentNode=a;c=0;return r()};this.setUnfilteredPosition=function(a,b){runtime.assert(Boolean(a),"PositionIterator.setUnfilteredPosition called without container");f.currentNode=a;if(a.nodeType===m)return c=b,runtime.assert(b<=a.length,"Error in setPosition: "+b+" > "+a.length),
+runtime.assert(0<=b,"Error in setPosition: "+b+" < 0"),b===a.length&&(f.nextSibling()?c=0:f.parentNode()?c=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid.")),!0;b<a.childNodes.length?(f.currentNode=a.childNodes.item(b),c=0):c=1;return r()};this.moveToEnd=function(){f.currentNode=k;c=1};this.moveToEndOfNode=function(a){a.nodeType===m?l.setUnfilteredPosition(a,a.length):(f.currentNode=a,c=1)};this.isBeforeNode=function(){return 0===c};this.getNodeFilter=function(){return a};
+a=(b?new n(b):new d).acceptNode;a.acceptNode=a;h=h||NodeFilter.SHOW_ALL;runtime.assert(k.nodeType!==Node.TEXT_NODE,"Internet Explorer doesn't allow tree walker roots to be text nodes");f=k.ownerDocument.createTreeWalker(k,h,a,p);c=0;null===f.firstChild()&&(c=1)};
// Input 13
-core.UnitTest=function(){};core.UnitTest.prototype.setUp=function(){};core.UnitTest.prototype.tearDown=function(){};core.UnitTest.prototype.description=function(){};core.UnitTest.prototype.tests=function(){};core.UnitTest.prototype.asyncTests=function(){};
-core.UnitTest.provideTestAreaDiv=function(){var g=runtime.getWindow().document,l=g.getElementById("testarea");runtime.assert(!l,'Unclean test environment, found a div with id "testarea".');l=g.createElement("div");l.setAttribute("id","testarea");g.body.appendChild(l);return l};
-core.UnitTest.cleanupTestAreaDiv=function(){var g=runtime.getWindow().document,l=g.getElementById("testarea");runtime.assert(!!l&&l.parentNode===g.body,'Test environment broken, found no div with id "testarea" below body.');g.body.removeChild(l)};core.UnitTest.createOdtDocument=function(g,l){var f="<?xml version='1.0' encoding='UTF-8'?>",f=f+"<office:document";Object.keys(l).forEach(function(g){f+=" xmlns:"+g+'="'+l[g]+'"'});f+=">";f+=g;f+="</office:document>";return runtime.parseXML(f)};
-core.UnitTestRunner=function(){function g(d){h+=1;runtime.log("fail",d)}function l(d,c){var e;try{if(d.length!==c.length)return g("array of length "+d.length+" should be "+c.length+" long"),!1;for(e=0;e<d.length;e+=1)if(d[e]!==c[e])return g(d[e]+" should be "+c[e]+" at array index "+e),!1}catch(a){return!1}return!0}function f(d,c,e){var a=d.attributes,b=a.length,q,k,h;for(q=0;q<b;q+=1)if(k=a.item(q),"xmlns"!==k.prefix&&"urn:webodf:names:steps"!==k.namespaceURI){h=c.getAttributeNS(k.namespaceURI,k.localName);
-if(!c.hasAttributeNS(k.namespaceURI,k.localName))return g("Attribute "+k.localName+" with value "+k.value+" was not present"),!1;if(h!==k.value)return g("Attribute "+k.localName+" was "+h+" should be "+k.value),!1}return e?!0:f(c,d,!0)}function p(d,c){var e,a;e=d.nodeType;a=c.nodeType;if(e!==a)return g("Nodetype '"+e+"' should be '"+a+"'"),!1;if(e===Node.TEXT_NODE){if(d.data===c.data)return!0;g("Textnode data '"+d.data+"' should be '"+c.data+"'");return!1}runtime.assert(e===Node.ELEMENT_NODE,"Only textnodes and elements supported.");
-if(d.namespaceURI!==c.namespaceURI)return g("namespace '"+d.namespaceURI+"' should be '"+c.namespaceURI+"'"),!1;if(d.localName!==c.localName)return g("localName '"+d.localName+"' should be '"+c.localName+"'"),!1;if(!f(d,c,!1))return!1;e=d.firstChild;for(a=c.firstChild;e;){if(!a)return g("Nodetype '"+e.nodeType+"' is unexpected here."),!1;if(!p(e,a))return!1;e=e.nextSibling;a=a.nextSibling}return a?(g("Nodetype '"+a.nodeType+"' is missing here."),!1):!0}function r(f,c){return 0===c?f===c&&1/f===1/
-c:f===c?!0:"number"===typeof c&&isNaN(c)?"number"===typeof f&&isNaN(f):Object.prototype.toString.call(c)===Object.prototype.toString.call([])?l(f,c):"object"===typeof c&&"object"===typeof f?c.constructor===Element||c.constructor===Node?p(c,f):d(c,f):!1}function n(d,c,e){"string"===typeof c&&"string"===typeof e||runtime.log("WARN: shouldBe() expects string arguments");var a,b;try{b=eval(c)}catch(q){a=q}d=eval(e);a?g(c+" should be "+d+". Threw exception "+a):r(b,d)?runtime.log("pass",c+" is "+e):String(typeof b)===
-String(typeof d)?(e=0===b&&0>1/b?"-0":String(b),g(c+" should be "+d+". Was "+e+".")):g(c+" should be "+d+" (of type "+typeof d+"). Was "+b+" (of type "+typeof b+").")}var h=0,d;d=function(d,c){var e=Object.keys(d),a=Object.keys(c);e.sort();a.sort();return l(e,a)&&Object.keys(d).every(function(a){var e=d[a],f=c[a];return r(e,f)?!0:(g(e+" should be "+f+" for key "+a),!1)})};this.areNodesEqual=p;this.shouldBeNull=function(d,c){n(d,c,"null")};this.shouldBeNonNull=function(d,c){var e,a;try{a=eval(c)}catch(b){e=
-b}e?g(c+" should be non-null. Threw exception "+e):null!==a?runtime.log("pass",c+" is non-null."):g(c+" should be non-null. Was "+a)};this.shouldBe=n;this.countFailedTests=function(){return h};this.name=function(d){var c,e,a=[],b=d.length;a.length=b;for(c=0;c<b;c+=1){e=Runtime.getFunctionName(d[c])||"";if(""===e)throw"Found a function without a name.";a[c]={f:d[c],name:e}}return a}};
-core.UnitTester=function(){function g(f,g){return"<span style='color:blue;cursor:pointer' onclick='"+g+"'>"+f+"</span>"}var l=0,f={};this.runTests=function(p,r,n){function h(a){if(0===a.length)f[d]=e,l+=m.countFailedTests(),r();else{b=a[0].f;var q=a[0].name;runtime.log("Running "+q);k=m.countFailedTests();c.setUp();b(function(){c.tearDown();e[q]=k===m.countFailedTests();h(a.slice(1))})}}var d=Runtime.getFunctionName(p)||"",m=new core.UnitTestRunner,c=new p(m),e={},a,b,q,k,t="BrowserRuntime"===runtime.type();
-if(f.hasOwnProperty(d))runtime.log("Test "+d+" has already run.");else{t?runtime.log("<span>Running "+g(d,'runSuite("'+d+'");')+": "+c.description()+"</span>"):runtime.log("Running "+d+": "+c.description);q=c.tests();for(a=0;a<q.length;a+=1)b=q[a].f,p=q[a].name,n.length&&-1===n.indexOf(p)||(t?runtime.log("<span>Running "+g(p,'runTest("'+d+'","'+p+'")')+"</span>"):runtime.log("Running "+p),k=m.countFailedTests(),c.setUp(),b(),c.tearDown(),e[p]=k===m.countFailedTests());h(c.asyncTests())}};this.countFailedTests=
-function(){return l};this.results=function(){return f}};
+core.PositionFilter=function(){};core.PositionFilter.FilterResult={FILTER_ACCEPT:1,FILTER_REJECT:2,FILTER_SKIP:3};core.PositionFilter.prototype.acceptPosition=function(k){};(function(){return core.PositionFilter})();
// Input 14
-core.Utils=function(){function g(l,f){if(f&&Array.isArray(f)){l=l||[];if(!Array.isArray(l))throw"Destination is not an array.";l=l.concat(f.map(function(f){return g(null,f)}))}else if(f&&"object"===typeof f){l=l||{};if("object"!==typeof l)throw"Destination is not an object.";Object.keys(f).forEach(function(p){l[p]=g(l[p],f[p])})}else l=f;return l}this.hashString=function(g){var f=0,p,r;p=0;for(r=g.length;p<r;p+=1)f=(f<<5)-f+g.charCodeAt(p),f|=0;return f};this.mergeObjects=function(l,f){Object.keys(f).forEach(function(p){l[p]=
-g(l[p],f[p])});return l}};
+core.PositionFilterChain=function(){var k=[],h=core.PositionFilter.FilterResult.FILTER_ACCEPT,b=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(p){var d;for(d=0;d<k.length;d+=1)if(k[d].acceptPosition(p)===b)return b;return h};this.addFilter=function(b){k.push(b)}};
// Input 15
+core.zip_HuftNode=function(){this.n=this.b=this.e=0;this.t=null};core.zip_HuftList=function(){this.list=this.next=null};
+core.RawInflate=function(){function k(a,c,b,e,m,f){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var d=Array(this.BMAX+1),l,g,h,k,A,n,q,p=Array(this.BMAX+1),F,t,r,s=new core.zip_HuftNode,J=Array(this.BMAX);k=Array(this.N_MAX);var v,G=Array(this.BMAX+1),D,u,O;O=this.root=null;for(A=0;A<d.length;A++)d[A]=0;for(A=0;A<p.length;A++)p[A]=0;for(A=0;A<J.length;A++)J[A]=null;for(A=0;A<k.length;A++)k[A]=0;for(A=0;A<G.length;A++)G[A]=0;l=256<c?a[256]:this.BMAX;F=a;t=0;A=c;do d[F[t]]++,t++;
+while(0<--A);if(d[0]===c)this.root=null,this.status=this.m=0;else{for(n=1;n<=this.BMAX&&0===d[n];n++);q=n;f<n&&(f=n);for(A=this.BMAX;0!==A&&0===d[A];A--);h=A;f>A&&(f=A);for(D=1<<n;n<A;n++,D<<=1)if(D-=d[n],0>D){this.status=2;this.m=f;return}D-=d[A];if(0>D)this.status=2,this.m=f;else{d[A]+=D;G[1]=n=0;F=d;t=1;for(r=2;0<--A;)n+=F[t++],G[r++]=n;F=a;A=t=0;do n=F[t++],0!==n&&(k[G[n]++]=A);while(++A<c);c=G[h];G[0]=A=0;F=k;t=0;k=-1;v=p[0]=0;r=null;u=0;for(q=q-1+1;q<=h;q++)for(a=d[q];0<a--;){for(;q>v+p[1+k];){v+=
+p[1+k];k++;u=h-v;u=u>f?f:u;n=q-v;g=1<<n;if(g>a+1)for(g-=a+1,r=q;++n<u;){g<<=1;if(g<=d[++r])break;g-=d[r]}v+n>l&&v<l&&(n=l-v);u=1<<n;p[1+k]=n;r=Array(u);for(g=0;g<u;g++)r[g]=new core.zip_HuftNode;O=null===O?this.root=new core.zip_HuftList:O.next=new core.zip_HuftList;O.next=null;O.list=r;J[k]=r;0<k&&(G[k]=A,s.b=p[k],s.e=16+n,s.t=r,n=(A&(1<<v)-1)>>v-p[k],J[k-1][n].e=s.e,J[k-1][n].b=s.b,J[k-1][n].n=s.n,J[k-1][n].t=s.t)}s.b=q-v;t>=c?s.e=99:F[t]<b?(s.e=256>F[t]?16:15,s.n=F[t++]):(s.e=m[F[t]-b],s.n=e[F[t++]-
+b]);g=1<<q-v;for(n=A>>v;n<u;n+=g)r[n].e=s.e,r[n].b=s.b,r[n].n=s.n,r[n].t=s.t;for(n=1<<q-1;0!==(A&n);n>>=1)A^=n;for(A^=n;(A&(1<<v)-1)!==G[k];)v-=p[k],k--}this.m=p[1];this.status=0!==D&&1!==h?1:0}}}function h(b){for(;a<b;){var e=c,m;m=s.length===A?-1:s[A++];c=e|m<<a;a+=8}}function b(a){return c&J[a]}function p(b){c>>=b;a-=b}function d(a,c,e){var f,d,l;if(0===e)return 0;for(l=0;;){h(v);d=z.list[b(v)];for(f=d.e;16<f;){if(99===f)return-1;p(d.b);f-=16;h(f);d=d.t[b(f)];f=d.e}p(d.b);if(16===f)q&=32767,a[c+
+l++]=g[q++]=d.n;else{if(15===f)break;h(f);t=d.n+b(f);p(f);h(u);d=x.list[b(u)];for(f=d.e;16<f;){if(99===f)return-1;p(d.b);f-=16;h(f);d=d.t[b(f)];f=d.e}p(d.b);h(f);w=q-d.n-b(f);for(p(f);0<t&&l<e;)t--,w&=32767,q&=32767,a[c+l++]=g[q++]=g[w++]}if(l===e)return e}m=-1;return l}function n(a,c,e){var m,f,l,g,A,n,q,t=Array(316);for(m=0;m<t.length;m++)t[m]=0;h(5);n=257+b(5);p(5);h(5);q=1+b(5);p(5);h(4);m=4+b(4);p(4);if(286<n||30<q)return-1;for(f=0;f<m;f++)h(3),t[K[f]]=b(3),p(3);for(f=m;19>f;f++)t[K[f]]=0;v=
+7;f=new k(t,19,19,null,null,v);if(0!==f.status)return-1;z=f.root;v=f.m;g=n+q;for(m=l=0;m<g;)if(h(v),A=z.list[b(v)],f=A.b,p(f),f=A.n,16>f)t[m++]=l=f;else if(16===f){h(2);f=3+b(2);p(2);if(m+f>g)return-1;for(;0<f--;)t[m++]=l}else{17===f?(h(3),f=3+b(3),p(3)):(h(7),f=11+b(7),p(7));if(m+f>g)return-1;for(;0<f--;)t[m++]=0;l=0}v=9;f=new k(t,n,257,G,D,v);0===v&&(f.status=1);if(0!==f.status)return-1;z=f.root;v=f.m;for(m=0;m<q;m++)t[m]=t[m+n];u=6;f=new k(t,q,0,F,O,u);x=f.root;u=f.m;return 0===u&&257<n||0!==f.status?
+-1:d(a,c,e)}var g=[],q,r=null,l,f,c,a,m,e,t,w,z,x,v,u,s,A,J=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],G=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],D=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],F=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],O=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],K=[16,17,18,0,8,7,9,6,
+10,5,11,4,12,3,13,2,14,1,15],Z;this.inflate=function(J,K){g.length=65536;a=c=q=0;m=-1;e=!1;t=w=0;z=null;s=J;A=0;var H=new Uint8Array(new ArrayBuffer(K));a:for(var T=0,y;T<K&&(!e||-1!==m);){if(0<t){if(0!==m)for(;0<t&&T<K;)t--,w&=32767,q&=32767,H[0+T]=g[q]=g[w],T+=1,q+=1,w+=1;else{for(;0<t&&T<K;)t-=1,q&=32767,h(8),H[0+T]=g[q]=b(8),T+=1,q+=1,p(8);0===t&&(m=-1)}if(T===K)break}if(-1===m){if(e)break;h(1);0!==b(1)&&(e=!0);p(1);h(2);m=b(2);p(2);z=null;t=0}switch(m){case 0:y=H;var aa=0+T,N=K-T,R=void 0,R=
+a&7;p(R);h(16);R=b(16);p(16);h(16);if(R!==(~c&65535))y=-1;else{p(16);t=R;for(R=0;0<t&&R<N;)t--,q&=32767,h(8),y[aa+R++]=g[q++]=b(8),p(8);0===t&&(m=-1);y=R}break;case 1:if(null!==z)y=d(H,0+T,K-T);else b:{y=H;aa=0+T;N=K-T;if(null===r){for(var I=void 0,R=Array(288),I=void 0,I=0;144>I;I++)R[I]=8;for(I=144;256>I;I++)R[I]=9;for(I=256;280>I;I++)R[I]=7;for(I=280;288>I;I++)R[I]=8;f=7;I=new k(R,288,257,G,D,f);if(0!==I.status){alert("HufBuild error: "+I.status);y=-1;break b}r=I.root;f=I.m;for(I=0;30>I;I++)R[I]=
+5;Z=5;I=new k(R,30,0,F,O,Z);if(1<I.status){r=null;alert("HufBuild error: "+I.status);y=-1;break b}l=I.root;Z=I.m}z=r;x=l;v=f;u=Z;y=d(y,aa,N)}break;case 2:y=null!==z?d(H,0+T,K-T):n(H,0+T,K-T);break;default:y=-1}if(-1===y)break a;T+=y}s=new Uint8Array(new ArrayBuffer(0));return H}};
+// Input 16
+core.ScheduledTask=function(k,h){function b(){n&&(runtime.clearTimeout(d),n=!1)}function p(){b();k.apply(void 0,g);g=null}var d,n=!1,g=[];this.trigger=function(){g=Array.prototype.slice.call(arguments);n||(n=!0,d=runtime.setTimeout(p,h))};this.triggerImmediate=function(){g=Array.prototype.slice.call(arguments);p()};this.processRequests=function(){n&&p()};this.cancel=b;this.destroy=function(d){b();d()}};
+// Input 17
+/*
+
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+core.StepIterator=function(k,h){function b(){f=null;a=c=void 0}function p(){void 0===a&&(a=k.acceptPosition(h)===l);return a}function d(a,c){b();return h.setUnfilteredPosition(a,c)}function n(){f||(f=h.container());return f}function g(){void 0===c&&(c=h.unfilteredDomOffset());return c}function q(){for(b();h.nextPosition();)if(b(),p())return!0;return!1}function r(){for(b();h.previousPosition();)if(b(),p())return!0;return!1}var l=core.PositionFilter.FilterResult.FILTER_ACCEPT,f,c,a;this.isStep=p;this.setPosition=
+d;this.container=n;this.offset=g;this.nextStep=q;this.previousStep=r;this.roundToClosestStep=function(){var a=n(),c=g(),b=p();b||(b=r(),b||(d(a,c),b=q()));return b};this.roundToPreviousStep=function(){var a=p();a||(a=r());return a};this.roundToNextStep=function(){var a=p();a||(a=q());return a}};
+// Input 18
+core.UnitTest=function(){};core.UnitTest.prototype.setUp=function(){};core.UnitTest.prototype.tearDown=function(){};core.UnitTest.prototype.description=function(){};core.UnitTest.prototype.tests=function(){};core.UnitTest.prototype.asyncTests=function(){};
+core.UnitTest.provideTestAreaDiv=function(){var k=runtime.getWindow().document,h=k.getElementById("testarea");runtime.assert(!h,'Unclean test environment, found a div with id "testarea".');h=k.createElement("div");h.setAttribute("id","testarea");k.body.appendChild(h);return h};
+core.UnitTest.cleanupTestAreaDiv=function(){var k=runtime.getWindow().document,h=k.getElementById("testarea");runtime.assert(!!h&&h.parentNode===k.body,'Test environment broken, found no div with id "testarea" below body.');k.body.removeChild(h)};core.UnitTest.createOdtDocument=function(k,h){var b="<?xml version='1.0' encoding='UTF-8'?>",b=b+"<office:document";Object.keys(h).forEach(function(k){b+=" xmlns:"+k+'="'+h[k]+'"'});b+=">";b+=k;b+="</office:document>";return runtime.parseXML(b)};
+core.UnitTestLogger=function(){var k=[],h=0,b=0,p="",d="";this.startTest=function(n,g){k=[];h=0;p=n;d=g;b=(new Date).getTime()};this.endTest=function(){var n=(new Date).getTime();return{description:d,suite:[p,d],success:0===h,log:k,time:n-b}};this.debug=function(b){k.push({category:"debug",message:b})};this.fail=function(b){h+=1;k.push({category:"fail",message:b})};this.pass=function(b){k.push({category:"pass",message:b})}};
+core.UnitTestRunner=function(k,h){function b(a){r+=1;c?h.debug(a):h.fail(a)}function p(a,c){var e;try{if(a.length!==c.length)return b("array of length "+a.length+" should be "+c.length+" long"),!1;for(e=0;e<a.length;e+=1)if(a[e]!==c[e])return b(a[e]+" should be "+c[e]+" at array index "+e),!1}catch(f){return!1}return!0}function d(a,c,e){var f=a.attributes,l=f.length,g,n,h;for(g=0;g<l;g+=1)if(n=f.item(g),"xmlns"!==n.prefix&&"urn:webodf:names:steps"!==n.namespaceURI){h=c.getAttributeNS(n.namespaceURI,
+n.localName);if(!c.hasAttributeNS(n.namespaceURI,n.localName))return b("Attribute "+n.localName+" with value "+n.value+" was not present"),!1;if(h!==n.value)return b("Attribute "+n.localName+" was "+h+" should be "+n.value),!1}return e?!0:d(c,a,!0)}function n(a,c){var e,f;e=a.nodeType;f=c.nodeType;if(e!==f)return b("Nodetype '"+e+"' should be '"+f+"'"),!1;if(e===Node.TEXT_NODE){if(a.data===c.data)return!0;b("Textnode data '"+a.data+"' should be '"+c.data+"'");return!1}runtime.assert(e===Node.ELEMENT_NODE,
+"Only textnodes and elements supported.");if(a.namespaceURI!==c.namespaceURI)return b("namespace '"+a.namespaceURI+"' should be '"+c.namespaceURI+"'"),!1;if(a.localName!==c.localName)return b("localName '"+a.localName+"' should be '"+c.localName+"'"),!1;if(!d(a,c,!1))return!1;e=a.firstChild;for(f=c.firstChild;e;){if(!f)return b("Nodetype '"+e.nodeType+"' is unexpected here."),!1;if(!n(e,f))return!1;e=e.nextSibling;f=f.nextSibling}return f?(b("Nodetype '"+f.nodeType+"' is missing here."),!1):!0}function g(a,
+c){return 0===c?a===c&&1/a===1/c:a===c?!0:null===a||null===c?!1:"number"===typeof c&&isNaN(c)?"number"===typeof a&&isNaN(a):Object.prototype.toString.call(c)===Object.prototype.toString.call([])?p(a,c):"object"===typeof c&&"object"===typeof a?c.constructor===Element||c.constructor===Node?n(a,c):f(a,c):!1}function q(a,c,e){"string"===typeof c&&"string"===typeof e||h.debug("WARN: shouldBe() expects string arguments");var f,d;try{d=eval(c)}catch(l){f=l}a=eval(e);f?b(c+" should be "+a+". Threw exception "+
+f):g(d,a)?h.pass(c+" is "+e):String(typeof d)===String(typeof a)?(e=0===d&&0>1/d?"-0":String(d),b(c+" should be "+a+". Was "+e+".")):b(c+" should be "+a+" (of type "+typeof a+"). Was "+d+" (of type "+typeof d+").")}var r=0,l,f,c=!1;this.resourcePrefix=function(){return k};this.beginExpectFail=function(){l=r;c=!0};this.endExpectFail=function(){var a=l===r;c=!1;r=l;a&&(r+=1,h.fail("Expected at least one failed test, but none registered."))};f=function(a,c){var e=Object.keys(a),f=Object.keys(c);e.sort();
+f.sort();return p(e,f)&&Object.keys(a).every(function(e){var f=a[e],d=c[e];return g(f,d)?!0:(b(f+" should be "+d+" for key "+e),!1)})};this.areNodesEqual=n;this.shouldBeNull=function(a,c){q(a,c,"null")};this.shouldBeNonNull=function(a,c){var e,f;try{f=eval(c)}catch(d){e=d}e?b(c+" should be non-null. Threw exception "+e):null!==f?h.pass(c+" is non-null."):b(c+" should be non-null. Was "+f)};this.shouldBe=q;this.testFailed=b;this.countFailedTests=function(){return r};this.name=function(a){var c,b,f=
+[],d=a.length;f.length=d;for(c=0;c<d;c+=1){b=Runtime.getFunctionName(a[c])||"";if(""===b)throw"Found a function without a name.";f[c]={f:a[c],name:b}}return f}};
+core.UnitTester=function(){function k(b,d){return"<span style='color:blue;cursor:pointer' onclick='"+d+"'>"+b+"</span>"}function h(d){b.reporter&&b.reporter(d)}var b=this,p=0,d=new core.UnitTestLogger,n={},g="BrowserRuntime"===runtime.type();this.resourcePrefix="";this.reporter=function(b){var d,l;g?runtime.log("<span>Running "+k(b.description,'runTest("'+b.suite[0]+'","'+b.description+'")')+"</span>"):runtime.log("Running "+b.description);if(!b.success)for(d=0;d<b.log.length;d+=1)l=b.log[d],runtime.log(l.category,
+l.message)};this.runTests=function(q,r,l){function f(b){if(0===b.length)n[c]=e,p+=a.countFailedTests(),r();else{w=b[0].f;var g=b[0].name,k=!0===b[0].expectFail;v=a.countFailedTests();l.length&&-1===l.indexOf(g)?f(b.slice(1)):(m.setUp(),d.startTest(c,g),k&&a.beginExpectFail(),w(function(){k&&a.endExpectFail();h(d.endTest());m.tearDown();e[g]=v===a.countFailedTests();f(b.slice(1))}))}}var c=Runtime.getFunctionName(q)||"",a=new core.UnitTestRunner(b.resourcePrefix,d),m=new q(a),e={},t,w,z,x,v;if(n.hasOwnProperty(c))runtime.log("Test "+
+c+" has already run.");else{g?runtime.log("<span>Running "+k(c,'runSuite("'+c+'");')+": "+m.description()+"</span>"):runtime.log("Running "+c+": "+m.description);z=m.tests();for(t=0;t<z.length;t+=1)if(w=z[t].f,q=z[t].name,x=!0===z[t].expectFail,!l.length||-1!==l.indexOf(q)){v=a.countFailedTests();m.setUp();d.startTest(c,q);x&&a.beginExpectFail();try{w()}catch(u){a.testFailed("Unexpected exception encountered: "+u.toString()+"\n"+u.stack)}x&&a.endExpectFail();h(d.endTest());m.tearDown();e[q]=v===a.countFailedTests()}f(m.asyncTests())}};
+this.countFailedTests=function(){return p};this.results=function(){return n}};
+// Input 19
+core.Utils=function(){function k(h,b){if(b&&Array.isArray(b)){h=h||[];if(!Array.isArray(h))throw"Destination is not an array.";h=h.concat(b.map(function(b){return k(null,b)}))}else if(b&&"object"===typeof b){h=h||{};if("object"!==typeof h)throw"Destination is not an object.";Object.keys(b).forEach(function(p){h[p]=k(h[p],b[p])})}else h=b;return h}this.hashString=function(h){var b=0,k,d;k=0;for(d=h.length;k<d;k+=1)b=(b<<5)-b+h.charCodeAt(k),b|=0;return b};this.mergeObjects=function(h,b){Object.keys(b).forEach(function(p){h[p]=
+k(h[p],b[p])});return h}};
+// Input 20
/*
WebODF
@@ -225,34 +321,29 @@ g(l[p],f[p])});return l}};
Project home: http://www.webodf.org/
*/
-runtime.loadClass("core.RawInflate");runtime.loadClass("core.ByteArray");runtime.loadClass("core.ByteArrayWriter");runtime.loadClass("core.Base64");
-core.Zip=function(g,l){function f(a){var b=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,
+core.Zip=function(k,h){function b(a){var c=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,
853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,
4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,
225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,
2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,
-2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],c,e,d=a.length,q=0,q=0;c=-1;for(e=0;e<d;e+=1)q=(c^a[e])&255,q=b[q],c=c>>>8^q;return c^-1}function p(a){return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&15,a>>5&63,(a&31)<<1)}function r(a){var b=a.getFullYear();return 1980>b?0:b-1980<<
-25|a.getMonth()+1<<21|a.getDate()<<16|a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1}function n(a,b){var c,e,d,q,f,h,g,m=this;this.load=function(b){if(null!==m.data)b(null,m.data);else{var c=f+34+e+d+256;c+g>k&&(c=k-g);runtime.read(a,g,c,function(c,e){if(c||null===e)b(c,e);else a:{var d=e,k=new core.ByteArray(d),g=k.readUInt32LE(),s;if(67324752!==g)b("File entry signature is wrong."+g.toString()+" "+d.length.toString(),null);else{k.pos+=22;g=k.readUInt16LE();s=k.readUInt16LE();k.pos+=g+s;if(q){d=
-d.subarray(k.pos,k.pos+f);if(f!==d.length){b("The amount of compressed bytes read was "+d.length.toString()+" instead of "+f.toString()+" for "+m.filename+" in "+a+".",null);break a}d=A(d,h)}else d=d.subarray(k.pos,k.pos+h);h!==d.length?b("The amount of bytes read was "+d.length.toString()+" instead of "+h.toString()+" for "+m.filename+" in "+a+".",null):(m.data=d,b(null,d))}}})}};this.set=function(a,b,c,e){m.filename=a;m.data=b;m.compressed=c;m.date=e};this.error=null;b&&(c=b.readUInt32LE(),33639248!==
-c?this.error="Central directory entry has wrong signature at position "+(b.pos-4).toString()+' for file "'+a+'": '+b.data.length.toString():(b.pos+=6,q=b.readUInt16LE(),this.date=p(b.readUInt32LE()),b.readUInt32LE(),f=b.readUInt32LE(),h=b.readUInt32LE(),e=b.readUInt16LE(),d=b.readUInt16LE(),c=b.readUInt16LE(),b.pos+=8,g=b.readUInt32LE(),this.filename=runtime.byteArrayToString(b.data.subarray(b.pos,b.pos+e),"utf8"),this.data=null,b.pos+=e+d+c))}function h(a,b){if(22!==a.length)b("Central directory length should be 22.",
-w);else{var c=new core.ByteArray(a),e;e=c.readUInt32LE();101010256!==e?b("Central directory signature is wrong: "+e.toString(),w):(e=c.readUInt16LE(),0!==e?b("Zip files with non-zero disk numbers are not supported.",w):(e=c.readUInt16LE(),0!==e?b("Zip files with non-zero disk numbers are not supported.",w):(e=c.readUInt16LE(),t=c.readUInt16LE(),e!==t?b("Number of entries is inconsistent.",w):(e=c.readUInt32LE(),c=c.readUInt16LE(),c=k-22-e,runtime.read(g,c,k-c,function(a,c){if(a||null===c)b(a,w);else a:{var e=
-new core.ByteArray(c),d,f;q=[];for(d=0;d<t;d+=1){f=new n(g,e);if(f.error){b(f.error,w);break a}q[q.length]=f}b(null,w)}})))))}}function d(a,b){var c=null,e,d;for(d=0;d<q.length;d+=1)if(e=q[d],e.filename===a){c=e;break}c?c.data?b(null,c.data):c.load(b):b(a+" not found.",null)}function m(a){var b=new core.ByteArrayWriter("utf8"),c=0;b.appendArray([80,75,3,4,20,0,0,0,0,0]);a.data&&(c=a.data.length);b.appendUInt32LE(r(a.date));b.appendUInt32LE(a.data?f(a.data):0);b.appendUInt32LE(c);b.appendUInt32LE(c);
-b.appendUInt16LE(a.filename.length);b.appendUInt16LE(0);b.appendString(a.filename);a.data&&b.appendByteArray(a.data);return b}function c(a,b){var c=new core.ByteArrayWriter("utf8"),e=0;c.appendArray([80,75,1,2,20,0,20,0,0,0,0,0]);a.data&&(e=a.data.length);c.appendUInt32LE(r(a.date));c.appendUInt32LE(a.data?f(a.data):0);c.appendUInt32LE(e);c.appendUInt32LE(e);c.appendUInt16LE(a.filename.length);c.appendArray([0,0,0,0,0,0,0,0,0,0,0,0]);c.appendUInt32LE(b);c.appendString(a.filename);return c}function e(a,
-b){if(a===q.length)b(null);else{var c=q[a];null!==c.data?e(a+1,b):c.load(function(c){c?b(c):e(a+1,b)})}}function a(a,b){e(0,function(e){if(e)b(e);else{var d,f,k=new core.ByteArrayWriter("utf8"),h=[0];for(d=0;d<q.length;d+=1)k.appendByteArrayWriter(m(q[d])),h.push(k.getLength());e=k.getLength();for(d=0;d<q.length;d+=1)f=q[d],k.appendByteArrayWriter(c(f,h[d]));d=k.getLength()-e;k.appendArray([80,75,5,6,0,0,0,0]);k.appendUInt16LE(q.length);k.appendUInt16LE(q.length);k.appendUInt32LE(d);k.appendUInt32LE(e);
-k.appendArray([0,0]);a(k.getByteArray())}})}function b(b,c){a(function(a){runtime.writeFile(b,a,c)},c)}var q,k,t,A=(new core.RawInflate).inflate,w=this,x=new core.Base64;this.load=d;this.save=function(a,b,c,e){var d,f;for(d=0;d<q.length;d+=1)if(f=q[d],f.filename===a){f.set(a,b,c,e);return}f=new n(g);f.set(a,b,c,e);q.push(f)};this.remove=function(a){var b,c;for(b=0;b<q.length;b+=1)if(c=q[b],c.filename===a)return q.splice(b,1),!0;return!1};this.write=function(a){b(g,a)};this.writeAs=b;this.createByteArray=
-a;this.loadContentXmlAsFragments=function(a,b){w.loadAsString(a,function(a,c){if(a)return b.rootElementReady(a);b.rootElementReady(null,c,!0)})};this.loadAsString=function(a,b){d(a,function(a,c){if(a||null===c)return b(a,null);var e=runtime.byteArrayToString(c,"utf8");b(null,e)})};this.loadAsDOM=function(a,b){w.loadAsString(a,function(a,c){if(a||null===c)b(a,null);else{var e=(new DOMParser).parseFromString(c,"text/xml");b(null,e)}})};this.loadAsDataURL=function(a,b,c){d(a,function(a,e){if(a||!e)return c(a,
-null);var d=0,f;b||(b=80===e[1]&&78===e[2]&&71===e[3]?"image/png":255===e[0]&&216===e[1]&&255===e[2]?"image/jpeg":71===e[0]&&73===e[1]&&70===e[2]?"image/gif":"");for(f="data:"+b+";base64,";d<e.length;)f+=x.convertUTF8ArrayToBase64(e.subarray(d,Math.min(d+45E3,e.length))),d+=45E3;c(null,f)})};this.getEntries=function(){return q.slice()};k=-1;null===l?q=[]:runtime.getFileSize(g,function(a){k=a;0>k?l("File '"+g+"' cannot be read.",w):runtime.read(g,k-22,22,function(a,b){a||null===l||null===b?l(a,w):
-h(b,l)})})};
-// Input 16
-gui.Avatar=function(g,l){var f=this,p,r,n;this.setColor=function(f){r.style.borderColor=f};this.setImageUrl=function(h){f.isVisible()?r.src=h:n=h};this.isVisible=function(){return"block"===p.style.display};this.show=function(){n&&(r.src=n,n=void 0);p.style.display="block"};this.hide=function(){p.style.display="none"};this.markAsFocussed=function(f){p.className=f?"active":""};this.destroy=function(f){g.removeChild(p);f()};(function(){var f=g.ownerDocument,d=f.documentElement.namespaceURI;p=f.createElementNS(d,
-"div");r=f.createElementNS(d,"img");r.width=64;r.height=64;p.appendChild(r);p.style.width="64px";p.style.height="70px";p.style.position="absolute";p.style.top="-80px";p.style.left="-34px";p.style.display=l?"block":"none";g.appendChild(p)})()};
-// Input 17
-gui.EditInfoHandle=function(g){var l=[],f,p=g.ownerDocument,r=p.documentElement.namespaceURI;this.setEdits=function(g){l=g;var h,d,m,c;f.innerHTML="";for(g=0;g<l.length;g+=1)h=p.createElementNS(r,"div"),h.className="editInfo",d=p.createElementNS(r,"span"),d.className="editInfoColor",d.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g].memberid),m=p.createElementNS(r,"span"),m.className="editInfoAuthor",m.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g].memberid),
-c=p.createElementNS(r,"span"),c.className="editInfoTime",c.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l[g].memberid),c.innerHTML=l[g].time,h.appendChild(d),h.appendChild(m),h.appendChild(c),f.appendChild(h)};this.show=function(){f.style.display="block"};this.hide=function(){f.style.display="none"};this.destroy=function(l){g.removeChild(f);l()};f=p.createElementNS(r,"div");f.setAttribute("class","editInfoHandle");f.style.display="none";g.appendChild(f)};
-// Input 18
+2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],b,e,f=a.length,d=0,d=0;b=-1;for(e=0;e<f;e+=1)d=(b^a[e])&255,d=c[d],b=b>>>8^d;return b^-1}function p(a){return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&15,a>>5&63,(a&31)<<1)}function d(a){var c=a.getFullYear();return 1980>c?0:c-1980<<
+25|a.getMonth()+1<<21|a.getDate()<<16|a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1}function n(a,c){var b,f,d,m,l,g,n,k=this;this.load=function(c){if(null!==k.data)c(null,k.data);else{var b=l+34+f+d+256;b+n>e&&(b=e-n);runtime.read(a,n,b,function(b,e){if(b||null===e)c(b,e);else a:{var f=e,d=new core.ByteArray(f),n=d.readUInt32LE(),h;if(67324752!==n)c("File entry signature is wrong."+n.toString()+" "+f.length.toString(),null);else{d.pos+=22;n=d.readUInt16LE();h=d.readUInt16LE();d.pos+=n+h;if(m){f=
+f.subarray(d.pos,d.pos+l);if(l!==f.length){c("The amount of compressed bytes read was "+f.length.toString()+" instead of "+l.toString()+" for "+k.filename+" in "+a+".",null);break a}f=w(f,g)}else f=f.subarray(d.pos,d.pos+g);g!==f.length?c("The amount of bytes read was "+f.length.toString()+" instead of "+g.toString()+" for "+k.filename+" in "+a+".",null):(k.data=f,c(null,f))}}})}};this.set=function(a,c,b,e){k.filename=a;k.data=c;k.compressed=b;k.date=e};this.error=null;c&&(b=c.readUInt32LE(),33639248!==
+b?this.error="Central directory entry has wrong signature at position "+(c.pos-4).toString()+' for file "'+a+'": '+c.data.length.toString():(c.pos+=6,m=c.readUInt16LE(),this.date=p(c.readUInt32LE()),c.readUInt32LE(),l=c.readUInt32LE(),g=c.readUInt32LE(),f=c.readUInt16LE(),d=c.readUInt16LE(),b=c.readUInt16LE(),c.pos+=8,n=c.readUInt32LE(),this.filename=runtime.byteArrayToString(c.data.subarray(c.pos,c.pos+f),"utf8"),this.data=null,c.pos+=f+d+b))}function g(a,c){if(22!==a.length)c("Central directory length should be 22.",
+z);else{var b=new core.ByteArray(a),f;f=b.readUInt32LE();101010256!==f?c("Central directory signature is wrong: "+f.toString(),z):(f=b.readUInt16LE(),0!==f?c("Zip files with non-zero disk numbers are not supported.",z):(f=b.readUInt16LE(),0!==f?c("Zip files with non-zero disk numbers are not supported.",z):(f=b.readUInt16LE(),t=b.readUInt16LE(),f!==t?c("Number of entries is inconsistent.",z):(f=b.readUInt32LE(),b=b.readUInt16LE(),b=e-22-f,runtime.read(k,b,e-b,function(a,b){if(a||null===b)c(a,z);else a:{var e=
+new core.ByteArray(b),f,d;m=[];for(f=0;f<t;f+=1){d=new n(k,e);if(d.error){c(d.error,z);break a}m[m.length]=d}c(null,z)}})))))}}function q(a,c){var b=null,e,f;for(f=0;f<m.length;f+=1)if(e=m[f],e.filename===a){b=e;break}b?b.data?c(null,b.data):b.load(c):c(a+" not found.",null)}function r(a){var c=new core.ByteArrayWriter("utf8"),e=0;c.appendArray([80,75,3,4,20,0,0,0,0,0]);a.data&&(e=a.data.length);c.appendUInt32LE(d(a.date));c.appendUInt32LE(a.data?b(a.data):0);c.appendUInt32LE(e);c.appendUInt32LE(e);
+c.appendUInt16LE(a.filename.length);c.appendUInt16LE(0);c.appendString(a.filename);a.data&&c.appendByteArray(a.data);return c}function l(a,c){var e=new core.ByteArrayWriter("utf8"),f=0;e.appendArray([80,75,1,2,20,0,20,0,0,0,0,0]);a.data&&(f=a.data.length);e.appendUInt32LE(d(a.date));e.appendUInt32LE(a.data?b(a.data):0);e.appendUInt32LE(f);e.appendUInt32LE(f);e.appendUInt16LE(a.filename.length);e.appendArray([0,0,0,0,0,0,0,0,0,0,0,0]);e.appendUInt32LE(c);e.appendString(a.filename);return e}function f(a,
+c){if(a===m.length)c(null);else{var b=m[a];null!==b.data?f(a+1,c):b.load(function(b){b?c(b):f(a+1,c)})}}function c(a,c){f(0,function(b){if(b)c(b);else{var e,f,d=new core.ByteArrayWriter("utf8"),g=[0];for(e=0;e<m.length;e+=1)d.appendByteArrayWriter(r(m[e])),g.push(d.getLength());b=d.getLength();for(e=0;e<m.length;e+=1)f=m[e],d.appendByteArrayWriter(l(f,g[e]));e=d.getLength()-b;d.appendArray([80,75,5,6,0,0,0,0]);d.appendUInt16LE(m.length);d.appendUInt16LE(m.length);d.appendUInt32LE(e);d.appendUInt32LE(b);
+d.appendArray([0,0]);a(d.getByteArray())}})}function a(a,b){c(function(c){runtime.writeFile(a,c,b)},b)}var m,e,t,w=(new core.RawInflate).inflate,z=this,x=new core.Base64;this.load=q;this.save=function(a,c,b,e){var f,d;for(f=0;f<m.length;f+=1)if(d=m[f],d.filename===a){d.set(a,c,b,e);return}d=new n(k);d.set(a,c,b,e);m.push(d)};this.remove=function(a){var c,b;for(c=0;c<m.length;c+=1)if(b=m[c],b.filename===a)return m.splice(c,1),!0;return!1};this.write=function(c){a(k,c)};this.writeAs=a;this.createByteArray=
+c;this.loadContentXmlAsFragments=function(a,c){z.loadAsString(a,function(a,b){if(a)return c.rootElementReady(a);c.rootElementReady(null,b,!0)})};this.loadAsString=function(a,c){q(a,function(a,b){if(a||null===b)return c(a,null);var e=runtime.byteArrayToString(b,"utf8");c(null,e)})};this.loadAsDOM=function(a,c){z.loadAsString(a,function(a,b){if(a||null===b)c(a,null);else{var e=(new DOMParser).parseFromString(b,"text/xml");c(null,e)}})};this.loadAsDataURL=function(a,c,b){q(a,function(a,e){if(a||!e)return b(a,
+null);var f=0,d;c||(c=80===e[1]&&78===e[2]&&71===e[3]?"image/png":255===e[0]&&216===e[1]&&255===e[2]?"image/jpeg":71===e[0]&&73===e[1]&&70===e[2]?"image/gif":"");for(d="data:"+c+";base64,";f<e.length;)d+=x.convertUTF8ArrayToBase64(e.subarray(f,Math.min(f+45E3,e.length))),f+=45E3;b(null,d)})};this.getEntries=function(){return m.slice()};e=-1;null===h?m=[]:runtime.getFileSize(k,function(a){e=a;0>e?h("File '"+k+"' cannot be read.",z):runtime.read(k,e-22,22,function(a,c){a||null===h||null===c?h(a,z):
+g(c,h)})})};
+// Input 21
+xmldom.LSSerializerFilter=function(){};xmldom.LSSerializerFilter.prototype.acceptNode=function(k){};
+// Input 22
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -287,9 +378,8 @@ c=p.createElementNS(r,"span"),c.className="editInfoTime",c.setAttributeNS("urn:w
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-gui.KeyboardHandler=function(){function g(f,g){g||(g=l.None);return f+":"+g}var l=gui.KeyboardHandler.Modifier,f=null,p={};this.setDefault=function(g){f=g};this.bind=function(f,l,h){f=g(f,l);runtime.assert(!1===p.hasOwnProperty(f),"tried to overwrite the callback handler of key combo: "+f);p[f]=h};this.unbind=function(f,l){var h=g(f,l);delete p[h]};this.reset=function(){f=null;p={}};this.handleEvent=function(r){var n=r.keyCode,h=l.None;r.metaKey&&(h|=l.Meta);r.ctrlKey&&(h|=l.Ctrl);r.altKey&&(h|=l.Alt);
-r.shiftKey&&(h|=l.Shift);n=g(n,h);n=p[n];h=!1;n?h=n():null!==f&&(h=f(r));h&&(r.preventDefault?r.preventDefault():r.returnValue=!1)}};gui.KeyboardHandler.Modifier={None:0,Meta:1,Ctrl:2,Alt:4,CtrlAlt:6,Shift:8,MetaShift:9,CtrlShift:10,AltShift:12};gui.KeyboardHandler.KeyCode={Backspace:8,Tab:9,Clear:12,Enter:13,End:35,Home:36,Left:37,Up:38,Right:39,Down:40,Delete:46,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90};(function(){return gui.KeyboardHandler})();
-// Input 19
+odf.OdfNodeFilter=function(){this.acceptNode=function(k){return"http://www.w3.org/1999/xhtml"===k.namespaceURI?NodeFilter.FILTER_SKIP:k.namespaceURI&&k.namespaceURI.match(/^urn:webodf:/)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}};
+// Input 23
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -331,9 +421,17 @@ odf.Namespaces={namespaceMap:{db:"urn:oasis:names:tc:opendocument:xmlns:database
office:"urn:oasis:names:tc:opendocument:xmlns:office:1.0",presentation:"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",style:"urn:oasis:names:tc:opendocument:xmlns:style:1.0",svg:"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",table:"urn:oasis:names:tc:opendocument:xmlns:table:1.0",text:"urn:oasis:names:tc:opendocument:xmlns:text:1.0",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"},prefixMap:{},dbns:"urn:oasis:names:tc:opendocument:xmlns:database:1.0",
dcns:"http://purl.org/dc/elements/1.1/",dr3dns:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",drawns:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",chartns:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0",fons:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",formns:"urn:oasis:names:tc:opendocument:xmlns:form:1.0",metans:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0",numberns:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",officens:"urn:oasis:names:tc:opendocument:xmlns:office:1.0",
presentationns:"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",stylens:"urn:oasis:names:tc:opendocument:xmlns:style:1.0",svgns:"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",tablens:"urn:oasis:names:tc:opendocument:xmlns:table:1.0",textns:"urn:oasis:names:tc:opendocument:xmlns:text:1.0",xlinkns:"http://www.w3.org/1999/xlink",xmlns:"http://www.w3.org/XML/1998/namespace"};
-(function(){var g=odf.Namespaces.namespaceMap,l=odf.Namespaces.prefixMap,f;for(f in g)g.hasOwnProperty(f)&&(l[g[f]]=f)})();odf.Namespaces.forEachPrefix=function(g){var l=odf.Namespaces.namespaceMap,f;for(f in l)l.hasOwnProperty(f)&&g(f,l[f])};odf.Namespaces.lookupNamespaceURI=function(g){var l=null;odf.Namespaces.namespaceMap.hasOwnProperty(g)&&(l=odf.Namespaces.namespaceMap[g]);return l};odf.Namespaces.lookupPrefix=function(g){var l=odf.Namespaces.prefixMap;return l.hasOwnProperty(g)?l[g]:null};
+(function(){var k=odf.Namespaces.namespaceMap,h=odf.Namespaces.prefixMap,b;for(b in k)k.hasOwnProperty(b)&&(h[k[b]]=b)})();odf.Namespaces.forEachPrefix=function(k){var h=odf.Namespaces.namespaceMap,b;for(b in h)h.hasOwnProperty(b)&&k(b,h[b])};odf.Namespaces.lookupNamespaceURI=function(k){var h=null;odf.Namespaces.namespaceMap.hasOwnProperty(k)&&(h=odf.Namespaces.namespaceMap[k]);return h};odf.Namespaces.lookupPrefix=function(k){var h=odf.Namespaces.prefixMap;return h.hasOwnProperty(k)?h[k]:null};
odf.Namespaces.lookupNamespaceURI.lookupNamespaceURI=odf.Namespaces.lookupNamespaceURI;
-// Input 20
+// Input 24
+xmldom.XPathIterator=function(){};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){};
+function createXPathSingleton(){function k(b,c,a){return-1!==b&&(b<c||-1===c)&&(b<a||-1===a)}function h(b){for(var c=[],a=0,d=b.length,e;a<d;){var g=b,n=d,h=c,q="",p=[],r=g.indexOf("[",a),s=g.indexOf("/",a),A=g.indexOf("=",a);k(s,r,A)?(q=g.substring(a,s),a=s+1):k(r,s,A)?(q=g.substring(a,r),a=l(g,r,p)):k(A,s,r)?(q=g.substring(a,A),a=A):(q=g.substring(a,n),a=n);h.push({location:q,predicates:p});if(a<d&&"="===b[a]){e=b.substring(a+1,d);if(2<e.length&&("'"===e[0]||'"'===e[0]))e=e.slice(1,e.length-1);
+else try{e=parseInt(e,10)}catch(J){}a=d}}return{steps:c,value:e}}function b(){var b=null,c=!1;this.setNode=function(a){b=a};this.reset=function(){c=!1};this.next=function(){var a=c?null:b;c=!0;return a}}function p(b,c,a){this.reset=function(){b.reset()};this.next=function(){for(var d=b.next();d;){d.nodeType===Node.ELEMENT_NODE&&(d=d.getAttributeNodeNS(c,a));if(d)break;d=b.next()}return d}}function d(b,c){var a=b.next(),d=null;this.reset=function(){b.reset();a=b.next();d=null};this.next=function(){for(;a;){if(d)if(c&&
+d.firstChild)d=d.firstChild;else{for(;!d.nextSibling&&d!==a;)d=d.parentNode;d===a?a=b.next():d=d.nextSibling}else{do(d=a.firstChild)||(a=b.next());while(a&&!d)}if(d&&d.nodeType===Node.ELEMENT_NODE)return d}return null}}function n(b,c){this.reset=function(){b.reset()};this.next=function(){for(var a=b.next();a&&!c(a);)a=b.next();return a}}function g(b,c,a){c=c.split(":",2);var d=a(c[0]),e=c[1];return new n(b,function(a){return a.localName===e&&a.namespaceURI===d})}function q(d,c,a){var m=new b,e=r(m,
+c,a),g=c.value;return void 0===g?new n(d,function(a){m.setNode(a);e.reset();return null!==e.next()}):new n(d,function(a){m.setNode(a);e.reset();return(a=e.next())?a.nodeValue===g:!1})}var r,l;l=function(b,c,a){for(var d=c,e=b.length,g=0;d<e;)"]"===b[d]?(g-=1,0>=g&&a.push(h(b.substring(c,d)))):"["===b[d]&&(0>=g&&(c=d+1),g+=1),d+=1;return d};r=function(b,c,a){var m,e,l,n;for(m=0;m<c.steps.length;m+=1){l=c.steps[m];e=l.location;if(""===e)b=new d(b,!1);else if("@"===e[0]){e=e.substr(1).split(":",2);n=
+a(e[0]);if(!n)throw"No namespace associated with the prefix "+e[0];b=new p(b,n,e[1])}else"."!==e&&(b=new d(b,!1),-1!==e.indexOf(":")&&(b=g(b,e,a)));for(e=0;e<l.predicates.length;e+=1)n=l.predicates[e],b=q(b,n,a)}return b};return{getODFElementsWithXPath:function(d,c,a){var m=d.ownerDocument,e=[],g=null;if(m&&"function"===typeof m.evaluate)for(a=m.evaluate(c,d,a,XPathResult.UNORDERED_NODE_ITERATOR_TYPE,null),g=a.iterateNext();null!==g;)g.nodeType===Node.ELEMENT_NODE&&e.push(g),g=a.iterateNext();else{e=
+new b;e.setNode(d);d=h(c);e=r(e,d,a);d=[];for(a=e.next();a;)d.push(a),a=e.next();e=d}return e}}}xmldom.XPath=createXPathSingleton();
+// Input 25
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -371,24 +469,44 @@ odf.Namespaces.lookupNamespaceURI.lookupNamespaceURI=odf.Namespaces.lookupNamesp
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");runtime.loadClass("odf.Namespaces");
-odf.OdfUtils=function(){function g(a){return"image"===(a&&a.localName)&&a.namespaceURI===y}function l(a){return null!==a&&a.nodeType===Node.ELEMENT_NODE&&"frame"===a.localName&&a.namespaceURI===y&&"as-char"===a.getAttributeNS(H,"anchor-type")}function f(a){var b;(b="annotation"===(a&&a.localName)&&a.namespaceURI===odf.Namespaces.officens)||(b="div"===(a&&a.localName)&&"annotationWrapper"===a.className);return b}function p(a){var b=a&&a.localName;return("p"===b||"h"===b)&&a.namespaceURI===H}function r(a){for(;a&&
-!p(a);)a=a.parentNode;return a}function n(a){return/^[ \t\r\n]+$/.test(a)}function h(a){if(null===a||a.nodeType!==Node.ELEMENT_NODE)return!1;var b=a.localName;return/^(span|p|h|a|meta)$/.test(b)&&a.namespaceURI===H||"span"===b&&"annotationHighlight"===a.className}function d(a){var b=a&&a.localName,c=!1;b&&(a=a.namespaceURI,a===H&&(c="s"===b||"tab"===b||"line-break"===b));return c}function m(a){return d(a)||l(a)||f(a)}function c(a){var b=a&&a.localName,c=!1;b&&(a=a.namespaceURI,a===H&&(c="s"===b));
-return c}function e(a){for(;null!==a.firstChild&&h(a);)a=a.firstChild;return a}function a(a){for(;null!==a.lastChild&&h(a);)a=a.lastChild;return a}function b(b){for(;!p(b)&&null===b.previousSibling;)b=b.parentNode;return p(b)?null:a(b.previousSibling)}function q(a){for(;!p(a)&&null===a.nextSibling;)a=a.parentNode;return p(a)?null:e(a.nextSibling)}function k(a){for(var e=!1;a;)if(a.nodeType===Node.TEXT_NODE)if(0===a.length)a=b(a);else return!n(a.data.substr(a.length-1,1));else m(a)?(e=!1===c(a),a=
-null):a=b(a);return e}function t(a){var b=!1,c;for(a=a&&e(a);a;){c=a.nodeType===Node.TEXT_NODE?a.length:0;if(0<c&&!n(a.data)){b=!0;break}if(m(a)){b=!0;break}a=q(a)}return b}function A(a,b){return n(a.data.substr(b))?!t(q(a)):!1}function w(a,c){var e=a.data,d;if(!n(e[c])||m(a.parentNode))return!1;0<c?n(e[c-1])||(d=!0):k(b(a))&&(d=!0);return!0===d?A(a,c)?!1:!0:!1}function x(a){return(a=/(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/.exec(a))?
-{value:parseFloat(a[1]),unit:a[3]}:null}function v(a){return(a=x(a))&&(0>a.value||"%"===a.unit)?null:a}function u(a){return(a=x(a))&&"%"!==a.unit?null:a}function s(a){switch(a.namespaceURI){case odf.Namespaces.drawns:case odf.Namespaces.svgns:case odf.Namespaces.dr3dns:return!1;case odf.Namespaces.textns:switch(a.localName){case "note-body":case "ruby-text":return!1}break;case odf.Namespaces.officens:switch(a.localName){case "annotation":case "binary-data":case "event-listeners":return!1}break;default:switch(a.localName){case "editinfo":return!1}}return!0}
-var H=odf.Namespaces.textns,y=odf.Namespaces.drawns,B=/^\s*$/,L=new core.DomUtils;this.isImage=g;this.isCharacterFrame=l;this.isInlineRoot=f;this.isTextSpan=function(a){return"span"===(a&&a.localName)&&a.namespaceURI===H};this.isParagraph=p;this.getParagraphElement=r;this.isWithinTrackedChanges=function(a,b){for(;a&&a!==b;){if(a.namespaceURI===H&&"tracked-changes"===a.localName)return!0;a=a.parentNode}return!1};this.isListItem=function(a){return"list-item"===(a&&a.localName)&&a.namespaceURI===H};
-this.isLineBreak=function(a){return"line-break"===(a&&a.localName)&&a.namespaceURI===H};this.isODFWhitespace=n;this.isGroupingElement=h;this.isCharacterElement=d;this.isAnchoredAsCharacterElement=m;this.isSpaceElement=c;this.firstChild=e;this.lastChild=a;this.previousNode=b;this.nextNode=q;this.scanLeftForNonSpace=k;this.lookLeftForCharacter=function(a){var c,e=c=0;a.nodeType===Node.TEXT_NODE&&(e=a.length);0<e?(c=a.data,c=n(c.substr(e-1,1))?1===e?k(b(a))?2:0:n(c.substr(e-2,1))?0:2:1):m(a)&&(c=1);
-return c};this.lookRightForCharacter=function(a){var b=!1,c=0;a&&a.nodeType===Node.TEXT_NODE&&(c=a.length);0<c?b=!n(a.data.substr(0,1)):m(a)&&(b=!0);return b};this.scanLeftForAnyCharacter=function(c){var e=!1,d;for(c=c&&a(c);c;){d=c.nodeType===Node.TEXT_NODE?c.length:0;if(0<d&&!n(c.data)){e=!0;break}if(m(c)){e=!0;break}c=b(c)}return e};this.scanRightForAnyCharacter=t;this.isTrailingWhitespace=A;this.isSignificantWhitespace=w;this.isDowngradableSpaceElement=function(a){return a.namespaceURI===H&&"s"===
-a.localName?k(b(a))&&t(q(a)):!1};this.getFirstNonWhitespaceChild=function(a){for(a=a&&a.firstChild;a&&a.nodeType===Node.TEXT_NODE&&B.test(a.nodeValue);)a=a.nextSibling;return a};this.parseLength=x;this.parseNonNegativeLength=v;this.parseFoFontSize=function(a){var b;b=(b=x(a))&&(0>=b.value||"%"===b.unit)?null:b;return b||u(a)};this.parseFoLineHeight=function(a){return v(a)||u(a)};this.getImpactedParagraphs=function(a){var b,c,e;b=a.commonAncestorContainer;var d=[],f=[];for(b.nodeType===Node.ELEMENT_NODE&&
-(d=L.getElementsByTagNameNS(b,H,"p").concat(L.getElementsByTagNameNS(b,H,"h")));b&&!p(b);)b=b.parentNode;b&&d.push(b);c=d.length;for(b=0;b<c;b+=1)e=d[b],L.rangeIntersectsNode(a,e)&&f.push(e);return f};this.getTextNodes=function(a,b){var c=a.startContainer.ownerDocument.createRange(),e;e=L.getNodesInRange(a,function(e){c.selectNodeContents(e);if(e.nodeType===Node.TEXT_NODE){if(b&&L.rangesIntersect(a,c)||L.containsRange(a,c))return Boolean(r(e)&&(!n(e.textContent)||w(e,0)))?NodeFilter.FILTER_ACCEPT:
-NodeFilter.FILTER_REJECT}else if(L.rangesIntersect(a,c)&&s(e))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});c.detach();return e};this.getTextElements=function(a,b,c){var e=a.startContainer.ownerDocument.createRange(),f;f=L.getNodesInRange(a,function(f){e.selectNodeContents(f);if(d(f.parentNode))return NodeFilter.FILTER_REJECT;if(f.nodeType===Node.TEXT_NODE){if(b&&L.rangesIntersect(a,e)||L.containsRange(a,e))if(c||Boolean(r(f)&&(!n(f.textContent)||w(f,0))))return NodeFilter.FILTER_ACCEPT}else if(m(f)){if(b&&
-L.rangesIntersect(a,e)||L.containsRange(a,e))return NodeFilter.FILTER_ACCEPT}else if(s(f)||h(f))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});e.detach();return f};this.getParagraphElements=function(a){var b=a.startContainer.ownerDocument.createRange(),c;c=L.getNodesInRange(a,function(c){b.selectNodeContents(c);if(p(c)){if(L.rangesIntersect(a,b))return NodeFilter.FILTER_ACCEPT}else if(s(c)||h(c))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});b.detach();return c};
-this.getImageElements=function(a){var b=a.startContainer.ownerDocument.createRange(),c;c=L.getNodesInRange(a,function(c){b.selectNodeContents(c);return g(c)&&L.containsRange(a,b)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP});b.detach();return c}};
-// Input 21
+odf.StyleInfo=function(){function k(a,c){var b,e,d,f,m,g=0;if(b=G[a.localName])if(d=b[a.namespaceURI])g=d.length;for(b=0;b<g;b+=1)e=d[b],f=e.ns,m=e.localname,(e=a.getAttributeNS(f,m))&&a.setAttributeNS(f,A[f]+m,c+e);for(d=a.firstElementChild;d;)k(d,c),d=d.nextElementSibling}function h(a,c){var b,e,d,f,m,g=0;if(b=G[a.localName])if(d=b[a.namespaceURI])g=d.length;for(b=0;b<g;b+=1)if(e=d[b],f=e.ns,m=e.localname,e=a.getAttributeNS(f,m))e=e.replace(c,""),a.setAttributeNS(f,A[f]+m,e);for(d=a.firstElementChild;d;)h(d,
+c),d=d.nextElementSibling}function b(a,c){var b,e,d,f,m,g=0;if(b=G[a.localName])if(d=b[a.namespaceURI])g=d.length;for(b=0;b<g;b+=1)if(f=d[b],e=f.ns,m=f.localname,e=a.getAttributeNS(e,m))c=c||{},f=f.keyname,c.hasOwnProperty(f)?c[f][e]=1:(m={},m[e]=1,c[f]=m);return c}function p(a,c){var e,d;b(a,c);for(e=a.firstChild;e;)e.nodeType===Node.ELEMENT_NODE&&(d=e,p(d,c)),e=e.nextSibling}function d(a,c,b){this.key=a;this.name=c;this.family=b;this.requires={}}function n(a,c,b){var e=a+'"'+c,f=b[e];f||(f=b[e]=
+new d(e,a,c));return f}function g(a,c,b){var e,d,f,m,l,k=0;e=a.getAttributeNS(v,"name");m=a.getAttributeNS(v,"family");e&&m&&(c=n(e,m,b));if(c){if(e=G[a.localName])if(f=e[a.namespaceURI])k=f.length;for(e=0;e<k;e+=1)if(m=f[e],d=m.ns,l=m.localname,d=a.getAttributeNS(d,l))m=m.keyname,m=n(d,m,b),c.requires[m.key]=m}for(a=a.firstElementChild;a;)g(a,c,b),a=a.nextElementSibling;return b}function q(a,c){var b=c[a.family];b||(b=c[a.family]={});b[a.name]=1;Object.keys(a.requires).forEach(function(b){q(a.requires[b],
+c)})}function r(a,c){var b=g(a,null,{});Object.keys(b).forEach(function(a){a=b[a];var e=c[a.family];e&&e.hasOwnProperty(a.name)&&q(a,c)})}function l(a,c){function b(c){(c=f.getAttributeNS(v,c))&&(a[c]=!0)}var e=["font-name","font-name-asian","font-name-complex"],d,f;for(d=c&&c.firstElementChild;d;)f=d,e.forEach(b),l(a,f),d=d.nextElementSibling}function f(a,c){function b(a){var e=m.getAttributeNS(v,a);e&&c.hasOwnProperty(e)&&m.setAttributeNS(v,"style:"+a,c[e])}var e=["font-name","font-name-asian",
+"font-name-complex"],d,m;for(d=a&&a.firstElementChild;d;)m=d,e.forEach(b),f(m,c),d=d.nextElementSibling}var c=odf.Namespaces.chartns,a=odf.Namespaces.dbns,m=odf.Namespaces.dr3dns,e=odf.Namespaces.drawns,t=odf.Namespaces.formns,w=odf.Namespaces.numberns,z=odf.Namespaces.officens,x=odf.Namespaces.presentationns,v=odf.Namespaces.stylens,u=odf.Namespaces.tablens,s=odf.Namespaces.textns,A={"urn:oasis:names:tc:opendocument:xmlns:chart:1.0":"chart:","urn:oasis:names:tc:opendocument:xmlns:database:1.0":"db:",
+"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0":"dr3d:","urn:oasis:names:tc:opendocument:xmlns:drawing:1.0":"draw:","urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0":"fo:","urn:oasis:names:tc:opendocument:xmlns:form:1.0":"form:","urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0":"number:","urn:oasis:names:tc:opendocument:xmlns:office:1.0":"office:","urn:oasis:names:tc:opendocument:xmlns:presentation:1.0":"presentation:","urn:oasis:names:tc:opendocument:xmlns:style:1.0":"style:","urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0":"svg:",
+"urn:oasis:names:tc:opendocument:xmlns:table:1.0":"table:","urn:oasis:names:tc:opendocument:xmlns:text:1.0":"chart:","http://www.w3.org/XML/1998/namespace":"xml:"},J={text:[{ens:v,en:"tab-stop",ans:v,a:"leader-text-style"},{ens:v,en:"drop-cap",ans:v,a:"style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-body-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-style-name"},{ens:s,en:"a",ans:s,a:"style-name"},{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens:s,en:"linenumbering-configuration",
+ans:s,a:"style-name"},{ens:s,en:"list-level-style-number",ans:s,a:"style-name"},{ens:s,en:"ruby-text",ans:s,a:"style-name"},{ens:s,en:"span",ans:s,a:"style-name"},{ens:s,en:"a",ans:s,a:"visited-style-name"},{ens:v,en:"text-properties",ans:v,a:"text-line-through-text-style"},{ens:s,en:"alphabetical-index-source",ans:s,a:"main-entry-style-name"},{ens:s,en:"index-entry-bibliography",ans:s,a:"style-name"},{ens:s,en:"index-entry-chapter",ans:s,a:"style-name"},{ens:s,en:"index-entry-link-end",ans:s,a:"style-name"},
+{ens:s,en:"index-entry-link-start",ans:s,a:"style-name"},{ens:s,en:"index-entry-page-number",ans:s,a:"style-name"},{ens:s,en:"index-entry-span",ans:s,a:"style-name"},{ens:s,en:"index-entry-tab-stop",ans:s,a:"style-name"},{ens:s,en:"index-entry-text",ans:s,a:"style-name"},{ens:s,en:"index-title-template",ans:s,a:"style-name"},{ens:s,en:"list-level-style-bullet",ans:s,a:"style-name"},{ens:s,en:"outline-level-style",ans:s,a:"style-name"}],paragraph:[{ens:e,en:"caption",ans:e,a:"text-style-name"},{ens:e,
+en:"circle",ans:e,a:"text-style-name"},{ens:e,en:"connector",ans:e,a:"text-style-name"},{ens:e,en:"control",ans:e,a:"text-style-name"},{ens:e,en:"custom-shape",ans:e,a:"text-style-name"},{ens:e,en:"ellipse",ans:e,a:"text-style-name"},{ens:e,en:"frame",ans:e,a:"text-style-name"},{ens:e,en:"line",ans:e,a:"text-style-name"},{ens:e,en:"measure",ans:e,a:"text-style-name"},{ens:e,en:"path",ans:e,a:"text-style-name"},{ens:e,en:"polygon",ans:e,a:"text-style-name"},{ens:e,en:"polyline",ans:e,a:"text-style-name"},
+{ens:e,en:"rect",ans:e,a:"text-style-name"},{ens:e,en:"regular-polygon",ans:e,a:"text-style-name"},{ens:z,en:"annotation",ans:e,a:"text-style-name"},{ens:t,en:"column",ans:t,a:"text-style-name"},{ens:v,en:"style",ans:v,a:"next-style-name"},{ens:u,en:"body",ans:u,a:"paragraph-style-name"},{ens:u,en:"even-columns",ans:u,a:"paragraph-style-name"},{ens:u,en:"even-rows",ans:u,a:"paragraph-style-name"},{ens:u,en:"first-column",ans:u,a:"paragraph-style-name"},{ens:u,en:"first-row",ans:u,a:"paragraph-style-name"},
+{ens:u,en:"last-column",ans:u,a:"paragraph-style-name"},{ens:u,en:"last-row",ans:u,a:"paragraph-style-name"},{ens:u,en:"odd-columns",ans:u,a:"paragraph-style-name"},{ens:u,en:"odd-rows",ans:u,a:"paragraph-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"default-style-name"},{ens:s,en:"alphabetical-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"bibliography-entry-template",ans:s,a:"style-name"},{ens:s,en:"h",ans:s,a:"style-name"},{ens:s,en:"illustration-index-entry-template",ans:s,a:"style-name"},
+{ens:s,en:"index-source-style",ans:s,a:"style-name"},{ens:s,en:"object-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"p",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-of-content-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"user-index-entry-template",ans:s,a:"style-name"},{ens:v,en:"page-layout-properties",ans:v,a:"register-truth-ref-style-name"}],chart:[{ens:c,en:"axis",ans:c,
+a:"style-name"},{ens:c,en:"chart",ans:c,a:"style-name"},{ens:c,en:"data-label",ans:c,a:"style-name"},{ens:c,en:"data-point",ans:c,a:"style-name"},{ens:c,en:"equation",ans:c,a:"style-name"},{ens:c,en:"error-indicator",ans:c,a:"style-name"},{ens:c,en:"floor",ans:c,a:"style-name"},{ens:c,en:"footer",ans:c,a:"style-name"},{ens:c,en:"grid",ans:c,a:"style-name"},{ens:c,en:"legend",ans:c,a:"style-name"},{ens:c,en:"mean-value",ans:c,a:"style-name"},{ens:c,en:"plot-area",ans:c,a:"style-name"},{ens:c,en:"regression-curve",
+ans:c,a:"style-name"},{ens:c,en:"series",ans:c,a:"style-name"},{ens:c,en:"stock-gain-marker",ans:c,a:"style-name"},{ens:c,en:"stock-loss-marker",ans:c,a:"style-name"},{ens:c,en:"stock-range-line",ans:c,a:"style-name"},{ens:c,en:"subtitle",ans:c,a:"style-name"},{ens:c,en:"title",ans:c,a:"style-name"},{ens:c,en:"wall",ans:c,a:"style-name"}],section:[{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens:s,en:"bibliography",ans:s,a:"style-name"},{ens:s,en:"illustration-index",ans:s,a:"style-name"},
+{ens:s,en:"index-title",ans:s,a:"style-name"},{ens:s,en:"object-index",ans:s,a:"style-name"},{ens:s,en:"section",ans:s,a:"style-name"},{ens:s,en:"table-of-content",ans:s,a:"style-name"},{ens:s,en:"table-index",ans:s,a:"style-name"},{ens:s,en:"user-index",ans:s,a:"style-name"}],ruby:[{ens:s,en:"ruby",ans:s,a:"style-name"}],table:[{ens:a,en:"query",ans:a,a:"style-name"},{ens:a,en:"table-representation",ans:a,a:"style-name"},{ens:u,en:"background",ans:u,a:"style-name"},{ens:u,en:"table",ans:u,a:"style-name"}],
+"table-column":[{ens:a,en:"column",ans:a,a:"style-name"},{ens:u,en:"table-column",ans:u,a:"style-name"}],"table-row":[{ens:a,en:"query",ans:a,a:"default-row-style-name"},{ens:a,en:"table-representation",ans:a,a:"default-row-style-name"},{ens:u,en:"table-row",ans:u,a:"style-name"}],"table-cell":[{ens:a,en:"column",ans:a,a:"default-cell-style-name"},{ens:u,en:"table-column",ans:u,a:"default-cell-style-name"},{ens:u,en:"table-row",ans:u,a:"default-cell-style-name"},{ens:u,en:"body",ans:u,a:"style-name"},
+{ens:u,en:"covered-table-cell",ans:u,a:"style-name"},{ens:u,en:"even-columns",ans:u,a:"style-name"},{ens:u,en:"covered-table-cell",ans:u,a:"style-name"},{ens:u,en:"even-columns",ans:u,a:"style-name"},{ens:u,en:"even-rows",ans:u,a:"style-name"},{ens:u,en:"first-column",ans:u,a:"style-name"},{ens:u,en:"first-row",ans:u,a:"style-name"},{ens:u,en:"last-column",ans:u,a:"style-name"},{ens:u,en:"last-row",ans:u,a:"style-name"},{ens:u,en:"odd-columns",ans:u,a:"style-name"},{ens:u,en:"odd-rows",ans:u,a:"style-name"},
+{ens:u,en:"table-cell",ans:u,a:"style-name"}],graphic:[{ens:m,en:"cube",ans:e,a:"style-name"},{ens:m,en:"extrude",ans:e,a:"style-name"},{ens:m,en:"rotate",ans:e,a:"style-name"},{ens:m,en:"scene",ans:e,a:"style-name"},{ens:m,en:"sphere",ans:e,a:"style-name"},{ens:e,en:"caption",ans:e,a:"style-name"},{ens:e,en:"circle",ans:e,a:"style-name"},{ens:e,en:"connector",ans:e,a:"style-name"},{ens:e,en:"control",ans:e,a:"style-name"},{ens:e,en:"custom-shape",ans:e,a:"style-name"},{ens:e,en:"ellipse",ans:e,a:"style-name"},
+{ens:e,en:"frame",ans:e,a:"style-name"},{ens:e,en:"g",ans:e,a:"style-name"},{ens:e,en:"line",ans:e,a:"style-name"},{ens:e,en:"measure",ans:e,a:"style-name"},{ens:e,en:"page-thumbnail",ans:e,a:"style-name"},{ens:e,en:"path",ans:e,a:"style-name"},{ens:e,en:"polygon",ans:e,a:"style-name"},{ens:e,en:"polyline",ans:e,a:"style-name"},{ens:e,en:"rect",ans:e,a:"style-name"},{ens:e,en:"regular-polygon",ans:e,a:"style-name"},{ens:z,en:"annotation",ans:e,a:"style-name"}],presentation:[{ens:m,en:"cube",ans:x,
+a:"style-name"},{ens:m,en:"extrude",ans:x,a:"style-name"},{ens:m,en:"rotate",ans:x,a:"style-name"},{ens:m,en:"scene",ans:x,a:"style-name"},{ens:m,en:"sphere",ans:x,a:"style-name"},{ens:e,en:"caption",ans:x,a:"style-name"},{ens:e,en:"circle",ans:x,a:"style-name"},{ens:e,en:"connector",ans:x,a:"style-name"},{ens:e,en:"control",ans:x,a:"style-name"},{ens:e,en:"custom-shape",ans:x,a:"style-name"},{ens:e,en:"ellipse",ans:x,a:"style-name"},{ens:e,en:"frame",ans:x,a:"style-name"},{ens:e,en:"g",ans:x,a:"style-name"},
+{ens:e,en:"line",ans:x,a:"style-name"},{ens:e,en:"measure",ans:x,a:"style-name"},{ens:e,en:"page-thumbnail",ans:x,a:"style-name"},{ens:e,en:"path",ans:x,a:"style-name"},{ens:e,en:"polygon",ans:x,a:"style-name"},{ens:e,en:"polyline",ans:x,a:"style-name"},{ens:e,en:"rect",ans:x,a:"style-name"},{ens:e,en:"regular-polygon",ans:x,a:"style-name"},{ens:z,en:"annotation",ans:x,a:"style-name"}],"drawing-page":[{ens:e,en:"page",ans:e,a:"style-name"},{ens:x,en:"notes",ans:e,a:"style-name"},{ens:v,en:"handout-master",
+ans:e,a:"style-name"},{ens:v,en:"master-page",ans:e,a:"style-name"}],"list-style":[{ens:s,en:"list",ans:s,a:"style-name"},{ens:s,en:"numbered-paragraph",ans:s,a:"style-name"},{ens:s,en:"list-item",ans:s,a:"style-override"},{ens:v,en:"style",ans:v,a:"list-style-name"}],data:[{ens:v,en:"style",ans:v,a:"data-style-name"},{ens:v,en:"style",ans:v,a:"percentage-data-style-name"},{ens:x,en:"date-time-decl",ans:v,a:"data-style-name"},{ens:s,en:"creation-date",ans:v,a:"data-style-name"},{ens:s,en:"creation-time",
+ans:v,a:"data-style-name"},{ens:s,en:"database-display",ans:v,a:"data-style-name"},{ens:s,en:"date",ans:v,a:"data-style-name"},{ens:s,en:"editing-duration",ans:v,a:"data-style-name"},{ens:s,en:"expression",ans:v,a:"data-style-name"},{ens:s,en:"meta-field",ans:v,a:"data-style-name"},{ens:s,en:"modification-date",ans:v,a:"data-style-name"},{ens:s,en:"modification-time",ans:v,a:"data-style-name"},{ens:s,en:"print-date",ans:v,a:"data-style-name"},{ens:s,en:"print-time",ans:v,a:"data-style-name"},{ens:s,
+en:"table-formula",ans:v,a:"data-style-name"},{ens:s,en:"time",ans:v,a:"data-style-name"},{ens:s,en:"user-defined",ans:v,a:"data-style-name"},{ens:s,en:"user-field-get",ans:v,a:"data-style-name"},{ens:s,en:"user-field-input",ans:v,a:"data-style-name"},{ens:s,en:"variable-get",ans:v,a:"data-style-name"},{ens:s,en:"variable-input",ans:v,a:"data-style-name"},{ens:s,en:"variable-set",ans:v,a:"data-style-name"}],"page-layout":[{ens:x,en:"notes",ans:v,a:"page-layout-name"},{ens:v,en:"handout-master",ans:v,
+a:"page-layout-name"},{ens:v,en:"master-page",ans:v,a:"page-layout-name"}]},G,D=xmldom.XPath;this.collectUsedFontFaces=l;this.changeFontFaceNames=f;this.UsedStyleList=function(a,c){var b={};this.uses=function(a){var c=a.localName,d=a.getAttributeNS(e,"name")||a.getAttributeNS(v,"name");a="style"===c?a.getAttributeNS(v,"family"):a.namespaceURI===w?"data":c;return(a=b[a])?0<a[d]:!1};p(a,b);c&&r(c,b)};this.hasDerivedStyles=function(a,c,b){var e=b.getAttributeNS(v,"name");b=b.getAttributeNS(v,"family");
+return D.getODFElementsWithXPath(a,"//style:*[@style:parent-style-name='"+e+"'][@style:family='"+b+"']",c).length?!0:!1};this.prefixStyleNames=function(a,c,b){var d;if(a){for(d=a.firstChild;d;){if(d.nodeType===Node.ELEMENT_NODE){var f=d,m=c,g=f.getAttributeNS(e,"name"),l=void 0;g?l=e:(g=f.getAttributeNS(v,"name"))&&(l=v);l&&f.setAttributeNS(l,A[l]+"name",m+g)}d=d.nextSibling}k(a,c);b&&k(b,c)}};this.removePrefixFromStyleNames=function(a,c,b){var d=RegExp("^"+c);if(a){for(c=a.firstChild;c;){if(c.nodeType===
+Node.ELEMENT_NODE){var f=c,m=d,g=f.getAttributeNS(e,"name"),l=void 0;g?l=e:(g=f.getAttributeNS(v,"name"))&&(l=v);l&&(g=g.replace(m,""),f.setAttributeNS(l,A[l]+"name",g))}c=c.nextSibling}h(a,d);b&&h(b,d)}};this.determineStylesForNode=b;G=function(){var a,c,b,e,d,f={},m,g,l,n;for(b in J)if(J.hasOwnProperty(b))for(e=J[b],c=e.length,a=0;a<c;a+=1)d=e[a],l=d.en,n=d.ens,f.hasOwnProperty(l)?m=f[l]:f[l]=m={},m.hasOwnProperty(n)?g=m[n]:m[n]=g=[],g.push({ns:d.ans,localname:d.a,keyname:b});return f}()};
+// Input 26
+"function"!==typeof Object.create&&(Object.create=function(k){var h=function(){};h.prototype=k;return new h});
+xmldom.LSSerializer=function(){function k(b){var n=b||{},g=function(b){var c={},a;for(a in b)b.hasOwnProperty(a)&&(c[b[a]]=a);return c}(b),k=[n],h=[g],l=0;this.push=function(){l+=1;n=k[l]=Object.create(n);g=h[l]=Object.create(g)};this.pop=function(){k.pop();h.pop();l-=1;n=k[l];g=h[l]};this.getLocalNamespaceDefinitions=function(){return g};this.getQName=function(b){var c=b.namespaceURI,a=0,d;if(!c)return b.localName;if(d=g[c])return d+":"+b.localName;do{d||!b.prefix?(d="ns"+a,a+=1):d=b.prefix;if(n[d]===
+c)break;if(!n[d]){n[d]=c;g[c]=d;break}d=null}while(null===d);return d+":"+b.localName}}function h(b){return b.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/'/g,"&apos;").replace(/"/g,"&quot;")}function b(d,n){var g="",k=p.filter?p.filter.acceptNode(n):NodeFilter.FILTER_ACCEPT,r;if(k===NodeFilter.FILTER_ACCEPT&&n.nodeType===Node.ELEMENT_NODE){d.push();r=d.getQName(n);var l,f=n.attributes,c,a,m,e="",t;l="<"+r;c=f.length;for(a=0;a<c;a+=1)m=f.item(a),"http://www.w3.org/2000/xmlns/"!==
+m.namespaceURI&&(t=p.filter?p.filter.acceptNode(m):NodeFilter.FILTER_ACCEPT,t===NodeFilter.FILTER_ACCEPT&&(t=d.getQName(m),m="string"===typeof m.value?h(m.value):m.value,e+=" "+(t+'="'+m+'"')));c=d.getLocalNamespaceDefinitions();for(a in c)c.hasOwnProperty(a)&&((f=c[a])?"xmlns"!==f&&(l+=" xmlns:"+c[a]+'="'+a+'"'):l+=' xmlns="'+a+'"');g+=l+(e+">")}if(k===NodeFilter.FILTER_ACCEPT||k===NodeFilter.FILTER_SKIP){for(k=n.firstChild;k;)g+=b(d,k),k=k.nextSibling;n.nodeValue&&(g+=h(n.nodeValue))}r&&(g+="</"+
+r+">",d.pop());return g}var p=this;this.filter=null;this.writeToString=function(d,n){if(!d)return"";var g=new k(n);return b(g,d)}};
+// Input 27
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -423,28 +541,36 @@ this.getImageElements=function(a){var b=a.startContainer.ownerDocument.createRan
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.Server=function(){};ops.Server.prototype.connect=function(g,l){};ops.Server.prototype.networkStatus=function(){};ops.Server.prototype.login=function(g,l,f,p){};ops.Server.prototype.joinSession=function(g,l,f,p){};ops.Server.prototype.leaveSession=function(g,l,f,p){};ops.Server.prototype.getGenesisUrl=function(g){};
-// Input 22
-xmldom.LSSerializerFilter=function(){};xmldom.LSSerializerFilter.prototype.acceptNode=function(g){};
-// Input 23
-xmldom.XPathIterator=function(){};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){};
-function createXPathSingleton(){function g(c,a,b){return-1!==c&&(c<a||-1===a)&&(c<b||-1===b)}function l(e){for(var a=[],b=0,d=e.length,f;b<d;){var h=e,m=d,l=a,n="",p=[],r=h.indexOf("[",b),s=h.indexOf("/",b),H=h.indexOf("=",b);g(s,r,H)?(n=h.substring(b,s),b=s+1):g(r,s,H)?(n=h.substring(b,r),b=c(h,r,p)):g(H,s,r)?(n=h.substring(b,H),b=H):(n=h.substring(b,m),b=m);l.push({location:n,predicates:p});if(b<d&&"="===e[b]){f=e.substring(b+1,d);if(2<f.length&&("'"===f[0]||'"'===f[0]))f=f.slice(1,f.length-1);
-else try{f=parseInt(f,10)}catch(y){}b=d}}return{steps:a,value:f}}function f(){var c=null,a=!1;this.setNode=function(a){c=a};this.reset=function(){a=!1};this.next=function(){var b=a?null:c;a=!0;return b}}function p(c,a,b){this.reset=function(){c.reset()};this.next=function(){for(var d=c.next();d;){d.nodeType===Node.ELEMENT_NODE&&(d=d.getAttributeNodeNS(a,b));if(d)break;d=c.next()}return d}}function r(c,a){var b=c.next(),d=null;this.reset=function(){c.reset();b=c.next();d=null};this.next=function(){for(;b;){if(d)if(a&&
-d.firstChild)d=d.firstChild;else{for(;!d.nextSibling&&d!==b;)d=d.parentNode;d===b?b=c.next():d=d.nextSibling}else{do(d=b.firstChild)||(b=c.next());while(b&&!d)}if(d&&d.nodeType===Node.ELEMENT_NODE)return d}return null}}function n(c,a){this.reset=function(){c.reset()};this.next=function(){for(var b=c.next();b&&!a(b);)b=c.next();return b}}function h(c,a,b){a=a.split(":",2);var d=b(a[0]),f=a[1];return new n(c,function(a){return a.localName===f&&a.namespaceURI===d})}function d(c,a,b){var d=new f,k=m(d,
-a,b),h=a.value;return void 0===h?new n(c,function(a){d.setNode(a);k.reset();return null!==k.next()}):new n(c,function(a){d.setNode(a);k.reset();return(a=k.next())?a.nodeValue===h:!1})}var m,c;c=function(c,a,b){for(var d=a,f=c.length,h=0;d<f;)"]"===c[d]?(h-=1,0>=h&&b.push(l(c.substring(a,d)))):"["===c[d]&&(0>=h&&(a=d+1),h+=1),d+=1;return d};m=function(c,a,b){var f,k,g,m;for(f=0;f<a.steps.length;f+=1){g=a.steps[f];k=g.location;if(""===k)c=new r(c,!1);else if("@"===k[0]){k=k.substr(1).split(":",2);m=
-b(k[0]);if(!m)throw"No namespace associated with the prefix "+k[0];c=new p(c,m,k[1])}else"."!==k&&(c=new r(c,!1),-1!==k.indexOf(":")&&(c=h(c,k,b)));for(k=0;k<g.predicates.length;k+=1)m=g.predicates[k],c=d(c,m,b)}return c};return{getODFElementsWithXPath:function(c,a,b){var d=c.ownerDocument,k=[],h=null;if(d&&"function"===typeof d.evaluate)for(b=d.evaluate(a,c,b,XPathResult.UNORDERED_NODE_ITERATOR_TYPE,null),h=b.iterateNext();null!==h;)h.nodeType===Node.ELEMENT_NODE&&k.push(h),h=b.iterateNext();else{k=
-new f;k.setNode(c);c=l(a);k=m(k,c,b);c=[];for(b=k.next();b;)c.push(b),b=k.next();k=c}return k}}}xmldom.XPath=createXPathSingleton();
-// Input 24
-runtime.loadClass("core.DomUtils");
-core.Cursor=function(g,l){function f(a){a.parentNode&&(d.push(a.previousSibling),d.push(a.nextSibling),a.parentNode.removeChild(a))}function p(a,b,c){if(b.nodeType===Node.TEXT_NODE){runtime.assert(Boolean(b),"putCursorIntoTextNode: invalid container");var e=b.parentNode;runtime.assert(Boolean(e),"putCursorIntoTextNode: container without parent");runtime.assert(0<=c&&c<=b.length,"putCursorIntoTextNode: offset is out of bounds");0===c?e.insertBefore(a,b):(c!==b.length&&b.splitText(c),e.insertBefore(a,
-b.nextSibling))}else b.nodeType===Node.ELEMENT_NODE&&b.insertBefore(a,b.childNodes.item(c));d.push(a.previousSibling);d.push(a.nextSibling)}var r=g.createElementNS("urn:webodf:names:cursor","cursor"),n=g.createElementNS("urn:webodf:names:cursor","anchor"),h,d=[],m=g.createRange(),c,e=new core.DomUtils;this.getNode=function(){return r};this.getAnchorNode=function(){return n.parentNode?n:r};this.getSelectedRange=function(){c?(m.setStartBefore(r),m.collapse(!0)):(m.setStartAfter(h?n:r),m.setEndBefore(h?
-r:n));return m};this.setSelectedRange=function(a,b){m&&m!==a&&m.detach();m=a;h=!1!==b;(c=a.collapsed)?(f(n),f(r),p(r,a.startContainer,a.startOffset)):(f(n),f(r),p(h?r:n,a.endContainer,a.endOffset),p(h?n:r,a.startContainer,a.startOffset));d.forEach(e.normalizeTextNodes);d.length=0};this.hasForwardSelection=function(){return h};this.remove=function(){f(r);d.forEach(e.normalizeTextNodes);d.length=0};r.setAttributeNS("urn:webodf:names:cursor","memberId",l);n.setAttributeNS("urn:webodf:names:cursor","memberId",
-l)};
-// Input 25
-runtime.loadClass("core.PositionIterator");core.PositionFilter=function(){};core.PositionFilter.FilterResult={FILTER_ACCEPT:1,FILTER_REJECT:2,FILTER_SKIP:3};core.PositionFilter.prototype.acceptPosition=function(g){};(function(){return core.PositionFilter})();
-// Input 26
-runtime.loadClass("core.PositionFilter");core.PositionFilterChain=function(){var g={},l=core.PositionFilter.FilterResult.FILTER_ACCEPT,f=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(p){for(var r in g)if(g.hasOwnProperty(r)&&g[r].acceptPosition(p)===f)return f;return l};this.addFilter=function(f,l){g[f]=l};this.removeFilter=function(f){delete g[f]}};
-// Input 27
+(function(){function k(c,a,b){for(c=c?c.firstChild:null;c;){if(c.localName===b&&c.namespaceURI===a)return c;c=c.nextSibling}return null}function h(c){var a,b=r.length;for(a=0;a<b;a+=1)if("urn:oasis:names:tc:opendocument:xmlns:office:1.0"===c.namespaceURI&&c.localName===r[a])return a;return-1}function b(c,a){var b=new n.UsedStyleList(c,a),e=new odf.OdfNodeFilter;this.acceptNode=function(c){var d=e.acceptNode(c);d===NodeFilter.FILTER_ACCEPT&&c.parentNode===a&&c.nodeType===Node.ELEMENT_NODE&&(d=b.uses(c)?
+NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT);return d}}function p(c,a){var d=new b(c,a);this.acceptNode=function(a){var c=d.acceptNode(a);c!==NodeFilter.FILTER_ACCEPT||!a.parentNode||a.parentNode.namespaceURI!==odf.Namespaces.textns||"s"!==a.parentNode.localName&&"tab"!==a.parentNode.localName||(c=NodeFilter.FILTER_REJECT);return c}}function d(c,a){if(a){var b=h(a),e,d=c.firstChild;if(-1!==b){for(;d;){e=h(d);if(-1!==e&&e>b)break;d=d.nextSibling}c.insertBefore(a,d)}}}var n=new odf.StyleInfo,
+g=new core.DomUtils,q=odf.Namespaces.stylens,r="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "),l=(new Date).getTime()+"_webodf_",f=new core.Base64;odf.ODFElement=function(){};odf.ODFDocumentElement=function(){};odf.ODFDocumentElement.prototype=new odf.ODFElement;odf.ODFDocumentElement.prototype.constructor=odf.ODFDocumentElement;odf.ODFDocumentElement.prototype.fontFaceDecls=null;odf.ODFDocumentElement.prototype.manifest=null;odf.ODFDocumentElement.prototype.settings=
+null;odf.ODFDocumentElement.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";odf.ODFDocumentElement.localName="document";odf.AnnotationElement=function(){};odf.OdfPart=function(c,a,b,e){var d=this;this.size=0;this.type=null;this.name=c;this.container=b;this.url=null;this.mimetype=a;this.onstatereadychange=this.document=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.data="";this.load=function(){null!==e&&(this.mimetype=a,e.loadAsDataURL(c,a,function(a,c){a&&
+runtime.log(a);d.url=c;if(d.onchange)d.onchange(d);if(d.onstatereadychange)d.onstatereadychange(d)}))}};odf.OdfPart.prototype.load=function(){};odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+f.toBase64(this.data):null};odf.OdfContainer=function a(m,e){function h(a){for(var b=a.firstChild,e;b;)e=b.nextSibling,b.nodeType===Node.ELEMENT_NODE?h(b):b.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&a.removeChild(b),b=e}function r(a){var b={},e,d,f=a.ownerDocument.createNodeIterator(a,
+NodeFilter.SHOW_ELEMENT,null,!1);for(a=f.nextNode();a;)"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&("annotation"===a.localName?(e=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))&&(b.hasOwnProperty(e)?runtime.log("Warning: annotation name used more than once with <office:annotation/>: '"+e+"'"):b[e]=a):"annotation-end"===a.localName&&((e=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))?b.hasOwnProperty(e)?(d=b[e],d.annotationEndElement?
+runtime.log("Warning: annotation name used more than once with <office:annotation-end/>: '"+e+"'"):d.annotationEndElement=a):runtime.log("Warning: annotation end without an annotation start, name: '"+e+"'"):runtime.log("Warning: annotation end without a name found"))),a=f.nextNode()}function z(a,b){for(var e=a&&a.firstChild;e;)e.nodeType===Node.ELEMENT_NODE&&e.setAttributeNS("urn:webodf:names:scope","scope",b),e=e.nextSibling}function x(a){var b={},e;for(a=a.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&
+a.namespaceURI===q&&"font-face"===a.localName&&(e=a.getAttributeNS(q,"name"),b[e]=a),a=a.nextSibling;return b}function v(a,b){var e=null,d,f,m;if(a)for(e=a.cloneNode(!0),d=e.firstElementChild;d;)f=d.nextElementSibling,(m=d.getAttributeNS("urn:webodf:names:scope","scope"))&&m!==b&&e.removeChild(d),d=f;return e}function u(a,b){var e,d,f,m=null,g={};if(a)for(b.forEach(function(a){n.collectUsedFontFaces(g,a)}),m=a.cloneNode(!0),e=m.firstElementChild;e;)d=e.nextElementSibling,f=e.getAttributeNS(q,"name"),
+g[f]||m.removeChild(e),e=d;return m}function s(a){var b=M.rootElement.ownerDocument,e;if(a){h(a.documentElement);try{e=b.importNode(a.documentElement,!0)}catch(d){}}return e}function A(a){M.state=a;if(M.onchange)M.onchange(M);if(M.onstatereadychange)M.onstatereadychange(M)}function J(a){U=null;M.rootElement=a;a.fontFaceDecls=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");a.styles=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");a.automaticStyles=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0",
+"automatic-styles");a.masterStyles=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");a.body=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");a.meta=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta");r(a)}function G(b){var e=s(b),f=M.rootElement,m;e&&"document-styles"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===e.namespaceURI?(f.fontFaceDecls=k(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),d(f,f.fontFaceDecls),
+m=k(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),f.styles=m||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),d(f,f.styles),m=k(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),f.automaticStyles=m||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),z(f.automaticStyles,"document-styles"),d(f,f.automaticStyles),e=k(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),f.masterStyles=
+e||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),d(f,f.masterStyles),n.prefixStyleNames(f.automaticStyles,l,f.masterStyles)):A(a.INVALID)}function D(b){b=s(b);var e,f,m,g;if(b&&"document-content"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI){e=M.rootElement;m=k(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");if(e.fontFaceDecls&&m){g=e.fontFaceDecls;var l,h,p,r,F={};f=x(g);r=x(m);for(m=m.firstElementChild;m;){l=
+m.nextElementSibling;if(m.namespaceURI===q&&"font-face"===m.localName)if(h=m.getAttributeNS(q,"name"),f.hasOwnProperty(h)){if(!m.isEqualNode(f[h])){p=h;for(var t=f,H=r,J=0,G=void 0,G=p=p.replace(/\d+$/,"");t.hasOwnProperty(G)||H.hasOwnProperty(G);)J+=1,G=p+J;p=G;m.setAttributeNS(q,"style:name",p);g.appendChild(m);f[p]=m;delete r[h];F[h]=p}}else g.appendChild(m),f[h]=m,delete r[h];m=l}g=F}else m&&(e.fontFaceDecls=m,d(e,m));f=k(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");
+z(f,"document-content");g&&n.changeFontFaceNames(f,g);if(e.automaticStyles&&f)for(g=f.firstChild;g;)e.automaticStyles.appendChild(g),g=f.firstChild;else f&&(e.automaticStyles=f,d(e,f));b=k(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===b)throw"<office:body/> tag is mising.";e.body=b;d(e,e.body)}else A(a.INVALID)}function F(a){a=s(a);var b;a&&"document-meta"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=M.rootElement,b.meta=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0",
+"meta"),d(b,b.meta))}function O(a){a=s(a);var b;a&&"document-settings"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=M.rootElement,b.settings=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),d(b,b.settings))}function K(a){a=s(a);var b;if(a&&"manifest"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===a.namespaceURI)for(b=M.rootElement,b.manifest=a,a=b.manifest.firstElementChild;a;)"file-entry"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===
+a.namespaceURI&&(S[a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),a=a.nextElementSibling}function Z(b){var e=b.shift();e?E.loadAsDOM(e.path,function(d,f){e.handler(f);d||M.state===a.INVALID||Z(b)}):(r(M.rootElement),A(a.DONE))}function Q(a){var b="";odf.Namespaces.forEachPrefix(function(a,e){b+=" xmlns:"+a+'="'+e+'"'});return'<?xml version="1.0" encoding="UTF-8"?><office:'+a+" "+
+b+' office:version="1.2">'}function W(){var a=new xmldom.LSSerializer,b=Q("document-meta");a.filter=new odf.OdfNodeFilter;b+=a.writeToString(M.rootElement.meta,odf.Namespaces.namespaceMap);return b+"</office:document-meta>"}function H(a,b){var e=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");e.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:full-path",a);e.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0",
+"manifest:media-type",b);return e}function T(){var a=runtime.parseXML('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2"></manifest:manifest>'),b=k(a,"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest"),e=new xmldom.LSSerializer,d;for(d in S)S.hasOwnProperty(d)&&b.appendChild(H(d,S[d]));e.filter=new odf.OdfNodeFilter;return'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'+e.writeToString(a,odf.Namespaces.namespaceMap)}
+function y(){var a=new xmldom.LSSerializer,b=Q("document-settings");a.filter=new odf.OdfNodeFilter;M.rootElement.settings.firstElementChild&&(b+=a.writeToString(M.rootElement.settings,odf.Namespaces.namespaceMap));return b+"</office:document-settings>"}function aa(){var a,e,d,f=odf.Namespaces.namespaceMap,m=new xmldom.LSSerializer,g=Q("document-styles");e=v(M.rootElement.automaticStyles,"document-styles");d=M.rootElement.masterStyles.cloneNode(!0);a=u(M.rootElement.fontFaceDecls,[d,M.rootElement.styles,
+e]);n.removePrefixFromStyleNames(e,l,d);m.filter=new b(d,e);g+=m.writeToString(a,f);g+=m.writeToString(M.rootElement.styles,f);g+=m.writeToString(e,f);g+=m.writeToString(d,f);return g+"</office:document-styles>"}function N(){var a,b,e=odf.Namespaces.namespaceMap,d=new xmldom.LSSerializer,f=Q("document-content");b=v(M.rootElement.automaticStyles,"document-content");a=u(M.rootElement.fontFaceDecls,[b]);d.filter=new p(M.rootElement.body,b);f+=d.writeToString(a,e);f+=d.writeToString(b,e);f+=d.writeToString(M.rootElement.body,
+e);return f+"</office:document-content>"}function R(b,e){runtime.loadXML(b,function(b,d){if(b)e(b);else{var f=s(d);f&&"document"===f.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===f.namespaceURI?(J(f),A(a.DONE)):A(a.INVALID)}})}function I(a,b){var e;e=M.rootElement;var f=e.meta;f||(e.meta=f=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),d(e,f));e=f;a&&g.mapKeyValObjOntoNode(e,a,odf.Namespaces.lookupNamespaceURI);b&&g.removeKeyElementsFromNode(e,
+b,odf.Namespaces.lookupNamespaceURI)}function ca(){function b(a,e){var d;e||(e=a);d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",e);f[a]=d;f.appendChild(d)}var e=new core.Zip("",null),d=runtime.byteArrayFromString("application/vnd.oasis.opendocument.text","utf8"),f=M.rootElement,m=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text");e.save("mimetype",d,!1,new Date);b("meta");b("settings");b("scripts");b("fontFaceDecls","font-face-decls");
+b("styles");b("automaticStyles","automatic-styles");b("masterStyles","master-styles");b("body");f.body.appendChild(m);S["/"]="application/vnd.oasis.opendocument.text";S["settings.xml"]="text/xml";S["meta.xml"]="text/xml";S["styles.xml"]="text/xml";S["content.xml"]="text/xml";A(a.DONE);return e}function ia(){var a,b=new Date,e=runtime.getWindow();a="WebODF/"+("undefined"!==String(typeof webodf_version)?webodf_version:"FromSource");e&&(a=a+" "+e.navigator.userAgent);I({"meta:generator":a},null);a=runtime.byteArrayFromString(y(),
+"utf8");E.save("settings.xml",a,!0,b);a=runtime.byteArrayFromString(W(),"utf8");E.save("meta.xml",a,!0,b);a=runtime.byteArrayFromString(aa(),"utf8");E.save("styles.xml",a,!0,b);a=runtime.byteArrayFromString(N(),"utf8");E.save("content.xml",a,!0,b);a=runtime.byteArrayFromString(T(),"utf8");E.save("META-INF/manifest.xml",a,!0,b)}function Y(a,b){ia();E.writeAs(a,function(a){b(a)})}var M=this,E,S={},U;this.onstatereadychange=e;this.state=this.onchange=null;this.setRootElement=J;this.getContentElement=
+function(){var a;U||(a=M.rootElement.body,U=k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","presentation")||k(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!U)throw"Could not find content element in <office:body/>.";return U};this.getDocumentType=function(){var a=M.getContentElement();return a&&a.localName};this.getPart=function(a){return new odf.OdfPart(a,S[a],M,E)};this.getPartData=function(a,b){E.load(a,
+b)};this.setMetadata=I;this.incrementEditingCycles=function(){var a;for(a=(a=M.rootElement.meta)&&a.firstChild;a&&(a.namespaceURI!==odf.Namespaces.metans||"editing-cycles"!==a.localName);)a=a.nextSibling;for(a=a&&a.firstChild;a&&a.nodeType!==Node.TEXT_NODE;)a=a.nextSibling;a=a?a.data:null;a=a?parseInt(a,10):0;isNaN(a)&&(a=0);I({"meta:editing-cycles":a+1},null)};this.createByteArray=function(a,b){ia();E.createByteArray(a,b)};this.saveAs=Y;this.save=function(a){Y(m,a)};this.getUrl=function(){return m};
+this.setBlob=function(a,b,e){e=f.convertBase64ToByteArray(e);E.save(a,e,!1,new Date);S.hasOwnProperty(a)&&runtime.log(a+" has been overwritten.");S[a]=b};this.removeBlob=function(a){var b=E.remove(a);runtime.assert(b,"file is not found: "+a);delete S[a]};this.state=a.LOADING;this.rootElement=function(a){var b=document.createElementNS(a.namespaceURI,a.localName),e;a=new a.Type;for(e in a)a.hasOwnProperty(e)&&(b[e]=a[e]);return b}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentElement.namespaceURI,
+localName:odf.ODFDocumentElement.localName});E=m?new core.Zip(m,function(b,e){E=e;b?R(m,function(e){b&&(E.error=b+"\n"+e,A(a.INVALID))}):Z([{path:"styles.xml",handler:G},{path:"content.xml",handler:D},{path:"meta.xml",handler:F},{path:"settings.xml",handler:O},{path:"META-INF/manifest.xml",handler:K}])}):ca()};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADING=1;odf.OdfContainer.DONE=2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED=5;odf.OdfContainer.getContainer=function(a){return new odf.OdfContainer(a,
+null)};return odf.OdfContainer})();
+// Input 28
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -482,14 +608,20 @@ runtime.loadClass("core.PositionFilter");core.PositionFilterChain=function(){var
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-gui.AnnotatableCanvas=function(){};gui.AnnotatableCanvas.prototype.refreshSize=function(){};gui.AnnotatableCanvas.prototype.getZoomLevel=function(){};gui.AnnotatableCanvas.prototype.getSizer=function(){};
-gui.AnnotationViewManager=function(g,l,f){function p(a){var b=a.node,d=a.end;a=m.createRange();d&&(a.setStart(b,b.childNodes.length),a.setEnd(d,0),d=c.getTextNodes(a,!1),d.forEach(function(a){var c=m.createElement("span"),d=b.getAttributeNS(odf.Namespaces.officens,"name");c.className="annotationHighlight";c.setAttribute("annotation",d);a.parentNode.insertBefore(c,a);c.appendChild(a)}));a.detach()}function r(a){var b=g.getSizer();a?(f.style.display="inline-block",b.style.paddingRight=e.getComputedStyle(f).width):
-(f.style.display="none",b.style.paddingRight=0);g.refreshSize()}function n(){d.sort(function(a,b){return a.node.compareDocumentPosition(b.node)===Node.DOCUMENT_POSITION_FOLLOWING?-1:1})}function h(){var a;for(a=0;a<d.length;a+=1){var b=d[a],c=b.node.parentElement,e=c.nextElementSibling,h=e.nextElementSibling,m=c.parentElement,l=0,l=d[d.indexOf(b)-1],n=void 0,b=g.getZoomLevel();c.style.left=(f.getBoundingClientRect().left-m.getBoundingClientRect().left)/b+"px";c.style.width=f.getBoundingClientRect().width/
-b+"px";e.style.width=parseFloat(c.style.left)-30+"px";l&&(n=l.node.parentElement.getBoundingClientRect(),20>=(m.getBoundingClientRect().top-n.bottom)/b?c.style.top=Math.abs(m.getBoundingClientRect().top-n.bottom)/b+20+"px":c.style.top="0px");h.style.left=e.getBoundingClientRect().width/b+"px";var e=h.style,m=h.getBoundingClientRect().left/b,l=h.getBoundingClientRect().top/b,n=c.getBoundingClientRect().left/b,r=c.getBoundingClientRect().top/b,p=0,s=0,p=n-m,p=p*p,s=r-l,s=s*s,m=Math.sqrt(p+s);e.width=
-m+"px";l=Math.asin((c.getBoundingClientRect().top-h.getBoundingClientRect().top)/(b*parseFloat(h.style.width)));h.style.transform="rotate("+l+"rad)";h.style.MozTransform="rotate("+l+"rad)";h.style.WebkitTransform="rotate("+l+"rad)";h.style.msTransform="rotate("+l+"rad)"}}var d=[],m=l.ownerDocument,c=new odf.OdfUtils,e=runtime.getWindow();runtime.assert(Boolean(e),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=h;this.addAnnotation=function(a){r(!0);
-d.push({node:a.node,end:a.end});n();var b=m.createElement("div"),c=m.createElement("div"),e=m.createElement("div"),f=m.createElement("div"),g=m.createElement("div"),l=a.node;b.className="annotationWrapper";l.parentNode.insertBefore(b,l);c.className="annotationNote";c.appendChild(l);g.className="annotationRemoveButton";c.appendChild(g);e.className="annotationConnector horizontal";f.className="annotationConnector angular";b.appendChild(c);b.appendChild(e);b.appendChild(f);a.end&&p(a);h()};this.forgetAnnotations=
-function(){for(;d.length;){var a=d[0],b=d.indexOf(a),c=a.node,e=c.parentNode.parentNode;"div"===e.localName&&(e.parentNode.insertBefore(c,e),e.parentNode.removeChild(e));a=a.node.getAttributeNS(odf.Namespaces.officens,"name");a=m.querySelectorAll('span.annotationHighlight[annotation="'+a+'"]');e=c=void 0;for(c=0;c<a.length;c+=1){for(e=a.item(c);e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.parentNode.removeChild(e)}-1!==b&&d.splice(b,1);0===d.length&&r(!1)}}};
-// Input 28
+odf.OdfUtils=function(){function k(a){return"image"===(a&&a.localName)&&a.namespaceURI===K}function h(a){return null!==a&&a.nodeType===Node.ELEMENT_NODE&&"frame"===a.localName&&a.namespaceURI===K&&"as-char"===a.getAttributeNS(O,"anchor-type")}function b(a){var c;(c="annotation"===(a&&a.localName)&&a.namespaceURI===odf.Namespaces.officens)||(c="div"===(a&&a.localName)&&"annotationWrapper"===a.className);return c}function p(a){return"a"===(a&&a.localName)&&a.namespaceURI===O}function d(a){var c=a&&
+a.localName;return("p"===c||"h"===c)&&a.namespaceURI===O}function n(a){for(;a&&!d(a);)a=a.parentNode;return a}function g(a){return/^[ \t\r\n]+$/.test(a)}function q(a){if(null===a||a.nodeType!==Node.ELEMENT_NODE)return!1;var c=a.localName;return/^(span|p|h|a|meta)$/.test(c)&&a.namespaceURI===O||"span"===c&&"annotationHighlight"===a.className}function r(a){var c=a&&a.localName,b=!1;c&&(a=a.namespaceURI,a===O&&(b="s"===c||"tab"===c||"line-break"===c));return b}function l(a){return r(a)||h(a)||b(a)}function f(a){var c=
+a&&a.localName,b=!1;c&&(a=a.namespaceURI,a===O&&(b="s"===c));return b}function c(a){for(;null!==a.firstChild&&q(a);)a=a.firstChild;return a}function a(a){for(;null!==a.lastChild&&q(a);)a=a.lastChild;return a}function m(c){for(;!d(c)&&null===c.previousSibling;)c=c.parentNode;return d(c)?null:a(c.previousSibling)}function e(a){for(;!d(a)&&null===a.nextSibling;)a=a.parentNode;return d(a)?null:c(a.nextSibling)}function t(a){for(var c=!1;a;)if(a.nodeType===Node.TEXT_NODE)if(0===a.length)a=m(a);else return!g(a.data.substr(a.length-
+1,1));else l(a)?(c=!1===f(a),a=null):a=m(a);return c}function w(a){var b=!1,d;for(a=a&&c(a);a;){d=a.nodeType===Node.TEXT_NODE?a.length:0;if(0<d&&!g(a.data)){b=!0;break}if(l(a)){b=!0;break}a=e(a)}return b}function z(a,c){return g(a.data.substr(c))?!w(e(a)):!1}function x(a,c){var b=a.data,e;if(!g(b[c])||l(a.parentNode))return!1;0<c?g(b[c-1])||(e=!0):t(m(a))&&(e=!0);return!0===e?z(a,c)?!1:!0:!1}function v(a){return(a=/(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/.exec(a))?
+{value:parseFloat(a[1]),unit:a[3]}:null}function u(a){return(a=v(a))&&(0>a.value||"%"===a.unit)?null:a}function s(a){return(a=v(a))&&"%"!==a.unit?null:a}function A(a){switch(a.namespaceURI){case odf.Namespaces.drawns:case odf.Namespaces.svgns:case odf.Namespaces.dr3dns:return!1;case odf.Namespaces.textns:switch(a.localName){case "note-body":case "ruby-text":return!1}break;case odf.Namespaces.officens:switch(a.localName){case "annotation":case "binary-data":case "event-listeners":return!1}break;default:switch(a.localName){case "cursor":case "editinfo":return!1}}return!0}
+function J(a,c){for(;0<c.length&&!W.rangeContainsNode(a,c[0]);)c.shift();for(;0<c.length&&!W.rangeContainsNode(a,c[c.length-1]);)c.pop()}function G(a,c,e){var d;d=W.getNodesInRange(a,function(a){var c=NodeFilter.FILTER_REJECT;if(r(a.parentNode)||b(a))c=NodeFilter.FILTER_REJECT;else if(a.nodeType===Node.TEXT_NODE){if(e||Boolean(n(a)&&(!g(a.textContent)||x(a,0))))c=NodeFilter.FILTER_ACCEPT}else if(l(a))c=NodeFilter.FILTER_ACCEPT;else if(A(a)||q(a))c=NodeFilter.FILTER_SKIP;return c},NodeFilter.SHOW_ELEMENT|
+NodeFilter.SHOW_TEXT);c||J(a,d);return d}function D(a,c,e){for(;a;){if(e(a)){c[0]!==a&&c.unshift(a);break}if(b(a))break;a=a.parentNode}}function F(a,c){var b=a;if(c<b.childNodes.length-1)b=b.childNodes[c+1];else{for(;!b.nextSibling;)b=b.parentNode;b=b.nextSibling}for(;b.firstChild;)b=b.firstChild;return b}var O=odf.Namespaces.textns,K=odf.Namespaces.drawns,Z=odf.Namespaces.xlinkns,Q=/^\s*$/,W=new core.DomUtils;this.isImage=k;this.isCharacterFrame=h;this.isInlineRoot=b;this.isTextSpan=function(a){return"span"===
+(a&&a.localName)&&a.namespaceURI===O};this.isHyperlink=p;this.getHyperlinkTarget=function(a){return a.getAttributeNS(Z,"href")};this.isParagraph=d;this.getParagraphElement=n;this.isWithinTrackedChanges=function(a,c){for(;a&&a!==c;){if(a.namespaceURI===O&&"tracked-changes"===a.localName)return!0;a=a.parentNode}return!1};this.isListItem=function(a){return"list-item"===(a&&a.localName)&&a.namespaceURI===O};this.isLineBreak=function(a){return"line-break"===(a&&a.localName)&&a.namespaceURI===O};this.isODFWhitespace=
+g;this.isGroupingElement=q;this.isCharacterElement=r;this.isAnchoredAsCharacterElement=l;this.isSpaceElement=f;this.firstChild=c;this.lastChild=a;this.previousNode=m;this.nextNode=e;this.scanLeftForNonSpace=t;this.lookLeftForCharacter=function(a){var c,b=c=0;a.nodeType===Node.TEXT_NODE&&(b=a.length);0<b?(c=a.data,c=g(c.substr(b-1,1))?1===b?t(m(a))?2:0:g(c.substr(b-2,1))?0:2:1):l(a)&&(c=1);return c};this.lookRightForCharacter=function(a){var c=!1,b=0;a&&a.nodeType===Node.TEXT_NODE&&(b=a.length);0<
+b?c=!g(a.data.substr(0,1)):l(a)&&(c=!0);return c};this.scanLeftForAnyCharacter=function(c){var b=!1,e;for(c=c&&a(c);c;){e=c.nodeType===Node.TEXT_NODE?c.length:0;if(0<e&&!g(c.data)){b=!0;break}if(l(c)){b=!0;break}c=m(c)}return b};this.scanRightForAnyCharacter=w;this.isTrailingWhitespace=z;this.isSignificantWhitespace=x;this.isDowngradableSpaceElement=function(a){return a.namespaceURI===O&&"s"===a.localName?t(m(a))&&w(e(a)):!1};this.getFirstNonWhitespaceChild=function(a){for(a=a&&a.firstChild;a&&a.nodeType===
+Node.TEXT_NODE&&Q.test(a.nodeValue);)a=a.nextSibling;return a};this.parseLength=v;this.parseNonNegativeLength=u;this.parseFoFontSize=function(a){var c;c=(c=v(a))&&(0>=c.value||"%"===c.unit)?null:c;return c||s(a)};this.parseFoLineHeight=function(a){return u(a)||s(a)};this.isTextContentContainingNode=A;this.getTextNodes=function(a,c){var b;b=W.getNodesInRange(a,function(a){var c=NodeFilter.FILTER_REJECT;a.nodeType===Node.TEXT_NODE?Boolean(n(a)&&(!g(a.textContent)||x(a,0)))&&(c=NodeFilter.FILTER_ACCEPT):
+A(a)&&(c=NodeFilter.FILTER_SKIP);return c},NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);c||J(a,b);return b};this.getTextElements=G;this.getParagraphElements=function(a){var c;c=W.getNodesInRange(a,function(a){var c=NodeFilter.FILTER_REJECT;if(d(a))c=NodeFilter.FILTER_ACCEPT;else if(A(a)||q(a))c=NodeFilter.FILTER_SKIP;return c},NodeFilter.SHOW_ELEMENT);D(a.startContainer,c,d);return c};this.getImageElements=function(a){var c;c=W.getNodesInRange(a,function(a){var c=NodeFilter.FILTER_SKIP;k(a)&&(c=
+NodeFilter.FILTER_ACCEPT);return c},NodeFilter.SHOW_ELEMENT);D(a.startContainer,c,k);return c};this.getHyperlinkElements=function(a){var c=[],b=a.cloneRange();a.collapsed&&a.endContainer.nodeType===Node.ELEMENT_NODE&&(a=F(a.endContainer,a.endOffset),a.nodeType===Node.TEXT_NODE&&b.setEnd(a,1));G(b,!0,!1).forEach(function(a){for(a=a.parentNode;!d(a);){if(p(a)&&-1===c.indexOf(a)){c.push(a);break}a=a.parentNode}});b.detach();return c}};
+// Input 29
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -527,22 +659,49 @@ function(){for(;d.length;){var a=d[0],b=d.indexOf(a),c=a.node,e=c.parentNode.par
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.Cursor");runtime.loadClass("core.DomUtils");runtime.loadClass("core.PositionIterator");runtime.loadClass("core.PositionFilter");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.OdfUtils");
-gui.SelectionMover=function(g,l){function f(){w.setUnfilteredPosition(g.getNode(),0);return w}function p(a,b){var c,d=null;a&&0<a.length&&(c=b?a.item(a.length-1):a.item(0));c&&(d={top:c.top,left:b?c.right:c.left,bottom:c.bottom});return d}function r(a,b,c,d){var e=a.nodeType;c.setStart(a,b);c.collapse(!d);d=p(c.getClientRects(),!0===d);!d&&0<b&&(c.setStart(a,b-1),c.setEnd(a,b),d=p(c.getClientRects(),!0));d||(e===Node.ELEMENT_NODE&&0<b&&a.childNodes.length>=b?d=r(a,b-1,c,!0):a.nodeType===Node.TEXT_NODE&&
-0<b?d=r(a,b-1,c,!0):a.previousSibling?d=r(a.previousSibling,a.previousSibling.nodeType===Node.TEXT_NODE?a.previousSibling.textContent.length:a.previousSibling.childNodes.length,c,!0):a.parentNode&&a.parentNode!==l?d=r(a.parentNode,0,c,!1):(c.selectNode(l),d=p(c.getClientRects(),!1)));runtime.assert(Boolean(d),"No visible rectangle found");return d}function n(a,b,c){var d=a,e=f(),h,k=l.ownerDocument.createRange(),q=g.getSelectedRange().cloneRange(),m;for(h=r(e.container(),e.unfilteredDomOffset(),k);0<
-d&&c();)d-=1;b?(b=e.container(),e=e.unfilteredDomOffset(),-1===A.comparePoints(q.startContainer,q.startOffset,b,e)?(q.setStart(b,e),m=!1):q.setEnd(b,e)):(q.setStart(e.container(),e.unfilteredDomOffset()),q.collapse(!0));g.setSelectedRange(q,m);e=f();q=r(e.container(),e.unfilteredDomOffset(),k);if(q.top===h.top||void 0===x)x=q.left;runtime.clearTimeout(v);v=runtime.setTimeout(function(){x=void 0},2E3);k.detach();return a-d}function h(a){var b=f();return a.acceptPosition(b)===u&&(b.setUnfilteredPosition(g.getAnchorNode(),
-0),a.acceptPosition(b)===u)?!0:!1}function d(a,b,c){for(var d=new core.LoopWatchDog(1E4),e=0,f=0,h=0<=b?1:-1,k=0<=b?a.nextPosition:a.previousPosition;0!==b&&k();)d.check(),f+=h,c.acceptPosition(a)===u&&(b-=h,e+=f,f=0);return e}function m(a,b,c){for(var d=f(),e=new core.LoopWatchDog(1E4),h=0,k=0;0<a&&d.nextPosition();)e.check(),c.acceptPosition(d)===u&&(h+=1,b.acceptPosition(d)===u&&(k+=h,h=0,a-=1));return k}function c(a,b,c){for(var d=f(),e=new core.LoopWatchDog(1E4),h=0,k=0;0<a&&d.previousPosition();)e.check(),
-c.acceptPosition(d)===u&&(h+=1,b.acceptPosition(d)===u&&(k+=h,h=0,a-=1));return k}function e(a,b){var c=f();return d(c,a,b)}function a(a,b,c){var e=f(),h=t.getParagraphElement(e.getCurrentNode()),k=0;e.setUnfilteredPosition(a,b);c.acceptPosition(e)!==u&&(k=d(e,-1,c),0===k||h&&h!==t.getParagraphElement(e.getCurrentNode()))&&(e.setUnfilteredPosition(a,b),k=d(e,1,c));return k}function b(a,b){var c=f(),d=0,e=0,h=0>a?-1:1;for(a=Math.abs(a);0<a;){for(var k=b,q=h,g=c,m=g.container(),n=0,p=null,v=void 0,
-t=10,w=void 0,A=0,F=void 0,C=void 0,Y=void 0,w=void 0,U=l.ownerDocument.createRange(),R=new core.LoopWatchDog(1E4),w=r(m,g.unfilteredDomOffset(),U),F=w.top,C=void 0===x?w.left:x,Y=F;!0===(0>q?g.previousPosition():g.nextPosition());)if(R.check(),k.acceptPosition(g)===u&&(n+=1,m=g.container(),w=r(m,g.unfilteredDomOffset(),U),w.top!==F)){if(w.top!==Y&&Y!==F)break;Y=w.top;w=Math.abs(C-w.left);if(null===p||w<t)p=m,v=g.unfilteredDomOffset(),t=w,A=n}null!==p?(g.setUnfilteredPosition(p,v),n=A):n=0;U.detach();
-d+=n;if(0===d)break;e+=d;a-=1}return e*h}function q(a,b){var c,d,e,h,k=f(),q=t.getParagraphElement(k.getCurrentNode()),g=0,m=l.ownerDocument.createRange();0>a?(c=k.previousPosition,d=-1):(c=k.nextPosition,d=1);for(e=r(k.container(),k.unfilteredDomOffset(),m);c.call(k);)if(b.acceptPosition(k)===u){if(t.getParagraphElement(k.getCurrentNode())!==q)break;h=r(k.container(),k.unfilteredDomOffset(),m);if(h.bottom!==e.bottom&&(e=h.top>=e.top&&h.bottom<e.bottom||h.top<=e.top&&h.bottom>e.bottom,!e))break;g+=
-d;e=h}m.detach();return g}function k(a,b,c){runtime.assert(null!==a,"SelectionMover.countStepsToPosition called with element===null");var d=f(),e=d.container(),h=d.unfilteredDomOffset(),k=0,q=new core.LoopWatchDog(1E4);for(d.setUnfilteredPosition(a,b);c.acceptPosition(d)!==u&&d.previousPosition();)q.check();a=d.container();runtime.assert(Boolean(a),"SelectionMover.countStepsToPosition: positionIterator.container() returned null");b=d.unfilteredDomOffset();for(d.setUnfilteredPosition(e,h);c.acceptPosition(d)!==
-u&&d.previousPosition();)q.check();e=A.comparePoints(a,b,d.container(),d.unfilteredDomOffset());if(0>e)for(;d.nextPosition()&&(q.check(),c.acceptPosition(d)===u&&(k+=1),d.container()!==a||d.unfilteredDomOffset()!==b););else if(0<e)for(;d.previousPosition()&&(q.check(),c.acceptPosition(d)!==u||(k-=1,d.container()!==a||d.unfilteredDomOffset()!==b)););return k}var t=new odf.OdfUtils,A=new core.DomUtils,w,x,v,u=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.movePointForward=function(a,b){return n(a,
-b||!1,w.nextPosition)};this.movePointBackward=function(a,b){return n(a,b||!1,w.previousPosition)};this.getStepCounter=function(){return{countSteps:e,convertForwardStepsBetweenFilters:m,convertBackwardStepsBetweenFilters:c,countLinesSteps:b,countStepsToLineBoundary:q,countStepsToPosition:k,isPositionWalkable:h,countPositionsToNearestStep:a}};(function(){w=gui.SelectionMover.createPositionIterator(l);var a=l.ownerDocument.createRange();a.setStart(w.container(),w.unfilteredDomOffset());a.collapse(!0);
-g.setSelectedRange(a)})()};gui.SelectionMover.createPositionIterator=function(g){var l=new function(){this.acceptNode=function(f){return f&&"urn:webodf:names:cursor"!==f.namespaceURI&&"urn:webodf:names:editinfo"!==f.namespaceURI?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}};return new core.PositionIterator(g,5,l,!1)};(function(){return gui.SelectionMover})();
-// Input 29
+gui.AnnotatableCanvas=function(){};gui.AnnotatableCanvas.prototype.refreshSize=function(){};gui.AnnotatableCanvas.prototype.getZoomLevel=function(){};gui.AnnotatableCanvas.prototype.getSizer=function(){};
+gui.AnnotationViewManager=function(k,h,b,p){function d(a){var c=a.annotationEndElement,b=l.createRange(),d=a.getAttributeNS(odf.Namespaces.officens,"name");c&&(b.setStart(a,a.childNodes.length),b.setEnd(c,0),a=f.getTextNodes(b,!1),a.forEach(function(a){var c=l.createElement("span");c.className="annotationHighlight";c.setAttribute("annotation",d);a.parentNode.insertBefore(c,a);c.appendChild(a)}));b.detach()}function n(a){var d=k.getSizer();a?(b.style.display="inline-block",d.style.paddingRight=c.getComputedStyle(b).width):
+(b.style.display="none",d.style.paddingRight=0);k.refreshSize()}function g(){r.sort(function(a,c){return 0!==(a.compareDocumentPosition(c)&Node.DOCUMENT_POSITION_FOLLOWING)?-1:1})}function q(){var a;for(a=0;a<r.length;a+=1){var c=r[a],e=c.parentNode,d=e.nextElementSibling,f=d.nextElementSibling,g=e.parentNode,l=0,l=r[r.indexOf(c)-1],n=void 0,c=k.getZoomLevel();e.style.left=(b.getBoundingClientRect().left-g.getBoundingClientRect().left)/c+"px";e.style.width=b.getBoundingClientRect().width/c+"px";d.style.width=
+parseFloat(e.style.left)-30+"px";l&&(n=l.parentNode.getBoundingClientRect(),20>=(g.getBoundingClientRect().top-n.bottom)/c?e.style.top=Math.abs(g.getBoundingClientRect().top-n.bottom)/c+20+"px":e.style.top="0px");f.style.left=d.getBoundingClientRect().width/c+"px";var d=f.style,g=f.getBoundingClientRect().left/c,l=f.getBoundingClientRect().top/c,n=e.getBoundingClientRect().left/c,h=e.getBoundingClientRect().top/c,q=0,A=0,q=n-g,q=q*q,A=h-l,A=A*A,g=Math.sqrt(q+A);d.width=g+"px";l=Math.asin((e.getBoundingClientRect().top-
+f.getBoundingClientRect().top)/(c*parseFloat(f.style.width)));f.style.transform="rotate("+l+"rad)";f.style.MozTransform="rotate("+l+"rad)";f.style.WebkitTransform="rotate("+l+"rad)";f.style.msTransform="rotate("+l+"rad)"}}var r=[],l=h.ownerDocument,f=new odf.OdfUtils,c=runtime.getWindow();runtime.assert(Boolean(c),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=q;this.getMinimumHeightForAnnotationPane=function(){return"none"!==b.style.display&&
+0<r.length?(r[r.length-1].parentNode.getBoundingClientRect().bottom-b.getBoundingClientRect().top)/k.getZoomLevel()+"px":null};this.addAnnotation=function(a){n(!0);r.push(a);g();var c=l.createElement("div"),b=l.createElement("div"),f=l.createElement("div"),k=l.createElement("div"),h;c.className="annotationWrapper";a.parentNode.insertBefore(c,a);b.className="annotationNote";b.appendChild(a);p&&(h=l.createElement("div"),h.className="annotationRemoveButton",b.appendChild(h));f.className="annotationConnector horizontal";
+k.className="annotationConnector angular";c.appendChild(b);c.appendChild(f);c.appendChild(k);a.annotationEndElement&&d(a);q()};this.forgetAnnotations=function(){for(;r.length;){var a=r[0],c=r.indexOf(a),b=a.parentNode.parentNode;"div"===b.localName&&(b.parentNode.insertBefore(a,b),b.parentNode.removeChild(b));for(var a=a.getAttributeNS(odf.Namespaces.officens,"name"),a=l.querySelectorAll('span.annotationHighlight[annotation="'+a+'"]'),d=b=void 0,b=0;b<a.length;b+=1){for(d=a.item(b);d.firstChild;)d.parentNode.insertBefore(d.firstChild,
+d);d.parentNode.removeChild(d)}-1!==c&&r.splice(c,1);0===r.length&&n(!1)}}};
+// Input 30
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+(function(){function k(h,b){var p=this;this.getDistance=function(b){var n=p.x-b.x;b=p.y-b.y;return Math.sqrt(n*n+b*b)};this.getCenter=function(b){return new k((p.x+b.x)/2,(p.y+b.y)/2)};p.x=h;p.y=b}gui.ZoomHelper=function(){function h(c,b,e,d){c=d?"translate3d("+c+"px, "+b+"px, 0) scale3d("+e+", "+e+", 1)":"translate("+c+"px, "+b+"px) scale("+e+")";a.style.WebkitTransform=c;a.style.MozTransform=c;a.style.msTransform=c;a.style.OTransform=c;a.style.transform=c}function b(a){a?h(-m.x,-m.y,w,!0):(h(0,
+0,w,!0),h(0,0,w,!1))}function p(a){if(v&&J){var c=v.style.overflow,b=v.classList.contains("customScrollbars");a&&b||!a&&!b||(a?(v.classList.add("customScrollbars"),v.style.overflow="hidden",runtime.requestAnimationFrame(function(){v.style.overflow=c})):v.classList.remove("customScrollbars"))}}function d(){h(-m.x,-m.y,w,!0);v.scrollLeft=0;v.scrollTop=0;p(!1)}function n(){h(0,0,w,!0);v.scrollLeft=m.x;v.scrollTop=m.y;p(!0)}function g(c){return new k(c.pageX-a.offsetLeft,c.pageY-a.offsetTop)}function q(c){e&&
+(m.x-=c.x-e.x,m.y-=c.y-e.y,m=new k(Math.min(Math.max(m.x,a.offsetLeft),(a.offsetLeft+a.offsetWidth)*w-v.clientWidth),Math.min(Math.max(m.y,a.offsetTop),(a.offsetTop+a.offsetHeight)*w-v.clientHeight)));e=c}function r(a){var c=a.touches.length,b=0<c?g(a.touches[0]):null;a=1<c?g(a.touches[1]):null;b&&a?(t=b.getDistance(a),z=w,e=b.getCenter(a),d(),A=s.PINCH):b&&(e=b,A=s.SCROLL)}function l(c){var e=c.touches.length,f=0<e?g(c.touches[0]):null,e=1<e?g(c.touches[1]):null;if(f&&e)if(c.preventDefault(),A===
+s.SCROLL)A=s.PINCH,d(),t=f.getDistance(e);else{c=f.getCenter(e);f=f.getDistance(e)/t;q(c);var e=w,l=Math.min(x,a.offsetParent.clientWidth/a.offsetWidth);w=z*f;w=Math.min(Math.max(w,l),x);f=w/e;m.x+=(f-1)*(c.x+m.x);m.y+=(f-1)*(c.y+m.y);b(!0)}else f&&(A===s.PINCH?(A=s.SCROLL,n()):q(f))}function f(){A===s.PINCH&&(u.emit(gui.ZoomHelper.signalZoomChanged,w),n(),b(!1));A=s.NONE}function c(){v&&(v.removeEventListener("touchstart",r,!1),v.removeEventListener("touchmove",l,!1),v.removeEventListener("touchend",
+f,!1))}var a,m,e,t,w,z,x=4,v,u=new core.EventNotifier([gui.ZoomHelper.signalZoomChanged]),s={NONE:0,SCROLL:1,PINCH:2},A=s.NONE,J=runtime.getWindow().hasOwnProperty("ontouchstart");this.subscribe=function(a,c){u.subscribe(a,c)};this.unsubscribe=function(a,c){u.unsubscribe(a,c)};this.getZoomLevel=function(){return w};this.setZoomLevel=function(c){a&&(w=c,b(!1),u.emit(gui.ZoomHelper.signalZoomChanged,w))};this.destroy=function(a){c();p(!1);a()};this.setZoomableElement=function(e){c();a=e;v=a.offsetParent;
+b(!1);v&&(v.addEventListener("touchstart",r,!1),v.addEventListener("touchmove",l,!1),v.addEventListener("touchend",f,!1));p(!0)};z=w=1;m=new k(0,0)};gui.ZoomHelper.signalZoomChanged="zoomChanged"})();
+// Input 31
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -577,8 +736,10 @@ g.setSelectedRange(a)})()};gui.SelectionMover.createPositionIterator=function(g)
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-odf.OdfNodeFilter=function(){this.acceptNode=function(g){return"http://www.w3.org/1999/xhtml"===g.namespaceURI?NodeFilter.FILTER_SKIP:g.namespaceURI&&g.namespaceURI.match(/^urn:webodf:/)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}};
-// Input 30
+(function(){function k(h,d,n,g,q){var r,l=0,f;for(f in h)if(h.hasOwnProperty(f)){if(l===n){r=f;break}l+=1}r?d.getPartData(h[r].href,function(c,a){if(c)runtime.log(c);else if(a){var f="@font-face { font-family: '"+(h[r].family||r)+"'; src: url(data:application/x-font-ttf;charset=binary;base64,"+b.convertUTF8ArrayToBase64(a)+') format("truetype"); }';try{g.insertRule(f,g.cssRules.length)}catch(e){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(e)+"\nRule: "+f)}}else runtime.log("missing font data for "+
+h[r].href);k(h,d,n+1,g,q)}):q&&q()}var h=xmldom.XPath,b=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(b,d){for(var n=b.rootElement.fontFaceDecls;d.cssRules.length;)d.deleteRule(d.cssRules.length-1);if(n){var g={},q,r,l,f;if(n)for(n=h.getODFElementsWithXPath(n,"style:font-face[svg:font-face-src]",odf.Namespaces.lookupNamespaceURI),q=0;q<n.length;q+=1)r=n[q],l=r.getAttributeNS(odf.Namespaces.stylens,"name"),f=r.getAttributeNS(odf.Namespaces.svgns,"font-family"),r=h.getODFElementsWithXPath(r,
+"svg:font-face-src/svg:font-face-uri",odf.Namespaces.lookupNamespaceURI),0<r.length&&(r=r[0].getAttributeNS(odf.Namespaces.xlinkns,"href"),g[l]={href:r,family:f});k(g,b,0,d)}}};return odf.FontLoader})();
+// Input 32
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -616,30 +777,20 @@ odf.OdfNodeFilter=function(){this.acceptNode=function(g){return"http://www.w3.or
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");runtime.loadClass("xmldom.XPath");runtime.loadClass("core.CSSUnits");odf.StyleTreeNode=function(g){this.derivedStyles={};this.element=g};
-odf.Style2CSS=function(){function g(a){var b,c,d,e={};if(!a)return e;for(a=a.firstElementChild;a;){if(c=a.namespaceURI!==k||"style"!==a.localName&&"default-style"!==a.localName?a.namespaceURI===w&&"list-style"===a.localName?"list":a.namespaceURI!==k||"page-layout"!==a.localName&&"default-page-layout"!==a.localName?void 0:"page":a.getAttributeNS(k,"family"))(b=a.getAttributeNS(k,"name"))||(b=""),e.hasOwnProperty(c)?d=e[c]:e[c]=d={},d[b]=a;a=a.nextElementSibling}return e}function l(a,b){if(a.hasOwnProperty(b))return a[b];
-var c,d=null;for(c in a)if(a.hasOwnProperty(c)&&(d=l(a[c].derivedStyles,b)))break;return d}function f(a,b,c){var d,e,h;if(!b.hasOwnProperty(a))return null;d=new odf.StyleTreeNode(b[a]);e=d.element.getAttributeNS(k,"parent-style-name");h=null;e&&(h=l(c,e)||f(e,b,c));h?h.derivedStyles[a]=d:c[a]=d;delete b[a];return d}function p(a,b){for(var c in a)a.hasOwnProperty(c)&&f(c,a,b)}function r(a,b,c){var d=[];c=c.derivedStyles;var e;var f=u[a],h;void 0===f?b=null:(h=b?"["+f+'|style-name="'+b+'"]':"","presentation"===
-f&&(f="draw",h=b?'[presentation|style-name="'+b+'"]':""),b=f+"|"+s[a].join(h+","+f+"|")+h);null!==b&&d.push(b);for(e in c)c.hasOwnProperty(e)&&(b=r(a,e,c[e]),d=d.concat(b));return d}function n(a,b,c){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==b||a.localName!==c);)a=a.nextElementSibling;return a}function h(a,b){var c="",d,e,f;for(d=0;d<b.length;d+=1)if(e=b[d],f=a.getAttributeNS(e[0],e[1])){f=f.trim();if(G.hasOwnProperty(e[1])){var h=f.indexOf(" "),k=void 0,q=void 0;-1!==h?(k=f.substring(0,h),
-q=f.substring(h)):(k=f,q="");(k=O.parseLength(k))&&"pt"===k.unit&&0.75>k.value&&(f="0.75pt"+q)}e[2]&&(c+=e[2]+":"+f+";")}return c}function d(a){return(a=n(a,k,"text-properties"))?O.parseFoFontSize(a.getAttributeNS(b,"font-size")):null}function m(a,b,c,d){return b+b+c+c+d+d}function c(a,c,d,e){c='text|list[text|style-name="'+c+'"]';var f=d.getAttributeNS(w,"level");d=n(d,k,"list-level-properties");d=n(d,k,"list-level-label-alignment");var h,q;d&&(h=d.getAttributeNS(b,"text-indent"),q=d.getAttributeNS(b,
-"margin-left"));h||(h="-0.6cm");d="-"===h.charAt(0)?h.substring(1):"-"+h;for(f=f&&parseInt(f,10);1<f;)c+=" > text|list-item > text|list",f-=1;if(q){f=c+" > text|list-item > *:not(text|list):first-child";f+="{";f=f+("margin-left:"+q+";")+"}";try{a.insertRule(f,a.cssRules.length)}catch(g){runtime.log("cannot load rule: "+f)}}e=c+" > text|list-item > *:not(text|list):first-child:before{"+e+";";e=e+"counter-increment:list;"+("margin-left:"+h+";");e+="width:"+d+";";e+="display:inline-block}";try{a.insertRule(e,
-a.cssRules.length)}catch(m){runtime.log("cannot load rule: "+e)}}function e(f,g,l,p){if("list"===g)for(var s=p.element.firstChild,t,u;s;){if(s.namespaceURI===w)if(t=s,"list-level-style-number"===s.localName){var G=t;u=G.getAttributeNS(k,"num-format");var T=G.getAttributeNS(k,"num-suffix")||"",G=G.getAttributeNS(k,"num-prefix")||"",$={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},X="";G&&(X+=' "'+G+'"');X=$.hasOwnProperty(u)?X+(" counter(list, "+$[u]+")"):u?X+(' "'+u+
-'"'):X+" ''";u="content:"+X+' "'+T+'"';c(f,l,t,u)}else"list-level-style-image"===s.localName?(u="content: none;",c(f,l,t,u)):"list-level-style-bullet"===s.localName&&(u="content: '"+t.getAttributeNS(w,"bullet-char")+"';",c(f,l,t,u));s=s.nextSibling}else if("page"===g){if(u=p.element,G=T=l="",s=n(u,k,"page-layout-properties"))if(t=u.getAttributeNS(k,"name"),l+=h(s,ja),(T=n(s,k,"background-image"))&&(G=T.getAttributeNS(x,"href"))&&(l=l+("background-image: url('odfkit:"+G+"');")+h(T,y)),"presentation"===
-aa)for(u=(u=n(u.parentNode.parentElement,q,"master-styles"))&&u.firstElementChild;u;){if(u.namespaceURI===k&&"master-page"===u.localName&&u.getAttributeNS(k,"page-layout-name")===t){G=u.getAttributeNS(k,"name");T="draw|page[draw|master-page-name="+G+"] {"+l+"}";G="office|body, draw|page[draw|master-page-name="+G+"] {"+h(s,ka)+" }";try{f.insertRule(T,f.cssRules.length),f.insertRule(G,f.cssRules.length)}catch(da){throw da;}}u=u.nextElementSibling}else if("text"===aa){T="office|text {"+l+"}";G="office|body {width: "+
-s.getAttributeNS(b,"page-width")+";}";try{f.insertRule(T,f.cssRules.length),f.insertRule(G,f.cssRules.length)}catch(S){throw S;}}}else{l=r(g,l,p).join(",");s="";if(t=n(p.element,k,"text-properties")){G=t;u=X="";T=1;t=""+h(G,H);$=G.getAttributeNS(k,"text-underline-style");"solid"===$&&(X+=" underline");$=G.getAttributeNS(k,"text-line-through-style");"solid"===$&&(X+=" line-through");X.length&&(t+="text-decoration:"+X+";");if(X=G.getAttributeNS(k,"font-name")||G.getAttributeNS(b,"font-family"))$=Z[X],
-t+="font-family: "+($||X)+";";$=G.parentElement;if(G=d($)){for(;$;){if(G=d($)){if("%"!==G.unit){u="font-size: "+G.value*T+G.unit+";";break}T*=G.value/100}G=$;X=$="";$=null;"default-style"===G.localName?$=null:($=G.getAttributeNS(k,"parent-style-name"),X=G.getAttributeNS(k,"family"),$=C.getODFElementsWithXPath(J,$?"//style:*[@style:name='"+$+"'][@style:family='"+X+"']":"//style:default-style[@style:family='"+X+"']",odf.Namespaces.lookupNamespaceURI)[0])}u||(u="font-size: "+parseFloat(F)*T+Y.getUnits(F)+
-";");t+=u}s+=t}if(t=n(p.element,k,"paragraph-properties"))u=t,t=""+h(u,B),(T=n(u,k,"background-image"))&&(G=T.getAttributeNS(x,"href"))&&(t=t+("background-image: url('odfkit:"+G+"');")+h(T,y)),(u=u.getAttributeNS(b,"line-height"))&&"normal"!==u&&(u=O.parseFoLineHeight(u),t="%"!==u.unit?t+("line-height: "+u.value+u.unit+";"):t+("line-height: "+u.value/100+";")),s+=t;if(t=n(p.element,k,"graphic-properties"))G=t,t=""+h(G,L),u=G.getAttributeNS(a,"opacity"),T=G.getAttributeNS(a,"fill"),G=G.getAttributeNS(a,
-"fill-color"),"solid"===T||"hatch"===T?G&&"none"!==G?(u=isNaN(parseFloat(u))?1:parseFloat(u)/100,T=G.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,m),(G=(T=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(T))?{r:parseInt(T[1],16),g:parseInt(T[2],16),b:parseInt(T[3],16)}:null)&&(t+="background-color: rgba("+G.r+","+G.g+","+G.b+","+u+");")):t+="background: none;":"none"===T&&(t+="background: none;"),s+=t;if(t=n(p.element,k,"drawing-page-properties"))u=""+h(t,L),"true"===t.getAttributeNS(v,"background-visible")&&
-(u+="background: none;"),s+=u;if(t=n(p.element,k,"table-cell-properties"))t=""+h(t,I),s+=t;if(t=n(p.element,k,"table-row-properties"))t=""+h(t,Q),s+=t;if(t=n(p.element,k,"table-column-properties"))t=""+h(t,W),s+=t;if(t=n(p.element,k,"table-properties"))u=t,t=""+h(u,z),u=u.getAttributeNS(A,"border-model"),"collapsing"===u?t+="border-collapse:collapse;":"separating"===u&&(t+="border-collapse:separate;"),s+=t;if(0!==s.length)try{f.insertRule(l+"{"+s+"}",f.cssRules.length)}catch(ga){throw ga;}}for(var E in p.derivedStyles)p.derivedStyles.hasOwnProperty(E)&&
-e(f,g,E,p.derivedStyles[E])}var a=odf.Namespaces.drawns,b=odf.Namespaces.fons,q=odf.Namespaces.officens,k=odf.Namespaces.stylens,t=odf.Namespaces.svgns,A=odf.Namespaces.tablens,w=odf.Namespaces.textns,x=odf.Namespaces.xlinkns,v=odf.Namespaces.presentationns,u={graphic:"draw","drawing-page":"draw",paragraph:"text",presentation:"presentation",ruby:"text",section:"text",table:"table","table-cell":"table","table-column":"table","table-row":"table",text:"text",list:"text",page:"office"},s={graphic:"circle connected control custom-shape ellipse frame g line measure page page-thumbnail path polygon polyline rect regular-polygon".split(" "),
-paragraph:"alphabetical-index-entry-template h illustration-index-entry-template index-source-style object-index-entry-template p table-index-entry-template table-of-content-entry-template user-index-entry-template".split(" "),presentation:"caption circle connector control custom-shape ellipse frame g line measure page-thumbnail path polygon polyline rect regular-polygon".split(" "),"drawing-page":"caption circle connector control page custom-shape ellipse frame g line measure page-thumbnail path polygon polyline rect regular-polygon".split(" "),
-ruby:["ruby","ruby-text"],section:"alphabetical-index bibliography illustration-index index-title object-index section table-of-content table-index user-index".split(" "),table:["background","table"],"table-cell":"body covered-table-cell even-columns even-rows first-column first-row last-column last-row odd-columns odd-rows table-cell".split(" "),"table-column":["table-column"],"table-row":["table-row"],text:"a index-entry-chapter index-entry-link-end index-entry-link-start index-entry-page-number index-entry-span index-entry-tab-stop index-entry-text index-title-template linenumbering-configuration list-level-style-number list-level-style-bullet outline-level-style span".split(" "),
-list:["list-item"]},H=[[b,"color","color"],[b,"background-color","background-color"],[b,"font-weight","font-weight"],[b,"font-style","font-style"]],y=[[k,"repeat","background-repeat"]],B=[[b,"background-color","background-color"],[b,"text-align","text-align"],[b,"text-indent","text-indent"],[b,"padding","padding"],[b,"padding-left","padding-left"],[b,"padding-right","padding-right"],[b,"padding-top","padding-top"],[b,"padding-bottom","padding-bottom"],[b,"border-left","border-left"],[b,"border-right",
-"border-right"],[b,"border-top","border-top"],[b,"border-bottom","border-bottom"],[b,"margin","margin"],[b,"margin-left","margin-left"],[b,"margin-right","margin-right"],[b,"margin-top","margin-top"],[b,"margin-bottom","margin-bottom"],[b,"border","border"]],L=[[b,"background-color","background-color"],[b,"min-height","min-height"],[a,"stroke","border"],[t,"stroke-color","border-color"],[t,"stroke-width","border-width"],[b,"border","border"],[b,"border-left","border-left"],[b,"border-right","border-right"],
-[b,"border-top","border-top"],[b,"border-bottom","border-bottom"]],I=[[b,"background-color","background-color"],[b,"border-left","border-left"],[b,"border-right","border-right"],[b,"border-top","border-top"],[b,"border-bottom","border-bottom"],[b,"border","border"]],W=[[k,"column-width","width"]],Q=[[k,"row-height","height"],[b,"keep-together",null]],z=[[k,"width","width"],[b,"margin-left","margin-left"],[b,"margin-right","margin-right"],[b,"margin-top","margin-top"],[b,"margin-bottom","margin-bottom"]],
-ja=[[b,"background-color","background-color"],[b,"padding","padding"],[b,"padding-left","padding-left"],[b,"padding-right","padding-right"],[b,"padding-top","padding-top"],[b,"padding-bottom","padding-bottom"],[b,"border","border"],[b,"border-left","border-left"],[b,"border-right","border-right"],[b,"border-top","border-top"],[b,"border-bottom","border-bottom"],[b,"margin","margin"],[b,"margin-left","margin-left"],[b,"margin-right","margin-right"],[b,"margin-top","margin-top"],[b,"margin-bottom",
-"margin-bottom"]],ka=[[b,"page-width","width"],[b,"page-height","height"]],G={border:!0,"border-left":!0,"border-right":!0,"border-top":!0,"border-bottom":!0,"stroke-width":!0},Z={},O=new odf.OdfUtils,aa,J,F,C=xmldom.XPath,Y=new core.CSSUnits;this.style2css=function(a,b,c,d,f){for(var h,k,q,m;b.cssRules.length;)b.deleteRule(b.cssRules.length-1);h=null;d&&(h=d.ownerDocument,J=d.parentNode);f&&(h=f.ownerDocument,J=f.parentNode);if(h)for(m in odf.Namespaces.forEachPrefix(function(a,c){k="@namespace "+
-a+" url("+c+");";try{b.insertRule(k,b.cssRules.length)}catch(d){}}),Z=c,aa=a,F=runtime.getWindow().getComputedStyle(document.body,null).getPropertyValue("font-size")||"12pt",a=g(d),d=g(f),f={},u)if(u.hasOwnProperty(m))for(q in c=f[m]={},p(a[m],c),p(d[m],c),c)c.hasOwnProperty(q)&&e(b,m,q,c[q])}};
-// Input 31
+odf.Formatting=function(){function k(a){return(a=s[a])?u.mergeObjects({},a):{}}function h(a,c,b){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==c||a.localName!==b);)a=a.nextElementSibling;return a}function b(){for(var a=c.rootElement.fontFaceDecls,b={},d,f,a=a&&a.firstElementChild;a;){if(d=a.getAttributeNS(e,"name"))if((f=a.getAttributeNS(m,"font-family"))||0<a.getElementsByTagNameNS(m,"font-face-uri").length)b[d]=f;a=a.nextElementSibling}return b}function p(a){for(var b=c.rootElement.styles.firstElementChild;b;){if(b.namespaceURI===
+e&&"default-style"===b.localName&&b.getAttributeNS(e,"family")===a)return b;b=b.nextElementSibling}return null}function d(a,b,d){var f,g,m;d=d||[c.rootElement.automaticStyles,c.rootElement.styles];for(m=0;m<d.length;m+=1)for(f=d[m],f=f.firstElementChild;f;){g=f.getAttributeNS(e,"name");if(f.namespaceURI===e&&"style"===f.localName&&f.getAttributeNS(e,"family")===b&&g===a||"list-style"===b&&f.namespaceURI===t&&"list-style"===f.localName&&g===a||"data"===b&&f.namespaceURI===w&&g===a)return f;f=f.nextElementSibling}return null}
+function n(a){for(var c,b,d,f,g={},m=a.firstElementChild;m;){if(m.namespaceURI===e)for(d=g[m.nodeName]={},b=m.attributes,c=0;c<b.length;c+=1)f=b.item(c),d[f.name]=f.value;m=m.nextElementSibling}b=a.attributes;for(c=0;c<b.length;c+=1)f=b.item(c),g[f.name]=f.value;return g}function g(a,b){for(var f=c.rootElement.styles,g,m={},l=a.getAttributeNS(e,"family"),h=a;h;)g=n(h),m=u.mergeObjects(g,m),h=(g=h.getAttributeNS(e,"parent-style-name"))?d(g,l,[f]):null;if(h=p(l))g=n(h),m=u.mergeObjects(g,m);!1!==b&&
+(g=k(l),m=u.mergeObjects(g,m));return m}function q(c,b){function e(a){Object.keys(a).forEach(function(c){Object.keys(a[c]).forEach(function(a){m+="|"+c+":"+a+"|"})})}for(var d=c.nodeType===Node.TEXT_NODE?c.parentNode:c,f,g=[],m="",l=!1;d;)!l&&x.isGroupingElement(d)&&(l=!0),(f=a.determineStylesForNode(d))&&g.push(f),d=d.parentNode;l&&(g.forEach(e),b&&(b[m]=g));return l?g:void 0}function r(a){var b={orderedStyles:[]};a.forEach(function(a){Object.keys(a).forEach(function(f){var m=Object.keys(a[f])[0],
+l={name:m,family:f,displayName:void 0,isCommonStyle:!1},h;(h=d(m,f))?(f=g(h),b=u.mergeObjects(f,b),l.displayName=h.getAttributeNS(e,"display-name"),l.isCommonStyle=h.parentNode===c.rootElement.styles):runtime.log("No style element found for '"+m+"' of family '"+f+"'");b.orderedStyles.push(l)})});return b}function l(a,c){var b={},e=[];c||(c={});a.forEach(function(a){q(a,b)});Object.keys(b).forEach(function(a){c[a]||(c[a]=r(b[a]));e.push(c[a])});return e}function f(a,c){var b=x.parseLength(a),e=c;if(b)switch(b.unit){case "cm":e=
+b.value;break;case "mm":e=0.1*b.value;break;case "in":e=2.54*b.value;break;case "pt":e=0.035277778*b.value;break;case "pc":case "px":case "em":break;default:runtime.log("Unit identifier: "+b.unit+" is not supported.")}return e}var c,a=new odf.StyleInfo,m=odf.Namespaces.svgns,e=odf.Namespaces.stylens,t=odf.Namespaces.textns,w=odf.Namespaces.numberns,z=odf.Namespaces.fons,x=new odf.OdfUtils,v=new core.DomUtils,u=new core.Utils,s={paragraph:{"style:paragraph-properties":{"fo:text-align":"left"}}};this.getSystemDefaultStyleAttributes=
+k;this.setOdfContainer=function(a){c=a};this.getFontMap=b;this.getAvailableParagraphStyles=function(){for(var a=c.rootElement.styles,b,d,f=[],a=a&&a.firstElementChild;a;)"style"===a.localName&&a.namespaceURI===e&&(b=a.getAttributeNS(e,"family"),"paragraph"===b&&(b=a.getAttributeNS(e,"name"),d=a.getAttributeNS(e,"display-name")||b,b&&d&&f.push({name:b,displayName:d}))),a=a.nextElementSibling;return f};this.isStyleUsed=function(b){var e,d=c.rootElement;e=a.hasDerivedStyles(d,odf.Namespaces.lookupNamespaceURI,
+b);b=(new a.UsedStyleList(d.styles)).uses(b)||(new a.UsedStyleList(d.automaticStyles)).uses(b)||(new a.UsedStyleList(d.body)).uses(b);return e||b};this.getDefaultStyleElement=p;this.getStyleElement=d;this.getStyleAttributes=n;this.getInheritedStyleAttributes=g;this.getFirstCommonParentStyleNameOrSelf=function(a){var b=c.rootElement.automaticStyles,f=c.rootElement.styles,g;for(g=d(a,"paragraph",[b]);g;)a=g.getAttributeNS(e,"parent-style-name"),g=d(a,"paragraph",[b]);return(g=d(a,"paragraph",[f]))?
+a:null};this.hasParagraphStyle=function(a){return Boolean(d(a,"paragraph"))};this.getAppliedStyles=l;this.getAppliedStylesForElement=function(a,c){return l([a],c)[0]};this.updateStyle=function(a,d){var f,g;v.mapObjOntoNode(a,d,odf.Namespaces.lookupNamespaceURI);(f=d["style:text-properties"]&&d["style:text-properties"]["style:font-name"])&&!b().hasOwnProperty(f)&&(g=a.ownerDocument.createElementNS(e,"style:font-face"),g.setAttributeNS(e,"style:name",f),g.setAttributeNS(m,"svg:font-family",f),c.rootElement.fontFaceDecls.appendChild(g))};
+this.createDerivedStyleObject=function(a,b,e){var f=d(a,b);runtime.assert(Boolean(f),"No style element found for '"+a+"' of family '"+b+"'");a=f.parentNode===c.rootElement.styles?{"style:parent-style-name":a}:n(f);a["style:family"]=b;u.mergeObjects(a,e);return a};this.getDefaultTabStopDistance=function(){for(var a=p("paragraph"),a=a&&a.firstElementChild,c;a;)a.namespaceURI===e&&"paragraph-properties"===a.localName&&(c=a.getAttributeNS(e,"tab-stop-distance")),a=a.nextElementSibling;c||(c="1.25cm");
+return x.parseNonNegativeLength(c)};this.getContentSize=function(a,b){var g,m,l,n,k,q,p,r,t,s,w;a:{var u,x,R;g=d(a,b);runtime.assert("paragraph"===b||"table"===b,"styleFamily has to be either paragraph or table");if(g){u=g.getAttributeNS(e,"master-page-name")||"Standard";for(g=c.rootElement.masterStyles.lastElementChild;g&&g.getAttributeNS(e,"name")!==u;)g=g.previousElementSibling;u=g.getAttributeNS(e,"page-layout-name");x=v.getElementsByTagNameNS(c.rootElement.automaticStyles,e,"page-layout");for(R=
+0;R<x.length;R+=1)if(g=x[R],g.getAttributeNS(e,"name")===u)break a}g=null}g||(g=h(c.rootElement.styles,e,"default-page-layout"));if(g=h(g,e,"page-layout-properties"))m=g.getAttributeNS(e,"print-orientation")||"portrait","portrait"===m?(m=21.001,l=29.7):(m=29.7,l=21.001),m=f(g.getAttributeNS(z,"page-width"),m),l=f(g.getAttributeNS(z,"page-height"),l),n=f(g.getAttributeNS(z,"margin"),null),null===n?(n=f(g.getAttributeNS(z,"margin-left"),2),k=f(g.getAttributeNS(z,"margin-right"),2),q=f(g.getAttributeNS(z,
+"margin-top"),2),p=f(g.getAttributeNS(z,"margin-bottom"),2)):n=k=q=p=n,r=f(g.getAttributeNS(z,"padding"),null),null===r?(r=f(g.getAttributeNS(z,"padding-left"),0),t=f(g.getAttributeNS(z,"padding-right"),0),s=f(g.getAttributeNS(z,"padding-top"),0),w=f(g.getAttributeNS(z,"padding-bottom"),0)):r=t=s=w=r;return{width:m-n-k-r-t,height:l-q-p-s-w}}};
+// Input 33
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -677,39 +828,33 @@ a+" url("+c+");";try{b.insertRule(k,b.cssRules.length)}catch(d){}}),Z=c,aa=a,F=r
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.Namespaces");
-odf.StyleInfo=function(){function g(a,b){var c,d,e,f,h,k=0;if(c=B[a.localName])if(e=c[a.namespaceURI])k=e.length;for(c=0;c<k;c+=1)d=e[c],f=d.ns,h=d.localname,(d=a.getAttributeNS(f,h))&&a.setAttributeNS(f,H[f]+h,b+d);for(e=a.firstElementChild;e;)g(e,b),e=e.nextElementSibling}function l(a,b){var c,d,e,f,h,k=0;if(c=B[a.localName])if(e=c[a.namespaceURI])k=e.length;for(c=0;c<k;c+=1)if(d=e[c],f=d.ns,h=d.localname,d=a.getAttributeNS(f,h))d=d.replace(b,""),a.setAttributeNS(f,H[f]+h,d);for(e=a.firstElementChild;e;)l(e,
-b),e=e.nextElementSibling}function f(a,b){var c,d,e,f,h,k=0;if(c=B[a.localName])if(e=c[a.namespaceURI])k=e.length;for(c=0;c<k;c+=1)if(f=e[c],d=f.ns,h=f.localname,d=a.getAttributeNS(d,h))b=b||{},f=f.keyname,b.hasOwnProperty(f)?b[f][d]=1:(h={},h[d]=1,b[f]=h);return b}function p(a,b){var c,d;f(a,b);for(c=a.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&(d=c,p(d,b)),c=c.nextSibling}function r(a,b,c){this.key=a;this.name=b;this.family=c;this.requires={}}function n(a,b,c){var d=a+'"'+b,e=c[d];e||(e=c[d]=
-new r(d,a,b));return e}function h(a,b,c){var d,e,f,k,q,g=0;d=a.getAttributeNS(v,"name");k=a.getAttributeNS(v,"family");d&&k&&(b=n(d,k,c));if(b){if(d=B[a.localName])if(f=d[a.namespaceURI])g=f.length;for(d=0;d<g;d+=1)if(k=f[d],e=k.ns,q=k.localname,e=a.getAttributeNS(e,q))k=k.keyname,k=n(e,k,c),b.requires[k.key]=k}for(a=a.firstElementChild;a;)h(a,b,c),a=a.nextElementSibling;return c}function d(a,b){var c=b[a.family];c||(c=b[a.family]={});c[a.name]=1;Object.keys(a.requires).forEach(function(c){d(a.requires[c],
-b)})}function m(a,b){var c=h(a,null,{});Object.keys(c).forEach(function(a){a=c[a];var e=b[a.family];e&&e.hasOwnProperty(a.name)&&d(a,b)})}function c(a,b){function d(b){(b=h.getAttributeNS(v,b))&&(a[b]=!0)}var e=["font-name","font-name-asian","font-name-complex"],f,h;for(f=b&&b.firstElementChild;f;)h=f,e.forEach(d),c(a,h),f=f.nextElementSibling}function e(a,b){function c(a){var d=h.getAttributeNS(v,a);d&&b.hasOwnProperty(d)&&h.setAttributeNS(v,"style:"+a,b[d])}var d=["font-name","font-name-asian",
-"font-name-complex"],f,h;for(f=a&&a.firstElementChild;f;)h=f,d.forEach(c),e(h,b),f=f.nextElementSibling}var a=odf.Namespaces.chartns,b=odf.Namespaces.dbns,q=odf.Namespaces.dr3dns,k=odf.Namespaces.drawns,t=odf.Namespaces.formns,A=odf.Namespaces.numberns,w=odf.Namespaces.officens,x=odf.Namespaces.presentationns,v=odf.Namespaces.stylens,u=odf.Namespaces.tablens,s=odf.Namespaces.textns,H={"urn:oasis:names:tc:opendocument:xmlns:chart:1.0":"chart:","urn:oasis:names:tc:opendocument:xmlns:database:1.0":"db:",
-"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0":"dr3d:","urn:oasis:names:tc:opendocument:xmlns:drawing:1.0":"draw:","urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0":"fo:","urn:oasis:names:tc:opendocument:xmlns:form:1.0":"form:","urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0":"number:","urn:oasis:names:tc:opendocument:xmlns:office:1.0":"office:","urn:oasis:names:tc:opendocument:xmlns:presentation:1.0":"presentation:","urn:oasis:names:tc:opendocument:xmlns:style:1.0":"style:","urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0":"svg:",
-"urn:oasis:names:tc:opendocument:xmlns:table:1.0":"table:","urn:oasis:names:tc:opendocument:xmlns:text:1.0":"chart:","http://www.w3.org/XML/1998/namespace":"xml:"},y={text:[{ens:v,en:"tab-stop",ans:v,a:"leader-text-style"},{ens:v,en:"drop-cap",ans:v,a:"style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-body-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"citation-style-name"},{ens:s,en:"a",ans:s,a:"style-name"},{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens:s,en:"linenumbering-configuration",
-ans:s,a:"style-name"},{ens:s,en:"list-level-style-number",ans:s,a:"style-name"},{ens:s,en:"ruby-text",ans:s,a:"style-name"},{ens:s,en:"span",ans:s,a:"style-name"},{ens:s,en:"a",ans:s,a:"visited-style-name"},{ens:v,en:"text-properties",ans:v,a:"text-line-through-text-style"},{ens:s,en:"alphabetical-index-source",ans:s,a:"main-entry-style-name"},{ens:s,en:"index-entry-bibliography",ans:s,a:"style-name"},{ens:s,en:"index-entry-chapter",ans:s,a:"style-name"},{ens:s,en:"index-entry-link-end",ans:s,a:"style-name"},
-{ens:s,en:"index-entry-link-start",ans:s,a:"style-name"},{ens:s,en:"index-entry-page-number",ans:s,a:"style-name"},{ens:s,en:"index-entry-span",ans:s,a:"style-name"},{ens:s,en:"index-entry-tab-stop",ans:s,a:"style-name"},{ens:s,en:"index-entry-text",ans:s,a:"style-name"},{ens:s,en:"index-title-template",ans:s,a:"style-name"},{ens:s,en:"list-level-style-bullet",ans:s,a:"style-name"},{ens:s,en:"outline-level-style",ans:s,a:"style-name"}],paragraph:[{ens:k,en:"caption",ans:k,a:"text-style-name"},{ens:k,
-en:"circle",ans:k,a:"text-style-name"},{ens:k,en:"connector",ans:k,a:"text-style-name"},{ens:k,en:"control",ans:k,a:"text-style-name"},{ens:k,en:"custom-shape",ans:k,a:"text-style-name"},{ens:k,en:"ellipse",ans:k,a:"text-style-name"},{ens:k,en:"frame",ans:k,a:"text-style-name"},{ens:k,en:"line",ans:k,a:"text-style-name"},{ens:k,en:"measure",ans:k,a:"text-style-name"},{ens:k,en:"path",ans:k,a:"text-style-name"},{ens:k,en:"polygon",ans:k,a:"text-style-name"},{ens:k,en:"polyline",ans:k,a:"text-style-name"},
-{ens:k,en:"rect",ans:k,a:"text-style-name"},{ens:k,en:"regular-polygon",ans:k,a:"text-style-name"},{ens:w,en:"annotation",ans:k,a:"text-style-name"},{ens:t,en:"column",ans:t,a:"text-style-name"},{ens:v,en:"style",ans:v,a:"next-style-name"},{ens:u,en:"body",ans:u,a:"paragraph-style-name"},{ens:u,en:"even-columns",ans:u,a:"paragraph-style-name"},{ens:u,en:"even-rows",ans:u,a:"paragraph-style-name"},{ens:u,en:"first-column",ans:u,a:"paragraph-style-name"},{ens:u,en:"first-row",ans:u,a:"paragraph-style-name"},
-{ens:u,en:"last-column",ans:u,a:"paragraph-style-name"},{ens:u,en:"last-row",ans:u,a:"paragraph-style-name"},{ens:u,en:"odd-columns",ans:u,a:"paragraph-style-name"},{ens:u,en:"odd-rows",ans:u,a:"paragraph-style-name"},{ens:s,en:"notes-configuration",ans:s,a:"default-style-name"},{ens:s,en:"alphabetical-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"bibliography-entry-template",ans:s,a:"style-name"},{ens:s,en:"h",ans:s,a:"style-name"},{ens:s,en:"illustration-index-entry-template",ans:s,a:"style-name"},
-{ens:s,en:"index-source-style",ans:s,a:"style-name"},{ens:s,en:"object-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"p",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-of-content-entry-template",ans:s,a:"style-name"},{ens:s,en:"table-index-entry-template",ans:s,a:"style-name"},{ens:s,en:"user-index-entry-template",ans:s,a:"style-name"},{ens:v,en:"page-layout-properties",ans:v,a:"register-truth-ref-style-name"}],chart:[{ens:a,en:"axis",ans:a,
-a:"style-name"},{ens:a,en:"chart",ans:a,a:"style-name"},{ens:a,en:"data-label",ans:a,a:"style-name"},{ens:a,en:"data-point",ans:a,a:"style-name"},{ens:a,en:"equation",ans:a,a:"style-name"},{ens:a,en:"error-indicator",ans:a,a:"style-name"},{ens:a,en:"floor",ans:a,a:"style-name"},{ens:a,en:"footer",ans:a,a:"style-name"},{ens:a,en:"grid",ans:a,a:"style-name"},{ens:a,en:"legend",ans:a,a:"style-name"},{ens:a,en:"mean-value",ans:a,a:"style-name"},{ens:a,en:"plot-area",ans:a,a:"style-name"},{ens:a,en:"regression-curve",
-ans:a,a:"style-name"},{ens:a,en:"series",ans:a,a:"style-name"},{ens:a,en:"stock-gain-marker",ans:a,a:"style-name"},{ens:a,en:"stock-loss-marker",ans:a,a:"style-name"},{ens:a,en:"stock-range-line",ans:a,a:"style-name"},{ens:a,en:"subtitle",ans:a,a:"style-name"},{ens:a,en:"title",ans:a,a:"style-name"},{ens:a,en:"wall",ans:a,a:"style-name"}],section:[{ens:s,en:"alphabetical-index",ans:s,a:"style-name"},{ens:s,en:"bibliography",ans:s,a:"style-name"},{ens:s,en:"illustration-index",ans:s,a:"style-name"},
-{ens:s,en:"index-title",ans:s,a:"style-name"},{ens:s,en:"object-index",ans:s,a:"style-name"},{ens:s,en:"section",ans:s,a:"style-name"},{ens:s,en:"table-of-content",ans:s,a:"style-name"},{ens:s,en:"table-index",ans:s,a:"style-name"},{ens:s,en:"user-index",ans:s,a:"style-name"}],ruby:[{ens:s,en:"ruby",ans:s,a:"style-name"}],table:[{ens:b,en:"query",ans:b,a:"style-name"},{ens:b,en:"table-representation",ans:b,a:"style-name"},{ens:u,en:"background",ans:u,a:"style-name"},{ens:u,en:"table",ans:u,a:"style-name"}],
-"table-column":[{ens:b,en:"column",ans:b,a:"style-name"},{ens:u,en:"table-column",ans:u,a:"style-name"}],"table-row":[{ens:b,en:"query",ans:b,a:"default-row-style-name"},{ens:b,en:"table-representation",ans:b,a:"default-row-style-name"},{ens:u,en:"table-row",ans:u,a:"style-name"}],"table-cell":[{ens:b,en:"column",ans:b,a:"default-cell-style-name"},{ens:u,en:"table-column",ans:u,a:"default-cell-style-name"},{ens:u,en:"table-row",ans:u,a:"default-cell-style-name"},{ens:u,en:"body",ans:u,a:"style-name"},
-{ens:u,en:"covered-table-cell",ans:u,a:"style-name"},{ens:u,en:"even-columns",ans:u,a:"style-name"},{ens:u,en:"covered-table-cell",ans:u,a:"style-name"},{ens:u,en:"even-columns",ans:u,a:"style-name"},{ens:u,en:"even-rows",ans:u,a:"style-name"},{ens:u,en:"first-column",ans:u,a:"style-name"},{ens:u,en:"first-row",ans:u,a:"style-name"},{ens:u,en:"last-column",ans:u,a:"style-name"},{ens:u,en:"last-row",ans:u,a:"style-name"},{ens:u,en:"odd-columns",ans:u,a:"style-name"},{ens:u,en:"odd-rows",ans:u,a:"style-name"},
-{ens:u,en:"table-cell",ans:u,a:"style-name"}],graphic:[{ens:q,en:"cube",ans:k,a:"style-name"},{ens:q,en:"extrude",ans:k,a:"style-name"},{ens:q,en:"rotate",ans:k,a:"style-name"},{ens:q,en:"scene",ans:k,a:"style-name"},{ens:q,en:"sphere",ans:k,a:"style-name"},{ens:k,en:"caption",ans:k,a:"style-name"},{ens:k,en:"circle",ans:k,a:"style-name"},{ens:k,en:"connector",ans:k,a:"style-name"},{ens:k,en:"control",ans:k,a:"style-name"},{ens:k,en:"custom-shape",ans:k,a:"style-name"},{ens:k,en:"ellipse",ans:k,a:"style-name"},
-{ens:k,en:"frame",ans:k,a:"style-name"},{ens:k,en:"g",ans:k,a:"style-name"},{ens:k,en:"line",ans:k,a:"style-name"},{ens:k,en:"measure",ans:k,a:"style-name"},{ens:k,en:"page-thumbnail",ans:k,a:"style-name"},{ens:k,en:"path",ans:k,a:"style-name"},{ens:k,en:"polygon",ans:k,a:"style-name"},{ens:k,en:"polyline",ans:k,a:"style-name"},{ens:k,en:"rect",ans:k,a:"style-name"},{ens:k,en:"regular-polygon",ans:k,a:"style-name"},{ens:w,en:"annotation",ans:k,a:"style-name"}],presentation:[{ens:q,en:"cube",ans:x,
-a:"style-name"},{ens:q,en:"extrude",ans:x,a:"style-name"},{ens:q,en:"rotate",ans:x,a:"style-name"},{ens:q,en:"scene",ans:x,a:"style-name"},{ens:q,en:"sphere",ans:x,a:"style-name"},{ens:k,en:"caption",ans:x,a:"style-name"},{ens:k,en:"circle",ans:x,a:"style-name"},{ens:k,en:"connector",ans:x,a:"style-name"},{ens:k,en:"control",ans:x,a:"style-name"},{ens:k,en:"custom-shape",ans:x,a:"style-name"},{ens:k,en:"ellipse",ans:x,a:"style-name"},{ens:k,en:"frame",ans:x,a:"style-name"},{ens:k,en:"g",ans:x,a:"style-name"},
-{ens:k,en:"line",ans:x,a:"style-name"},{ens:k,en:"measure",ans:x,a:"style-name"},{ens:k,en:"page-thumbnail",ans:x,a:"style-name"},{ens:k,en:"path",ans:x,a:"style-name"},{ens:k,en:"polygon",ans:x,a:"style-name"},{ens:k,en:"polyline",ans:x,a:"style-name"},{ens:k,en:"rect",ans:x,a:"style-name"},{ens:k,en:"regular-polygon",ans:x,a:"style-name"},{ens:w,en:"annotation",ans:x,a:"style-name"}],"drawing-page":[{ens:k,en:"page",ans:k,a:"style-name"},{ens:x,en:"notes",ans:k,a:"style-name"},{ens:v,en:"handout-master",
-ans:k,a:"style-name"},{ens:v,en:"master-page",ans:k,a:"style-name"}],"list-style":[{ens:s,en:"list",ans:s,a:"style-name"},{ens:s,en:"numbered-paragraph",ans:s,a:"style-name"},{ens:s,en:"list-item",ans:s,a:"style-override"},{ens:v,en:"style",ans:v,a:"list-style-name"}],data:[{ens:v,en:"style",ans:v,a:"data-style-name"},{ens:v,en:"style",ans:v,a:"percentage-data-style-name"},{ens:x,en:"date-time-decl",ans:v,a:"data-style-name"},{ens:s,en:"creation-date",ans:v,a:"data-style-name"},{ens:s,en:"creation-time",
-ans:v,a:"data-style-name"},{ens:s,en:"database-display",ans:v,a:"data-style-name"},{ens:s,en:"date",ans:v,a:"data-style-name"},{ens:s,en:"editing-duration",ans:v,a:"data-style-name"},{ens:s,en:"expression",ans:v,a:"data-style-name"},{ens:s,en:"meta-field",ans:v,a:"data-style-name"},{ens:s,en:"modification-date",ans:v,a:"data-style-name"},{ens:s,en:"modification-time",ans:v,a:"data-style-name"},{ens:s,en:"print-date",ans:v,a:"data-style-name"},{ens:s,en:"print-time",ans:v,a:"data-style-name"},{ens:s,
-en:"table-formula",ans:v,a:"data-style-name"},{ens:s,en:"time",ans:v,a:"data-style-name"},{ens:s,en:"user-defined",ans:v,a:"data-style-name"},{ens:s,en:"user-field-get",ans:v,a:"data-style-name"},{ens:s,en:"user-field-input",ans:v,a:"data-style-name"},{ens:s,en:"variable-get",ans:v,a:"data-style-name"},{ens:s,en:"variable-input",ans:v,a:"data-style-name"},{ens:s,en:"variable-set",ans:v,a:"data-style-name"}],"page-layout":[{ens:x,en:"notes",ans:v,a:"page-layout-name"},{ens:v,en:"handout-master",ans:v,
-a:"page-layout-name"},{ens:v,en:"master-page",ans:v,a:"page-layout-name"}]},B,L=xmldom.XPath;this.collectUsedFontFaces=c;this.changeFontFaceNames=e;this.UsedStyleList=function(a,b){var c={};this.uses=function(a){var b=a.localName,d=a.getAttributeNS(k,"name")||a.getAttributeNS(v,"name");a="style"===b?a.getAttributeNS(v,"family"):a.namespaceURI===A?"data":b;return(a=c[a])?0<a[d]:!1};p(a,c);b&&m(b,c)};this.hasDerivedStyles=function(a,b,c){var d=c.getAttributeNS(v,"name");c=c.getAttributeNS(v,"family");
-return L.getODFElementsWithXPath(a,"//style:*[@style:parent-style-name='"+d+"'][@style:family='"+c+"']",b).length?!0:!1};this.prefixStyleNames=function(a,b,c){var d;if(a){for(d=a.firstChild;d;){if(d.nodeType===Node.ELEMENT_NODE){var e=d,f=b,h=e.getAttributeNS(k,"name"),q=void 0;h?q=k:(h=e.getAttributeNS(v,"name"))&&(q=v);q&&e.setAttributeNS(q,H[q]+"name",f+h)}d=d.nextSibling}g(a,b);c&&g(c,b)}};this.removePrefixFromStyleNames=function(a,b,c){var d=RegExp("^"+b);if(a){for(b=a.firstChild;b;){if(b.nodeType===
-Node.ELEMENT_NODE){var e=b,f=d,h=e.getAttributeNS(k,"name"),q=void 0;h?q=k:(h=e.getAttributeNS(v,"name"))&&(q=v);q&&(h=h.replace(f,""),e.setAttributeNS(q,H[q]+"name",h))}b=b.nextSibling}l(a,d);c&&l(c,d)}};this.determineStylesForNode=f;B=function(){var a,b,c,d,e,f={},h,k,q,g;for(c in y)if(y.hasOwnProperty(c))for(d=y[c],b=d.length,a=0;a<b;a+=1)e=d[a],q=e.en,g=e.ens,f.hasOwnProperty(q)?h=f[q]:f[q]=h={},h.hasOwnProperty(g)?k=h[g]:h[g]=k=[],k.push({ns:e.ans,localname:e.a,keyname:c});return f}()};
-// Input 32
+odf.StyleTreeNode=function(k){this.derivedStyles={};this.element=k};
+odf.Style2CSS=function(){function k(a){var c,b,d,f={};if(!a)return f;for(a=a.firstElementChild;a;){if(b=a.namespaceURI!==e||"style"!==a.localName&&"default-style"!==a.localName?a.namespaceURI===z&&"list-style"===a.localName?"list":a.namespaceURI!==e||"page-layout"!==a.localName&&"default-page-layout"!==a.localName?void 0:"page":a.getAttributeNS(e,"family"))(c=a.getAttributeNS(e,"name"))||(c=""),f.hasOwnProperty(b)?d=f[b]:f[b]=d={},d[c]=a;a=a.nextElementSibling}return f}function h(a,c){if(a.hasOwnProperty(c))return a[c];
+var b,e=null;for(b in a)if(a.hasOwnProperty(b)&&(e=h(a[b].derivedStyles,c)))break;return e}function b(a,c,d){var f,g,m;if(!c.hasOwnProperty(a))return null;f=new odf.StyleTreeNode(c[a]);g=f.element.getAttributeNS(e,"parent-style-name");m=null;g&&(m=h(d,g)||b(g,c,d));m?m.derivedStyles[a]=f:d[a]=f;delete c[a];return f}function p(a,c){for(var e in a)a.hasOwnProperty(e)&&b(e,a,c)}function d(a,c,b){var e=[];b=b.derivedStyles;var f;var g=u[a],m;void 0===g?c=null:(m=c?"["+g+'|style-name="'+c+'"]':"","presentation"===
+g&&(g="draw",m=c?'[presentation|style-name="'+c+'"]':""),c=g+"|"+s[a].join(m+","+g+"|")+m);null!==c&&e.push(c);for(f in b)b.hasOwnProperty(f)&&(c=d(a,f,b[f]),e=e.concat(c));return e}function n(a,c,b){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==c||a.localName!==b);)a=a.nextElementSibling;return a}function g(a,c){var b="",e,d,f;for(e=0;e<c.length;e+=1)if(d=c[e],f=a.getAttributeNS(d[0],d[1])){f=f.trim();if(H.hasOwnProperty(d[1])){var g=f.indexOf(" "),m=void 0,l=void 0;-1!==g?(m=f.substring(0,g),
+l=f.substring(g)):(m=f,l="");(m=y.parseLength(m))&&"pt"===m.unit&&0.75>m.value&&(f="0.75pt"+l)}d[2]&&(b+=d[2]+":"+f+";")}return b}function q(c){return(c=n(c,e,"text-properties"))?y.parseFoFontSize(c.getAttributeNS(a,"font-size")):null}function r(a,c,b,e){return c+c+b+b+e+e}function l(c,b,d,f){b='text|list[text|style-name="'+b+'"]';var g=d.getAttributeNS(z,"level");d=n(d,e,"list-level-properties");d=n(d,e,"list-level-label-alignment");var m,l;d&&(m=d.getAttributeNS(a,"text-indent"),l=d.getAttributeNS(a,
+"margin-left"));m||(m="-0.6cm");d="-"===m.charAt(0)?m.substring(1):"-"+m;for(g=g&&parseInt(g,10);1<g;)b+=" > text|list-item > text|list",g-=1;if(l){g=b+" > text|list-item > *:not(text|list):first-child";g+="{";g=g+("margin-left:"+l+";")+"}";try{c.insertRule(g,c.cssRules.length)}catch(h){runtime.log("cannot load rule: "+g)}}f=b+" > text|list-item > *:not(text|list):first-child:before{"+f+";";f=f+"counter-increment:list;"+("margin-left:"+m+";");f+="width:"+d+";";f+="display:inline-block}";try{c.insertRule(f,
+c.cssRules.length)}catch(k){runtime.log("cannot load rule: "+f)}}function f(b,h,k,p){if("list"===h)for(var t=p.element.firstChild,s,u;t;){if(t.namespaceURI===z)if(s=t,"list-level-style-number"===t.localName){var H=s;u=H.getAttributeNS(e,"num-format");var P=H.getAttributeNS(e,"num-suffix")||"",H=H.getAttributeNS(e,"num-prefix")||"",X={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},V="";H&&(V+=' "'+H+'"');V=X.hasOwnProperty(u)?V+(" counter(list, "+X[u]+")"):u?V+(' "'+u+
+'"'):V+" ''";u="content:"+V+' "'+P+'"';l(b,k,s,u)}else"list-level-style-image"===t.localName?(u="content: none;",l(b,k,s,u)):"list-level-style-bullet"===t.localName&&(u="content: '"+s.getAttributeNS(z,"bullet-char")+"';",l(b,k,s,u));t=t.nextSibling}else if("page"===h){if(u=p.element,H=P=k="",t=n(u,e,"page-layout-properties"))if(s=u.getAttributeNS(e,"name"),k+=g(t,Q),(P=n(t,e,"background-image"))&&(H=P.getAttributeNS(x,"href"))&&(k=k+("background-image: url('odfkit:"+H+"');")+g(P,J)),"presentation"===
+aa)for(u=(u=n(u.parentNode.parentNode,m,"master-styles"))&&u.firstElementChild;u;){if(u.namespaceURI===e&&"master-page"===u.localName&&u.getAttributeNS(e,"page-layout-name")===s){H=u.getAttributeNS(e,"name");P="draw|page[draw|master-page-name="+H+"] {"+k+"}";H="office|body, draw|page[draw|master-page-name="+H+"] {"+g(t,W)+" }";try{b.insertRule(P,b.cssRules.length),b.insertRule(H,b.cssRules.length)}catch(ga){throw ga;}}u=u.nextElementSibling}else if("text"===aa){P="office|text {"+k+"}";H="office|body {width: "+
+t.getAttributeNS(a,"page-width")+";}";try{b.insertRule(P,b.cssRules.length),b.insertRule(H,b.cssRules.length)}catch(ha){throw ha;}}}else{k=d(h,k,p).join(",");t="";if(s=n(p.element,e,"text-properties")){H=s;u=V="";P=1;s=""+g(H,A);X=H.getAttributeNS(e,"text-underline-style");"solid"===X&&(V+=" underline");X=H.getAttributeNS(e,"text-line-through-style");"solid"===X&&(V+=" line-through");V.length&&(s+="text-decoration:"+V+";");if(V=H.getAttributeNS(e,"font-name")||H.getAttributeNS(a,"font-family"))X=
+T[V],s+="font-family: "+(X||V)+";";X=H.parentNode;if(H=q(X)){for(;X;){if(H=q(X)){if("%"!==H.unit){u="font-size: "+H.value*P+H.unit+";";break}P*=H.value/100}H=X;V=X="";X=null;"default-style"===H.localName?X=null:(X=H.getAttributeNS(e,"parent-style-name"),V=H.getAttributeNS(e,"family"),X=I.getODFElementsWithXPath(N,X?"//style:*[@style:name='"+X+"'][@style:family='"+V+"']":"//style:default-style[@style:family='"+V+"']",odf.Namespaces.lookupNamespaceURI)[0])}u||(u="font-size: "+parseFloat(R)*P+ca.getUnits(R)+
+";");s+=u}t+=s}if(s=n(p.element,e,"paragraph-properties"))u=s,s=""+g(u,G),(P=n(u,e,"background-image"))&&(H=P.getAttributeNS(x,"href"))&&(s=s+("background-image: url('odfkit:"+H+"');")+g(P,J)),(u=u.getAttributeNS(a,"line-height"))&&"normal"!==u&&(u=y.parseFoLineHeight(u),s="%"!==u.unit?s+("line-height: "+u.value+u.unit+";"):s+("line-height: "+u.value/100+";")),t+=s;if(s=n(p.element,e,"graphic-properties"))H=s,s=""+g(H,D),u=H.getAttributeNS(c,"opacity"),P=H.getAttributeNS(c,"fill"),H=H.getAttributeNS(c,
+"fill-color"),"solid"===P||"hatch"===P?H&&"none"!==H?(u=isNaN(parseFloat(u))?1:parseFloat(u)/100,P=H.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,r),(H=(P=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(P))?{r:parseInt(P[1],16),g:parseInt(P[2],16),b:parseInt(P[3],16)}:null)&&(s+="background-color: rgba("+H.r+","+H.g+","+H.b+","+u+");")):s+="background: none;":"none"===P&&(s+="background: none;"),t+=s;if(s=n(p.element,e,"drawing-page-properties"))u=""+g(s,D),"true"===s.getAttributeNS(v,"background-visible")&&
+(u+="background: none;"),t+=u;if(s=n(p.element,e,"table-cell-properties"))s=""+g(s,F),t+=s;if(s=n(p.element,e,"table-row-properties"))s=""+g(s,K),t+=s;if(s=n(p.element,e,"table-column-properties"))s=""+g(s,O),t+=s;if(s=n(p.element,e,"table-properties"))u=s,s=""+g(u,Z),u=u.getAttributeNS(w,"border-model"),"collapsing"===u?s+="border-collapse:collapse;":"separating"===u&&(s+="border-collapse:separate;"),t+=s;if(0!==t.length)try{b.insertRule(k+"{"+t+"}",b.cssRules.length)}catch($){throw $;}}for(var ea in p.derivedStyles)p.derivedStyles.hasOwnProperty(ea)&&
+f(b,h,ea,p.derivedStyles[ea])}var c=odf.Namespaces.drawns,a=odf.Namespaces.fons,m=odf.Namespaces.officens,e=odf.Namespaces.stylens,t=odf.Namespaces.svgns,w=odf.Namespaces.tablens,z=odf.Namespaces.textns,x=odf.Namespaces.xlinkns,v=odf.Namespaces.presentationns,u={graphic:"draw","drawing-page":"draw",paragraph:"text",presentation:"presentation",ruby:"text",section:"text",table:"table","table-cell":"table","table-column":"table","table-row":"table",text:"text",list:"text",page:"office"},s={graphic:"circle connected control custom-shape ellipse frame g line measure page page-thumbnail path polygon polyline rect regular-polygon".split(" "),
+paragraph:"alphabetical-index-entry-template h illustration-index-entry-template index-source-style object-index-entry-template p table-index-entry-template table-of-content-entry-template user-index-entry-template".split(" "),presentation:"caption circle connector control custom-shape ellipse frame g line measure page-thumbnail path polygon polyline rect regular-polygon".split(" "),"drawing-page":"caption circle connector control page custom-shape ellipse frame g line measure page-thumbnail path polygon polyline rect regular-polygon".split(" "),
+ruby:["ruby","ruby-text"],section:"alphabetical-index bibliography illustration-index index-title object-index section table-of-content table-index user-index".split(" "),table:["background","table"],"table-cell":"body covered-table-cell even-columns even-rows first-column first-row last-column last-row odd-columns odd-rows table-cell".split(" "),"table-column":["table-column"],"table-row":["table-row"],text:"a index-entry-chapter index-entry-link-end index-entry-link-start index-entry-page-number index-entry-span index-entry-tab-stop index-entry-text index-title-template linenumbering-configuration list-level-style-number list-level-style-bullet outline-level-style span".split(" "),
+list:["list-item"]},A=[[a,"color","color"],[a,"background-color","background-color"],[a,"font-weight","font-weight"],[a,"font-style","font-style"]],J=[[e,"repeat","background-repeat"]],G=[[a,"background-color","background-color"],[a,"text-align","text-align"],[a,"text-indent","text-indent"],[a,"padding","padding"],[a,"padding-left","padding-left"],[a,"padding-right","padding-right"],[a,"padding-top","padding-top"],[a,"padding-bottom","padding-bottom"],[a,"border-left","border-left"],[a,"border-right",
+"border-right"],[a,"border-top","border-top"],[a,"border-bottom","border-bottom"],[a,"margin","margin"],[a,"margin-left","margin-left"],[a,"margin-right","margin-right"],[a,"margin-top","margin-top"],[a,"margin-bottom","margin-bottom"],[a,"border","border"]],D=[[a,"background-color","background-color"],[a,"min-height","min-height"],[c,"stroke","border"],[t,"stroke-color","border-color"],[t,"stroke-width","border-width"],[a,"border","border"],[a,"border-left","border-left"],[a,"border-right","border-right"],
+[a,"border-top","border-top"],[a,"border-bottom","border-bottom"]],F=[[a,"background-color","background-color"],[a,"border-left","border-left"],[a,"border-right","border-right"],[a,"border-top","border-top"],[a,"border-bottom","border-bottom"],[a,"border","border"]],O=[[e,"column-width","width"]],K=[[e,"row-height","height"],[a,"keep-together",null]],Z=[[e,"width","width"],[a,"margin-left","margin-left"],[a,"margin-right","margin-right"],[a,"margin-top","margin-top"],[a,"margin-bottom","margin-bottom"]],
+Q=[[a,"background-color","background-color"],[a,"padding","padding"],[a,"padding-left","padding-left"],[a,"padding-right","padding-right"],[a,"padding-top","padding-top"],[a,"padding-bottom","padding-bottom"],[a,"border","border"],[a,"border-left","border-left"],[a,"border-right","border-right"],[a,"border-top","border-top"],[a,"border-bottom","border-bottom"],[a,"margin","margin"],[a,"margin-left","margin-left"],[a,"margin-right","margin-right"],[a,"margin-top","margin-top"],[a,"margin-bottom","margin-bottom"]],
+W=[[a,"page-width","width"],[a,"page-height","height"]],H={border:!0,"border-left":!0,"border-right":!0,"border-top":!0,"border-bottom":!0,"stroke-width":!0},T={},y=new odf.OdfUtils,aa,N,R,I=xmldom.XPath,ca=new core.CSSUnits;this.style2css=function(a,c,b,e,d){for(var g,m,l,h;c.cssRules.length;)c.deleteRule(c.cssRules.length-1);g=null;e&&(g=e.ownerDocument,N=e.parentNode);d&&(g=d.ownerDocument,N=d.parentNode);if(g)for(h in odf.Namespaces.forEachPrefix(function(a,b){m="@namespace "+a+" url("+b+");";
+try{c.insertRule(m,c.cssRules.length)}catch(e){}}),T=b,aa=a,R=runtime.getWindow().getComputedStyle(document.body,null).getPropertyValue("font-size")||"12pt",a=k(e),e=k(d),d={},u)if(u.hasOwnProperty(h))for(l in b=d[h]={},p(a[h],b),p(e[h],b),b)b.hasOwnProperty(l)&&f(c,h,l,b[l])}};
+// Input 34
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -744,10 +889,8 @@ Node.ELEMENT_NODE){var e=b,f=d,h=e.getAttributeNS(k,"name"),q=void 0;h?q=k:(h=e.
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.OdfUtils");
-odf.TextSerializer=function(){function g(p){var r="",n=l.filter?l.filter.acceptNode(p):NodeFilter.FILTER_ACCEPT,h=p.nodeType,d;if(n===NodeFilter.FILTER_ACCEPT||n===NodeFilter.FILTER_SKIP)for(d=p.firstChild;d;)r+=g(d),d=d.nextSibling;n===NodeFilter.FILTER_ACCEPT&&(h===Node.ELEMENT_NODE&&f.isParagraph(p)?r+="\n":h===Node.TEXT_NODE&&p.textContent&&(r+=p.textContent));return r}var l=this,f=new odf.OdfUtils;this.filter=null;this.writeToString=function(f){if(!f)return"";f=g(f);"\n"===f[f.length-1]&&(f=
-f.substr(0,f.length-1));return f}};
-// Input 33
+ops.Canvas=function(){};ops.Canvas.prototype.getZoomLevel=function(){};ops.Canvas.prototype.getElement=function(){};
+// Input 35
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -785,22 +928,68 @@ f.substr(0,f.length-1));return f}};
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils");
-ops.TextPositionFilter=function(g){function l(d,g,c){var e,a;if(g){if(f.isInlineRoot(g)&&f.isGroupingElement(c))return h;e=f.lookLeftForCharacter(g);if(1===e||2===e&&(f.scanRightForAnyCharacter(c)||f.scanRightForAnyCharacter(f.nextNode(d))))return n}e=null===g&&f.isParagraph(d);a=f.lookRightForCharacter(c);if(e)return a?n:f.scanRightForAnyCharacter(c)?h:n;if(!a)return h;g=g||f.previousNode(d);return f.scanLeftForAnyCharacter(g)?h:n}var f=new odf.OdfUtils,p=Node.ELEMENT_NODE,r=Node.TEXT_NODE,n=core.PositionFilter.FilterResult.FILTER_ACCEPT,
-h=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(d){var m=d.container(),c=m.nodeType,e,a,b;if(c!==p&&c!==r)return h;if(c===r){if(!f.isGroupingElement(m.parentNode)||f.isWithinTrackedChanges(m.parentNode,g()))return h;c=d.unfilteredDomOffset();e=m.data;runtime.assert(c!==e.length,"Unexpected offset.");if(0<c){d=e[c-1];if(!f.isODFWhitespace(d))return n;if(1<c)if(d=e[c-2],!f.isODFWhitespace(d))a=n;else{if(!f.isODFWhitespace(e.substr(0,c)))return h}else b=f.previousNode(m),
-f.scanLeftForNonSpace(b)&&(a=n);if(a===n)return f.isTrailingWhitespace(m,c)?h:n;a=e[c];return f.isODFWhitespace(a)?h:f.scanLeftForAnyCharacter(f.previousNode(m))?h:n}b=d.leftNode();a=m;m=m.parentNode;a=l(m,b,a)}else!f.isGroupingElement(m)||f.isWithinTrackedChanges(m,g())?a=h:(b=d.leftNode(),a=d.rightNode(),a=l(m,b,a));return a}};
-// Input 34
-"function"!==typeof Object.create&&(Object.create=function(g){var l=function(){};l.prototype=g;return new l});
-xmldom.LSSerializer=function(){function g(f){var g=f||{},h=function(c){var a={},b;for(b in c)c.hasOwnProperty(b)&&(a[c[b]]=b);return a}(f),d=[g],m=[h],c=0;this.push=function(){c+=1;g=d[c]=Object.create(g);h=m[c]=Object.create(h)};this.pop=function(){d.pop();m.pop();c-=1;g=d[c];h=m[c]};this.getLocalNamespaceDefinitions=function(){return h};this.getQName=function(c){var a=c.namespaceURI,b=0,d;if(!a)return c.localName;if(d=h[a])return d+":"+c.localName;do{d||!c.prefix?(d="ns"+b,b+=1):d=c.prefix;if(g[d]===
-a)break;if(!g[d]){g[d]=a;h[a]=d;break}d=null}while(null===d);return d+":"+c.localName}}function l(f){return f.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/'/g,"&apos;").replace(/"/g,"&quot;")}function f(g,n){var h="",d=p.filter?p.filter.acceptNode(n):NodeFilter.FILTER_ACCEPT,m;if(d===NodeFilter.FILTER_ACCEPT&&n.nodeType===Node.ELEMENT_NODE){g.push();m=g.getQName(n);var c,e=n.attributes,a,b,q,k="",t;c="<"+m;a=e.length;for(b=0;b<a;b+=1)q=e.item(b),"http://www.w3.org/2000/xmlns/"!==
-q.namespaceURI&&(t=p.filter?p.filter.acceptNode(q):NodeFilter.FILTER_ACCEPT,t===NodeFilter.FILTER_ACCEPT&&(t=g.getQName(q),q="string"===typeof q.value?l(q.value):q.value,k+=" "+(t+'="'+q+'"')));a=g.getLocalNamespaceDefinitions();for(b in a)a.hasOwnProperty(b)&&((e=a[b])?"xmlns"!==e&&(c+=" xmlns:"+a[b]+'="'+b+'"'):c+=' xmlns="'+b+'"');h+=c+(k+">")}if(d===NodeFilter.FILTER_ACCEPT||d===NodeFilter.FILTER_SKIP){for(d=n.firstChild;d;)h+=f(g,d),d=d.nextSibling;n.nodeValue&&(h+=l(n.nodeValue))}m&&(h+="</"+
-m+">",g.pop());return h}var p=this;this.filter=null;this.writeToString=function(l,n){if(!l)return"";var h=new g(n);return f(h,l)}};
-// Input 35
+(function(){function k(){function a(e){b=!0;runtime.setTimeout(function(){try{e()}catch(d){runtime.log(String(d))}b=!1;0<c.length&&a(c.pop())},10)}var c=[],b=!1;this.clearQueue=function(){c.length=0};this.addToQueue=function(e){if(0===c.length&&!b)return a(e);c.push(e)}}function h(a){function c(){for(;0<b.cssRules.length;)b.deleteRule(0);b.insertRule("#shadowContent draw|page {display:none;}",0);b.insertRule("office|presentation draw|page {display:none;}",1);b.insertRule("#shadowContent draw|page:nth-of-type("+
+e+") {display:block;}",2);b.insertRule("office|presentation draw|page:nth-of-type("+e+") {display:block;}",3)}var b=a.sheet,e=1;this.showFirstPage=function(){e=1;c()};this.showNextPage=function(){e+=1;c()};this.showPreviousPage=function(){1<e&&(e-=1,c())};this.showPage=function(a){0<a&&(e=a,c())};this.css=a;this.destroy=function(c){a.parentNode.removeChild(a);c()}}function b(a){for(;a.firstChild;)a.removeChild(a.firstChild)}function p(a){a=a.sheet;for(var c=a.cssRules;c.length;)a.deleteRule(c.length-
+1)}function d(a,c,b){(new odf.Style2CSS).style2css(a.getDocumentType(),b.sheet,c.getFontMap(),a.rootElement.styles,a.rootElement.automaticStyles)}function n(a,c,b){var e=null;a=a.rootElement.body.getElementsByTagNameNS(F,b+"-decl");b=c.getAttributeNS(F,"use-"+b+"-name");var d;if(b&&0<a.length)for(c=0;c<a.length;c+=1)if(d=a[c],d.getAttributeNS(F,"name")===b){e=d.textContent;break}return e}function g(a,c,e,d){var f=a.ownerDocument;c=a.getElementsByTagNameNS(c,e);for(a=0;a<c.length;a+=1)b(c[a]),d&&(e=
+c[a],e.appendChild(f.createTextNode(d)))}function q(a,c,b){c.setAttributeNS("urn:webodf:names:helper","styleid",a);var e,d=c.getAttributeNS(J,"anchor-type"),f=c.getAttributeNS(s,"x"),g=c.getAttributeNS(s,"y"),m=c.getAttributeNS(s,"width"),l=c.getAttributeNS(s,"height"),h=c.getAttributeNS(x,"min-height"),k=c.getAttributeNS(x,"min-width");if("as-char"===d)e="display: inline-block;";else if(d||f||g)e="position: absolute;";else if(m||l||h||k)e="display: block;";f&&(e+="left: "+f+";");g&&(e+="top: "+g+
+";");m&&(e+="width: "+m+";");l&&(e+="height: "+l+";");h&&(e+="min-height: "+h+";");k&&(e+="min-width: "+k+";");e&&(e="draw|"+c.localName+'[webodfhelper|styleid="'+a+'"] {'+e+"}",b.insertRule(e,b.cssRules.length))}function r(a){for(a=a.firstChild;a;){if(a.namespaceURI===v&&"binary-data"===a.localName)return"data:image/png;base64,"+a.textContent.replace(/[\r\n\s]/g,"");a=a.nextSibling}return""}function l(a,c,b,e){function d(c){c&&(c='draw|image[webodfhelper|styleid="'+a+'"] {'+("background-image: url("+
+c+");")+"}",e.insertRule(c,e.cssRules.length))}function f(a){d(a.url)}b.setAttributeNS("urn:webodf:names:helper","styleid",a);var g=b.getAttributeNS(G,"href"),m;if(g)try{m=c.getPart(g),m.onchange=f,m.load()}catch(l){runtime.log("slight problem: "+String(l))}else g=r(b),d(g)}function f(a){var c=a.ownerDocument;Q.getElementsByTagNameNS(a,J,"line-break").forEach(function(a){a.hasChildNodes()||a.appendChild(c.createElement("br"))})}function c(a){var c=a.ownerDocument;Q.getElementsByTagNameNS(a,J,"s").forEach(function(a){for(var b,
+e;a.firstChild;)a.removeChild(a.firstChild);a.appendChild(c.createTextNode(" "));e=parseInt(a.getAttributeNS(J,"c"),10);if(1<e)for(a.removeAttributeNS(J,"c"),b=1;b<e;b+=1)a.parentNode.insertBefore(a.cloneNode(!0),a)})}function a(a){Q.getElementsByTagNameNS(a,J,"tab").forEach(function(a){a.textContent="\t"})}function m(a,c){function b(a,e){var g=m.documentElement.namespaceURI;"video/"===e.substr(0,6)?(d=m.createElementNS(g,"video"),d.setAttribute("controls","controls"),f=m.createElementNS(g,"source"),
+a&&f.setAttribute("src",a),f.setAttribute("type",e),d.appendChild(f),c.parentNode.appendChild(d)):c.innerHtml="Unrecognised Plugin"}function e(a){b(a.url,a.mimetype)}var d,f,g,m=c.ownerDocument,l;if(g=c.getAttributeNS(G,"href"))try{l=a.getPart(g),l.onchange=e,l.load()}catch(h){runtime.log("slight problem: "+String(h))}else runtime.log("using MP4 data fallback"),g=r(c),b(g,"video/mp4")}function e(a){var c=a.getElementsByTagName("head")[0],b,e;b=a.styleSheets.length;for(e=c.firstElementChild;e&&("style"!==
+e.localName||!e.hasAttribute("webodfcss"));)e=e.nextElementSibling;if(e)return b=parseInt(e.getAttribute("webodfcss"),10),e.setAttribute("webodfcss",b+1),e;"string"===String(typeof webodf_css)?b=webodf_css:(e="webodf.css",runtime.currentDirectory&&(e=runtime.currentDirectory(),0<e.length&&"/"!==e.substr(-1)&&(e+="/"),e+="../webodf.css"),b=runtime.readFileSync(e,"utf-8"));e=a.createElementNS(c.namespaceURI,"style");e.setAttribute("media","screen, print, handheld, projection");e.setAttribute("type",
+"text/css");e.setAttribute("webodfcss","1");e.appendChild(a.createTextNode(b));c.appendChild(e);return e}function t(a){var c=parseInt(a.getAttribute("webodfcss"),10);1===c?a.parentNode.removeChild(a):a.setAttribute("count",c-1)}function w(a){var c=a.getElementsByTagName("head")[0],b=a.createElementNS(c.namespaceURI,"style"),e="";b.setAttribute("type","text/css");b.setAttribute("media","screen, print, handheld, projection");odf.Namespaces.forEachPrefix(function(a,c){e+="@namespace "+a+" url("+c+");\n"});
+e+="@namespace webodfhelper url(urn:webodf:names:helper);\n";b.appendChild(a.createTextNode(e));c.appendChild(b);return b}var z=odf.Namespaces.drawns,x=odf.Namespaces.fons,v=odf.Namespaces.officens,u=odf.Namespaces.stylens,s=odf.Namespaces.svgns,A=odf.Namespaces.tablens,J=odf.Namespaces.textns,G=odf.Namespaces.xlinkns,D=odf.Namespaces.xmlns,F=odf.Namespaces.presentationns,O=runtime.getWindow(),K=xmldom.XPath,Z=new odf.OdfUtils,Q=new core.DomUtils;odf.OdfCanvas=function(r){function s(a,c,b){function e(a,
+c,b,d){C.addToQueue(function(){l(a,c,b,d)})}var d,f;d=c.getElementsByTagNameNS(z,"image");for(c=0;c<d.length;c+=1)f=d.item(c),e("image"+String(c),a,f,b)}function x(a,c){function b(a,c){C.addToQueue(function(){m(a,c)})}var e,d,f;d=c.getElementsByTagNameNS(z,"plugin");for(e=0;e<d.length;e+=1)f=d.item(e),b(a,f)}function G(){var a;a=S.firstChild;var c=ba.getZoomLevel();a&&(S.style.WebkitTransformOrigin="0% 0%",S.style.MozTransformOrigin="0% 0%",S.style.msTransformOrigin="0% 0%",S.style.OTransformOrigin=
+"0% 0%",S.style.transformOrigin="0% 0%",P&&((a=P.getMinimumHeightForAnnotationPane())?S.style.minHeight=a:S.style.removeProperty("min-height")),r.style.width=Math.round(c*S.offsetWidth)+"px",r.style.height=Math.round(c*S.offsetHeight)+"px")}function aa(a){da?(U.parentNode||S.appendChild(U),P&&P.forgetAnnotations(),P=new gui.AnnotationViewManager(I,a.body,U,ka),Q.getElementsByTagNameNS(a.body,v,"annotation").forEach(P.addAnnotation),P.rerenderAnnotations(),G()):U.parentNode&&(S.removeChild(U),P.forgetAnnotations(),
+G())}function N(e){function m(){p(V);p(ga);p(ha);b(r);r.style.display="inline-block";var l=Y.rootElement;r.ownerDocument.importNode(l,!0);M.setOdfContainer(Y);var h=Y,k=V;(new odf.FontLoader).loadFonts(h,k.sheet);d(Y,M,ga);k=Y;h=ha.sheet;b(r);S=ca.createElementNS(r.namespaceURI,"div");S.style.display="inline-block";S.style.background="white";S.style.setProperty("float","left","important");S.appendChild(l);r.appendChild(S);U=ca.createElementNS(r.namespaceURI,"div");U.id="annotationsPane";$=ca.createElementNS(r.namespaceURI,
+"div");$.id="shadowContent";$.style.position="absolute";$.style.top=0;$.style.left=0;k.getContentElement().appendChild($);var t=l.body,w,G=[],y;for(w=t.firstElementChild;w&&w!==t;)if(w.namespaceURI===z&&(G[G.length]=w),w.firstElementChild)w=w.firstElementChild;else{for(;w&&w!==t&&!w.nextElementSibling;)w=w.parentNode;w&&w.nextElementSibling&&(w=w.nextElementSibling)}for(y=0;y<G.length;y+=1)w=G[y],q("frame"+String(y),w,h);G=K.getODFElementsWithXPath(t,".//*[*[@text:anchor-type='paragraph']]",odf.Namespaces.lookupNamespaceURI);
+for(w=0;w<G.length;w+=1)t=G[w],t.setAttributeNS&&t.setAttributeNS("urn:webodf:names:helper","containsparagraphanchor",!0);var t=$,B,C,N;N=0;var I,E,G=k.rootElement.ownerDocument;if((w=l.body.firstElementChild)&&w.namespaceURI===v&&("presentation"===w.localName||"drawing"===w.localName))for(w=w.firstElementChild;w;){y=w.getAttributeNS(z,"master-page-name");if(y){for(B=k.rootElement.masterStyles.firstElementChild;B&&(B.getAttributeNS(u,"name")!==y||"master-page"!==B.localName||B.namespaceURI!==u);)B=
+B.nextElementSibling;y=B}else y=null;if(y){B=w.getAttributeNS("urn:webodf:names:helper","styleid");C=G.createElementNS(z,"draw:page");E=y.firstElementChild;for(I=0;E;)"true"!==E.getAttributeNS(F,"placeholder")&&(N=E.cloneNode(!0),C.appendChild(N),q(B+"_"+I,N,h)),E=E.nextElementSibling,I+=1;E=I=N=void 0;var R=C.getElementsByTagNameNS(z,"frame");for(N=0;N<R.length;N+=1)I=R[N],(E=I.getAttributeNS(F,"class"))&&!/^(date-time|footer|header|page-number)$/.test(E)&&I.parentNode.removeChild(I);t.appendChild(C);
+N=String(t.getElementsByTagNameNS(z,"page").length);g(C,J,"page-number",N);g(C,F,"header",n(k,w,"header"));g(C,F,"footer",n(k,w,"footer"));q(B,C,h);C.setAttributeNS(z,"draw:master-page-name",y.getAttributeNS(u,"name"))}w=w.nextElementSibling}t=r.namespaceURI;G=l.body.getElementsByTagNameNS(A,"table-cell");for(w=0;w<G.length;w+=1)y=G.item(w),y.hasAttributeNS(A,"number-columns-spanned")&&y.setAttributeNS(t,"colspan",y.getAttributeNS(A,"number-columns-spanned")),y.hasAttributeNS(A,"number-rows-spanned")&&
+y.setAttributeNS(t,"rowspan",y.getAttributeNS(A,"number-rows-spanned"));f(l.body);c(l.body);a(l.body);s(k,l.body,h);x(k,l.body);y=l.body;k=r.namespaceURI;w={};var G={},Q;B=O.document.getElementsByTagNameNS(J,"list-style");for(t=0;t<B.length;t+=1)I=B.item(t),(E=I.getAttributeNS(u,"name"))&&(G[E]=I);y=y.getElementsByTagNameNS(J,"list");for(t=0;t<y.length;t+=1)if(I=y.item(t),B=I.getAttributeNS(D,"id")){C=I.getAttributeNS(J,"continue-list");I.setAttributeNS(k,"id",B);N="text|list#"+B+" > text|list-item > *:first-child:before {";
+if(E=I.getAttributeNS(J,"style-name")){I=G[E];Q=Z.getFirstNonWhitespaceChild(I);I=void 0;if(Q)if("list-level-style-number"===Q.localName){I=Q.getAttributeNS(u,"num-format");E=Q.getAttributeNS(u,"num-suffix")||"";var R="",R={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},L=void 0,L=Q.getAttributeNS(u,"num-prefix")||"",L=R.hasOwnProperty(I)?L+(" counter(list, "+R[I]+")"):I?L+("'"+I+"';"):L+" ''";E&&(L+=" '"+E+"'");I=R="content: "+L+";"}else"list-level-style-image"===Q.localName?
+I="content: none;":"list-level-style-bullet"===Q.localName&&(I="content: '"+Q.getAttributeNS(J,"bullet-char")+"';");Q=I}if(C){for(I=w[C];I;)I=w[I];N+="counter-increment:"+C+";";Q?(Q=Q.replace("list",C),N+=Q):N+="content:counter("+C+");"}else C="",Q?(Q=Q.replace("list",B),N+=Q):N+="content: counter("+B+");",N+="counter-increment:"+B+";",h.insertRule("text|list#"+B+" {counter-reset:"+B+"}",h.cssRules.length);N+="}";w[B]=C;N&&h.insertRule(N,h.cssRules.length)}S.insertBefore($,S.firstChild);ba.setZoomableElement(S);
+aa(l);if(!e&&(l=[Y],ea.hasOwnProperty("statereadychange")))for(h=ea.statereadychange,Q=0;Q<h.length;Q+=1)h[Q].apply(null,l)}Y.state===odf.OdfContainer.DONE?m():(runtime.log("WARNING: refreshOdf called but ODF was not DONE."),fa=runtime.setTimeout(function na(){Y.state===odf.OdfContainer.DONE?m():(runtime.log("will be back later..."),fa=runtime.setTimeout(na,500))},100))}function R(a){C.clearQueue();r.innerHTML=runtime.tr("Loading")+" "+a+"...";r.removeAttribute("style");Y=new odf.OdfContainer(a,function(a){Y=
+a;N(!1)})}runtime.assert(null!==r&&void 0!==r,"odf.OdfCanvas constructor needs DOM element");runtime.assert(null!==r.ownerDocument&&void 0!==r.ownerDocument,"odf.OdfCanvas constructor needs DOM");var I=this,ca=r.ownerDocument,ia=new core.Async,Y,M=new odf.Formatting,E,S=null,U=null,da=!1,ka=!1,P=null,X,V,ga,ha,$,ea={},fa,ja,L=!1,B=!1,C=new k,ba=new gui.ZoomHelper;this.refreshCSS=function(){L=!0;ja.trigger()};this.refreshSize=function(){ja.trigger()};this.odfContainer=function(){return Y};this.setOdfContainer=
+function(a,c){Y=a;N(!0===c)};this.load=this.load=R;this.save=function(a){Y.save(a)};this.addListener=function(a,c){switch(a){case "click":var b=r,e=a;b.addEventListener?b.addEventListener(e,c,!1):b.attachEvent?b.attachEvent("on"+e,c):b["on"+e]=c;break;default:b=ea.hasOwnProperty(a)?ea[a]:ea[a]=[],c&&-1===b.indexOf(c)&&b.push(c)}};this.getFormatting=function(){return M};this.getAnnotationViewManager=function(){return P};this.refreshAnnotations=function(){aa(Y.rootElement)};this.rerenderAnnotations=
+function(){P&&(B=!0,ja.trigger())};this.getSizer=function(){return S};this.enableAnnotations=function(a,c){a!==da&&(da=a,ka=c,Y&&aa(Y.rootElement))};this.addAnnotation=function(a){P&&(P.addAnnotation(a),G())};this.forgetAnnotations=function(){P&&(P.forgetAnnotations(),G())};this.getZoomHelper=function(){return ba};this.setZoomLevel=function(a){ba.setZoomLevel(a)};this.getZoomLevel=function(){return ba.getZoomLevel()};this.fitToContainingElement=function(a,c){var b=ba.getZoomLevel(),e=r.offsetHeight/
+b,b=a/(r.offsetWidth/b);c/e<b&&(b=c/e);ba.setZoomLevel(b)};this.fitToWidth=function(a){var c=r.offsetWidth/ba.getZoomLevel();ba.setZoomLevel(a/c)};this.fitSmart=function(a,c){var b,e;e=ba.getZoomLevel();b=r.offsetWidth/e;e=r.offsetHeight/e;b=a/b;void 0!==c&&c/e<b&&(b=c/e);ba.setZoomLevel(Math.min(1,b))};this.fitToHeight=function(a){var c=r.offsetHeight/ba.getZoomLevel();ba.setZoomLevel(a/c)};this.showFirstPage=function(){E.showFirstPage()};this.showNextPage=function(){E.showNextPage()};this.showPreviousPage=
+function(){E.showPreviousPage()};this.showPage=function(a){E.showPage(a);G()};this.getElement=function(){return r};this.addCssForFrameWithImage=function(a){var c=a.getAttributeNS(z,"name"),b=a.firstElementChild;q(c,a,ha.sheet);b&&l(c+"img",Y,b,ha.sheet)};this.destroy=function(a){var c=ca.getElementsByTagName("head")[0],b=[E.destroy,ja.destroy];runtime.clearTimeout(fa);U&&U.parentNode&&U.parentNode.removeChild(U);ba.destroy(function(){S&&(r.removeChild(S),S=null)});t(X);c.removeChild(V);c.removeChild(ga);
+c.removeChild(ha);ia.destroyAll(b,a)};X=e(ca);E=new h(w(ca));V=w(ca);ga=w(ca);ha=w(ca);ja=new core.ScheduledTask(function(){L&&(d(Y,M,ga),L=!1);B&&(P&&P.rerenderAnnotations(),B=!1);G()},0);ba.subscribe(gui.ZoomHelper.signalZoomChanged,G)}})();
+// Input 36
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.MemberProperties=function(){};
+ops.Member=function(k,h){var b=new ops.MemberProperties;this.getMemberId=function(){return k};this.getProperties=function(){return b};this.setProperties=function(h){Object.keys(h).forEach(function(d){b[d]=h[d]})};this.removeProperties=function(h){Object.keys(h).forEach(function(d){"fullName"!==d&&"color"!==d&&"imageUrl"!==d&&b.hasOwnProperty(d)&&delete b[d]})};runtime.assert(Boolean(k),"No memberId was supplied!");h.fullName||(h.fullName=runtime.tr("Unknown Author"));h.color||(h.color="black");h.imageUrl||
+(h.imageUrl="avatar-joe.png");b=h};
+// Input 37
+/*
+
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
The JavaScript code in this page is free software: you can redistribute it
and/or modify it under the terms of the GNU Affero General Public License
(GNU AGPL) as published by the Free Software Foundation, either version 3 of
@@ -833,10 +1022,14 @@ m+">",g.pop());return h}var p=this;this.filter=null;this.writeToString=function(
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("odf.TextSerializer");
-gui.Clipboard=function(){var g,l,f;this.setDataFromRange=function(f,r){var n=!0,h,d=f.clipboardData;h=runtime.getWindow();var m=r.startContainer.ownerDocument;!d&&h&&(d=h.clipboardData);d?(m=m.createElement("span"),m.appendChild(r.cloneContents()),h=d.setData("text/plain",l.writeToString(m)),n=n&&h,h=d.setData("text/html",g.writeToString(m,odf.Namespaces.namespaceMap)),n=n&&h,f.preventDefault()):n=!1;return n};g=new xmldom.LSSerializer;l=new odf.TextSerializer;f=new odf.OdfNodeFilter;g.filter=f;l.filter=
-f};
-// Input 36
+gui.SelectionMover=function(k,h){function b(){f.setUnfilteredPosition(k.getNode(),0);return f}function p(a,c){var b,d=null;a&&0<a.length&&(b=c?a.item(a.length-1):a.item(0));b&&(d={top:b.top,left:c?b.right:b.left,bottom:b.bottom});return d}function d(a,c,b,f){var g=a.nodeType;b.setStart(a,c);b.collapse(!f);f=p(b.getClientRects(),!0===f);!f&&0<c&&(b.setStart(a,c-1),b.setEnd(a,c),f=p(b.getClientRects(),!0));f||(g===Node.ELEMENT_NODE&&0<c&&a.childNodes.length>=c?f=d(a,c-1,b,!0):a.nodeType===Node.TEXT_NODE&&
+0<c?f=d(a,c-1,b,!0):a.previousSibling?f=d(a.previousSibling,a.previousSibling.nodeType===Node.TEXT_NODE?a.previousSibling.textContent.length:a.previousSibling.childNodes.length,b,!0):a.parentNode&&a.parentNode!==h?f=d(a.parentNode,0,b,!1):(b.selectNode(h),f=p(b.getClientRects(),!1)));runtime.assert(Boolean(f),"No visible rectangle found");return f}function n(a,d,e){for(var f=b(),g=new core.LoopWatchDog(1E4),l=0,h=0;0<a&&f.nextPosition();)g.check(),e.acceptPosition(f)===c&&(l+=1,d.acceptPosition(f)===
+c&&(h+=l,l=0,a-=1));return h}function g(a,d,e){for(var f=b(),g=new core.LoopWatchDog(1E4),l=0,h=0;0<a&&f.previousPosition();)g.check(),e.acceptPosition(f)===c&&(l+=1,d.acceptPosition(f)===c&&(h+=l,l=0,a-=1));return h}function q(a,f){var e=b(),g=0,l=0,k=0>a?-1:1;for(a=Math.abs(a);0<a;){for(var n=f,q=k,p=e,r=p.container(),A=0,J=null,G=void 0,D=10,F=void 0,O=0,K=void 0,Z=void 0,Q=void 0,F=void 0,W=h.ownerDocument.createRange(),H=new core.LoopWatchDog(1E4),F=d(r,p.unfilteredDomOffset(),W),K=F.top,Z=F.left,
+Q=K;!0===(0>q?p.previousPosition():p.nextPosition());)if(H.check(),n.acceptPosition(p)===c&&(A+=1,r=p.container(),F=d(r,p.unfilteredDomOffset(),W),F.top!==K)){if(F.top!==Q&&Q!==K)break;Q=F.top;F=Math.abs(Z-F.left);if(null===J||F<D)J=r,G=p.unfilteredDomOffset(),D=F,O=A}null!==J?(p.setUnfilteredPosition(J,G),A=O):A=0;W.detach();g+=A;if(0===g)break;l+=g;a-=1}return l*k}function r(a,f){var e,g,k,n,q=b(),p=l.getParagraphElement(q.getCurrentNode()),r=0,s=h.ownerDocument.createRange();0>a?(e=q.previousPosition,
+g=-1):(e=q.nextPosition,g=1);for(k=d(q.container(),q.unfilteredDomOffset(),s);e.call(q);)if(f.acceptPosition(q)===c){if(l.getParagraphElement(q.getCurrentNode())!==p)break;n=d(q.container(),q.unfilteredDomOffset(),s);if(n.bottom!==k.bottom&&(k=n.top>=k.top&&n.bottom<k.bottom||n.top<=k.top&&n.bottom>k.bottom,!k))break;r+=g;k=n}s.detach();return r}var l=new odf.OdfUtils,f,c=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.getStepCounter=function(){return{convertForwardStepsBetweenFilters:n,convertBackwardStepsBetweenFilters:g,
+countLinesSteps:q,countStepsToLineBoundary:r}};(function(){f=gui.SelectionMover.createPositionIterator(h);var a=h.ownerDocument.createRange();a.setStart(f.container(),f.unfilteredDomOffset());a.collapse(!0);k.setSelectedRange(a)})()};
+gui.SelectionMover.createPositionIterator=function(k){var h=new function(){this.acceptNode=function(b){return b&&"urn:webodf:names:cursor"!==b.namespaceURI&&"urn:webodf:names:editinfo"!==b.namespaceURI?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}};return new core.PositionIterator(k,5,h,!1)};(function(){return gui.SelectionMover})();
+// Input 38
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -874,34 +1067,13 @@ f};
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.Base64");runtime.loadClass("core.Zip");runtime.loadClass("core.DomUtils");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfNodeFilter");
-(function(){function g(a,b,c){for(a=a?a.firstChild:null;a;){if(a.localName===c&&a.namespaceURI===b)return a;a=a.nextSibling}return null}function l(a){var b,c=m.length;for(b=0;b<c;b+=1)if("urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&a.localName===m[b])return b;return-1}function f(a,b){var c=new n.UsedStyleList(a,b),d=new odf.OdfNodeFilter;this.acceptNode=function(a){var e=d.acceptNode(a);e===NodeFilter.FILTER_ACCEPT&&a.parentNode===b&&a.nodeType===Node.ELEMENT_NODE&&(e=c.uses(a)?
-NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT);return e}}function p(a,b){var c=new f(a,b);this.acceptNode=function(a){var b=c.acceptNode(a);b!==NodeFilter.FILTER_ACCEPT||!a.parentNode||a.parentNode.namespaceURI!==odf.Namespaces.textns||"s"!==a.parentNode.localName&&"tab"!==a.parentNode.localName||(b=NodeFilter.FILTER_REJECT);return b}}function r(a,b){if(b){var c=l(b),d,e=a.firstChild;if(-1!==c){for(;e;){d=l(e);if(-1!==d&&d>c)break;e=e.nextSibling}a.insertBefore(b,e)}}}var n=new odf.StyleInfo,
-h=new core.DomUtils,d=odf.Namespaces.stylens,m="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "),c=(new Date).getTime()+"_webodf_",e=new core.Base64;odf.ODFElement=function(){};odf.ODFDocumentElement=function(){};odf.ODFDocumentElement.prototype=new odf.ODFElement;odf.ODFDocumentElement.prototype.constructor=odf.ODFDocumentElement;odf.ODFDocumentElement.prototype.fontFaceDecls=null;odf.ODFDocumentElement.prototype.manifest=null;odf.ODFDocumentElement.prototype.settings=
-null;odf.ODFDocumentElement.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";odf.ODFDocumentElement.localName="document";odf.OdfPart=function(a,b,c,d){var e=this;this.size=0;this.type=null;this.name=a;this.container=c;this.url=null;this.mimetype=b;this.onstatereadychange=this.document=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.data="";this.load=function(){null!==d&&(this.mimetype=b,d.loadAsDataURL(a,b,function(a,b){a&&runtime.log(a);e.url=b;if(e.onchange)e.onchange(e);
-if(e.onstatereadychange)e.onstatereadychange(e)}))}};odf.OdfPart.prototype.load=function(){};odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+e.toBase64(this.data):null};odf.OdfContainer=function b(q,k){function m(b){for(var c=b.firstChild,d;c;)d=c.nextSibling,c.nodeType===Node.ELEMENT_NODE?m(c):c.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&b.removeChild(c),c=d}function l(b,c){for(var d=b&&b.firstChild;d;)d.nodeType===Node.ELEMENT_NODE&&d.setAttributeNS("urn:webodf:names:scope",
-"scope",c),d=d.nextSibling}function w(b){var c={},e;for(b=b.firstChild;b;)b.nodeType===Node.ELEMENT_NODE&&b.namespaceURI===d&&"font-face"===b.localName&&(e=b.getAttributeNS(d,"name"),c[e]=b),b=b.nextSibling;return c}function x(b,c){var d=null,e,f,h;if(b)for(d=b.cloneNode(!0),e=d.firstElementChild;e;)f=e.nextElementSibling,(h=e.getAttributeNS("urn:webodf:names:scope","scope"))&&h!==c&&d.removeChild(e),e=f;return d}function v(b,c){var e,f,h,k=null,g={};if(b)for(c.forEach(function(b){n.collectUsedFontFaces(g,
-b)}),k=b.cloneNode(!0),e=k.firstElementChild;e;)f=e.nextElementSibling,h=e.getAttributeNS(d,"name"),g[h]||k.removeChild(e),e=f;return k}function u(b){var c=R.rootElement.ownerDocument,d;if(b){m(b.documentElement);try{d=c.importNode(b.documentElement,!0)}catch(e){}}return d}function s(b){R.state=b;if(R.onchange)R.onchange(R);if(R.onstatereadychange)R.onstatereadychange(R)}function H(b){ba=null;R.rootElement=b;b.fontFaceDecls=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");
-b.styles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");b.automaticStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");b.masterStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");b.body=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");b.meta=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta")}function y(d){var e=u(d),f=R.rootElement,h;e&&"document-styles"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===
-e.namespaceURI?(f.fontFaceDecls=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),r(f,f.fontFaceDecls),h=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),f.styles=h||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),r(f,f.styles),h=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),f.automaticStyles=h||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),l(f.automaticStyles,
-"document-styles"),r(f,f.automaticStyles),e=g(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),f.masterStyles=e||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),r(f,f.masterStyles),n.prefixStyleNames(f.automaticStyles,c,f.masterStyles)):s(b.INVALID)}function B(c){c=u(c);var e,f,h,k;if(c&&"document-content"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===c.namespaceURI){e=R.rootElement;h=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0",
-"font-face-decls");if(e.fontFaceDecls&&h){k=e.fontFaceDecls;var q,m,p,t,v={};f=w(k);t=w(h);for(h=h.firstElementChild;h;){q=h.nextElementSibling;if(h.namespaceURI===d&&"font-face"===h.localName)if(m=h.getAttributeNS(d,"name"),f.hasOwnProperty(m)){if(!h.isEqualNode(f[m])){p=m;for(var y=f,I=t,z=0,B=void 0,B=p=p.replace(/\d+$/,"");y.hasOwnProperty(B)||I.hasOwnProperty(B);)z+=1,B=p+z;p=B;h.setAttributeNS(d,"style:name",p);k.appendChild(h);f[p]=h;delete t[m];v[m]=p}}else k.appendChild(h),f[m]=h,delete t[m];
-h=q}k=v}else h&&(e.fontFaceDecls=h,r(e,h));f=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");l(f,"document-content");k&&n.changeFontFaceNames(f,k);if(e.automaticStyles&&f)for(k=f.firstChild;k;)e.automaticStyles.appendChild(k),k=f.firstChild;else f&&(e.automaticStyles=f,r(e,f));c=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===c)throw"<office:body/> tag is mising.";e.body=c;r(e,e.body)}else s(b.INVALID)}function L(b){b=u(b);var c;b&&"document-meta"===
-b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI&&(c=R.rootElement,c.meta=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),r(c,c.meta))}function I(b){b=u(b);var c;b&&"document-settings"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI&&(c=R.rootElement,c.settings=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),r(c,c.settings))}function W(b){b=u(b);var c;if(b&&"manifest"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===
-b.namespaceURI)for(c=R.rootElement,c.manifest=b,b=c.manifest.firstElementChild;b;)"file-entry"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===b.namespaceURI&&(M[b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),b=b.nextElementSibling}function Q(c){var d=c.shift();d?P.loadAsDOM(d.path,function(e,f){d.handler(f);e||R.state===b.INVALID||Q(c)}):s(b.DONE)}function z(b){var c=
-"";odf.Namespaces.forEachPrefix(function(b,d){c+=" xmlns:"+b+'="'+d+'"'});return'<?xml version="1.0" encoding="UTF-8"?><office:'+b+" "+c+' office:version="1.2">'}function ja(){var b=new xmldom.LSSerializer,c=z("document-meta");b.filter=new odf.OdfNodeFilter;c+=b.writeToString(R.rootElement.meta,odf.Namespaces.namespaceMap);return c+"</office:document-meta>"}function ka(b,c){var d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0",
-"manifest:full-path",b);d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:media-type",c);return d}function G(){var b=runtime.parseXML('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2"></manifest:manifest>'),c=g(b,"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest"),d=new xmldom.LSSerializer,e;for(e in M)M.hasOwnProperty(e)&&c.appendChild(ka(e,M[e]));d.filter=new odf.OdfNodeFilter;return'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'+
-d.writeToString(b,odf.Namespaces.namespaceMap)}function Z(){var b=new xmldom.LSSerializer,c=z("document-settings");b.filter=new odf.OdfNodeFilter;c+=b.writeToString(R.rootElement.settings,odf.Namespaces.namespaceMap);return c+"</office:document-settings>"}function O(){var b,d,e,h=odf.Namespaces.namespaceMap,k=new xmldom.LSSerializer,g=z("document-styles");d=x(R.rootElement.automaticStyles,"document-styles");e=R.rootElement.masterStyles.cloneNode(!0);b=v(R.rootElement.fontFaceDecls,[e,R.rootElement.styles,
-d]);n.removePrefixFromStyleNames(d,c,e);k.filter=new f(e,d);g+=k.writeToString(b,h);g+=k.writeToString(R.rootElement.styles,h);g+=k.writeToString(d,h);g+=k.writeToString(e,h);return g+"</office:document-styles>"}function aa(){var b,c,d=odf.Namespaces.namespaceMap,e=new xmldom.LSSerializer,f=z("document-content");c=x(R.rootElement.automaticStyles,"document-content");b=v(R.rootElement.fontFaceDecls,[c]);e.filter=new p(R.rootElement.body,c);f+=e.writeToString(b,d);f+=e.writeToString(c,d);f+=e.writeToString(R.rootElement.body,
-d);return f+"</office:document-content>"}function J(c,d){runtime.loadXML(c,function(c,e){if(c)d(c);else{var f=u(e);f&&"document"===f.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===f.namespaceURI?(H(f),s(b.DONE)):s(b.INVALID)}})}function F(b,c){var d;d=R.rootElement;var e=d.meta;e||(d.meta=e=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),r(d,e));d=e;b&&h.mapKeyValObjOntoNode(d,b,odf.Namespaces.lookupNamespaceURI);c&&h.removeKeyElementsFromNode(d,
-c,odf.Namespaces.lookupNamespaceURI)}function C(){function c(b,d){var e;d||(d=b);e=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",d);f[b]=e;f.appendChild(e)}var d=new core.Zip("",null),e=runtime.byteArrayFromString("application/vnd.oasis.opendocument.text","utf8"),f=R.rootElement,h=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text");d.save("mimetype",e,!1,new Date);c("meta");c("settings");c("scripts");c("fontFaceDecls","font-face-decls");
-c("styles");c("automaticStyles","automatic-styles");c("masterStyles","master-styles");c("body");f.body.appendChild(h);s(b.DONE);return d}function Y(){var b,c=new Date,d=runtime.getWindow();b="WebODF/"+("undefined"!==String(typeof webodf_version)?webodf_version:"FromSource");d&&(b=b+" "+d.navigator.userAgent);F({"meta:generator":b},null);b=runtime.byteArrayFromString(Z(),"utf8");P.save("settings.xml",b,!0,c);b=runtime.byteArrayFromString(ja(),"utf8");P.save("meta.xml",b,!0,c);b=runtime.byteArrayFromString(O(),
-"utf8");P.save("styles.xml",b,!0,c);b=runtime.byteArrayFromString(aa(),"utf8");P.save("content.xml",b,!0,c);b=runtime.byteArrayFromString(G(),"utf8");P.save("META-INF/manifest.xml",b,!0,c)}function U(b,c){Y();P.writeAs(b,function(b){c(b)})}var R=this,P,M={},ba;this.onstatereadychange=k;this.state=this.onchange=null;this.setRootElement=H;this.getContentElement=function(){var b;ba||(b=R.rootElement.body,ba=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0",
-"presentation")||g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!ba)throw"Could not find content element in <office:body/>.";return ba};this.getDocumentType=function(){var b=R.getContentElement();return b&&b.localName};this.getPart=function(b){return new odf.OdfPart(b,M[b],R,P)};this.getPartData=function(b,c){P.load(b,c)};this.setMetadata=F;this.incrementEditingCycles=function(){var b;for(b=(b=R.rootElement.meta)&&b.firstChild;b&&(b.namespaceURI!==odf.Namespaces.metans||
-"editing-cycles"!==b.localName);)b=b.nextSibling;for(b=b&&b.firstChild;b&&b.nodeType!==Node.TEXT_NODE;)b=b.nextSibling;b=b?b.data:null;b=b?parseInt(b,10):0;isNaN(b)&&(b=0);F({"meta:editing-cycles":b+1},null)};this.createByteArray=function(b,c){Y();P.createByteArray(b,c)};this.saveAs=U;this.save=function(b){U(q,b)};this.getUrl=function(){return q};this.setBlob=function(b,c,d){d=e.convertBase64ToByteArray(d);P.save(b,d,!1,new Date);M.hasOwnProperty(b)&&runtime.log(b+" has been overwritten.");M[b]=c};
-this.removeBlob=function(b){var c=P.remove(b);runtime.assert(c,"file is not found: "+b);delete M[b]};this.state=b.LOADING;this.rootElement=function(b){var c=document.createElementNS(b.namespaceURI,b.localName),d;b=new b.Type;for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);return c}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentElement.namespaceURI,localName:odf.ODFDocumentElement.localName});P=q?new core.Zip(q,function(c,d){P=d;c?J(q,function(d){c&&(P.error=c+"\n"+d,s(b.INVALID))}):Q([{path:"styles.xml",
-handler:y},{path:"content.xml",handler:B},{path:"meta.xml",handler:L},{path:"settings.xml",handler:I},{path:"META-INF/manifest.xml",handler:W}])}):C()};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADING=1;odf.OdfContainer.DONE=2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED=5;odf.OdfContainer.getContainer=function(b){return new odf.OdfContainer(b,null)};return odf.OdfContainer})();
-// Input 37
+ops.Document=function(){};ops.Document.prototype.getMemberIds=function(){};ops.Document.prototype.removeCursor=function(k){};ops.Document.prototype.getDocumentElement=function(){};ops.Document.prototype.getRootNode=function(){};ops.Document.prototype.getDOMDocument=function(){};ops.Document.prototype.cloneDocumentElement=function(){};ops.Document.prototype.setDocumentElement=function(k){};ops.Document.prototype.subscribe=function(k,h){};ops.Document.prototype.unsubscribe=function(k,h){};
+ops.Document.prototype.getCanvas=function(){};ops.Document.prototype.createRootFilter=function(k){};ops.Document.signalCursorAdded="cursor/added";ops.Document.signalCursorRemoved="cursor/removed";ops.Document.signalCursorMoved="cursor/moved";ops.Document.signalMemberAdded="member/added";ops.Document.signalMemberUpdated="member/updated";ops.Document.signalMemberRemoved="member/removed";
+// Input 39
+ops.OdtCursor=function(k,h){var b=this,p={},d,n,g,q=new core.EventNotifier([ops.OdtCursor.signalCursorUpdated]);this.removeFromDocument=function(){g.remove()};this.subscribe=function(b,d){q.subscribe(b,d)};this.unsubscribe=function(b,d){q.unsubscribe(b,d)};this.getStepCounter=function(){return n.getStepCounter()};this.getMemberId=function(){return k};this.getNode=function(){return g.getNode()};this.getAnchorNode=function(){return g.getAnchorNode()};this.getSelectedRange=function(){return g.getSelectedRange()};
+this.setSelectedRange=function(d,l){g.setSelectedRange(d,l);q.emit(ops.OdtCursor.signalCursorUpdated,b)};this.hasForwardSelection=function(){return g.hasForwardSelection()};this.getDocument=function(){return h};this.getSelectionType=function(){return d};this.setSelectionType=function(b){p.hasOwnProperty(b)?d=b:runtime.log("Invalid selection type: "+b)};this.resetSelectionType=function(){b.setSelectionType(ops.OdtCursor.RangeSelection)};g=new core.Cursor(h.getDOMDocument(),k);n=new gui.SelectionMover(g,
+h.getRootNode());p[ops.OdtCursor.RangeSelection]=!0;p[ops.OdtCursor.RegionSelection]=!0;b.resetSelectionType()};ops.OdtCursor.RangeSelection="Range";ops.OdtCursor.RegionSelection="Region";ops.OdtCursor.signalCursorUpdated="cursorUpdated";(function(){return ops.OdtCursor})();
+// Input 40
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -939,11 +1111,41 @@ handler:y},{path:"content.xml",handler:B},{path:"meta.xml",handler:L},{path:"set
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.Base64");runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.OdfContainer");
-(function(){function g(l,r,n,h,d){var m,c=0,e;for(e in l)if(l.hasOwnProperty(e)){if(c===n){m=e;break}c+=1}m?r.getPartData(l[m].href,function(a,b){if(a)runtime.log(a);else if(b){var c="@font-face { font-family: '"+(l[m].family||m)+"'; src: url(data:application/x-font-ttf;charset=binary;base64,"+f.convertUTF8ArrayToBase64(b)+') format("truetype"); }';try{h.insertRule(c,h.cssRules.length)}catch(e){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(e)+"\nRule: "+c)}}else runtime.log("missing font data for "+
-l[m].href);g(l,r,n+1,h,d)}):d&&d()}var l=xmldom.XPath,f=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(f,r){for(var n=f.rootElement.fontFaceDecls;r.cssRules.length;)r.deleteRule(r.cssRules.length-1);if(n){var h={},d,m,c,e;if(n)for(n=l.getODFElementsWithXPath(n,"style:font-face[svg:font-face-src]",odf.Namespaces.lookupNamespaceURI),d=0;d<n.length;d+=1)m=n[d],c=m.getAttributeNS(odf.Namespaces.stylens,"name"),e=m.getAttributeNS(odf.Namespaces.svgns,"font-family"),m=l.getODFElementsWithXPath(m,
-"svg:font-face-src/svg:font-face-uri",odf.Namespaces.lookupNamespaceURI),0<m.length&&(m=m[0].getAttributeNS(odf.Namespaces.xlinkns,"href"),h[c]={href:m,family:e});g(h,f,0,r)}}};return odf.FontLoader})();
-// Input 38
+ops.Operation=function(){};ops.Operation.prototype.init=function(k){};ops.Operation.prototype.execute=function(k){};ops.Operation.prototype.spec=function(){};
+// Input 41
+/*
+
+ Copyright (C) 2010-2014 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+(function(){var k=0;ops.StepsCache=function(h,b,p){function d(a,c,e){this.nodeId=a;this.steps=c;this.node=e;this.previousBookmark=this.nextBookmark=null;this.setIteratorPosition=function(a){a.setPositionBeforeElement(e);do if(b.acceptPosition(a)===u)break;while(a.nextPosition())}}function n(a,c,e){this.nodeId=a;this.steps=c;this.node=e;this.previousBookmark=this.nextBookmark=null;this.setIteratorPosition=function(a){a.setUnfilteredPosition(e,0);do if(b.acceptPosition(a)===u)break;while(a.nextPosition())}}
+function g(a,c){var b="["+a.nodeId;c&&(b+=" => "+c.nodeId);return b+"]"}function q(){for(var a=x,c,b,e,d=new core.LoopWatchDog(0,1E5);a;){d.check();(c=a.previousBookmark)?runtime.assert(c.nextBookmark===a,"Broken bookmark link to previous @"+g(c,a)):(runtime.assert(a===x,"Broken bookmark link @"+g(a)),runtime.assert(void 0===v||x.steps<=v,"Base point is damaged @"+g(a)));(b=a.nextBookmark)&&runtime.assert(b.previousBookmark===a,"Broken bookmark link to next @"+g(a,b));if(void 0===v||a.steps<=v)runtime.assert(z.containsNode(h,
+a.node),"Disconnected node is being reported as undamaged @"+g(a)),c&&(e=a.node.compareDocumentPosition(c.node),runtime.assert(0===e||0!==(e&Node.DOCUMENT_POSITION_PRECEDING),"Bookmark order with previous does not reflect DOM order @"+g(c,a))),b&&z.containsNode(h,b.node)&&(e=a.node.compareDocumentPosition(b.node),runtime.assert(0===e||0!==(e&Node.DOCUMENT_POSITION_FOLLOWING),"Bookmark order with next does not reflect DOM order @"+g(a,b)));a=a.nextBookmark}}function r(a){var c="";a.nodeType===Node.ELEMENT_NODE&&
+(c=a.getAttributeNS(m,"nodeId"));return c}function l(a){var c=k.toString();a.setAttributeNS(m,"nodeId",c);k+=1;return c}function f(a){var c,b,d=new core.LoopWatchDog(0,1E4);void 0!==v&&a>v&&(a=v);for(c=Math.floor(a/p)*p;!b&&0!==c;)b=e[c],c-=p;for(b=b||x;b.nextBookmark&&b.nextBookmark.steps<=a;)d.check(),b=b.nextBookmark;return b}function c(a){a.previousBookmark&&(a.previousBookmark.nextBookmark=a.nextBookmark);a.nextBookmark&&(a.nextBookmark.previousBookmark=a.previousBookmark)}function a(a){for(var c,
+b=null;!b&&a&&a!==h;)(c=r(a))&&(b=t[c])&&b.node!==a&&(runtime.log("Cloned node detected. Creating new bookmark"),b=null,a.removeAttributeNS(m,"nodeId")),a=a.parentNode;return b}var m="urn:webodf:names:steps",e={},t={},w=new odf.OdfUtils,z=new core.DomUtils,x,v,u=core.PositionFilter.FilterResult.FILTER_ACCEPT,s;this.updateCache=function(a,b,g){var m;m=b.getCurrentNode();if(b.isBeforeNode()&&w.isParagraph(m)){g||(a+=1);b=a;var k,n,q;if(void 0!==v&&v<b){k=f(v);for(g=k.nextBookmark;g&&g.steps<=b;)n=g.nextBookmark,
+q=Math.ceil(g.steps/p)*p,e[q]===g&&delete e[q],z.containsNode(h,g.node)?g.steps=b+1:(c(g),delete t[g.nodeId]),g=n;v=b}else k=f(b);b=k;g=r(m)||l(m);(k=t[g])?k.node===m?k.steps=a:(runtime.log("Cloned node detected. Creating new bookmark"),g=l(m),k=t[g]=new d(g,a,m)):k=t[g]=new d(g,a,m);m=k;b!==m&&b.nextBookmark!==m&&(c(m),a=b.nextBookmark,m.nextBookmark=b.nextBookmark,m.previousBookmark=b,b.nextBookmark=m,a&&(a.previousBookmark=m));a=Math.ceil(m.steps/p)*p;b=e[a];if(!b||m.steps>b.steps)e[a]=m;s()}};
+this.setToClosestStep=function(a,c){var b;s();b=f(a);b.setIteratorPosition(c);return b.steps};this.setToClosestDomPoint=function(c,b,d){var g,m;s();if(c===h&&0===b)g=x;else if(c===h&&b===h.childNodes.length)for(m in g=x,e)e.hasOwnProperty(m)&&(c=e[m],c.steps>g.steps&&(g=c));else if(g=a(c.childNodes.item(b)||c),!g)for(d.setUnfilteredPosition(c,b);!g&&d.previousNode();)g=a(d.getCurrentNode());g=g||x;void 0!==v&&g.steps>v&&(g=f(v));g.setIteratorPosition(d);return g.steps};this.damageCacheAfterStep=function(a){0>
+a&&(a=0);void 0===v?v=a:a<v&&(v=a);s()};(function(){var a=r(h)||l(h);x=new n(a,0,h);s=ops.StepsCache.ENABLE_CACHE_VERIFICATION?q:function(){}})()};ops.StepsCache.ENABLE_CACHE_VERIFICATION=!1;ops.StepsCache.Bookmark=function(){};ops.StepsCache.Bookmark.prototype.setIteratorPosition=function(h){}})();
+// Input 42
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -981,11 +1183,11 @@ l[m].href);g(l,r,n+1,h,d)}):d&&d()}var l=xmldom.XPath,f=new core.Base64;odf.Font
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");runtime.loadClass("core.Utils");
-odf.ObjectNameGenerator=function(g,l){function f(a,b){var c={};this.generateName=function(){var d=b(),e=0,f;do f=a+e,e+=1;while(c[f]||d[f]);c[f]=!0;return f}}function p(){var a={};[g.rootElement.automaticStyles,g.rootElement.styles].forEach(function(b){for(b=b.firstElementChild;b;)b.namespaceURI===r&&"style"===b.localName&&(a[b.getAttributeNS(r,"name")]=!0),b=b.nextElementSibling});return a}var r=odf.Namespaces.stylens,n=odf.Namespaces.drawns,h=odf.Namespaces.xlinkns,d=new core.DomUtils,m=(new core.Utils).hashString(l),
-c=null,e=null,a=null,b={},q={};this.generateStyleName=function(){null===c&&(c=new f("auto"+m+"_",function(){return p()}));return c.generateName()};this.generateFrameName=function(){null===e&&(d.getElementsByTagNameNS(g.rootElement.body,n,"frame").forEach(function(a){b[a.getAttributeNS(n,"name")]=!0}),e=new f("fr"+m+"_",function(){return b}));return e.generateName()};this.generateImageName=function(){null===a&&(d.getElementsByTagNameNS(g.rootElement.body,n,"image").forEach(function(a){a=a.getAttributeNS(h,
-"href");a=a.substring(9,a.lastIndexOf("."));q[a]=!0}),a=new f("img"+m+"_",function(){return q}));return a.generateName()}};
-// Input 39
+(function(){ops.StepsTranslator=function(k,h,b,p){function d(){var c=k();c!==g&&(runtime.log("Undo detected. Resetting steps cache"),g=c,q=new ops.StepsCache(g,b,p),l=h(g))}function n(c,a){if(!a||b.acceptPosition(c)===f)return!0;for(;c.previousPosition();)if(b.acceptPosition(c)===f){if(a(0,c.container(),c.unfilteredDomOffset()))return!0;break}for(;c.nextPosition();)if(b.acceptPosition(c)===f){if(a(1,c.container(),c.unfilteredDomOffset()))return!0;break}return!1}var g=k(),q=new ops.StepsCache(g,b,
+p),r=new core.DomUtils,l=h(k()),f=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.convertStepsToDomPoint=function(c){var a,g;if(isNaN(c))throw new TypeError("Requested steps is not numeric ("+c+")");if(0>c)throw new RangeError("Requested steps is negative ("+c+")");d();for(a=q.setToClosestStep(c,l);a<c&&l.nextPosition();)(g=b.acceptPosition(l)===f)&&(a+=1),q.updateCache(a,l,g);if(a!==c)throw new RangeError("Requested steps ("+c+") exceeds available steps ("+a+")");return{node:l.container(),offset:l.unfilteredDomOffset()}};
+this.convertDomPointToSteps=function(c,a,m){var e;d();r.containsNode(g,c)||(a=0>r.comparePoints(g,0,c,a),c=g,a=a?0:g.childNodes.length);l.setUnfilteredPosition(c,a);n(l,m)||l.setUnfilteredPosition(c,a);m=l.container();a=l.unfilteredDomOffset();c=q.setToClosestDomPoint(m,a,l);if(0>r.comparePoints(l.container(),l.unfilteredDomOffset(),m,a))return 0<c?c-1:c;for(;(l.container()!==m||l.unfilteredDomOffset()!==a)&&l.nextPosition();)(e=b.acceptPosition(l)===f)&&(c+=1),q.updateCache(c,l,e);return c+0};this.prime=
+function(){var c,a;d();for(c=q.setToClosestStep(0,l);l.nextPosition();)(a=b.acceptPosition(l)===f)&&(c+=1),q.updateCache(c,l,a)};this.handleStepsInserted=function(c){d();q.damageCacheAfterStep(c.position)};this.handleStepsRemoved=function(c){d();q.damageCacheAfterStep(c.position-1)}};ops.StepsTranslator.PREVIOUS_STEP=0;ops.StepsTranslator.NEXT_STEP=1;return ops.StepsTranslator})();
+// Input 43
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1023,21 +1225,10 @@ c=null,e=null,a=null,b={},q={};this.generateStyleName=function(){null===c&&(c=ne
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.Utils");runtime.loadClass("odf.ObjectNameGenerator");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfContainer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.OdfUtils");
-odf.Formatting=function(){function g(a){return(a=u[a])?v.mergeObjects({},a):{}}function l(a,b,c){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==b||a.localName!==c);)a=a.nextElementSibling;return a}function f(){for(var a=e.rootElement.fontFaceDecls,c={},d,f,a=a&&a.firstElementChild;a;){if(d=a.getAttributeNS(q,"name"))if((f=a.getAttributeNS(b,"font-family"))||0<a.getElementsByTagNameNS(b,"font-face-uri").length)c[d]=f;a=a.nextElementSibling}return c}function p(a){for(var b=e.rootElement.styles.firstElementChild;b;){if(b.namespaceURI===
-q&&"default-style"===b.localName&&b.getAttributeNS(q,"family")===a)return b;b=b.nextElementSibling}return null}function r(a,b,c){var d,f,h;c=c||[e.rootElement.automaticStyles,e.rootElement.styles];for(h=0;h<c.length;h+=1)for(d=c[h],d=d.firstElementChild;d;){f=d.getAttributeNS(q,"name");if(d.namespaceURI===q&&"style"===d.localName&&d.getAttributeNS(q,"family")===b&&f===a||"list-style"===b&&d.namespaceURI===k&&"list-style"===d.localName&&f===a||"data"===b&&d.namespaceURI===t&&f===a)return d;d=d.nextElementSibling}return null}
-function n(a){for(var b,c,d,e,f={},h=a.firstElementChild;h;){if(h.namespaceURI===q)for(d=f[h.nodeName]={},c=h.attributes,b=0;b<c.length;b+=1)e=c.item(b),d[e.name]=e.value;h=h.nextElementSibling}c=a.attributes;for(b=0;b<c.length;b+=1)e=c.item(b),f[e.name]=e.value;return f}function h(a,b){for(var c=e.rootElement.styles,d,f={},h=a.getAttributeNS(q,"family"),k=a;k;)d=n(k),f=v.mergeObjects(d,f),k=(d=k.getAttributeNS(q,"parent-style-name"))?r(d,h,[c]):null;if(k=p(h))d=n(k),f=v.mergeObjects(d,f);b&&(d=g(h))&&
-(f=v.mergeObjects(d,f));return f}function d(b,c){function d(a){Object.keys(a).forEach(function(b){Object.keys(a[b]).forEach(function(a){k+="|"+b+":"+a+"|"})})}for(var e=b.nodeType===Node.TEXT_NODE?b.parentNode:b,f,h=[],k="",g=!1;e;)!g&&w.isGroupingElement(e)&&(g=!0),(f=a.determineStylesForNode(e))&&h.push(f),e=e.parentElement;g&&(h.forEach(d),c&&(c[k]=h));return g?h:void 0}function m(a){var b={orderedStyles:[]};a.forEach(function(a){Object.keys(a).forEach(function(c){var d=Object.keys(a[c])[0],e,
-f;(e=r(d,c))?(f=h(e),b=v.mergeObjects(f,b),f=e.getAttributeNS(q,"display-name")):runtime.log("No style element found for '"+d+"' of family '"+c+"'");b.orderedStyles.push({name:d,family:c,displayName:f})})});return b}function c(a,b){var c=w.parseLength(a),d=b;if(c)switch(c.unit){case "cm":d=c.value;break;case "mm":d=0.1*c.value;break;case "in":d=2.54*c.value;break;case "pt":d=0.035277778*c.value;break;case "pc":case "px":case "em":break;default:runtime.log("Unit identifier: "+c.unit+" is not supported.")}return d}
-var e,a=new odf.StyleInfo,b=odf.Namespaces.svgns,q=odf.Namespaces.stylens,k=odf.Namespaces.textns,t=odf.Namespaces.numberns,A=odf.Namespaces.fons,w=new odf.OdfUtils,x=new core.DomUtils,v=new core.Utils,u={paragraph:{"style:paragraph-properties":{"fo:text-align":"left"}}};this.getSystemDefaultStyleAttributes=g;this.setOdfContainer=function(a){e=a};this.getFontMap=f;this.getAvailableParagraphStyles=function(){for(var a=e.rootElement.styles,b,c,d=[],a=a&&a.firstElementChild;a;)"style"===a.localName&&
-a.namespaceURI===q&&(b=a.getAttributeNS(q,"family"),"paragraph"===b&&(b=a.getAttributeNS(q,"name"),c=a.getAttributeNS(q,"display-name")||b,b&&c&&d.push({name:b,displayName:c}))),a=a.nextElementSibling;return d};this.isStyleUsed=function(b){var c,d=e.rootElement;c=a.hasDerivedStyles(d,odf.Namespaces.lookupNamespaceURI,b);b=(new a.UsedStyleList(d.styles)).uses(b)||(new a.UsedStyleList(d.automaticStyles)).uses(b)||(new a.UsedStyleList(d.body)).uses(b);return c||b};this.getDefaultStyleElement=p;this.getStyleElement=
-r;this.getStyleAttributes=n;this.getInheritedStyleAttributes=h;this.getFirstCommonParentStyleNameOrSelf=function(a){var b=e.rootElement.automaticStyles,c=e.rootElement.styles,d;for(d=r(a,"paragraph",[b]);d;)a=d.getAttributeNS(q,"parent-style-name"),d=r(a,"paragraph",[b]);return(d=r(a,"paragraph",[c]))?a:null};this.hasParagraphStyle=function(a){return Boolean(r(a,"paragraph"))};this.getAppliedStyles=function(a){var b={},c=[];a.forEach(function(a){d(a,b)});Object.keys(b).forEach(function(a){c.push(m(b[a]))});
-return c};this.getAppliedStylesForElement=function(a){return(a=d(a))?m(a):void 0};this.updateStyle=function(a,c){var d,h;x.mapObjOntoNode(a,c,odf.Namespaces.lookupNamespaceURI);(d=c["style:text-properties"]&&c["style:text-properties"]["style:font-name"])&&!f().hasOwnProperty(d)&&(h=a.ownerDocument.createElementNS(q,"style:font-face"),h.setAttributeNS(q,"style:name",d),h.setAttributeNS(b,"svg:font-family",d),e.rootElement.fontFaceDecls.appendChild(h))};this.createDerivedStyleObject=function(a,b,c){var d=
-r(a,b);runtime.assert(Boolean(d),"No style element found for '"+a+"' of family '"+b+"'");a=d.parentNode===e.rootElement.automaticStyles?n(d):{"style:parent-style-name":a};a["style:family"]=b;v.mergeObjects(a,c);return a};this.getDefaultTabStopDistance=function(){for(var a=p("paragraph"),a=a&&a.firstElementChild,b;a;)a.namespaceURI===q&&"paragraph-properties"===a.localName&&(b=a.getAttributeNS(q,"tab-stop-distance")),a=a.nextElementSibling;b||(b="1.25cm");return w.parseNonNegativeLength(b)};this.getContentSize=
-function(a,b){var d,f,h,k,g,m,n,p,t,v,u;a:{var w,aa,J;d=r(a,b);runtime.assert("paragraph"===b||"table"===b,"styleFamily has to be either paragraph or table");if(d){w=d.getAttributeNS(q,"master-page-name")||"Standard";for(d=e.rootElement.masterStyles.lastElementChild;d&&d.getAttributeNS(q,"name")!==w;)d=d.previousElementSibling;w=d.getAttributeNS(q,"page-layout-name");aa=x.getElementsByTagNameNS(e.rootElement.automaticStyles,q,"page-layout");for(J=0;J<aa.length;J+=1)if(d=aa[J],d.getAttributeNS(q,"name")===
-w)break a}d=null}d||(d=l(e.rootElement.styles,q,"default-page-layout"));if(d=l(d,q,"page-layout-properties"))f=d.getAttributeNS(q,"print-orientation")||"portrait","portrait"===f?(f=21.001,h=29.7):(f=29.7,h=21.001),f=c(d.getAttributeNS(A,"page-width"),f),h=c(d.getAttributeNS(A,"page-height"),h),k=c(d.getAttributeNS(A,"margin"),null),null===k?(k=c(d.getAttributeNS(A,"margin-left"),2),g=c(d.getAttributeNS(A,"margin-right"),2),m=c(d.getAttributeNS(A,"margin-top"),2),n=c(d.getAttributeNS(A,"margin-bottom"),
-2)):k=g=m=n=k,p=c(d.getAttributeNS(A,"padding"),null),null===p?(p=c(d.getAttributeNS(A,"padding-left"),0),t=c(d.getAttributeNS(A,"padding-right"),0),v=c(d.getAttributeNS(A,"padding-top"),0),u=c(d.getAttributeNS(A,"padding-bottom"),0)):p=t=v=u=p;return{width:f-k-g-p-t,height:h-m-n-v-u}}};
-// Input 40
+ops.TextPositionFilter=function(k){function h(d,h,l){var f,c;if(h){if(b.isInlineRoot(h)&&b.isGroupingElement(l))return g;f=b.lookLeftForCharacter(h);if(1===f||2===f&&(b.scanRightForAnyCharacter(l)||b.scanRightForAnyCharacter(b.nextNode(d))))return n}f=null===h&&b.isParagraph(d);c=b.lookRightForCharacter(l);if(f)return c?n:b.scanRightForAnyCharacter(l)?g:n;if(!c)return g;h=h||b.previousNode(d);return b.scanLeftForAnyCharacter(h)?g:n}var b=new odf.OdfUtils,p=Node.ELEMENT_NODE,d=Node.TEXT_NODE,n=core.PositionFilter.FilterResult.FILTER_ACCEPT,
+g=core.PositionFilter.FilterResult.FILTER_REJECT;this.acceptPosition=function(q){var r=q.container(),l=r.nodeType,f,c,a;if(l!==p&&l!==d)return g;if(l===d){if(!b.isGroupingElement(r.parentNode)||b.isWithinTrackedChanges(r.parentNode,k()))return g;l=q.unfilteredDomOffset();f=r.data;runtime.assert(l!==f.length,"Unexpected offset.");if(0<l){q=f[l-1];if(!b.isODFWhitespace(q))return n;if(1<l)if(q=f[l-2],!b.isODFWhitespace(q))c=n;else{if(!b.isODFWhitespace(f.substr(0,l)))return g}else a=b.previousNode(r),
+b.scanLeftForNonSpace(a)&&(c=n);if(c===n)return b.isTrailingWhitespace(r,l)?g:n;c=f[l];return b.isODFWhitespace(c)?g:b.scanLeftForAnyCharacter(b.previousNode(r))?g:n}a=q.leftNode();c=r;r=r.parentNode;c=h(r,a,c)}else!b.isGroupingElement(r)||b.isWithinTrackedChanges(r,k())?c=g:(a=q.leftNode(),c=q.rightNode(),c=h(r,a,c));return c}};
+// Input 44
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1075,36 +1266,26 @@ w)break a}d=null}d||(d=l(e.rootElement.styles,q,"default-page-layout"));if(d=l(d
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfContainer");runtime.loadClass("odf.Formatting");runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.FontLoader");runtime.loadClass("odf.Style2CSS");runtime.loadClass("odf.OdfUtils");runtime.loadClass("gui.AnnotationViewManager");
-(function(){function g(){function a(d){c=!0;runtime.setTimeout(function(){try{d()}catch(e){runtime.log(String(e))}c=!1;0<b.length&&a(b.pop())},10)}var b=[],c=!1;this.clearQueue=function(){b.length=0};this.addToQueue=function(d){if(0===b.length&&!c)return a(d);b.push(d)}}function l(a){function b(){for(;0<c.cssRules.length;)c.deleteRule(0);c.insertRule("#shadowContent draw|page {display:none;}",0);c.insertRule("office|presentation draw|page {display:none;}",1);c.insertRule("#shadowContent draw|page:nth-of-type("+
-d+") {display:block;}",2);c.insertRule("office|presentation draw|page:nth-of-type("+d+") {display:block;}",3)}var c=a.sheet,d=1;this.showFirstPage=function(){d=1;b()};this.showNextPage=function(){d+=1;b()};this.showPreviousPage=function(){1<d&&(d-=1,b())};this.showPage=function(a){0<a&&(d=a,b())};this.css=a;this.destroy=function(b){a.parentNode.removeChild(a);b()}}function f(a){for(;a.firstChild;)a.removeChild(a.firstChild)}function p(a,b,c){(new odf.Style2CSS).style2css(a.getDocumentType(),c.sheet,
-b.getFontMap(),a.rootElement.styles,a.rootElement.automaticStyles)}function r(a,b,c){var d=null;a=a.rootElement.body.getElementsByTagNameNS(L,c+"-decl");c=b.getAttributeNS(L,"use-"+c+"-name");var e;if(c&&0<a.length)for(b=0;b<a.length;b+=1)if(e=a[b],e.getAttributeNS(L,"name")===c){d=e.textContent;break}return d}function n(a,b,c,d){var e=a.ownerDocument;b=a.getElementsByTagNameNS(b,c);for(a=0;a<b.length;a+=1)f(b[a]),d&&(c=b[a],c.appendChild(e.createTextNode(d)))}function h(a,b,c){b.setAttributeNS("urn:webodf:names:helper",
-"styleid",a);var d,e=b.getAttributeNS(H,"anchor-type"),f=b.getAttributeNS(u,"x"),h=b.getAttributeNS(u,"y"),k=b.getAttributeNS(u,"width"),g=b.getAttributeNS(u,"height"),q=b.getAttributeNS(w,"min-height"),m=b.getAttributeNS(w,"min-width");if("as-char"===e)d="display: inline-block;";else if(e||f||h)d="position: absolute;";else if(k||g||q||m)d="display: block;";f&&(d+="left: "+f+";");h&&(d+="top: "+h+";");k&&(d+="width: "+k+";");g&&(d+="height: "+g+";");q&&(d+="min-height: "+q+";");m&&(d+="min-width: "+
-m+";");d&&(d="draw|"+b.localName+'[webodfhelper|styleid="'+a+'"] {'+d+"}",c.insertRule(d,c.cssRules.length))}function d(a){for(a=a.firstChild;a;){if(a.namespaceURI===x&&"binary-data"===a.localName)return"data:image/png;base64,"+a.textContent.replace(/[\r\n\s]/g,"");a=a.nextSibling}return""}function m(a,b,c,e){function f(b){b&&(b='draw|image[webodfhelper|styleid="'+a+'"] {'+("background-image: url("+b+");")+"}",e.insertRule(b,e.cssRules.length))}function h(a){f(a.url)}c.setAttributeNS("urn:webodf:names:helper",
-"styleid",a);var k=c.getAttributeNS(y,"href"),g;if(k)try{g=b.getPart(k),g.onchange=h,g.load()}catch(q){runtime.log("slight problem: "+String(q))}else k=d(c),f(k)}function c(a){function b(c){var d,e;c.hasAttributeNS(y,"href")&&(d=c.getAttributeNS(y,"href"),"#"===d[0]?(d=d.substring(1),e=function(){var b=W.getODFElementsWithXPath(a,"//text:bookmark-start[@text:name='"+d+"']",odf.Namespaces.lookupNamespaceURI);0===b.length&&(b=W.getODFElementsWithXPath(a,"//text:bookmark[@text:name='"+d+"']",odf.Namespaces.lookupNamespaceURI));
-0<b.length&&b[0].scrollIntoView(!0);return!1}):e=function(){I.open(d)},c.onclick=e)}var c,d,e;d=a.getElementsByTagNameNS(H,"a");for(c=0;c<d.length;c+=1)e=d.item(c),b(e)}function e(a){var b=a.ownerDocument;z.getElementsByTagNameNS(a,H,"line-break").forEach(function(a){a.hasChildNodes()||a.appendChild(b.createElement("br"))})}function a(a){var b=a.ownerDocument;z.getElementsByTagNameNS(a,H,"s").forEach(function(a){for(var c,d;a.firstChild;)a.removeChild(a.firstChild);a.appendChild(b.createTextNode(" "));
-d=parseInt(a.getAttributeNS(H,"c"),10);if(1<d)for(a.removeAttributeNS(H,"c"),c=1;c<d;c+=1)a.parentNode.insertBefore(a.cloneNode(!0),a)})}function b(a){z.getElementsByTagNameNS(a,H,"tab").forEach(function(a){a.textContent="\t"})}function q(a,b){function c(a,d){var e=g.documentElement.namespaceURI;"video/"===d.substr(0,6)?(f=g.createElementNS(e,"video"),f.setAttribute("controls","controls"),h=g.createElementNS(e,"source"),a&&h.setAttribute("src",a),h.setAttribute("type",d),f.appendChild(h),b.parentNode.appendChild(f)):
-b.innerHtml="Unrecognised Plugin"}function e(a){c(a.url,a.mimetype)}var f,h,k,g=b.ownerDocument,q;if(k=b.getAttributeNS(y,"href"))try{q=a.getPart(k),q.onchange=e,q.load()}catch(m){runtime.log("slight problem: "+String(m))}else runtime.log("using MP4 data fallback"),k=d(b),c(k,"video/mp4")}function k(a){var b=a.getElementsByTagName("head")[0],c;"undefined"!==String(typeof webodf_css)?(c=a.createElementNS(b.namespaceURI,"style"),c.setAttribute("media","screen, print, handheld, projection"),c.appendChild(a.createTextNode(webodf_css))):
-(c=a.createElementNS(b.namespaceURI,"link"),a="webodf.css",runtime.currentDirectory&&(a=runtime.currentDirectory()+"/../"+a),c.setAttribute("href",a),c.setAttribute("rel","stylesheet"));c.setAttribute("type","text/css");b.appendChild(c);return c}function t(a){var b=a.getElementsByTagName("head")[0],c=a.createElementNS(b.namespaceURI,"style"),d="";c.setAttribute("type","text/css");c.setAttribute("media","screen, print, handheld, projection");odf.Namespaces.forEachPrefix(function(a,b){d+="@namespace "+
-a+" url("+b+");\n"});d+="@namespace webodfhelper url(urn:webodf:names:helper);\n";c.appendChild(a.createTextNode(d));b.appendChild(c);return c}var A=odf.Namespaces.drawns,w=odf.Namespaces.fons,x=odf.Namespaces.officens,v=odf.Namespaces.stylens,u=odf.Namespaces.svgns,s=odf.Namespaces.tablens,H=odf.Namespaces.textns,y=odf.Namespaces.xlinkns,B=odf.Namespaces.xmlns,L=odf.Namespaces.presentationns,I=runtime.getWindow(),W=xmldom.XPath,Q=new odf.OdfUtils,z=new core.DomUtils;odf.OdfCanvas=function(d){function u(a,
-b,c){function d(a,b,c,e){E.addToQueue(function(){m(a,b,c,e)})}var e,f;e=b.getElementsByTagNameNS(A,"image");for(b=0;b<e.length;b+=1)f=e.item(b),d("image"+String(b),a,f,c)}function w(a,b){function c(a,b){E.addToQueue(function(){q(a,b)})}var d,e,f;e=b.getElementsByTagNameNS(A,"plugin");for(d=0;d<e.length;d+=1)f=e.item(d),c(a,f)}function y(){M.firstChild&&(1<S?(M.style.MozTransformOrigin="center top",M.style.WebkitTransformOrigin="center top",M.style.OTransformOrigin="center top",M.style.msTransformOrigin=
-"center top"):(M.style.MozTransformOrigin="left top",M.style.WebkitTransformOrigin="left top",M.style.OTransformOrigin="left top",M.style.msTransformOrigin="left top"),M.style.WebkitTransform="scale("+S+")",M.style.MozTransform="scale("+S+")",M.style.OTransform="scale("+S+")",M.style.msTransform="scale("+S+")",d.style.width=Math.round(S*M.offsetWidth)+"px",d.style.height=Math.round(S*M.offsetHeight)+"px")}function O(a){function b(a){return d===a.getAttributeNS(x,"name")}var c=z.getElementsByTagNameNS(a,
-x,"annotation");a=z.getElementsByTagNameNS(a,x,"annotation-end");var d,e;for(e=0;e<c.length;e+=1)d=c[e].getAttributeNS(x,"name"),ca.addAnnotation({node:c[e],end:a.filter(b)[0]||null});ca.rerenderAnnotations()}function aa(a){la?(ba.parentNode||(M.appendChild(ba),y()),ca&&ca.forgetAnnotations(),ca=new gui.AnnotationViewManager(C,a.body,ba),O(a.body)):ba.parentNode&&(M.removeChild(ba),ca.forgetAnnotations(),y())}function J(k){function g(){f(d);d.style.display="inline-block";var q=U.rootElement;d.ownerDocument.importNode(q,
-!0);R.setOdfContainer(U);var m=U,l=T;(new odf.FontLoader).loadFonts(m,l.sheet);p(U,R,$);l=U;m=X.sheet;f(d);M=Y.createElementNS(d.namespaceURI,"div");M.style.display="inline-block";M.style.background="white";M.appendChild(q);d.appendChild(M);ba=Y.createElementNS(d.namespaceURI,"div");ba.id="annotationsPane";da=Y.createElementNS(d.namespaceURI,"div");da.id="shadowContent";da.style.position="absolute";da.style.top=0;da.style.left=0;l.getContentElement().appendChild(da);var t=q.body,z,D=[],C;for(z=t.firstElementChild;z&&
-z!==t;)if(z.namespaceURI===A&&(D[D.length]=z),z.firstElementChild)z=z.firstElementChild;else{for(;z&&z!==t&&!z.nextElementSibling;)z=z.parentElement;z&&z.nextElementSibling&&(z=z.nextElementSibling)}for(C=0;C<D.length;C+=1)z=D[C],h("frame"+String(C),z,m);D=W.getODFElementsWithXPath(t,".//*[*[@text:anchor-type='paragraph']]",odf.Namespaces.lookupNamespaceURI);for(z=0;z<D.length;z+=1)t=D[z],t.setAttributeNS&&t.setAttributeNS("urn:webodf:names:helper","containsparagraphanchor",!0);var t=da,O,E,F;F=0;
-var J,P,D=l.rootElement.ownerDocument;if((z=q.body.firstElementChild)&&z.namespaceURI===x&&("presentation"===z.localName||"drawing"===z.localName))for(z=z.firstElementChild;z;){C=z.getAttributeNS(A,"master-page-name");if(C){for(O=l.rootElement.masterStyles.firstElementChild;O&&(O.getAttributeNS(v,"name")!==C||"master-page"!==O.localName||O.namespaceURI!==v););C=O}else C=null;if(C){O=z.getAttributeNS("urn:webodf:names:helper","styleid");E=D.createElementNS(A,"draw:page");P=C.firstElementChild;for(J=
-0;P;)"true"!==P.getAttributeNS(L,"placeholder")&&(F=P.cloneNode(!0),E.appendChild(F),h(O+"_"+J,F,m)),P=P.nextElementSibling,J+=1;P=J=F=void 0;var V=E.getElementsByTagNameNS(A,"frame");for(F=0;F<V.length;F+=1)J=V[F],(P=J.getAttributeNS(L,"class"))&&!/^(date-time|footer|header|page-number')$/.test(P)&&J.parentNode.removeChild(J);t.appendChild(E);F=String(t.getElementsByTagNameNS(A,"page").length);n(E,H,"page-number",F);n(E,L,"header",r(l,z,"header"));n(E,L,"footer",r(l,z,"footer"));h(O,E,m);E.setAttributeNS(A,
-"draw:master-page-name",C.getAttributeNS(v,"name"))}z=z.nextElementSibling}t=d.namespaceURI;D=q.body.getElementsByTagNameNS(s,"table-cell");for(z=0;z<D.length;z+=1)C=D.item(z),C.hasAttributeNS(s,"number-columns-spanned")&&C.setAttributeNS(t,"colspan",C.getAttributeNS(s,"number-columns-spanned")),C.hasAttributeNS(s,"number-rows-spanned")&&C.setAttributeNS(t,"rowspan",C.getAttributeNS(s,"number-rows-spanned"));c(q.body);e(q.body);a(q.body);b(q.body);u(l,q.body,m);w(l,q.body);C=q.body;l=d.namespaceURI;
-z={};var D={},K;O=I.document.getElementsByTagNameNS(H,"list-style");for(t=0;t<O.length;t+=1)J=O.item(t),(P=J.getAttributeNS(v,"name"))&&(D[P]=J);C=C.getElementsByTagNameNS(H,"list");for(t=0;t<C.length;t+=1)if(J=C.item(t),O=J.getAttributeNS(B,"id")){E=J.getAttributeNS(H,"continue-list");J.setAttributeNS(l,"id",O);F="text|list#"+O+" > text|list-item > *:first-child:before {";if(P=J.getAttributeNS(H,"style-name")){J=D[P];K=Q.getFirstNonWhitespaceChild(J);J=void 0;if(K)if("list-level-style-number"===
-K.localName){J=K.getAttributeNS(v,"num-format");P=K.getAttributeNS(v,"num-suffix")||"";var V="",V={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},S=void 0,S=K.getAttributeNS(v,"num-prefix")||"",S=V.hasOwnProperty(J)?S+(" counter(list, "+V[J]+")"):J?S+("'"+J+"';"):S+" ''";P&&(S+=" '"+P+"'");J=V="content: "+S+";"}else"list-level-style-image"===K.localName?J="content: none;":"list-level-style-bullet"===K.localName&&(J="content: '"+K.getAttributeNS(H,"bullet-char")+"';");
-K=J}if(E){for(J=z[E];J;)J=z[J];F+="counter-increment:"+E+";";K?(K=K.replace("list",E),F+=K):F+="content:counter("+E+");"}else E="",K?(K=K.replace("list",O),F+=K):F+="content: counter("+O+");",F+="counter-increment:"+O+";",m.insertRule("text|list#"+O+" {counter-reset:"+O+"}",m.cssRules.length);F+="}";z[O]=E;F&&m.insertRule(F,m.cssRules.length)}M.insertBefore(da,M.firstChild);y();aa(q);if(!k&&(q=[U],ga.hasOwnProperty("statereadychange")))for(m=ga.statereadychange,K=0;K<m.length;K+=1)m[K].apply(null,
-q)}U.state===odf.OdfContainer.DONE?g():(runtime.log("WARNING: refreshOdf called but ODF was not DONE."),runtime.setTimeout(function ha(){U.state===odf.OdfContainer.DONE?g():(runtime.log("will be back later..."),runtime.setTimeout(ha,500))},100))}function F(a){E.clearQueue();d.innerHTML=runtime.tr("Loading")+" "+a+"...";d.removeAttribute("style");U=new odf.OdfContainer(a,function(a){U=a;J(!1)})}runtime.assert(null!==d&&void 0!==d,"odf.OdfCanvas constructor needs DOM element");runtime.assert(null!==
-d.ownerDocument&&void 0!==d.ownerDocument,"odf.OdfCanvas constructor needs DOM");var C=this,Y=d.ownerDocument,U,R=new odf.Formatting,P,M=null,ba=null,la=!1,ca=null,ma,T,$,X,da,S=1,ga={},E=new g;this.refreshCSS=function(){p(U,R,$);y()};this.refreshSize=function(){y()};this.odfContainer=function(){return U};this.setOdfContainer=function(a,b){U=a;J(!0===b)};this.load=this.load=F;this.save=function(a){U.save(a)};this.addListener=function(a,b){switch(a){case "click":var c=d,e=a;c.addEventListener?c.addEventListener(e,
-b,!1):c.attachEvent?c.attachEvent("on"+e,b):c["on"+e]=b;break;default:c=ga.hasOwnProperty(a)?ga[a]:ga[a]=[],b&&-1===c.indexOf(b)&&c.push(b)}};this.getFormatting=function(){return R};this.getAnnotationViewManager=function(){return ca};this.refreshAnnotations=function(){aa(U.rootElement)};this.rerenderAnnotations=function(){ca&&ca.rerenderAnnotations()};this.getSizer=function(){return M};this.enableAnnotations=function(a){a!==la&&(la=a,U&&aa(U.rootElement))};this.addAnnotation=function(a){ca&&ca.addAnnotation(a)};
-this.forgetAnnotations=function(){ca&&ca.forgetAnnotations()};this.setZoomLevel=function(a){S=a;y()};this.getZoomLevel=function(){return S};this.fitToContainingElement=function(a,b){var c=d.offsetHeight/S;S=a/(d.offsetWidth/S);b/c<S&&(S=b/c);y()};this.fitToWidth=function(a){S=a/(d.offsetWidth/S);y()};this.fitSmart=function(a,b){var c,e;c=d.offsetWidth/S;e=d.offsetHeight/S;c=a/c;void 0!==b&&b/e<c&&(c=b/e);S=Math.min(1,c);y()};this.fitToHeight=function(a){S=a/(d.offsetHeight/S);y()};this.showFirstPage=
-function(){P.showFirstPage()};this.showNextPage=function(){P.showNextPage()};this.showPreviousPage=function(){P.showPreviousPage()};this.showPage=function(a){P.showPage(a);y()};this.getElement=function(){return d};this.addCssForFrameWithImage=function(a){var b=a.getAttributeNS(A,"name"),c=a.firstElementChild;h(b,a,X.sheet);c&&m(b+"img",U,c,X.sheet)};this.destroy=function(a){var b=Y.getElementsByTagName("head")[0];ba&&ba.parentNode&&ba.parentNode.removeChild(ba);M&&(d.removeChild(M),M=null);b.removeChild(ma);
-b.removeChild(T);b.removeChild($);b.removeChild(X);P.destroy(a)};ma=k(Y);P=new l(t(Y));T=t(Y);$=t(Y);X=t(Y)}})();
-// Input 41
+ops.OdtDocument=function(k){function h(){var a=k.odfContainer().getContentElement(),c=a&&a.localName;runtime.assert("text"===c,"Unsupported content element type '"+c+"' for OdtDocument");return a}function b(){return c.getDocumentElement().ownerDocument}function p(a){for(;a&&!(a.namespaceURI===odf.Namespaces.officens&&"text"===a.localName||a.namespaceURI===odf.Namespaces.officens&&"annotation"===a.localName);)a=a.parentNode;return a}function d(a){this.acceptPosition=function(c){c=c.container();var b;
+b="string"===typeof a?e[a].getNode():a;return p(c)===p(b)?z:x}}function n(a,c,b,e){e=gui.SelectionMover.createPositionIterator(e);var d;1===b.length?d=b[0]:(d=new core.PositionFilterChain,b.forEach(d.addFilter));b=new core.StepIterator(d,e);b.setPosition(a,c);return b}function g(a){var c=gui.SelectionMover.createPositionIterator(h());a=u.convertStepsToDomPoint(a);c.setUnfilteredPosition(a.node,a.offset);return c}function q(c){return a.getParagraphElement(c)}function r(a,c){return k.getFormatting().getStyleElement(a,
+c)}function l(a){return r(a,"paragraph")}function f(a,c,b){a=a.childNodes.item(c)||a;return(a=q(a))&&m.containsNode(b,a)?a:b}var c=this,a,m,e={},t={},w=new core.EventNotifier([ops.Document.signalMemberAdded,ops.Document.signalMemberUpdated,ops.Document.signalMemberRemoved,ops.Document.signalCursorAdded,ops.Document.signalCursorRemoved,ops.Document.signalCursorMoved,ops.OdtDocument.signalParagraphChanged,ops.OdtDocument.signalParagraphStyleModified,ops.OdtDocument.signalCommonStyleCreated,ops.OdtDocument.signalCommonStyleDeleted,
+ops.OdtDocument.signalTableAdded,ops.OdtDocument.signalOperationStart,ops.OdtDocument.signalOperationEnd,ops.OdtDocument.signalProcessingBatchStart,ops.OdtDocument.signalProcessingBatchEnd,ops.OdtDocument.signalUndoStackChanged,ops.OdtDocument.signalStepsInserted,ops.OdtDocument.signalStepsRemoved]),z=core.PositionFilter.FilterResult.FILTER_ACCEPT,x=core.PositionFilter.FilterResult.FILTER_REJECT,v,u,s;this.getDocumentElement=function(){return k.odfContainer().rootElement};this.getDOMDocument=function(){return this.getDocumentElement().ownerDocument};
+this.cloneDocumentElement=function(){var a=c.getDocumentElement(),b=k.getAnnotationViewManager();b&&b.forgetAnnotations();a=a.cloneNode(!0);k.refreshAnnotations();return a};this.setDocumentElement=function(a){var c=k.odfContainer();c.setRootElement(a);k.setOdfContainer(c,!0);k.refreshCSS()};this.getDOMDocument=b;this.getRootElement=p;this.createStepIterator=n;this.getIteratorAtPosition=g;this.convertDomPointToCursorStep=function(a,c,b){return u.convertDomPointToSteps(a,c,b)};this.convertDomToCursorRange=
+function(a,c){var b,e;b=c&&c(a.anchorNode,a.anchorOffset);b=u.convertDomPointToSteps(a.anchorNode,a.anchorOffset,b);c||a.anchorNode!==a.focusNode||a.anchorOffset!==a.focusOffset?(e=c&&c(a.focusNode,a.focusOffset),e=u.convertDomPointToSteps(a.focusNode,a.focusOffset,e)):e=b;return{position:b,length:e-b}};this.convertCursorToDomRange=function(a,c){var e=b().createRange(),d,f;d=u.convertStepsToDomPoint(a);c?(f=u.convertStepsToDomPoint(a+c),0<c?(e.setStart(d.node,d.offset),e.setEnd(f.node,f.offset)):
+(e.setStart(f.node,f.offset),e.setEnd(d.node,d.offset))):e.setStart(d.node,d.offset);return e};this.getStyleElement=r;this.upgradeWhitespacesAtPosition=function(c){c=g(c);var b,e,d;c.previousPosition();c.previousPosition();for(d=-1;1>=d;d+=1){b=c.container();e=c.unfilteredDomOffset();if(b.nodeType===Node.TEXT_NODE&&" "===b.data[e]&&a.isSignificantWhitespace(b,e)){runtime.assert(" "===b.data[e],"upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");var f=b.ownerDocument.createElementNS(odf.Namespaces.textns,
+"text:s"),m=b.parentNode,l=b;f.appendChild(b.ownerDocument.createTextNode(" "));1===b.length?m.replaceChild(f,b):(b.deleteData(e,1),0<e&&(e<b.length&&b.splitText(e),l=b.nextSibling),m.insertBefore(f,l));b=f;c.moveToEndOfNode(b)}c.nextPosition()}};this.downgradeWhitespacesAtPosition=function(c){var b=g(c),e;c=b.container();for(b=b.unfilteredDomOffset();!a.isSpaceElement(c)&&c.childNodes.item(b);)c=c.childNodes.item(b),b=0;c.nodeType===Node.TEXT_NODE&&(c=c.parentNode);a.isDowngradableSpaceElement(c)&&
+(b=c.firstChild,e=c.lastChild,m.mergeIntoParent(c),e!==b&&m.normalizeTextNodes(e),m.normalizeTextNodes(b))};this.getParagraphStyleElement=l;this.getParagraphElement=q;this.getParagraphStyleAttributes=function(a){return(a=l(a))?k.getFormatting().getInheritedStyleAttributes(a,!1):null};this.getTextNodeAtStep=function(a,d){var f=g(a),m=f.container(),l,h=0,k=null;m.nodeType===Node.TEXT_NODE?(l=m,h=f.unfilteredDomOffset(),0<l.length&&(0<h&&(l=l.splitText(h)),l.parentNode.insertBefore(b().createTextNode(""),
+l),l=l.previousSibling,h=0)):(l=b().createTextNode(""),h=0,m.insertBefore(l,f.rightNode()));if(d){if(e[d]&&c.getCursorPosition(d)===a){for(k=e[d].getNode();k.nextSibling&&"cursor"===k.nextSibling.localName;)k.parentNode.insertBefore(k.nextSibling,k);0<l.length&&l.nextSibling!==k&&(l=b().createTextNode(""),h=0);k.parentNode.insertBefore(l,k)}}else for(;l.nextSibling&&"cursor"===l.nextSibling.localName;)l.parentNode.insertBefore(l.nextSibling,l);for(;l.previousSibling&&l.previousSibling.nodeType===
+Node.TEXT_NODE;)f=l.previousSibling,f.appendData(l.data),h=f.length,l=f,l.parentNode.removeChild(l.nextSibling);for(;l.nextSibling&&l.nextSibling.nodeType===Node.TEXT_NODE;)f=l.nextSibling,l.appendData(f.data),l.parentNode.removeChild(f);return{textNode:l,offset:h}};this.fixCursorPositions=function(){Object.keys(e).forEach(function(a){var b=e[a],d=p(b.getNode()),g=c.createRootFilter(d),m,l,h,k=!1;h=b.getSelectedRange();m=f(h.startContainer,h.startOffset,d);l=n(h.startContainer,h.startOffset,[v,g],
+m);h.collapsed?d=l:(m=f(h.endContainer,h.endOffset,d),d=n(h.endContainer,h.endOffset,[v,g],m));l.isStep()&&d.isStep()?l.container()!==d.container()||l.offset()!==d.offset()||h.collapsed&&b.getAnchorNode()===b.getNode()||(k=!0,h.setStart(l.container(),l.offset()),h.collapse(!0)):(k=!0,runtime.assert(l.roundToClosestStep(),"No walkable step found for cursor owned by "+a),h.setStart(l.container(),l.offset()),runtime.assert(d.roundToClosestStep(),"No walkable step found for cursor owned by "+a),h.setEnd(d.container(),
+d.offset()));k&&(b.setSelectedRange(h,b.hasForwardSelection()),c.emit(ops.Document.signalCursorMoved,b))})};this.getCursorPosition=function(a){return(a=e[a])?u.convertDomPointToSteps(a.getNode(),0):0};this.getCursorSelection=function(a){a=e[a];var c=0,b=0;a&&(c=u.convertDomPointToSteps(a.getNode(),0),b=u.convertDomPointToSteps(a.getAnchorNode(),0));return{position:b,length:c-b}};this.getPositionFilter=function(){return v};this.getOdfCanvas=function(){return k};this.getCanvas=function(){return k};
+this.getRootNode=h;this.addMember=function(a){runtime.assert(void 0===t[a.getMemberId()],"This member already exists");t[a.getMemberId()]=a};this.getMember=function(a){return t.hasOwnProperty(a)?t[a]:null};this.removeMember=function(a){delete t[a]};this.getCursor=function(a){return e[a]};this.getMemberIds=function(){var a=[],c;for(c in e)e.hasOwnProperty(c)&&a.push(e[c].getMemberId());return a};this.addCursor=function(a){runtime.assert(Boolean(a),"OdtDocument::addCursor without cursor");var b=a.getMemberId(),
+d=c.convertCursorToDomRange(0,0);runtime.assert("string"===typeof b,"OdtDocument::addCursor has cursor without memberid");runtime.assert(!e[b],"OdtDocument::addCursor is adding a duplicate cursor with memberid "+b);a.setSelectedRange(d,!0);e[b]=a};this.removeCursor=function(a){var b=e[a];return b?(b.removeFromDocument(),delete e[a],c.emit(ops.Document.signalCursorRemoved,a),!0):!1};this.moveCursor=function(a,b,d,f){a=e[a];b=c.convertCursorToDomRange(b,d);a&&(a.setSelectedRange(b,0<=d),a.setSelectionType(f||
+ops.OdtCursor.RangeSelection))};this.getFormatting=function(){return k.getFormatting()};this.emit=function(a,c){w.emit(a,c)};this.subscribe=function(a,c){w.subscribe(a,c)};this.unsubscribe=function(a,c){w.unsubscribe(a,c)};this.createRootFilter=function(a){return new d(a)};this.close=function(a){a()};this.destroy=function(a){a()};v=new ops.TextPositionFilter(h);a=new odf.OdfUtils;m=new core.DomUtils;u=new ops.StepsTranslator(h,gui.SelectionMover.createPositionIterator,v,500);w.subscribe(ops.OdtDocument.signalStepsInserted,
+u.handleStepsInserted);w.subscribe(ops.OdtDocument.signalStepsRemoved,u.handleStepsRemoved);w.subscribe(ops.OdtDocument.signalOperationEnd,function(a){var b=a.spec(),e=b.memberid,b=(new Date(b.timestamp)).toISOString(),d=k.odfContainer();a.isEdit&&(e=c.getMember(e).getProperties().fullName,d.setMetadata({"dc:creator":e,"dc:date":b},null),s||(d.incrementEditingCycles(),d.setMetadata(null,["meta:editing-duration","meta:document-statistic"])),s=a)})};ops.OdtDocument.signalParagraphChanged="paragraph/changed";
+ops.OdtDocument.signalTableAdded="table/added";ops.OdtDocument.signalCommonStyleCreated="style/created";ops.OdtDocument.signalCommonStyleDeleted="style/deleted";ops.OdtDocument.signalParagraphStyleModified="paragraphstyle/modified";ops.OdtDocument.signalOperationStart="operation/start";ops.OdtDocument.signalOperationEnd="operation/end";ops.OdtDocument.signalProcessingBatchStart="router/batchstart";ops.OdtDocument.signalProcessingBatchEnd="router/batchend";ops.OdtDocument.signalUndoStackChanged="undo/changed";
+ops.OdtDocument.signalStepsInserted="steps/inserted";ops.OdtDocument.signalStepsRemoved="steps/removed";(function(){return ops.OdtDocument})();
+// Input 45
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1142,12 +1323,11 @@ b.removeChild(T);b.removeChild($);b.removeChild(X);P.destroy(a)};ma=k(Y);P=new l
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.Namespaces");
-odf.TextStyleApplicator=function(g,l,f){function p(c){function d(a,b){return"object"===typeof a&&"object"===typeof b?Object.keys(a).every(function(c){return d(a[c],b[c])}):a===b}this.isStyleApplied=function(a){a=l.getAppliedStylesForElement(a);return d(c,a)}}function r(c){var e={};this.applyStyleToContainer=function(a){var b;b=a.getAttributeNS(d,"style-name");var h=a.ownerDocument;b=b||"";if(!e.hasOwnProperty(b)){var k=b,n;n=b?l.createDerivedStyleObject(b,"text",c):c;h=h.createElementNS(m,"style:style");
-l.updateStyle(h,n);h.setAttributeNS(m,"style:name",g.generateStyleName());h.setAttributeNS(m,"style:family","text");h.setAttributeNS("urn:webodf:names:scope","scope","document-content");f.appendChild(h);e[k]=h}b=e[b].getAttributeNS(m,"name");a.setAttributeNS(d,"text:style-name",b)}}function n(c,e){var a=c.ownerDocument,b=c.parentNode,f,k,g=new core.LoopWatchDog(1E4);k=[];"span"!==b.localName||b.namespaceURI!==d?(f=a.createElementNS(d,"text:span"),b.insertBefore(f,c),b=!1):(c.previousSibling&&!h.rangeContainsNode(e,
-b.firstChild)?(f=b.cloneNode(!1),b.parentNode.insertBefore(f,b.nextSibling)):f=b,b=!0);k.push(c);for(a=c.nextSibling;a&&h.rangeContainsNode(e,a);)g.check(),k.push(a),a=a.nextSibling;k.forEach(function(a){a.parentNode!==f&&f.appendChild(a)});if(a&&b)for(k=f.cloneNode(!1),f.parentNode.insertBefore(k,f.nextSibling);a;)g.check(),b=a.nextSibling,k.appendChild(a),a=b;return f}var h=new core.DomUtils,d=odf.Namespaces.textns,m=odf.Namespaces.stylens;this.applyStyle=function(c,d,a){var b={},f,h,g,m;runtime.assert(a&&
-a.hasOwnProperty("style:text-properties"),"applyStyle without any text properties");b["style:text-properties"]=a["style:text-properties"];g=new r(b);m=new p(b);c.forEach(function(a){f=m.isStyleApplied(a);!1===f&&(h=n(a,d),g.applyStyleToContainer(h))})}};
-// Input 42
+ops.OpAddAnnotation=function(){function k(b,d,g){var f=b.getTextNodeAtStep(g,h);f&&(b=f.textNode,g=b.parentNode,f.offset!==b.length&&b.splitText(f.offset),g.insertBefore(d,b.nextSibling),0===b.length&&g.removeChild(b))}var h,b,p,d,n,g;this.init=function(g){h=g.memberid;b=parseInt(g.timestamp,10);p=parseInt(g.position,10);d=parseInt(g.length,10)||0;n=g.name};this.isEdit=!0;this.group=void 0;this.execute=function(q){var r=q.getCursor(h),l,f;f=new core.DomUtils;g=q.getDOMDocument();var c=new Date(b),
+a,m,e,t;a=g.createElementNS(odf.Namespaces.officens,"office:annotation");a.setAttributeNS(odf.Namespaces.officens,"office:name",n);l=g.createElementNS(odf.Namespaces.dcns,"dc:creator");l.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",h);l.textContent=q.getMember(h).getProperties().fullName;m=g.createElementNS(odf.Namespaces.dcns,"dc:date");m.appendChild(g.createTextNode(c.toISOString()));c=g.createElementNS(odf.Namespaces.textns,"text:list");e=g.createElementNS(odf.Namespaces.textns,
+"text:list-item");t=g.createElementNS(odf.Namespaces.textns,"text:p");e.appendChild(t);c.appendChild(e);a.appendChild(l);a.appendChild(m);a.appendChild(c);d&&(l=g.createElementNS(odf.Namespaces.officens,"office:annotation-end"),l.setAttributeNS(odf.Namespaces.officens,"office:name",n),a.annotationEndElement=l,k(q,l,p+d));k(q,a,p);q.emit(ops.OdtDocument.signalStepsInserted,{position:p,length:d});r&&(l=g.createRange(),f=f.getElementsByTagNameNS(a,odf.Namespaces.textns,"p")[0],l.selectNodeContents(f),
+r.setSelectedRange(l,!1),q.emit(ops.Document.signalCursorMoved,r));q.getOdfCanvas().addAnnotation(a);q.fixCursorPositions();return!0};this.spec=function(){return{optype:"AddAnnotation",memberid:h,timestamp:b,position:p,length:d,name:n}}};
+// Input 46
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1185,36 +1365,8 @@ a.hasOwnProperty("style:text-properties"),"applyStyle without any text propertie
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");
-gui.StyleHelper=function(g){function l(f,h,d){var g=!0,c;for(c=0;c<f.length&&!(g=f[c]["style:text-properties"],g=!g||g[h]!==d);c+=1);return!g}function f(f,h,d){function m(){b=!0;(e=g.getDefaultStyleElement("paragraph"))||(e=null)}var c,e;f=p.getParagraphElements(f);for(var a={},b=!1;0<f.length;){(c=f[0].getAttributeNS(r,"style-name"))?a[c]||(e=g.getStyleElement(c,"paragraph"),a[c]=!0,e||b||m()):b?e=void 0:m();if(void 0!==e&&(c=null===e?g.getSystemDefaultStyleAttributes("paragraph"):g.getInheritedStyleAttributes(e,
-!0),(c=c["style:paragraph-properties"])&&-1===d.indexOf(c[h])))return!1;f.pop()}return!0}var p=new odf.OdfUtils,r=odf.Namespaces.textns;this.getAppliedStyles=function(f){var h;f.collapsed?(h=f.startContainer,h.hasChildNodes()&&f.startOffset<h.childNodes.length&&(h=h.childNodes.item(f.startOffset)),f=[h]):f=p.getTextNodes(f,!0);return g.getAppliedStyles(f)};this.isBold=function(f){return l(f,"fo:font-weight","bold")};this.isItalic=function(f){return l(f,"fo:font-style","italic")};this.hasUnderline=
-function(f){return l(f,"style:text-underline-style","solid")};this.hasStrikeThrough=function(f){return l(f,"style:text-line-through-style","solid")};this.isAlignedLeft=function(g){return f(g,"fo:text-align",["left","start"])};this.isAlignedCenter=function(g){return f(g,"fo:text-align",["center"])};this.isAlignedRight=function(g){return f(g,"fo:text-align",["right","end"])};this.isAlignedJustified=function(g){return f(g,"fo:text-align",["justify"])}};
-// Input 43
-core.RawDeflate=function(){function g(){this.dl=this.fc=0}function l(){this.extra_bits=this.static_tree=this.dyn_tree=null;this.max_code=this.max_length=this.elems=this.extra_base=0}function f(a,b,c,d){this.good_length=a;this.max_lazy=b;this.nice_length=c;this.max_chain=d}function p(){this.next=null;this.len=0;this.ptr=[];this.ptr.length=r;this.off=0}var r=8192,n,h,d,m,c=null,e,a,b,q,k,t,A,w,x,v,u,s,H,y,B,L,I,W,Q,z,ja,ka,G,Z,O,aa,J,F,C,Y,U,R,P,M,ba,la,ca,ma,T,$,X,da,S,ga,E,fa,D,pa,ha,ia,Da,N=[0,0,
-0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],qa=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],sa=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],xa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ra;ra=[new f(0,0,0,0),new f(4,4,8,4),new f(4,5,16,8),new f(4,6,32,32),new f(4,4,16,16),new f(8,16,32,32),new f(8,16,128,128),new f(8,32,128,256),new f(32,128,258,1024),new f(32,258,258,4096)];var Aa=function(b){c[a+e++]=b;if(a+e===r){var f;if(0!==e){null!==n?(b=n,n=n.next):b=new p;
-b.next=null;b.len=b.off=0;null===h?h=d=b:d=d.next=b;b.len=e-a;for(f=0;f<b.len;f++)b.ptr[f]=c[a+f];e=a=0}}},ta=function(b){b&=65535;a+e<r-2?(c[a+e++]=b&255,c[a+e++]=b>>>8):(Aa(b&255),Aa(b>>>8))},Ba=function(){u=(u<<5^q[I+3-1]&255)&8191;s=A[32768+u];A[I&32767]=s;A[32768+u]=I},V=function(a,b){x>16-b?(w|=a<<x,ta(w),w=a>>16-x,x+=b-16):(w|=a<<x,x+=b)},K=function(a,b){V(b[a].fc,b[a].dl)},ua=function(a,b,c){return a[b].fc<a[c].fc||a[b].fc===a[c].fc&&ca[b]<=ca[c]},na=function(a,b,c){var d;for(d=0;d<c&&Da<
-ia.length;d++)a[b+d]=ia.charCodeAt(Da++)&255;return d},ea=function(){var a,b,c=65536-z-I;if(-1===c)c--;else if(65274<=I){for(a=0;32768>a;a++)q[a]=q[a+32768];W-=32768;I-=32768;v-=32768;for(a=0;8192>a;a++)b=A[32768+a],A[32768+a]=32768<=b?b-32768:0;for(a=0;32768>a;a++)b=A[a],A[a]=32768<=b?b-32768:0;c+=32768}Q||(a=na(q,I+z,c),0>=a?Q=!0:z+=a)},oa=function(a){var b=ja,c=I,d,e=L,f=32506<I?I-32506:0,h=I+258,k=q[c+e-1],g=q[c+e];L>=Z&&(b>>=2);do if(d=a,q[d+e]===g&&q[d+e-1]===k&&q[d]===q[c]&&q[++d]===q[c+1]){c+=
-2;d++;do++c;while(q[c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&q[++c]===q[++d]&&c<h);d=258-(h-c);c=h-258;if(d>e){W=a;e=d;if(258<=d)break;k=q[c+e-1];g=q[c+e]}a=A[a&32767]}while(a>f&&0!==--b);return e},Ca=function(a,b){t[S++]=b;0===a?O[b].fc++:(a--,O[ma[b]+256+1].fc++,aa[(256>a?T[a]:T[256+(a>>7)])&255].fc++,k[ga++]=a,fa|=D);D<<=1;0===(S&7)&&(da[E++]=fa,fa=0,D=1);if(2<G&&0===(S&4095)){var c=8*S,d=I-v,e;for(e=0;30>e;e++)c+=aa[e].fc*
-(5+qa[e]);c>>=3;if(ga<parseInt(S/2,10)&&c<parseInt(d/2,10))return!0}return 8191===S||8192===ga},ya=function(a,b){for(var c=M[b],d=b<<1;d<=ba;){d<ba&&ua(a,M[d+1],M[d])&&d++;if(ua(a,c,M[d]))break;M[b]=M[d];b=d;d<<=1}M[b]=c},Ea=function(a,b){var c=0;do c|=a&1,a>>=1,c<<=1;while(0<--b);return c>>1},za=function(a,b){var c=[];c.length=16;var d=0,e;for(e=1;15>=e;e++)d=d+P[e-1]<<1,c[e]=d;for(d=0;d<=b;d++)e=a[d].dl,0!==e&&(a[d].fc=Ea(c[e]++,e))},va=function(a){var b=a.dyn_tree,c=a.static_tree,d=a.elems,e,f=
--1,h=d;ba=0;la=573;for(e=0;e<d;e++)0!==b[e].fc?(M[++ba]=f=e,ca[e]=0):b[e].dl=0;for(;2>ba;)e=M[++ba]=2>f?++f:0,b[e].fc=1,ca[e]=0,pa--,null!==c&&(ha-=c[e].dl);a.max_code=f;for(e=ba>>1;1<=e;e--)ya(b,e);do e=M[1],M[1]=M[ba--],ya(b,1),c=M[1],M[--la]=e,M[--la]=c,b[h].fc=b[e].fc+b[c].fc,ca[h]=ca[e]>ca[c]+1?ca[e]:ca[c]+1,b[e].dl=b[c].dl=h,M[1]=h++,ya(b,1);while(2<=ba);M[--la]=M[1];h=a.dyn_tree;e=a.extra_bits;var d=a.extra_base,c=a.max_code,k=a.max_length,g=a.static_tree,q,m,l,p,n=0;for(m=0;15>=m;m++)P[m]=
-0;h[M[la]].dl=0;for(a=la+1;573>a;a++)q=M[a],m=h[h[q].dl].dl+1,m>k&&(m=k,n++),h[q].dl=m,q>c||(P[m]++,l=0,q>=d&&(l=e[q-d]),p=h[q].fc,pa+=p*(m+l),null!==g&&(ha+=p*(g[q].dl+l)));if(0!==n){do{for(m=k-1;0===P[m];)m--;P[m]--;P[m+1]+=2;P[k]--;n-=2}while(0<n);for(m=k;0!==m;m--)for(q=P[m];0!==q;)e=M[--a],e>c||(h[e].dl!==m&&(pa+=(m-h[e].dl)*h[e].fc,h[e].fc=m),q--)}za(b,f)},Fa=function(a,b){var c,d=-1,e,f=a[0].dl,h=0,k=7,g=4;0===f&&(k=138,g=3);a[b+1].dl=65535;for(c=0;c<=b;c++)e=f,f=a[c+1].dl,++h<k&&e===f||(h<
-g?C[e].fc+=h:0!==e?(e!==d&&C[e].fc++,C[16].fc++):10>=h?C[17].fc++:C[18].fc++,h=0,d=e,0===f?(k=138,g=3):e===f?(k=6,g=3):(k=7,g=4))},wa=function(){8<x?ta(w):0<x&&Aa(w);x=w=0},Ha=function(a,b){var c,d=0,e=0,f=0,h=0,g,q;if(0!==S){do 0===(d&7)&&(h=da[f++]),c=t[d++]&255,0===(h&1)?K(c,a):(g=ma[c],K(g+256+1,a),q=N[g],0!==q&&(c-=$[g],V(c,q)),c=k[e++],g=(256>c?T[c]:T[256+(c>>7)])&255,K(g,b),q=qa[g],0!==q&&(c-=X[g],V(c,q))),h>>=1;while(d<S)}K(256,a)},Ia=function(a,b){var c,d=-1,e,f=a[0].dl,h=0,k=7,g=4;0===f&&
-(k=138,g=3);for(c=0;c<=b;c++)if(e=f,f=a[c+1].dl,!(++h<k&&e===f)){if(h<g){do K(e,C);while(0!==--h)}else 0!==e?(e!==d&&(K(e,C),h--),K(16,C),V(h-3,2)):10>=h?(K(17,C),V(h-3,3)):(K(18,C),V(h-11,7));h=0;d=e;0===f?(k=138,g=3):e===f?(k=6,g=3):(k=7,g=4)}},Ja=function(){var a;for(a=0;286>a;a++)O[a].fc=0;for(a=0;30>a;a++)aa[a].fc=0;for(a=0;19>a;a++)C[a].fc=0;O[256].fc=1;fa=S=ga=E=pa=ha=0;D=1},Ga=function(a){var b,c,d,e;e=I-v;da[E]=fa;va(Y);va(U);Fa(O,Y.max_code);Fa(aa,U.max_code);va(R);for(d=18;3<=d&&0===C[xa[d]].dl;d--);
-pa+=3*(d+1)+14;b=pa+3+7>>3;c=ha+3+7>>3;c<=b&&(b=c);if(e+4<=b&&0<=v)for(V(0+a,3),wa(),ta(e),ta(~e),d=0;d<e;d++)Aa(q[v+d]);else if(c===b)V(2+a,3),Ha(J,F);else{V(4+a,3);e=Y.max_code+1;b=U.max_code+1;d+=1;V(e-257,5);V(b-1,5);V(d-4,4);for(c=0;c<d;c++)V(C[xa[c]].dl,3);Ia(O,e-1);Ia(aa,b-1);Ha(O,aa)}Ja();0!==a&&wa()},Ka=function(b,d,f){var k,g,q;for(k=0;null!==h&&k<f;){g=f-k;g>h.len&&(g=h.len);for(q=0;q<g;q++)b[d+k+q]=h.ptr[h.off+q];h.off+=g;h.len-=g;k+=g;0===h.len&&(g=h,h=h.next,g.next=n,n=g)}if(k===f)return k;
-if(a<e){g=f-k;g>e-a&&(g=e-a);for(q=0;q<g;q++)b[d+k+q]=c[a+q];a+=g;k+=g;e===a&&(e=a=0)}return k},La=function(c,d,f){var k;if(!m){if(!Q){x=w=0;var g,l;if(0===F[0].dl){Y.dyn_tree=O;Y.static_tree=J;Y.extra_bits=N;Y.extra_base=257;Y.elems=286;Y.max_length=15;Y.max_code=0;U.dyn_tree=aa;U.static_tree=F;U.extra_bits=qa;U.extra_base=0;U.elems=30;U.max_length=15;U.max_code=0;R.dyn_tree=C;R.static_tree=null;R.extra_bits=sa;R.extra_base=0;R.elems=19;R.max_length=7;for(l=g=R.max_code=0;28>l;l++)for($[l]=g,k=0;k<
-1<<N[l];k++)ma[g++]=l;ma[g-1]=l;for(l=g=0;16>l;l++)for(X[l]=g,k=0;k<1<<qa[l];k++)T[g++]=l;for(g>>=7;30>l;l++)for(X[l]=g<<7,k=0;k<1<<qa[l]-7;k++)T[256+g++]=l;for(k=0;15>=k;k++)P[k]=0;for(k=0;143>=k;)J[k++].dl=8,P[8]++;for(;255>=k;)J[k++].dl=9,P[9]++;for(;279>=k;)J[k++].dl=7,P[7]++;for(;287>=k;)J[k++].dl=8,P[8]++;za(J,287);for(k=0;30>k;k++)F[k].dl=5,F[k].fc=Ea(k,5);Ja()}for(k=0;8192>k;k++)A[32768+k]=0;ka=ra[G].max_lazy;Z=ra[G].good_length;ja=ra[G].max_chain;v=I=0;z=na(q,0,65536);if(0>=z)Q=!0,z=0;else{for(Q=
-!1;262>z&&!Q;)ea();for(k=u=0;2>k;k++)u=(u<<5^q[k]&255)&8191}h=null;a=e=0;3>=G?(L=2,B=0):(B=2,y=0);b=!1}m=!0;if(0===z)return b=!0,0}k=Ka(c,d,f);if(k===f)return f;if(b)return k;if(3>=G)for(;0!==z&&null===h;){Ba();0!==s&&32506>=I-s&&(B=oa(s),B>z&&(B=z));if(3<=B)if(l=Ca(I-W,B-3),z-=B,B<=ka){B--;do I++,Ba();while(0!==--B);I++}else I+=B,B=0,u=q[I]&255,u=(u<<5^q[I+1]&255)&8191;else l=Ca(0,q[I]&255),z--,I++;l&&(Ga(0),v=I);for(;262>z&&!Q;)ea()}else for(;0!==z&&null===h;){Ba();L=B;H=W;B=2;0!==s&&L<ka&&32506>=
-I-s&&(B=oa(s),B>z&&(B=z),3===B&&4096<I-W&&B--);if(3<=L&&B<=L){l=Ca(I-1-H,L-3);z-=L-1;L-=2;do I++,Ba();while(0!==--L);y=0;B=2;I++;l&&(Ga(0),v=I)}else 0!==y?Ca(0,q[I-1]&255)&&(Ga(0),v=I):y=1,I++,z--;for(;262>z&&!Q;)ea()}0===z&&(0!==y&&Ca(0,q[I-1]&255),Ga(1),b=!0);return k+Ka(c,k+d,f-k)};this.deflate=function(a,b){var e,f;ia=a;Da=0;"undefined"===String(typeof b)&&(b=6);(e=b)?1>e?e=1:9<e&&(e=9):e=6;G=e;Q=m=!1;if(null===c){n=h=d=null;c=[];c.length=r;q=[];q.length=65536;k=[];k.length=8192;t=[];t.length=
-32832;A=[];A.length=65536;O=[];O.length=573;for(e=0;573>e;e++)O[e]=new g;aa=[];aa.length=61;for(e=0;61>e;e++)aa[e]=new g;J=[];J.length=288;for(e=0;288>e;e++)J[e]=new g;F=[];F.length=30;for(e=0;30>e;e++)F[e]=new g;C=[];C.length=39;for(e=0;39>e;e++)C[e]=new g;Y=new l;U=new l;R=new l;P=[];P.length=16;M=[];M.length=573;ca=[];ca.length=573;ma=[];ma.length=256;T=[];T.length=512;$=[];$.length=29;X=[];X.length=30;da=[];da.length=1024}var p=Array(1024),v=[],s=[];for(e=La(p,0,p.length);0<e;){s.length=e;for(f=
-0;f<e;f++)s[f]=String.fromCharCode(p[f]);v[v.length]=s.join("");e=La(p,0,p.length)}ia="";return v.join("")}};
-// Input 44
-runtime.loadClass("odf.Namespaces");
-gui.ImageSelector=function(g){function l(){var f=g.getSizer(),d,m;d=r.createElement("div");d.id="imageSelector";d.style.borderWidth="1px";f.appendChild(d);p.forEach(function(c){m=r.createElement("div");m.className=c;d.appendChild(m)});return d}var f=odf.Namespaces.svgns,p="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),r=g.getElement().ownerDocument,n=!1;this.select=function(h){var d,m,c=r.getElementById("imageSelector");c||(c=l());n=!0;d=c.parentNode;
-m=h.getBoundingClientRect();var e=d.getBoundingClientRect(),a=g.getZoomLevel();d=(m.left-e.left)/a-1;m=(m.top-e.top)/a-1;c.style.display="block";c.style.left=d+"px";c.style.top=m+"px";c.style.width=h.getAttributeNS(f,"width");c.style.height=h.getAttributeNS(f,"height")};this.clearSelection=function(){var f;n&&(f=r.getElementById("imageSelector"))&&(f.style.display="none");n=!1};this.isSelectorElement=function(f){var d=r.getElementById("imageSelector");return d?f===d||f.parentNode===d:!1}};
-// Input 45
-runtime.loadClass("odf.OdfCanvas");
-odf.CommandLineTools=function(){this.roundTrip=function(g,l,f){return new odf.OdfContainer(g,function(p){if(p.state===odf.OdfContainer.INVALID)return f("Document "+g+" is invalid.");p.state===odf.OdfContainer.DONE?p.saveAs(l,function(g){f(g)}):f("Document was not completely loaded.")})};this.render=function(g,l,f){for(l=l.getElementsByTagName("body")[0];l.firstChild;)l.removeChild(l.firstChild);l=new odf.OdfCanvas(l);l.addListener("statereadychange",function(g){f(g)});l.load(g)}};
-// Input 46
+ops.OpAddCursor=function(){var k,h;this.init=function(b){k=b.memberid;h=b.timestamp};this.isEdit=!1;this.group=void 0;this.execute=function(b){var h=b.getCursor(k);if(h)return!1;h=new ops.OdtCursor(k,b);b.addCursor(h);b.emit(ops.Document.signalCursorAdded,h);return!0};this.spec=function(){return{optype:"AddCursor",memberid:k,timestamp:h}}};
+// Input 47
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -1239,9 +1391,8 @@ odf.CommandLineTools=function(){this.roundTrip=function(g,l,f){return new odf.Od
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.Member=function(g,l){var f={};this.getMemberId=function(){return g};this.getProperties=function(){return f};this.setProperties=function(g){Object.keys(g).forEach(function(l){f[l]=g[l]})};this.removeProperties=function(g){delete g.fullName;delete g.color;delete g.imageUrl;Object.keys(g).forEach(function(g){f.hasOwnProperty(g)&&delete f[g]})};runtime.assert(Boolean(g),"No memberId was supplied!");l.fullName||(l.fullName=runtime.tr("Unknown Author"));l.color||(l.color="black");l.imageUrl||(l.imageUrl=
-"avatar-joe.png");f=l};
-// Input 47
+ops.OpAddMember=function(){var k,h,b;this.init=function(p){k=p.memberid;h=parseInt(p.timestamp,10);b=p.setProperties};this.isEdit=!1;this.group=void 0;this.execute=function(h){var d;if(h.getMember(k))return!1;d=new ops.Member(k,b);h.addMember(d);h.emit(ops.Document.signalMemberAdded,d);return!0};this.spec=function(){return{optype:"AddMember",memberid:k,timestamp:h,setProperties:b}}};
+// Input 48
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1279,33 +1430,9 @@ ops.Member=function(g,l){var f={};this.getMemberId=function(){return g};this.get
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils");
-(function(){function g(f,g,r){function n(a,b){function c(a){for(var b=0;a&&a.previousSibling;)b+=1,a=a.previousSibling;return b}this.steps=a;this.node=b;this.setIteratorPosition=function(a){a.setUnfilteredPosition(b.parentNode,c(b));do if(g.acceptPosition(a)===t)break;while(a.nextPosition())}}function h(a){return a.nodeType===Node.ELEMENT_NODE&&a.getAttributeNS(c,"nodeId")}function d(a){var b=l;a.setAttributeNS(c,"nodeId",b.toString());l+=1;return b}function m(b,d){var e,k=null;for(b=b.childNodes[d]||
-b;!k&&b&&b!==f;)(e=h(b))&&(k=a[e])&&k.node!==b&&(runtime.log("Cloned node detected. Creating new bookmark"),k=null,b.removeAttributeNS(c,"nodeId")),b=b.parentNode;return k}var c="urn:webodf:names:steps",e={},a={},b=new odf.OdfUtils,q=new core.DomUtils,k,t=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.updateCache=function(c,f,k,g){var q;0===k&&b.isParagraph(f)?(q=!0,g||(c+=1)):f.hasChildNodes()&&f.childNodes[k]&&(f=f.childNodes[k],(q=b.isParagraph(f))&&(c+=1));q&&(k=h(f)||d(f),(g=a[k])?g.node===
-f?g.steps=c:(runtime.log("Cloned node detected. Creating new bookmark"),k=d(f),g=a[k]=new n(c,f)):g=a[k]=new n(c,f),k=g,c=Math.ceil(k.steps/r)*r,f=e[c],!f||k.steps>f.steps)&&(e[c]=k)};this.setToClosestStep=function(a,b){for(var c=Math.floor(a/r)*r,d;!d&&0!==c;)d=e[c],c-=r;d=d||k;d.setIteratorPosition(b);return d.steps};this.setToClosestDomPoint=function(a,b,c){var d;if(a===f&&0===b)d=k;else if(a===f&&b===f.childNodes.length)d=Object.keys(e).map(function(a){return e[a]}).reduce(function(a,b){return b.steps>
-a.steps?b:a},k);else if(d=m(a,b),!d)for(c.setUnfilteredPosition(a,b);!d&&c.previousNode();)d=m(c.container(),c.unfilteredDomOffset());d=d||k;d.setIteratorPosition(c);return d.steps};this.updateCacheAtPoint=function(b,c){var d={};Object.keys(a).map(function(b){return a[b]}).filter(function(a){return a.steps>b}).forEach(function(b){var k=Math.ceil(b.steps/r)*r,g,m;if(q.containsNode(f,b.node)){if(c(b),g=Math.ceil(b.steps/r)*r,m=d[g],!m||b.steps>m.steps)d[g]=b}else delete a[h(b.node)];e[k]===b&&delete e[k]});
-Object.keys(d).forEach(function(a){e[a]=d[a]})};k=new function(a,b){this.steps=a;this.node=b;this.setIteratorPosition=function(a){a.setUnfilteredPosition(b,0);do if(g.acceptPosition(a)===t)break;while(a.nextPosition())}}(0,f)}var l=0;ops.StepsTranslator=function(f,l,r,n){function h(){var b=f();b!==m&&(runtime.log("Undo detected. Resetting steps cache"),m=b,c=new g(m,r,n),a=l(m))}function d(a,c){if(!c||r.acceptPosition(a)===b)return!0;for(;a.previousPosition();)if(r.acceptPosition(a)===b){if(c(0,a.container(),
-a.unfilteredDomOffset()))return!0;break}for(;a.nextPosition();)if(r.acceptPosition(a)===b){if(c(1,a.container(),a.unfilteredDomOffset()))return!0;break}return!1}var m=f(),c=new g(m,r,n),e=new core.DomUtils,a=l(f()),b=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.convertStepsToDomPoint=function(d){var e,f;0>d&&(runtime.log("warn","Requested steps were negative ("+d+")"),d=0);h();for(e=c.setToClosestStep(d,a);e<d&&a.nextPosition();)(f=r.acceptPosition(a)===b)&&(e+=1),c.updateCache(e,a.container(),
-a.unfilteredDomOffset(),f);e!==d&&runtime.log("warn","Requested "+d+" steps but only "+e+" are available");return{node:a.container(),offset:a.unfilteredDomOffset()}};this.convertDomPointToSteps=function(f,k,g){var l;h();e.containsNode(m,f)||(k=0>e.comparePoints(m,0,f,k),f=m,k=k?0:m.childNodes.length);a.setUnfilteredPosition(f,k);d(a,g)||a.setUnfilteredPosition(f,k);g=a.container();k=a.unfilteredDomOffset();f=c.setToClosestDomPoint(g,k,a);if(0>e.comparePoints(a.container(),a.unfilteredDomOffset(),
-g,k))return 0<f?f-1:f;for(;(a.container()!==g||a.unfilteredDomOffset()!==k)&&a.nextPosition();)(l=r.acceptPosition(a)===b)&&(f+=1),c.updateCache(f,a.container(),a.unfilteredDomOffset(),l);return f+0};this.prime=function(){var d,e;h();for(d=c.setToClosestStep(0,a);a.nextPosition();)(e=r.acceptPosition(a)===b)&&(d+=1),c.updateCache(d,a.container(),a.unfilteredDomOffset(),e)};this.handleStepsInserted=function(a){h();c.updateCacheAtPoint(a.position,function(b){b.steps+=a.length})};this.handleStepsRemoved=
-function(a){h();c.updateCacheAtPoint(a.position,function(b){b.steps-=a.length;0>b.steps&&(b.steps=0)})}};ops.StepsTranslator.PREVIOUS_STEP=0;ops.StepsTranslator.NEXT_STEP=1;return ops.StepsTranslator})();
-// Input 48
-xmldom.RNG={};
-xmldom.RelaxNGParser=function(){function g(c,d){this.message=function(){d&&(c+=1===d.nodeType?" Element ":" Node ",c+=d.nodeName,d.nodeValue&&(c+=" with value '"+d.nodeValue+"'"),c+=".");return c}}function l(c){if(2>=c.e.length)return c;var d={name:c.name,e:c.e.slice(0,2)};return l({name:c.name,e:[d].concat(c.e.slice(2))})}function f(c){c=c.split(":",2);var e="",a;1===c.length?c=["",c[0]]:e=c[0];for(a in d)d[a]===e&&(c[0]=a);return c}function p(c,d){for(var a=0,b,h,k=c.name;c.e&&a<c.e.length;)if(b=c.e[a],
-"ref"===b.name){h=d[b.a.name];if(!h)throw b.a.name+" was not defined.";b=c.e.slice(a+1);c.e=c.e.slice(0,a);c.e=c.e.concat(h.e);c.e=c.e.concat(b)}else a+=1,p(b,d);b=c.e;"choice"!==k||b&&b[1]&&"empty"!==b[1].name||(b&&b[0]&&"empty"!==b[0].name?(b[1]=b[0],b[0]={name:"empty"}):(delete c.e,c.name="empty"));if("group"===k||"interleave"===k)"empty"===b[0].name?"empty"===b[1].name?(delete c.e,c.name="empty"):(k=c.name=b[1].name,c.names=b[1].names,b=c.e=b[1].e):"empty"===b[1].name&&(k=c.name=b[0].name,c.names=
-b[0].names,b=c.e=b[0].e);"oneOrMore"===k&&"empty"===b[0].name&&(delete c.e,c.name="empty");if("attribute"===k){h=c.names?c.names.length:0;for(var g,m=[],l=[],a=0;a<h;a+=1)g=f(c.names[a]),l[a]=g[0],m[a]=g[1];c.localnames=m;c.namespaces=l}"interleave"===k&&("interleave"===b[0].name?c.e="interleave"===b[1].name?b[0].e.concat(b[1].e):[b[1]].concat(b[0].e):"interleave"===b[1].name&&(c.e=[b[0]].concat(b[1].e)))}function r(c,d){for(var a=0,b;c.e&&a<c.e.length;)b=c.e[a],"elementref"===b.name?(b.id=b.id||
-0,c.e[a]=d[b.id]):"element"!==b.name&&r(b,d),a+=1}var n=this,h,d={"http://www.w3.org/XML/1998/namespace":"xml"},m;m=function(c,e,a){var b=[],h,g,n=c.localName,p=[];h=c.attributes;var r=n,x=p,v={},u,s;for(u=0;h&&u<h.length;u+=1)if(s=h.item(u),s.namespaceURI)"http://www.w3.org/2000/xmlns/"===s.namespaceURI&&(d[s.value]=s.localName);else{"name"!==s.localName||"element"!==r&&"attribute"!==r||x.push(s.value);if("name"===s.localName||"combine"===s.localName||"type"===s.localName){var H=s,y;y=s.value;y=
-y.replace(/^\s\s*/,"");for(var B=/\s/,L=y.length-1;B.test(y.charAt(L));)L-=1;y=y.slice(0,L+1);H.value=y}v[s.localName]=s.value}h=v;h.combine=h.combine||void 0;c=c.firstChild;r=b;x=p;for(v="";c;){if(c.nodeType===Node.ELEMENT_NODE&&"http://relaxng.org/ns/structure/1.0"===c.namespaceURI){if(u=m(c,e,r))"name"===u.name?x.push(d[u.a.ns]+":"+u.text):"choice"===u.name&&u.names&&u.names.length&&(x=x.concat(u.names),delete u.names),r.push(u)}else c.nodeType===Node.TEXT_NODE&&(v+=c.nodeValue);c=c.nextSibling}c=
-v;"value"!==n&&"param"!==n&&(c=/^\s*([\s\S]*\S)?\s*$/.exec(c)[1]);"value"===n&&void 0===h.type&&(h.type="token",h.datatypeLibrary="");"attribute"!==n&&"element"!==n||void 0===h.name||(g=f(h.name),b=[{name:"name",text:g[1],a:{ns:g[0]}}].concat(b),delete h.name);"name"===n||"nsName"===n||"value"===n?void 0===h.ns&&(h.ns=""):delete h.ns;"name"===n&&(g=f(c),h.ns=g[0],c=g[1]);1<b.length&&("define"===n||"oneOrMore"===n||"zeroOrMore"===n||"optional"===n||"list"===n||"mixed"===n)&&(b=[{name:"group",e:l({name:"group",
-e:b}).e}]);2<b.length&&"element"===n&&(b=[b[0]].concat({name:"group",e:l({name:"group",e:b.slice(1)}).e}));1===b.length&&"attribute"===n&&b.push({name:"text",text:c});1!==b.length||"choice"!==n&&"group"!==n&&"interleave"!==n?2<b.length&&("choice"===n||"group"===n||"interleave"===n)&&(b=l({name:n,e:b}).e):(n=b[0].name,p=b[0].names,h=b[0].a,c=b[0].text,b=b[0].e);"mixed"===n&&(n="interleave",b=[b[0],{name:"text"}]);"optional"===n&&(n="choice",b=[b[0],{name:"empty"}]);"zeroOrMore"===n&&(n="choice",b=
-[{name:"oneOrMore",e:[b[0]]},{name:"empty"}]);if("define"===n&&h.combine){a:{r=h.combine;x=h.name;v=b;for(u=0;a&&u<a.length;u+=1)if(s=a[u],"define"===s.name&&s.a&&s.a.name===x){s.e=[{name:r,e:s.e.concat(v)}];a=s;break a}a=null}if(a)return null}a={name:n};b&&0<b.length&&(a.e=b);for(g in h)if(h.hasOwnProperty(g)){a.a=h;break}void 0!==c&&(a.text=c);p&&0<p.length&&(a.names=p);"element"===n&&(a.id=e.length,e.push(a),a={name:"elementref",id:a.id});return a};this.parseRelaxNGDOM=function(c,e){var a=[],b=
-m(c&&c.documentElement,a,void 0),f,k,l={};for(f=0;f<b.e.length;f+=1)k=b.e[f],"define"===k.name?l[k.a.name]=k:"start"===k.name&&(h=k);if(!h)return[new g("No Relax NG start element was found.")];p(h,l);for(f in l)l.hasOwnProperty(f)&&p(l[f],l);for(f=0;f<a.length;f+=1)p(a[f],l);e&&(n.rootPattern=e(h.e[0],a));r(h,a);for(f=0;f<a.length;f+=1)r(a[f],a);n.start=h;n.elements=a;n.nsmap=d;return null}};
+ops.OpAddStyle=function(){var k,h,b,p,d,n,g=odf.Namespaces.stylens;this.init=function(g){k=g.memberid;h=g.timestamp;b=g.styleName;p=g.styleFamily;d="true"===g.isAutomaticStyle||!0===g.isAutomaticStyle;n=g.setProperties};this.isEdit=!0;this.group=void 0;this.execute=function(h){var k=h.getOdfCanvas().odfContainer(),l=h.getFormatting(),f=h.getDOMDocument().createElementNS(g,"style:style");if(!f)return!1;n&&l.updateStyle(f,n);f.setAttributeNS(g,"style:family",p);f.setAttributeNS(g,"style:name",b);d?
+k.rootElement.automaticStyles.appendChild(f):k.rootElement.styles.appendChild(f);h.getOdfCanvas().refreshCSS();d||h.emit(ops.OdtDocument.signalCommonStyleCreated,{name:b,family:p});return!0};this.spec=function(){return{optype:"AddStyle",memberid:k,timestamp:h,styleName:b,styleFamily:p,isAutomaticStyle:d,setProperties:n}}};
// Input 49
-runtime.loadClass("core.Cursor");runtime.loadClass("gui.SelectionMover");
-ops.OdtCursor=function(g,l){var f=this,p={},r,n,h;this.removeFromOdtDocument=function(){h.remove()};this.move=function(d,h){var c=0;0<d?c=n.movePointForward(d,h):0>=d&&(c=-n.movePointBackward(-d,h));f.handleUpdate();return c};this.handleUpdate=function(){};this.getStepCounter=function(){return n.getStepCounter()};this.getMemberId=function(){return g};this.getNode=function(){return h.getNode()};this.getAnchorNode=function(){return h.getAnchorNode()};this.getSelectedRange=function(){return h.getSelectedRange()};
-this.setSelectedRange=function(d,g){h.setSelectedRange(d,g);f.handleUpdate()};this.hasForwardSelection=function(){return h.hasForwardSelection()};this.getOdtDocument=function(){return l};this.getSelectionType=function(){return r};this.setSelectionType=function(d){p.hasOwnProperty(d)?r=d:runtime.log("Invalid selection type: "+d)};this.resetSelectionType=function(){f.setSelectionType(ops.OdtCursor.RangeSelection)};h=new core.Cursor(l.getDOM(),g);n=new gui.SelectionMover(h,l.getRootNode());p[ops.OdtCursor.RangeSelection]=
-!0;p[ops.OdtCursor.RegionSelection]=!0;f.resetSelectionType()};ops.OdtCursor.RangeSelection="Range";ops.OdtCursor.RegionSelection="Region";(function(){return ops.OdtCursor})();
-// Input 50
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1343,25 +1470,10 @@ this.setSelectedRange=function(d,g){h.setSelectedRange(d,g);f.handleUpdate()};th
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.EventNotifier");runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.Namespaces");runtime.loadClass("gui.SelectionMover");runtime.loadClass("core.PositionFilterChain");runtime.loadClass("ops.StepsTranslator");runtime.loadClass("ops.TextPositionFilter");runtime.loadClass("ops.Member");
-ops.OdtDocument=function(g){function l(){var a=g.odfContainer().getContentElement(),b=a&&a.localName;runtime.assert("text"===b,"Unsupported content element type '"+b+"' for OdtDocument");return a}function f(){return l().ownerDocument}function p(a){for(;a&&!(a.namespaceURI===odf.Namespaces.officens&&"text"===a.localName||a.namespaceURI===odf.Namespaces.officens&&"annotation"===a.localName);)a=a.parentNode;return a}function r(b){this.acceptPosition=function(c){c=c.container();var d;d="string"===typeof b?
-a[b].getNode():b;return p(c)===p(d)?k:t}}function n(a){var b=gui.SelectionMover.createPositionIterator(l());a=w.convertStepsToDomPoint(a);b.setUnfilteredPosition(a.node,a.offset);return b}function h(a,b){return g.getFormatting().getStyleElement(a,b)}function d(a){return h(a,"paragraph")}var m=this,c,e,a={},b={},q=new core.EventNotifier([ops.OdtDocument.signalMemberAdded,ops.OdtDocument.signalMemberUpdated,ops.OdtDocument.signalMemberRemoved,ops.OdtDocument.signalCursorAdded,ops.OdtDocument.signalCursorRemoved,
-ops.OdtDocument.signalCursorMoved,ops.OdtDocument.signalParagraphChanged,ops.OdtDocument.signalParagraphStyleModified,ops.OdtDocument.signalCommonStyleCreated,ops.OdtDocument.signalCommonStyleDeleted,ops.OdtDocument.signalTableAdded,ops.OdtDocument.signalOperationExecuted,ops.OdtDocument.signalUndoStackChanged,ops.OdtDocument.signalStepsInserted,ops.OdtDocument.signalStepsRemoved]),k=core.PositionFilter.FilterResult.FILTER_ACCEPT,t=core.PositionFilter.FilterResult.FILTER_REJECT,A,w,x;this.getDOM=
-f;this.getRootElement=p;this.getIteratorAtPosition=n;this.convertDomPointToCursorStep=function(a,b,c){return w.convertDomPointToSteps(a,b,c)};this.convertDomToCursorRange=function(a,b){var c,d;c=b(a.anchorNode,a.anchorOffset);c=w.convertDomPointToSteps(a.anchorNode,a.anchorOffset,c);b||a.anchorNode!==a.focusNode||a.anchorOffset!==a.focusOffset?(d=b(a.focusNode,a.focusOffset),d=w.convertDomPointToSteps(a.focusNode,a.focusOffset,d)):d=c;return{position:c,length:d-c}};this.convertCursorToDomRange=function(a,
-b){var c=f().createRange(),d,e;d=w.convertStepsToDomPoint(a);b?(e=w.convertStepsToDomPoint(a+b),0<b?(c.setStart(d.node,d.offset),c.setEnd(e.node,e.offset)):(c.setStart(e.node,e.offset),c.setEnd(d.node,d.offset))):c.setStart(d.node,d.offset);return c};this.getStyleElement=h;this.upgradeWhitespacesAtPosition=function(a){a=n(a);var b,d,e;a.previousPosition();a.previousPosition();for(e=-1;1>=e;e+=1){b=a.container();d=a.unfilteredDomOffset();if(b.nodeType===Node.TEXT_NODE&&" "===b.data[d]&&c.isSignificantWhitespace(b,
-d)){runtime.assert(" "===b.data[d],"upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");var f=b.ownerDocument.createElementNS(odf.Namespaces.textns,"text:s");f.appendChild(b.ownerDocument.createTextNode(" "));b.deleteData(d,1);0<d&&(b=b.splitText(d));b.parentNode.insertBefore(f,b);b=f;a.moveToEndOfNode(b)}a.nextPosition()}};this.downgradeWhitespacesAtPosition=function(a){var b=n(a),d;a=b.container();for(b=b.unfilteredDomOffset();!c.isSpaceElement(a)&&a.childNodes[b];)a=a.childNodes[b],
-b=0;a.nodeType===Node.TEXT_NODE&&(a=a.parentNode);c.isDowngradableSpaceElement(a)&&(b=a.firstChild,d=a.lastChild,e.mergeIntoParent(a),d!==b&&e.normalizeTextNodes(d),e.normalizeTextNodes(b))};this.getParagraphStyleElement=d;this.getParagraphElement=function(a){return c.getParagraphElement(a)};this.getParagraphStyleAttributes=function(a){return(a=d(a))?g.getFormatting().getInheritedStyleAttributes(a):null};this.getTextNodeAtStep=function(b,c){var d=n(b),e=d.container(),h,g=0,k=null;e.nodeType===Node.TEXT_NODE?
-(h=e,g=d.unfilteredDomOffset(),0<h.length&&(0<g&&(h=h.splitText(g)),h.parentNode.insertBefore(f().createTextNode(""),h),h=h.previousSibling,g=0)):(h=f().createTextNode(""),g=0,e.insertBefore(h,d.rightNode()));if(c){if(a[c]&&m.getCursorPosition(c)===b){for(k=a[c].getNode();k.nextSibling&&"cursor"===k.nextSibling.localName;)k.parentNode.insertBefore(k.nextSibling,k);0<h.length&&h.nextSibling!==k&&(h=f().createTextNode(""),g=0);k.parentNode.insertBefore(h,k)}}else for(;h.nextSibling&&"cursor"===h.nextSibling.localName;)h.parentNode.insertBefore(h.nextSibling,
-h);for(;h.previousSibling&&h.previousSibling.nodeType===Node.TEXT_NODE;)h.previousSibling.appendData(h.data),g=h.previousSibling.length,h=h.previousSibling,h.parentNode.removeChild(h.nextSibling);for(;h.nextSibling&&h.nextSibling.nodeType===Node.TEXT_NODE;)h.appendData(h.nextSibling.data),h.parentNode.removeChild(h.nextSibling);return{textNode:h,offset:g}};this.fixCursorPositions=function(){var b=new core.PositionFilterChain;b.addFilter("BaseFilter",A);Object.keys(a).forEach(function(c){var d=a[c],
-e=d.getStepCounter(),f,h,g=!1;b.addFilter("RootFilter",m.createRootFilter(c));c=e.countStepsToPosition(d.getAnchorNode(),0,b);e.isPositionWalkable(b)?0===c&&(g=!0,d.move(0)):(g=!0,f=e.countPositionsToNearestStep(d.getNode(),0,b),h=e.countPositionsToNearestStep(d.getAnchorNode(),0,b),d.move(f),0!==c&&(0<h&&(c+=1),0<f&&(c-=1),e=e.countSteps(c,b),d.move(e),d.move(-e,!0)));g&&m.emit(ops.OdtDocument.signalCursorMoved,d);b.removeFilter("RootFilter")})};this.getDistanceFromCursor=function(b,c,d){b=a[b];
-var e,f;runtime.assert(null!==c&&void 0!==c,"OdtDocument.getDistanceFromCursor called without node");b&&(e=w.convertDomPointToSteps(b.getNode(),0),f=w.convertDomPointToSteps(c,d));return f-e};this.getCursorPosition=function(b){return(b=a[b])?w.convertDomPointToSteps(b.getNode(),0):0};this.getCursorSelection=function(b){b=a[b];var c=0,d=0;b&&(c=w.convertDomPointToSteps(b.getNode(),0),d=w.convertDomPointToSteps(b.getAnchorNode(),0));return{position:d,length:c-d}};this.getPositionFilter=function(){return A};
-this.getOdfCanvas=function(){return g};this.getRootNode=l;this.addMember=function(a){runtime.assert(void 0===b[a.getMemberId()],"This member already exists");b[a.getMemberId()]=a};this.getMember=function(a){return b.hasOwnProperty(a)?b[a]:null};this.removeMember=function(a){delete b[a]};this.getCursor=function(b){return a[b]};this.getCursors=function(){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push(a[c]);return b};this.addCursor=function(b){runtime.assert(Boolean(b),"OdtDocument::addCursor without cursor");
-var c=b.getStepCounter().countSteps(1,A),d=b.getMemberId();runtime.assert("string"===typeof d,"OdtDocument::addCursor has cursor without memberid");runtime.assert(!a[d],"OdtDocument::addCursor is adding a duplicate cursor with memberid "+d);b.move(c);a[d]=b};this.removeCursor=function(b){var c=a[b];return c?(c.removeFromOdtDocument(),delete a[b],m.emit(ops.OdtDocument.signalCursorRemoved,b),!0):!1};this.moveCursor=function(b,c,d,e){b=a[b];c=m.convertCursorToDomRange(c,d);b&&c&&(b.setSelectedRange(c,
-0<=d),b.setSelectionType(e||ops.OdtCursor.RangeSelection))};this.getFormatting=function(){return g.getFormatting()};this.emit=function(a,b){q.emit(a,b)};this.subscribe=function(a,b){q.subscribe(a,b)};this.unsubscribe=function(a,b){q.unsubscribe(a,b)};this.createRootFilter=function(a){return new r(a)};this.close=function(a){a()};this.destroy=function(a){a()};A=new ops.TextPositionFilter(l);c=new odf.OdfUtils;e=new core.DomUtils;w=new ops.StepsTranslator(l,gui.SelectionMover.createPositionIterator,
-A,500);q.subscribe(ops.OdtDocument.signalStepsInserted,w.handleStepsInserted);q.subscribe(ops.OdtDocument.signalStepsRemoved,w.handleStepsRemoved);q.subscribe(ops.OdtDocument.signalOperationExecuted,function(a){var b=a.spec(),c=b.memberid,b=(new Date(b.timestamp)).toISOString(),d=g.odfContainer();a.isEdit&&(c=m.getMember(c).getProperties().fullName,d.setMetadata({"dc:creator":c,"dc:date":b},null),x||(d.incrementEditingCycles(),d.setMetadata(null,["meta:editing-duration","meta:document-statistic"])),
-x=a)})};ops.OdtDocument.signalMemberAdded="member/added";ops.OdtDocument.signalMemberUpdated="member/updated";ops.OdtDocument.signalMemberRemoved="member/removed";ops.OdtDocument.signalCursorAdded="cursor/added";ops.OdtDocument.signalCursorRemoved="cursor/removed";ops.OdtDocument.signalCursorMoved="cursor/moved";ops.OdtDocument.signalParagraphChanged="paragraph/changed";ops.OdtDocument.signalTableAdded="table/added";ops.OdtDocument.signalCommonStyleCreated="style/created";
-ops.OdtDocument.signalCommonStyleDeleted="style/deleted";ops.OdtDocument.signalParagraphStyleModified="paragraphstyle/modified";ops.OdtDocument.signalOperationExecuted="operation/executed";ops.OdtDocument.signalUndoStackChanged="undo/changed";ops.OdtDocument.signalStepsInserted="steps/inserted";ops.OdtDocument.signalStepsRemoved="steps/removed";(function(){return ops.OdtDocument})();
-// Input 51
+odf.ObjectNameGenerator=function(k,h){function b(a,c){var b={};this.generateName=function(){var d=c(),f=0,g;do g=a+f,f+=1;while(b[g]||d[g]);b[g]=!0;return g}}function p(){var a={};[k.rootElement.automaticStyles,k.rootElement.styles].forEach(function(c){for(c=c.firstElementChild;c;)c.namespaceURI===d&&"style"===c.localName&&(a[c.getAttributeNS(d,"name")]=!0),c=c.nextElementSibling});return a}var d=odf.Namespaces.stylens,n=odf.Namespaces.drawns,g=odf.Namespaces.xlinkns,q=new core.DomUtils,r=(new core.Utils).hashString(h),
+l=null,f=null,c=null,a={},m={};this.generateStyleName=function(){null===l&&(l=new b("auto"+r+"_",function(){return p()}));return l.generateName()};this.generateFrameName=function(){null===f&&(q.getElementsByTagNameNS(k.rootElement.body,n,"frame").forEach(function(c){a[c.getAttributeNS(n,"name")]=!0}),f=new b("fr"+r+"_",function(){return a}));return f.generateName()};this.generateImageName=function(){null===c&&(q.getElementsByTagNameNS(k.rootElement.body,n,"image").forEach(function(a){a=a.getAttributeNS(g,
+"href");a=a.substring(9,a.lastIndexOf("."));m[a]=!0}),c=new b("img"+r+"_",function(){return m}));return c.generateName()}};
+// Input 50
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1399,55 +1511,14 @@ ops.OdtDocument.signalCommonStyleDeleted="style/deleted";ops.OdtDocument.signalP
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.Operation=function(){};ops.Operation.prototype.init=function(g){};ops.Operation.prototype.execute=function(g){};ops.Operation.prototype.spec=function(){};
-// Input 52
-runtime.loadClass("xmldom.RelaxNGParser");
-xmldom.RelaxNG=function(){function g(a){return function(){var b;return function(){void 0===b&&(b=a());return b}}()}function l(a,b){return function(){var c={},d=0;return function(e){var f=e.hash||e.toString();if(c.hasOwnProperty(f))return c[f];c[f]=e=b(e);e.hash=a+d.toString();d+=1;return e}}()}function f(a){return function(){var b={};return function(c){var d,e;if(b.hasOwnProperty(c.localName)){if(e=b[c.localName],d=e[c.namespaceURI],void 0!==d)return d}else b[c.localName]=e={};return e[c.namespaceURI]=
-d=a(c)}}()}function p(a,b,c){return function(){var d={},e=0;return function(f,h){var g=b&&b(f,h),k;if(void 0!==g)return g;k=f.hash||f.toString();g=h.hash||h.toString();if(d.hasOwnProperty(k)){if(k=d[k],k.hasOwnProperty(g))return k[g]}else d[k]=k={};k[g]=g=c(f,h);g.hash=a+e.toString();e+=1;return g}}()}function r(a,b){"choice"===b.p1.type?r(a,b.p1):a[b.p1.hash]=b.p1;"choice"===b.p2.type?r(a,b.p2):a[b.p2.hash]=b.p2}function n(a,b){return{type:"element",nc:a,nullable:!1,textDeriv:function(){return y},
-startTagOpenDeriv:function(c){return a.contains(c)?q(b,B):y},attDeriv:function(){return y},startTagCloseDeriv:function(){return this}}}function h(){return{type:"list",nullable:!1,hash:"list",textDeriv:function(){return B}}}function d(a,b,e,f){if(b===y)return y;if(f>=e.length)return b;0===f&&(f=0);for(var h=e.item(f);h.namespaceURI===c;){f+=1;if(f>=e.length)return b;h=e.item(f)}return h=d(a,b.attDeriv(a,e.item(f)),e,f+1)}function m(a,b,c){c.e[0].a?(a.push(c.e[0].text),b.push(c.e[0].a.ns)):m(a,b,c.e[0]);
-c.e[1].a?(a.push(c.e[1].text),b.push(c.e[1].a.ns)):m(a,b,c.e[1])}var c="http://www.w3.org/2000/xmlns/",e,a,b,q,k,t,A,w,x,v,u,s,H,y={type:"notAllowed",nullable:!1,hash:"notAllowed",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return y},startTagOpenDeriv:function(){return y},attDeriv:function(){return y},startTagCloseDeriv:function(){return y},endTagDeriv:function(){return y}},B={type:"empty",nullable:!0,hash:"empty",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return y},
-startTagOpenDeriv:function(){return y},attDeriv:function(){return y},startTagCloseDeriv:function(){return B},endTagDeriv:function(){return y}},L={type:"text",nullable:!0,hash:"text",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return L},startTagOpenDeriv:function(){return y},attDeriv:function(){return y},startTagCloseDeriv:function(){return L},endTagDeriv:function(){return y}};e=p("choice",function(a,b){if(a===y)return b;if(b===y||a===b)return a},function(a,b){var c={},d;r(c,{p1:a,
-p2:b});b=a=void 0;for(d in c)c.hasOwnProperty(d)&&(void 0===a?a=c[d]:b=void 0===b?c[d]:e(b,c[d]));return function(a,b){return{type:"choice",nullable:a.nullable||b.nullable,hash:void 0,nc:void 0,p:void 0,p1:a,p2:b,textDeriv:function(c,d){return e(a.textDeriv(c,d),b.textDeriv(c,d))},startTagOpenDeriv:f(function(c){return e(a.startTagOpenDeriv(c),b.startTagOpenDeriv(c))}),attDeriv:function(c,d){return e(a.attDeriv(c,d),b.attDeriv(c,d))},startTagCloseDeriv:g(function(){return e(a.startTagCloseDeriv(),
-b.startTagCloseDeriv())}),endTagDeriv:g(function(){return e(a.endTagDeriv(),b.endTagDeriv())})}}(a,b)});a=function(a,b,c){return function(){var d={},e=0;return function(f,h){var g=b&&b(f,h),k,m;if(void 0!==g)return g;k=f.hash||f.toString();g=h.hash||h.toString();k<g&&(m=k,k=g,g=m,m=f,f=h,h=m);if(d.hasOwnProperty(k)){if(k=d[k],k.hasOwnProperty(g))return k[g]}else d[k]=k={};k[g]=g=c(f,h);g.hash=a+e.toString();e+=1;return g}}()}("interleave",function(a,b){if(a===y||b===y)return y;if(a===B)return b;if(b===
-B)return a},function(b,c){return{type:"interleave",nullable:b.nullable&&c.nullable,hash:void 0,p1:b,p2:c,textDeriv:function(d,f){return e(a(b.textDeriv(d,f),c),a(b,c.textDeriv(d,f)))},startTagOpenDeriv:f(function(d){return e(u(function(b){return a(b,c)},b.startTagOpenDeriv(d)),u(function(c){return a(b,c)},c.startTagOpenDeriv(d)))}),attDeriv:function(d,f){return e(a(b.attDeriv(d,f),c),a(b,c.attDeriv(d,f)))},startTagCloseDeriv:g(function(){return a(b.startTagCloseDeriv(),c.startTagCloseDeriv())}),endTagDeriv:void 0}});
-b=p("group",function(a,b){if(a===y||b===y)return y;if(a===B)return b;if(b===B)return a},function(a,c){return{type:"group",p1:a,p2:c,nullable:a.nullable&&c.nullable,textDeriv:function(d,f){var h=b(a.textDeriv(d,f),c);return a.nullable?e(h,c.textDeriv(d,f)):h},startTagOpenDeriv:function(d){var f=u(function(a){return b(a,c)},a.startTagOpenDeriv(d));return a.nullable?e(f,c.startTagOpenDeriv(d)):f},attDeriv:function(d,f){return e(b(a.attDeriv(d,f),c),b(a,c.attDeriv(d,f)))},startTagCloseDeriv:g(function(){return b(a.startTagCloseDeriv(),
-c.startTagCloseDeriv())})}});q=p("after",function(a,b){if(a===y||b===y)return y},function(a,b){return{type:"after",p1:a,p2:b,nullable:!1,textDeriv:function(c,d){return q(a.textDeriv(c,d),b)},startTagOpenDeriv:f(function(c){return u(function(a){return q(a,b)},a.startTagOpenDeriv(c))}),attDeriv:function(c,d){return q(a.attDeriv(c,d),b)},startTagCloseDeriv:g(function(){return q(a.startTagCloseDeriv(),b)}),endTagDeriv:g(function(){return a.nullable?b:y})}});k=l("oneormore",function(a){return a===y?y:
-{type:"oneOrMore",p:a,nullable:a.nullable,textDeriv:function(c,d){return b(a.textDeriv(c,d),e(this,B))},startTagOpenDeriv:function(c){var d=this;return u(function(a){return b(a,e(d,B))},a.startTagOpenDeriv(c))},attDeriv:function(c,d){return b(a.attDeriv(c,d),e(this,B))},startTagCloseDeriv:g(function(){return k(a.startTagCloseDeriv())})}});A=p("attribute",void 0,function(a,b){return{type:"attribute",nullable:!1,hash:void 0,nc:a,p:b,p1:void 0,p2:void 0,textDeriv:void 0,startTagOpenDeriv:void 0,attDeriv:function(c,
-d){return a.contains(d)&&(b.nullable&&/^\s+$/.test(d.nodeValue)||b.textDeriv(c,d.nodeValue).nullable)?B:y},startTagCloseDeriv:function(){return y},endTagDeriv:void 0}});t=l("value",function(a){return{type:"value",nullable:!1,value:a,textDeriv:function(b,c){return c===a?B:y},attDeriv:function(){return y},startTagCloseDeriv:function(){return this}}});x=l("data",function(a){return{type:"data",nullable:!1,dataType:a,textDeriv:function(){return B},attDeriv:function(){return y},startTagCloseDeriv:function(){return this}}});
-u=function W(a,b){return"after"===b.type?q(b.p1,a(b.p2)):"choice"===b.type?e(W(a,b.p1),W(a,b.p2)):b};s=function(a,b,c){var f=c.currentNode;b=b.startTagOpenDeriv(f);b=d(a,b,f.attributes,0);var h=b=b.startTagCloseDeriv(),f=c.currentNode;b=c.firstChild();for(var g=[],k;b;)b.nodeType===Node.ELEMENT_NODE?g.push(b):b.nodeType!==Node.TEXT_NODE||/^\s*$/.test(b.nodeValue)||g.push(b.nodeValue),b=c.nextSibling();0===g.length&&(g=[""]);k=h;for(h=0;k!==y&&h<g.length;h+=1)b=g[h],"string"===typeof b?k=/^\s*$/.test(b)?
-e(k,k.textDeriv(a,b)):k.textDeriv(a,b):(c.currentNode=b,k=s(a,k,c));c.currentNode=f;return b=k.endTagDeriv()};w=function(a){var b,c,d;if("name"===a.name)b=a.text,c=a.a.ns,a={name:b,ns:c,hash:"{"+c+"}"+b,contains:function(a){return a.namespaceURI===c&&a.localName===b}};else if("choice"===a.name){b=[];c=[];m(b,c,a);a="";for(d=0;d<b.length;d+=1)a+="{"+c[d]+"}"+b[d]+",";a={hash:a,contains:function(a){var d;for(d=0;d<b.length;d+=1)if(b[d]===a.localName&&c[d]===a.namespaceURI)return!0;return!1}}}else a=
-{hash:"anyName",contains:function(){return!0}};return a};v=function Q(c,d){var f,g;if("elementref"===c.name){f=c.id||0;c=d[f];if(void 0!==c.name){var m=c;f=d[m.id]={hash:"element"+m.id.toString()};m=n(w(m.e[0]),v(m.e[1],d));for(g in m)m.hasOwnProperty(g)&&(f[g]=m[g]);return f}return c}switch(c.name){case "empty":return B;case "notAllowed":return y;case "text":return L;case "choice":return e(Q(c.e[0],d),Q(c.e[1],d));case "interleave":f=Q(c.e[0],d);for(g=1;g<c.e.length;g+=1)f=a(f,Q(c.e[g],d));return f;
-case "group":return b(Q(c.e[0],d),Q(c.e[1],d));case "oneOrMore":return k(Q(c.e[0],d));case "attribute":return A(w(c.e[0]),Q(c.e[1],d));case "value":return t(c.text);case "data":return f=c.a&&c.a.type,void 0===f&&(f=""),x(f);case "list":return h()}throw"No support for "+c.name;};this.makePattern=function(a,b){var c={},d;for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);return d=v(a,c)};this.validate=function(a,b){var c;a.currentNode=a.root;c=s(null,H,a);c.nullable?b(null):(runtime.log("Error in Relax NG validation: "+
-c),b(["Error in Relax NG validation: "+c]))};this.init=function(a){H=a}};
-// Input 53
-runtime.loadClass("xmldom.RelaxNGParser");
-xmldom.RelaxNG2=function(){function g(f,d){this.message=function(){d&&(f+=d.nodeType===Node.ELEMENT_NODE?" Element ":" Node ",f+=d.nodeName,d.nodeValue&&(f+=" with value '"+d.nodeValue+"'"),f+=".");return f}}function l(f,d,g,c){return"empty"===f.name?null:r(f,d,g,c)}function f(f,d){if(2!==f.e.length)throw"Element with wrong # of elements: "+f.e.length;for(var m=d.currentNode,c=m?m.nodeType:0,e=null;c>Node.ELEMENT_NODE;){if(c!==Node.COMMENT_NODE&&(c!==Node.TEXT_NODE||!/^\s+$/.test(d.currentNode.nodeValue)))return[new g("Not allowed node of type "+
-c+".")];c=(m=d.nextSibling())?m.nodeType:0}if(!m)return[new g("Missing element "+f.names)];if(f.names&&-1===f.names.indexOf(n[m.namespaceURI]+":"+m.localName))return[new g("Found "+m.nodeName+" instead of "+f.names+".",m)];if(d.firstChild()){for(e=l(f.e[1],d,m);d.nextSibling();)if(c=d.currentNode.nodeType,!(d.currentNode&&d.currentNode.nodeType===Node.TEXT_NODE&&/^\s+$/.test(d.currentNode.nodeValue)||c===Node.COMMENT_NODE))return[new g("Spurious content.",d.currentNode)];if(d.parentNode()!==m)return[new g("Implementation error.")]}else e=
-l(f.e[1],d,m);d.nextSibling();return e}var p,r,n;r=function(h,d,m,c){var e=h.name,a=null;if("text"===e)a:{for(var b=(h=d.currentNode)?h.nodeType:0;h!==m&&3!==b;){if(1===b){a=[new g("Element not allowed here.",h)];break a}b=(h=d.nextSibling())?h.nodeType:0}d.nextSibling();a=null}else if("data"===e)a=null;else if("value"===e)c!==h.text&&(a=[new g("Wrong value, should be '"+h.text+"', not '"+c+"'",m)]);else if("list"===e)a=null;else if("attribute"===e)a:{if(2!==h.e.length)throw"Attribute with wrong # of elements: "+
-h.e.length;e=h.localnames.length;for(a=0;a<e;a+=1){c=m.getAttributeNS(h.namespaces[a],h.localnames[a]);""!==c||m.hasAttributeNS(h.namespaces[a],h.localnames[a])||(c=void 0);if(void 0!==b&&void 0!==c){a=[new g("Attribute defined too often.",m)];break a}b=c}a=void 0===b?[new g("Attribute not found: "+h.names,m)]:l(h.e[1],d,m,b)}else if("element"===e)a=f(h,d);else if("oneOrMore"===e){c=0;do b=d.currentNode,e=r(h.e[0],d,m),c+=1;while(!e&&b!==d.currentNode);1<c?(d.currentNode=b,a=null):a=e}else if("choice"===
-e){if(2!==h.e.length)throw"Choice with wrong # of options: "+h.e.length;b=d.currentNode;if("empty"===h.e[0].name){if(e=r(h.e[1],d,m,c))d.currentNode=b;a=null}else{if(e=l(h.e[0],d,m,c))d.currentNode=b,e=r(h.e[1],d,m,c);a=e}}else if("group"===e){if(2!==h.e.length)throw"Group with wrong # of members: "+h.e.length;a=r(h.e[0],d,m)||r(h.e[1],d,m)}else if("interleave"===e)a:{b=h.e.length;c=[b];for(var q=b,k,n,p,w;0<q;){k=0;n=d.currentNode;for(a=0;a<b;a+=1)p=d.currentNode,!0!==c[a]&&c[a]!==p&&(w=h.e[a],(e=
-r(w,d,m))?(d.currentNode=p,void 0===c[a]&&(c[a]=!1)):p===d.currentNode||"oneOrMore"===w.name||"choice"===w.name&&("oneOrMore"===w.e[0].name||"oneOrMore"===w.e[1].name)?(k+=1,c[a]=p):(k+=1,c[a]=!0));if(n===d.currentNode&&k===q){a=null;break a}if(0===k){for(a=0;a<b;a+=1)if(!1===c[a]){a=[new g("Interleave does not match.",m)];break a}a=null;break a}for(a=q=0;a<b;a+=1)!0!==c[a]&&(q+=1)}a=null}else throw e+" not allowed in nonEmptyPattern.";return a};this.validate=function(f,d){f.currentNode=f.root;var g=
-l(p.e[0],f,f.root);d(g)};this.init=function(f,d){p=f;n=d}};
-// Input 54
-runtime.loadClass("core.DomUtils");runtime.loadClass("gui.Avatar");runtime.loadClass("ops.OdtCursor");
-gui.Caret=function(g,l,f){function p(c){e&&m.parentNode&&(!a||c)&&(c&&void 0!==b&&runtime.clearTimeout(b),a=!0,h.style.opacity=c||"0"===h.style.opacity?"1":"0",b=runtime.setTimeout(function(){a=!1;p(!1)},500))}function r(a,b){var c=a.getBoundingClientRect(),d=0,e=0;c&&b&&(d=Math.max(c.top,b.top),e=Math.min(c.bottom,b.bottom));return e-d}function n(){var a;a=g.getSelectedRange().cloneRange();var b=g.getNode(),d,e=null;b.previousSibling&&(d=b.previousSibling.nodeType===Node.TEXT_NODE?b.previousSibling.textContent.length:
-b.previousSibling.childNodes.length,a.setStart(b.previousSibling,0<d?d-1:0),a.setEnd(b.previousSibling,d),(d=a.getBoundingClientRect())&&d.height&&(e=d));b.nextSibling&&(a.setStart(b.nextSibling,0),a.setEnd(b.nextSibling,0<(b.nextSibling.nodeType===Node.TEXT_NODE?b.nextSibling.textContent.length:b.nextSibling.childNodes.length)?1:0),(d=a.getBoundingClientRect())&&d.height&&(!e||r(b,d)>r(b,e))&&(e=d));a=e;b=g.getOdtDocument().getOdfCanvas().getZoomLevel();c&&g.getSelectionType()===ops.OdtCursor.RangeSelection?
-h.style.visibility="visible":h.style.visibility="hidden";a?(h.style.top="0",e=q.getBoundingClientRect(h),8>a.height&&(a={top:a.top-(8-a.height)/2,height:8}),h.style.height=q.adaptRangeDifferenceToZoomLevel(a.height,b)+"px",h.style.top=q.adaptRangeDifferenceToZoomLevel(a.top-e.top,b)+"px"):(h.style.height="1em",h.style.top="5%")}var h,d,m,c=!0,e=!1,a=!1,b,q=new core.DomUtils;this.handleUpdate=n;this.refreshCursorBlinking=function(){f||g.getSelectedRange().collapsed?(e=!0,p(!0)):(e=!1,h.style.opacity=
-"0")};this.setFocus=function(){e=!0;d.markAsFocussed(!0);p(!0)};this.removeFocus=function(){e=!1;d.markAsFocussed(!1);h.style.opacity="1"};this.show=function(){c=!0;n();d.markAsFocussed(!0)};this.hide=function(){c=!1;n();d.markAsFocussed(!1)};this.setAvatarImageUrl=function(a){d.setImageUrl(a)};this.setColor=function(a){h.style.borderColor=a;d.setColor(a)};this.getCursor=function(){return g};this.getFocusElement=function(){return h};this.toggleHandleVisibility=function(){d.isVisible()?d.hide():d.show()};
-this.showHandle=function(){d.show()};this.hideHandle=function(){d.hide()};this.ensureVisible=function(){var a,b,c,d,e=g.getOdtDocument().getOdfCanvas().getElement().parentNode,f;c=e.offsetWidth-e.clientWidth+5;d=e.offsetHeight-e.clientHeight+5;f=h.getBoundingClientRect();a=f.left-c;b=f.top-d;c=f.right+c;d=f.bottom+d;f=e.getBoundingClientRect();b<f.top?e.scrollTop-=f.top-b:d>f.bottom&&(e.scrollTop+=d-f.bottom);a<f.left?e.scrollLeft-=f.left-a:c>f.right&&(e.scrollLeft+=c-f.right);n()};this.destroy=function(a){d.destroy(function(b){b?
-a(b):(m.removeChild(h),a())})};(function(){var a=g.getOdtDocument().getDOM();h=a.createElementNS(a.documentElement.namespaceURI,"span");h.style.top="5%";m=g.getNode();m.appendChild(h);d=new gui.Avatar(m,l);n()})()};
-// Input 55
-gui.EventManager=function(g){function l(){return g.getOdfCanvas().getElement()}function f(){var c=this,a=[];this.handlers=[];this.isSubscribed=!1;this.handleEvent=function(b){-1===a.indexOf(b)&&(a.push(b),c.handlers.forEach(function(a){a(b)}),runtime.setTimeout(function(){a.splice(a.indexOf(b),1)},0))}}function p(c){var a=c.scrollX,b=c.scrollY;this.restore=function(){c.scrollX===a&&c.scrollY===b||c.scrollTo(a,b)}}function r(c){var a=c.scrollTop,b=c.scrollLeft;this.restore=function(){if(c.scrollTop!==
-a||c.scrollLeft!==b)c.scrollTop=a,c.scrollLeft=b}}function n(c,a,b){var f="on"+a,h=!1;c.attachEvent&&(h=c.attachEvent(f,b));!h&&c.addEventListener&&(c.addEventListener(a,b,!1),h=!0);h&&!d[a]||!c.hasOwnProperty(f)||(c[f]=b)}var h=runtime.getWindow(),d={beforecut:!0,beforepaste:!0},m,c;this.subscribe=function(d,a){var b=m[d],f=l();b?(b.handlers.push(a),b.isSubscribed||(b.isSubscribed=!0,n(h,d,b.handleEvent),n(f,d,b.handleEvent),n(c,d,b.handleEvent))):n(f,d,a)};this.unsubscribe=function(c,a){var b=m[c],
-d=b&&b.handlers.indexOf(a),f=l();b?-1!==d&&b.handlers.splice(d,1):(b="on"+c,f.detachEvent&&f.detachEvent(b,a),f.removeEventListener&&f.removeEventListener(c,a,!1),f[b]===a&&(f[b]=null))};this.focus=function(){var d,a=l(),b=h.getSelection();if(g.getDOM().activeElement!==l()){for(d=a;d&&!d.scrollTop&&!d.scrollLeft;)d=d.parentNode;d=d?new r(d):new p(h);a.focus();d&&d.restore()}b&&b.extend&&(c.parentNode!==a&&a.appendChild(c),b.collapse(c.firstChild,0),b.extend(c,c.childNodes.length))};(function(){var d=
-l(),a=d.ownerDocument;runtime.assert(Boolean(h),"EventManager requires a window object to operate correctly");m={mousedown:new f,mouseup:new f,focus:new f};c=a.createElement("div");c.id="eventTrap";c.setAttribute("contenteditable","true");c.style.position="absolute";c.style.left="-10000px";c.appendChild(a.createTextNode("dummy content"));d.appendChild(c)})()};
-// Input 56
-runtime.loadClass("gui.SelectionMover");gui.ShadowCursor=function(g){var l=g.getDOM().createRange(),f=!0;this.removeFromOdtDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return l};this.setSelectedRange=function(g,r){l=g;f=!1!==r};this.hasForwardSelection=function(){return f};this.getOdtDocument=function(){return g};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};l.setStart(g.getRootNode(),0)};
-gui.ShadowCursor.ShadowCursorMemberId="";(function(){return gui.ShadowCursor})();
-// Input 57
+odf.TextStyleApplicator=function(k,h,b){function p(b){function d(a,c){return"object"===typeof a&&"object"===typeof c?Object.keys(a).every(function(b){return d(a[b],c[b])}):a===c}var c={};this.isStyleApplied=function(a){a=h.getAppliedStylesForElement(a,c);return d(b,a)}}function d(d){var f={};this.applyStyleToContainer=function(c){var a;a=c.getAttributeNS(q,"style-name");var g=c.ownerDocument;a=a||"";if(!f.hasOwnProperty(a)){var e=a,n;n=a?h.createDerivedStyleObject(a,"text",d):d;g=g.createElementNS(r,
+"style:style");h.updateStyle(g,n);g.setAttributeNS(r,"style:name",k.generateStyleName());g.setAttributeNS(r,"style:family","text");g.setAttributeNS("urn:webodf:names:scope","scope","document-content");b.appendChild(g);f[e]=g}a=f[a].getAttributeNS(r,"name");c.setAttributeNS(q,"text:style-name",a)}}function n(b,d){var c=b.ownerDocument,a=b.parentNode,m,e,h=new core.LoopWatchDog(1E4);e=[];"span"!==a.localName||a.namespaceURI!==q?(m=c.createElementNS(q,"text:span"),a.insertBefore(m,b),a=!1):(b.previousSibling&&
+!g.rangeContainsNode(d,a.firstChild)?(m=a.cloneNode(!1),a.parentNode.insertBefore(m,a.nextSibling)):m=a,a=!0);e.push(b);for(c=b.nextSibling;c&&g.rangeContainsNode(d,c);)h.check(),e.push(c),c=c.nextSibling;e.forEach(function(a){a.parentNode!==m&&m.appendChild(a)});if(c&&a)for(e=m.cloneNode(!1),m.parentNode.insertBefore(e,m.nextSibling);c;)h.check(),a=c.nextSibling,e.appendChild(c),c=a;return m}var g=new core.DomUtils,q=odf.Namespaces.textns,r=odf.Namespaces.stylens;this.applyStyle=function(b,f,c){var a=
+{},g,e,h,k;runtime.assert(c&&c.hasOwnProperty("style:text-properties"),"applyStyle without any text properties");a["style:text-properties"]=c["style:text-properties"];h=new d(a);k=new p(a);b.forEach(function(a){g=k.isStyleApplied(a);!1===g&&(e=n(a,f),h.applyStyleToContainer(e))})}};
+// Input 51
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -1482,12 +1553,13 @@ gui.ShadowCursor.ShadowCursorMemberId="";(function(){return gui.ShadowCursor})()
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-gui.UndoManager=function(){};gui.UndoManager.prototype.subscribe=function(g,l){};gui.UndoManager.prototype.unsubscribe=function(g,l){};gui.UndoManager.prototype.setOdtDocument=function(g){};gui.UndoManager.prototype.saveInitialState=function(){};gui.UndoManager.prototype.resetInitialState=function(){};gui.UndoManager.prototype.setPlaybackFunction=function(g){};gui.UndoManager.prototype.hasUndoStates=function(){};gui.UndoManager.prototype.hasRedoStates=function(){};
-gui.UndoManager.prototype.moveForward=function(g){};gui.UndoManager.prototype.moveBackward=function(g){};gui.UndoManager.prototype.onOperationExecuted=function(g){};gui.UndoManager.signalUndoStackChanged="undoStackChanged";gui.UndoManager.signalUndoStateCreated="undoStateCreated";gui.UndoManager.signalUndoStateModified="undoStateModified";(function(){return gui.UndoManager})();
-// Input 58
+ops.OpApplyDirectStyling=function(){function k(b,d,f){var c=b.getOdfCanvas().odfContainer(),a=q.splitBoundaries(d),m=g.getTextNodes(d,!1);d={startContainer:d.startContainer,startOffset:d.startOffset,endContainer:d.endContainer,endOffset:d.endOffset};(new odf.TextStyleApplicator(new odf.ObjectNameGenerator(c,h),b.getFormatting(),c.rootElement.automaticStyles)).applyStyle(m,d,f);a.forEach(q.normalizeTextNodes)}var h,b,p,d,n,g=new odf.OdfUtils,q=new core.DomUtils;this.init=function(g){h=g.memberid;b=
+g.timestamp;p=parseInt(g.position,10);d=parseInt(g.length,10);n=g.setProperties};this.isEdit=!0;this.group=void 0;this.execute=function(q){var l=q.convertCursorToDomRange(p,d),f=g.getParagraphElements(l);k(q,l,n);l.detach();q.getOdfCanvas().refreshCSS();q.fixCursorPositions();f.forEach(function(c){q.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:c,memberId:h,timeStamp:b})});q.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"ApplyDirectStyling",memberid:h,
+timestamp:b,position:p,length:d,setProperties:n}}};
+// Input 52
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -1522,12 +1594,13 @@ gui.UndoManager.prototype.moveForward=function(g){};gui.UndoManager.prototype.mo
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-gui.UndoStateRules=function(){function g(f){return f.spec().optype}function l(f){return f.isEdit}this.getOpType=g;this.isEditOperation=l;this.isPartOfOperationSet=function(f,p){if(f.isEdit){if(0===p.length)return!0;var r;if(r=p[p.length-1].isEdit)a:{r=p.filter(l);var n=g(f),h;b:switch(n){case "RemoveText":case "InsertText":h=!0;break b;default:h=!1}if(h&&n===g(r[0])){if(1===r.length){r=!0;break a}n=r[r.length-2].spec().position;r=r[r.length-1].spec().position;h=f.spec().position;if(r===h-(r-n)){r=
-!0;break a}}r=!1}return r}return!0}};
-// Input 59
+ops.OpApplyHyperlink=function(){function k(b){for(;b;){if(q.isHyperlink(b))return!0;b=b.parentNode}return!1}var h,b,p,d,n,g=new core.DomUtils,q=new odf.OdfUtils;this.init=function(g){h=g.memberid;b=g.timestamp;p=g.position;d=g.length;n=g.hyperlink};this.isEdit=!0;this.group=void 0;this.execute=function(r){var l=r.getDOMDocument(),f=r.convertCursorToDomRange(p,d),c=g.splitBoundaries(f),a=[],m=q.getTextNodes(f,!1);if(0===m.length)return!1;m.forEach(function(c){var b=q.getParagraphElement(c);runtime.assert(!1===
+k(c),"The given range should not contain any link.");var d=n,f=l.createElementNS(odf.Namespaces.textns,"text:a");f.setAttributeNS(odf.Namespaces.xlinkns,"xlink:type","simple");f.setAttributeNS(odf.Namespaces.xlinkns,"xlink:href",d);c.parentNode.insertBefore(f,c);f.appendChild(c);-1===a.indexOf(b)&&a.push(b)});c.forEach(g.normalizeTextNodes);f.detach();r.getOdfCanvas().refreshSize();r.getOdfCanvas().rerenderAnnotations();a.forEach(function(a){r.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:a,
+memberId:h,timeStamp:b})});return!0};this.spec=function(){return{optype:"ApplyHyperlink",memberid:h,timestamp:b,position:p,length:d,hyperlink:n}}};
+// Input 53
/*
- Copyright (C) 2012 KO GmbH <aditya.bhatt@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -1562,12 +1635,13 @@ gui.UndoStateRules=function(){function g(f){return f.spec().optype}function l(f)
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.EditInfo=function(g,l){function f(){var f=[],h;for(h in r)r.hasOwnProperty(h)&&f.push({memberid:h,time:r[h].time});f.sort(function(d,f){return d.time-f.time});return f}var p,r={};this.getNode=function(){return p};this.getOdtDocument=function(){return l};this.getEdits=function(){return r};this.getSortedEdits=function(){return f()};this.addEdit=function(f,h){r[f]={time:h}};this.clearEdits=function(){r={}};this.destroy=function(f){g.parentNode&&g.removeChild(p);f()};p=l.getDOM().createElementNS("urn:webodf:names:editinfo",
-"editinfo");g.insertBefore(p,g.firstChild)};
-// Input 60
+ops.OpInsertImage=function(){var k,h,b,p,d,n,g,q,r=odf.Namespaces.drawns,l=odf.Namespaces.svgns,f=odf.Namespaces.textns,c=odf.Namespaces.xlinkns;this.init=function(a){k=a.memberid;h=a.timestamp;b=a.position;p=a.filename;d=a.frameWidth;n=a.frameHeight;g=a.frameStyleName;q=a.frameName};this.isEdit=!0;this.group=void 0;this.execute=function(a){var m=a.getOdfCanvas(),e=a.getTextNodeAtStep(b,k),t,w;if(!e)return!1;t=e.textNode;w=a.getParagraphElement(t);var e=e.offset!==t.length?t.splitText(e.offset):t.nextSibling,
+z=a.getDOMDocument(),x=z.createElementNS(r,"draw:image"),z=z.createElementNS(r,"draw:frame");x.setAttributeNS(c,"xlink:href",p);x.setAttributeNS(c,"xlink:type","simple");x.setAttributeNS(c,"xlink:show","embed");x.setAttributeNS(c,"xlink:actuate","onLoad");z.setAttributeNS(r,"draw:style-name",g);z.setAttributeNS(r,"draw:name",q);z.setAttributeNS(f,"text:anchor-type","as-char");z.setAttributeNS(l,"svg:width",d);z.setAttributeNS(l,"svg:height",n);z.appendChild(x);t.parentNode.insertBefore(z,e);a.emit(ops.OdtDocument.signalStepsInserted,
+{position:b,length:1});0===t.length&&t.parentNode.removeChild(t);m.addCssForFrameWithImage(z);m.refreshCSS();a.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:w,memberId:k,timeStamp:h});m.rerenderAnnotations();return!0};this.spec=function(){return{optype:"InsertImage",memberid:k,timestamp:h,filename:p,position:b,frameWidth:d,frameHeight:n,frameStyleName:g,frameName:q}}};
+// Input 54
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -1602,12 +1676,12 @@ ops.EditInfo=function(g,l){function f(){var f=[],h;for(h in r)r.hasOwnProperty(h
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");
-ops.OpAddAnnotation=function(){function g(d,f,c){var e=d.getTextNodeAtStep(c,l);e&&(d=e.textNode,c=d.parentNode,e.offset!==d.length&&d.splitText(e.offset),c.insertBefore(f,d.nextSibling),0===d.length&&c.removeChild(d))}var l,f,p,r,n,h;this.init=function(d){l=d.memberid;f=parseInt(d.timestamp,10);p=parseInt(d.position,10);r=parseInt(d.length,10)||0;n=d.name};this.isEdit=!0;this.execute=function(d){var m={},c=d.getCursor(l),e,a;a=new core.DomUtils;h=d.getDOM();var b=new Date(f),q,k,t,A;e=h.createElementNS(odf.Namespaces.officens,
-"office:annotation");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);q=h.createElementNS(odf.Namespaces.dcns,"dc:creator");q.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l);q.textContent=d.getMember(l).getProperties().fullName;k=h.createElementNS(odf.Namespaces.dcns,"dc:date");k.appendChild(h.createTextNode(b.toISOString()));b=h.createElementNS(odf.Namespaces.textns,"text:list");t=h.createElementNS(odf.Namespaces.textns,"text:list-item");A=h.createElementNS(odf.Namespaces.textns,
-"text:p");t.appendChild(A);b.appendChild(t);e.appendChild(q);e.appendChild(k);e.appendChild(b);m.node=e;if(!m.node)return!1;if(r){e=h.createElementNS(odf.Namespaces.officens,"office:annotation-end");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);m.end=e;if(!m.end)return!1;g(d,m.end,p+r)}g(d,m.node,p);d.emit(ops.OdtDocument.signalStepsInserted,{position:p,length:r});c&&(e=h.createRange(),a=a.getElementsByTagNameNS(m.node,odf.Namespaces.textns,"p")[0],e.selectNodeContents(a),c.setSelectedRange(e),
-d.emit(ops.OdtDocument.signalCursorMoved,c));d.getOdfCanvas().addAnnotation(m);d.fixCursorPositions();return!0};this.spec=function(){return{optype:"AddAnnotation",memberid:l,timestamp:f,position:p,length:r,name:n}}};
-// Input 61
+ops.OpInsertTable=function(){function k(b,c){var a;if(1===l.length)a=l[0];else if(3===l.length)switch(b){case 0:a=l[0];break;case p-1:a=l[2];break;default:a=l[1]}else a=l[b];if(1===a.length)return a[0];if(3===a.length)switch(c){case 0:return a[0];case d-1:return a[2];default:return a[1]}return a[c]}var h,b,p,d,n,g,q,r,l;this.init=function(f){h=f.memberid;b=f.timestamp;n=f.position;p=f.initialRows;d=f.initialColumns;g=f.tableName;q=f.tableStyleName;r=f.tableColumnStyleName;l=f.tableCellStyleMatrix};
+this.isEdit=!0;this.group=void 0;this.execute=function(f){var c=f.getTextNodeAtStep(n),a=f.getRootNode();if(c){var m=f.getDOMDocument(),e=m.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table"),l=m.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-column"),w,z,x,v;q&&e.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",q);g&&e.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:name",g);l.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0",
+"table:number-columns-repeated",d);r&&l.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",r);e.appendChild(l);for(x=0;x<p;x+=1){l=m.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-row");for(v=0;v<d;v+=1)w=m.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-cell"),(z=k(x,v))&&w.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",z),z=m.createElementNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0",
+"text:p"),w.appendChild(z),l.appendChild(w);e.appendChild(l)}c=f.getParagraphElement(c.textNode);a.insertBefore(e,c.nextSibling);f.emit(ops.OdtDocument.signalStepsInserted,{position:n,length:d*p+1});f.getOdfCanvas().refreshSize();f.emit(ops.OdtDocument.signalTableAdded,{tableElement:e,memberId:h,timeStamp:b});f.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertTable",memberid:h,timestamp:b,position:n,initialRows:p,initialColumns:d,tableName:g,tableStyleName:q,
+tableColumnStyleName:r,tableCellStyleMatrix:l}}};
+// Input 55
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1645,34 +1719,50 @@ d.emit(ops.OdtDocument.signalCursorMoved,c));d.getOdfCanvas().addAnnotation(m);d
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpAddCursor=function(){var g,l;this.init=function(f){g=f.memberid;l=f.timestamp};this.isEdit=!1;this.execute=function(f){var l=f.getCursor(g);if(l)return!1;l=new ops.OdtCursor(g,f);f.addCursor(l);f.emit(ops.OdtDocument.signalCursorAdded,l);return!0};this.spec=function(){return{optype:"AddCursor",memberid:g,timestamp:l}}};
-// Input 62
+ops.OpInsertText=function(){var k,h,b,p,d;this.init=function(n){k=n.memberid;h=n.timestamp;b=n.position;d=n.text;p="true"===n.moveCursor||!0===n.moveCursor};this.isEdit=!0;this.group=void 0;this.execute=function(n){var g,q,r,l=null,f=n.getDOMDocument(),c,a=0,m,e=n.getCursor(k),t;n.upgradeWhitespacesAtPosition(b);if(g=n.getTextNodeAtStep(b)){q=g.textNode;l=q.nextSibling;r=q.parentNode;c=n.getParagraphElement(q);for(t=0;t<d.length;t+=1)if(" "===d[t]&&(0===t||t===d.length-1||" "===d[t-1])||"\t"===d[t])0===
+a?(g.offset!==q.length&&(l=q.splitText(g.offset)),0<t&&q.appendData(d.substring(0,t))):a<t&&(a=d.substring(a,t),r.insertBefore(f.createTextNode(a),l)),a=t+1,m=" "===d[t]?"text:s":"text:tab",m=f.createElementNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0",m),m.appendChild(f.createTextNode(d[t])),r.insertBefore(m,l);0===a?q.insertData(g.offset,d):a<d.length&&(g=d.substring(a),r.insertBefore(f.createTextNode(g),l));r=q.parentNode;l=q.nextSibling;r.removeChild(q);r.insertBefore(q,l);0===q.length&&
+q.parentNode.removeChild(q);n.emit(ops.OdtDocument.signalStepsInserted,{position:b,length:d.length});e&&p&&(n.moveCursor(k,b+d.length,0),n.emit(ops.Document.signalCursorMoved,e));0<b&&(1<b&&n.downgradeWhitespacesAtPosition(b-2),n.downgradeWhitespacesAtPosition(b-1));n.downgradeWhitespacesAtPosition(b);n.downgradeWhitespacesAtPosition(b+d.length-1);n.downgradeWhitespacesAtPosition(b+d.length);n.getOdfCanvas().refreshSize();n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:c,memberId:k,
+timeStamp:h});n.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertText",memberid:k,timestamp:h,position:b,text:d,moveCursor:p}}};
+// Input 56
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
- This file is part of WebODF.
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+ This license applies to this entire compilation.
+ @licend
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.Member");ops.OpAddMember=function(){var g,l,f;this.init=function(p){g=p.memberid;l=parseInt(p.timestamp,10);f=p.setProperties};this.isEdit=!1;this.execute=function(l){if(l.getMember(g))return!1;var r=new ops.Member(g,f);l.addMember(r);l.emit(ops.OdtDocument.signalMemberAdded,r);return!0};this.spec=function(){return{optype:"AddMember",memberid:g,timestamp:l,setProperties:f}}};
-// Input 63
+ops.OpMoveCursor=function(){var k,h,b,p,d;this.init=function(n){k=n.memberid;h=n.timestamp;b=n.position;p=n.length||0;d=n.selectionType||ops.OdtCursor.RangeSelection};this.isEdit=!1;this.group=void 0;this.execute=function(h){var g=h.getCursor(k),q;if(!g)return!1;q=h.convertCursorToDomRange(b,p);g.setSelectedRange(q,0<=p);g.setSelectionType(d);h.emit(ops.Document.signalCursorMoved,g);return!0};this.spec=function(){return{optype:"MoveCursor",memberid:k,timestamp:h,position:b,length:p,selectionType:d}}};
+// Input 57
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1710,10 +1800,9 @@ runtime.loadClass("ops.Member");ops.OpAddMember=function(){var g,l,f;this.init=f
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");
-ops.OpAddStyle=function(){var g,l,f,p,r,n,h=odf.Namespaces.stylens;this.init=function(d){g=d.memberid;l=d.timestamp;f=d.styleName;p=d.styleFamily;r="true"===d.isAutomaticStyle||!0===d.isAutomaticStyle;n=d.setProperties};this.isEdit=!0;this.execute=function(d){var g=d.getOdfCanvas().odfContainer(),c=d.getFormatting(),e=d.getDOM().createElementNS(h,"style:style");if(!e)return!1;n&&c.updateStyle(e,n);e.setAttributeNS(h,"style:family",p);e.setAttributeNS(h,"style:name",f);r?g.rootElement.automaticStyles.appendChild(e):
-g.rootElement.styles.appendChild(e);d.getOdfCanvas().refreshCSS();r||d.emit(ops.OdtDocument.signalCommonStyleCreated,{name:f,family:p});return!0};this.spec=function(){return{optype:"AddStyle",memberid:g,timestamp:l,styleName:f,styleFamily:p,isAutomaticStyle:r,setProperties:n}}};
-// Input 64
+ops.OpRemoveAnnotation=function(){var k,h,b,p,d;this.init=function(n){k=n.memberid;h=n.timestamp;b=parseInt(n.position,10);p=parseInt(n.length,10);d=new core.DomUtils};this.isEdit=!0;this.group=void 0;this.execute=function(h){function g(b){r.parentNode.insertBefore(b,r)}for(var k=h.getIteratorAtPosition(b).container(),r;k.namespaceURI!==odf.Namespaces.officens||"annotation"!==k.localName;)k=k.parentNode;if(null===k)return!1;r=k;k=r.annotationEndElement;h.getOdfCanvas().forgetAnnotations();d.getElementsByTagNameNS(r,
+"urn:webodf:names:cursor","cursor").forEach(g);d.getElementsByTagNameNS(r,"urn:webodf:names:cursor","anchor").forEach(g);r.parentNode.removeChild(r);k&&k.parentNode.removeChild(k);h.emit(ops.OdtDocument.signalStepsRemoved,{position:0<b?b-1:b,length:p});h.fixCursorPositions();h.getOdfCanvas().refreshAnnotations();return!0};this.spec=function(){return{optype:"RemoveAnnotation",memberid:k,timestamp:h,position:b,length:p}}};
+// Input 58
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1751,11 +1840,8 @@ g.rootElement.styles.appendChild(e);d.getOdfCanvas().refreshCSS();r||d.emit(ops.
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.TextStyleApplicator");
-ops.OpApplyDirectStyling=function(){function g(f,c,e){var a=f.getOdfCanvas().odfContainer(),b=d.splitBoundaries(c),g=h.getTextNodes(c,!1);c={startContainer:c.startContainer,startOffset:c.startOffset,endContainer:c.endContainer,endOffset:c.endOffset};(new odf.TextStyleApplicator(new odf.ObjectNameGenerator(a,l),f.getFormatting(),a.rootElement.automaticStyles)).applyStyle(g,c,e);b.forEach(d.normalizeTextNodes)}var l,f,p,r,n,h=new odf.OdfUtils,d=new core.DomUtils;this.init=function(d){l=d.memberid;f=
-d.timestamp;p=parseInt(d.position,10);r=parseInt(d.length,10);n=d.setProperties};this.isEdit=!0;this.execute=function(d){var c=d.convertCursorToDomRange(p,r),e=h.getImpactedParagraphs(c);g(d,c,n);c.detach();d.getOdfCanvas().refreshCSS();d.fixCursorPositions();e.forEach(function(a){d.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:a,memberId:l,timeStamp:f})});d.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"ApplyDirectStyling",memberid:l,timestamp:f,
-position:p,length:r,setProperties:n}}};
-// Input 65
+ops.OpRemoveBlob=function(){var k,h,b;this.init=function(p){k=p.memberid;h=p.timestamp;b=p.filename};this.isEdit=!0;this.group=void 0;this.execute=function(h){h.getOdfCanvas().odfContainer().removeBlob(b);return!0};this.spec=function(){return{optype:"RemoveBlob",memberid:k,timestamp:h,filename:b}}};
+// Input 59
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1793,13 +1879,11 @@ position:p,length:r,setProperties:n}}};
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpInsertImage=function(){var g,l,f,p,r,n,h,d,m=odf.Namespaces.drawns,c=odf.Namespaces.svgns,e=odf.Namespaces.textns,a=odf.Namespaces.xlinkns;this.init=function(a){g=a.memberid;l=a.timestamp;f=a.position;p=a.filename;r=a.frameWidth;n=a.frameHeight;h=a.frameStyleName;d=a.frameName};this.isEdit=!0;this.execute=function(b){var q=b.getOdfCanvas(),k=b.getTextNodeAtStep(f,g),t,A;if(!k)return!1;t=k.textNode;A=b.getParagraphElement(t);var k=k.offset!==t.length?t.splitText(k.offset):t.nextSibling,w=b.getDOM(),
-x=w.createElementNS(m,"draw:image"),w=w.createElementNS(m,"draw:frame");x.setAttributeNS(a,"xlink:href",p);x.setAttributeNS(a,"xlink:type","simple");x.setAttributeNS(a,"xlink:show","embed");x.setAttributeNS(a,"xlink:actuate","onLoad");w.setAttributeNS(m,"draw:style-name",h);w.setAttributeNS(m,"draw:name",d);w.setAttributeNS(e,"text:anchor-type","as-char");w.setAttributeNS(c,"svg:width",r);w.setAttributeNS(c,"svg:height",n);w.appendChild(x);t.parentNode.insertBefore(w,k);b.emit(ops.OdtDocument.signalStepsInserted,
-{position:f,length:1});0===t.length&&t.parentNode.removeChild(t);q.addCssForFrameWithImage(w);q.refreshCSS();b.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:A,memberId:g,timeStamp:l});q.rerenderAnnotations();return!0};this.spec=function(){return{optype:"InsertImage",memberid:g,timestamp:l,filename:p,position:f,frameWidth:r,frameHeight:n,frameStyleName:h,frameName:d}}};
-// Input 66
+ops.OpRemoveCursor=function(){var k,h;this.init=function(b){k=b.memberid;h=b.timestamp};this.isEdit=!1;this.group=void 0;this.execute=function(b){return b.removeCursor(k)?!0:!1};this.spec=function(){return{optype:"RemoveCursor",memberid:k,timestamp:h}}};
+// Input 60
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -1834,12 +1918,35 @@ x=w.createElementNS(m,"draw:image"),w=w.createElementNS(m,"draw:frame");x.setAtt
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpInsertTable=function(){function g(d,a){var b;if(1===c.length)b=c[0];else if(3===c.length)switch(d){case 0:b=c[0];break;case p-1:b=c[2];break;default:b=c[1]}else b=c[d];if(1===b.length)return b[0];if(3===b.length)switch(a){case 0:return b[0];case r-1:return b[2];default:return b[1]}return b[a]}var l,f,p,r,n,h,d,m,c;this.init=function(e){l=e.memberid;f=e.timestamp;n=e.position;p=e.initialRows;r=e.initialColumns;h=e.tableName;d=e.tableStyleName;m=e.tableColumnStyleName;c=e.tableCellStyleMatrix};
-this.isEdit=!0;this.execute=function(c){var a=c.getTextNodeAtStep(n),b=c.getRootNode();if(a){var q=c.getDOM(),k=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table"),t=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-column"),A,w,x,v;d&&k.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",d);h&&k.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:name",h);t.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0",
-"table:number-columns-repeated",r);m&&t.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",m);k.appendChild(t);for(x=0;x<p;x+=1){t=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-row");for(v=0;v<r;v+=1)A=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-cell"),(w=g(x,v))&&A.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",w),w=q.createElementNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0",
-"text:p"),A.appendChild(w),t.appendChild(A);k.appendChild(t)}a=c.getParagraphElement(a.textNode);b.insertBefore(k,a.nextSibling);c.emit(ops.OdtDocument.signalStepsInserted,{position:n,length:r*p+1});c.getOdfCanvas().refreshSize();c.emit(ops.OdtDocument.signalTableAdded,{tableElement:k,memberId:l,timeStamp:f});c.getOdfCanvas().rerenderAnnotations();return!0}return!1};this.spec=function(){return{optype:"InsertTable",memberid:l,timestamp:f,position:n,initialRows:p,initialColumns:r,tableName:h,tableStyleName:d,
-tableColumnStyleName:m,tableCellStyleMatrix:c}}};
-// Input 67
+ops.OpRemoveHyperlink=function(){var k,h,b,p,d=new core.DomUtils,n=new odf.OdfUtils;this.init=function(d){k=d.memberid;h=d.timestamp;b=d.position;p=d.length};this.isEdit=!0;this.group=void 0;this.execute=function(g){var q=g.convertCursorToDomRange(b,p),r=n.getHyperlinkElements(q);runtime.assert(1===r.length,"The given range should only contain a single link.");r=d.mergeIntoParent(r[0]);q.detach();g.getOdfCanvas().refreshSize();g.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:n.getParagraphElement(r),
+memberId:k,timeStamp:h});g.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveHyperlink",memberid:k,timestamp:h,position:b,length:p}}};
+// Input 61
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OpRemoveMember=function(){var k,h;this.init=function(b){k=b.memberid;h=parseInt(b.timestamp,10)};this.isEdit=!1;this.group=void 0;this.execute=function(b){if(!b.getMember(k))return!1;b.removeMember(k);b.emit(ops.Document.signalMemberRemoved,k);return!0};this.spec=function(){return{optype:"RemoveMember",memberid:k,timestamp:h}}};
+// Input 62
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1877,11 +1984,8 @@ tableColumnStyleName:m,tableCellStyleMatrix:c}}};
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpInsertText=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.position;p=n.text;r="true"===n.moveCursor||!0===n.moveCursor};this.isEdit=!0;this.execute=function(n){var h,d,m,c=null,e=n.getDOM(),a,b=0,q,k=n.getCursor(g),t;n.upgradeWhitespacesAtPosition(f);if(h=n.getTextNodeAtStep(f)){d=h.textNode;c=d.nextSibling;m=d.parentNode;a=n.getParagraphElement(d);for(t=0;t<p.length;t+=1)if(" "===p[t]&&(0===t||t===p.length-1||" "===p[t-1])||"\t"===p[t])0===b?(h.offset!==d.length&&
-(c=d.splitText(h.offset)),0<t&&d.appendData(p.substring(0,t))):b<t&&(b=p.substring(b,t),m.insertBefore(e.createTextNode(b),c)),b=t+1,q=" "===p[t]?"text:s":"text:tab",q=e.createElementNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0",q),q.appendChild(e.createTextNode(p[t])),m.insertBefore(q,c);0===b?d.insertData(h.offset,p):b<p.length&&(h=p.substring(b),m.insertBefore(e.createTextNode(h),c));m=d.parentNode;c=d.nextSibling;m.removeChild(d);m.insertBefore(d,c);0===d.length&&d.parentNode.removeChild(d);
-n.emit(ops.OdtDocument.signalStepsInserted,{position:f,length:p.length});k&&r&&(n.moveCursor(g,f+p.length,0),n.emit(ops.OdtDocument.signalCursorMoved,k));0<f&&(1<f&&n.downgradeWhitespacesAtPosition(f-2),n.downgradeWhitespacesAtPosition(f-1));n.downgradeWhitespacesAtPosition(f);n.downgradeWhitespacesAtPosition(f+p.length-1);n.downgradeWhitespacesAtPosition(f+p.length);n.getOdfCanvas().refreshSize();n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:a,memberId:g,timeStamp:l});n.getOdfCanvas().rerenderAnnotations();
-return!0}return!1};this.spec=function(){return{optype:"InsertText",memberid:g,timestamp:l,position:f,text:p,moveCursor:r}}};
-// Input 68
+ops.OpRemoveStyle=function(){var k,h,b,p;this.init=function(d){k=d.memberid;h=d.timestamp;b=d.styleName;p=d.styleFamily};this.isEdit=!0;this.group=void 0;this.execute=function(d){var h=d.getStyleElement(b,p);if(!h)return!1;h.parentNode.removeChild(h);d.getOdfCanvas().refreshCSS();d.emit(ops.OdtDocument.signalCommonStyleDeleted,{name:b,family:p});return!0};this.spec=function(){return{optype:"RemoveStyle",memberid:k,timestamp:h,styleName:b,styleFamily:p}}};
+// Input 63
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1919,8 +2023,12 @@ return!0}return!1};this.spec=function(){return{optype:"InsertText",memberid:g,ti
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpMoveCursor=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.position;p=n.length||0;r=n.selectionType||ops.OdtCursor.RangeSelection};this.isEdit=!1;this.execute=function(l){var h=l.getCursor(g),d;if(!h)return!1;d=l.convertCursorToDomRange(f,p);h.setSelectedRange(d,0<=p);h.setSelectionType(r);l.emit(ops.OdtDocument.signalCursorMoved,h);return!0};this.spec=function(){return{optype:"MoveCursor",memberid:g,timestamp:l,position:f,length:p,selectionType:r}}};
-// Input 69
+ops.OpRemoveText=function(){function k(b){function d(a){return q.hasOwnProperty(a.namespaceURI)||"br"===a.localName&&n.isLineBreak(a.parentNode)||a.nodeType===Node.TEXT_NODE&&q.hasOwnProperty(a.parentNode.namespaceURI)}function f(a){if(n.isCharacterElement(a))return!1;if(a.nodeType===Node.TEXT_NODE)return 0===a.textContent.length;for(a=a.firstChild;a;){if(q.hasOwnProperty(a.namespaceURI)||!f(a))return!1;a=a.nextSibling}return!0}function c(a){var m;a.nodeType===Node.TEXT_NODE?(m=a.parentNode,m.removeChild(a)):
+m=g.removeUnwantedNodes(a,d);return m&&!n.isParagraph(m)&&m!==b&&f(m)?c(m):m}this.isEmpty=f;this.mergeChildrenIntoParent=c}var h,b,p,d,n,g,q={};this.init=function(k){runtime.assert(0<=k.length,"OpRemoveText only supports positive lengths");h=k.memberid;b=k.timestamp;p=parseInt(k.position,10);d=parseInt(k.length,10);n=new odf.OdfUtils;g=new core.DomUtils;q[odf.Namespaces.dbns]=!0;q[odf.Namespaces.dcns]=!0;q[odf.Namespaces.dr3dns]=!0;q[odf.Namespaces.drawns]=!0;q[odf.Namespaces.chartns]=!0;q[odf.Namespaces.formns]=
+!0;q[odf.Namespaces.numberns]=!0;q[odf.Namespaces.officens]=!0;q[odf.Namespaces.presentationns]=!0;q[odf.Namespaces.stylens]=!0;q[odf.Namespaces.svgns]=!0;q[odf.Namespaces.tablens]=!0;q[odf.Namespaces.textns]=!0};this.isEdit=!0;this.group=void 0;this.execute=function(q){var l,f,c,a,m=q.getCursor(h),e=new k(q.getRootNode());q.upgradeWhitespacesAtPosition(p);q.upgradeWhitespacesAtPosition(p+d);f=q.convertCursorToDomRange(p,d);g.splitBoundaries(f);l=q.getParagraphElement(f.startContainer);c=n.getTextElements(f,
+!1,!0);a=n.getParagraphElements(f);f.detach();c.forEach(function(a){e.mergeChildrenIntoParent(a)});f=a.reduce(function(a,c){var b,d=a,f=c,g,m=null;e.isEmpty(a)&&(c.parentNode!==a.parentNode&&(g=c.parentNode,a.parentNode.insertBefore(c,a.nextSibling)),f=a,d=c,m=d.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo").item(0)||d.firstChild);for(;f.firstChild;)b=f.firstChild,f.removeChild(b),"editinfo"!==b.localName&&d.insertBefore(b,m);g&&e.isEmpty(g)&&e.mergeChildrenIntoParent(g);e.mergeChildrenIntoParent(f);
+return d});q.emit(ops.OdtDocument.signalStepsRemoved,{position:p,length:d});q.downgradeWhitespacesAtPosition(p);q.fixCursorPositions();q.getOdfCanvas().refreshSize();q.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:f||l,memberId:h,timeStamp:b});m&&(m.resetSelectionType(),q.emit(ops.Document.signalCursorMoved,m));q.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveText",memberid:h,timestamp:b,position:p,length:d}}};
+// Input 64
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -1958,11 +2066,8 @@ ops.OpMoveCursor=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");runtime.loadClass("core.DomUtils");
-ops.OpRemoveAnnotation=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=parseInt(n.position,10);p=parseInt(n.length,10);r=new core.DomUtils};this.isEdit=!0;this.execute=function(g){for(var h=g.getIteratorAtPosition(f).container(),d,l,c;h.namespaceURI!==odf.Namespaces.officens||"annotation"!==h.localName;)h=h.parentNode;if(null===h)return!1;(d=h.getAttributeNS(odf.Namespaces.officens,"name"))&&(l=r.getElementsByTagNameNS(g.getRootNode(),odf.Namespaces.officens,"annotation-end").filter(function(c){return d===
-c.getAttributeNS(odf.Namespaces.officens,"name")})[0]||null);g.getOdfCanvas().forgetAnnotations();for(c=r.getElementsByTagNameNS(h,"urn:webodf:names:cursor","cursor");c.length;)h.parentNode.insertBefore(c.pop(),h);h.parentNode.removeChild(h);l&&l.parentNode.removeChild(l);g.emit(ops.OdtDocument.signalStepsRemoved,{position:0<f?f-1:f,length:p});g.fixCursorPositions();g.getOdfCanvas().refreshAnnotations();return!0};this.spec=function(){return{optype:"RemoveAnnotation",memberid:g,timestamp:l,position:f,
-length:p}}};
-// Input 70
+ops.OpSetBlob=function(){var k,h,b,p,d;this.init=function(n){k=n.memberid;h=n.timestamp;b=n.filename;p=n.mimetype;d=n.content};this.isEdit=!0;this.group=void 0;this.execute=function(h){h.getOdfCanvas().odfContainer().setBlob(b,p,d);return!0};this.spec=function(){return{optype:"SetBlob",memberid:k,timestamp:h,filename:b,mimetype:p,content:d}}};
+// Input 65
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -2000,8 +2105,9 @@ length:p}}};
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpRemoveBlob=function(){var g,l,f;this.init=function(p){g=p.memberid;l=p.timestamp;f=p.filename};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().removeBlob(f);return!0};this.spec=function(){return{optype:"RemoveBlob",memberid:g,timestamp:l,filename:f}}};
-// Input 71
+ops.OpSetParagraphStyle=function(){var k,h,b,p;this.init=function(d){k=d.memberid;h=d.timestamp;b=d.position;p=d.styleName};this.isEdit=!0;this.group=void 0;this.execute=function(d){var n;n=d.getIteratorAtPosition(b);return(n=d.getParagraphElement(n.container()))?(""!==p?n.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","text:style-name",p):n.removeAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","style-name"),d.getOdfCanvas().refreshSize(),d.emit(ops.OdtDocument.signalParagraphChanged,
+{paragraphElement:n,timeStamp:h,memberId:k}),d.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=function(){return{optype:"SetParagraphStyle",memberid:k,timestamp:h,position:b,styleName:p}}};
+// Input 66
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -2039,8 +2145,10 @@ ops.OpRemoveBlob=function(){var g,l,f;this.init=function(p){g=p.memberid;l=p.tim
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpRemoveCursor=function(){var g,l;this.init=function(f){g=f.memberid;l=f.timestamp};this.isEdit=!1;this.execute=function(f){return f.removeCursor(g)?!0:!1};this.spec=function(){return{optype:"RemoveCursor",memberid:g,timestamp:l}}};
-// Input 72
+ops.OpSplitParagraph=function(){var k,h,b,p,d;this.init=function(n){k=n.memberid;h=n.timestamp;b=n.position;p="true"===n.moveCursor||!0===n.moveCursor;d=new odf.OdfUtils};this.isEdit=!0;this.group=void 0;this.execute=function(n){var g,q,r,l,f,c,a,m=n.getCursor(k);n.upgradeWhitespacesAtPosition(b);g=n.getTextNodeAtStep(b);if(!g)return!1;q=n.getParagraphElement(g.textNode);if(!q)return!1;r=d.isListItem(q.parentNode)?q.parentNode:q;0===g.offset?(a=g.textNode.previousSibling,c=null):(a=g.textNode,c=g.offset>=
+g.textNode.length?null:g.textNode.splitText(g.offset));for(l=g.textNode;l!==r;){l=l.parentNode;f=l.cloneNode(!1);c&&f.appendChild(c);if(a)for(;a&&a.nextSibling;)f.appendChild(a.nextSibling);else for(;l.firstChild;)f.appendChild(l.firstChild);l.parentNode.insertBefore(f,l.nextSibling);a=l;c=f}d.isListItem(c)&&(c=c.childNodes.item(0));0===g.textNode.length&&g.textNode.parentNode.removeChild(g.textNode);n.emit(ops.OdtDocument.signalStepsInserted,{position:b,length:1});m&&p&&(n.moveCursor(k,b+1,0),n.emit(ops.Document.signalCursorMoved,
+m));n.fixCursorPositions();n.getOdfCanvas().refreshSize();n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:q,memberId:k,timeStamp:h});n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:c,memberId:k,timeStamp:h});n.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph",memberid:k,timestamp:h,position:b,moveCursor:p}}};
+// Input 67
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2065,8 +2173,35 @@ ops.OpRemoveCursor=function(){var g,l;this.init=function(f){g=f.memberid;l=f.tim
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.Member");ops.OpRemoveMember=function(){var g,l;this.init=function(f){g=f.memberid;l=parseInt(f.timestamp,10)};this.isEdit=!1;this.execute=function(f){if(!f.getMember(g))return!1;f.removeMember(g);f.emit(ops.OdtDocument.signalMemberRemoved,g);return!0};this.spec=function(){return{optype:"RemoveMember",memberid:g,timestamp:l}}};
-// Input 73
+ops.OpUpdateMember=function(){function k(b){var d="//dc:creator[@editinfo:memberid='"+h+"']";b=xmldom.XPath.getODFElementsWithXPath(b.getRootNode(),d,function(b){return"editinfo"===b?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(b)});for(d=0;d<b.length;d+=1)b[d].textContent=p.fullName}var h,b,p,d;this.init=function(k){h=k.memberid;b=parseInt(k.timestamp,10);p=k.setProperties;d=k.removedProperties};this.isEdit=!1;this.group=void 0;this.execute=function(b){var g=b.getMember(h);if(!g)return!1;
+d&&g.removeProperties(d);p&&(g.setProperties(p),p.fullName&&k(b));b.emit(ops.Document.signalMemberUpdated,g);return!0};this.spec=function(){return{optype:"UpdateMember",memberid:h,timestamp:b,setProperties:p,removedProperties:d}}};
+// Input 68
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OpUpdateMetadata=function(){var k,h,b,p;this.init=function(d){k=d.memberid;h=parseInt(d.timestamp,10);b=d.setProperties;p=d.removedProperties};this.isEdit=!0;this.group=void 0;this.execute=function(d){d=d.getOdfCanvas().odfContainer();var h=[];p&&(h=p.attributes.split(","));d.setMetadata(b,h);return!0};this.spec=function(){return{optype:"UpdateMetadata",memberid:k,timestamp:h,setProperties:b,removedProperties:p}}};
+// Input 69
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -2104,8 +2239,10 @@ runtime.loadClass("ops.Member");ops.OpRemoveMember=function(){var g,l;this.init=
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpRemoveStyle=function(){var g,l,f,p;this.init=function(r){g=r.memberid;l=r.timestamp;f=r.styleName;p=r.styleFamily};this.isEdit=!0;this.execute=function(g){var l=g.getStyleElement(f,p);if(!l)return!1;l.parentNode.removeChild(l);g.getOdfCanvas().refreshCSS();g.emit(ops.OdtDocument.signalCommonStyleDeleted,{name:f,family:p});return!0};this.spec=function(){return{optype:"RemoveStyle",memberid:g,timestamp:l,styleName:f,styleFamily:p}}};
-// Input 74
+ops.OpUpdateParagraphStyle=function(){function k(b,d){var g,f,c=d?d.split(","):[];for(g=0;g<c.length;g+=1)f=c[g].split(":"),b.removeAttributeNS(odf.Namespaces.lookupNamespaceURI(f[0]),f[1])}var h,b,p,d,n,g=odf.Namespaces.stylens;this.init=function(g){h=g.memberid;b=g.timestamp;p=g.styleName;d=g.setProperties;n=g.removedProperties};this.isEdit=!0;this.group=void 0;this.execute=function(b){var h=b.getFormatting(),l,f,c;return(l=""!==p?b.getParagraphStyleElement(p):h.getDefaultStyleElement("paragraph"))?
+(f=l.getElementsByTagNameNS(g,"paragraph-properties").item(0),c=l.getElementsByTagNameNS(g,"text-properties").item(0),d&&h.updateStyle(l,d),n&&(h=n["style:paragraph-properties"],f&&h&&(k(f,h.attributes),0===f.attributes.length&&l.removeChild(f)),h=n["style:text-properties"],c&&h&&(k(c,h.attributes),0===c.attributes.length&&l.removeChild(c)),k(l,n.attributes)),b.getOdfCanvas().refreshCSS(),b.emit(ops.OdtDocument.signalParagraphStyleModified,p),b.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=
+function(){return{optype:"UpdateParagraphStyle",memberid:h,timestamp:b,styleName:p,setProperties:d,removedProperties:n}}};
+// Input 70
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -2143,16 +2280,12 @@ ops.OpRemoveStyle=function(){var g,l,f,p;this.init=function(r){g=r.memberid;l=r.
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfUtils");runtime.loadClass("core.DomUtils");
-ops.OpRemoveText=function(){function g(f){function c(a){return d.hasOwnProperty(a.namespaceURI)||"br"===a.localName&&n.isLineBreak(a.parentNode)||a.nodeType===Node.TEXT_NODE&&d.hasOwnProperty(a.parentNode.namespaceURI)}function e(a){if(n.isCharacterElement(a))return!1;if(a.nodeType===Node.TEXT_NODE)return 0===a.textContent.length;for(a=a.firstChild;a;){if(d.hasOwnProperty(a.namespaceURI)||!e(a))return!1;a=a.nextSibling}return!0}function a(b){var d;b.nodeType===Node.TEXT_NODE?(d=b.parentNode,d.removeChild(b)):
-d=h.removeUnwantedNodes(b,c);return!n.isParagraph(d)&&d!==f&&e(d)?a(d):d}this.isEmpty=e;this.mergeChildrenIntoParent=a}var l,f,p,r,n,h,d={};this.init=function(g){runtime.assert(0<=g.length,"OpRemoveText only supports positive lengths");l=g.memberid;f=g.timestamp;p=parseInt(g.position,10);r=parseInt(g.length,10);n=new odf.OdfUtils;h=new core.DomUtils;d[odf.Namespaces.dbns]=!0;d[odf.Namespaces.dcns]=!0;d[odf.Namespaces.dr3dns]=!0;d[odf.Namespaces.drawns]=!0;d[odf.Namespaces.chartns]=!0;d[odf.Namespaces.formns]=
-!0;d[odf.Namespaces.numberns]=!0;d[odf.Namespaces.officens]=!0;d[odf.Namespaces.presentationns]=!0;d[odf.Namespaces.stylens]=!0;d[odf.Namespaces.svgns]=!0;d[odf.Namespaces.tablens]=!0;d[odf.Namespaces.textns]=!0};this.isEdit=!0;this.execute=function(d){var c,e,a,b,q=d.getCursor(l),k=new g(d.getRootNode());d.upgradeWhitespacesAtPosition(p);d.upgradeWhitespacesAtPosition(p+r);e=d.convertCursorToDomRange(p,r);h.splitBoundaries(e);c=d.getParagraphElement(e.startContainer);a=n.getTextElements(e,!1,!0);
-b=n.getParagraphElements(e);e.detach();a.forEach(function(a){k.mergeChildrenIntoParent(a)});e=b.reduce(function(a,b){var c,d=!1,e=a,f=b,h,g=null;k.isEmpty(a)&&(d=!0,b.parentNode!==a.parentNode&&(h=b.parentNode,a.parentNode.insertBefore(b,a.nextSibling)),f=a,e=b,g=e.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo")[0]||e.firstChild);for(;f.hasChildNodes();)c=d?f.lastChild:f.firstChild,f.removeChild(c),"editinfo"!==c.localName&&e.insertBefore(c,g);h&&k.isEmpty(h)&&k.mergeChildrenIntoParent(h);
-k.mergeChildrenIntoParent(f);return e});d.emit(ops.OdtDocument.signalStepsRemoved,{position:p,length:r});d.downgradeWhitespacesAtPosition(p);d.fixCursorPositions();d.getOdfCanvas().refreshSize();d.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:e||c,memberId:l,timeStamp:f});q&&(q.resetSelectionType(),d.emit(ops.OdtDocument.signalCursorMoved,q));d.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveText",memberid:l,timestamp:f,position:p,length:r}}};
-// Input 75
+ops.OperationFactory=function(){var k;this.register=function(h,b){k[h]=b};this.create=function(h){var b=null,p=k[h.optype];p&&(b=new p,b.init(h));return b};k={AddMember:ops.OpAddMember,UpdateMember:ops.OpUpdateMember,RemoveMember:ops.OpRemoveMember,AddCursor:ops.OpAddCursor,ApplyDirectStyling:ops.OpApplyDirectStyling,SetBlob:ops.OpSetBlob,RemoveBlob:ops.OpRemoveBlob,InsertImage:ops.OpInsertImage,InsertTable:ops.OpInsertTable,InsertText:ops.OpInsertText,RemoveText:ops.OpRemoveText,SplitParagraph:ops.OpSplitParagraph,
+SetParagraphStyle:ops.OpSetParagraphStyle,UpdateParagraphStyle:ops.OpUpdateParagraphStyle,AddStyle:ops.OpAddStyle,RemoveStyle:ops.OpRemoveStyle,MoveCursor:ops.OpMoveCursor,RemoveCursor:ops.OpRemoveCursor,AddAnnotation:ops.OpAddAnnotation,RemoveAnnotation:ops.OpRemoveAnnotation,UpdateMetadata:ops.OpUpdateMetadata,ApplyHyperlink:ops.OpApplyHyperlink,RemoveHyperlink:ops.OpRemoveHyperlink}};
+// Input 71
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2187,11 +2320,12 @@ k.mergeChildrenIntoParent(f);return e});d.emit(ops.OdtDocument.signalStepsRemove
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpSetBlob=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.filename;p=n.mimetype;r=n.content};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().setBlob(f,p,r);return!0};this.spec=function(){return{optype:"SetBlob",memberid:g,timestamp:l,filename:f,mimetype:p,content:r}}};
-// Input 76
+ops.OperationRouter=function(){};ops.OperationRouter.prototype.setOperationFactory=function(k){};ops.OperationRouter.prototype.setPlaybackFunction=function(k){};ops.OperationRouter.prototype.push=function(k){};ops.OperationRouter.prototype.close=function(k){};ops.OperationRouter.prototype.subscribe=function(k,h){};ops.OperationRouter.prototype.unsubscribe=function(k,h){};ops.OperationRouter.prototype.hasLocalUnsyncedOps=function(){};ops.OperationRouter.prototype.hasSessionHostConnection=function(){};
+ops.OperationRouter.signalProcessingBatchStart="router/batchstart";ops.OperationRouter.signalProcessingBatchEnd="router/batchend";
+// Input 72
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2226,9 +2360,9 @@ ops.OpSetBlob=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.ti
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpSetParagraphStyle=function(){var g,l,f,p;this.init=function(r){g=r.memberid;l=r.timestamp;f=r.position;p=r.styleName};this.isEdit=!0;this.execute=function(r){var n;n=r.getIteratorAtPosition(f);return(n=r.getParagraphElement(n.container()))?(""!==p?n.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","text:style-name",p):n.removeAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","style-name"),r.getOdfCanvas().refreshSize(),r.emit(ops.OdtDocument.signalParagraphChanged,
-{paragraphElement:n,timeStamp:l,memberId:g}),r.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=function(){return{optype:"SetParagraphStyle",memberid:g,timestamp:l,position:f,styleName:p}}};
-// Input 77
+ops.TrivialOperationRouter=function(){var k=new core.EventNotifier([ops.OperationRouter.signalProcessingBatchStart,ops.OperationRouter.signalProcessingBatchEnd]),h,b,p=0;this.setOperationFactory=function(b){h=b};this.setPlaybackFunction=function(d){b=d};this.push=function(d){p+=1;k.emit(ops.OperationRouter.signalProcessingBatchStart,{});d.forEach(function(d){d=d.spec();d.timestamp=(new Date).getTime();d=h.create(d);d.group="g"+p;b(d)});k.emit(ops.OperationRouter.signalProcessingBatchEnd,{})};this.close=
+function(b){b()};this.subscribe=function(b,h){k.subscribe(b,h)};this.unsubscribe=function(b,h){k.unsubscribe(b,h)};this.hasLocalUnsyncedOps=function(){return!1};this.hasSessionHostConnection=function(){return!0}};
+// Input 73
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@@ -2266,10 +2400,9 @@ ops.OpSetParagraphStyle=function(){var g,l,f,p;this.init=function(r){g=r.memberi
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpSplitParagraph=function(){var g,l,f,p,r;this.init=function(n){g=n.memberid;l=n.timestamp;f=n.position;p="true"===n.moveCursor||!0===n.moveCursor;r=new odf.OdfUtils};this.isEdit=!0;this.execute=function(n){var h,d,m,c,e,a,b,q=n.getCursor(g);n.upgradeWhitespacesAtPosition(f);h=n.getTextNodeAtStep(f);if(!h)return!1;d=n.getParagraphElement(h.textNode);if(!d)return!1;m=r.isListItem(d.parentNode)?d.parentNode:d;0===h.offset?(b=h.textNode.previousSibling,a=null):(b=h.textNode,a=h.offset>=h.textNode.length?
-null:h.textNode.splitText(h.offset));for(c=h.textNode;c!==m;){c=c.parentNode;e=c.cloneNode(!1);a&&e.appendChild(a);if(b)for(;b&&b.nextSibling;)e.appendChild(b.nextSibling);else for(;c.firstChild;)e.appendChild(c.firstChild);c.parentNode.insertBefore(e,c.nextSibling);b=c;a=e}r.isListItem(a)&&(a=a.childNodes[0]);0===h.textNode.length&&h.textNode.parentNode.removeChild(h.textNode);n.emit(ops.OdtDocument.signalStepsInserted,{position:f,length:1});q&&p&&(n.moveCursor(g,f+1,0),n.emit(ops.OdtDocument.signalCursorMoved,
-q));n.fixCursorPositions();n.getOdfCanvas().refreshSize();n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:d,memberId:g,timeStamp:l});n.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:a,memberId:g,timeStamp:l});n.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph",memberid:g,timestamp:l,position:f,moveCursor:p}}};
-// Input 78
+ops.Session=function(k){function h(b){d.emit(ops.OdtDocument.signalProcessingBatchStart,b)}function b(b){d.emit(ops.OdtDocument.signalProcessingBatchEnd,b)}var p=new ops.OperationFactory,d=new ops.OdtDocument(k),n=null;this.setOperationFactory=function(b){p=b;n&&n.setOperationFactory(p)};this.setOperationRouter=function(g){n&&(n.unsubscribe(ops.OperationRouter.signalProcessingBatchStart,h),n.unsubscribe(ops.OperationRouter.signalProcessingBatchEnd,b));n=g;n.subscribe(ops.OperationRouter.signalProcessingBatchStart,
+h);n.subscribe(ops.OperationRouter.signalProcessingBatchEnd,b);g.setPlaybackFunction(function(b){d.emit(ops.OdtDocument.signalOperationStart,b);return b.execute(d)?(d.emit(ops.OdtDocument.signalOperationEnd,b),!0):!1});g.setOperationFactory(p)};this.getOperationFactory=function(){return p};this.getOdtDocument=function(){return d};this.enqueue=function(b){n.push(b)};this.close=function(b){n.close(function(h){h?b(h):d.close(b)})};this.destroy=function(b){d.destroy(b)};this.setOperationRouter(new ops.TrivialOperationRouter)};
+// Input 74
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2294,10 +2427,63 @@ q));n.fixCursorPositions();n.getOdfCanvas().refreshSize();n.emit(ops.OdtDocument
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.Member");runtime.loadClass("xmldom.XPath");
-ops.OpUpdateMember=function(){function g(){var f="//dc:creator[@editinfo:memberid='"+l+"']",f=xmldom.XPath.getODFElementsWithXPath(n.getRootNode(),f,function(d){return"editinfo"===d?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(d)}),d;for(d=0;d<f.length;d+=1)f[d].textContent=p.fullName}var l,f,p,r,n;this.init=function(h){l=h.memberid;f=parseInt(h.timestamp,10);p=h.setProperties;r=h.removedProperties};this.isEdit=!1;this.execute=function(f){n=f;var d=f.getMember(l);if(!d)return!1;r&&
-d.removeProperties(r);p&&(d.setProperties(p),p.fullName&&g());f.emit(ops.OdtDocument.signalMemberUpdated,d);return!0};this.spec=function(){return{optype:"UpdateMember",memberid:l,timestamp:f,setProperties:p,removedProperties:r}}};
-// Input 79
+gui.AnnotationController=function(k,h){function b(){var b=g.getCursor(h),b=b&&b.getNode(),c=!1;if(b){a:{for(c=g.getRootNode();b&&b!==c;){if(b.namespaceURI===l&&"annotation"===b.localName){b=!0;break a}b=b.parentNode}b=!1}c=!b}c!==q&&(q=c,r.emit(gui.AnnotationController.annotatableChanged,q))}function p(d){d.getMemberId()===h&&b()}function d(d){d===h&&b()}function n(d){d.getMemberId()===h&&b()}var g=k.getOdtDocument(),q=!1,r=new core.EventNotifier([gui.AnnotationController.annotatableChanged]),l=odf.Namespaces.officens;
+this.isAnnotatable=function(){return q};this.addAnnotation=function(){var b=new ops.OpAddAnnotation,c=g.getCursorSelection(h),a=c.length,c=c.position;q&&(c=0<=a?c:c+a,a=Math.abs(a),b.init({memberid:h,position:c,length:a,name:h+Date.now()}),k.enqueue([b]))};this.removeAnnotation=function(b){var c,a;c=g.convertDomPointToCursorStep(b,0)+1;a=g.convertDomPointToCursorStep(b,b.childNodes.length);b=new ops.OpRemoveAnnotation;b.init({memberid:h,position:c,length:a-c});a=new ops.OpMoveCursor;a.init({memberid:h,
+position:0<c?c-1:c,length:0});k.enqueue([b,a])};this.subscribe=function(b,c){r.subscribe(b,c)};this.unsubscribe=function(b,c){r.unsubscribe(b,c)};this.destroy=function(b){g.unsubscribe(ops.Document.signalCursorAdded,p);g.unsubscribe(ops.Document.signalCursorRemoved,d);g.unsubscribe(ops.Document.signalCursorMoved,n);b()};g.subscribe(ops.Document.signalCursorAdded,p);g.subscribe(ops.Document.signalCursorRemoved,d);g.subscribe(ops.Document.signalCursorMoved,n);b()};
+gui.AnnotationController.annotatableChanged="annotatable/changed";(function(){return gui.AnnotationController})();
+// Input 75
+gui.Avatar=function(k,h){var b=this,p,d,n;this.setColor=function(b){d.style.borderColor=b};this.setImageUrl=function(g){b.isVisible()?d.src=g:n=g};this.isVisible=function(){return"block"===p.style.display};this.show=function(){n&&(d.src=n,n=void 0);p.style.display="block"};this.hide=function(){p.style.display="none"};this.markAsFocussed=function(b){b?p.classList.add("active"):p.classList.remove("active")};this.destroy=function(b){k.removeChild(p);b()};(function(){var b=k.ownerDocument,n=b.documentElement.namespaceURI;
+p=b.createElementNS(n,"div");d=b.createElementNS(n,"img");d.width=64;d.height=64;p.appendChild(d);p.style.width="64px";p.style.height="70px";p.style.position="absolute";p.style.top="-80px";p.style.left="-34px";p.style.display=h?"block":"none";p.className="handle";k.appendChild(p)})()};
+// Input 76
+gui.Caret=function(k,h,b){function p(){r.style.opacity="0"===r.style.opacity?"1":"0";t.trigger()}function d(a,b){var c=a.getBoundingClientRect(),e=0,d=0;c&&b&&(e=Math.max(c.top,b.top),d=Math.min(c.bottom,b.bottom));return d-e}function n(){Object.keys(v).forEach(function(a){u[a]=v[a]})}function g(){var e,f,g,m;if(!1===v.isShown||k.getSelectionType()!==ops.OdtCursor.RangeSelection||!b&&!k.getSelectedRange().collapsed)v.visibility="hidden",r.style.visibility="hidden",t.cancel();else{v.visibility="visible";
+r.style.visibility="visible";if(!1===v.isFocused)r.style.opacity="1",t.cancel();else{if(w||u.visibility!==v.visibility)r.style.opacity="1",t.cancel();t.trigger()}if(x||z||u.visibility!==v.visibility){e=k.getSelectedRange().cloneRange();f=k.getNode();var h=null;f.previousSibling&&(g=f.previousSibling.nodeType===Node.TEXT_NODE?f.previousSibling.textContent.length:f.previousSibling.childNodes.length,e.setStart(f.previousSibling,0<g?g-1:0),e.setEnd(f.previousSibling,g),(g=e.getBoundingClientRect())&&
+g.height&&(h=g));f.nextSibling&&(e.setStart(f.nextSibling,0),e.setEnd(f.nextSibling,0<(f.nextSibling.nodeType===Node.TEXT_NODE?f.nextSibling.textContent.length:f.nextSibling.childNodes.length)?1:0),(g=e.getBoundingClientRect())&&g.height&&(!h||d(f,g)>d(f,h))&&(h=g));f=h;h=k.getDocument().getCanvas();e=h.getZoomLevel();h=a.getBoundingClientRect(h.getSizer());f?(r.style.top="0",g=a.getBoundingClientRect(r),8>f.height&&(f={top:f.top-(8-f.height)/2,height:8}),r.style.height=a.adaptRangeDifferenceToZoomLevel(f.height,
+e)+"px",r.style.top=a.adaptRangeDifferenceToZoomLevel(f.top-g.top,e)+"px"):(r.style.height="1em",r.style.top="5%");c&&(f=runtime.getWindow().getComputedStyle(r,null),g=a.getBoundingClientRect(r),c.style.bottom=a.adaptRangeDifferenceToZoomLevel(h.bottom-g.bottom,e)+"px",c.style.left=a.adaptRangeDifferenceToZoomLevel(g.right-h.left,e)+"px",f.font?c.style.font=f.font:(c.style.fontStyle=f.fontStyle,c.style.fontVariant=f.fontVariant,c.style.fontWeight=f.fontWeight,c.style.fontSize=f.fontSize,c.style.lineHeight=
+f.lineHeight,c.style.fontFamily=f.fontFamily))}if(z){var h=k.getDocument().getCanvas().getElement().parentNode,p;g=h.offsetWidth-h.clientWidth+5;m=h.offsetHeight-h.clientHeight+5;p=r.getBoundingClientRect();e=p.left-g;f=p.top-m;g=p.right+g;m=p.bottom+m;p=h.getBoundingClientRect();f<p.top?h.scrollTop-=p.top-f:m>p.bottom&&(h.scrollTop+=m-p.bottom);e<p.left?h.scrollLeft-=p.left-e:g>p.right&&(h.scrollLeft+=g-p.right)}}u.isFocused!==v.isFocused&&l.markAsFocussed(v.isFocused);n();x=z=w=!1}function q(a){f.removeChild(r);
+a()}var r,l,f,c,a=new core.DomUtils,m=new core.Async,e,t,w=!1,z=!1,x=!1,v={isFocused:!1,isShown:!0,visibility:"hidden"},u={isFocused:!v.isFocused,isShown:!v.isShown,visibility:"hidden"};this.handleUpdate=function(){x=!0;"hidden"!==v.visibility&&(v.visibility="hidden",r.style.visibility="hidden");e.trigger()};this.refreshCursorBlinking=function(){w=!0;e.trigger()};this.setFocus=function(){v.isFocused=!0;e.trigger()};this.removeFocus=function(){v.isFocused=!1;e.trigger()};this.show=function(){v.isShown=
+!0;e.trigger()};this.hide=function(){v.isShown=!1;e.trigger()};this.setAvatarImageUrl=function(a){l.setImageUrl(a)};this.setColor=function(a){r.style.borderColor=a;l.setColor(a)};this.getCursor=function(){return k};this.getFocusElement=function(){return r};this.toggleHandleVisibility=function(){l.isVisible()?l.hide():l.show()};this.showHandle=function(){l.show()};this.hideHandle=function(){l.hide()};this.setOverlayElement=function(a){c=a;x=!0;e.trigger()};this.ensureVisible=function(){z=!0;e.trigger()};
+this.destroy=function(a){m.destroyAll([e.destroy,t.destroy,l.destroy,q],a)};(function(){var a=k.getDocument().getDOMDocument();r=a.createElementNS(a.documentElement.namespaceURI,"span");r.className="caret";r.style.top="5%";f=k.getNode();f.appendChild(r);l=new gui.Avatar(f,h);e=new core.ScheduledTask(g,0);t=new core.ScheduledTask(p,500);e.triggerImmediate()})()};
+// Input 77
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
+
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+
+ This license applies to this entire compilation.
+ @licend
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+odf.TextSerializer=function(){function k(p){var d="",n=h.filter?h.filter.acceptNode(p):NodeFilter.FILTER_ACCEPT,g=p.nodeType,q;if((n===NodeFilter.FILTER_ACCEPT||n===NodeFilter.FILTER_SKIP)&&b.isTextContentContainingNode(p))for(q=p.firstChild;q;)d+=k(q),q=q.nextSibling;n===NodeFilter.FILTER_ACCEPT&&(g===Node.ELEMENT_NODE&&b.isParagraph(p)?d+="\n":g===Node.TEXT_NODE&&p.textContent&&(d+=p.textContent));return d}var h=this,b=new odf.OdfUtils;this.filter=null;this.writeToString=function(b){if(!b)return"";
+b=k(b);"\n"===b[b.length-1]&&(b=b.substr(0,b.length-1));return b}};
+// Input 78
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2322,12 +2508,11 @@ d.removeProperties(r);p&&(d.setProperties(p),p.fullName&&g());f.emit(ops.OdtDocu
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OpUpdateMetadata=function(){var g,l,f,p;this.init=function(r){g=r.memberid;l=parseInt(r.timestamp,10);f=r.setProperties;p=r.removedProperties};this.isEdit=!0;this.execute=function(g){g=g.getOdfCanvas().odfContainer();var l=[],h=["dc:date","dc:creator","meta:editing-cycles"];f&&h.forEach(function(d){if(f[d])return!1});p&&(h.forEach(function(d){if(-1!==l.indexOf(d))return!1}),l=p.attributes.split(","));g.setMetadata(f,l);return!0};this.spec=function(){return{optype:"UpdateMetadata",memberid:g,timestamp:l,
-setProperties:f,removedProperties:p}}};
-// Input 80
+gui.MimeDataExporter=function(){var k,h;this.exportRangeToDataTransfer=function(b,h){var d;d=h.startContainer.ownerDocument.createElement("span");d.appendChild(h.cloneContents());d=k.writeToString(d);try{b.setData("text/plain",d)}catch(n){b.setData("Text",d)}};k=new odf.TextSerializer;h=new odf.OdfNodeFilter;k.filter=h};
+// Input 79
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2362,14 +2547,11 @@ setProperties:f,removedProperties:p}}};
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("odf.Namespaces");
-ops.OpUpdateParagraphStyle=function(){function g(d,f){var c,e,a=f?f.split(","):[];for(c=0;c<a.length;c+=1)e=a[c].split(":"),d.removeAttributeNS(odf.Namespaces.lookupNamespaceURI(e[0]),e[1])}var l,f,p,r,n,h=odf.Namespaces.stylens;this.init=function(d){l=d.memberid;f=d.timestamp;p=d.styleName;r=d.setProperties;n=d.removedProperties};this.isEdit=!0;this.execute=function(d){var f=d.getFormatting(),c,e,a;return(c=""!==p?d.getParagraphStyleElement(p):f.getDefaultStyleElement("paragraph"))?(e=c.getElementsByTagNameNS(h,
-"paragraph-properties")[0],a=c.getElementsByTagNameNS(h,"text-properties")[0],r&&f.updateStyle(c,r),n&&(n["style:paragraph-properties"]&&(g(e,n["style:paragraph-properties"].attributes),0===e.attributes.length&&c.removeChild(e)),n["style:text-properties"]&&(g(a,n["style:text-properties"].attributes),0===a.attributes.length&&c.removeChild(a)),g(c,n.attributes)),d.getOdfCanvas().refreshCSS(),d.emit(ops.OdtDocument.signalParagraphStyleModified,p),d.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=
-function(){return{optype:"UpdateParagraphStyle",memberid:l,timestamp:f,styleName:p,setProperties:r,removedProperties:n}}};
-// Input 81
+gui.Clipboard=function(k){this.setDataFromRange=function(h,b){var p,d=h.clipboardData;p=runtime.getWindow();!d&&p&&(d=p.clipboardData);d?(p=!0,k.exportRangeToDataTransfer(d,b),h.preventDefault()):p=!1;return p}};
+// Input 80
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2014 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2404,11 +2586,10 @@ function(){return{optype:"UpdateParagraphStyle",memberid:l,timestamp:f,styleName
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.OpAddMember");runtime.loadClass("ops.OpUpdateMember");runtime.loadClass("ops.OpRemoveMember");runtime.loadClass("ops.OpAddCursor");runtime.loadClass("ops.OpApplyDirectStyling");runtime.loadClass("ops.OpRemoveCursor");runtime.loadClass("ops.OpMoveCursor");runtime.loadClass("ops.OpSetBlob");runtime.loadClass("ops.OpRemoveBlob");runtime.loadClass("ops.OpInsertImage");runtime.loadClass("ops.OpInsertTable");runtime.loadClass("ops.OpInsertText");runtime.loadClass("ops.OpRemoveText");
-runtime.loadClass("ops.OpSplitParagraph");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("ops.OpUpdateParagraphStyle");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpRemoveStyle");runtime.loadClass("ops.OpAddAnnotation");runtime.loadClass("ops.OpRemoveAnnotation");runtime.loadClass("ops.OpUpdateMetadata");
-ops.OperationFactory=function(){function g(f){return function(){return new f}}var l;this.register=function(f,g){l[f]=g};this.create=function(f){var g=null,r=l[f.optype];r&&(g=r(f),g.init(f));return g};l={AddMember:g(ops.OpAddMember),UpdateMember:g(ops.OpUpdateMember),RemoveMember:g(ops.OpRemoveMember),AddCursor:g(ops.OpAddCursor),ApplyDirectStyling:g(ops.OpApplyDirectStyling),SetBlob:g(ops.OpSetBlob),RemoveBlob:g(ops.OpRemoveBlob),InsertImage:g(ops.OpInsertImage),InsertTable:g(ops.OpInsertTable),
-InsertText:g(ops.OpInsertText),RemoveText:g(ops.OpRemoveText),SplitParagraph:g(ops.OpSplitParagraph),SetParagraphStyle:g(ops.OpSetParagraphStyle),UpdateParagraphStyle:g(ops.OpUpdateParagraphStyle),AddStyle:g(ops.OpAddStyle),RemoveStyle:g(ops.OpRemoveStyle),MoveCursor:g(ops.OpMoveCursor),RemoveCursor:g(ops.OpRemoveCursor),AddAnnotation:g(ops.OpAddAnnotation),RemoveAnnotation:g(ops.OpRemoveAnnotation),UpdateMetadata:g(ops.OpUpdateMetadata)}};
-// Input 82
+gui.StyleSummary=function(k){function h(b,g){var h=b+"|"+g,p;d.hasOwnProperty(h)||(p=[],k.forEach(function(d){d=(d=d[b])&&d[g];-1===p.indexOf(d)&&p.push(d)}),d[h]=p);return d[h]}function b(b,d,k){return function(){var p=h(b,d);return k.length>=p.length&&p.every(function(b){return-1!==k.indexOf(b)})}}function p(b,d){var k=h(b,d);return 1===k.length?k[0]:void 0}var d={};this.getPropertyValues=h;this.getCommonValue=p;this.isBold=b("style:text-properties","fo:font-weight",["bold"]);this.isItalic=b("style:text-properties",
+"fo:font-style",["italic"]);this.hasUnderline=b("style:text-properties","style:text-underline-style",["solid"]);this.hasStrikeThrough=b("style:text-properties","style:text-line-through-style",["solid"]);this.fontSize=function(){var b=p("style:text-properties","fo:font-size");return b&&parseFloat(b)};this.fontName=function(){return p("style:text-properties","style:font-name")};this.isAlignedLeft=b("style:paragraph-properties","fo:text-align",["left","start"]);this.isAlignedCenter=b("style:paragraph-properties",
+"fo:text-align",["center"]);this.isAlignedRight=b("style:paragraph-properties","fo:text-align",["right","end"]);this.isAlignedJustified=b("style:paragraph-properties","fo:text-align",["justify"]);this.text={isBold:this.isBold,isItalic:this.isItalic,hasUnderline:this.hasUnderline,hasStrikeThrough:this.hasStrikeThrough,fontSize:this.fontSize,fontName:this.fontName};this.paragraph={isAlignedLeft:this.isAlignedLeft,isAlignedCenter:this.isAlignedCenter,isAlignedRight:this.isAlignedRight,isAlignedJustified:this.isAlignedJustified}};
+// Input 81
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2446,11 +2627,38 @@ InsertText:g(ops.OpInsertText),RemoveText:g(ops.OpRemoveText),SplitParagraph:g(o
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OperationRouter=function(){};ops.OperationRouter.prototype.setOperationFactory=function(g){};ops.OperationRouter.prototype.setPlaybackFunction=function(g){};ops.OperationRouter.prototype.push=function(g){};ops.OperationRouter.prototype.close=function(g){};ops.OperationRouter.prototype.subscribe=function(g,l){};ops.OperationRouter.prototype.unsubscribe=function(g,l){};ops.OperationRouter.prototype.hasLocalUnsyncedOps=function(){};ops.OperationRouter.prototype.hasSessionHostConnection=function(){};
+gui.DirectFormattingController=function(k,h,b,p){function d(a){var b;a.collapsed?(b=a.startContainer,b.hasChildNodes()&&a.startOffset<b.childNodes.length&&(b=b.childNodes.item(a.startOffset)),a=[b]):a=K.getTextNodes(a,!0);return a}function n(a,b){var c={};Object.keys(a).forEach(function(e){var d=a[e](),f=b[e]();d!==f&&(c[e]=f)});return c}function g(){var a,b,c;a=(a=(a=F.getCursor(h))&&a.getSelectedRange())?d(a):[];a=F.getFormatting().getAppliedStyles(a);a[0]&&H&&(a[0]=O.mergeObjects(a[0],H));T=a;
+c=new gui.StyleSummary(T);a=n(y.text,c.text);b=n(y.paragraph,c.paragraph);y=c;0<Object.keys(a).length&&Z.emit(gui.DirectFormattingController.textStylingChanged,a);0<Object.keys(b).length&&Z.emit(gui.DirectFormattingController.paragraphStylingChanged,b)}function q(a){("string"===typeof a?a:a.getMemberId())===h&&g()}function r(){g()}function l(a){var b=F.getCursor(h);a=a.paragraphElement;b&&F.getParagraphElement(b.getNode())===a&&g()}function f(a,b){b(!a());return!0}function c(a){var b=F.getCursorSelection(h),
+c={"style:text-properties":a};0!==b.length?(a=new ops.OpApplyDirectStyling,a.init({memberid:h,position:b.position,length:b.length,setProperties:c}),k.enqueue([a])):(H=O.mergeObjects(H||{},c),g())}function a(a,b){var e={};e[a]=b;c(e)}function m(a){a=a.spec();H&&a.memberid===h&&"SplitParagraph"!==a.optype&&(H=null,g())}function e(b){a("fo:font-weight",b?"bold":"normal")}function t(b){a("fo:font-style",b?"italic":"normal")}function w(b){a("style:text-underline-style",b?"solid":"none")}function z(b){a("style:text-line-through-style",
+b?"solid":"none")}function x(a){return a===ops.StepsTranslator.NEXT_STEP}function v(a){var c=F.getCursor(h).getSelectedRange(),c=K.getParagraphElements(c),e=F.getFormatting(),d=[],f={},g;c.forEach(function(c){var m=F.convertDomPointToCursorStep(c,0,x),l=c.getAttributeNS(odf.Namespaces.textns,"style-name"),k;c=l?f.hasOwnProperty(l)?f[l]:void 0:g;c||(c=b.generateStyleName(),l?(f[l]=c,k=e.createDerivedStyleObject(l,"paragraph",{})):(g=c,k={}),k=a(k),l=new ops.OpAddStyle,l.init({memberid:h,styleName:c.toString(),
+styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:k}),d.push(l));l=new ops.OpSetParagraphStyle;l.init({memberid:h,styleName:c.toString(),position:m});d.push(l)});k.enqueue(d)}function u(a){v(function(b){return O.mergeObjects(b,a)})}function s(a){u({"style:paragraph-properties":{"fo:text-align":a}})}function A(a,b){var c=F.getFormatting().getDefaultTabStopDistance(),e=b["style:paragraph-properties"],d;e&&(e=e["fo:margin-left"])&&(d=K.parseLength(e));return O.mergeObjects(b,{"style:paragraph-properties":{"fo:margin-left":d&&
+d.unit===c.unit?d.value+a*c.value+d.unit:a*c.value+c.unit}})}function J(a,b){var c=d(a),e=F.getFormatting().getAppliedStyles(c)[0],f=F.getFormatting().getAppliedStylesForElement(b);if(!e||"text"!==e["style:family"]||!e["style:text-properties"])return!1;if(!f||!f["style:text-properties"])return!0;e=e["style:text-properties"];f=f["style:text-properties"];return!Object.keys(e).every(function(a){return e[a]===f[a]})}function G(){}var D=this,F=k.getOdtDocument(),O=new core.Utils,K=new odf.OdfUtils,Z=new core.EventNotifier([gui.DirectFormattingController.textStylingChanged,
+gui.DirectFormattingController.paragraphStylingChanged]),Q=odf.Namespaces.textns,W=core.PositionFilter.FilterResult.FILTER_ACCEPT,H,T=[],y=new gui.StyleSummary(T);this.formatTextSelection=c;this.createCursorStyleOp=function(a,b,c){var e=null;(c=c?T[0]:H)&&c["style:text-properties"]&&(e=new ops.OpApplyDirectStyling,e.init({memberid:h,position:a,length:b,setProperties:{"style:text-properties":c["style:text-properties"]}}),H=null,g());return e};this.setBold=e;this.setItalic=t;this.setHasUnderline=w;
+this.setHasStrikethrough=z;this.setFontSize=function(b){a("fo:font-size",b+"pt")};this.setFontName=function(b){a("style:font-name",b)};this.getAppliedStyles=function(){return T};this.toggleBold=f.bind(D,function(){return y.isBold()},e);this.toggleItalic=f.bind(D,function(){return y.isItalic()},t);this.toggleUnderline=f.bind(D,function(){return y.hasUnderline()},w);this.toggleStrikethrough=f.bind(D,function(){return y.hasStrikeThrough()},z);this.isBold=function(){return y.isBold()};this.isItalic=function(){return y.isItalic()};
+this.hasUnderline=function(){return y.hasUnderline()};this.hasStrikeThrough=function(){return y.hasStrikeThrough()};this.fontSize=function(){return y.fontSize()};this.fontName=function(){return y.fontName()};this.isAlignedLeft=function(){return y.isAlignedLeft()};this.isAlignedCenter=function(){return y.isAlignedCenter()};this.isAlignedRight=function(){return y.isAlignedRight()};this.isAlignedJustified=function(){return y.isAlignedJustified()};this.alignParagraphLeft=function(){s("left");return!0};
+this.alignParagraphCenter=function(){s("center");return!0};this.alignParagraphRight=function(){s("right");return!0};this.alignParagraphJustified=function(){s("justify");return!0};this.indent=function(){v(A.bind(null,1));return!0};this.outdent=function(){v(A.bind(null,-1));return!0};this.createParagraphStyleOps=function(a){var c=F.getCursor(h),e=c.getSelectedRange(),d=[],f,g;c.hasForwardSelection()?(f=c.getAnchorNode(),g=c.getNode()):(f=c.getNode(),g=c.getAnchorNode());c=F.getParagraphElement(g);runtime.assert(Boolean(c),
+"DirectFormattingController: Cursor outside paragraph");var m;a:{m=c;var l=gui.SelectionMover.createPositionIterator(m),k=new core.PositionFilterChain;k.addFilter(F.getPositionFilter());k.addFilter(F.createRootFilter(h));for(l.setUnfilteredPosition(e.endContainer,e.endOffset);l.nextPosition();)if(k.acceptPosition(l)===W){m=F.getParagraphElement(l.getCurrentNode())!==m;break a}m=!0}if(!m)return d;g!==f&&(c=F.getParagraphElement(f));if(!H&&!J(e,c))return d;e=T[0];if(!e)return d;if(f=c.getAttributeNS(Q,
+"style-name"))e={"style:text-properties":e["style:text-properties"]},e=F.getFormatting().createDerivedStyleObject(f,"paragraph",e);c=b.generateStyleName();f=new ops.OpAddStyle;f.init({memberid:h,styleName:c,styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:e});d.push(f);f=new ops.OpSetParagraphStyle;f.init({memberid:h,styleName:c,position:a});d.push(f);return d};this.subscribe=function(a,b){Z.subscribe(a,b)};this.unsubscribe=function(a,b){Z.unsubscribe(a,b)};this.destroy=function(a){F.unsubscribe(ops.Document.signalCursorAdded,
+q);F.unsubscribe(ops.Document.signalCursorRemoved,q);F.unsubscribe(ops.Document.signalCursorMoved,q);F.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,r);F.unsubscribe(ops.OdtDocument.signalParagraphChanged,l);F.unsubscribe(ops.OdtDocument.signalOperationEnd,m);a()};(function(){F.subscribe(ops.Document.signalCursorAdded,q);F.subscribe(ops.Document.signalCursorRemoved,q);F.subscribe(ops.Document.signalCursorMoved,q);F.subscribe(ops.OdtDocument.signalParagraphStyleModified,r);F.subscribe(ops.OdtDocument.signalParagraphChanged,
+l);F.subscribe(ops.OdtDocument.signalOperationEnd,m);g();p||(D.alignParagraphCenter=G,D.alignParagraphJustified=G,D.alignParagraphLeft=G,D.alignParagraphRight=G,D.createParagraphStyleOps=function(){return[]},D.indent=G,D.outdent=G)})()};gui.DirectFormattingController.textStylingChanged="textStyling/changed";gui.DirectFormattingController.paragraphStylingChanged="paragraphStyling/changed";(function(){return gui.DirectFormattingController})();
+// Input 82
+gui.HyperlinkClickHandler=function(k){function h(){k().removeAttributeNS("urn:webodf:names:helper","links")}function b(){k().setAttributeNS("urn:webodf:names:helper","links","inactive")}var p=gui.HyperlinkClickHandler.Modifier.None,d=gui.HyperlinkClickHandler.Modifier.Ctrl,n=gui.HyperlinkClickHandler.Modifier.Meta,g=new odf.OdfUtils,q=xmldom.XPath,r=p;this.handleClick=function(b){var f=b.target||b.srcElement,c,a;b.ctrlKey?c=d:b.metaKey&&(c=n);if(r===p||r===c){a:{for(;null!==f;){if(g.isHyperlink(f))break a;
+if(g.isParagraph(f))break;f=f.parentNode}f=null}f&&(f=g.getHyperlinkTarget(f),""!==f&&("#"===f[0]?(f=f.substring(1),c=k(),a=q.getODFElementsWithXPath(c,"//text:bookmark-start[@text:name='"+f+"']",odf.Namespaces.lookupNamespaceURI),0===a.length&&(a=q.getODFElementsWithXPath(c,"//text:bookmark[@text:name='"+f+"']",odf.Namespaces.lookupNamespaceURI)),0<a.length&&a[0].scrollIntoView(!0)):runtime.getWindow().open(f),b.preventDefault?b.preventDefault():b.returnValue=!1))}};this.showPointerCursor=h;this.showTextCursor=
+b;this.setModifier=function(d){r=d;r!==p?b():h()}};gui.HyperlinkClickHandler.Modifier={None:0,Ctrl:1,Meta:2};
// Input 83
+gui.HyperlinkController=function(k,h){var b=new odf.OdfUtils,p=k.getOdtDocument();this.addHyperlink=function(b,n){var g=p.getCursorSelection(h),q=new ops.OpApplyHyperlink,r=[];if(0===g.length||n)n=n||b,q=new ops.OpInsertText,q.init({memberid:h,position:g.position,text:n}),g.length=n.length,r.push(q);q=new ops.OpApplyHyperlink;q.init({memberid:h,position:g.position,length:g.length,hyperlink:b});r.push(q);k.enqueue(r)};this.removeHyperlinks=function(){var d=gui.SelectionMover.createPositionIterator(p.getRootNode()),
+n=p.getCursor(h).getSelectedRange(),g=b.getHyperlinkElements(n),q=n.collapsed&&1===g.length,r=p.getDOMDocument().createRange(),l=[],f,c;0!==g.length&&(g.forEach(function(a){r.selectNodeContents(a);f=p.convertDomToCursorRange({anchorNode:r.startContainer,anchorOffset:r.startOffset,focusNode:r.endContainer,focusOffset:r.endOffset});c=new ops.OpRemoveHyperlink;c.init({memberid:h,position:f.position,length:f.length});l.push(c)}),q||(q=g[0],-1===n.comparePoint(q,0)&&(r.setStart(q,0),r.setEnd(n.startContainer,
+n.startOffset),f=p.convertDomToCursorRange({anchorNode:r.startContainer,anchorOffset:r.startOffset,focusNode:r.endContainer,focusOffset:r.endOffset}),0<f.length&&(c=new ops.OpApplyHyperlink,c.init({memberid:h,position:f.position,length:f.length,hyperlink:b.getHyperlinkTarget(q)}),l.push(c))),g=g[g.length-1],d.moveToEndOfNode(g),d=d.unfilteredDomOffset(),1===n.comparePoint(g,d)&&(r.setStart(n.endContainer,n.endOffset),r.setEnd(g,d),f=p.convertDomToCursorRange({anchorNode:r.startContainer,anchorOffset:r.startOffset,
+focusNode:r.endContainer,focusOffset:r.endOffset}),0<f.length&&(c=new ops.OpApplyHyperlink,c.init({memberid:h,position:f.position,length:f.length,hyperlink:b.getHyperlinkTarget(g)}),l.push(c)))),k.enqueue(l),r.detach())}};
+// Input 84
+gui.EventManager=function(k){function h(){var a=this,b=[];this.filters=[];this.handlers=[];this.handleEvent=function(c){-1===b.indexOf(c)&&(b.push(c),a.filters.every(function(a){return a(c)})&&a.handlers.forEach(function(a){a(c)}),runtime.setTimeout(function(){b.splice(b.indexOf(c),1)},0))}}function b(a){var b=a.scrollX,c=a.scrollY;this.restore=function(){a.scrollX===b&&a.scrollY===c||a.scrollTo(b,c)}}function p(a){var b=a.scrollTop,c=a.scrollLeft;this.restore=function(){if(a.scrollTop!==b||a.scrollLeft!==
+c)a.scrollTop=b,a.scrollLeft=c}}function d(a,b,c){var d="on"+b,f=!1;a.attachEvent&&(a.attachEvent(d,c),f=!0);!f&&a.addEventListener&&(a.addEventListener(b,c,!1),f=!0);f&&!l[b]||!a.hasOwnProperty(d)||(a[d]=c)}function n(b,g){var l=c[b]||null;!l&&g&&(l=c[b]=new h,f[b]&&d(r,b,l.handleEvent),d(a,b,l.handleEvent),d(m,b,l.handleEvent));return l}function g(){return k.getDOMDocument().activeElement===a}function q(a){for(var c=[];a;)(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight)&&c.push(new p(a)),
+a=a.parentNode;c.push(new b(r));return c}var r=runtime.getWindow(),l={beforecut:!0,beforepaste:!0},f={mousedown:!0,mouseup:!0,focus:!0},c={},a,m=k.getCanvas().getElement();this.addFilter=function(a,b){n(a,!0).filters.push(b)};this.removeFilter=function(a,b){var c=n(a,!0),d=c.filters.indexOf(b);-1!==d&&c.filters.splice(d,1)};this.subscribe=function(a,b){n(a,!0).handlers.push(b)};this.unsubscribe=function(a,b){var c=n(a,!1),d=c&&c.handlers.indexOf(b);c&&-1!==d&&c.handlers.splice(d,1)};this.hasFocus=
+g;this.focus=function(){var b;g()||(b=q(a),a.focus(),b.forEach(function(a){a.restore()}))};this.getEventTrap=function(){return a};this.blur=function(){g()&&a.blur()};this.destroy=function(b){a.parentNode.removeChild(a);b()};(function(){var b=k.getOdfCanvas().getSizer(),c=b.ownerDocument;runtime.assert(Boolean(r),"EventManager requires a window object to operate correctly");a=c.createElement("input");a.id="eventTrap";a.setAttribute("tabindex",-1);b.appendChild(a)})()};
+// Input 85
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
@licstart
This file is part of WebODF.
@@ -2472,59 +2680,68 @@ ops.OperationRouter=function(){};ops.OperationRouter.prototype.setOperationFacto
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.OperationTransformMatrix=function(){function g(a){a.position+=a.length;a.length*=-1}function l(a){var b=0>a.length;b&&g(a);return b}function f(a,b){var c=[];a&&["style:parent-style-name","style:next-style-name"].forEach(function(d){a[d]===b&&c.push(d)});return c}function p(a,b){a&&["style:parent-style-name","style:next-style-name"].forEach(function(c){a[c]===b&&delete a[c]})}function r(a){var b={};Object.keys(a).forEach(function(c){b[c]="object"===typeof a[c]?r(a[c]):a[c]});return b}function n(a,
-b,c,d){var e,f,h=!1,g=!1,l,m,n=d&&d.attributes?d.attributes.split(","):[];a&&(c||0<n.length)&&Object.keys(a).forEach(function(b){e=a[b];"object"!==typeof e&&(l=c&&c[b],void 0!==l?(delete a[b],g=!0,l===e&&(delete c[b],h=!0)):n&&-1!==n.indexOf(b)&&(delete a[b],g=!0))});if(b&&b.attributes&&(c||0<n.length)){m=b.attributes.split(",");for(d=0;d<m.length;d+=1)if(f=m[d],c&&void 0!==c[f]||n&&-1!==n.indexOf(f))m.splice(d,1),d-=1,g=!0;0<m.length?b.attributes=m.join(","):delete b.attributes}return{majorChanged:h,
-minorChanged:g}}function h(a){for(var b in a)if(a.hasOwnProperty(b))return!0;return!1}function d(a){for(var b in a)if(a.hasOwnProperty(b)&&("attributes"!==b||0<a.attributes.length))return!0;return!1}function m(a,b,c){var e=a.setProperties?a.setProperties[c]:null,f=a.removedProperties?a.removedProperties[c]:null,g=b.setProperties?b.setProperties[c]:null,l=b.removedProperties?b.removedProperties[c]:null,m;m=n(e,f,g,l);e&&!h(e)&&delete a.setProperties[c];f&&!d(f)&&delete a.removedProperties[c];g&&!h(g)&&
-delete b.setProperties[c];l&&!d(l)&&delete b.removedProperties[c];return m}function c(a,b){return{opSpecsA:[a],opSpecsB:[b]}}var e={AddCursor:{AddCursor:c,AddMember:c,AddStyle:c,ApplyDirectStyling:c,InsertText:c,MoveCursor:c,RemoveCursor:c,RemoveMember:c,RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},AddMember:{AddStyle:c,InsertText:c,MoveCursor:c,RemoveCursor:c,RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitParagraph:c,
-UpdateMetadata:c,UpdateParagraphStyle:c},AddStyle:{AddStyle:c,ApplyDirectStyling:c,InsertText:c,MoveCursor:c,RemoveCursor:c,RemoveMember:c,RemoveStyle:function(a,b){var c,d=[a],e=[b];a.styleFamily===b.styleFamily&&(c=f(a.setProperties,b.styleName),0<c.length&&(c={optype:"UpdateParagraphStyle",memberid:b.memberid,timestamp:b.timestamp,styleName:a.styleName,removedProperties:{attributes:c.join(",")}},e.unshift(c)),p(a.setProperties,b.styleName));return{opSpecsA:d,opSpecsB:e}},RemoveText:c,SetParagraphStyle:c,
-SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},ApplyDirectStyling:{ApplyDirectStyling:function(a,b,c){var d,e,f,g,l,n,p,s;g=[a];f=[b];if(!(a.position+a.length<=b.position||a.position>=b.position+b.length)){d=c?a:b;e=c?b:a;if(a.position!==b.position||a.length!==b.length)n=r(d),p=r(e);b=m(e,d,"style:text-properties");if(b.majorChanged||b.minorChanged)f=[],a=[],g=d.position+d.length,l=e.position+e.length,e.position<d.position?b.minorChanged&&(s=r(p),s.length=d.position-e.position,
-a.push(s),e.position=d.position,e.length=l-e.position):d.position<e.position&&b.majorChanged&&(s=r(n),s.length=e.position-d.position,f.push(s),d.position=e.position,d.length=g-d.position),l>g?b.minorChanged&&(n=p,n.position=g,n.length=l-g,a.push(n),e.length=g-e.position):g>l&&b.majorChanged&&(n.position=l,n.length=g-l,f.push(n),d.length=l-d.position),d.setProperties&&h(d.setProperties)&&f.push(d),e.setProperties&&h(e.setProperties)&&a.push(e),c?(g=f,f=a):g=a}return{opSpecsA:g,opSpecsB:f}},InsertText:function(a,
-b){b.position<=a.position?a.position+=b.text.length:b.position<=a.position+a.length&&(a.length+=b.text.length);return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:c,RemoveCursor:c,RemoveStyle:c,RemoveText:function(a,b){var c=a.position+a.length,d=b.position+b.length,e=[a],f=[b];d<=a.position?a.position-=b.length:b.position<c&&(a.position<b.position?a.length=d<c?a.length-b.length:b.position-a.position:(a.position=b.position,d<c?a.length=c-d:e=[]));return{opSpecsA:e,opSpecsB:f}},SetParagraphStyle:c,SplitParagraph:function(a,
-b){b.position<a.position?a.position+=1:b.position<a.position+a.length&&(a.length+=1);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMetadata:c,UpdateParagraphStyle:c},InsertText:{InsertText:function(a,b,c){a.position<b.position?b.position+=a.text.length:a.position>b.position?a.position+=b.text.length:c?b.position+=a.text.length:a.position+=b.text.length;return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:function(a,b){var c=l(b);a.position<b.position?b.position+=a.text.length:a.position<b.position+b.length&&
-(b.length+=a.text.length);c&&g(b);return{opSpecsA:[a],opSpecsB:[b]}},RemoveCursor:c,RemoveMember:c,RemoveStyle:c,RemoveText:function(a,b){var c;c=b.position+b.length;var d=[a],e=[b];c<=a.position?a.position-=b.length:a.position<=b.position?b.position+=a.text.length:(b.length=a.position-b.position,c={optype:"RemoveText",memberid:b.memberid,timestamp:b.timestamp,position:a.position+a.text.length,length:c-a.position},e.unshift(c),a.position=b.position);return{opSpecsA:d,opSpecsB:e}},SplitParagraph:function(a,
-b,c){if(a.position<b.position)b.position+=a.text.length;else if(a.position>b.position)a.position+=1;else return c?b.position+=a.text.length:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},MoveCursor:{MoveCursor:c,RemoveCursor:function(a,b){return{opSpecsA:a.memberid===b.memberid?[]:[a],opSpecsB:[b]}},RemoveMember:c,RemoveStyle:c,RemoveText:function(a,b){var c=l(a),d=a.position+a.length,e=b.position+b.length;e<=a.position?a.position-=b.length:
-b.position<d&&(a.position<b.position?a.length=e<d?a.length-b.length:b.position-a.position:(a.position=b.position,a.length=e<d?d-e:0));c&&g(a);return{opSpecsA:[a],opSpecsB:[b]}},SetParagraphStyle:c,SplitParagraph:function(a,b){var c=l(a);b.position<a.position?a.position+=1:b.position<a.position+a.length&&(a.length+=1);c&&g(a);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},RemoveCursor:{RemoveCursor:function(a,b){var c=a.memberid===b.memberid;return{opSpecsA:c?
-[]:[a],opSpecsB:c?[]:[b]}},RemoveMember:c,RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},RemoveMember:{RemoveStyle:c,RemoveText:c,SetParagraphStyle:c,SplitParagraph:c,UpdateMetadata:c,UpdateParagraphStyle:c},RemoveStyle:{RemoveStyle:function(a,b){var c=a.styleName===b.styleName&&a.styleFamily===b.styleFamily;return{opSpecsA:c?[]:[a],opSpecsB:c?[]:[b]}},RemoveText:c,SetParagraphStyle:function(a,b){var c,d=[a],e=[b];"paragraph"===
-a.styleFamily&&a.styleName===b.styleName&&(c={optype:"SetParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,position:b.position,styleName:""},d.unshift(c),b.styleName="");return{opSpecsA:d,opSpecsB:e}},SplitParagraph:c,UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:function(a,b){var c,d=[a],e=[b];"paragraph"===a.styleFamily&&(c=f(b.setProperties,a.styleName),0<c.length&&(c={optype:"UpdateParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,styleName:b.styleName,removedProperties:{attributes:c.join(",")}},
-d.unshift(c)),a.styleName===b.styleName?e=[]:p(b.setProperties,a.styleName));return{opSpecsA:d,opSpecsB:e}}},RemoveText:{RemoveText:function(a,b){var c=a.position+a.length,d=b.position+b.length,e=[a],f=[b];d<=a.position?a.position-=b.length:c<=b.position?b.position-=a.length:b.position<c&&(a.position<b.position?(a.length=d<c?a.length-b.length:b.position-a.position,c<d?(b.position=a.position,b.length=d-c):f=[]):(c<d?b.length-=a.length:b.position<a.position?b.length=a.position-b.position:f=[],d<c?(a.position=
-b.position,a.length=c-d):e=[]));return{opSpecsA:e,opSpecsB:f}},SplitParagraph:function(a,b){var c=a.position+a.length,d=[a],e=[b];b.position<=a.position?a.position+=1:b.position<c&&(a.length=b.position-a.position,c={optype:"RemoveText",memberid:a.memberid,timestamp:a.timestamp,position:b.position+1,length:c-b.position},d.unshift(c));a.position+a.length<=b.position?b.position-=a.length:a.position<b.position&&(b.position=a.position);return{opSpecsA:d,opSpecsB:e}},UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},
-SetParagraphStyle:{UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},SplitParagraph:{SplitParagraph:function(a,b,c){a.position<b.position?b.position+=1:a.position>b.position?a.position+=1:a.position===b.position&&(c?b.position+=1:a.position+=1);return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:c,UpdateMetadata:c,UpdateParagraphStyle:c},UpdateMember:{UpdateMetadata:c,UpdateParagraphStyle:c},UpdateMetadata:{UpdateMetadata:function(a,b,c){var e,f=[a],g=[b];e=c?a:b;a=c?b:a;n(a.setProperties||null,
-a.removedProperties||null,e.setProperties||null,e.removedProperties||null);e.setProperties&&h(e.setProperties)||e.removedProperties&&d(e.removedProperties)||(c?f=[]:g=[]);a.setProperties&&h(a.setProperties)||a.removedProperties&&d(a.removedProperties)||(c?g=[]:f=[]);return{opSpecsA:f,opSpecsB:g}},UpdateParagraphStyle:c},UpdateParagraphStyle:{UpdateParagraphStyle:function(a,b,c){var e,f=[a],g=[b];a.styleName===b.styleName&&(e=c?a:b,a=c?b:a,m(a,e,"style:paragraph-properties"),m(a,e,"style:text-properties"),
-n(a.setProperties||null,a.removedProperties||null,e.setProperties||null,e.removedProperties||null),e.setProperties&&h(e.setProperties)||e.removedProperties&&d(e.removedProperties)||(c?f=[]:g=[]),a.setProperties&&h(a.setProperties)||a.removedProperties&&d(a.removedProperties)||(c?g=[]:f=[]));return{opSpecsA:f,opSpecsB:g}}}};this.passUnchanged=c;this.extendTransformations=function(a){Object.keys(a).forEach(function(b){var c=a[b],d,f=e.hasOwnProperty(b);runtime.log((f?"Extending":"Adding")+" map for optypeA: "+
-b);f||(e[b]={});d=e[b];Object.keys(c).forEach(function(a){var e=d.hasOwnProperty(a);runtime.assert(b<=a,"Wrong order:"+b+", "+a);runtime.log(" "+(e?"Overwriting":"Adding")+" entry for optypeB: "+a);d[a]=c[a]})})};this.transformOpspecVsOpspec=function(a,b){var c=a.optype<=b.optype,d;runtime.log("Crosstransforming:");runtime.log(runtime.toJson(a));runtime.log(runtime.toJson(b));c||(d=a,a=b,b=d);(d=(d=e[a.optype])&&d[b.optype])?(d=d(a,b,!c),c||null===d||(d={opSpecsA:d.opSpecsB,opSpecsB:d.opSpecsA})):
-d=null;runtime.log("result:");d?(runtime.log(runtime.toJson(d.opSpecsA)),runtime.log(runtime.toJson(d.opSpecsB))):runtime.log("null");return d}};
-// Input 84
+gui.IOSSafariSupport=function(k){function h(){b.innerHeight!==b.outerHeight&&(p.style.display="none",runtime.requestAnimationFrame(function(){p.style.display="block"}))}var b=runtime.getWindow(),p=k.getEventTrap();this.destroy=function(b){k.unsubscribe("focus",h);p.removeAttribute("autocapitalize");b()};k.subscribe("focus",h);p.setAttribute("autocapitalize","off")};
+// Input 86
+gui.ImageController=function(k,h,b){var p={"image/gif":".gif","image/jpeg":".jpg","image/png":".png"},d=odf.Namespaces.textns,n=k.getOdtDocument(),g=n.getFormatting(),q={};this.insertImage=function(r,l,f,c){var a;runtime.assert(0<f&&0<c,"Both width and height of the image should be greater than 0px.");a=n.getParagraphElement(n.getCursor(h).getNode()).getAttributeNS(d,"style-name");q.hasOwnProperty(a)||(q[a]=g.getContentSize(a,"paragraph"));a=q[a];f*=0.0264583333333334;c*=0.0264583333333334;var m=
+1,e=1;f>a.width&&(m=a.width/f);c>a.height&&(e=a.height/c);m=Math.min(m,e);a=f*m;f=c*m;e=n.getOdfCanvas().odfContainer().rootElement.styles;c=r.toLowerCase();var m=p.hasOwnProperty(c)?p[c]:null,t;c=[];runtime.assert(null!==m,"Image type is not supported: "+r);m="Pictures/"+b.generateImageName()+m;t=new ops.OpSetBlob;t.init({memberid:h,filename:m,mimetype:r,content:l});c.push(t);g.getStyleElement("Graphics","graphic",[e])||(r=new ops.OpAddStyle,r.init({memberid:h,styleName:"Graphics",styleFamily:"graphic",
+isAutomaticStyle:!1,setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph","svg:x":"0cm","svg:y":"0cm","style:wrap":"dynamic","style:number-wrapped-paragraphs":"no-limit","style:wrap-contour":"false","style:vertical-pos":"top","style:vertical-rel":"paragraph","style:horizontal-pos":"center","style:horizontal-rel":"paragraph"}}}),c.push(r));r=b.generateStyleName();l=new ops.OpAddStyle;l.init({memberid:h,styleName:r,styleFamily:"graphic",isAutomaticStyle:!0,setProperties:{"style:parent-style-name":"Graphics",
+"style:graphic-properties":{"style:vertical-pos":"top","style:vertical-rel":"baseline","style:horizontal-pos":"center","style:horizontal-rel":"paragraph","fo:background-color":"transparent","style:background-transparency":"100%","style:shadow":"none","style:mirror":"none","fo:clip":"rect(0cm, 0cm, 0cm, 0cm)","draw:luminance":"0%","draw:contrast":"0%","draw:red":"0%","draw:green":"0%","draw:blue":"0%","draw:gamma":"100%","draw:color-inversion":"false","draw:image-opacity":"100%","draw:color-mode":"standard"}}});
+c.push(l);t=new ops.OpInsertImage;t.init({memberid:h,position:n.getCursorPosition(h),filename:m,frameWidth:a+"cm",frameHeight:f+"cm",frameStyleName:r,frameName:b.generateFrameName()});c.push(t);k.enqueue(c)}};
+// Input 87
+gui.ImageSelector=function(k){function h(){var b=k.getSizer(),h=d.createElement("div");h.id="imageSelector";h.style.borderWidth="1px";b.appendChild(h);p.forEach(function(b){var g=d.createElement("div");g.className=b;h.appendChild(g)});return h}var b=odf.Namespaces.svgns,p="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),d=k.getElement().ownerDocument,n=!1;this.select=function(g){var p,r,l=d.getElementById("imageSelector");l||(l=h());n=!0;p=l.parentNode;
+r=g.getBoundingClientRect();var f=p.getBoundingClientRect(),c=k.getZoomLevel();p=(r.left-f.left)/c-1;r=(r.top-f.top)/c-1;l.style.display="block";l.style.left=p+"px";l.style.top=r+"px";l.style.width=g.getAttributeNS(b,"width");l.style.height=g.getAttributeNS(b,"height")};this.clearSelection=function(){var b;n&&(b=d.getElementById("imageSelector"))&&(b.style.display="none");n=!1};this.isSelectorElement=function(b){var h=d.getElementById("imageSelector");return h?b===h||b.parentNode===h:!1}};
+// Input 88
+(function(){function k(h){function b(b){g=b.which&&String.fromCharCode(b.which)===n;n=void 0;return!1===g}function k(){g=!1}function d(b){n=b.data;g=!1}var n,g=!1;this.destroy=function(g){h.unsubscribe("textInput",k);h.unsubscribe("compositionend",d);h.removeFilter("keypress",b);g()};h.subscribe("textInput",k);h.subscribe("compositionend",d);h.addFilter("keypress",b)}gui.InputMethodEditor=function(h,b){function p(b){m&&(b?m.getNode().setAttributeNS(a,"composing","true"):(m.getNode().removeAttributeNS(a,
+"composing"),w.textContent=""))}function d(){u&&(u=!1,p(!1),A.emit(gui.InputMethodEditor.signalCompositionEnd,{data:s}),s="")}function n(){d();m&&m.getSelectedRange().collapsed?e.value="":e.value=x;e.setSelectionRange(0,e.value.length)}function g(){J=void 0;v.cancel();p(!0);u||A.emit(gui.InputMethodEditor.signalCompositionStart,{data:""})}function q(a){a=J=a.data;u=!0;s+=a;v.trigger()}function r(a){a.data!==J&&(a=a.data,u=!0,s+=a,v.trigger());J=void 0}function l(){w.textContent=e.value}function f(){b.blur();
+e.setAttribute("disabled",!0)}function c(){var a=b.hasFocus();a&&b.blur();F?e.removeAttribute("disabled"):e.setAttribute("disabled",!0);a&&b.focus()}var a="urn:webodf:names:cursor",m=null,e=b.getEventTrap(),t=e.ownerDocument,w,z=new core.Async,x="b",v,u=!1,s="",A=new core.EventNotifier([gui.InputMethodEditor.signalCompositionStart,gui.InputMethodEditor.signalCompositionEnd]),J,G=[],D,F=!1;this.subscribe=A.subscribe;this.unsubscribe=A.unsubscribe;this.registerCursor=function(a){a.getMemberId()===h&&
+(m=a,m.getNode().appendChild(w),b.subscribe("input",l),b.subscribe("compositionupdate",l))};this.removeCursor=function(a){m&&a===h&&(m.getNode().removeChild(w),b.unsubscribe("input",l),b.unsubscribe("compositionupdate",l),m=null)};this.setEditing=function(a){F=a;c()};this.destroy=function(a){b.unsubscribe("compositionstart",g);b.unsubscribe("compositionend",q);b.unsubscribe("textInput",r);b.unsubscribe("keypress",d);b.unsubscribe("mousedown",f);b.unsubscribe("mouseup",c);b.unsubscribe("focus",n);
+z.destroyAll(D,a)};(function(){b.subscribe("compositionstart",g);b.subscribe("compositionend",q);b.subscribe("textInput",r);b.subscribe("keypress",d);b.subscribe("mousedown",f);b.subscribe("mouseup",c);b.subscribe("focus",n);G.push(new k(b));D=G.map(function(a){return a.destroy});w=t.createElement("span");w.setAttribute("id","composer");v=new core.ScheduledTask(n,1);D.push(v.destroy)})()};gui.InputMethodEditor.signalCompositionStart="input/compositionstart";gui.InputMethodEditor.signalCompositionEnd=
+"input/compositionend";return gui.InputMethodEditor})();
+// Input 89
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
- This file is part of WebODF.
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+ This license applies to this entire compilation.
+ @licend
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.OperationFactory");runtime.loadClass("ops.OperationTransformMatrix");
-ops.OperationTransformer=function(){function g(g){var l=[];g.forEach(function(h){l.push(f.create(h))});return l}function l(f,g){for(var h,d,m=[],c=[];0<f.length&&g;){h=f.shift();h=p.transformOpspecVsOpspec(h,g);if(!h)return null;m=m.concat(h.opSpecsA);if(0===h.opSpecsB.length){m=m.concat(f);g=null;break}for(;1<h.opSpecsB.length;){d=l(f,h.opSpecsB.shift());if(!d)return null;c=c.concat(d.opSpecsB);f=d.opSpecsA}g=h.opSpecsB.pop()}g&&c.push(g);return{opSpecsA:m,opSpecsB:c}}var f,p=new ops.OperationTransformMatrix;
-this.setOperationFactory=function(g){f=g};this.getOperationTransformMatrix=function(){return p};this.transform=function(f,n){for(var h,d=[];0<n.length;){h=l(f,n.shift());if(!h)return null;f=h.opSpecsA;d=d.concat(h.opSpecsB)}return{opsA:g(f),opsB:g(d)}}};
-// Input 85
+gui.KeyboardHandler=function(){function k(b,k){k||(k=h.None);return b+":"+k}var h=gui.KeyboardHandler.Modifier,b=null,p={};this.setDefault=function(d){b=d};this.bind=function(b,h,g,q){b=k(b,h);runtime.assert(q||!1===p.hasOwnProperty(b),"tried to overwrite the callback handler of key combo: "+b);p[b]=g};this.unbind=function(b,h){var g=k(b,h);delete p[g]};this.reset=function(){b=null;p={}};this.handleEvent=function(d){var n=d.keyCode,g=h.None;d.metaKey&&(g|=h.Meta);d.ctrlKey&&(g|=h.Ctrl);d.altKey&&
+(g|=h.Alt);d.shiftKey&&(g|=h.Shift);n=k(n,g);n=p[n];g=!1;n?g=n():null!==b&&(g=b(d));g&&(d.preventDefault?d.preventDefault():d.returnValue=!1)}};gui.KeyboardHandler.Modifier={None:0,Meta:1,Ctrl:2,Alt:4,CtrlAlt:6,Shift:8,MetaShift:9,CtrlShift:10,AltShift:12};
+gui.KeyboardHandler.KeyCode={Backspace:8,Tab:9,Clear:12,Enter:13,Ctrl:17,End:35,Home:36,Left:37,Up:38,Right:39,Down:40,Delete:46,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,LeftMeta:91,MetaInMozilla:224};(function(){return gui.KeyboardHandler})();
+// Input 90
/*
- Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2559,11 +2776,11 @@ this.setOperationFactory=function(g){f=g};this.getOperationTransformMatrix=funct
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-ops.TrivialOperationRouter=function(){var g,l;this.setOperationFactory=function(f){g=f};this.setPlaybackFunction=function(f){l=f};this.push=function(f){f.forEach(function(f){f=f.spec();f.timestamp=(new Date).getTime();f=g.create(f);l(f)})};this.close=function(f){f()};this.subscribe=function(f,g){};this.unsubscribe=function(f,g){};this.hasLocalUnsyncedOps=function(){return!1};this.hasSessionHostConnection=function(){return!0}};
-// Input 86
+gui.PlainTextPasteboard=function(k,h){function b(b,d){b.init(d);return b}this.createPasteOps=function(p){var d=k.getCursorPosition(h),n=d,g=[];p.replace(/\r/g,"").split("\n").forEach(function(d){g.push(b(new ops.OpSplitParagraph,{memberid:h,position:n,moveCursor:!0}));n+=1;g.push(b(new ops.OpInsertText,{memberid:h,position:n,text:d,moveCursor:!0}));n+=d.length});g.push(b(new ops.OpRemoveText,{memberid:h,position:d,length:1}));return g}};
+// Input 91
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2014 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2598,11 +2815,25 @@ ops.TrivialOperationRouter=function(){var g,l;this.setOperationFactory=function(
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.EditInfo");runtime.loadClass("gui.EditInfoHandle");
-gui.EditInfoMarker=function(g,l){function f(c,d){return runtime.setTimeout(function(){h.style.opacity=c},d)}var p=this,r,n,h,d,m;this.addEdit=function(c,e){var a=Date.now()-e;g.addEdit(c,e);n.setEdits(g.getSortedEdits());h.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",c);d&&runtime.clearTimeout(d);m&&runtime.clearTimeout(m);1E4>a?(f(1,0),d=f(0.5,1E4-a),m=f(0.2,2E4-a)):1E4<=a&&2E4>a?(f(0.5,0),m=f(0.2,2E4-a)):f(0.2,0)};this.getEdits=function(){return g.getEdits()};this.clearEdits=function(){g.clearEdits();
-n.setEdits([]);h.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&h.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return g};this.show=function(){h.style.display="block"};this.hide=function(){p.hideHandle();h.style.display="none"};this.showHandle=function(){n.show()};this.hideHandle=function(){n.hide()};this.destroy=function(c){r.removeChild(h);n.destroy(function(d){d?c(d):g.destroy(c)})};(function(){var c=g.getOdtDocument().getDOM();
-h=c.createElementNS(c.documentElement.namespaceURI,"div");h.setAttribute("class","editInfoMarker");h.onmouseover=function(){p.showHandle()};h.onmouseout=function(){p.hideHandle()};r=g.getNode();r.appendChild(h);n=new gui.EditInfoHandle(r);l||p.hide()})()};
-// Input 87
+odf.WordBoundaryFilter=function(k,h){function b(a,b,c){for(var d=null,f=k.getRootNode(),g;a!==f&&null!==a&&null===d;)g=0>b?a.previousSibling:a.nextSibling,c(g)===NodeFilter.FILTER_ACCEPT&&(d=g),a=a.parentNode;return d}function p(a,b){var c;return null===a?m.NO_NEIGHBOUR:g.isCharacterElement(a)?m.SPACE_CHAR:a.nodeType===d||g.isTextSpan(a)||g.isHyperlink(a)?(c=a.textContent.charAt(b()),r.test(c)?m.SPACE_CHAR:q.test(c)?m.PUNCTUATION_CHAR:m.WORD_CHAR):m.OTHER}var d=Node.TEXT_NODE,n=Node.ELEMENT_NODE,
+g=new odf.OdfUtils,q=/[!-#%-*,-\/:-;?-@\[-\]_{}\u00a1\u00ab\u00b7\u00bb\u00bf;\u00b7\u055a-\u055f\u0589-\u058a\u05be\u05c0\u05c3\u05c6\u05f3-\u05f4\u0609-\u060a\u060c-\u060d\u061b\u061e-\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0964-\u0965\u0970\u0df4\u0e4f\u0e5a-\u0e5b\u0f04-\u0f12\u0f3a-\u0f3d\u0f85\u0fd0-\u0fd4\u104a-\u104f\u10fb\u1361-\u1368\u166d-\u166e\u169b-\u169c\u16eb-\u16ed\u1735-\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u180a\u1944-\u1945\u19de-\u19df\u1a1e-\u1a1f\u1b5a-\u1b60\u1c3b-\u1c3f\u1c7e-\u1c7f\u2000-\u206e\u207d-\u207e\u208d-\u208e\u3008-\u3009\u2768-\u2775\u27c5-\u27c6\u27e6-\u27ef\u2983-\u2998\u29d8-\u29db\u29fc-\u29fd\u2cf9-\u2cfc\u2cfe-\u2cff\u2e00-\u2e7e\u3000-\u303f\u30a0\u30fb\ua60d-\ua60f\ua673\ua67e\ua874-\ua877\ua8ce-\ua8cf\ua92e-\ua92f\ua95f\uaa5c-\uaa5f\ufd3e-\ufd3f\ufe10-\ufe19\ufe30-\ufe52\ufe54-\ufe61\ufe63\ufe68\ufe6a-\ufe6b\uff01-\uff03\uff05-\uff0a\uff0c-\uff0f\uff1a-\uff1b\uff1f-\uff20\uff3b-\uff3d\uff3f\uff5b\uff5d\uff5f-\uff65]|\ud800[\udd00-\udd01\udf9f\udfd0]|\ud802[\udd1f\udd3f\ude50-\ude58]|\ud809[\udc00-\udc7e]/,
+r=/\s/,l=core.PositionFilter.FilterResult.FILTER_ACCEPT,f=core.PositionFilter.FilterResult.FILTER_REJECT,c=odf.WordBoundaryFilter.IncludeWhitespace.TRAILING,a=odf.WordBoundaryFilter.IncludeWhitespace.LEADING,m={NO_NEIGHBOUR:0,SPACE_CHAR:1,PUNCTUATION_CHAR:2,WORD_CHAR:3,OTHER:4};this.acceptPosition=function(e){var d=e.container(),g=e.leftNode(),k=e.rightNode(),q=e.unfilteredDomOffset,r=function(){return e.unfilteredDomOffset()-1};d.nodeType===n&&(null===k&&(k=b(d,1,e.getNodeFilter())),null===g&&(g=
+b(d,-1,e.getNodeFilter())));d!==k&&(q=function(){return 0});d!==g&&null!==g&&(r=function(){return g.textContent.length-1});d=p(g,r);k=p(k,q);return d===m.WORD_CHAR&&k===m.WORD_CHAR||d===m.PUNCTUATION_CHAR&&k===m.PUNCTUATION_CHAR||h===c&&d!==m.NO_NEIGHBOUR&&k===m.SPACE_CHAR||h===a&&d===m.SPACE_CHAR&&k!==m.NO_NEIGHBOUR?f:l}};odf.WordBoundaryFilter.IncludeWhitespace={None:0,TRAILING:1,LEADING:2};(function(){return odf.WordBoundaryFilter})();
+// Input 92
+gui.SelectionController=function(k,h){function b(){var a=x.getCursor(h).getNode();return x.createStepIterator(a,0,[s,J],x.getRootElement(a))}function p(a,b,c){c=new odf.WordBoundaryFilter(x,c);return x.createStepIterator(a,b,[s,J,c],x.getRootElement(a))}function d(a){return function(b){var c=a(b);return function(b,d){return a(d)===c}}}function n(a,b){return b?{anchorNode:a.startContainer,anchorOffset:a.startOffset,focusNode:a.endContainer,focusOffset:a.endOffset}:{anchorNode:a.endContainer,anchorOffset:a.endOffset,
+focusNode:a.startContainer,focusOffset:a.startOffset}}function g(a,b,c){var d=new ops.OpMoveCursor;d.init({memberid:h,position:a,length:b||0,selectionType:c});return d}function q(a){var b;b=p(a.startContainer,a.startOffset,G);b.roundToPreviousStep()&&a.setStart(b.container(),b.offset());b=p(a.endContainer,a.endOffset,D);b.roundToNextStep()&&a.setEnd(b.container(),b.offset())}function r(a){var b=u.getParagraphElements(a),c=b[0],b=b[b.length-1];c&&a.setStart(c,0);b&&(u.isParagraph(a.endContainer)&&
+0===a.endOffset?a.setEndBefore(b):a.setEnd(b,b.childNodes.length))}function l(a){var b=x.getCursorSelection(h),c=x.getCursor(h).getStepCounter();0!==a&&(a=0<a?c.convertForwardStepsBetweenFilters(a,A,s):-c.convertBackwardStepsBetweenFilters(-a,A,s),a=b.length+a,k.enqueue([g(b.position,a)]))}function f(a){var c=b(),d=x.getCursor(h).getAnchorNode();a(c)&&(a=x.convertDomToCursorRange({anchorNode:d,anchorOffset:0,focusNode:c.container(),focusOffset:c.offset()}),k.enqueue([g(a.position,a.length)]))}function c(a){var b=
+x.getCursorPosition(h),c=x.getCursor(h).getStepCounter();0!==a&&(a=0<a?c.convertForwardStepsBetweenFilters(a,A,s):-c.convertBackwardStepsBetweenFilters(-a,A,s),k.enqueue([g(b+a,0)]))}function a(a){var c=b();a(c)&&(a=x.convertDomPointToCursorStep(c.container(),c.offset()),k.enqueue([g(a,0)]))}function m(a,b){var d=x.getParagraphElement(x.getCursor(h).getNode());runtime.assert(Boolean(d),"SelectionController: Cursor outside paragraph");d=x.getCursor(h).getStepCounter().countLinesSteps(a,A);b?l(d):c(d)}
+function e(a,b){var d=x.getCursor(h).getStepCounter().countStepsToLineBoundary(a,A);b?l(d):c(d)}function t(a,b){var c=x.getCursor(h),c=n(c.getSelectedRange(),c.hasForwardSelection()),d=p(c.focusNode,c.focusOffset,G);if(0<=a?d.nextStep():d.previousStep())c.focusNode=d.container(),c.focusOffset=d.offset(),b||(c.anchorNode=c.focusNode,c.anchorOffset=c.focusOffset),c=x.convertDomToCursorRange(c),k.enqueue([g(c.position,c.length)])}function w(a,b){var c=x.getCursor(h),e=b(c.getNode()),c=n(c.getSelectedRange(),
+c.hasForwardSelection());runtime.assert(Boolean(e),"SelectionController: Cursor outside root");0>a?(c.focusNode=e,c.focusOffset=0):(c.focusNode=e,c.focusOffset=e.childNodes.length);e=x.convertDomToCursorRange(c,d(b));k.enqueue([g(e.position,e.length)])}function z(a){var b=x.getCursor(h),b=x.getRootElement(b.getNode());runtime.assert(Boolean(b),"SelectionController: Cursor outside root");a=0>a?x.convertDomPointToCursorStep(b,0,function(a){return a===ops.StepsTranslator.NEXT_STEP}):x.convertDomPointToCursorStep(b,
+b.childNodes.length);k.enqueue([g(a,0)]);return!0}var x=k.getOdtDocument(),v=new core.DomUtils,u=new odf.OdfUtils,s=x.getPositionFilter(),A=new core.PositionFilterChain,J=x.createRootFilter(h),G=odf.WordBoundaryFilter.IncludeWhitespace.TRAILING,D=odf.WordBoundaryFilter.IncludeWhitespace.LEADING;this.selectionToRange=function(a){var b=0<=v.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset),c=a.focusNode.ownerDocument.createRange();b?(c.setStart(a.anchorNode,a.anchorOffset),c.setEnd(a.focusNode,
+a.focusOffset)):(c.setStart(a.focusNode,a.focusOffset),c.setEnd(a.anchorNode,a.anchorOffset));return{range:c,hasForwardSelection:b}};this.rangeToSelection=n;this.selectImage=function(a){var b=x.getRootElement(a),c=x.createRootFilter(b),b=x.createStepIterator(a,0,[c,x.getPositionFilter()],b),d;b.roundToPreviousStep()||runtime.assert(!1,"No walkable position before frame");c=b.container();d=b.offset();b.setPosition(a,a.childNodes.length);b.roundToNextStep()||runtime.assert(!1,"No walkable position after frame");
+a=x.convertDomToCursorRange({anchorNode:c,anchorOffset:d,focusNode:b.container(),focusOffset:b.offset()});a=g(a.position,a.length,ops.OdtCursor.RegionSelection);k.enqueue([a])};this.expandToWordBoundaries=q;this.expandToParagraphBoundaries=r;this.selectRange=function(a,b,c){var e=x.getOdfCanvas().getElement(),f;f=v.containsNode(e,a.startContainer);e=v.containsNode(e,a.endContainer);if(f||e)if(f&&e&&(2===c?q(a):3<=c&&r(a)),a=n(a,b),b=x.convertDomToCursorRange(a,d(u.getParagraphElement)),a=x.getCursorSelection(h),
+b.position!==a.position||b.length!==a.length)a=g(b.position,b.length,ops.OdtCursor.RangeSelection),k.enqueue([a])};this.moveCursorToLeft=function(){a(function(a){return a.previousStep()});return!0};this.moveCursorToRight=function(){a(function(a){return a.nextStep()});return!0};this.extendSelectionToLeft=function(){f(function(a){return a.previousStep()});return!0};this.extendSelectionToRight=function(){f(function(a){return a.nextStep()});return!0};this.moveCursorUp=function(){m(-1,!1);return!0};this.moveCursorDown=
+function(){m(1,!1);return!0};this.extendSelectionUp=function(){m(-1,!0);return!0};this.extendSelectionDown=function(){m(1,!0);return!0};this.moveCursorBeforeWord=function(){t(-1,!1);return!0};this.moveCursorPastWord=function(){t(1,!1);return!0};this.extendSelectionBeforeWord=function(){t(-1,!0);return!0};this.extendSelectionPastWord=function(){t(1,!0);return!0};this.moveCursorToLineStart=function(){e(-1,!1);return!0};this.moveCursorToLineEnd=function(){e(1,!1);return!0};this.extendSelectionToLineStart=
+function(){e(-1,!0);return!0};this.extendSelectionToLineEnd=function(){e(1,!0);return!0};this.extendSelectionToParagraphStart=function(){w(-1,x.getParagraphElement);return!0};this.extendSelectionToParagraphEnd=function(){w(1,x.getParagraphElement);return!0};this.moveCursorToDocumentStart=function(){z(-1);return!0};this.moveCursorToDocumentEnd=function(){z(1);return!0};this.extendSelectionToDocumentStart=function(){w(-1,x.getRootElement);return!0};this.extendSelectionToDocumentEnd=function(){w(1,x.getRootElement);
+return!0};this.extendSelectionToEntireDocument=function(){var a=x.getCursor(h),a=x.getRootElement(a.getNode());runtime.assert(Boolean(a),"SelectionController: Cursor outside root");a=x.convertDomToCursorRange({anchorNode:a,anchorOffset:0,focusNode:a,focusOffset:a.childNodes.length},d(x.getRootElement));k.enqueue([g(a.position,a.length)]);return!0};A.addFilter(s);A.addFilter(x.createRootFilter(h))};
+// Input 93
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2640,21 +2871,11 @@ h=c.createElementNS(c.documentElement.namespaceURI,"div");h.setAttribute("class"
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-gui.PlainTextPasteboard=function(g,l){function f(f,g){f.init(g);return f}this.createPasteOps=function(p){var r=g.getCursorPosition(l),n=r,h=[];p.replace(/\r/g,"").split("\n").forEach(function(d){h.push(f(new ops.OpSplitParagraph,{memberid:l,position:n,moveCursor:!0}));n+=1;h.push(f(new ops.OpInsertText,{memberid:l,position:n,text:d,moveCursor:!0}));n+=d.length});h.push(f(new ops.OpRemoveText,{memberid:l,position:r,length:1}));return h}};
-// Input 88
-runtime.loadClass("core.DomUtils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("gui.SelectionMover");
-gui.SelectionView=function(g){function l(){var a=q.getRootNode();k!==a&&(k=a,t=k.parentNode.parentNode.parentNode,t.appendChild(w),t.appendChild(x),t.appendChild(v))}function f(a,b){a.style.left=b.left+"px";a.style.top=b.top+"px";a.style.width=b.width+"px";a.style.height=b.height+"px"}function p(a){H=a;w.style.display=x.style.display=v.style.display=!0===a?"block":"none"}function r(a){var b=s.getBoundingClientRect(t),c=q.getOdfCanvas().getZoomLevel(),d={};d.top=s.adaptRangeDifferenceToZoomLevel(a.top-
-b.top,c);d.left=s.adaptRangeDifferenceToZoomLevel(a.left-b.left,c);d.bottom=s.adaptRangeDifferenceToZoomLevel(a.bottom-b.top,c);d.right=s.adaptRangeDifferenceToZoomLevel(a.right-b.left,c);d.width=s.adaptRangeDifferenceToZoomLevel(a.width,c);d.height=s.adaptRangeDifferenceToZoomLevel(a.height,c);return d}function n(a){a=a.getBoundingClientRect();return Boolean(a&&0!==a.height)}function h(a){var b=u.getTextElements(a,!0,!1),c=a.cloneRange(),d=a.cloneRange();a=a.cloneRange();if(!b.length)return null;
-var e;a:{e=0;var f=b[e],g=c.startContainer===f?c.startOffset:0,h=g;c.setStart(f,g);for(c.setEnd(f,h);!n(c);){if(f.nodeType===Node.ELEMENT_NODE&&h<f.childNodes.length)h=f.childNodes.length;else if(f.nodeType===Node.TEXT_NODE&&h<f.length)h+=1;else if(b[e])f=b[e],e+=1,g=h=0;else{e=!1;break a}c.setStart(f,g);c.setEnd(f,h)}e=!0}if(!e)return null;a:{e=b.length-1;f=b[e];h=g=d.endContainer===f?d.endOffset:f.length||f.childNodes.length;d.setStart(f,g);for(d.setEnd(f,h);!n(d);){if(f.nodeType===Node.ELEMENT_NODE&&
-0<g)g=0;else if(f.nodeType===Node.TEXT_NODE&&0<g)g-=1;else if(b[e])f=b[e],e-=1,g=h=f.length||f.childNodes.length;else{b=!1;break a}d.setStart(f,g);d.setEnd(f,h)}b=!0}if(!b)return null;a.setStart(c.startContainer,c.startOffset);a.setEnd(d.endContainer,d.endOffset);return{firstRange:c,lastRange:d,fillerRange:a}}function d(a,b){var c={};c.top=Math.min(a.top,b.top);c.left=Math.min(a.left,b.left);c.right=Math.max(a.right,b.right);c.bottom=Math.max(a.bottom,b.bottom);c.width=c.right-c.left;c.height=c.bottom-
-c.top;return c}function m(a,b){b&&0<b.width&&0<b.height&&(a=a?d(a,b):b);return a}function c(a){function b(a){y.setUnfilteredPosition(a,0);return w.acceptNode(a)===B&&t.acceptPosition(y)===B?B:L}function c(a){var d=null;b(a)===B&&(d=s.getBoundingClientRect(a));return d}var d=a.commonAncestorContainer,e=a.startContainer,f=a.endContainer,g=a.startOffset,h=a.endOffset,k,l,n=null,p,r=A.createRange(),t,w=new odf.OdfNodeFilter,v;if(e===d||f===d)return r=a.cloneRange(),n=r.getBoundingClientRect(),r.detach(),
-n;for(a=e;a.parentNode!==d;)a=a.parentNode;for(l=f;l.parentNode!==d;)l=l.parentNode;t=q.createRootFilter(e);for(d=a.nextSibling;d&&d!==l;)p=c(d),n=m(n,p),d=d.nextSibling;if(u.isParagraph(a))n=m(n,s.getBoundingClientRect(a));else if(a.nodeType===Node.TEXT_NODE)d=a,r.setStart(d,g),r.setEnd(d,d===l?h:d.length),p=r.getBoundingClientRect(),n=m(n,p);else for(v=A.createTreeWalker(a,NodeFilter.SHOW_TEXT,b,!1),d=v.currentNode=e;d&&d!==f;)r.setStart(d,g),r.setEnd(d,d.length),p=r.getBoundingClientRect(),n=m(n,
-p),k=d,g=0,d=v.nextNode();k||(k=e);if(u.isParagraph(l))n=m(n,s.getBoundingClientRect(l));else if(l.nodeType===Node.TEXT_NODE)d=l,r.setStart(d,d===a?g:0),r.setEnd(d,h),p=r.getBoundingClientRect(),n=m(n,p);else for(v=A.createTreeWalker(l,NodeFilter.SHOW_TEXT,b,!1),d=v.currentNode=f;d&&d!==k;)if(r.setStart(d,0),r.setEnd(d,h),p=r.getBoundingClientRect(),n=m(n,p),d=v.previousNode())h=d.length;return n}function e(a,b){var c=a.getBoundingClientRect(),d={width:0};d.top=c.top;d.bottom=c.bottom;d.height=c.height;
-d.left=d.right=b?c.right:c.left;return d}function a(){l();if(g.getSelectionType()===ops.OdtCursor.RangeSelection){p(!0);var a=g.getSelectedRange(),b=h(a),k,m,n,q;a.collapsed||!b?p(!1):(p(!0),a=b.firstRange,k=b.lastRange,b=b.fillerRange,m=r(e(a,!1)),q=r(e(k,!0)),n=(n=c(b))?r(n):d(m,q),f(w,{left:m.left,top:m.top,width:Math.max(0,n.width-(m.left-n.left)),height:m.height}),q.top===m.top||q.bottom===m.bottom?x.style.display=v.style.display="none":(f(v,{left:n.left,top:q.top,width:Math.max(0,q.right-n.left),
-height:q.height}),f(x,{left:n.left,top:m.top+m.height,width:Math.max(0,parseFloat(w.style.left)+parseFloat(w.style.width)-parseFloat(v.style.left)),height:Math.max(0,q.top-m.bottom)})),a.detach(),k.detach(),b.detach())}else p(!1)}function b(b){b===g&&a()}var q=g.getOdtDocument(),k,t,A=q.getDOM(),w=A.createElement("div"),x=A.createElement("div"),v=A.createElement("div"),u=new odf.OdfUtils,s=new core.DomUtils,H=!0,y=gui.SelectionMover.createPositionIterator(q.getRootNode()),B=NodeFilter.FILTER_ACCEPT,
-L=NodeFilter.FILTER_REJECT;this.show=this.rerender=a;this.hide=function(){p(!1)};this.visible=function(){return H};this.destroy=function(a){t.removeChild(w);t.removeChild(x);t.removeChild(v);g.getOdtDocument().unsubscribe(ops.OdtDocument.signalCursorMoved,b);a()};(function(){var a=g.getMemberId();l();w.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);x.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);v.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",
-a);w.className=x.className=v.className="selectionOverlay";g.getOdtDocument().subscribe(ops.OdtDocument.signalCursorMoved,b)})()};
-// Input 89
+gui.TextController=function(k,h,b,p){function d(b){var d=new ops.OpRemoveText;d.init({memberid:h,position:b.position,length:b.length});return d}function n(b){0>b.length&&(b.position+=b.length,b.length=-b.length);return b}function g(b,d){var c=new core.PositionFilterChain,a=gui.SelectionMover.createPositionIterator(q.getRootElement(b)),g=d?a.nextPosition:a.previousPosition;c.addFilter(q.getPositionFilter());c.addFilter(q.createRootFilter(h));for(a.setUnfilteredPosition(b,0);g();)if(c.acceptPosition(a)===
+r)return!0;return!1}var q=k.getOdtDocument(),r=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.enqueueParagraphSplittingOps=function(){var b=n(q.getCursorSelection(h)),f,c=[];0<b.length&&(f=d(b),c.push(f));f=new ops.OpSplitParagraph;f.init({memberid:h,position:b.position,moveCursor:!0});c.push(f);p&&(b=p(b.position+1),c=c.concat(b));k.enqueue(c);return!0};this.removeTextByBackspaceKey=function(){var b=q.getCursor(h),f=n(q.getCursorSelection(h)),c=null;0===f.length?g(b.getNode(),!1)&&(c=new ops.OpRemoveText,
+c.init({memberid:h,position:f.position-1,length:1}),k.enqueue([c])):(c=d(f),k.enqueue([c]));return null!==c};this.removeTextByDeleteKey=function(){var b=q.getCursor(h),f=n(q.getCursorSelection(h)),c=null;0===f.length?g(b.getNode(),!0)&&(c=new ops.OpRemoveText,c.init({memberid:h,position:f.position,length:1}),k.enqueue([c])):(c=d(f),k.enqueue([c]));return null!==c};this.removeCurrentSelection=function(){var b=n(q.getCursorSelection(h));0!==b.length&&(b=d(b),k.enqueue([b]));return!0};this.insertText=
+function(g){var f=n(q.getCursorSelection(h)),c,a=[],m=!1;0<f.length&&(c=d(f),a.push(c),m=!0);c=new ops.OpInsertText;c.init({memberid:h,position:f.position,text:g,moveCursor:!0});a.push(c);b&&(g=b(f.position,g.length,m))&&a.push(g);k.enqueue(a)}};(function(){return gui.TextController})();
+// Input 94
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2692,13 +2913,40 @@ a);w.className=x.className=v.className="selectionOverlay";g.getOdtDocument().sub
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("gui.SelectionView");
-gui.SelectionViewManager=function(){function g(){return Object.keys(l).map(function(f){return l[f]})}var l={};this.getSelectionView=function(f){return l.hasOwnProperty(f)?l[f]:null};this.getSelectionViews=g;this.removeSelectionView=function(f){l.hasOwnProperty(f)&&(l[f].destroy(function(){}),delete l[f])};this.hideSelectionView=function(f){l.hasOwnProperty(f)&&l[f].hide()};this.showSelectionView=function(f){l.hasOwnProperty(f)&&l[f].show()};this.rerenderSelectionViews=function(){Object.keys(l).forEach(function(f){l[f].visible()&&
-l[f].rerender()})};this.registerCursor=function(f,g){var r=f.getMemberId(),n=new gui.SelectionView(f);g?n.show():n.hide();return l[r]=n};this.destroy=function(f){var l=g();(function n(g,d){d?f(d):g<l.length?l[g].destroy(function(d){n(g+1,d)}):f()})(0,void 0)}};
-// Input 90
+gui.UndoManager=function(){};gui.UndoManager.prototype.subscribe=function(k,h){};gui.UndoManager.prototype.unsubscribe=function(k,h){};gui.UndoManager.prototype.setDocument=function(k){};gui.UndoManager.prototype.setInitialState=function(){};gui.UndoManager.prototype.initialize=function(){};gui.UndoManager.prototype.purgeInitialState=function(){};gui.UndoManager.prototype.setPlaybackFunction=function(k){};gui.UndoManager.prototype.hasUndoStates=function(){};
+gui.UndoManager.prototype.hasRedoStates=function(){};gui.UndoManager.prototype.moveForward=function(k){};gui.UndoManager.prototype.moveBackward=function(k){};gui.UndoManager.prototype.onOperationExecuted=function(k){};gui.UndoManager.signalUndoStackChanged="undoStackChanged";gui.UndoManager.signalUndoStateCreated="undoStateCreated";gui.UndoManager.signalUndoStateModified="undoStateModified";(function(){return gui.UndoManager})();
+// Input 95
+(function(){var k=core.PositionFilter.FilterResult.FILTER_ACCEPT;gui.SessionController=function(h,b,p,d){function n(a){var c=K.getCursor(b).getSelectedRange();c.collapsed?a.preventDefault():T.setDataFromRange(a,c)?da.removeCurrentSelection():runtime.log("Cut operation failed")}function g(){return!1!==K.getCursor(b).getSelectedRange().collapsed}function q(a){var c=K.getCursor(b).getSelectedRange();c.collapsed?a.preventDefault():T.setDataFromRange(a,c)||runtime.log("Copy operation failed")}function r(a){var b;
+O.clipboardData&&O.clipboardData.getData?b=O.clipboardData.getData("Text"):a.clipboardData&&a.clipboardData.getData&&(b=a.clipboardData.getData("text/plain"));b&&(da.removeCurrentSelection(),h.enqueue(ha.createPasteOps(b)));a.preventDefault?a.preventDefault():a.returnValue=!1}function l(){return!1}function f(a){if(M)M.onOperationExecuted(a)}function c(a){K.emit(ops.OdtDocument.signalUndoStackChanged,a)}function a(){var a=E.getEventTrap(),b,c;return M?(c=E.hasFocus(),M.moveBackward(1),b=K.getOdfCanvas().getSizer(),
+Q.containsNode(b,a)||(b.appendChild(a),c&&E.focus()),!0):!1}function m(){var a;return M?(a=E.hasFocus(),M.moveForward(1),a&&E.focus(),!0):!1}function e(){var a=O.getSelection(),b=0<a.rangeCount&&L.selectionToRange(a);R&&b&&(ca=!0,P.clearSelection(),X.setUnfilteredPosition(a.focusNode,a.focusOffset),ia.acceptPosition(X)===k&&(2===ea?L.expandToWordBoundaries(b.range):3<=ea&&L.expandToParagraphBoundaries(b.range),p.setSelectedRange(b.range,b.hasForwardSelection),K.emit(ops.Document.signalCursorMoved,
+p)))}function t(a){var c=a.target||a.srcElement||null,d=K.getCursor(b);if(R=null!==c&&Q.containsNode(K.getOdfCanvas().getElement(),c))ca=!1,ia=K.createRootFilter(c),ea=a.detail,d&&a.shiftKey?O.getSelection().collapse(d.getAnchorNode(),0):(a=O.getSelection(),c=d.getSelectedRange(),a.extend?d.hasForwardSelection()?(a.collapse(c.startContainer,c.startOffset),a.extend(c.endContainer,c.endOffset)):(a.collapse(c.endContainer,c.endOffset),a.extend(c.startContainer,c.startOffset)):(a.removeAllRanges(),a.addRange(c.cloneRange()))),
+1<ea&&e()}function w(a){var b=K.getRootElement(a),c=K.createRootFilter(b),b=K.createStepIterator(a,0,[c,K.getPositionFilter()],b);b.setPosition(a,a.childNodes.length);return b.roundToNextStep()?{container:b.container(),offset:b.offset()}:null}function z(a){var b;b=(b=O.getSelection())?{anchorNode:b.anchorNode,anchorOffset:b.anchorOffset,focusNode:b.focusNode,focusOffset:b.focusOffset}:null;var c,d;if(!b.anchorNode&&!b.focusNode){d=a.clientX;var e=a.clientY,f=K.getDOMDocument();c=null;f.caretRangeFromPoint?
+(d=f.caretRangeFromPoint(d,e),c={container:d.startContainer,offset:d.startOffset}):f.caretPositionFromPoint&&(d=f.caretPositionFromPoint(d,e))&&d.offsetNode&&(c={container:d.offsetNode,offset:d.offset});c&&(b.anchorNode=c.container,b.anchorOffset=c.offset,b.focusNode=b.anchorNode,b.focusOffset=b.anchorOffset)}if(W.isImage(b.focusNode)&&0===b.focusOffset&&W.isCharacterFrame(b.focusNode.parentNode)){if(d=b.focusNode.parentNode,c=d.getBoundingClientRect(),a.clientX>c.right&&(c=w(d)))b.anchorNode=b.focusNode=
+c.container,b.anchorOffset=b.focusOffset=c.offset}else W.isImage(b.focusNode.firstChild)&&1===b.focusOffset&&W.isCharacterFrame(b.focusNode)&&(c=w(b.focusNode))&&(b.anchorNode=b.focusNode=c.container,b.anchorOffset=b.focusOffset=c.offset);b.anchorNode&&b.focusNode&&(b=L.selectionToRange(b),L.selectRange(b.range,b.hasForwardSelection,a.detail));E.focus()}function x(a){var b=a.target||a.srcElement||null,c,d;V.processRequests();W.isImage(b)&&W.isCharacterFrame(b.parentNode)&&O.getSelection().isCollapsed?
+(L.selectImage(b.parentNode),E.focus()):P.isSelectorElement(b)?E.focus():R&&(ca?(b=p.getSelectedRange(),c=b.collapsed,W.isImage(b.endContainer)&&0===b.endOffset&&W.isCharacterFrame(b.endContainer.parentNode)&&(d=b.endContainer.parentNode,d=w(d))&&(b.setEnd(d.container,d.offset),c&&b.collapse(!1)),L.selectRange(b,p.hasForwardSelection(),a.detail),E.focus()):ma?z(a):Y=runtime.setTimeout(function(){z(a)},0));ea=0;ca=R=!1}function v(a){var c=K.getCursor(b).getSelectedRange();c.collapsed||H.exportRangeToDataTransfer(a.dataTransfer,
+c)}function u(){R&&E.focus();ea=0;ca=R=!1}function s(a){x(a)}function A(a){var b=a.target||a.srcElement||null,c=null;"annotationRemoveButton"===b.className?(c=Q.getElementsByTagNameNS(b.parentNode,odf.Namespaces.officens,"annotation")[0],S.removeAnnotation(c),E.focus()):x(a)}function J(a){(a=a.data)&&da.insertText(a)}function G(a){return function(){a();return!0}}function D(a){return function(c){return K.getCursor(b).getSelectionType()===ops.OdtCursor.RangeSelection?a(c):!0}}function F(a){E.unsubscribe("keydown",
+y.handleEvent);E.unsubscribe("keypress",aa.handleEvent);E.unsubscribe("keyup",N.handleEvent);E.unsubscribe("copy",q);E.unsubscribe("mousedown",t);E.unsubscribe("mousemove",V.trigger);E.unsubscribe("mouseup",A);E.unsubscribe("contextmenu",s);E.unsubscribe("dragstart",v);E.unsubscribe("dragend",u);E.unsubscribe("click",fa.handleClick);K.unsubscribe(ops.OdtDocument.signalOperationEnd,ga.trigger);K.unsubscribe(ops.Document.signalCursorAdded,$.registerCursor);K.unsubscribe(ops.Document.signalCursorRemoved,
+$.removeCursor);K.unsubscribe(ops.OdtDocument.signalOperationEnd,f);a()}var O=runtime.getWindow(),K=h.getOdtDocument(),Z=new core.Async,Q=new core.DomUtils,W=new odf.OdfUtils,H=new gui.MimeDataExporter,T=new gui.Clipboard(H),y=new gui.KeyboardHandler,aa=new gui.KeyboardHandler,N=new gui.KeyboardHandler,R=!1,I=new odf.ObjectNameGenerator(K.getOdfCanvas().odfContainer(),b),ca=!1,ia=null,Y,M=null,E=new gui.EventManager(K),S=new gui.AnnotationController(h,b),U=new gui.DirectFormattingController(h,b,I,
+d.directParagraphStylingEnabled),da=new gui.TextController(h,b,U.createCursorStyleOp,U.createParagraphStyleOps),ka=new gui.ImageController(h,b,I),P=new gui.ImageSelector(K.getOdfCanvas()),X=gui.SelectionMover.createPositionIterator(K.getRootNode()),V,ga,ha=new gui.PlainTextPasteboard(K,b),$=new gui.InputMethodEditor(b,E),ea=0,fa=new gui.HyperlinkClickHandler(K.getRootNode),ja=new gui.HyperlinkController(h,b),L=new gui.SelectionController(h,b),B=gui.KeyboardHandler.Modifier,C=gui.KeyboardHandler.KeyCode,
+ba=-1!==O.navigator.appVersion.toLowerCase().indexOf("mac"),ma=-1!==["iPad","iPod","iPhone"].indexOf(O.navigator.platform),la;runtime.assert(null!==O,"Expected to be run in an environment which has a global window, like a browser.");this.undo=a;this.redo=m;this.insertLocalCursor=function(){runtime.assert(void 0===h.getOdtDocument().getCursor(b),"Inserting local cursor a second time.");var a=new ops.OpAddCursor;a.init({memberid:b});h.enqueue([a]);E.focus()};this.removeLocalCursor=function(){runtime.assert(void 0!==
+h.getOdtDocument().getCursor(b),"Removing local cursor without inserting before.");var a=new ops.OpRemoveCursor;a.init({memberid:b});h.enqueue([a])};this.startEditing=function(){$.subscribe(gui.InputMethodEditor.signalCompositionStart,da.removeCurrentSelection);$.subscribe(gui.InputMethodEditor.signalCompositionEnd,J);E.subscribe("beforecut",g);E.subscribe("cut",n);E.subscribe("beforepaste",l);E.subscribe("paste",r);O.addEventListener("focus",fa.showTextCursor,!1);M&&M.initialize();$.setEditing(!0);
+fa.setModifier(ba?gui.HyperlinkClickHandler.Modifier.Meta:gui.HyperlinkClickHandler.Modifier.Ctrl);y.bind(C.Backspace,B.None,G(da.removeTextByBackspaceKey),!0);y.bind(C.Delete,B.None,da.removeTextByDeleteKey);y.bind(C.Tab,B.None,D(function(){da.insertText("\t");return!0}));ba?(y.bind(C.Clear,B.None,da.removeCurrentSelection),y.bind(C.B,B.Meta,D(U.toggleBold)),y.bind(C.I,B.Meta,D(U.toggleItalic)),y.bind(C.U,B.Meta,D(U.toggleUnderline)),y.bind(C.L,B.MetaShift,D(U.alignParagraphLeft)),y.bind(C.E,B.MetaShift,
+D(U.alignParagraphCenter)),y.bind(C.R,B.MetaShift,D(U.alignParagraphRight)),y.bind(C.J,B.MetaShift,D(U.alignParagraphJustified)),y.bind(C.C,B.MetaShift,S.addAnnotation),y.bind(C.Z,B.Meta,a),y.bind(C.Z,B.MetaShift,m),y.bind(C.LeftMeta,B.Meta,fa.showPointerCursor),y.bind(C.MetaInMozilla,B.Meta,fa.showPointerCursor),N.bind(C.LeftMeta,B.None,fa.showTextCursor),N.bind(C.MetaInMozilla,B.None,fa.showTextCursor)):(y.bind(C.B,B.Ctrl,D(U.toggleBold)),y.bind(C.I,B.Ctrl,D(U.toggleItalic)),y.bind(C.U,B.Ctrl,D(U.toggleUnderline)),
+y.bind(C.L,B.CtrlShift,D(U.alignParagraphLeft)),y.bind(C.E,B.CtrlShift,D(U.alignParagraphCenter)),y.bind(C.R,B.CtrlShift,D(U.alignParagraphRight)),y.bind(C.J,B.CtrlShift,D(U.alignParagraphJustified)),y.bind(C.C,B.CtrlAlt,S.addAnnotation),y.bind(C.Z,B.Ctrl,a),y.bind(C.Z,B.CtrlShift,m),y.bind(C.Ctrl,B.Ctrl,fa.showPointerCursor),N.bind(C.Ctrl,B.None,fa.showTextCursor));aa.setDefault(D(function(a){var b;b=null===a.which||void 0===a.which?String.fromCharCode(a.keyCode):0!==a.which&&0!==a.charCode?String.fromCharCode(a.which):
+null;return!b||a.altKey||a.ctrlKey||a.metaKey?!1:(da.insertText(b),!0)}));aa.bind(C.Enter,B.None,D(da.enqueueParagraphSplittingOps))};this.endEditing=function(){$.unsubscribe(gui.InputMethodEditor.signalCompositionStart,da.removeCurrentSelection);$.unsubscribe(gui.InputMethodEditor.signalCompositionEnd,J);E.unsubscribe("cut",n);E.unsubscribe("beforecut",g);E.unsubscribe("paste",r);E.unsubscribe("beforepaste",l);O.removeEventListener("focus",fa.showTextCursor,!1);$.setEditing(!1);fa.setModifier(gui.HyperlinkClickHandler.Modifier.None);
+y.bind(C.Backspace,B.None,function(){return!0},!0);y.unbind(C.Delete,B.None);y.unbind(C.Tab,B.None);ba?(y.unbind(C.Clear,B.None),y.unbind(C.B,B.Meta),y.unbind(C.I,B.Meta),y.unbind(C.U,B.Meta),y.unbind(C.L,B.MetaShift),y.unbind(C.E,B.MetaShift),y.unbind(C.R,B.MetaShift),y.unbind(C.J,B.MetaShift),y.unbind(C.C,B.MetaShift),y.unbind(C.Z,B.Meta),y.unbind(C.Z,B.MetaShift),y.unbind(C.LeftMeta,B.Meta),y.unbind(C.MetaInMozilla,B.Meta),N.unbind(C.LeftMeta,B.None),N.unbind(C.MetaInMozilla,B.None)):(y.unbind(C.B,
+B.Ctrl),y.unbind(C.I,B.Ctrl),y.unbind(C.U,B.Ctrl),y.unbind(C.L,B.CtrlShift),y.unbind(C.E,B.CtrlShift),y.unbind(C.R,B.CtrlShift),y.unbind(C.J,B.CtrlShift),y.unbind(C.C,B.CtrlAlt),y.unbind(C.Z,B.Ctrl),y.unbind(C.Z,B.CtrlShift),y.unbind(C.Ctrl,B.Ctrl),N.unbind(C.Ctrl,B.None));aa.setDefault(null);aa.unbind(C.Enter,B.None)};this.getInputMemberId=function(){return b};this.getSession=function(){return h};this.setUndoManager=function(a){M&&M.unsubscribe(gui.UndoManager.signalUndoStackChanged,c);if(M=a)M.setDocument(K),
+M.setPlaybackFunction(h.enqueue),M.subscribe(gui.UndoManager.signalUndoStackChanged,c)};this.getUndoManager=function(){return M};this.getAnnotationController=function(){return S};this.getDirectFormattingController=function(){return U};this.getHyperlinkController=function(){return ja};this.getImageController=function(){return ka};this.getSelectionController=function(){return L};this.getTextController=function(){return da};this.getEventManager=function(){return E};this.getKeyboardHandlers=function(){return{keydown:y,
+keypress:aa}};this.destroy=function(a){var b=[];la&&b.push(la.destroy);b=b.concat([V.destroy,ga.destroy,U.destroy,$.destroy,E.destroy,F]);runtime.clearTimeout(Y);Z.destroyAll(b,a)};V=new core.ScheduledTask(e,0);ga=new core.ScheduledTask(function(){var a=K.getCursor(b);if(a&&a.getSelectionType()===ops.OdtCursor.RegionSelection&&(a=W.getImageElements(a.getSelectedRange())[0])){P.select(a.parentNode);return}P.clearSelection()},0);y.bind(C.Left,B.None,D(L.moveCursorToLeft));y.bind(C.Right,B.None,D(L.moveCursorToRight));
+y.bind(C.Up,B.None,D(L.moveCursorUp));y.bind(C.Down,B.None,D(L.moveCursorDown));y.bind(C.Left,B.Shift,D(L.extendSelectionToLeft));y.bind(C.Right,B.Shift,D(L.extendSelectionToRight));y.bind(C.Up,B.Shift,D(L.extendSelectionUp));y.bind(C.Down,B.Shift,D(L.extendSelectionDown));y.bind(C.Home,B.None,D(L.moveCursorToLineStart));y.bind(C.End,B.None,D(L.moveCursorToLineEnd));y.bind(C.Home,B.Ctrl,D(L.moveCursorToDocumentStart));y.bind(C.End,B.Ctrl,D(L.moveCursorToDocumentEnd));y.bind(C.Home,B.Shift,D(L.extendSelectionToLineStart));
+y.bind(C.End,B.Shift,D(L.extendSelectionToLineEnd));y.bind(C.Up,B.CtrlShift,D(L.extendSelectionToParagraphStart));y.bind(C.Down,B.CtrlShift,D(L.extendSelectionToParagraphEnd));y.bind(C.Home,B.CtrlShift,D(L.extendSelectionToDocumentStart));y.bind(C.End,B.CtrlShift,D(L.extendSelectionToDocumentEnd));ba?(y.bind(C.Left,B.Alt,D(L.moveCursorBeforeWord)),y.bind(C.Right,B.Alt,D(L.moveCursorPastWord)),y.bind(C.Left,B.Meta,D(L.moveCursorToLineStart)),y.bind(C.Right,B.Meta,D(L.moveCursorToLineEnd)),y.bind(C.Home,
+B.Meta,D(L.moveCursorToDocumentStart)),y.bind(C.End,B.Meta,D(L.moveCursorToDocumentEnd)),y.bind(C.Left,B.AltShift,D(L.extendSelectionBeforeWord)),y.bind(C.Right,B.AltShift,D(L.extendSelectionPastWord)),y.bind(C.Left,B.MetaShift,D(L.extendSelectionToLineStart)),y.bind(C.Right,B.MetaShift,D(L.extendSelectionToLineEnd)),y.bind(C.Up,B.AltShift,D(L.extendSelectionToParagraphStart)),y.bind(C.Down,B.AltShift,D(L.extendSelectionToParagraphEnd)),y.bind(C.Up,B.MetaShift,D(L.extendSelectionToDocumentStart)),
+y.bind(C.Down,B.MetaShift,D(L.extendSelectionToDocumentEnd)),y.bind(C.A,B.Meta,D(L.extendSelectionToEntireDocument))):(y.bind(C.Left,B.Ctrl,D(L.moveCursorBeforeWord)),y.bind(C.Right,B.Ctrl,D(L.moveCursorPastWord)),y.bind(C.Left,B.CtrlShift,D(L.extendSelectionBeforeWord)),y.bind(C.Right,B.CtrlShift,D(L.extendSelectionPastWord)),y.bind(C.A,B.Ctrl,D(L.extendSelectionToEntireDocument)));ma&&(la=new gui.IOSSafariSupport(E));E.subscribe("keydown",y.handleEvent);E.subscribe("keypress",aa.handleEvent);E.subscribe("keyup",
+N.handleEvent);E.subscribe("copy",q);E.subscribe("mousedown",t);E.subscribe("mousemove",V.trigger);E.subscribe("mouseup",A);E.subscribe("contextmenu",s);E.subscribe("dragstart",v);E.subscribe("dragend",u);E.subscribe("click",fa.handleClick);K.subscribe(ops.OdtDocument.signalOperationEnd,ga.trigger);K.subscribe(ops.Document.signalCursorAdded,$.registerCursor);K.subscribe(ops.Document.signalCursorRemoved,$.removeCursor);K.subscribe(ops.OdtDocument.signalOperationEnd,f)};return gui.SessionController})();
+// Input 96
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2733,17 +2981,17 @@ l[f].rerender()})};this.registerCursor=function(f,g){var r=f.getMemberId(),n=new
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.DomUtils");runtime.loadClass("gui.UndoManager");runtime.loadClass("gui.UndoStateRules");
-gui.TrivialUndoManager=function(g){function l(){t.emit(gui.UndoManager.signalUndoStackChanged,{undoAvailable:h.hasUndoStates(),redoAvailable:h.hasRedoStates()})}function f(){b!==c&&b!==q[q.length-1]&&q.push(b)}function p(a){var b=a.previousSibling||a.nextSibling;a.parentNode.removeChild(a);d.normalizeTextNodes(b)}function r(a){return Object.keys(a).map(function(b){return a[b]})}function n(b){function c(a){var b=a.spec();if(f[b.memberid])switch(b.optype){case "AddCursor":d[b.memberid]||(d[b.memberid]=
-a,delete f[b.memberid],g-=1);break;case "MoveCursor":e[b.memberid]||(e[b.memberid]=a)}}var d={},e={},f={},g,h=b.pop();a.getCursors().forEach(function(a){f[a.getMemberId()]=!0});for(g=Object.keys(f).length;h&&0<g;)h.reverse(),h.forEach(c),h=b.pop();return r(d).concat(r(e))}var h=this,d=new core.DomUtils,m,c=[],e,a,b=[],q=[],k=[],t=new core.EventNotifier([gui.UndoManager.signalUndoStackChanged,gui.UndoManager.signalUndoStateCreated,gui.UndoManager.signalUndoStateModified,gui.TrivialUndoManager.signalDocumentRootReplaced]),
-A=g||new gui.UndoStateRules;this.subscribe=function(a,b){t.subscribe(a,b)};this.unsubscribe=function(a,b){t.unsubscribe(a,b)};this.hasUndoStates=function(){return 0<q.length};this.hasRedoStates=function(){return 0<k.length};this.setOdtDocument=function(b){a=b};this.resetInitialState=function(){q.length=0;k.length=0;c.length=0;b.length=0;m=null;l()};this.saveInitialState=function(){var e=a.getOdfCanvas().odfContainer(),g=a.getOdfCanvas().getAnnotationViewManager();g&&g.forgetAnnotations();m=e.rootElement.cloneNode(!0);
-a.getOdfCanvas().refreshAnnotations();e=m;d.getElementsByTagNameNS(e,"urn:webodf:names:cursor","cursor").forEach(p);d.getElementsByTagNameNS(e,"urn:webodf:names:cursor","anchor").forEach(p);f();q.unshift(c);b=c=n(q);q.length=0;k.length=0;l()};this.setPlaybackFunction=function(a){e=a};this.onOperationExecuted=function(a){k.length=0;A.isEditOperation(a)&&b===c||!A.isPartOfOperationSet(a,b)?(f(),b=[a],q.push(b),t.emit(gui.UndoManager.signalUndoStateCreated,{operations:b}),l()):(b.push(a),t.emit(gui.UndoManager.signalUndoStateModified,
-{operations:b}))};this.moveForward=function(a){for(var c=0,d;a&&k.length;)d=k.pop(),q.push(d),d.forEach(e),a-=1,c+=1;c&&(b=q[q.length-1],l());return c};this.moveBackward=function(d){for(var f=a.getOdfCanvas(),g=f.odfContainer(),h=0;d&&q.length;)k.push(q.pop()),d-=1,h+=1;h&&(g.setRootElement(m.cloneNode(!0)),f.setOdfContainer(g,!0),t.emit(gui.TrivialUndoManager.signalDocumentRootReplaced,{}),a.getCursors().forEach(function(b){a.removeCursor(b.getMemberId())}),c.forEach(e),q.forEach(function(a){a.forEach(e)}),
-f.refreshCSS(),b=q[q.length-1]||c,l());return h}};gui.TrivialUndoManager.signalDocumentRootReplaced="documentRootReplaced";(function(){return gui.TrivialUndoManager})();
-// Input 91
+gui.CaretManager=function(k){function h(b){return a.hasOwnProperty(b)?a[b]:null}function b(){return Object.keys(a).map(function(b){return a[b]})}function p(b){var c=a[b];c&&(c.destroy(function(){}),delete a[b])}function d(a){a=a.getMemberId();a===k.getInputMemberId()&&(a=h(a))&&a.refreshCursorBlinking()}function n(){var a=h(k.getInputMemberId());w=!1;a&&a.ensureVisible()}function g(){var a=h(k.getInputMemberId());a&&(a.handleUpdate(),w||(w=!0,t=runtime.setTimeout(n,50)))}function q(a){a.memberId===
+k.getInputMemberId()&&g()}function r(){var a=h(k.getInputMemberId());a&&a.setFocus()}function l(){var a=h(k.getInputMemberId());a&&a.removeFocus()}function f(){var a=h(k.getInputMemberId());a&&a.show()}function c(){var a=h(k.getInputMemberId());a&&a.hide()}var a={},m=new core.Async,e=runtime.getWindow(),t,w=!1;this.registerCursor=function(b,c,d){var e=b.getMemberId();c=new gui.Caret(b,c,d);d=k.getEventManager();a[e]=c;e===k.getInputMemberId()?(runtime.log("Starting to track input on new cursor of "+
+e),b.subscribe(ops.OdtCursor.signalCursorUpdated,g),c.setOverlayElement(d.getEventTrap())):b.subscribe(ops.OdtCursor.signalCursorUpdated,c.handleUpdate);return c};this.getCaret=h;this.getCarets=b;this.destroy=function(g){var h=k.getSession().getOdtDocument(),n=k.getEventManager(),u=b().map(function(a){return a.destroy});runtime.clearTimeout(t);h.unsubscribe(ops.OdtDocument.signalParagraphChanged,q);h.unsubscribe(ops.Document.signalCursorMoved,d);h.unsubscribe(ops.Document.signalCursorRemoved,p);n.unsubscribe("focus",
+r);n.unsubscribe("blur",l);e.removeEventListener("focus",f,!1);e.removeEventListener("blur",c,!1);a={};m.destroyAll(u,g)};(function(){var a=k.getSession().getOdtDocument(),b=k.getEventManager();a.subscribe(ops.OdtDocument.signalParagraphChanged,q);a.subscribe(ops.Document.signalCursorMoved,d);a.subscribe(ops.Document.signalCursorRemoved,p);b.subscribe("focus",r);b.subscribe("blur",l);e.addEventListener("focus",f,!1);e.addEventListener("blur",c,!1)})()};
+// Input 97
+gui.EditInfoHandle=function(k){var h=[],b,p=k.ownerDocument,d=p.documentElement.namespaceURI;this.setEdits=function(k){h=k;var g,q,r,l;b.innerHTML="";for(k=0;k<h.length;k+=1)g=p.createElementNS(d,"div"),g.className="editInfo",q=p.createElementNS(d,"span"),q.className="editInfoColor",q.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",h[k].memberid),r=p.createElementNS(d,"span"),r.className="editInfoAuthor",r.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",h[k].memberid),
+l=p.createElementNS(d,"span"),l.className="editInfoTime",l.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",h[k].memberid),l.innerHTML=h[k].time,g.appendChild(q),g.appendChild(r),g.appendChild(l),b.appendChild(g)};this.show=function(){b.style.display="block"};this.hide=function(){b.style.display="none"};this.destroy=function(d){k.removeChild(b);d()};b=p.createElementNS(d,"div");b.setAttribute("class","editInfoHandle");b.style.display="none";k.appendChild(b)};
+// Input 98
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012 KO GmbH <aditya.bhatt@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2778,40 +3026,55 @@ f.refreshCSS(),b=q[q.length-1]||c,l());return h}};gui.TrivialUndoManager.signalD
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("ops.TrivialOperationRouter");runtime.loadClass("ops.OperationFactory");runtime.loadClass("ops.OdtDocument");
-ops.Session=function(g){var l=new ops.OperationFactory,f=new ops.OdtDocument(g),p=null;this.setOperationFactory=function(f){l=f;p&&p.setOperationFactory(l)};this.setOperationRouter=function(g){p=g;g.setPlaybackFunction(function(g){return g.execute(f)?(f.emit(ops.OdtDocument.signalOperationExecuted,g),!0):!1});g.setOperationFactory(l)};this.getOperationFactory=function(){return l};this.getOdtDocument=function(){return f};this.enqueue=function(f){p.push(f)};this.close=function(g){p.close(function(l){l?
-g(l):f.close(g)})};this.destroy=function(g){f.destroy(g)};this.setOperationRouter(new ops.TrivialOperationRouter)};
-// Input 92
+ops.EditInfo=function(k,h){function b(){var b=[],g;for(g in d)d.hasOwnProperty(g)&&b.push({memberid:g,time:d[g].time});b.sort(function(b,d){return b.time-d.time});return b}var p,d={};this.getNode=function(){return p};this.getOdtDocument=function(){return h};this.getEdits=function(){return d};this.getSortedEdits=function(){return b()};this.addEdit=function(b,g){d[b]={time:g}};this.clearEdits=function(){d={}};this.destroy=function(b){k.parentNode&&k.removeChild(p);b()};p=h.getDOMDocument().createElementNS("urn:webodf:names:editinfo",
+"editinfo");k.insertBefore(p,k.firstChild)};
+// Input 99
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
- This file is part of WebODF.
+ The JavaScript code in this page is free software: you can redistribute it
+ and/or modify it under the terms of the GNU Affero General Public License
+ (GNU AGPL) as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version. The code is distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
- WebODF is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License (GNU AGPL)
- as published by the Free Software Foundation, either version 3 of
- the License, or (at your option) any later version.
+ You should have received a copy of the GNU Affero General Public License
+ along with this code. If not, see <http://www.gnu.org/licenses/>.
- WebODF is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ As additional permission under GNU AGPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
- You should have received a copy of the GNU Affero General Public License
- along with WebODF. If not, see <http://www.gnu.org/licenses/>.
- @licend
+ As a special exception to the AGPL, any HTML file which merely makes function
+ calls to this code, and for that purpose includes it by reference shall be
+ deemed a separate work for copyright law purposes. In addition, the copyright
+ holders of this code give you permission to combine this code with free
+ software libraries that are released under the GNU LGPL. You may copy and
+ distribute such a system following the terms of the GNU AGPL for this code
+ and the LGPL for the libraries. If you modify this code, you may extend this
+ exception to your version of the code, but you are not obligated to do so.
+ If you do not wish to do so, delete this exception statement from your
+ version.
+ This license applies to this entire compilation.
+ @licend
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.EventNotifier");runtime.loadClass("core.PositionFilter");runtime.loadClass("ops.Session");runtime.loadClass("ops.OpAddAnnotation");runtime.loadClass("ops.OpRemoveAnnotation");runtime.loadClass("gui.SelectionMover");
-gui.AnnotationController=function(g,l){function f(){var e=h.getCursor(l),e=e&&e.getNode(),a=!1;if(e){a:{for(a=h.getRootNode();e&&e!==a;){if(e.namespaceURI===c&&"annotation"===e.localName){e=!0;break a}e=e.parentNode}e=!1}a=!e}a!==d&&(d=a,m.emit(gui.AnnotationController.annotatableChanged,d))}function p(c){c.getMemberId()===l&&f()}function r(c){c===l&&f()}function n(c){c.getMemberId()===l&&f()}var h=g.getOdtDocument(),d=!1,m=new core.EventNotifier([gui.AnnotationController.annotatableChanged]),c=odf.Namespaces.officens;
-this.isAnnotatable=function(){return d};this.addAnnotation=function(){var c=new ops.OpAddAnnotation,a=h.getCursorSelection(l),b=a.length,a=a.position;d&&(a=0<=b?a:a+b,b=Math.abs(b),c.init({memberid:l,position:a,length:b,name:l+Date.now()}),g.enqueue([c]))};this.removeAnnotation=function(c){var a,b;a=h.convertDomPointToCursorStep(c,0)+1;b=h.convertDomPointToCursorStep(c,c.childNodes.length);c=new ops.OpRemoveAnnotation;c.init({memberid:l,position:a,length:b-a});b=new ops.OpMoveCursor;b.init({memberid:l,
-position:0<a?a-1:a,length:0});g.enqueue([c,b])};this.subscribe=function(c,a){m.subscribe(c,a)};this.unsubscribe=function(c,a){m.unsubscribe(c,a)};this.destroy=function(c){h.unsubscribe(ops.OdtDocument.signalCursorAdded,p);h.unsubscribe(ops.OdtDocument.signalCursorRemoved,r);h.unsubscribe(ops.OdtDocument.signalCursorMoved,n);c()};h.subscribe(ops.OdtDocument.signalCursorAdded,p);h.subscribe(ops.OdtDocument.signalCursorRemoved,r);h.subscribe(ops.OdtDocument.signalCursorMoved,n);f()};
-gui.AnnotationController.annotatableChanged="annotatable/changed";(function(){return gui.AnnotationController})();
-// Input 93
+gui.EditInfoMarker=function(k,h){function b(b,c){return runtime.setTimeout(function(){g.style.opacity=b},c)}var p=this,d,n,g,q,r,l;this.addEdit=function(d,c){var a=Date.now()-c;k.addEdit(d,c);n.setEdits(k.getSortedEdits());g.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",d);runtime.clearTimeout(r);runtime.clearTimeout(l);1E4>a?(q=b(1,0),r=b(0.5,1E4-a),l=b(0.2,2E4-a)):1E4<=a&&2E4>a?(q=b(0.5,0),l=b(0.2,2E4-a)):q=b(0.2,0)};this.getEdits=function(){return k.getEdits()};this.clearEdits=
+function(){k.clearEdits();n.setEdits([]);g.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&g.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return k};this.show=function(){g.style.display="block"};this.hide=function(){p.hideHandle();g.style.display="none"};this.showHandle=function(){n.show()};this.hideHandle=function(){n.hide()};this.destroy=function(b){runtime.clearTimeout(q);runtime.clearTimeout(r);runtime.clearTimeout(l);d.removeChild(g);
+n.destroy(function(c){c?b(c):k.destroy(b)})};(function(){var b=k.getOdtDocument().getDOMDocument();g=b.createElementNS(b.documentElement.namespaceURI,"div");g.setAttribute("class","editInfoMarker");g.onmouseover=function(){p.showHandle()};g.onmouseout=function(){p.hideHandle()};d=k.getNode();d.appendChild(g);n=new gui.EditInfoHandle(d);h||p.hide()})()};
+// Input 100
+gui.ShadowCursor=function(k){var h=k.getDOMDocument().createRange(),b=!0;this.removeFromDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return h};this.setSelectedRange=function(k,d){h=k;b=!1!==d};this.hasForwardSelection=function(){return b};this.getDocument=function(){return k};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};h.setStart(k.getRootNode(),0)};gui.ShadowCursor.ShadowCursorMemberId="";
+(function(){return gui.ShadowCursor})();
+// Input 101
+gui.SelectionView=function(k){};gui.SelectionView.prototype.rerender=function(){};gui.SelectionView.prototype.show=function(){};gui.SelectionView.prototype.hide=function(){};gui.SelectionView.prototype.destroy=function(k){};
+// Input 102
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2849,17 +3112,12 @@ gui.AnnotationController.annotatableChanged="annotatable/changed";(function(){re
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.EventNotifier");runtime.loadClass("core.Utils");runtime.loadClass("odf.OdfUtils");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("gui.StyleHelper");
-gui.DirectParagraphStyler=function(g,l,f){function p(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b=k.getCursor(l),b=b&&b.getSelectedRange(),c;v=a(v,b?w.isAlignedLeft(b):!1,"isAlignedLeft");u=a(u,b?w.isAlignedCenter(b):!1,"isAlignedCenter");s=a(s,b?w.isAlignedRight(b):!1,"isAlignedRight");H=a(H,b?w.isAlignedJustified(b):!1,"isAlignedJustified");c&&x.emit(gui.DirectParagraphStyler.paragraphStylingChanged,c)}function r(a){a.getMemberId()===l&&p()}function n(a){a===l&&p()}function h(a){a.getMemberId()===
-l&&p()}function d(){p()}function m(a){var b=k.getCursor(l);b&&k.getParagraphElement(b.getNode())===a.paragraphElement&&p()}function c(a){return a===ops.StepsTranslator.NEXT_STEP}function e(a){var b=k.getCursor(l).getSelectedRange(),b=A.getParagraphElements(b),d=k.getFormatting();b.forEach(function(b){var e=k.convertDomPointToCursorStep(b,0,c),h=b.getAttributeNS(odf.Namespaces.textns,"style-name");b=f.generateStyleName();var m;h&&(m=d.createDerivedStyleObject(h,"paragraph",{}));m=a(m||{});h=new ops.OpAddStyle;
-h.init({memberid:l,styleName:b,styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:m});m=new ops.OpSetParagraphStyle;m.init({memberid:l,styleName:b,position:e});g.enqueue([h,m])})}function a(a){e(function(b){return t.mergeObjects(b,a)})}function b(b){a({"style:paragraph-properties":{"fo:text-align":b}})}function q(a,b){var c=k.getFormatting().getDefaultTabStopDistance(),d=b["style:paragraph-properties"],d=(d=d&&d["fo:margin-left"])&&A.parseLength(d);return t.mergeObjects(b,{"style:paragraph-properties":{"fo:margin-left":d&&
-d.unit===c.unit?d.value+a*c.value+d.unit:a*c.value+c.unit}})}var k=g.getOdtDocument(),t=new core.Utils,A=new odf.OdfUtils,w=new gui.StyleHelper(k.getFormatting()),x=new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]),v,u,s,H;this.isAlignedLeft=function(){return v};this.isAlignedCenter=function(){return u};this.isAlignedRight=function(){return s};this.isAlignedJustified=function(){return H};this.alignParagraphLeft=function(){b("left");return!0};this.alignParagraphCenter=function(){b("center");
-return!0};this.alignParagraphRight=function(){b("right");return!0};this.alignParagraphJustified=function(){b("justify");return!0};this.indent=function(){e(q.bind(null,1));return!0};this.outdent=function(){e(q.bind(null,-1));return!0};this.subscribe=function(a,b){x.subscribe(a,b)};this.unsubscribe=function(a,b){x.unsubscribe(a,b)};this.destroy=function(a){k.unsubscribe(ops.OdtDocument.signalCursorAdded,r);k.unsubscribe(ops.OdtDocument.signalCursorRemoved,n);k.unsubscribe(ops.OdtDocument.signalCursorMoved,
-h);k.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,d);k.unsubscribe(ops.OdtDocument.signalParagraphChanged,m);a()};k.subscribe(ops.OdtDocument.signalCursorAdded,r);k.subscribe(ops.OdtDocument.signalCursorRemoved,n);k.subscribe(ops.OdtDocument.signalCursorMoved,h);k.subscribe(ops.OdtDocument.signalParagraphStyleModified,d);k.subscribe(ops.OdtDocument.signalParagraphChanged,m);p()};gui.DirectParagraphStyler.paragraphStylingChanged="paragraphStyling/changed";(function(){return gui.DirectParagraphStyler})();
-// Input 94
+gui.SelectionViewManager=function(k){function h(){return Object.keys(b).map(function(h){return b[h]})}var b={};this.getSelectionView=function(h){return b.hasOwnProperty(h)?b[h]:null};this.getSelectionViews=h;this.removeSelectionView=function(h){b.hasOwnProperty(h)&&(b[h].destroy(function(){}),delete b[h])};this.hideSelectionView=function(h){b.hasOwnProperty(h)&&b[h].hide()};this.showSelectionView=function(h){b.hasOwnProperty(h)&&b[h].show()};this.rerenderSelectionViews=function(){Object.keys(b).forEach(function(h){b[h].rerender()})};
+this.registerCursor=function(h,d){var n=h.getMemberId(),g=new k(h);d?g.show():g.hide();return b[n]=g};this.destroy=function(b){function d(g,h){h?b(h):g<k.length?k[g].destroy(function(b){d(g+1,b)}):b()}var k=h();d(0,void 0)}};
+// Input 103
/*
- Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -2894,23 +3152,27 @@ h);k.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,d);k.unsubscribe(o
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.EventNotifier");runtime.loadClass("core.Utils");runtime.loadClass("ops.OpApplyDirectStyling");runtime.loadClass("gui.StyleHelper");
-gui.DirectTextStyler=function(g,l){function f(a,b){for(var c=0,d=b[c];d&&a;)a=a[d],c+=1,d=b[c];return b.length===c?a:void 0}function p(a,b){var c=f(a[0],b);return a.every(function(a){return c===f(a,b)})?c:void 0}function r(){var a=u.getCursor(l),a=(a=a&&a.getSelectedRange())&&s.getAppliedStyles(a)||[];a[0]&&y&&(a[0]=v.mergeObjects(a[0],y));return a}function n(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b,c;B=r();L=a(L,B?s.isBold(B):!1,"isBold");I=a(I,B?s.isItalic(B):!1,"isItalic");
-W=a(W,B?s.hasUnderline(B):!1,"hasUnderline");Q=a(Q,B?s.hasStrikeThrough(B):!1,"hasStrikeThrough");b=B&&p(B,["style:text-properties","fo:font-size"]);z=a(z,b&&parseFloat(b),"fontSize");ja=a(ja,B&&p(B,["style:text-properties","style:font-name"]),"fontName");c&&H.emit(gui.DirectTextStyler.textStylingChanged,c)}function h(a){a.getMemberId()===l&&n()}function d(a){a===l&&n()}function m(a){a.getMemberId()===l&&n()}function c(){n()}function e(a){var b=u.getCursor(l);b&&u.getParagraphElement(b.getNode())===
-a.paragraphElement&&n()}function a(a,b){var c=u.getCursor(l);if(!c)return!1;c=s.getAppliedStyles(c.getSelectedRange());b(!a(c));return!0}function b(a){var b=u.getCursorSelection(l),c={"style:text-properties":a};0!==b.length?(a=new ops.OpApplyDirectStyling,a.init({memberid:l,position:b.position,length:b.length,setProperties:c}),g.enqueue([a])):(y=v.mergeObjects(y||{},c),n())}function q(a,c){var d={};d[a]=c;b(d)}function k(a){a=a.spec();y&&a.memberid===l&&"SplitParagraph"!==a.optype&&(y=null,n())}function t(a){q("fo:font-weight",
-a?"bold":"normal")}function A(a){q("fo:font-style",a?"italic":"normal")}function w(a){q("style:text-underline-style",a?"solid":"none")}function x(a){q("style:text-line-through-style",a?"solid":"none")}var v=new core.Utils,u=g.getOdtDocument(),s=new gui.StyleHelper(u.getFormatting()),H=new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]),y,B=[],L=!1,I=!1,W=!1,Q=!1,z,ja;this.formatTextSelection=b;this.createCursorStyleOp=function(a,b){var c=null;y&&(c=new ops.OpApplyDirectStyling,c.init({memberid:l,
-position:a,length:b,setProperties:y}),y=null,n());return c};this.setBold=t;this.setItalic=A;this.setHasUnderline=w;this.setHasStrikethrough=x;this.setFontSize=function(a){q("fo:font-size",a+"pt")};this.setFontName=function(a){q("style:font-name",a)};this.getAppliedStyles=function(){return B};this.toggleBold=a.bind(this,s.isBold,t);this.toggleItalic=a.bind(this,s.isItalic,A);this.toggleUnderline=a.bind(this,s.hasUnderline,w);this.toggleStrikethrough=a.bind(this,s.hasStrikeThrough,x);this.isBold=function(){return L};
-this.isItalic=function(){return I};this.hasUnderline=function(){return W};this.hasStrikeThrough=function(){return Q};this.fontSize=function(){return z};this.fontName=function(){return ja};this.subscribe=function(a,b){H.subscribe(a,b)};this.unsubscribe=function(a,b){H.unsubscribe(a,b)};this.destroy=function(a){u.unsubscribe(ops.OdtDocument.signalCursorAdded,h);u.unsubscribe(ops.OdtDocument.signalCursorRemoved,d);u.unsubscribe(ops.OdtDocument.signalCursorMoved,m);u.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,
-c);u.unsubscribe(ops.OdtDocument.signalParagraphChanged,e);u.unsubscribe(ops.OdtDocument.signalOperationExecuted,k);a()};u.subscribe(ops.OdtDocument.signalCursorAdded,h);u.subscribe(ops.OdtDocument.signalCursorRemoved,d);u.subscribe(ops.OdtDocument.signalCursorMoved,m);u.subscribe(ops.OdtDocument.signalParagraphStyleModified,c);u.subscribe(ops.OdtDocument.signalParagraphChanged,e);u.subscribe(ops.OdtDocument.signalOperationExecuted,k);n()};gui.DirectTextStyler.textStylingChanged="textStyling/changed";
-(function(){return gui.DirectTextStyler})();
-// Input 95
-runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.ObjectNameGenerator");
-gui.ImageManager=function(g,l,f){var p={"image/gif":".gif","image/jpeg":".jpg","image/png":".png"},r=odf.Namespaces.textns,n=g.getOdtDocument(),h=n.getFormatting(),d={};this.insertImage=function(m,c,e,a){var b;runtime.assert(0<e&&0<a,"Both width and height of the image should be greater than 0px.");b=n.getParagraphElement(n.getCursor(l).getNode()).getAttributeNS(r,"style-name");d.hasOwnProperty(b)||(d[b]=h.getContentSize(b,"paragraph"));b=d[b];e*=0.0264583333333334;a*=0.0264583333333334;var q=1,k=
-1;e>b.width&&(q=b.width/e);a>b.height&&(k=b.height/a);q=Math.min(q,k);b=e*q;e=a*q;k=n.getOdfCanvas().odfContainer().rootElement.styles;a=m.toLowerCase();var q=p.hasOwnProperty(a)?p[a]:null,t;a=[];runtime.assert(null!==q,"Image type is not supported: "+m);q="Pictures/"+f.generateImageName()+q;t=new ops.OpSetBlob;t.init({memberid:l,filename:q,mimetype:m,content:c});a.push(t);h.getStyleElement("Graphics","graphic",[k])||(m=new ops.OpAddStyle,m.init({memberid:l,styleName:"Graphics",styleFamily:"graphic",
-isAutomaticStyle:!1,setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph","svg:x":"0cm","svg:y":"0cm","style:wrap":"dynamic","style:number-wrapped-paragraphs":"no-limit","style:wrap-contour":"false","style:vertical-pos":"top","style:vertical-rel":"paragraph","style:horizontal-pos":"center","style:horizontal-rel":"paragraph"}}}),a.push(m));m=f.generateStyleName();c=new ops.OpAddStyle;c.init({memberid:l,styleName:m,styleFamily:"graphic",isAutomaticStyle:!0,setProperties:{"style:parent-style-name":"Graphics",
-"style:graphic-properties":{"style:vertical-pos":"top","style:vertical-rel":"baseline","style:horizontal-pos":"center","style:horizontal-rel":"paragraph","fo:background-color":"transparent","style:background-transparency":"100%","style:shadow":"none","style:mirror":"none","fo:clip":"rect(0cm, 0cm, 0cm, 0cm)","draw:luminance":"0%","draw:contrast":"0%","draw:red":"0%","draw:green":"0%","draw:blue":"0%","draw:gamma":"100%","draw:color-inversion":"false","draw:image-opacity":"100%","draw:color-mode":"standard"}}});
-a.push(c);t=new ops.OpInsertImage;t.init({memberid:l,position:n.getCursorPosition(l),filename:q,frameWidth:b+"cm",frameHeight:e+"cm",frameStyleName:m,frameName:f.generateFrameName()});a.push(t);g.enqueue(a)}};
-// Input 96
+gui.SessionViewOptions=function(){this.caretBlinksOnRangeSelect=this.caretAvatarsInitiallyVisible=this.editInfoMarkersInitiallyVisible=!0};
+(function(){gui.SessionView=function(k,h,b,p,d){function n(a,b,c){function d(b,c,e){c=b+'[editinfo|memberid="'+a+'"]'+e+c;a:{var f=m.firstChild;for(b=b+'[editinfo|memberid="'+a+'"]'+e+"{";f;){if(f.nodeType===Node.TEXT_NODE&&0===f.data.indexOf(b)){b=f;break a}f=f.nextSibling}b=null}b?b.data=c:m.appendChild(document.createTextNode(c))}d("div.editInfoMarker","{ background-color: "+c+"; }","");d("span.editInfoColor","{ background-color: "+c+"; }","");d("span.editInfoAuthor",'{ content: "'+b+'"; }',":before");
+d("dc|creator","{ background-color: "+c+"; }","");d(".selectionOverlay","{ fill: "+c+"; stroke: "+c+";}","")}function g(a){var b,c;for(c in t)t.hasOwnProperty(c)&&(b=t[c],a?b.show():b.hide())}function q(a){p.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function r(a){var b=a.getMemberId();a=a.getProperties();n(b,a.fullName,a.color);h===b&&n("","",a.color)}function l(a){var c=a.getMemberId(),e=b.getOdtDocument().getMember(c).getProperties();p.registerCursor(a,z,x);d.registerCursor(a,
+!0);if(a=p.getCaret(c))a.setAvatarImageUrl(e.imageUrl),a.setColor(e.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+c+"'! +++")}function f(a){a=a.getMemberId();var b=d.getSelectionView(h),c=d.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),e=p.getCaret(h);a===h?(c.hide(),b&&b.show(),e&&e.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(c.show(),b&&b.hide(),e&&e.hide())}function c(a){d.removeSelectionView(a)}function a(a){var c=a.paragraphElement,d=a.memberId;a=a.timeStamp;
+var f,g="",h=c.getElementsByTagNameNS(e,"editinfo").item(0);h?(g=h.getAttributeNS(e,"id"),f=t[g]):(g=Math.random().toString(),f=new ops.EditInfo(c,b.getOdtDocument()),f=new gui.EditInfoMarker(f,w),h=c.getElementsByTagNameNS(e,"editinfo").item(0),h.setAttributeNS(e,"id",g),t[g]=f);f.addEdit(d,new Date(a))}var m,e="urn:webodf:names:editinfo",t={},w=void 0!==k.editInfoMarkersInitiallyVisible?Boolean(k.editInfoMarkersInitiallyVisible):!0,z=void 0!==k.caretAvatarsInitiallyVisible?Boolean(k.caretAvatarsInitiallyVisible):
+!0,x=void 0!==k.caretBlinksOnRangeSelect?Boolean(k.caretBlinksOnRangeSelect):!0;this.showEditInfoMarkers=function(){w||(w=!0,g(w))};this.hideEditInfoMarkers=function(){w&&(w=!1,g(w))};this.showCaretAvatars=function(){z||(z=!0,q(z))};this.hideCaretAvatars=function(){z&&(z=!1,q(z))};this.getSession=function(){return b};this.getCaret=function(a){return p.getCaret(a)};this.destroy=function(e){var g=b.getOdtDocument(),h=Object.keys(t).map(function(a){return t[a]});g.unsubscribe(ops.Document.signalMemberAdded,
+r);g.unsubscribe(ops.Document.signalMemberUpdated,r);g.unsubscribe(ops.Document.signalCursorAdded,l);g.unsubscribe(ops.Document.signalCursorRemoved,c);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,a);g.unsubscribe(ops.Document.signalCursorMoved,f);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,d.rerenderSelectionViews);g.unsubscribe(ops.OdtDocument.signalTableAdded,d.rerenderSelectionViews);g.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,d.rerenderSelectionViews);m.parentNode.removeChild(m);
+(function J(a,b){b?e(b):a<h.length?h[a].destroy(function(b){J(a+1,b)}):e()})(0,void 0)};(function(){var e=b.getOdtDocument(),g=document.getElementsByTagName("head").item(0);e.subscribe(ops.Document.signalMemberAdded,r);e.subscribe(ops.Document.signalMemberUpdated,r);e.subscribe(ops.Document.signalCursorAdded,l);e.subscribe(ops.Document.signalCursorRemoved,c);e.subscribe(ops.OdtDocument.signalParagraphChanged,a);e.subscribe(ops.Document.signalCursorMoved,f);e.subscribe(ops.OdtDocument.signalParagraphChanged,
+d.rerenderSelectionViews);e.subscribe(ops.OdtDocument.signalTableAdded,d.rerenderSelectionViews);e.subscribe(ops.OdtDocument.signalParagraphStyleModified,d.rerenderSelectionViews);m=document.createElementNS(g.namespaceURI,"style");m.type="text/css";m.media="screen, print, handheld, projection";m.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));m.appendChild(document.createTextNode("@namespace dc url(http://purl.org/dc/elements/1.1/);"));g.appendChild(m)})()}})();
+// Input 104
+gui.SvgSelectionView=function(k){function h(){var b=a.getRootNode();m!==b&&(m=b,e=m.parentNode.parentNode.parentNode,e.appendChild(z),z.setAttribute("class","selectionOverlay"),z.appendChild(x))}function b(b){var c=u.getBoundingClientRect(e),d=a.getCanvas().getZoomLevel(),f={};f.top=u.adaptRangeDifferenceToZoomLevel(b.top-c.top,d);f.left=u.adaptRangeDifferenceToZoomLevel(b.left-c.left,d);f.bottom=u.adaptRangeDifferenceToZoomLevel(b.bottom-c.top,d);f.right=u.adaptRangeDifferenceToZoomLevel(b.right-
+c.left,d);f.width=u.adaptRangeDifferenceToZoomLevel(b.width,d);f.height=u.adaptRangeDifferenceToZoomLevel(b.height,d);return f}function p(a){a=a.getBoundingClientRect();return Boolean(a&&0!==a.height)}function d(a){var b=v.getTextElements(a,!0,!1),c=a.cloneRange(),d=a.cloneRange();a=a.cloneRange();if(!b.length)return null;var e;a:{e=0;var f=b[e],g=c.startContainer===f?c.startOffset:0,h=g;c.setStart(f,g);for(c.setEnd(f,h);!p(c);){if(f.nodeType===Node.ELEMENT_NODE&&h<f.childNodes.length)h=f.childNodes.length;
+else if(f.nodeType===Node.TEXT_NODE&&h<f.length)h+=1;else if(b[e])f=b[e],e+=1,g=h=0;else{e=!1;break a}c.setStart(f,g);c.setEnd(f,h)}e=!0}if(!e)return null;a:{e=b.length-1;f=b[e];h=g=d.endContainer===f?d.endOffset:f.nodeType===Node.TEXT_NODE?f.length:f.childNodes.length;d.setStart(f,g);for(d.setEnd(f,h);!p(d);){if(f.nodeType===Node.ELEMENT_NODE&&0<g)g=0;else if(f.nodeType===Node.TEXT_NODE&&0<g)g-=1;else if(b[e])f=b[e],e-=1,g=h=f.length||f.childNodes.length;else{b=!1;break a}d.setStart(f,g);d.setEnd(f,
+h)}b=!0}if(!b)return null;a.setStart(c.startContainer,c.startOffset);a.setEnd(d.endContainer,d.endOffset);return{firstRange:c,lastRange:d,fillerRange:a}}function n(a,b){var c={};c.top=Math.min(a.top,b.top);c.left=Math.min(a.left,b.left);c.right=Math.max(a.right,b.right);c.bottom=Math.max(a.bottom,b.bottom);c.width=c.right-c.left;c.height=c.bottom-c.top;return c}function g(a,b){b&&0<b.width&&0<b.height&&(a=a?n(a,b):b);return a}function q(b){function c(a){A.setUnfilteredPosition(a,0);return w.acceptNode(a)===
+J&&s.acceptPosition(A)===J?J:G}function d(a){var b=null;c(a)===J&&(b=u.getBoundingClientRect(a));return b}var e=b.commonAncestorContainer,f=b.startContainer,h=b.endContainer,m=b.startOffset,k=b.endOffset,l,n,p=null,q,r=t.createRange(),s,w=new odf.OdfNodeFilter,x;if(f===e||h===e)return r=b.cloneRange(),p=r.getBoundingClientRect(),r.detach(),p;for(b=f;b.parentNode!==e;)b=b.parentNode;for(n=h;n.parentNode!==e;)n=n.parentNode;s=a.createRootFilter(f);for(e=b.nextSibling;e&&e!==n;)q=d(e),p=g(p,q),e=e.nextSibling;
+if(v.isParagraph(b))p=g(p,u.getBoundingClientRect(b));else if(b.nodeType===Node.TEXT_NODE)e=b,r.setStart(e,m),r.setEnd(e,e===n?k:e.length),q=r.getBoundingClientRect(),p=g(p,q);else for(x=t.createTreeWalker(b,NodeFilter.SHOW_TEXT,c,!1),e=x.currentNode=f;e&&e!==h;)r.setStart(e,m),r.setEnd(e,e.length),q=r.getBoundingClientRect(),p=g(p,q),l=e,m=0,e=x.nextNode();l||(l=f);if(v.isParagraph(n))p=g(p,u.getBoundingClientRect(n));else if(n.nodeType===Node.TEXT_NODE)e=n,r.setStart(e,e===b?m:0),r.setEnd(e,k),
+q=r.getBoundingClientRect(),p=g(p,q);else for(x=t.createTreeWalker(n,NodeFilter.SHOW_TEXT,c,!1),e=x.currentNode=h;e&&e!==l;)if(r.setStart(e,0),r.setEnd(e,k),q=r.getBoundingClientRect(),p=g(p,q),e=x.previousNode())k=e.length;return p}function r(a,b){var c=a.getBoundingClientRect(),d={width:0};d.top=c.top;d.bottom=c.bottom;d.height=c.height;d.left=d.right=b?c.right:c.left;return d}function l(){var a=k.getSelectedRange(),c;if(c=s&&k.getSelectionType()===ops.OdtCursor.RangeSelection&&!a.collapsed){h();
+var a=d(a),e,f,g,m,l,p,t,u;if(a){c=a.firstRange;e=a.lastRange;f=a.fillerRange;g=b(r(c,!1));l=b(r(e,!0));m=(m=q(f))?b(m):n(g,l);p=m.left;m=g.left+Math.max(0,m.width-(g.left-m.left));t=Math.min(g.top,l.top);u=l.top+l.height;g=[{x:g.left,y:t+g.height},{x:g.left,y:t},{x:m,y:t},{x:m,y:u-l.height},{x:l.right,y:u-l.height},{x:l.right,y:u},{x:p,y:u},{x:p,y:t+g.height},{x:g.left,y:t+g.height}];l="";for(p=0;p<g.length;p+=1)l+=g[p].x+","+g[p].y+" ";x.setAttribute("points",l);c.detach();e.detach();f.detach()}c=
+Boolean(a)}z.style.display=c?"block":"none"}function f(a){s&&a===k&&D.trigger()}function c(a){e.removeChild(z);k.getDocument().unsubscribe(ops.Document.signalCursorMoved,f);a()}var a=k.getDocument(),m,e,t=a.getDOMDocument(),w=new core.Async,z=t.createElementNS("http://www.w3.org/2000/svg","svg"),x=t.createElementNS("http://www.w3.org/2000/svg","polygon"),v=new odf.OdfUtils,u=new core.DomUtils,s=!0,A=gui.SelectionMover.createPositionIterator(a.getRootNode()),J=NodeFilter.FILTER_ACCEPT,G=NodeFilter.FILTER_REJECT,
+D;this.rerender=function(){s&&D.trigger()};this.show=function(){s=!0;D.trigger()};this.hide=function(){s=!1;D.trigger()};this.destroy=function(a){w.destroyAll([D.destroy,c],a)};(function(){var a=k.getMemberId();D=new core.ScheduledTask(l,0);h();z.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",a);k.getDocument().subscribe(ops.Document.signalCursorMoved,f)})()};
+// Input 105
/*
Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@@ -2948,45 +3210,13 @@ a.push(c);t=new ops.OpInsertImage;t.init({memberid:l,position:n.getCursorPositio
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("core.PositionFilter");
-gui.TextManipulator=function(g,l,f){function p(d){var c=new ops.OpRemoveText;c.init({memberid:l,position:d.position,length:d.length});return c}function r(d){0>d.length&&(d.position+=d.length,d.length=-d.length);return d}function n(f,c){var e=new core.PositionFilterChain,a=gui.SelectionMover.createPositionIterator(h.getRootElement(f)),b=c?a.nextPosition:a.previousPosition;e.addFilter("BaseFilter",h.getPositionFilter());e.addFilter("RootFilter",h.createRootFilter(l));for(a.setUnfilteredPosition(f,0);b();)if(e.acceptPosition(a)===
-d)return!0;return!1}var h=g.getOdtDocument(),d=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.enqueueParagraphSplittingOps=function(){var d=r(h.getCursorSelection(l)),c,e=[];0<d.length&&(c=p(d),e.push(c));c=new ops.OpSplitParagraph;c.init({memberid:l,position:d.position,moveCursor:!0});e.push(c);g.enqueue(e);return!0};this.removeTextByBackspaceKey=function(){var d=h.getCursor(l),c=r(h.getCursorSelection(l)),e=null;0===c.length?n(d.getNode(),!1)&&(e=new ops.OpRemoveText,e.init({memberid:l,position:c.position-
-1,length:1}),g.enqueue([e])):(e=p(c),g.enqueue([e]));return null!==e};this.removeTextByDeleteKey=function(){var d=h.getCursor(l),c=r(h.getCursorSelection(l)),e=null;0===c.length?n(d.getNode(),!0)&&(e=new ops.OpRemoveText,e.init({memberid:l,position:c.position,length:1}),g.enqueue([e])):(e=p(c),g.enqueue([e]));return null!==e};this.removeCurrentSelection=function(){var d=r(h.getCursorSelection(l));0!==d.length&&(d=p(d),g.enqueue([d]));return!0};this.insertText=function(d){var c=r(h.getCursorSelection(l)),
-e,a=[];0<c.length&&(e=p(c),a.push(e));e=new ops.OpInsertText;e.init({memberid:l,position:c.position,text:d,moveCursor:!0});a.push(e);f&&(d=f(c.position,d.length))&&a.push(d);g.enqueue(a)}};(function(){return gui.TextManipulator})();
-// Input 97
-runtime.loadClass("core.DomUtils");runtime.loadClass("core.Async");runtime.loadClass("core.ScheduledTask");runtime.loadClass("odf.OdfUtils");runtime.loadClass("odf.ObjectNameGenerator");runtime.loadClass("ops.OdtCursor");runtime.loadClass("ops.OpAddCursor");runtime.loadClass("ops.OpRemoveCursor");runtime.loadClass("gui.Clipboard");runtime.loadClass("gui.DirectTextStyler");runtime.loadClass("gui.DirectParagraphStyler");runtime.loadClass("gui.KeyboardHandler");runtime.loadClass("gui.ImageManager");
-runtime.loadClass("gui.ImageSelector");runtime.loadClass("gui.TextManipulator");runtime.loadClass("gui.AnnotationController");runtime.loadClass("gui.EventManager");runtime.loadClass("gui.PlainTextPasteboard");
-gui.SessionController=function(){var g=core.PositionFilter.FilterResult.FILTER_ACCEPT;gui.SessionController=function(l,f,p,r){function n(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function h(a,b,c){var d=new ops.OpMoveCursor;d.init({memberid:f,position:a,length:b||0,selectionType:c});return d}function d(a){var b=/[A-Za-z0-9]/,c=gui.SelectionMover.createPositionIterator(D.getRootNode()),d;for(c.setUnfilteredPosition(a.startContainer,a.startOffset);c.previousPosition();){d=c.getCurrentNode();
-if(d.nodeType===Node.TEXT_NODE){if(d=d.data[c.unfilteredDomOffset()],!b.test(d))break}else if(!ia.isTextSpan(d))break;a.setStart(c.container(),c.unfilteredDomOffset())}c.setUnfilteredPosition(a.endContainer,a.endOffset);do if(d=c.getCurrentNode(),d.nodeType===Node.TEXT_NODE){if(d=d.data[c.unfilteredDomOffset()],!b.test(d))break}else if(!ia.isTextSpan(d))break;while(c.nextPosition());a.setEnd(c.container(),c.unfilteredDomOffset())}function m(a){var b=D.getParagraphElement(a.startContainer),c=D.getParagraphElement(a.endContainer);
-b&&a.setStart(b,0);c&&(ia.isParagraph(a.endContainer)&&0===a.endOffset?a.setEndBefore(c):a.setEnd(c,c.childNodes.length))}function c(a){a=D.getDistanceFromCursor(f,a,0);var b=null!==a?a+1:null,c;if(b||a)c=D.getCursorPosition(f),a=h(c+a,b-a,ops.OdtCursor.RegionSelection),l.enqueue([a]);K.focus()}function e(a){var b=0<=ha.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset),c=a.focusNode.ownerDocument.createRange();b?(c.setStart(a.anchorNode,a.anchorOffset),c.setEnd(a.focusNode,a.focusOffset)):
-(c.setStart(a.focusNode,a.focusOffset),c.setEnd(a.anchorNode,a.anchorOffset));return{range:c,hasForwardSelection:b}}function a(a){return function(b){var c=a(b);return function(b,d){return a(d)===c}}}function b(b,c,e){var g=D.getOdfCanvas().getElement(),k;k=ha.containsNode(g,b.startContainer);g=ha.containsNode(g,b.endContainer);if(k||g)if(k&&g&&(2===e?d(b):3<=e&&m(b)),b=c?{anchorNode:b.startContainer,anchorOffset:b.startOffset,focusNode:b.endContainer,focusOffset:b.endOffset}:{anchorNode:b.endContainer,
-anchorOffset:b.endOffset,focusNode:b.startContainer,focusOffset:b.startOffset},c=D.convertDomToCursorRange(b,a(ia.getParagraphElement)),b=D.getCursorSelection(f),c.position!==b.position||c.length!==b.length)b=h(c.position,c.length,ops.OdtCursor.RangeSelection),l.enqueue([b])}function q(a){var b=D.getCursorSelection(f),c=D.getCursor(f).getStepCounter();0!==a&&(a=0<a?c.convertForwardStepsBetweenFilters(a,sa,xa):-c.convertBackwardStepsBetweenFilters(-a,sa,xa),a=b.length+a,l.enqueue([h(b.position,a)]))}
-function k(a){var b=D.getCursorPosition(f),c=D.getCursor(f).getStepCounter();0!==a&&(a=0<a?c.convertForwardStepsBetweenFilters(a,sa,xa):-c.convertBackwardStepsBetweenFilters(-a,sa,xa),l.enqueue([h(b+a,0)]))}function t(){k(-1);return!0}function A(){k(1);return!0}function w(){q(-1);return!0}function x(){q(1);return!0}function v(a,b){var c=D.getParagraphElement(D.getCursor(f).getNode());runtime.assert(Boolean(c),"SessionController: Cursor outside paragraph");c=D.getCursor(f).getStepCounter().countLinesSteps(a,
-sa);b?q(c):k(c)}function u(){v(-1,!1);return!0}function s(){v(1,!1);return!0}function H(){v(-1,!0);return!0}function y(){v(1,!0);return!0}function B(a,b){var c=D.getCursor(f).getStepCounter().countStepsToLineBoundary(a,sa);b?q(c):k(c)}function L(){B(-1,!1);return!0}function I(){B(1,!1);return!0}function W(){B(-1,!0);return!0}function Q(){B(1,!0);return!0}function z(){var a=D.getParagraphElement(D.getCursor(f).getNode()),b,c;runtime.assert(Boolean(a),"SessionController: Cursor outside paragraph");
-c=D.getDistanceFromCursor(f,a,0);b=gui.SelectionMover.createPositionIterator(D.getRootNode());for(b.setUnfilteredPosition(a,0);0===c&&b.previousPosition();)a=b.getCurrentNode(),ia.isParagraph(a)&&(c=D.getDistanceFromCursor(f,a,0));q(c);return!0}function ja(){var a=D.getParagraphElement(D.getCursor(f).getNode()),b,c;runtime.assert(Boolean(a),"SessionController: Cursor outside paragraph");b=gui.SelectionMover.createPositionIterator(D.getRootNode());b.moveToEndOfNode(a);for(c=D.getDistanceFromCursor(f,
-b.container(),b.unfilteredDomOffset());0===c&&b.nextPosition();)a=b.getCurrentNode(),ia.isParagraph(a)&&(b.moveToEndOfNode(a),c=D.getDistanceFromCursor(f,b.container(),b.unfilteredDomOffset()));q(c);return!0}function ka(a,b){var c=gui.SelectionMover.createPositionIterator(D.getRootNode());0<a&&c.moveToEnd();c=D.getDistanceFromCursor(f,c.container(),c.unfilteredDomOffset());b?q(c):k(c)}function G(){ka(-1,!1);return!0}function Z(){ka(1,!1);return!0}function O(){ka(-1,!0);return!0}function aa(){ka(1,
-!0);return!0}function J(){var a=D.getRootNode(),a=D.convertDomPointToCursorStep(a,a.childNodes.length);l.enqueue([h(0,a)]);return!0}function F(){var a=D.getCursor(f);if(a&&a.getSelectionType()===ops.OdtCursor.RegionSelection&&(a=ia.getImageElements(a.getSelectedRange())[0])){ya.select(a.parentNode);return}ya.clearSelection()}function C(a){var b=D.getCursor(f).getSelectedRange();b.collapsed?a.preventDefault():Da.setDataFromRange(a,b)?oa.removeCurrentSelection():runtime.log("Cut operation failed")}
-function Y(){return!1!==D.getCursor(f).getSelectedRange().collapsed}function U(a){var b=D.getCursor(f).getSelectedRange();b.collapsed?a.preventDefault():Da.setDataFromRange(a,b)||runtime.log("Copy operation failed")}function R(a){var b;fa.clipboardData&&fa.clipboardData.getData?b=fa.clipboardData.getData("Text"):a.clipboardData&&a.clipboardData.getData&&(b=a.clipboardData.getData("text/plain"));b&&(oa.removeCurrentSelection(),l.enqueue(Fa.createPasteOps(b)));a.preventDefault?a.preventDefault():a.returnValue=
-!1}function P(){return!1}function M(a){if(V)V.onOperationExecuted(a)}function ba(a){D.emit(ops.OdtDocument.signalUndoStackChanged,a)}function la(){return V?(V.moveBackward(1),va.trigger(),!0):!1}function ca(){return V?(V.moveForward(1),va.trigger(),!0):!1}function ma(){var a=fa.getSelection(),b=0<a.rangeCount&&e(a);ra&&b&&(ta=!0,ya.clearSelection(),Ea.setUnfilteredPosition(a.focusNode,a.focusOffset),Ba.acceptPosition(Ea)===g&&(2===wa?d(b.range):3<=wa&&m(b.range),p.setSelectedRange(b.range,b.hasForwardSelection),
-D.emit(ops.OdtDocument.signalCursorMoved,p)))}function T(a){var b=a.target||a.srcElement,c=D.getCursor(f);if(ra=b&&ha.containsNode(D.getOdfCanvas().getElement(),b))ta=!1,Ba=D.createRootFilter(b),wa=a.detail,c&&a.shiftKey?fa.getSelection().collapse(c.getAnchorNode(),0):(a=fa.getSelection(),b=c.getSelectedRange(),a.extend?c.hasForwardSelection()?(a.collapse(b.startContainer,b.startOffset),a.extend(b.endContainer,b.endOffset)):(a.collapse(b.endContainer,b.endOffset),a.extend(b.startContainer,b.startOffset)):
-(a.removeAllRanges(),a.addRange(b.cloneRange()),D.getOdfCanvas().getElement().setActive())),1<wa&&ma()}function $(a){var d=a.target||a.srcElement,f=a.detail,g=a.clientX,h=a.clientY;za.processRequests();ia.isImage(d)&&ia.isCharacterFrame(d.parentNode)?(c(d.parentNode),K.focus()):ra&&!ya.isSelectorElement(d)&&(ta?(b(p.getSelectedRange(),p.hasForwardSelection(),a.detail),K.focus()):runtime.setTimeout(function(){var a;a=(a=fa.getSelection())?{anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,
-focusOffset:a.focusOffset}:null;var c;if(!a.anchorNode&&!a.focusNode){var d=D.getDOM();c=null;d.caretRangeFromPoint?(d=d.caretRangeFromPoint(g,h),c={container:d.startContainer,offset:d.startOffset}):d.caretPositionFromPoint&&(d=d.caretPositionFromPoint(g,h))&&d.offsetNode&&(c={container:d.offsetNode,offset:d.offset});c&&(a.anchorNode=c.container,a.anchorOffset=c.offset,a.focusNode=a.anchorNode,a.focusOffset=a.anchorOffset)}a.anchorNode&&a.focusNode&&(a=e(a),b(a.range,a.hasForwardSelection,f));K.focus()},
-0));wa=0;ta=ra=!1}function X(){ra&&K.focus();wa=0;ta=ra=!1}function da(a){$(a)}function S(a){var b=a.target||a.srcElement,c=null;"annotationRemoveButton"===b.className?(c=ha.getElementsByTagNameNS(b.parentNode,odf.Namespaces.officens,"annotation")[0],ua.removeAnnotation(c)):$(a)}function ga(a){return function(){a();return!0}}function E(a){return function(b){return D.getCursor(f).getSelectionType()===ops.OdtCursor.RangeSelection?a(b):!0}}var fa=runtime.getWindow(),D=l.getOdtDocument(),pa=new core.Async,
-ha=new core.DomUtils,ia=new odf.OdfUtils,Da=new gui.Clipboard,N=new gui.KeyboardHandler,qa=new gui.KeyboardHandler,sa=new core.PositionFilterChain,xa=D.getPositionFilter(),ra=!1,Aa=new odf.ObjectNameGenerator(D.getOdfCanvas().odfContainer(),f),ta=!1,Ba=null,V=null,K=new gui.EventManager(D),ua=new gui.AnnotationController(l,f),na=new gui.DirectTextStyler(l,f),ea=r&&r.directParagraphStylingEnabled?new gui.DirectParagraphStyler(l,f,Aa):null,oa=new gui.TextManipulator(l,f,na.createCursorStyleOp),Ca=new gui.ImageManager(l,
-f,Aa),ya=new gui.ImageSelector(D.getOdfCanvas()),Ea=gui.SelectionMover.createPositionIterator(D.getRootNode()),za,va,Fa=new gui.PlainTextPasteboard(D,f),wa=0;runtime.assert(null!==fa,"Expected to be run in an environment which has a global window, like a browser.");sa.addFilter("BaseFilter",xa);sa.addFilter("RootFilter",D.createRootFilter(f));this.selectRange=b;this.moveCursorToLeft=t;this.moveCursorToDocumentBoundary=ka;this.extendSelectionToEntireDocument=J;this.startEditing=function(){var a;D.getOdfCanvas().getElement().classList.add("virtualSelections");
-K.subscribe("keydown",N.handleEvent);K.subscribe("keypress",qa.handleEvent);K.subscribe("keyup",n);K.subscribe("beforecut",Y);K.subscribe("cut",C);K.subscribe("copy",U);K.subscribe("beforepaste",P);K.subscribe("paste",R);K.subscribe("mousedown",T);K.subscribe("mousemove",za.trigger);K.subscribe("mouseup",S);K.subscribe("contextmenu",da);K.subscribe("dragend",X);D.subscribe(ops.OdtDocument.signalOperationExecuted,va.trigger);D.subscribe(ops.OdtDocument.signalOperationExecuted,M);a=new ops.OpAddCursor;
-a.init({memberid:f});l.enqueue([a]);V&&V.saveInitialState()};this.endEditing=function(){var a;a=new ops.OpRemoveCursor;a.init({memberid:f});l.enqueue([a]);V&&V.resetInitialState();D.unsubscribe(ops.OdtDocument.signalOperationExecuted,M);D.unsubscribe(ops.OdtDocument.signalOperationExecuted,va.trigger);K.unsubscribe("keydown",N.handleEvent);K.unsubscribe("keypress",qa.handleEvent);K.unsubscribe("keyup",n);K.unsubscribe("cut",C);K.unsubscribe("beforecut",Y);K.unsubscribe("copy",U);K.unsubscribe("paste",
-R);K.unsubscribe("beforepaste",P);K.unsubscribe("mousemove",za.trigger);K.unsubscribe("mousedown",T);K.unsubscribe("mouseup",S);K.unsubscribe("contextmenu",da);K.unsubscribe("dragend",X);D.getOdfCanvas().getElement().classList.remove("virtualSelections")};this.getInputMemberId=function(){return f};this.getSession=function(){return l};this.setUndoManager=function(a){V&&V.unsubscribe(gui.UndoManager.signalUndoStackChanged,ba);if(V=a)V.setOdtDocument(D),V.setPlaybackFunction(function(a){a.execute(D)}),
-V.subscribe(gui.UndoManager.signalUndoStackChanged,ba)};this.getUndoManager=function(){return V};this.getAnnotationController=function(){return ua};this.getDirectTextStyler=function(){return na};this.getDirectParagraphStyler=function(){return ea};this.getImageManager=function(){return Ca};this.getTextManipulator=function(){return oa};this.getEventManager=function(){return K};this.getKeyboardHandlers=function(){return{keydown:N,keypress:qa}};this.destroy=function(a){var b=[za.destroy,na.destroy];ea&&
-b.push(ea.destroy);pa.destroyAll(b,a)};(function(){var a=-1!==fa.navigator.appVersion.toLowerCase().indexOf("mac"),b=gui.KeyboardHandler.Modifier,c=gui.KeyboardHandler.KeyCode;za=new core.ScheduledTask(ma,0);va=new core.ScheduledTask(F,0);N.bind(c.Tab,b.None,E(function(){oa.insertText("\t");return!0}));N.bind(c.Left,b.None,E(t));N.bind(c.Right,b.None,E(A));N.bind(c.Up,b.None,E(u));N.bind(c.Down,b.None,E(s));N.bind(c.Backspace,b.None,ga(oa.removeTextByBackspaceKey));N.bind(c.Delete,b.None,oa.removeTextByDeleteKey);
-N.bind(c.Left,b.Shift,E(w));N.bind(c.Right,b.Shift,E(x));N.bind(c.Up,b.Shift,E(H));N.bind(c.Down,b.Shift,E(y));N.bind(c.Home,b.None,E(L));N.bind(c.End,b.None,E(I));N.bind(c.Home,b.Ctrl,E(G));N.bind(c.End,b.Ctrl,E(Z));N.bind(c.Home,b.Shift,E(W));N.bind(c.End,b.Shift,E(Q));N.bind(c.Up,b.CtrlShift,E(z));N.bind(c.Down,b.CtrlShift,E(ja));N.bind(c.Home,b.CtrlShift,E(O));N.bind(c.End,b.CtrlShift,E(aa));a?(N.bind(c.Clear,b.None,oa.removeCurrentSelection),N.bind(c.Left,b.Meta,E(L)),N.bind(c.Right,b.Meta,E(I)),
-N.bind(c.Home,b.Meta,E(G)),N.bind(c.End,b.Meta,E(Z)),N.bind(c.Left,b.MetaShift,E(W)),N.bind(c.Right,b.MetaShift,E(Q)),N.bind(c.Up,b.AltShift,E(z)),N.bind(c.Down,b.AltShift,E(ja)),N.bind(c.Up,b.MetaShift,E(O)),N.bind(c.Down,b.MetaShift,E(aa)),N.bind(c.A,b.Meta,E(J)),N.bind(c.B,b.Meta,E(na.toggleBold)),N.bind(c.I,b.Meta,E(na.toggleItalic)),N.bind(c.U,b.Meta,E(na.toggleUnderline)),ea&&(N.bind(c.L,b.MetaShift,E(ea.alignParagraphLeft)),N.bind(c.E,b.MetaShift,E(ea.alignParagraphCenter)),N.bind(c.R,b.MetaShift,
-E(ea.alignParagraphRight)),N.bind(c.J,b.MetaShift,E(ea.alignParagraphJustified))),ua&&N.bind(c.C,b.MetaShift,ua.addAnnotation),N.bind(c.Z,b.Meta,la),N.bind(c.Z,b.MetaShift,ca)):(N.bind(c.A,b.Ctrl,E(J)),N.bind(c.B,b.Ctrl,E(na.toggleBold)),N.bind(c.I,b.Ctrl,E(na.toggleItalic)),N.bind(c.U,b.Ctrl,E(na.toggleUnderline)),ea&&(N.bind(c.L,b.CtrlShift,E(ea.alignParagraphLeft)),N.bind(c.E,b.CtrlShift,E(ea.alignParagraphCenter)),N.bind(c.R,b.CtrlShift,E(ea.alignParagraphRight)),N.bind(c.J,b.CtrlShift,E(ea.alignParagraphJustified))),
-ua&&N.bind(c.C,b.CtrlAlt,ua.addAnnotation),N.bind(c.Z,b.Ctrl,la),N.bind(c.Z,b.CtrlShift,ca));qa.setDefault(E(function(a){var b;b=null===a.which||void 0===a.which?String.fromCharCode(a.keyCode):0!==a.which&&0!==a.charCode?String.fromCharCode(a.which):null;return!b||a.altKey||a.ctrlKey||a.metaKey?!1:(oa.insertText(b),!0)}));qa.bind(c.Enter,b.None,E(oa.enqueueParagraphSplittingOps))})()};return gui.SessionController}();
-// Input 98
+gui.UndoStateRules=function(){function k(b,h){var g=b.length;this.previous=function(){for(g-=1;0<=g;g-=1)if(h(b[g]))return b[g];return null}}function h(b){b=b.spec();var h;b.hasOwnProperty("position")&&(h=b.position);return h}function b(b){return b.isEdit}function p(b,k,g){if(!g)return g=h(b)-h(k),0===g||1===Math.abs(g);b=h(b);k=h(k);g=h(g);return b-k===k-g}this.isEditOperation=b;this.isPartOfOperationSet=function(d,h){var g=void 0!==d.group,q;if(!d.isEdit||0===h.length)return!0;q=h[h.length-1];if(g&&
+d.group===q.group)return!0;a:switch(d.spec().optype){case "RemoveText":case "InsertText":q=!0;break a;default:q=!1}if(q&&h.some(b)){if(g){var r;g=d.spec().optype;q=new k(h,b);var l=q.previous(),f=null,c,a;runtime.assert(Boolean(l),"No edit operations found in state");a=l.group;runtime.assert(void 0!==a,"Operation has no group");for(c=1;l&&l.group===a;){if(g===l.spec().optype){r=l;break}l=q.previous()}if(r){for(l=q.previous();l;){if(l.group!==a){if(2===c)break;a=l.group;c+=1}if(g===l.spec().optype){f=
+l;break}l=q.previous()}r=p(d,r,f)}else r=!1;return r}r=d.spec().optype;g=new k(h,b);q=g.previous();runtime.assert(Boolean(q),"No edit operations found in state");r=r===q.spec().optype?p(d,q,g.previous()):!1;return r}return!1}};
+// Input 106
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -3021,15 +3251,88 @@ ua&&N.bind(c.C,b.CtrlAlt,ua.addAnnotation),N.bind(c.Z,b.Ctrl,la),N.bind(c.Z,b.Ct
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("gui.Caret");
-gui.CaretManager=function(g){function l(a){return b.hasOwnProperty(a)?b[a]:null}function f(){return Object.keys(b).map(function(a){return b[a]})}function p(a){a===g.getInputMemberId()&&g.getSession().getOdtDocument().getOdfCanvas().getElement().removeAttribute("tabindex");delete b[a]}function r(a){a=a.getMemberId();a===g.getInputMemberId()&&(a=l(a))&&a.refreshCursorBlinking()}function n(){var a=l(g.getInputMemberId());k=!1;a&&a.ensureVisible()}function h(){var a=l(g.getInputMemberId());a&&(a.handleUpdate(),
-k||(k=!0,runtime.setTimeout(n,50)))}function d(a){a.memberId===g.getInputMemberId()&&h()}function m(){var a=l(g.getInputMemberId());a&&a.setFocus()}function c(){var a=l(g.getInputMemberId());a&&a.removeFocus()}function e(){var a=l(g.getInputMemberId());a&&a.show()}function a(){var a=l(g.getInputMemberId());a&&a.hide()}var b={},q=runtime.getWindow(),k=!1;this.registerCursor=function(a,c,d){var e=a.getMemberId();c=new gui.Caret(a,c,d);b[e]=c;e===g.getInputMemberId()?(runtime.log("Starting to track input on new cursor of "+
-e),a.handleUpdate=h,g.getSession().getOdtDocument().getOdfCanvas().getElement().setAttribute("tabindex",-1),g.getEventManager().focus()):a.handleUpdate=c.handleUpdate;return c};this.getCaret=l;this.getCarets=f;this.destroy=function(h){var k=g.getSession().getOdtDocument(),l=g.getEventManager(),n=f();k.unsubscribe(ops.OdtDocument.signalParagraphChanged,d);k.unsubscribe(ops.OdtDocument.signalCursorMoved,r);k.unsubscribe(ops.OdtDocument.signalCursorRemoved,p);l.unsubscribe("focus",m);l.unsubscribe("blur",
-c);q.removeEventListener("focus",e,!1);q.removeEventListener("blur",a,!1);(function u(a,b){b?h(b):a<n.length?n[a].destroy(function(b){u(a+1,b)}):h()})(0,void 0);b={}};(function(){var b=g.getSession().getOdtDocument(),f=g.getEventManager();b.subscribe(ops.OdtDocument.signalParagraphChanged,d);b.subscribe(ops.OdtDocument.signalCursorMoved,r);b.subscribe(ops.OdtDocument.signalCursorRemoved,p);f.subscribe("focus",m);f.subscribe("blur",c);q.addEventListener("focus",e,!1);q.addEventListener("blur",a,!1)})()};
-// Input 99
+gui.TrivialUndoManager=function(k){function h(a){0<a.length&&(u=!0,m(a),u=!1)}function b(){x.emit(gui.UndoManager.signalUndoStackChanged,{undoAvailable:r.hasUndoStates(),redoAvailable:r.hasRedoStates()})}function p(){t!==a&&t!==w[w.length-1]&&w.push(t)}function d(a){var b=a.previousSibling||a.nextSibling;a.parentNode.removeChild(a);f.normalizeTextNodes(b)}function n(a){return Object.keys(a).map(function(b){return a[b]})}function g(a){function b(a){var e=a.spec();if(f[e.memberid])switch(e.optype){case "AddCursor":c[e.memberid]||
+(c[e.memberid]=a,delete f[e.memberid],g-=1);break;case "MoveCursor":d[e.memberid]||(d[e.memberid]=a)}}var c={},d={},f={},g,h=a.pop();e.getMemberIds().forEach(function(a){f[a]=!0});for(g=Object.keys(f).length;h&&0<g;)h.reverse(),h.forEach(b),h=a.pop();return n(c).concat(n(d))}function q(){var h=c=e.cloneDocumentElement();f.getElementsByTagNameNS(h,l,"cursor").forEach(d);f.getElementsByTagNameNS(h,l,"anchor").forEach(d);p();t=a=g([a].concat(w));w.length=0;z.length=0;b()}var r=this,l="urn:webodf:names:cursor",
+f=new core.DomUtils,c,a=[],m,e,t=[],w=[],z=[],x=new core.EventNotifier([gui.UndoManager.signalUndoStackChanged,gui.UndoManager.signalUndoStateCreated,gui.UndoManager.signalUndoStateModified,gui.TrivialUndoManager.signalDocumentRootReplaced]),v=k||new gui.UndoStateRules,u=!1;this.subscribe=function(a,b){x.subscribe(a,b)};this.unsubscribe=function(a,b){x.unsubscribe(a,b)};this.hasUndoStates=function(){return 0<w.length};this.hasRedoStates=function(){return 0<z.length};this.setDocument=function(a){e=
+a};this.purgeInitialState=function(){w.length=0;z.length=0;a.length=0;t.length=0;c=null;b()};this.setInitialState=q;this.initialize=function(){c||q()};this.setPlaybackFunction=function(a){m=a};this.onOperationExecuted=function(c){u||(v.isEditOperation(c)&&(t===a||0<z.length)||!v.isPartOfOperationSet(c,t)?(z.length=0,p(),t=[c],w.push(t),x.emit(gui.UndoManager.signalUndoStateCreated,{operations:t}),b()):(t.push(c),x.emit(gui.UndoManager.signalUndoStateModified,{operations:t})))};this.moveForward=function(a){for(var c=
+0,e;a&&z.length;)e=z.pop(),w.push(e),h(e),a-=1,c+=1;c&&(t=w[w.length-1],b());return c};this.moveBackward=function(d){for(var f=0;d&&w.length;)z.push(w.pop()),d-=1,f+=1;f&&(e.setDocumentElement(c.cloneNode(!0)),x.emit(gui.TrivialUndoManager.signalDocumentRootReplaced,{}),e.getMemberIds().forEach(function(a){e.removeCursor(a)}),h(a),w.forEach(h),t=w[w.length-1]||a,b());return f}};gui.TrivialUndoManager.signalDocumentRootReplaced="documentRootReplaced";(function(){return gui.TrivialUndoManager})();
+// Input 107
/*
- Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OperationTransformMatrix=function(){function k(b){b.position+=b.length;b.length*=-1}function h(b){var a=0>b.length;a&&k(b);return a}function b(b,a){function d(f){b[f]===a&&e.push(f)}var e=[];b&&["style:parent-style-name","style:next-style-name"].forEach(d);return e}function p(b,a){function d(e){b[e]===a&&delete b[e]}b&&["style:parent-style-name","style:next-style-name"].forEach(d)}function d(b){var a={};Object.keys(b).forEach(function(f){a[f]="object"===typeof b[f]?d(b[f]):b[f]});return a}function n(b,
+a,d,e){var f,g=!1,h=!1,k,l=[];e&&e.attributes&&(l=e.attributes.split(","));b&&(d||0<l.length)&&Object.keys(b).forEach(function(a){var e=b[a],f;"object"!==typeof e&&(d&&(f=d[a]),void 0!==f?(delete b[a],h=!0,f===e&&(delete d[a],g=!0)):-1!==l.indexOf(a)&&(delete b[a],h=!0))});if(a&&a.attributes&&(d||0<l.length)){k=a.attributes.split(",");for(e=0;e<k.length;e+=1)if(f=k[e],d&&void 0!==d[f]||l&&-1!==l.indexOf(f))k.splice(e,1),e-=1,h=!0;0<k.length?a.attributes=k.join(","):delete a.attributes}return{majorChanged:g,
+minorChanged:h}}function g(b){for(var a in b)if(b.hasOwnProperty(a))return!0;return!1}function q(b){for(var a in b)if(b.hasOwnProperty(a)&&("attributes"!==a||0<b.attributes.length))return!0;return!1}function r(b,a,d,e,f){var h=b?b[f]:null,k=a?a[f]:null,l=d?d[f]:null,p=e?e[f]:null,r;r=n(h,k,l,p);h&&!g(h)&&delete b[f];k&&!q(k)&&delete a[f];l&&!g(l)&&delete d[f];p&&!q(p)&&delete e[f];return r}function l(b,a){return{opSpecsA:[b],opSpecsB:[a]}}var f;f={AddCursor:{AddCursor:l,AddMember:l,AddStyle:l,ApplyDirectStyling:l,
+InsertText:l,MoveCursor:l,RemoveCursor:l,RemoveMember:l,RemoveStyle:l,RemoveText:l,SetParagraphStyle:l,SplitParagraph:l,UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},AddMember:{AddStyle:l,InsertText:l,MoveCursor:l,RemoveCursor:l,RemoveStyle:l,RemoveText:l,SetParagraphStyle:l,SplitParagraph:l,UpdateMetadata:l,UpdateParagraphStyle:l},AddStyle:{AddStyle:l,ApplyDirectStyling:l,InsertText:l,MoveCursor:l,RemoveCursor:l,RemoveMember:l,RemoveStyle:function(c,a){var d,e=[c],f=[a];c.styleFamily===
+a.styleFamily&&(d=b(c.setProperties,a.styleName),0<d.length&&(d={optype:"UpdateParagraphStyle",memberid:a.memberid,timestamp:a.timestamp,styleName:c.styleName,removedProperties:{attributes:d.join(",")}},f.unshift(d)),p(c.setProperties,a.styleName));return{opSpecsA:e,opSpecsB:f}},RemoveText:l,SetParagraphStyle:l,SplitParagraph:l,UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},ApplyDirectStyling:{ApplyDirectStyling:function(b,a,f){var e,h,k,l,n,p,q,s;l=[b];k=[a];if(!(b.position+b.length<=a.position||
+b.position>=a.position+a.length)){e=f?b:a;h=f?a:b;if(b.position!==a.position||b.length!==a.length)p=d(e),q=d(h);a=r(h.setProperties,null,e.setProperties,null,"style:text-properties");if(a.majorChanged||a.minorChanged)k=[],b=[],l=e.position+e.length,n=h.position+h.length,h.position<e.position?a.minorChanged&&(s=d(q),s.length=e.position-h.position,b.push(s),h.position=e.position,h.length=n-h.position):e.position<h.position&&a.majorChanged&&(s=d(p),s.length=h.position-e.position,k.push(s),e.position=
+h.position,e.length=l-e.position),n>l?a.minorChanged&&(p=q,p.position=l,p.length=n-l,b.push(p),h.length=l-h.position):l>n&&a.majorChanged&&(p.position=n,p.length=l-n,k.push(p),e.length=n-e.position),e.setProperties&&g(e.setProperties)&&k.push(e),h.setProperties&&g(h.setProperties)&&b.push(h),f?(l=k,k=b):l=b}return{opSpecsA:l,opSpecsB:k}},InsertText:function(b,a){a.position<=b.position?b.position+=a.text.length:a.position<=b.position+b.length&&(b.length+=a.text.length);return{opSpecsA:[b],opSpecsB:[a]}},
+MoveCursor:l,RemoveCursor:l,RemoveStyle:l,RemoveText:function(b,a){var d=b.position+b.length,e=a.position+a.length,f=[b],g=[a];e<=b.position?b.position-=a.length:a.position<d&&(b.position<a.position?b.length=e<d?b.length-a.length:a.position-b.position:(b.position=a.position,e<d?b.length=d-e:f=[]));return{opSpecsA:f,opSpecsB:g}},SetParagraphStyle:l,SplitParagraph:function(b,a){a.position<b.position?b.position+=1:a.position<b.position+b.length&&(b.length+=1);return{opSpecsA:[b],opSpecsB:[a]}},UpdateMetadata:l,
+UpdateParagraphStyle:l},InsertText:{InsertText:function(b,a,d){b.position<a.position?a.position+=b.text.length:b.position>a.position?b.position+=a.text.length:d?a.position+=b.text.length:b.position+=a.text.length;return{opSpecsA:[b],opSpecsB:[a]}},MoveCursor:function(b,a){var d=h(a);b.position<a.position?a.position+=b.text.length:b.position<a.position+a.length&&(a.length+=b.text.length);d&&k(a);return{opSpecsA:[b],opSpecsB:[a]}},RemoveCursor:l,RemoveMember:l,RemoveStyle:l,RemoveText:function(b,a){var d;
+d=a.position+a.length;var e=[b],f=[a];d<=b.position?b.position-=a.length:b.position<=a.position?a.position+=b.text.length:(a.length=b.position-a.position,d={optype:"RemoveText",memberid:a.memberid,timestamp:a.timestamp,position:b.position+b.text.length,length:d-b.position},f.unshift(d),b.position=a.position);return{opSpecsA:e,opSpecsB:f}},SplitParagraph:function(b,a,d){if(b.position<a.position)a.position+=b.text.length;else if(b.position>a.position)b.position+=1;else return d?a.position+=b.text.length:
+b.position+=1,null;return{opSpecsA:[b],opSpecsB:[a]}},UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},MoveCursor:{MoveCursor:l,RemoveCursor:function(b,a){return{opSpecsA:b.memberid===a.memberid?[]:[b],opSpecsB:[a]}},RemoveMember:l,RemoveStyle:l,RemoveText:function(b,a){var d=h(b),e=b.position+b.length,f=a.position+a.length;f<=b.position?b.position-=a.length:a.position<e&&(b.position<a.position?b.length=f<e?b.length-a.length:a.position-b.position:(b.position=a.position,b.length=f<e?e-f:0));
+d&&k(b);return{opSpecsA:[b],opSpecsB:[a]}},SetParagraphStyle:l,SplitParagraph:function(b,a){var d=h(b);a.position<b.position?b.position+=1:a.position<b.position+b.length&&(b.length+=1);d&&k(b);return{opSpecsA:[b],opSpecsB:[a]}},UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},RemoveCursor:{RemoveCursor:function(b,a){var d=b.memberid===a.memberid;return{opSpecsA:d?[]:[b],opSpecsB:d?[]:[a]}},RemoveMember:l,RemoveStyle:l,RemoveText:l,SetParagraphStyle:l,SplitParagraph:l,UpdateMember:l,UpdateMetadata:l,
+UpdateParagraphStyle:l},RemoveMember:{RemoveStyle:l,RemoveText:l,SetParagraphStyle:l,SplitParagraph:l,UpdateMetadata:l,UpdateParagraphStyle:l},RemoveStyle:{RemoveStyle:function(b,a){var d=b.styleName===a.styleName&&b.styleFamily===a.styleFamily;return{opSpecsA:d?[]:[b],opSpecsB:d?[]:[a]}},RemoveText:l,SetParagraphStyle:function(b,a){var d,e=[b],f=[a];"paragraph"===b.styleFamily&&b.styleName===a.styleName&&(d={optype:"SetParagraphStyle",memberid:b.memberid,timestamp:b.timestamp,position:a.position,
+styleName:""},e.unshift(d),a.styleName="");return{opSpecsA:e,opSpecsB:f}},SplitParagraph:l,UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:function(c,a){var d,e=[c],f=[a];"paragraph"===c.styleFamily&&(d=b(a.setProperties,c.styleName),0<d.length&&(d={optype:"UpdateParagraphStyle",memberid:c.memberid,timestamp:c.timestamp,styleName:a.styleName,removedProperties:{attributes:d.join(",")}},e.unshift(d)),c.styleName===a.styleName?f=[]:p(a.setProperties,c.styleName));return{opSpecsA:e,opSpecsB:f}}},
+RemoveText:{RemoveText:function(b,a){var d=b.position+b.length,e=a.position+a.length,f=[b],g=[a];e<=b.position?b.position-=a.length:d<=a.position?a.position-=b.length:a.position<d&&(b.position<a.position?(b.length=e<d?b.length-a.length:a.position-b.position,d<e?(a.position=b.position,a.length=e-d):g=[]):(d<e?a.length-=b.length:a.position<b.position?a.length=b.position-a.position:g=[],e<d?(b.position=a.position,b.length=d-e):f=[]));return{opSpecsA:f,opSpecsB:g}},SplitParagraph:function(b,a){var d=
+b.position+b.length,e=[b],f=[a];a.position<=b.position?b.position+=1:a.position<d&&(b.length=a.position-b.position,d={optype:"RemoveText",memberid:b.memberid,timestamp:b.timestamp,position:a.position+1,length:d-a.position},e.unshift(d));b.position+b.length<=a.position?a.position-=b.length:b.position<a.position&&(a.position=b.position);return{opSpecsA:e,opSpecsB:f}},UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},SetParagraphStyle:{UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},SplitParagraph:{SplitParagraph:function(b,
+a,d){b.position<a.position?a.position+=1:b.position>a.position?b.position+=1:b.position===a.position&&(d?a.position+=1:b.position+=1);return{opSpecsA:[b],opSpecsB:[a]}},UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},UpdateMember:{UpdateMetadata:l,UpdateParagraphStyle:l},UpdateMetadata:{UpdateMetadata:function(b,a,d){var e,f=[b],h=[a];e=d?b:a;b=d?a:b;n(b.setProperties||null,b.removedProperties||null,e.setProperties||null,e.removedProperties||null);e.setProperties&&g(e.setProperties)||e.removedProperties&&
+q(e.removedProperties)||(d?f=[]:h=[]);b.setProperties&&g(b.setProperties)||b.removedProperties&&q(b.removedProperties)||(d?h=[]:f=[]);return{opSpecsA:f,opSpecsB:h}},UpdateParagraphStyle:l},UpdateParagraphStyle:{UpdateParagraphStyle:function(b,a,d){var e,f=[b],h=[a];b.styleName===a.styleName&&(e=d?b:a,b=d?a:b,r(b.setProperties,b.removedProperties,e.setProperties,e.removedProperties,"style:paragraph-properties"),r(b.setProperties,b.removedProperties,e.setProperties,e.removedProperties,"style:text-properties"),
+n(b.setProperties||null,b.removedProperties||null,e.setProperties||null,e.removedProperties||null),e.setProperties&&g(e.setProperties)||e.removedProperties&&q(e.removedProperties)||(d?f=[]:h=[]),b.setProperties&&g(b.setProperties)||b.removedProperties&&q(b.removedProperties)||(d?h=[]:f=[]));return{opSpecsA:f,opSpecsB:h}}}};this.passUnchanged=l;this.extendTransformations=function(b){Object.keys(b).forEach(function(a){var d=b[a],e,g=f.hasOwnProperty(a);runtime.log((g?"Extending":"Adding")+" map for optypeA: "+
+a);g||(f[a]={});e=f[a];Object.keys(d).forEach(function(b){var c=e.hasOwnProperty(b);runtime.assert(a<=b,"Wrong order:"+a+", "+b);runtime.log(" "+(c?"Overwriting":"Adding")+" entry for optypeB: "+b);e[b]=d[b]})})};this.transformOpspecVsOpspec=function(b,a){var d=b.optype<=a.optype,e;runtime.log("Crosstransforming:");runtime.log(runtime.toJson(b));runtime.log(runtime.toJson(a));d||(e=b,b=a,a=e);(e=(e=f[b.optype])&&e[a.optype])?(e=e(b,a,!d),d||null===e||(e={opSpecsA:e.opSpecsB,opSpecsB:e.opSpecsA})):
+e=null;runtime.log("result:");e?(runtime.log(runtime.toJson(e.opSpecsA)),runtime.log(runtime.toJson(e.opSpecsB))):runtime.log("null");return e}};
+// Input 108
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
+
+ @licstart
+ This file is part of WebODF.
+
+ WebODF is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License (GNU AGPL)
+ as published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ WebODF is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with WebODF. If not, see <http://www.gnu.org/licenses/>.
+ @licend
+
+ @source: http://www.webodf.org/
+ @source: https://github.com/kogmbh/WebODF/
+*/
+ops.OperationTransformer=function(){function k(d){var h=[];d.forEach(function(d){h.push(b.create(d))});return h}function h(b,k){for(var g,q,r=[],l=[];0<b.length&&k;){g=b.shift();g=p.transformOpspecVsOpspec(g,k);if(!g)return null;r=r.concat(g.opSpecsA);if(0===g.opSpecsB.length){r=r.concat(b);k=null;break}for(;1<g.opSpecsB.length;){q=h(b,g.opSpecsB.shift());if(!q)return null;l=l.concat(q.opSpecsB);b=q.opSpecsA}k=g.opSpecsB.pop()}k&&l.push(k);return{opSpecsA:r,opSpecsB:l}}var b,p=new ops.OperationTransformMatrix;
+this.setOperationFactory=function(d){b=d};this.getOperationTransformMatrix=function(){return p};this.transform=function(b,n){for(var g,p=[];0<n.length;){g=h(b,n.shift());if(!g)return null;b=g.opSpecsA;p=p.concat(g.opSpecsB)}return{opsA:k(b),opsB:k(p)}}};
+// Input 109
+/*
+
+ Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@@ -3064,15 +3367,6 @@ c);q.removeEventListener("focus",e,!1);q.removeEventListener("blur",a,!1);(funct
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
*/
-runtime.loadClass("gui.Caret");runtime.loadClass("ops.EditInfo");runtime.loadClass("gui.EditInfoMarker");gui.SessionViewOptions=function(){this.caretBlinksOnRangeSelect=this.caretAvatarsInitiallyVisible=this.editInfoMarkersInitiallyVisible=!0};
-gui.SessionView=function(){return function(g,l,f,p,r){function n(a,b,c){function d(b,c,e){c=b+'[editinfo|memberid="'+a+'"]'+e+c;a:{var f=t.firstChild;for(b=b+'[editinfo|memberid="'+a+'"]'+e+"{";f;){if(f.nodeType===Node.TEXT_NODE&&0===f.data.indexOf(b)){b=f;break a}f=f.nextSibling}b=null}b?b.data=c:t.appendChild(document.createTextNode(c))}d("div.editInfoMarker","{ background-color: "+c+"; }","");d("span.editInfoColor","{ background-color: "+c+"; }","");d("span.editInfoAuthor",'{ content: "'+b+'"; }',
-":before");d("dc|creator","{ background-color: "+c+"; }","");d("div.selectionOverlay","{ background-color: "+c+";}","")}function h(a){var b,c;for(c in w)w.hasOwnProperty(c)&&(b=w[c],a?b.show():b.hide())}function d(a){p.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function m(a){var b=a.getMemberId();a=a.getProperties();n(b,a.fullName,a.color);l===b&&n("","",a.color)}function c(a){var b=a.getMemberId(),c=f.getOdtDocument().getMember(b).getProperties();p.registerCursor(a,v,u);r.registerCursor(a,
-!0);if(a=p.getCaret(b))a.setAvatarImageUrl(c.imageUrl),a.setColor(c.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+b+"'! +++")}function e(a){a=a.getMemberId();var b=r.getSelectionView(l),c=r.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),d=p.getCaret(l);a===l?(c.hide(),b&&b.show(),d&&d.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(c.show(),b&&b.hide(),d&&d.hide())}function a(a){r.removeSelectionView(a)}function b(a){var b=a.paragraphElement,c=a.memberId;a=a.timeStamp;
-var d,e="",g=b.getElementsByTagNameNS(A,"editinfo")[0];g?(e=g.getAttributeNS(A,"id"),d=w[e]):(e=Math.random().toString(),d=new ops.EditInfo(b,f.getOdtDocument()),d=new gui.EditInfoMarker(d,x),g=b.getElementsByTagNameNS(A,"editinfo")[0],g.setAttributeNS(A,"id",e),w[e]=d);d.addEdit(c,new Date(a))}function q(){H=!0}function k(){s=runtime.getWindow().setInterval(function(){H&&(r.rerenderSelectionViews(),H=!1)},200)}var t,A="urn:webodf:names:editinfo",w={},x=void 0!==g.editInfoMarkersInitiallyVisible?
-Boolean(g.editInfoMarkersInitiallyVisible):!0,v=void 0!==g.caretAvatarsInitiallyVisible?Boolean(g.caretAvatarsInitiallyVisible):!0,u=void 0!==g.caretBlinksOnRangeSelect?Boolean(g.caretBlinksOnRangeSelect):!0,s,H=!1;this.showEditInfoMarkers=function(){x||(x=!0,h(x))};this.hideEditInfoMarkers=function(){x&&(x=!1,h(x))};this.showCaretAvatars=function(){v||(v=!0,d(v))};this.hideCaretAvatars=function(){v&&(v=!1,d(v))};this.getSession=function(){return f};this.getCaret=function(a){return p.getCaret(a)};
-this.destroy=function(d){var g=f.getOdtDocument(),h=Object.keys(w).map(function(a){return w[a]});g.unsubscribe(ops.OdtDocument.signalMemberAdded,m);g.unsubscribe(ops.OdtDocument.signalMemberUpdated,m);g.unsubscribe(ops.OdtDocument.signalCursorAdded,c);g.unsubscribe(ops.OdtDocument.signalCursorRemoved,a);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,b);g.unsubscribe(ops.OdtDocument.signalCursorMoved,e);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,q);g.unsubscribe(ops.OdtDocument.signalTableAdded,
-q);g.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,q);runtime.getWindow().clearInterval(s);t.parentNode.removeChild(t);(function W(a,b){b?d(b):a<h.length?h[a].destroy(function(b){W(a+1,b)}):d()})(0,void 0)};(function(){var d=f.getOdtDocument(),g=document.getElementsByTagName("head")[0];d.subscribe(ops.OdtDocument.signalMemberAdded,m);d.subscribe(ops.OdtDocument.signalMemberUpdated,m);d.subscribe(ops.OdtDocument.signalCursorAdded,c);d.subscribe(ops.OdtDocument.signalCursorRemoved,a);d.subscribe(ops.OdtDocument.signalParagraphChanged,
-b);d.subscribe(ops.OdtDocument.signalCursorMoved,e);k();d.subscribe(ops.OdtDocument.signalParagraphChanged,q);d.subscribe(ops.OdtDocument.signalTableAdded,q);d.subscribe(ops.OdtDocument.signalParagraphStyleModified,q);t=document.createElementNS(g.namespaceURI,"style");t.type="text/css";t.media="screen, print, handheld, projection";t.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);"));t.appendChild(document.createTextNode("@namespace dc url(http://purl.org/dc/elements/1.1/);"));
-g.appendChild(t)})()}}();
-// Input 100
-var webodf_css="@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0);\n@namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0);\n@namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0);\n@namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0);\n@namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0);\n@namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0);\n@namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0);\n@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0);\n@namespace webodfhelper url(urn:webodf:names:helper);\n@namespace cursor url(urn:webodf:names:cursor);\n@namespace editinfo url(urn:webodf:names:editinfo);\n@namespace annotation url(urn:webodf:names:annotation);\n@namespace dc url(http://purl.org/dc/elements/1.1/);\n\noffice|document > *, office|document-content > * {\n display: none;\n}\noffice|body, office|document {\n display: inline-block;\n position: relative;\n}\n\ntext|p, text|h {\n display: block;\n padding: 0;\n margin: 0;\n line-height: normal;\n position: relative;\n min-height: 1.3em; /* prevent empty paragraphs and headings from collapsing if they are empty */\n}\n*[webodfhelper|containsparagraphanchor] {\n position: relative;\n}\ntext|s {\n white-space: pre;\n}\ntext|tab {\n display: inline;\n white-space: pre;\n}\ntext|tracked-changes {\n /*Consumers that do not support change tracking, should ignore changes.*/\n display: none;\n}\noffice|binary-data {\n display: none;\n}\noffice|text {\n display: block;\n text-align: left;\n overflow: visible;\n word-wrap: break-word;\n}\n\noffice|text::selection {\n /** Let's not draw selection highlight that overflows into the office|text\n * node when selecting content across several paragraphs\n */\n background: transparent;\n}\n\n.virtualSelections office|document *::selection {\n background: transparent;\n}\n.virtualSelections office|document *::-moz-selection {\n background: transparent;\n}\n\noffice|text * draw|text-box {\n/** only for text documents */\n display: block;\n border: 1px solid #d3d3d3;\n}\noffice|spreadsheet {\n display: block;\n border-collapse: collapse;\n empty-cells: show;\n font-family: sans-serif;\n font-size: 10pt;\n text-align: left;\n page-break-inside: avoid;\n overflow: hidden;\n}\noffice|presentation {\n display: inline-block;\n text-align: left;\n}\n#shadowContent {\n display: inline-block;\n text-align: left;\n}\ndraw|page {\n display: block;\n position: relative;\n overflow: hidden;\n}\npresentation|notes, presentation|footer-decl, presentation|date-time-decl {\n display: none;\n}\n@media print {\n draw|page {\n border: 1pt solid black;\n page-break-inside: avoid;\n }\n presentation|notes {\n /*TODO*/\n }\n}\noffice|spreadsheet text|p {\n border: 0px;\n padding: 1px;\n margin: 0px;\n}\noffice|spreadsheet table|table {\n margin: 3px;\n}\noffice|spreadsheet table|table:after {\n /* show sheet name the end of the sheet */\n /*content: attr(table|name);*/ /* gives parsing error in opera */\n}\noffice|spreadsheet table|table-row {\n counter-increment: row;\n}\noffice|spreadsheet table|table-row:before {\n width: 3em;\n background: #cccccc;\n border: 1px solid black;\n text-align: center;\n content: counter(row);\n display: table-cell;\n}\noffice|spreadsheet table|table-cell {\n border: 1px solid #cccccc;\n}\ntable|table {\n display: table;\n}\ndraw|frame table|table {\n width: 100%;\n height: 100%;\n background: white;\n}\ntable|table-header-rows {\n display: table-header-group;\n}\ntable|table-row {\n display: table-row;\n}\ntable|table-column {\n display: table-column;\n}\ntable|table-cell {\n width: 0.889in;\n display: table-cell;\n word-break: break-all; /* prevent long words from extending out the table cell */\n}\ndraw|frame {\n display: block;\n}\ndraw|image {\n display: block;\n width: 100%;\n height: 100%;\n top: 0px;\n left: 0px;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n -moz-background-size: 100% 100%;\n}\n/* only show the first image in frame */\ndraw|frame > draw|image:nth-of-type(n+2) {\n display: none;\n}\ntext|list:before {\n display: none;\n content:\"\";\n}\ntext|list {\n counter-reset: list;\n}\ntext|list-item {\n display: block;\n}\ntext|number {\n display:none;\n}\n\ntext|a {\n color: blue;\n text-decoration: underline;\n cursor: pointer;\n}\ntext|note-citation {\n vertical-align: super;\n font-size: smaller;\n}\ntext|note-body {\n display: none;\n}\ntext|note:hover text|note-citation {\n background: #dddddd;\n}\ntext|note:hover text|note-body {\n display: block;\n left:1em;\n max-width: 80%;\n position: absolute;\n background: #ffffaa;\n}\nsvg|title, svg|desc {\n display: none;\n}\nvideo {\n width: 100%;\n height: 100%\n}\n\n/* below set up the cursor */\ncursor|cursor {\n display: inline;\n width: 0px;\n height: 1em;\n /* making the position relative enables the avatar to use\n the cursor as reference for its absolute position */\n position: relative;\n z-index: 1;\n}\ncursor|cursor > span {\n /* IMPORTANT: when changing these values ensure DEFAULT_CARET_TOP and DEFAULT_CARET_HEIGHT\n in Caret.js remain in sync */\n display: inline;\n position: absolute;\n top: 5%; /* push down the caret; 0px can do the job, 5% looks better, 10% is a bit over */\n height: 1em;\n border-left: 2px solid black;\n outline: none;\n}\n\ncursor|cursor > div {\n padding: 3px;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n border: none !important;\n border-radius: 5px;\n opacity: 0.3;\n}\n\ncursor|cursor > div > img {\n border-radius: 5px;\n}\n\ncursor|cursor > div.active {\n opacity: 0.8;\n}\n\ncursor|cursor > div:after {\n content: ' ';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 43%;\n}\n\n\n.editInfoMarker {\n position: absolute;\n width: 10px;\n height: 100%;\n left: -20px;\n opacity: 0.8;\n top: 0;\n border-radius: 5px;\n background-color: transparent;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n}\n.editInfoMarker:hover {\n box-shadow: 0px 0px 8px rgba(0, 0, 0, 1);\n}\n\n.editInfoHandle {\n position: absolute;\n background-color: black;\n padding: 5px;\n border-radius: 5px;\n opacity: 0.8;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n bottom: 100%;\n margin-bottom: 10px;\n z-index: 3;\n left: -25px;\n}\n.editInfoHandle:after {\n content: ' ';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 5px;\n}\n.editInfo {\n font-family: sans-serif;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n color: white;\n width: 100%;\n height: 12pt;\n}\n.editInfoColor {\n float: left;\n width: 10pt;\n height: 10pt;\n border: 1px solid white;\n}\n.editInfoAuthor {\n float: left;\n margin-left: 5pt;\n font-size: 10pt;\n text-align: left;\n height: 12pt;\n line-height: 12pt;\n}\n.editInfoTime {\n float: right;\n margin-left: 30pt;\n font-size: 8pt;\n font-style: italic;\n color: yellow;\n height: 12pt;\n line-height: 12pt;\n}\n\n.annotationWrapper {\n display: inline;\n position: relative;\n}\n\n.annotationRemoveButton:before {\n content: '\u00d7';\n color: white;\n padding: 5px;\n line-height: 1em;\n}\n\n.annotationRemoveButton {\n width: 20px;\n height: 20px;\n border-radius: 10px;\n background-color: black;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n position: absolute;\n top: -10px;\n left: -10px;\n z-index: 3;\n text-align: center;\n font-family: sans-serif;\n font-style: normal;\n font-weight: normal;\n text-decoration: none;\n font-size: 15px;\n}\n.annotationRemoveButton:hover {\n cursor: pointer;\n box-shadow: 0px 0px 5px rgba(0, 0, 0, 1);\n}\n\n.annotationNote {\n width: 4cm;\n position: absolute;\n display: inline;\n z-index: 10;\n}\n.annotationNote > office|annotation {\n display: block;\n text-align: left;\n}\n\n.annotationConnector {\n position: absolute;\n display: inline;\n z-index: 2;\n border-top: 1px dashed brown;\n}\n.annotationConnector.angular {\n -moz-transform-origin: left top;\n -webkit-transform-origin: left top;\n -ms-transform-origin: left top;\n transform-origin: left top;\n}\n.annotationConnector.horizontal {\n left: 0;\n}\n.annotationConnector.horizontal:before {\n content: '';\n display: inline;\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: brown transparent transparent transparent;\n top: -1px;\n left: -5px;\n}\n\noffice|annotation {\n width: 100%;\n height: 100%;\n display: none;\n background: rgb(198, 238, 184);\n background: -moz-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -webkit-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -o-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -ms-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: linear-gradient(180deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n box-shadow: 0 3px 4px -3px #ccc;\n}\n\noffice|annotation > dc|creator {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n color: white;\n background-color: brown;\n padding: 4px;\n}\noffice|annotation > dc|date {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n border: 4px solid transparent;\n}\noffice|annotation > text|list {\n display: block;\n padding: 5px;\n}\n\n/* This is very temporary CSS. This must go once\n * we start bundling webodf-default ODF styles for annotations.\n */\noffice|annotation text|p {\n font-size: 10pt;\n color: black;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n font-family: sans-serif;\n}\n\ndc|*::selection {\n background: transparent;\n}\ndc|*::-moz-selection {\n background: transparent;\n}\n\n#annotationsPane {\n background-color: #EAEAEA;\n width: 4cm;\n height: 100%;\n display: none;\n position: absolute;\n outline: 1px solid #ccc;\n}\n\n.annotationHighlight {\n background-color: yellow;\n position: relative;\n}\n\n.selectionOverlay {\n position: absolute;\n z-index: 15;\n opacity: 0.2;\n pointer-events: none;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n}\n\n#imageSelector {\n display: none;\n position: absolute;\n border-style: solid;\n border-color: black;\n}\n\n#imageSelector > div {\n width: 5px;\n height: 5px;\n display: block;\n position: absolute;\n border: 1px solid black;\n background-color: #ffffff;\n}\n\n#imageSelector > .topLeft {\n top: -4px;\n left: -4px;\n}\n\n#imageSelector > .topRight {\n top: -4px;\n right: -4px;\n}\n\n#imageSelector > .bottomRight {\n right: -4px;\n bottom: -4px;\n}\n\n#imageSelector > .bottomLeft {\n bottom: -4px;\n left: -4px;\n}\n\n#imageSelector > .topMiddle {\n top: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .rightMiddle {\n top: 50%;\n right: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n\n#imageSelector > .bottomMiddle {\n bottom: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .leftMiddle {\n top: 50%;\n left: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n";
+ops.Server=function(){};ops.Server.prototype.connect=function(k,h){};ops.Server.prototype.networkStatus=function(){};ops.Server.prototype.login=function(k,h,b,p){};ops.Server.prototype.joinSession=function(k,h,b,p){};ops.Server.prototype.leaveSession=function(k,h,b,p){};ops.Server.prototype.getGenesisUrl=function(k){};
+// Input 110
+var webodf_css='@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0);\n@namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0);\n@namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0);\n@namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0);\n@namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0);\n@namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0);\n@namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0);\n@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0);\n@namespace webodfhelper url(urn:webodf:names:helper);\n@namespace cursor url(urn:webodf:names:cursor);\n@namespace editinfo url(urn:webodf:names:editinfo);\n@namespace annotation url(urn:webodf:names:annotation);\n@namespace dc url(http://purl.org/dc/elements/1.1/);\n@namespace svgns url(http://www.w3.org/2000/svg);\n\noffice|document > *, office|document-content > * {\n display: none;\n}\noffice|body, office|document {\n display: inline-block;\n position: relative;\n}\n\ntext|p, text|h {\n display: block;\n padding: 0;\n margin: 0;\n line-height: normal;\n position: relative;\n min-height: 1.3em; /* prevent empty paragraphs and headings from collapsing if they are empty */\n}\n*[webodfhelper|containsparagraphanchor] {\n position: relative;\n}\ntext|s {\n white-space: pre;\n}\ntext|tab {\n display: inline;\n white-space: pre;\n}\ntext|tracked-changes {\n /*Consumers that do not support change tracking, should ignore changes.*/\n display: none;\n}\noffice|binary-data {\n display: none;\n}\noffice|text {\n display: block;\n text-align: left;\n overflow: visible;\n word-wrap: break-word;\n}\n\noffice|text::selection {\n /** Let\'s not draw selection highlight that overflows into the office|text\n * node when selecting content across several paragraphs\n */\n background: transparent;\n}\n\noffice|document *::selection {\n background: transparent;\n}\noffice|document *::-moz-selection {\n background: transparent;\n}\n\noffice|text * draw|text-box {\n/** only for text documents */\n display: block;\n border: 1px solid #d3d3d3;\n}\ndraw|frame {\n /** make sure frames are above the main body. */\n z-index: 1;\n}\noffice|spreadsheet {\n display: block;\n border-collapse: collapse;\n empty-cells: show;\n font-family: sans-serif;\n font-size: 10pt;\n text-align: left;\n page-break-inside: avoid;\n overflow: hidden;\n}\noffice|presentation {\n display: inline-block;\n text-align: left;\n}\n#shadowContent {\n display: inline-block;\n text-align: left;\n}\ndraw|page {\n display: block;\n position: relative;\n overflow: hidden;\n}\npresentation|notes, presentation|footer-decl, presentation|date-time-decl {\n display: none;\n}\n@media print {\n draw|page {\n border: 1pt solid black;\n page-break-inside: avoid;\n }\n presentation|notes {\n /*TODO*/\n }\n}\noffice|spreadsheet text|p {\n border: 0px;\n padding: 1px;\n margin: 0px;\n}\noffice|spreadsheet table|table {\n margin: 3px;\n}\noffice|spreadsheet table|table:after {\n /* show sheet name the end of the sheet */\n /*content: attr(table|name);*/ /* gives parsing error in opera */\n}\noffice|spreadsheet table|table-row {\n counter-increment: row;\n}\noffice|spreadsheet table|table-row:before {\n width: 3em;\n background: #cccccc;\n border: 1px solid black;\n text-align: center;\n content: counter(row);\n display: table-cell;\n}\noffice|spreadsheet table|table-cell {\n border: 1px solid #cccccc;\n}\ntable|table {\n display: table;\n}\ndraw|frame table|table {\n width: 100%;\n height: 100%;\n background: white;\n}\ntable|table-header-rows {\n display: table-header-group;\n}\ntable|table-row {\n display: table-row;\n}\ntable|table-column {\n display: table-column;\n}\ntable|table-cell {\n width: 0.889in;\n display: table-cell;\n word-break: break-all; /* prevent long words from extending out the table cell */\n}\ndraw|frame {\n display: block;\n}\ndraw|image {\n display: block;\n width: 100%;\n height: 100%;\n top: 0px;\n left: 0px;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n -moz-background-size: 100% 100%;\n}\n/* only show the first image in frame */\ndraw|frame > draw|image:nth-of-type(n+2) {\n display: none;\n}\ntext|list:before {\n display: none;\n content:"";\n}\ntext|list {\n counter-reset: list;\n}\ntext|list-item {\n display: block;\n}\ntext|number {\n display:none;\n}\n\ntext|a {\n color: blue;\n text-decoration: underline;\n cursor: pointer;\n}\noffice|text[webodfhelper|links="inactive"] text|a {\n cursor: text;\n}\ntext|note-citation {\n vertical-align: super;\n font-size: smaller;\n}\ntext|note-body {\n display: none;\n}\ntext|note:hover text|note-citation {\n background: #dddddd;\n}\ntext|note:hover text|note-body {\n display: block;\n left:1em;\n max-width: 80%;\n position: absolute;\n background: #ffffaa;\n}\nsvg|title, svg|desc {\n display: none;\n}\nvideo {\n width: 100%;\n height: 100%\n}\n\n/* below set up the cursor */\ncursor|cursor {\n display: inline;\n width: 0;\n height: 1em;\n /* making the position relative enables the avatar to use\n the cursor as reference for its absolute position */\n position: relative;\n z-index: 1;\n pointer-events: none;\n}\n\ncursor|cursor > .caret {\n /* IMPORTANT: when changing these values ensure DEFAULT_CARET_TOP and DEFAULT_CARET_HEIGHT\n in Caret.js remain in sync */\n display: inline;\n position: absolute;\n top: 5%; /* push down the caret; 0px can do the job, 5% looks better, 10% is a bit over */\n height: 1em;\n border-left: 2px solid black;\n outline: none;\n}\n\ncursor|cursor > .handle {\n padding: 3px;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n border: none !important;\n border-radius: 5px;\n opacity: 0.3;\n}\n\ncursor|cursor > .handle > img {\n border-radius: 5px;\n}\n\ncursor|cursor > .handle.active {\n opacity: 0.8;\n}\n\ncursor|cursor > .handle:after {\n content: \' \';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 43%;\n}\n\n/** Input Method Editor input pane & behaviours */\n/* not within a cursor */\n#eventTrap {\n height: auto;\n display: block;\n position: absolute;\n width: 1px;\n outline: none;\n opacity: 0;\n color: rgba(255, 255, 255, 0); /* hide the blinking caret by setting the colour to fully transparent */\n overflow: hidden; /* The overflow visibility is used to hide and show characters being entered */\n pointer-events: none;\n}\n\n/* within a cursor */\ncursor|cursor > #composer {\n text-decoration: underline;\n}\n\ncursor|cursor[cursor|composing="true"] > #composer {\n display: inline-block;\n height: auto;\n width: auto;\n}\n\ncursor|cursor[cursor|composing="true"] {\n display: inline-block;\n width: auto;\n height: inherit;\n}\n\ncursor|cursor[cursor|composing="true"] > .caret {\n /* during composition, the caret should be pushed along by the composition text, inline with the text */\n position: static;\n /* as it is now part of an inline-block, it will no longer need correct to top or height values to align properly */\n height: auto !important;\n top: auto !important;\n}\n\neditinfo|editinfo {\n /* Empty or invisible display:inline elements respond very badly to mouse selection.\n Inline blocks are much more reliably selectable in Chrome & friends */\n display: inline-block;\n}\n\n.editInfoMarker {\n position: absolute;\n width: 10px;\n height: 100%;\n left: -20px;\n opacity: 0.8;\n top: 0;\n border-radius: 5px;\n background-color: transparent;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n}\n.editInfoMarker:hover {\n box-shadow: 0px 0px 8px rgba(0, 0, 0, 1);\n}\n\n.editInfoHandle {\n position: absolute;\n background-color: black;\n padding: 5px;\n border-radius: 5px;\n opacity: 0.8;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n bottom: 100%;\n margin-bottom: 10px;\n z-index: 3;\n left: -25px;\n}\n.editInfoHandle:after {\n content: \' \';\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: black transparent transparent transparent;\n\n top: 100%;\n left: 5px;\n}\n.editInfo {\n font-family: sans-serif;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n color: white;\n width: 100%;\n height: 12pt;\n}\n.editInfoColor {\n float: left;\n width: 10pt;\n height: 10pt;\n border: 1px solid white;\n}\n.editInfoAuthor {\n float: left;\n margin-left: 5pt;\n font-size: 10pt;\n text-align: left;\n height: 12pt;\n line-height: 12pt;\n}\n.editInfoTime {\n float: right;\n margin-left: 30pt;\n font-size: 8pt;\n font-style: italic;\n color: yellow;\n height: 12pt;\n line-height: 12pt;\n}\n\n.annotationWrapper {\n display: inline;\n position: relative;\n}\n\n.annotationRemoveButton:before {\n content: \'\u00d7\';\n color: white;\n padding: 5px;\n line-height: 1em;\n}\n\n.annotationRemoveButton {\n width: 20px;\n height: 20px;\n border-radius: 10px;\n background-color: black;\n box-shadow: 0px 0px 5px rgba(50, 50, 50, 0.75);\n position: absolute;\n top: -10px;\n left: -10px;\n z-index: 3;\n text-align: center;\n font-family: sans-serif;\n font-style: normal;\n font-weight: normal;\n text-decoration: none;\n font-size: 15px;\n}\n.annotationRemoveButton:hover {\n cursor: pointer;\n box-shadow: 0px 0px 5px rgba(0, 0, 0, 1);\n}\n\n.annotationNote {\n width: 4cm;\n position: absolute;\n display: inline;\n z-index: 10;\n}\n.annotationNote > office|annotation {\n display: block;\n text-align: left;\n}\n\n.annotationConnector {\n position: absolute;\n display: inline;\n z-index: 2;\n border-top: 1px dashed brown;\n}\n.annotationConnector.angular {\n -moz-transform-origin: left top;\n -webkit-transform-origin: left top;\n -ms-transform-origin: left top;\n transform-origin: left top;\n}\n.annotationConnector.horizontal {\n left: 0;\n}\n.annotationConnector.horizontal:before {\n content: \'\';\n display: inline;\n position: absolute;\n width: 0px;\n height: 0px;\n border-style: solid;\n border-width: 8.7px 5px 0 5px;\n border-color: brown transparent transparent transparent;\n top: -1px;\n left: -5px;\n}\n\noffice|annotation {\n width: 100%;\n height: 100%;\n display: none;\n background: rgb(198, 238, 184);\n background: -moz-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -webkit-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -o-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: -ms-linear-gradient(90deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n background: linear-gradient(180deg, rgb(198, 238, 184) 30%, rgb(180, 196, 159) 100%);\n box-shadow: 0 3px 4px -3px #ccc;\n}\n\noffice|annotation > dc|creator {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n color: white;\n background-color: brown;\n padding: 4px;\n}\noffice|annotation > dc|date {\n display: block;\n font-size: 10pt;\n font-weight: normal;\n font-style: normal;\n font-family: sans-serif;\n border: 4px solid transparent;\n color: black;\n}\noffice|annotation > text|list {\n display: block;\n padding: 5px;\n}\n\n/* This is very temporary CSS. This must go once\n * we start bundling webodf-default ODF styles for annotations.\n */\noffice|annotation text|p {\n font-size: 10pt;\n color: black;\n font-weight: normal;\n font-style: normal;\n text-decoration: none;\n font-family: sans-serif;\n}\n\ndc|*::selection {\n background: transparent;\n}\ndc|*::-moz-selection {\n background: transparent;\n}\n\n#annotationsPane {\n background-color: #EAEAEA;\n width: 4cm;\n height: 100%;\n display: none;\n position: absolute;\n outline: 1px solid #ccc;\n}\n\n.annotationHighlight {\n background-color: yellow;\n position: relative;\n}\n\n.selectionOverlay {\n position: absolute;\n pointer-events: none;\n top: 0;\n left: 0;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 15;\n}\n.selectionOverlay > polygon {\n fill-opacity: 0.3;\n stroke-opacity: 0.8;\n stroke-width: 1;\n fill-rule: evenodd;\n}\n\n#imageSelector {\n display: none;\n position: absolute;\n border-style: solid;\n border-color: black;\n}\n\n#imageSelector > div {\n width: 5px;\n height: 5px;\n display: block;\n position: absolute;\n border: 1px solid black;\n background-color: #ffffff;\n}\n\n#imageSelector > .topLeft {\n top: -4px;\n left: -4px;\n}\n\n#imageSelector > .topRight {\n top: -4px;\n right: -4px;\n}\n\n#imageSelector > .bottomRight {\n right: -4px;\n bottom: -4px;\n}\n\n#imageSelector > .bottomLeft {\n bottom: -4px;\n left: -4px;\n}\n\n#imageSelector > .topMiddle {\n top: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .rightMiddle {\n top: 50%;\n right: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n\n#imageSelector > .bottomMiddle {\n bottom: -4px;\n left: 50%;\n margin-left: -2.5px; /* half of the width defined in #imageSelector > div */\n}\n\n#imageSelector > .leftMiddle {\n top: 50%;\n left: -4px;\n margin-top: -2.5px; /* half of the height defined in #imageSelector > div */\n}\n\ndiv.customScrollbars::-webkit-scrollbar\n{\n width: 8px;\n height: 8px;\n background-color: transparent;\n}\n\ndiv.customScrollbars::-webkit-scrollbar-track\n{\n background-color: transparent;\n}\n\ndiv.customScrollbars::-webkit-scrollbar-thumb\n{\n background-color: #444;\n border-radius: 4px;\n}\n';