From e3adf6bd19355f30b1c876a41c101e551bac2a9a Mon Sep 17 00:00:00 2001 From: "Friedrich W. H. Kossebau" Date: Tue, 3 Dec 2013 20:34:48 +0100 Subject: [PATCH] Sync with webodf 82510ae020f8ee8a1f7b65a27b6af107b6023e90 * exposes some state-change/error events in the Editor API * catches more possible errors and handles them (e.g. staying cool on temporary disconnection to server, but warning about it) * improves selection by mouse * fixes selected paragraph style not being set to all selected paragraphs * fixes leaking of some helper attributes into saved ODT files --- js/3rdparty/webodf/editor/Editor.js | 90 +- js/3rdparty/webodf/editor/EditorSession.js | 52 +- .../webodf/editor/server/ServerFactory.js | 3 +- .../editor/server/owncloud/ServerFactory.js | 4 +- .../editor/server/pullbox/OperationRouter.js | 188 +- .../webodf/editor/server/pullbox/Server.js | 43 +- .../editor/server/pullbox/ServerFactory.js | 4 +- .../editor/server/pullbox/SessionList.js | 2 + .../webodf/editor/widgets/paragraphStyles.js | 2 +- js/3rdparty/webodf/webodf-debug.js | 24333 ++++++++-------- js/3rdparty/webodf/webodf.js | 4013 ++- 11 files changed, 14564 insertions(+), 14170 deletions(-) diff --git a/js/3rdparty/webodf/editor/Editor.js b/js/3rdparty/webodf/editor/Editor.js index e05638b6..86840e2f 100644 --- a/js/3rdparty/webodf/editor/Editor.js +++ b/js/3rdparty/webodf/editor/Editor.js @@ -76,9 +76,25 @@ define("webodf/editor/Editor", [ saveOdtFile = args.saveCallback, close = args.closeCallback, odfCanvas, + eventNotifier = new core.EventNotifier([ + Editor.EVENT_ERROR, + Editor.EVENT_BEFORESAVETOFILE, + Editor.EVENT_SAVEDTOFILE, + Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, + Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED + ]), pendingMemberId, pendingEditorReadyCallback; + /** + * @param {!string} eventid + * @param {*} args + * @return {undefined} + */ + function fireEvent(eventid, args) { + eventNotifier.emit(eventid, args); + } + function getFileBlob(cbSuccess, cbError) { var odfContainer = odfCanvas.odfContainer(); @@ -196,14 +212,27 @@ define("webodf/editor/Editor", [ } blob = new Blob([data.buffer], {type: mimetype}); saveAs(blob, filename); + //TODO: add callback as event handler to saveAs + fireEvent(Editor.EVENT_SAVEDTOFILE, null); } function onerror(error) { + // TODO: use callback for that alert(error); } + fireEvent(Editor.EVENT_BEFORESAVETOFILE, null); getFileBlob(onsuccess, onerror); }; + /** + * @param {!Object} error + * @return {undefined} + */ + function handleOperationRouterErrors(error) { + // TODO: translate error into Editor ids or at least document the possible values + fireEvent(Editor.EVENT_ERROR, error); + } + /** * open the initial document of an editing-session, * request a replay of previous operations, call @@ -219,9 +248,24 @@ define("webodf/editor/Editor", [ // overwrite router // TODO: serverFactory should be a backendFactory, // and there should be a backendFactory for local editing - var opRouter = serverFactory.createOperationRouter(sessionId, memberId, server, odfCanvas.odfContainer()); + var opRouter = serverFactory.createOperationRouter(sessionId, memberId, server, odfCanvas.odfContainer(), handleOperationRouterErrors); session.setOperationRouter(opRouter); + // forward events + // TODO: relying here on that opRouter uses the same id strings ATM, those should be defined at OperationRouter interface + opRouter.subscribe(Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, function (hasUnsyncedOps) { + fireEvent(Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, hasUnsyncedOps); + }); + opRouter.subscribe(Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED, function (hasSessionHostConnection) { + fireEvent(Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED, hasSessionHostConnection); + }); + opRouter.subscribe(Editor.EVENT_BEFORESAVETOFILE, function () { + fireEvent(Editor.EVENT_BEFORESAVETOFILE, null); + }); + opRouter.subscribe(Editor.EVENT_SAVEDTOFILE, function () { + fireEvent(Editor.EVENT_SAVEDTOFILE, null); + }); + // now get existing ops and after that let the user edit opRouter.requestReplay(function done() { editorReadyCallback(); }); @@ -288,6 +332,38 @@ define("webodf/editor/Editor", [ editorSession.sessionController.endEditing(); }; + /** + * Allows to register listeners for certain events. Currently + * available events are, with the type of the argument passed to the callback: + * Editor.EVENT_BEFORESAVETOFILE - no argument + * Editor.EVENT_SAVEDTOFILE - no argument + * Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED - boolean, reflecting new hasLocalUnsyncedOperations state + * Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED - boolean, reflecting new hasSessionhostConnection state + * Editor.EVENT_ERROR - string, one of these errorcodes: + * "notMemberOfSession" + * "opExecutionFailure" + * "sessionDoesNotExist" + * "unknownOpReceived" + * "unknownServerReply" + * "unresolvableConflictingOps" + * + * @param {!string} eventid + * @param {!Function} listener + * @return {undefined} + */ + this.addEventListener = function (eventid, listener) { + eventNotifier.subscribe(eventid, listener); + }; + + /** + * @param {!string} eventid + * @param {!Function} listener + * @return {undefined} + */ + this.removeEventListener = function (eventid, listener) { + eventNotifier.unsubscribe(eventid, listener); + }; + /** * @param {!function(!Object=)} callback, passing an error object in case of error * @return {undefined} @@ -440,6 +516,18 @@ define("webodf/editor/Editor", [ init(); } + + /**@const @type {!string}*/ + Editor.EVENT_ERROR = "error"; + /**@const @type {!string}*/ + Editor.EVENT_BEFORESAVETOFILE = "beforeSaveToFile"; + /**@const @type {!string}*/ + Editor.EVENT_SAVEDTOFILE = "savedToFile"; + /**@const @type {!string}*/ + Editor.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED = "hasLocalUnsyncedOperationsChanged"; + /**@const @type {!string}*/ + Editor.EVENT_HASSESSIONHOSTCONNECTIONCHANGED = "hasSessionHostConnectionChanged"; + return Editor; }); diff --git a/js/3rdparty/webodf/editor/EditorSession.js b/js/3rdparty/webodf/editor/EditorSession.js index b96f4a7e..91d28b43 100644 --- a/js/3rdparty/webodf/editor/EditorSession.js +++ b/js/3rdparty/webodf/editor/EditorSession.js @@ -48,7 +48,9 @@ define("webodf/editor/EditorSession", [ }; runtime.loadClass("core.DomUtils"); + runtime.loadClass("odf.OdfUtils"); runtime.loadClass("ops.OdtDocument"); + runtime.loadClass("ops.StepsTranslator"); runtime.loadClass("ops.Session"); runtime.loadClass("odf.Namespaces"); runtime.loadClass("odf.OdfCanvas"); @@ -80,6 +82,7 @@ define("webodf/editor/EditorSession", [ fontStyles = document.createElement('style'), formatting = odtDocument.getFormatting(), domUtils = new core.DomUtils(), + odfUtils = new odf.OdfUtils(), eventNotifier = new core.EventNotifier([ EditorSession.signalMemberAdded, EditorSession.signalMemberUpdated, @@ -306,16 +309,45 @@ define("webodf/editor/EditorSession", [ return currentCommonStyleName; }; - this.setCurrentParagraphStyle = function (value) { - var op; - if (currentCommonStyleName !== value) { - op = new ops.OpSetParagraphStyle(); - op.init({ - memberid: localMemberId, - position: self.getCursorPosition(), - styleName: value - }); - session.enqueue([op]); + /** + * Round the step up to the next step + * @param {!number} step + * @returns {!boolean} + */ + function roundUp(step) { + return step === ops.StepsTranslator.NEXT_STEP; + } + + /** + * Applies the paragraph style with the given + * style name to all the paragraphs within + * the cursor selection. + * @param {!string} styleName + * @return {undefined} + */ + this.setCurrentParagraphStyle = function (styleName) { + var range = odtDocument.getCursor(localMemberId).getSelectedRange(), + paragraphs = odfUtils.getParagraphElements(range), + opQueue = []; + + paragraphs.forEach(function (paragraph) { + var paragraphStartPoint = odtDocument.convertDomPointToCursorStep(paragraph, 0, roundUp), + paragraphStyleName = paragraph.getAttributeNS(odf.Namespaces.textns, "style-name"), + opSetParagraphStyle; + + if (paragraphStyleName !== styleName) { + opSetParagraphStyle = new ops.OpSetParagraphStyle(); + opSetParagraphStyle.init({ + memberid: localMemberId, + styleName: styleName, + position: paragraphStartPoint + }); + opQueue.push(opSetParagraphStyle); + } + }); + + if (opQueue.length > 0) { + session.enqueue(opQueue); } }; diff --git a/js/3rdparty/webodf/editor/server/ServerFactory.js b/js/3rdparty/webodf/editor/server/ServerFactory.js index c028c426..23680445 100644 --- a/js/3rdparty/webodf/editor/server/ServerFactory.js +++ b/js/3rdparty/webodf/editor/server/ServerFactory.js @@ -53,9 +53,10 @@ ServerFactory.prototype.createServer = function () {"use strict"; }; * @param {!string} memberId * @param {!ops.Server} server * @param {!odf.OdfContainer} odfContainer TODO: needed for pullbox writing to server at end, find better solution + * @param {!function(!Object)} errorCallback * @return {!ops.OperationRouter} */ -ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server, odfContainer) {"use strict"; }; +ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server, odfContainer, errorCallback) {"use strict"; }; /** * @param {!ops.Server} server diff --git a/js/3rdparty/webodf/editor/server/owncloud/ServerFactory.js b/js/3rdparty/webodf/editor/server/owncloud/ServerFactory.js index 7c4e1067..0d6b2b43 100644 --- a/js/3rdparty/webodf/editor/server/owncloud/ServerFactory.js +++ b/js/3rdparty/webodf/editor/server/owncloud/ServerFactory.js @@ -50,8 +50,8 @@ define("webodf/editor/server/owncloud/ServerFactory", [ }; return server; }; - this.createOperationRouter = function (sid, mid, server, odfContainer) { - return new PullBoxOperationRouter(sid, mid, server, odfContainer); + this.createOperationRouter = function (sid, mid, server, odfContainer, errorCallback) { + return new PullBoxOperationRouter(sid, mid, server, odfContainer, errorCallback); }; this.createSessionList = function (server) { return new PullBoxSessionList(server); diff --git a/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js b/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js index a24744a5..a6cf8d61 100644 --- a/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js +++ b/js/3rdparty/webodf/editor/server/pullbox/OperationRouter.js @@ -28,7 +28,18 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { "use strict"; + // TODO: these eventid strings should be defined at OperationRouter interface + var /**@const @type {!string}*/ + EVENT_BEFORESAVETOFILE = "beforeSaveToFile", + /**@const @type {!string}*/ + EVENT_SAVEDTOFILE = "savedToFile", + /**@const @type {!string}*/ + EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED = "hasLocalUnsyncedOperationsChanged", + /**@const @type {!string}*/ + EVENT_HASSESSIONHOSTCONNECTIONCHANGED = "hasSessionHostConnectionChanged"; + runtime.loadClass("ops.OperationTransformer"); + runtime.loadClass("core.EventNotifier"); /** * route operations in a networked collaborative manner. @@ -43,11 +54,11 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { * @constructor * @implements ops.OperationRouter */ - return function PullBoxOperationRouter(sessionId, memberId, server, odfContainer) { + return function PullBoxOperationRouter(sessionId, memberId, server, odfContainer, errorCallback) { "use strict"; var operationFactory, - /**@type{function(!ops.Operation)}*/ + /**@type{function(!ops.Operation):boolean}*/ playbackFunction, idleTimeout = null, syncOpsTimeout = null, @@ -58,7 +69,7 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { /**@type{!boolean}*/ isSyncCallRunning = false, /**@type{!boolean}*/ - hasUnresolvableConflict = false, + hasError = false, /**@type{!boolean}*/ syncingBlocked = false, /** @type {!string} id of latest op stack state known on the server */ @@ -71,8 +82,20 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { unplayedServerOpspecQueue = [], /** @type {!Array.} sync request callbacks which should be called after the received ops have been applied server */ uncalledSyncRequestCallbacksQueue = [], + /** @type {!Array.} ops created since the last sync call to the server */ + hasLocalUnsyncedOpsStateSubscribers = [], /**@type{!boolean}*/ hasLocalUnsyncedOps = false, + /** @type {!Array.} */ + hasSessionHostConnectionStateSubscribers = [], + /**@type{!boolean}*/ + hasSessionHostConnection = true, + eventNotifier = new core.EventNotifier([ + EVENT_BEFORESAVETOFILE, + EVENT_SAVEDTOFILE, + EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, + EVENT_HASSESSIONHOSTCONNECTIONCHANGED + ]), /**@type{!boolean} tells if any local ops have been modifying ops */ hasPushedModificationOps = false, operationTransformer = new ops.OperationTransformer(), @@ -84,7 +107,8 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { * @return {undefined} */ function updateHasLocalUnsyncedOpsState() { - var hasLocalUnsyncedOpsNow = (unsyncedClientOpspecQueue.length > 0); + var i, + hasLocalUnsyncedOpsNow = (unsyncedClientOpspecQueue.length > 0); // no change? if (hasLocalUnsyncedOps === hasLocalUnsyncedOpsNow) { @@ -92,6 +116,23 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { } hasLocalUnsyncedOps = hasLocalUnsyncedOpsNow; + eventNotifier.emit(EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, hasLocalUnsyncedOps); + } + + /** + * @param {!boolean} hasConnection + * @return {undefined} + */ + function updateHasSessionHostConnectionState(hasConnection) { + var i; + + // no change? + if (hasSessionHostConnection === hasConnection) { + return; + } + + hasSessionHostConnection = hasConnection; + eventNotifier.emit(EVENT_HASSESSIONHOSTCONNECTIONCHANGED, hasSessionHostConnection); } /** @@ -122,9 +163,16 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { op = operationFactory.create(opspec); runtime.log(" op in: "+runtime.toJson(opspec)); if (op !== null) { - playbackFunction(op); + if (!playbackFunction(op)) { + hasError = true; + errorCallback("opExecutionFailure"); + return; + } } else { + hasError = true; runtime.log("ignoring invalid incoming opspec: " + opspec); + errorCallback("unknownOpReceived"); + return; } } @@ -214,7 +262,7 @@ define("webodf/editor/server/pullbox/OperationRouter", [], function () { }, syncOpsDelay); } - if (isSyncCallRunning || hasUnresolvableConflict) { + if (isSyncCallRunning || hasError) { return; } // TODO: hack, remove @@ -243,13 +291,25 @@ runtime.log("OperationRouter: sending sync_ops call"); client_ops: syncedClientOpspecs } }, function(responseData) { - var response = /** @type{{result:string, head_seq:string, ops:Array.}} */(runtime.fromJson(responseData)); + var response, + /**@type{!boolean}*/ + hasUnresolvableConflict = false; + + updateHasSessionHostConnectionState(true); - // TODO: hack, remove if (syncingBlocked) { return; } + try { + response = /** @type{{result:string, head_seq:string, ops:Array.}} */(runtime.fromJson(responseData)); + } catch (e) { + hasError = true; + runtime.log("Could not parse reply: "+responseData); + errorCallback("unknownServerReply"); + return; + } + // TODO: hack, remove runtime.log("sync_ops reply: " + responseData); // just new ops? @@ -290,20 +350,28 @@ runtime.log("OperationRouter: sending sync_ops call"); if (!hasUnresolvableConflict) { isInstantSyncRequested = true; } + } else if (response.result === "error") { + runtime.log("server reports an error: "+response.error); + hasError = true; + errorCallback( + response.error === "ENOSESSION" ? "sessionDoesNotExist": + response.error === "ENOMEMBER" ? "notMemberOfSession": + "unknownServerReply" + ); + return; } else { - runtime.assert(false, "Unexpected result on sync-ops call: "+response.result); + hasError = true; + runtime.log("Unexpected result on sync-ops call: "+response.result); + errorCallback("unknownServerReply"); + return; } // unlock isSyncCallRunning = false; if (hasUnresolvableConflict) { - // TODO: offer option to reload session automatically? - runtime.assert(false, - "Sorry to tell:\n" + - "we hit a pair of operations in a state which yet need to be supported for transformation against each other.\n" + - "Client disconnected from session, no further editing accepted.\n\n" + - "Please reconnect manually for now."); + hasError = true; + errorCallback("unresolvableConflictingOps"); } else { // prepare next sync if (isInstantSyncRequested) { @@ -318,6 +386,22 @@ runtime.log("OperationRouter: sending sync_ops call"); } playUnplayedServerOpSpecs(); } + }, function() { + runtime.log("meh, server cannot be reached ATM."); + // signal connection problem, but do not give up for now + updateHasSessionHostConnectionState(false); + // put the (not) send ops back into the outgoing queue + unsyncedClientOpspecQueue = syncedClientOpspecs.concat(unsyncedClientOpspecQueue); + syncRequestCallbacksQueue = syncRequestCallbacksArray.concat(syncRequestCallbacksQueue); + // unlock + isSyncCallRunning = false; + // nothing on client to sync? + if (unsyncedClientOpspecQueue.length === 0) { + idleTimeout = runtime.getWindow().setTimeout(startSyncOpsTimeout, idleDelay); + } else { + startSyncOpsTimeout(); + } + playUnplayedServerOpSpecs(); }); } @@ -381,7 +465,7 @@ runtime.log("OperationRouter: instant opsSync requested"); /** * Sets the method which should be called to apply operations. * - * @param {!function(!ops.Operation)} playback_func + * @param {!function(!ops.Operation):boolean} playback_func * @return {undefined} */ this.setPlaybackFunction = function (playback_func) { @@ -395,7 +479,10 @@ runtime.log("OperationRouter: instant opsSync requested"); * @return {undefined} */ this.push = function (operations) { - if (hasUnresolvableConflict) { + var i, op, opspec, + timestamp = (new Date()).getTime(); + + if (hasError) { return; } // TODO: should be an assert in the future @@ -406,22 +493,27 @@ runtime.log("OperationRouter: instant opsSync requested"); return; } - operations.forEach(function(op) { - var timedOp, - opspec = op.spec(); + for (i = 0; i < operations.length; i += 1) { + op = operations[i]; + opspec = op.spec(); // note if any local ops modified hasPushedModificationOps = hasPushedModificationOps || op.isEdit; - // apply locally - opspec.timestamp = (new Date()).getTime(); - timedOp = operationFactory.create(opspec); + // add timestamp TODO: improve the useless recreation of the op + opspec.timestamp = timestamp; + op = operationFactory.create(opspec); - playbackFunction(timedOp); + // apply locally + if (!playbackFunction(op)) { + hasError = true; + errorCallback("opExecutionFailure"); + return; + } // send to server unsyncedClientOpspecQueue.push(opspec); - }); + } triggerPushingOps(); @@ -434,25 +526,65 @@ runtime.log("OperationRouter: instant opsSync requested"); * A callback is called on success. */ this.close = function (cb) { + function cbDoneSaving(err) { + eventNotifier.emit(EVENT_SAVEDTOFILE, null); + cb(err); + } + function cbSuccess(fileData) { - server.writeSessionStateToFile(sessionId, memberId, lastServerSeq, fileData, cb); + server.writeSessionStateToFile(sessionId, memberId, lastServerSeq, fileData, cbDoneSaving); } function doClose() { syncingBlocked = true; if (hasPushedModificationOps) { - odfContainer.createByteArray(cbSuccess, cb); + eventNotifier.emit(EVENT_BEFORESAVETOFILE, null); + + odfContainer.createByteArray(cbSuccess, cbDoneSaving); } else { cb(); } } - if (hasLocalUnsyncedOps) { + if (hasError) { + cb(); + } else if (hasLocalUnsyncedOps) { requestInstantOpsSync(doClose); } else { doClose(); } }; + /** + * @param {!string} eventId + * @param {!Function} cb + * @return {undefined} + */ + this.subscribe = function (eventId, cb) { + eventNotifier.subscribe(eventId, cb); + }; + + /** + * @param {!string} eventId + * @param {!Function} cb + * @return {undefined} + */ + this.unsubscribe = function (eventId, cb) { + eventNotifier.unsubscribe(eventId, cb); + }; + + /** + * @return {!boolean} + */ + this.hasLocalUnsyncedOps = function () { + return hasLocalUnsyncedOps; + }; + + /** + * @return {!boolean} + */ + this.hasSessionHostConnection = function () { + return hasSessionHostConnection; + }; }; }); diff --git a/js/3rdparty/webodf/editor/server/pullbox/Server.js b/js/3rdparty/webodf/editor/server/pullbox/Server.js index ee17cee9..9b749fdc 100644 --- a/js/3rdparty/webodf/editor/server/pullbox/Server.js +++ b/js/3rdparty/webodf/editor/server/pullbox/Server.js @@ -40,6 +40,7 @@ define("webodf/editor/server/pullbox/Server", [], function () { var self = this, token, + /**@const*/serverCallTimeout = 10000, base64 = new core.Base64(); args = args || {}; @@ -53,22 +54,33 @@ define("webodf/editor/server/pullbox/Server", [], function () { /** * @param {!Object} message * @param {!function(!string)} cb + * @param {!function(!number,!string)} cbError passes the status number + * and the statustext, or -1 if there was an exception on sending * @return {undefined} */ - function call(message, cb) { + function call(message, cb, cbError) { var xhr = new XMLHttpRequest(), messageString = JSON.stringify(message); function handleResult() { if (xhr.readyState === 4) { - if ((xhr.status < 200 || xhr.status >= 300) && xhr.status === 0) { + if (xhr.status < 200 || xhr.status >= 300) { // report error runtime.log("Status " + String(xhr.status) + ": " + xhr.responseText || xhr.statusText); + cbError(xhr.status, xhr.statusText); + } else { + runtime.log("Status " + String(xhr.status) + ": " + + xhr.responseText || xhr.statusText); + cb(xhr.responseText); } - cb(xhr.responseText); } } + function handleTimeout() { + runtime.log("Timeout on call to server."); + cbError(0, xhr.statusText); + } + runtime.log("Sending message to server: "+messageString); // create body data for request from metadata and payload @@ -78,11 +90,14 @@ runtime.log("Sending message to server: "+messageString); xhr.setRequestHeader("requesttoken", token); } xhr.onreadystatechange = handleResult; + xhr.timeout = serverCallTimeout; + // TODO: seems handleResult is called on timeout as well, with xhr.status === 0 +// xhr.ontimeout = handleTimeout; try { xhr.send(messageString); } catch (e) { runtime.log("Problem with calling server: " + e + " " + data); - cb(e.message); + cbError(-1, e.message); } } @@ -151,14 +166,14 @@ runtime.log("Sending message to server: "+messageString); } else { failCb(responseData); } - }); + }, failCb); }; /** * @param {!string} userId * @param {!string} sessionId * @param {!function(!string)} successCb - * @param {function()=} failCb + * @param {!function()} failCb * @return {undefined} */ this.joinSession = function (userId, sessionId, successCb, failCb) { @@ -175,18 +190,16 @@ runtime.log("Sending message to server: "+messageString); if (response.hasOwnProperty("success") && response.success) { successCb(response.member_id); } else { - if (failCb) { - failCb(); - } + failCb(); } - }); + }, failCb); }; /** * @param {!string} sessionId * @param {!string} memberId * @param {!function()} successCb - * @param {function()=} failCb + * @param {!function()} failCb * @return {undefined} */ this.leaveSession = function (sessionId, memberId, successCb, failCb) { @@ -203,18 +216,16 @@ runtime.log("Sending message to server: "+messageString); if (response.hasOwnProperty("success") && response.success) { successCb(); } else { - if (failCb) { - failCb(); - } + failCb(); } - }); + }, failCb); }; /** * @param {!string} sessionId * @param {!string} memberId * @param {!string} seqHead - * @param {function()=} callback + * @param {!function(!Object=)} callback * @return {undefined} */ this.writeSessionStateToFile = function(sessionId, memberId, seqHead, fileData, callback) { diff --git a/js/3rdparty/webodf/editor/server/pullbox/ServerFactory.js b/js/3rdparty/webodf/editor/server/pullbox/ServerFactory.js index b2b5478c..626b5ed8 100644 --- a/js/3rdparty/webodf/editor/server/pullbox/ServerFactory.js +++ b/js/3rdparty/webodf/editor/server/pullbox/ServerFactory.js @@ -40,8 +40,8 @@ define("webodf/editor/server/pullbox/ServerFactory", [ this.createServer = function (args) { return new PullBoxServer(args); }; - this.createOperationRouter = function (sid, mid, server, odfContainer) { - return new PullBoxOperationRouter(sid, mid, server, odfContainer); + this.createOperationRouter = function (sid, mid, server, odfContainer, errorCallback) { + return new PullBoxOperationRouter(sid, mid, server, odfContainer, errorCallback); }; this.createSessionList = function (server) { return new PullBoxSessionList(server); diff --git a/js/3rdparty/webodf/editor/server/pullbox/SessionList.js b/js/3rdparty/webodf/editor/server/pullbox/SessionList.js index 988da2eb..68b96169 100644 --- a/js/3rdparty/webodf/editor/server/pullbox/SessionList.js +++ b/js/3rdparty/webodf/editor/server/pullbox/SessionList.js @@ -111,6 +111,8 @@ define("webodf/editor/server/pullbox/SessionList", [], function () { } else { runtime.log("Meh, sessionlist data broken: " + responseData); } + }, function() { + // ignore error for now }); } diff --git a/js/3rdparty/webodf/editor/widgets/paragraphStyles.js b/js/3rdparty/webodf/editor/widgets/paragraphStyles.js index e7a93640..57acaacb 100644 --- a/js/3rdparty/webodf/editor/widgets/paragraphStyles.js +++ b/js/3rdparty/webodf/editor/widgets/paragraphStyles.js @@ -75,7 +75,7 @@ define("webodf/editor/widgets/paragraphStyles", if (value === "") { value = defaultStyleUIId; } - select.set('value', value); + select.set('value', value, false); }; // events diff --git a/js/3rdparty/webodf/webodf-debug.js b/js/3rdparty/webodf/webodf-debug.js index 52a5ea3d..07813529 100644 --- a/js/3rdparty/webodf/webodf-debug.js +++ b/js/3rdparty/webodf/webodf-debug.js @@ -1,46 +1,4 @@ -/* - - - Copyright (C) 2012 KO GmbH - - @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 . - - 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/ -*/ -var core = {}; -var gui = {}; -var xmldom = {}; -var odf = {}; -var ops = {}; +var webodf_version = "0.4.2-1556-gf8a94ee"; function Runtime() { } Runtime.prototype.getVariable = function(name) { @@ -77,17 +35,23 @@ Runtime.prototype.clearTimeout = function(timeoutID) { }; Runtime.prototype.libraryPaths = function() { }; +Runtime.prototype.currentDirectory = function() { +}; +Runtime.prototype.setCurrentDirectory = function(dir) { +}; Runtime.prototype.type = function() { }; Runtime.prototype.getDOMImplementation = function() { }; Runtime.prototype.parseXML = function(xml) { }; +Runtime.prototype.exit = function(exitCode) { +}; Runtime.prototype.getWindow = function() { }; Runtime.prototype.assert = function(condition, message, callback) { }; -var IS_COMPILED_CODE = false; +var IS_COMPILED_CODE = true; Runtime.byteArrayToString = function(bytearray, encoding) { function byteArrayToString(bytearray) { var s = "", i, l = bytearray.length; @@ -486,6 +450,9 @@ function BrowserRuntime(logoutput) { }; this.setCurrentDirectory = function() { }; + this.currentDirectory = function() { + return"" + }; this.type = function() { return"BrowserRuntime" }; @@ -592,7 +559,7 @@ function NodeJSRuntime() { }) }; this.readFileSync = function(path, encoding) { - var enc = encoding === "binary" ? null : encoding, r = fs.readFileSync(path, enc), s; + var s, enc = encoding === "binary" ? null : encoding, r = fs.readFileSync(path, enc); if(r === null) { throw"File " + path + " could not be read."; } @@ -678,7 +645,7 @@ function NodeJSRuntime() { init() } function RhinoRuntime() { - var self = this, dom = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(), builder, entityresolver, currentDirectory = ""; + var self = this, Packages = {}, dom = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(), builder, entityresolver, currentDirectory = ""; dom.setValidating(false); dom.setNamespaceAware(true); dom.setExpandEntityReferences(false); @@ -695,7 +662,7 @@ function RhinoRuntime() { builder = dom.newDocumentBuilder(); builder.setEntityResolver(entityresolver); this.byteArrayFromString = function(string, encoding) { - var a = [], i, l = string.length; + var i, l = string.length, a = new Uint8Array(new ArrayBuffer(l)); for(i = 0;i < l;i += 1) { a[i] = string.charCodeAt(i) & 255 } @@ -706,13 +673,12 @@ function RhinoRuntime() { this.fromJson = Runtime.fromJson; this.toJson = Runtime.toJson; function loadXML(path, callback) { - var file = new Packages.java.io.File(path), xmlDocument; + var file = new Packages.java.io.File(path), xmlDocument = null; try { xmlDocument = builder.parse(file) }catch(err) { print(err); - callback(err); - return + return callback(err, null) } callback(null, xmlDocument) } @@ -722,10 +688,10 @@ function RhinoRuntime() { } var file = new Packages.java.io.File(path), data, rhinoencoding = encoding === "binary" ? "latin1" : encoding; if(!file.isFile()) { - callback(path + " is not a file.") + callback(path + " is not a file.", null) }else { data = readFile(path, rhinoencoding); - if(encoding === "binary") { + if(data && encoding === "binary") { data = self.byteArrayFromString(data, "binary") } callback(null, data) @@ -765,8 +731,9 @@ function RhinoRuntime() { if(currentDirectory) { path = currentDirectory + "/" + path } - var file = new Packages.java.io.File(path); - if(file["delete"]()) { + var file = new Packages.java.io.File(path), otherPath = path + Math.random(), other = new Packages.java.io.File(otherPath); + if(file.rename(other)) { + other.deleteOnExit(); callback(null) }else { callback("Could not delete " + path) @@ -780,7 +747,7 @@ function RhinoRuntime() { if(data) { callback(null, this.byteArrayFromString(data.substring(offset, offset + length), "binary")) }else { - callback("Cannot read " + path) + callback("Cannot read " + path, null) } }; this.readFileSync = function(path, encoding) { @@ -848,14 +815,15 @@ function RhinoRuntime() { return builder.getDOMImplementation() }; this.parseXML = function(xml) { - return builder.parse(xml) + var reader = new Packages.java.io.StringReader(xml), source = new Packages.org.xml.sax.InputSource(reader); + return builder.parse(source) }; this.exit = quit; this.getWindow = function() { return null } } -var runtime = function() { +Runtime.create = function create() { var result; if(String(typeof window) !== "undefined") { result = new BrowserRuntime(window.document.getElementById("logoutput")) @@ -867,98 +835,175 @@ var runtime = function() { } } return result -}(); +}; +var runtime = Runtime.create(); +var core = {}; +var gui = {}; +var xmldom = {}; +var odf = {}; +var ops = {}; (function() { - var cache = {}, dircontents = {}; - function getOrDefinePackage(packageNameComponents) { - var topname = packageNameComponents[0], i, pkg; - pkg = eval("if (typeof " + topname + " === 'undefined') {" + "eval('" + topname + " = {};');}" + topname); - for(i = 1;i < packageNameComponents.length - 1;i += 1) { - if(!pkg.hasOwnProperty(packageNameComponents[i])) { - pkg = pkg[packageNameComponents[i]] = {} - }else { - pkg = pkg[packageNameComponents[i]] + var dependencies = {}, loadedFiles = {}; + function loadManifest(dir, manifests) { + var path = dir + "/manifest.json", content, list, manifest, m; + if(loadedFiles.hasOwnProperty(path)) { + return + } + loadedFiles[path] = 1; + try { + content = runtime.readFileSync(path, "utf-8") + }catch(e) { + console.log(String(e)); + return + } + list = JSON.parse((content)); + manifest = (list); + for(m in manifest) { + if(manifest.hasOwnProperty(m)) { + manifests[m] = {dir:dir, deps:manifest[m]} } } - return pkg[packageNameComponents[packageNameComponents.length - 1]] } - runtime.loadClass = function(classpath) { + 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) + } + } + for(i = 0;i < deps.length;i += 1) { + add(deps[i], []) + } + return sorted + } + function expandDependencies(manifests) { + var path, deps, allDeps = {}; + for(path in manifests) { + if(manifests.hasOwnProperty(path)) { + expandPathDependencies(path, manifests, allDeps) + } + } + for(path in manifests) { + if(manifests.hasOwnProperty(path)) { + deps = (Object.keys(allDeps[path])); + manifests[path].deps = sortDeps(deps, allDeps); + manifests[path].deps.push(path) + } + } + dependencies = manifests + } + function loadManifests() { + if(Object.keys(dependencies).length > 0) { + return + } + var paths = runtime.libraryPaths(), manifests = {}, i; + if(runtime.currentDirectory()) { + loadManifest(runtime.currentDirectory(), manifests) + } + for(i = 0;i < paths.length;i += 1) { + loadManifest(paths[i], manifests) + } + 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]) + } + } + return deps + } + function evalArray(paths, contents) { + var i = 0; + while(i < paths.length && contents[i] !== undefined) { + if(contents[i] !== null) { + eval((contents[i])); + contents[i] = null + } + i += 1 + } + } + 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)) + } + }) + } + if(async) { + for(i = 0;i < paths.length;i += 1) { + loadedFiles[paths[i]] = 1; + loadFile(i) + } + } + 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)) + } + } + evalArray(paths, contents) + } + runtime.loadClass = function(classname) { if(IS_COMPILED_CODE) { return } - if(cache.hasOwnProperty(classpath)) { + var classpath = classPath(classname), paths; + if(loadedFiles.hasOwnProperty(classpath)) { return } - var names = classpath.split("."), impl; - impl = getOrDefinePackage(names); - if(impl) { - cache[classpath] = true; - return - } - function getPathFromManifests(classpath) { - var path = classpath.replace(/\./g, "/") + ".js", dirs = runtime.libraryPaths(), i, dir, code, codestr; - if(runtime.currentDirectory) { - dirs.push(runtime.currentDirectory()) - } - for(i = 0;i < dirs.length;i += 1) { - dir = dirs[i]; - if(!dircontents.hasOwnProperty(dir)) { - try { - code = runtime.readFileSync(dirs[i] + "/manifest.js", "utf8"); - if(code && code.length) { - codestr = (code); - dircontents[dir] = eval(codestr) - }else { - dircontents[dir] = null - } - }catch(e1) { - dircontents[dir] = null; - runtime.log("Cannot load manifest for " + dir + ".") - } - } - code = null; - dir = dircontents[dir]; - if(dir && (dir.indexOf && dir.indexOf(path) !== -1)) { - return dirs[i] + "/" + path - } - } - return null - } - function load(classpath) { - var code, path; - path = getPathFromManifests(classpath); - if(!path) { - throw classpath + " is not listed in any manifest.js."; - } - try { - code = runtime.readFileSync(path, "utf8") - }catch(e2) { - runtime.log("Error loading " + classpath + " " + e2); - throw e2; - } - if(code === undefined) { - throw"Cannot load class " + classpath; - } - code += "\n//# sourceURL=" + path; - code += "\n//@ sourceURL=" + path; - try { - code = eval(classpath + " = eval(code);") - }catch(e4) { - runtime.log("Error loading " + classpath + " " + e4); - throw e4; - } - return code - } - impl = load(classpath); - if(!impl || Runtime.getFunctionName(impl) !== names[names.length - 1]) { - runtime.log("Loaded code is not for " + names[names.length - 1]); - throw"Loaded code is not for " + names[names.length - 1]; - } - cache[classpath] = true + loadManifests(); + paths = getDependencies(classname); + loadFiles(paths) } })(); (function() { - var translator = function() { + var translator = function(string) { + return string }; function tr(original) { var result = translator(original); @@ -994,7 +1039,7 @@ var runtime = function() { runtime.setCurrentDirectory(path); function inner_run() { var script, path, args, argv, result; - result = eval(codestring); + result = (eval(codestring)); if(result) { runtime.exit(result) } @@ -1023,6 +1068,43 @@ var runtime = function() { } } })(String(typeof arguments) !== "undefined" && arguments); +core.Async = function Async() { + this.forEach = function(items, f, callback) { + var i, l = items.length, itemsDone = 0; + function end(err) { + if(itemsDone !== l) { + if(err) { + itemsDone = l; + callback(err) + }else { + itemsDone += 1; + if(itemsDone === l) { + callback(null) + } + } + } + } + for(i = 0;i < l;i += 1) { + f(items[i], end) + } + }; + this.destroyAll = function(items, callback) { + function destroy(itemIndex, err) { + if(err) { + callback(err) + }else { + if(itemIndex < items.length) { + items[itemIndex](function(err) { + destroy(itemIndex + 1, err) + }) + }else { + callback() + } + } + } + destroy(0, undefined) + } +}; function makeBase64() { function makeB64tab(bin) { var t = {}, i, l; @@ -1251,6 +1333,7816 @@ function makeBase64() { return core.Base64 } core.Base64 = makeBase64(); +core.ByteArray = function ByteArray(data) { + this.pos = 0; + this.data = data; + this.readUInt32LE = function() { + this.pos += 4; + var d = this.data, pos = this.pos; + return d[--pos] << 24 | d[--pos] << 16 | d[--pos] << 8 | d[--pos] + }; + this.readUInt16LE = function() { + this.pos += 2; + var d = this.data, pos = this.pos; + return d[--pos] << 8 | d[--pos] + } +}; +core.ByteArrayWriter = function ByteArrayWriter(encoding) { + var self = this, length = 0, bufferSize = 1024, data = new Uint8Array(new ArrayBuffer(bufferSize)); + function expand(extraLength) { + var newData; + if(extraLength > bufferSize - length) { + bufferSize = Math.max(2 * bufferSize, length + extraLength); + newData = new Uint8Array(new ArrayBuffer(bufferSize)); + newData.set(data); + data = newData + } + } + this.appendByteArrayWriter = function(writer) { + self.appendByteArray(writer.getByteArray()) + }; + this.appendByteArray = function(array) { + var l = array.length; + expand(l); + data.set(array, length); + length += l + }; + this.appendArray = function(array) { + var l = array.length; + expand(l); + data.set(array, length); + length += l + }; + this.appendUInt16LE = function(value) { + self.appendArray([value & 255, value >> 8 & 255]) + }; + this.appendUInt32LE = function(value) { + self.appendArray([value & 255, value >> 8 & 255, value >> 16 & 255, value >> 24 & 255]) + }; + this.appendString = function(string) { + self.appendByteArray(runtime.byteArrayFromString(string, encoding)) + }; + this.getLength = function() { + return length + }; + this.getByteArray = function() { + var a = new Uint8Array(new ArrayBuffer(length)); + a.set(data.subarray(0, length)); + return a + } +}; +core.CSSUnits = function CSSUnits() { + var self = this, sizemap = {"in":1, "cm":2.54, "mm":25.4, "pt":72, "pc":12}; + this.convert = function(value, oldUnit, newUnit) { + return value * sizemap[newUnit] / sizemap[oldUnit] + }; + this.convertMeasure = function(measure, newUnit) { + var value, oldUnit, newMeasure; + if(measure && newUnit) { + value = parseFloat(measure); + oldUnit = measure.replace(value.toString(), ""); + newMeasure = self.convert(value, oldUnit, newUnit).toString() + }else { + newMeasure = "" + } + return newMeasure + }; + this.getUnits = function(measure) { + return measure.substr(measure.length - 2, measure.length) + } +}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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 browserQuirks; + function getBrowserQuirks() { + var range, directBoundingRect, rangeBoundingRect, testContainer, testElement, detectedQuirks, window, document; + if(browserQuirks === undefined) { + window = runtime.getWindow(); + document = window && window.document; + browserQuirks = {rangeBCRIgnoresElementBCR:false, unscaledRangeClientRects:false}; + if(document) { + testContainer = document.createElement("div"); + testContainer.style.position = "absolute"; + testContainer.style.left = "-99999px"; + testContainer.style.transform = "scale(2)"; + testContainer.style["-webkit-transform"] = "scale(2)"; + testElement = document.createElement("div"); + testContainer.appendChild(testElement); + document.body.appendChild(testContainer); + range = document.createRange(); + range.selectNode(testElement); + browserQuirks.rangeBCRIgnoresElementBCR = range.getClientRects().length === 0; + testElement.appendChild(document.createTextNode("Rect transform test")); + directBoundingRect = testElement.getBoundingClientRect(); + rangeBoundingRect = range.getBoundingClientRect(); + browserQuirks.unscaledRangeClientRects = Math.abs(directBoundingRect.height - rangeBoundingRect.height) > 2; + range.detach(); + document.body.removeChild(testContainer); + detectedQuirks = Object.keys(browserQuirks).map(function(quirk) { + return quirk + ":" + String(browserQuirks[quirk]) + }).join(", "); + runtime.log("Detected browser quirks - " + detectedQuirks) + } + } + return browserQuirks + } + core.DomUtils = function DomUtils() { + var sharedRange = null; + function getSharedRange(doc) { + var range; + if(sharedRange) { + range = sharedRange + }else { + sharedRange = range = (doc.createRange()) + } + return range + } + function findStablePoint(container, offset) { + var c = container; + if(offset < c.childNodes.length) { + c = c.childNodes.item(offset); + offset = 0; + while(c.firstChild) { + c = c.firstChild + } + }else { + while(c.lastChild) { + c = c.lastChild; + offset = c.nodeType === Node.TEXT_NODE ? c.textContent.length : c.childNodes.length + } + } + return{container:c, offset:offset} + } + function splitBoundaries(range) { + var modifiedNodes = [], end, splitStart, node, text; + if(range.startContainer.nodeType === Node.TEXT_NODE || range.endContainer.nodeType === Node.TEXT_NODE) { + end = range.endContainer && findStablePoint(range.endContainer, range.endOffset); + range.setEnd(end.container, end.offset); + node = range.endContainer; + if(range.endOffset !== 0 && node.nodeType === Node.TEXT_NODE) { + text = (node); + if(range.endOffset !== text.length) { + modifiedNodes.push(text.splitText(range.endOffset)); + modifiedNodes.push(text) + } + } + node = range.startContainer; + if(range.startOffset !== 0 && node.nodeType === Node.TEXT_NODE) { + text = (node); + if(range.startOffset !== text.length) { + splitStart = text.splitText(range.startOffset); + modifiedNodes.push(text); + modifiedNodes.push(splitStart); + range.setStart(splitStart, 0) + } + } + } + return modifiedNodes + } + this.splitBoundaries = splitBoundaries; + function containsRange(container, insideRange) { + return container.compareBoundaryPoints(Range.START_TO_START, insideRange) <= 0 && container.compareBoundaryPoints(Range.END_TO_END, insideRange) >= 0 + } + this.containsRange = containsRange; + function rangesIntersect(range1, range2) { + 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) + }else { + if(filterResult === NodeFilter.FILTER_REJECT) { + break + } + } + n = n.parentNode + } + elements.reverse(); + n = treeWalker.nextNode(); + while(n) { + elements.push(n); + n = treeWalker.nextNode() + } + return elements + } + this.getNodesInRange = getNodesInRange; + function mergeTextNodes(node, nextNode) { + var mergedNode = null, text, nextText; + if(node.nodeType === Node.TEXT_NODE) { + text = (node); + if(text.length === 0) { + text.parentNode.removeChild(text); + if(nextNode.nodeType === Node.TEXT_NODE) { + mergedNode = nextNode + } + }else { + if(nextNode.nodeType === Node.TEXT_NODE) { + nextText = (nextNode); + text.appendData(nextText.data); + nextNode.parentNode.removeChild(nextNode) + } + mergedNode = node + } + } + return mergedNode + } + function normalizeTextNodes(node) { + if(node && node.nextSibling) { + node = mergeTextNodes(node, node.nextSibling) + } + if(node && node.previousSibling) { + mergeTextNodes(node.previousSibling, node) + } + } + this.normalizeTextNodes = normalizeTextNodes; + function rangeContainsNode(limits, node) { + var range = node.ownerDocument.createRange(), nodeRange = node.ownerDocument.createRange(), result; + range.setStart(limits.startContainer, limits.startOffset); + range.setEnd(limits.endContainer, limits.endOffset); + nodeRange.selectNodeContents(node); + result = containsRange(range, nodeRange); + range.detach(); + nodeRange.detach(); + return result + } + this.rangeContainsNode = rangeContainsNode; + function mergeIntoParent(targetNode) { + var parent = targetNode.parentNode; + while(targetNode.firstChild) { + parent.insertBefore(targetNode.firstChild, targetNode) + } + parent.removeChild(targetNode); + return parent + } + this.mergeIntoParent = mergeIntoParent; + function removeUnwantedNodes(targetNode, shouldRemove) { + var parent = targetNode.parentNode, node = targetNode.firstChild, next; + while(node) { + next = node.nextSibling; + removeUnwantedNodes(node, shouldRemove); + node = next + } + if(shouldRemove(targetNode)) { + parent = mergeIntoParent(targetNode) + } + return parent + } + this.removeUnwantedNodes = removeUnwantedNodes; + function getElementsByTagNameNS(node, namespace, tagName) { + var e = [], list, i, l; + list = node.getElementsByTagNameNS(namespace, tagName); + e.length = l = list.length; + for(i = 0;i < l;i += 1) { + e[i] = (list.item(i)) + } + 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)) + } + this.containsNode = containsNode; + 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 + } + var comparison = c1.compareDocumentPosition(c2); + if(comparison === 2) { + comparison = -1 + }else { + if(comparison === 4) { + comparison = 1 + }else { + if(comparison === 10) { + o1 = getPositionInContainingNode(c1, c2); + comparison = o1 < o2 ? 1 : -1 + }else { + o2 = getPositionInContainingNode(c2, c1); + comparison = o2 < o1 ? -1 : 1 + } + } + } + return comparison + } + this.comparePoints = comparePoints; + function adaptRangeDifferenceToZoomLevel(inputNumber, zoomLevel) { + if(getBrowserQuirks().unscaledRangeClientRects) { + return inputNumber + } + return inputNumber / zoomLevel + } + this.adaptRangeDifferenceToZoomLevel = adaptRangeDifferenceToZoomLevel; + function getBoundingClientRect(node) { + var doc = (node.ownerDocument), quirks = getBrowserQuirks(), range, element; + if(quirks.unscaledRangeClientRects === false || quirks.rangeBCRIgnoresElementBCR) { + if(node.nodeType === Node.ELEMENT_NODE) { + element = (node); + return element.getBoundingClientRect() + } + } + range = getSharedRange(doc); + range.selectNode(node); + return range.getBoundingClientRect() + } + this.getBoundingClientRect = getBoundingClientRect; + function mapKeyValObjOntoNode(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(ns) { + element = (node.getElementsByTagNameNS(ns, localName)[0]); + if(!element) { + element = node.ownerDocument.createElementNS(ns, key); + node.appendChild(element) + } + element.textContent = value + }else { + runtime.log("Key ignored: " + key) + } + }) + } + this.mapKeyValObjOntoNode = mapKeyValObjOntoNode; + function removeKeyElementsFromNode(node, propertyNames, nsResolver) { + propertyNames.forEach(function(propertyName) { + var parts = propertyName.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), element; + if(ns) { + element = (node.getElementsByTagNameNS(ns, localName)[0]); + if(element) { + element.parentNode.removeChild(element) + }else { + runtime.log("Element for " + propertyName + " not found.") + } + }else { + runtime.log("Property Name ignored: " + propertyName) + } + }) + } + this.removeKeyElementsFromNode = removeKeyElementsFromNode; + function getKeyValRepresentationOfNode(node, prefixResolver) { + var properties = {}, currentSibling = node.firstElementChild, prefix; + while(currentSibling) { + prefix = prefixResolver(currentSibling.namespaceURI); + if(prefix) { + properties[prefix + ":" + currentSibling.localName] = currentSibling.textContent + } + currentSibling = currentSibling.nextElementSibling + } + return properties + } + 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) + } + node.appendChild(element); + mapObjOntoNode(element, (value), nsResolver) + }else { + if(ns) { + node.setAttributeNS(ns, key, String(value)) + } + } + }) + } + this.mapObjOntoNode = mapObjOntoNode; + function init(self) { + var appVersion, webKitOrSafari, ie, window = runtime.getWindow(); + if(window === null) { + return + } + appVersion = window.navigator.appVersion.toLowerCase(); + webKitOrSafari = appVersion.indexOf("chrome") === -1 && (appVersion.indexOf("applewebkit") !== -1 || appVersion.indexOf("safari") !== -1); + ie = appVersion.indexOf("msie"); + if(webKitOrSafari || ie) { + self.containsNode = containsNodeForBrokenWebKit + } + } + init(this) + }; + return core.DomUtils +})(); +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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.EventNotifier = function EventNotifier(eventIds) { + var eventListener = {}; + this.emit = function(eventId, args) { + var i, subscribers; + runtime.assert(eventListener.hasOwnProperty(eventId), 'unknown event fired "' + eventId + '"'); + subscribers = eventListener[eventId]; + for(i = 0;i < subscribers.length;i += 1) { + subscribers[i](args) + } + }; + 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.') + }; + this.unsubscribe = function(eventId, cb) { + var cbIndex; + runtime.assert(eventListener.hasOwnProperty(eventId), 'tried to unsubscribe from unknown event "' + eventId + '"'); + cbIndex = eventListener[eventId].indexOf(cb); + runtime.assert(cbIndex !== -1, 'tried to unsubscribe unknown callback from event "' + eventId + '"'); + if(cbIndex !== -1) { + eventListener[eventId].splice(cbIndex, 1) + } + runtime.log('event "' + eventId + '" unsubscribed.') + }; + function init() { + var i, eventId; + for(i = 0;i < eventIds.length;i += 1) { + eventId = eventIds[i]; + runtime.assert(!eventListener.hasOwnProperty(eventId), 'Duplicated event ids: "' + eventId + '" registered more than once.'); + eventListener[eventId] = [] + } + } + init() +}; +/* + + Copyright (C) 2012 KO GmbH + + @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 . + + 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.LoopWatchDog = function LoopWatchDog(timeout, maxChecks) { + var startTime = Date.now(), checks = 0; + function check() { + var t; + if(timeout) { + t = Date.now(); + if(t - startTime > timeout) { + runtime.log("alert", "watchdog timeout"); + throw"timeout!"; + } + } + if(maxChecks > 0) { + checks += 1; + if(checks > maxChecks) { + runtime.log("alert", "watchdog loop overflow"); + throw"loop overflow"; + } + } + } + this.check = check +}; +core.PositionIterator = function PositionIterator(root, whatToShow, filter, expandEntityReferences) { + var self = this, walker, currentPos, nodeFilter, TEXT_NODE = Node.TEXT_NODE, ELEMENT_NODE = Node.ELEMENT_NODE, FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT; + function EmptyTextNodeFilter() { + this.acceptNode = function(node) { + var text = (node); + if(!node || node.nodeType === TEXT_NODE && text.length === 0) { + return FILTER_REJECT + } + return FILTER_ACCEPT + } + } + function FilteredEmptyTextNodeFilter(filter) { + this.acceptNode = function(node) { + var text = (node); + if(!node || node.nodeType === TEXT_NODE && text.length === 0) { + return FILTER_REJECT + } + return filter.acceptNode(node) + } + } + this.nextPosition = function() { + var currentNode = walker.currentNode, nodeType = currentNode.nodeType, text = (currentNode); + if(currentNode === root) { + return false + } + if(currentPos === 0 && nodeType === ELEMENT_NODE) { + if(walker.firstChild() === null) { + currentPos = 1 + } + }else { + if(nodeType === TEXT_NODE && currentPos + 1 < text.length) { + currentPos += 1 + }else { + if(walker.nextSibling() !== null) { + currentPos = 0 + }else { + if(walker.parentNode()) { + currentPos = 1 + }else { + return false + } + } + } + } + return true + }; + function setAtEnd() { + var text = (walker.currentNode), type = text.nodeType; + if(type === TEXT_NODE) { + currentPos = text.length - 1 + }else { + currentPos = type === ELEMENT_NODE ? 1 : 0 + } + } + function previousNode() { + if(walker.previousSibling() === null) { + if(!walker.parentNode() || walker.currentNode === root) { + walker.firstChild(); + return false + } + currentPos = 0 + }else { + setAtEnd() + } + return true + } + this.previousPosition = function() { + var moved = true, currentNode = walker.currentNode; + if(currentPos === 0) { + moved = previousNode() + }else { + if(currentNode.nodeType === TEXT_NODE) { + currentPos -= 1 + }else { + if(walker.lastChild() !== null) { + setAtEnd() + }else { + if(currentNode === root) { + moved = false + }else { + currentPos = 0 + } + } + } + } + return moved + }; + this.previousNode = previousNode; + this.container = function() { + var n = (walker.currentNode), t = n.nodeType; + if(currentPos === 0 && t !== TEXT_NODE) { + n = (n.parentNode) + } + return n + }; + this.rightNode = function() { + var n = walker.currentNode, text = (n), nodeType = n.nodeType; + if(nodeType === TEXT_NODE && currentPos === text.length) { + n = n.nextSibling; + while(n && nodeFilter(n) !== FILTER_ACCEPT) { + n = n.nextSibling + } + }else { + if(nodeType === ELEMENT_NODE && currentPos === 1) { + n = null + } + } + return n + }; + this.leftNode = function() { + var n = walker.currentNode; + if(currentPos === 0) { + n = n.previousSibling; + while(n && nodeFilter(n) !== FILTER_ACCEPT) { + n = n.previousSibling + } + }else { + if(n.nodeType === ELEMENT_NODE) { + n = n.lastChild; + while(n && nodeFilter(n) !== FILTER_ACCEPT) { + n = n.previousSibling + } + } + } + return n + }; + this.getCurrentNode = function() { + var n = (walker.currentNode); + return n + }; + this.unfilteredDomOffset = function() { + if(walker.currentNode.nodeType === TEXT_NODE) { + return currentPos + } + var c = 0, n = walker.currentNode; + if(currentPos === 1) { + n = n.lastChild + }else { + n = n.previousSibling + } + while(n) { + c += 1; + n = n.previousSibling + } + return c + }; + this.getPreviousSibling = function() { + var currentNode = walker.currentNode, sibling = walker.previousSibling(); + walker.currentNode = currentNode; + return sibling + }; + this.getNextSibling = function() { + var currentNode = walker.currentNode, sibling = walker.nextSibling(); + walker.currentNode = currentNode; + return sibling + }; + this.setUnfilteredPosition = function(container, offset) { + var filterResult, node, text; + runtime.assert(container !== null && container !== undefined, "PositionIterator.setUnfilteredPosition called without container"); + walker.currentNode = container; + if(container.nodeType === TEXT_NODE) { + currentPos = offset; + text = (container); + runtime.assert(offset <= text.length, "Error in setPosition: " + offset + " > " + text.length); + runtime.assert(offset >= 0, "Error in setPosition: " + offset + " < 0"); + if(offset === text.length) { + if(walker.nextSibling()) { + currentPos = 0 + }else { + if(walker.parentNode()) { + currentPos = 1 + }else { + runtime.assert(false, "Error in setUnfilteredPosition: position not valid.") + } + } + } + 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) { + 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 + }; + this.moveToEnd = function() { + walker.currentNode = root; + currentPos = 1 + }; + this.moveToEndOfNode = function(node) { + var text; + if(node.nodeType === TEXT_NODE) { + text = (node); + self.setUnfilteredPosition(text, text.length) + }else { + walker.currentNode = node; + currentPos = 1 + } + }; + this.getNodeFilter = function() { + return nodeFilter + }; + function init() { + var f; + if(filter) { + f = new FilteredEmptyTextNodeFilter(filter) + }else { + f = new EmptyTextNodeFilter + } + nodeFilter = (f.acceptNode); + nodeFilter.acceptNode = nodeFilter; + whatToShow = whatToShow || 4294967295; + 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; + if(walker.firstChild() === null) { + currentPos = 1 + } + } + init() +}; +core.zip_HuftNode = function() { + this.e = 0; + this.b = 0; + this.n = 0; + this.t = null +}; +core.zip_HuftList = function() { + this.next = null; + this.list = null +}; +core.RawInflate = function RawInflate() { + var zip_WSIZE = 32768; + var zip_STORED_BLOCK = 0; + var zip_lbits = 9; + var zip_dbits = 6; + var zip_slide = []; + var zip_wp; + var zip_fixed_tl = null; + var zip_fixed_td; + var zip_fixed_bl; + var zip_bit_buf; + var zip_bit_len; + var zip_method; + var zip_eof; + var zip_copy_leng; + var zip_copy_dist; + var zip_tl, zip_td; + var zip_bl, zip_bd; + var zip_inflate_data; + var zip_inflate_pos; + var zip_MASK_BITS = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535]; + var zip_cplens = [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]; + var zip_cplext = [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]; + var zip_cpdist = [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]; + var zip_cpdext = [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]; + var zip_border = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + function Zip_HuftBuild(b, n, s, d, e, mm) { + this.BMAX = 16; + this.N_MAX = 288; + this.status = 0; + this.root = null; + this.m = 0; + var a, c = new Array(this.BMAX + 1), el, f, g, h, i, j, k, lx = new Array(this.BMAX + 1), p, pidx, q, r = new core.zip_HuftNode, u = new Array(this.BMAX), v = new Array(this.N_MAX), w, x = new Array(this.BMAX + 1), xp, y, z, o, tail; + tail = this.root = null; + for(i = 0;i < c.length;i++) { + c[i] = 0 + } + for(i = 0;i < lx.length;i++) { + lx[i] = 0 + } + for(i = 0;i < u.length;i++) { + u[i] = null + } + for(i = 0;i < v.length;i++) { + v[i] = 0 + } + for(i = 0;i < x.length;i++) { + x[i] = 0 + } + el = n > 256 ? b[256] : this.BMAX; + p = b; + pidx = 0; + i = n; + do { + c[p[pidx]]++; + pidx++ + }while(--i > 0); + if(c[0] === n) { + this.root = null; + this.m = 0; + this.status = 0; + return + } + for(j = 1;j <= this.BMAX;j++) { + if(c[j] !== 0) { + break + } + } + k = j; + if(mm < j) { + mm = j + } + for(i = this.BMAX;i !== 0;i--) { + if(c[i] !== 0) { + break + } + } + g = i; + if(mm > i) { + mm = i + } + for(y = 1 << j;j < i;j++, y <<= 1) { + y -= c[j]; + if(y < 0) { + this.status = 2; + this.m = mm; + return + } + } + y -= c[i]; + if(y < 0) { + this.status = 2; + this.m = mm; + return + } + c[i] += y; + x[1] = j = 0; + p = c; + pidx = 1; + xp = 2; + while(--i > 0) { + j += p[pidx++]; + x[xp++] = j + } + p = b; + pidx = 0; + i = 0; + do { + j = p[pidx++]; + if(j !== 0) { + v[x[j]++] = i + } + }while(++i < n); + n = x[g]; + x[0] = i = 0; + p = v; + pidx = 0; + h = -1; + w = lx[0] = 0; + q = null; + z = 0; + k -= 1; + for(k += 1;k <= g;k++) { + a = c[k]; + while(a-- > 0) { + while(k > w + lx[1 + h]) { + w += lx[1 + h]; + h++; + z = g - w; + z = z > mm ? mm : z; + j = k - w; + f = 1 << j; + if(f > a + 1) { + f -= a + 1; + xp = k; + while(++j < z) { + f <<= 1; + if(f <= c[++xp]) { + break + } + f -= c[xp] + } + } + if(w + j > el && w < el) { + j = el - w + } + z = 1 << j; + lx[1 + h] = j; + q = new Array(z); + for(o = 0;o < z;o++) { + q[o] = new core.zip_HuftNode + } + if(tail === null) { + tail = this.root = new core.zip_HuftList + }else { + tail = tail.next = new core.zip_HuftList + } + tail.next = null; + tail.list = q; + u[h] = q; + if(h > 0) { + x[h] = i; + r.b = lx[h]; + r.e = 16 + j; + r.t = q; + j = (i & (1 << w) - 1) >> w - lx[h]; + u[h - 1][j].e = r.e; + u[h - 1][j].b = r.b; + u[h - 1][j].n = (r).n; + u[h - 1][j].t = r.t + } + } + r.b = k - w; + if(pidx >= n) { + r.e = 99 + }else { + if(p[pidx] < s) { + r.e = p[pidx] < 256 ? 16 : 15; + r.n = p[pidx++] + }else { + r.e = e[p[pidx] - s]; + r.n = d[p[pidx++] - s] + } + } + f = 1 << k - w; + for(j = i >> w;j < z;j += f) { + q[j].e = r.e; + q[j].b = r.b; + q[j].n = (r).n; + q[j].t = r.t + } + for(j = 1 << k - 1;(i & j) !== 0;j >>= 1) { + i ^= j + } + i ^= j; + while((i & (1 << w) - 1) !== x[h]) { + w -= lx[h]; + h-- + } + } + } + this.m = lx[1]; + this.status = y !== 0 && g !== 1 ? 1 : 0 + } + function zip_GET_BYTE() { + if(zip_inflate_data.length === zip_inflate_pos) { + return-1 + } + return zip_inflate_data[zip_inflate_pos++] + } + function zip_NEEDBITS(n) { + while(zip_bit_len < n) { + zip_bit_buf |= zip_GET_BYTE() << zip_bit_len; + zip_bit_len += 8 + } + } + function zip_GETBITS(n) { + return zip_bit_buf & zip_MASK_BITS[n] + } + function zip_DUMPBITS(n) { + zip_bit_buf >>= n; + zip_bit_len -= n + } + function zip_inflate_codes(buff, off, size) { + var e, t, n; + if(size === 0) { + return 0 + } + n = 0; + for(;;) { + zip_NEEDBITS(zip_bl); + t = zip_tl.list[zip_GETBITS(zip_bl)]; + e = t.e; + while(e > 16) { + if(e === 99) { + return-1 + } + zip_DUMPBITS(t.b); + e -= 16; + zip_NEEDBITS(e); + t = t.t[zip_GETBITS(e)]; + e = t.e + } + zip_DUMPBITS(t.b); + if(e === 16) { + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] = t.n; + if(n === size) { + return size + } + }else { + if(e === 15) { + break + } + zip_NEEDBITS(e); + zip_copy_leng = t.n + zip_GETBITS(e); + zip_DUMPBITS(e); + zip_NEEDBITS(zip_bd); + t = zip_td.list[zip_GETBITS(zip_bd)]; + e = t.e; + while(e > 16) { + if(e === 99) { + return-1 + } + zip_DUMPBITS(t.b); + e -= 16; + zip_NEEDBITS(e); + t = t.t[zip_GETBITS(e)]; + e = t.e + } + zip_DUMPBITS(t.b); + zip_NEEDBITS(e); + zip_copy_dist = zip_wp - t.n - zip_GETBITS(e); + zip_DUMPBITS(e); + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_copy_dist &= zip_WSIZE - 1; + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++] + } + if(n === size) { + return size + } + } + } + zip_method = -1; + return n + } + function zip_inflate_stored(buff, off, size) { + var n; + n = zip_bit_len & 7; + zip_DUMPBITS(n); + zip_NEEDBITS(16); + n = zip_GETBITS(16); + zip_DUMPBITS(16); + zip_NEEDBITS(16); + if(n !== (~zip_bit_buf & 65535)) { + return-1 + } + zip_DUMPBITS(16); + zip_copy_leng = n; + n = 0; + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_wp &= zip_WSIZE - 1; + zip_NEEDBITS(8); + buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); + zip_DUMPBITS(8) + } + if(zip_copy_leng === 0) { + zip_method = -1 + } + return n + } + var zip_fixed_bd; + function zip_inflate_fixed(buff, off, size) { + if(zip_fixed_tl === null) { + var i; + var l = new Array(288); + var h; + for(i = 0;i < 144;i++) { + l[i] = 8 + } + for(i = 144;i < 256;i++) { + l[i] = 9 + } + for(i = 256;i < 280;i++) { + l[i] = 7 + } + for(i = 280;i < 288;i++) { + l[i] = 8 + } + zip_fixed_bl = 7; + h = new Zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext, zip_fixed_bl); + if(h.status !== 0) { + alert("HufBuild error: " + h.status); + return-1 + } + zip_fixed_tl = h.root; + zip_fixed_bl = h.m; + for(i = 0;i < 30;i++) { + l[i] = 5 + } + zip_fixed_bd = 5; + h = new Zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd); + if(h.status > 1) { + zip_fixed_tl = null; + alert("HufBuild error: " + h.status); + return-1 + } + zip_fixed_td = h.root; + zip_fixed_bd = h.m + } + zip_tl = zip_fixed_tl; + zip_td = zip_fixed_td; + zip_bl = zip_fixed_bl; + zip_bd = zip_fixed_bd; + return zip_inflate_codes(buff, off, size) + } + function zip_inflate_dynamic(buff, off, size) { + var i; + var j; + var l; + var n; + var t; + var nb; + var nl; + var nd; + var ll = new Array(286 + 30); + var h; + for(i = 0;i < ll.length;i++) { + ll[i] = 0 + } + zip_NEEDBITS(5); + nl = 257 + zip_GETBITS(5); + zip_DUMPBITS(5); + zip_NEEDBITS(5); + nd = 1 + zip_GETBITS(5); + zip_DUMPBITS(5); + zip_NEEDBITS(4); + nb = 4 + zip_GETBITS(4); + zip_DUMPBITS(4); + if(nl > 286 || nd > 30) { + return-1 + } + for(j = 0;j < nb;j++) { + zip_NEEDBITS(3); + ll[zip_border[j]] = zip_GETBITS(3); + zip_DUMPBITS(3) + } + for(j = nb;j < 19;j++) { + ll[zip_border[j]] = 0 + } + zip_bl = 7; + h = new Zip_HuftBuild(ll, 19, 19, null, null, zip_bl); + if(h.status !== 0) { + return-1 + } + zip_tl = h.root; + zip_bl = h.m; + n = nl + nd; + i = l = 0; + while(i < n) { + zip_NEEDBITS(zip_bl); + t = zip_tl.list[zip_GETBITS(zip_bl)]; + j = t.b; + zip_DUMPBITS(j); + j = t.n; + if(j < 16) { + ll[i++] = l = j + }else { + if(j === 16) { + zip_NEEDBITS(2); + j = 3 + zip_GETBITS(2); + zip_DUMPBITS(2); + if(i + j > n) { + return-1 + } + while(j-- > 0) { + ll[i++] = l + } + }else { + if(j === 17) { + zip_NEEDBITS(3); + j = 3 + zip_GETBITS(3); + zip_DUMPBITS(3); + if(i + j > n) { + return-1 + } + while(j-- > 0) { + ll[i++] = 0 + } + l = 0 + }else { + zip_NEEDBITS(7); + j = 11 + zip_GETBITS(7); + zip_DUMPBITS(7); + if(i + j > n) { + return-1 + } + while(j-- > 0) { + ll[i++] = 0 + } + l = 0 + } + } + } + } + zip_bl = zip_lbits; + h = new Zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl); + if(zip_bl === 0) { + h.status = 1 + } + if(h.status !== 0) { + return-1 + } + zip_tl = h.root; + zip_bl = h.m; + for(i = 0;i < nd;i++) { + ll[i] = ll[i + nl] + } + zip_bd = zip_dbits; + h = new Zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd); + zip_td = h.root; + zip_bd = h.m; + if(zip_bd === 0 && nl > 257) { + return-1 + } + if(h.status !== 0) { + return-1 + } + return zip_inflate_codes(buff, off, size) + } + function zip_inflate_start() { + zip_slide.length = 2 * zip_WSIZE; + zip_wp = 0; + zip_bit_buf = 0; + zip_bit_len = 0; + zip_method = -1; + zip_eof = false; + zip_copy_leng = zip_copy_dist = 0; + zip_tl = null + } + function zip_inflate_internal(buff, off, size) { + var n = 0, i; + while(n < size) { + if(zip_eof && zip_method === -1) { + return n + } + if(zip_copy_leng > 0) { + if(zip_method !== zip_STORED_BLOCK) { + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_copy_dist &= zip_WSIZE - 1; + zip_wp &= zip_WSIZE - 1; + buff[off + n] = zip_slide[zip_wp] = zip_slide[zip_copy_dist]; + n += 1; + zip_wp += 1; + zip_copy_dist += 1 + } + }else { + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng -= 1; + zip_wp &= zip_WSIZE - 1; + zip_NEEDBITS(8); + buff[off + n] = zip_slide[zip_wp] = zip_GETBITS(8); + n += 1; + zip_wp += 1; + zip_DUMPBITS(8) + } + if(zip_copy_leng === 0) { + zip_method = -1 + } + } + if(n === size) { + return n + } + } + if(zip_method === -1) { + if(zip_eof) { + break + } + zip_NEEDBITS(1); + if(zip_GETBITS(1) !== 0) { + zip_eof = true + } + zip_DUMPBITS(1); + zip_NEEDBITS(2); + zip_method = zip_GETBITS(2); + zip_DUMPBITS(2); + zip_tl = null; + zip_copy_leng = 0 + } + switch(zip_method) { + case 0: + i = zip_inflate_stored(buff, off + n, size - n); + break; + case 1: + if(zip_tl !== null) { + i = zip_inflate_codes(buff, off + n, size - n) + }else { + i = zip_inflate_fixed(buff, off + n, size - n) + } + break; + case 2: + if(zip_tl !== null) { + i = zip_inflate_codes(buff, off + n, size - n) + }else { + i = zip_inflate_dynamic(buff, off + n, size - n) + } + break; + default: + i = -1; + break + } + if(i === -1) { + if(zip_eof) { + return 0 + } + return-1 + } + n += i + } + return n + } + function zip_inflate(data, size) { + zip_inflate_start(); + zip_inflate_data = data; + zip_inflate_pos = 0; + var buff = new Uint8Array(new ArrayBuffer(size)); + zip_inflate_internal(buff, 0, size); + zip_inflate_data = new Uint8Array(new ArrayBuffer(0)); + return buff + } + this.inflate = zip_inflate +}; +core.ScheduledTask = function ScheduledTask(fn, delay) { + var timeoutId, scheduled = false, args = []; + function cancel() { + if(scheduled) { + runtime.clearTimeout(timeoutId); + scheduled = false + } + } + function execute() { + cancel(); + fn.apply(undefined, args); + args = null + } + this.trigger = function() { + args = Array.prototype.slice.call(arguments); + if(!scheduled) { + scheduled = true; + timeoutId = runtime.setTimeout(execute, delay) + } + }; + this.triggerImmediate = function() { + args = Array.prototype.slice.call(arguments); + execute() + }; + this.processRequests = function() { + if(scheduled) { + execute() + } + }; + this.cancel = cancel; + this.destroy = function(callback) { + cancel(); + callback() + } +}; +core.NamedFunction; +core.NamedAsyncFunction; +core.UnitTest = function UnitTest() { +}; +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 maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea"); + runtime.assert(!testarea, 'Unclean test environment, found a div with id "testarea".'); + testarea = maindoc.createElement("div"); + testarea.setAttribute("id", "testarea"); + maindoc.body.appendChild(testarea); + return(testarea) +}; +core.UnitTest.cleanupTestAreaDiv = function() { + var maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea"); + runtime.assert(!!testarea && testarea.parentNode === maindoc.body, 'Test environment broken, found no div with id "testarea" below body.'); + maindoc.body.removeChild(testarea) +}; +core.UnitTest.createOdtDocument = function(xml, namespaceMap) { + var xmlDoc = ""; + xmlDoc += "" + text + "" + } + 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"; + if(results.hasOwnProperty(testName)) { + runtime.log("Test " + testName + " has already run."); + return + } + if(inBrowser) { + runtime.log("Running " + link(testName, 'runSuite("' + testName + '");') + ": " + test.description() + "") + }else { + runtime.log("Running " + testName + ": " + test.description) + } + tests = test.tests(); + for(i = 0;i < tests.length;i += 1) { + t = tests[i].f; + tname = tests[i].name; + if(testNames.length && testNames.indexOf(tname) === -1) { + continue + } + if(inBrowser) { + runtime.log("Running " + link(tname, 'runTest("' + testName + '","' + tname + '")') + "") + }else { + runtime.log("Running " + tname) + } + lastFailCount = runner.countFailedTests(); + test.setUp(); + t(); + test.tearDown(); + testResults[tname] = lastFailCount === runner.countFailedTests() + } + function runAsyncTests(todo) { + if(todo.length === 0) { + results[testName] = testResults; + failedTests += runner.countFailedTests(); + callback(); + return + } + t = todo[0].f; + var fname = todo[0].name; + runtime.log("Running " + fname); + lastFailCount = runner.countFailedTests(); + test.setUp(); + t(function() { + test.tearDown(); + testResults[fname] = lastFailCount === runner.countFailedTests(); + runAsyncTests(todo.slice(1)) + }) + } + runAsyncTests(test.asyncTests()) + }; + this.countFailedTests = function() { + return failedTests + }; + this.results = function() { + return results + } +}; +core.Utils = function Utils() { + function hashString(value) { + var hash = 0, i, l; + for(i = 0, l = value.length;i < l;i += 1) { + hash = (hash << 5) - hash + value.charCodeAt(i); + hash |= 0 + } + return hash + } + this.hashString = hashString; + var mergeObjects; + function mergeItems(destination, source) { + if(source && Array.isArray(source)) { + destination = destination || []; + if(!Array.isArray(destination)) { + throw"Destination is not an array."; + } + destination = (destination).concat((source).map(function(obj) { + return mergeItems(null, obj) + })) + }else { + if(source && typeof source === "object") { + destination = destination || {}; + if(typeof destination !== "object") { + throw"Destination is not an object."; + } + Object.keys((source)).forEach(function(p) { + destination[p] = mergeItems(destination[p], source[p]) + }) + }else { + destination = source + } + } + return destination + } + mergeObjects = function(destination, source) { + Object.keys(source).forEach(function(p) { + destination[p] = mergeItems(destination[p], source[p]) + }); + return destination + }; + this.mergeObjects = mergeObjects +}; +/* + + WebODF + Copyright (c) 2010 Jos van den Oever + Licensed under the ... License: + + 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) { + var table = [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], crc = + 0, i, iTop = data.length, x = 0, y = 0; + crc = crc ^ -1; + for(i = 0;i < iTop;i += 1) { + y = (crc ^ data[i]) & 255; + x = table[y]; + crc = crc >>> 8 ^ x + } + return crc ^ -1 + } + function dosTime2Date(dostime) { + var year = (dostime >> 25 & 127) + 1980, month = (dostime >> 21 & 15) - 1, mday = dostime >> 16 & 31, hour = dostime >> 11 & 15, min = dostime >> 5 & 63, sec = (dostime & 31) << 1, d = new Date(year, month, mday, hour, min, sec); + return d + } + function date2DosTime(date) { + var y = date.getFullYear(); + return y < 1980 ? 0 : y - 1980 << 25 | date.getMonth() + 1 << 21 | date.getDate() << 16 | date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1 + } + function ZipEntry(url, stream) { + var sig, namelen, extralen, commentlen, compressionMethod, compressedSize, uncompressedSize, offset, entry = this; + function handleEntryData(data, callback) { + var estream = new core.ByteArray(data), esig = estream.readUInt32LE(), filenamelen, eextralen; + if(esig !== 67324752) { + callback("File entry signature is wrong." + esig.toString() + " " + data.length.toString(), null); + return + } + estream.pos += 22; + filenamelen = estream.readUInt16LE(); + eextralen = estream.readUInt16LE(); + estream.pos += filenamelen + eextralen; + if(compressionMethod) { + data = data.subarray(estream.pos, estream.pos + compressedSize); + if(compressedSize !== data.length) { + callback("The amount of compressed bytes read was " + data.length.toString() + " instead of " + compressedSize.toString() + " for " + entry.filename + " in " + url + ".", null); + return + } + data = inflate(data, uncompressedSize) + }else { + data = data.subarray(estream.pos, estream.pos + uncompressedSize) + } + if(uncompressedSize !== data.length) { + callback("The amount of bytes read was " + data.length.toString() + " instead of " + uncompressedSize.toString() + " for " + entry.filename + " in " + url + ".", null); + return + } + entry.data = data; + callback(null, data) + } + function load(callback) { + if(entry.data !== null) { + callback(null, entry.data); + return + } + var size = compressedSize + 34 + namelen + extralen + 256; + if(size + offset > filesize) { + size = filesize - offset + } + runtime.read(url, offset, size, function(err, data) { + if(err || data === null) { + callback(err, data) + }else { + handleEntryData(data, callback) + } + }) + } + this.load = load; + function set(filename, data, compressed, date) { + entry.filename = filename; + entry.data = data; + entry.compressed = compressed; + entry.date = date + } + this.set = set; + this.error = null; + if(!stream) { + return + } + sig = stream.readUInt32LE(); + if(sig !== 33639248) { + this.error = "Central directory entry has wrong signature at position " + (stream.pos - 4).toString() + ' for file "' + url + '": ' + stream.data.length.toString(); + return + } + stream.pos += 6; + compressionMethod = stream.readUInt16LE(); + this.date = dosTime2Date(stream.readUInt32LE()); + stream.readUInt32LE(); + compressedSize = stream.readUInt32LE(); + uncompressedSize = stream.readUInt32LE(); + namelen = stream.readUInt16LE(); + extralen = stream.readUInt16LE(); + commentlen = stream.readUInt16LE(); + stream.pos += 8; + offset = stream.readUInt32LE(); + this.filename = runtime.byteArrayToString(stream.data.subarray(stream.pos, stream.pos + namelen), "utf8"); + this.data = null; + stream.pos += namelen + extralen + commentlen + } + function handleCentralDirectory(data, callback) { + var stream = new core.ByteArray(data), i, e; + entries = []; + for(i = 0;i < nEntries;i += 1) { + e = new ZipEntry(url, stream); + if(e.error) { + callback(e.error, zip); + return + } + entries[entries.length] = e + } + callback(null, zip) + } + function handleCentralDirectoryEnd(data, callback) { + if(data.length !== 22) { + callback("Central directory length should be 22.", zip); + return + } + var stream = new core.ByteArray(data), sig, disk, cddisk, diskNEntries, cdsSize, cdsOffset; + sig = stream.readUInt32LE(); + if(sig !== 101010256) { + callback("Central directory signature is wrong: " + sig.toString(), zip); + return + } + disk = stream.readUInt16LE(); + if(disk !== 0) { + callback("Zip files with non-zero disk numbers are not supported.", zip); + return + } + cddisk = stream.readUInt16LE(); + if(cddisk !== 0) { + callback("Zip files with non-zero disk numbers are not supported.", zip); + return + } + diskNEntries = stream.readUInt16LE(); + nEntries = stream.readUInt16LE(); + if(diskNEntries !== nEntries) { + callback("Number of entries is inconsistent.", zip); + return + } + cdsSize = stream.readUInt32LE(); + cdsOffset = stream.readUInt16LE(); + cdsOffset = filesize - 22 - cdsSize; + runtime.read(url, cdsOffset, filesize - cdsOffset, function(err, data) { + if(err || data === null) { + callback(err, zip) + }else { + handleCentralDirectory(data, callback) + } + }) + } + function load(filename, callback) { + var entry = null, e, i; + for(i = 0;i < entries.length;i += 1) { + e = entries[i]; + if(e.filename === filename) { + entry = e; + break + } + } + if(entry) { + if(entry.data) { + callback(null, entry.data) + }else { + entry.load(callback) + } + }else { + callback(filename + " not found.", null) + } + } + function loadAsString(filename, callback) { + load(filename, function(err, data) { + if(err || data === null) { + return callback(err, null) + } + var d = runtime.byteArrayToString(data, "utf8"); + callback(null, d) + }) + } + function loadContentXmlAsFragments(filename, handler) { + zip.loadAsString(filename, function(err, data) { + if(err) { + return handler.rootElementReady(err) + } + handler.rootElementReady(null, data, true) + }) + } + function loadAsDataURL(filename, mimetype, callback) { + load(filename, function(err, data) { + if(err || !data) { + return callback(err, null) + } + var p = data, chunksize = 45E3, i = 0, dataurl; + if(!mimetype) { + if(p[1] === 80 && (p[2] === 78 && p[3] === 71)) { + mimetype = "image/png" + }else { + if(p[0] === 255 && (p[1] === 216 && p[2] === 255)) { + mimetype = "image/jpeg" + }else { + if(p[0] === 71 && (p[1] === 73 && p[2] === 70)) { + mimetype = "image/gif" + }else { + mimetype = "" + } + } + } + } + dataurl = "data:" + mimetype + ";base64,"; + while(i < data.length) { + dataurl += base64.convertUTF8ArrayToBase64(p.subarray(i, Math.min(i + chunksize, p.length))); + i += chunksize + } + callback(null, dataurl) + }) + } + function loadAsDOM(filename, callback) { + zip.loadAsString(filename, function(err, xmldata) { + if(err || xmldata === null) { + callback(err, null); + return + } + var parser = new DOMParser, dom = parser.parseFromString(xmldata, "text/xml"); + callback(null, dom) + }) + } + function save(filename, data, compressed, date) { + var i, entry; + for(i = 0;i < entries.length;i += 1) { + entry = entries[i]; + if(entry.filename === filename) { + entry.set(filename, data, compressed, date); + return + } + } + entry = new ZipEntry(url); + entry.set(filename, data, compressed, date); + entries.push(entry) + } + function remove(filename) { + var i, entry; + for(i = 0;i < entries.length;i += 1) { + entry = entries[i]; + if(entry.filename === filename) { + entries.splice(i, 1); + return true + } + } + return false + } + function writeEntry(entry) { + var data = new core.ByteArrayWriter("utf8"), length = 0; + data.appendArray([80, 75, 3, 4, 20, 0, 0, 0, 0, 0]); + if(entry.data) { + length = entry.data.length + } + data.appendUInt32LE(date2DosTime(entry.date)); + data.appendUInt32LE(entry.data ? crc32(entry.data) : 0); + data.appendUInt32LE(length); + data.appendUInt32LE(length); + data.appendUInt16LE(entry.filename.length); + data.appendUInt16LE(0); + data.appendString(entry.filename); + if(entry.data) { + data.appendByteArray(entry.data) + } + return data + } + function writeCODEntry(entry, offset) { + var data = new core.ByteArrayWriter("utf8"), length = 0; + data.appendArray([80, 75, 1, 2, 20, 0, 20, 0, 0, 0, 0, 0]); + if(entry.data) { + length = entry.data.length + } + data.appendUInt32LE(date2DosTime(entry.date)); + data.appendUInt32LE(entry.data ? crc32(entry.data) : 0); + data.appendUInt32LE(length); + data.appendUInt32LE(length); + data.appendUInt16LE(entry.filename.length); + data.appendArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + data.appendUInt32LE(offset); + data.appendString(entry.filename); + return data + } + function loadAllEntries(position, callback) { + if(position === entries.length) { + callback(null); + return + } + var entry = entries[position]; + if(entry.data !== null) { + loadAllEntries(position + 1, callback); + return + } + entry.load(function(err) { + if(err) { + callback(err); + return + } + loadAllEntries(position + 1, callback) + }) + } + function createByteArray(successCallback, errorCallback) { + loadAllEntries(0, function(err) { + if(err) { + errorCallback(err); + return + } + var i, e, codoffset, codsize, data = new core.ByteArrayWriter("utf8"), offsets = [0]; + for(i = 0;i < entries.length;i += 1) { + data.appendByteArrayWriter(writeEntry(entries[i])); + offsets.push(data.getLength()) + } + codoffset = data.getLength(); + for(i = 0;i < entries.length;i += 1) { + e = entries[i]; + data.appendByteArrayWriter(writeCODEntry(e, offsets[i])) + } + codsize = data.getLength() - codoffset; + data.appendArray([80, 75, 5, 6, 0, 0, 0, 0]); + data.appendUInt16LE(entries.length); + data.appendUInt16LE(entries.length); + data.appendUInt32LE(codsize); + data.appendUInt32LE(codoffset); + data.appendArray([0, 0]); + successCallback(data.getByteArray()) + }) + } + function writeAs(newurl, callback) { + createByteArray(function(data) { + runtime.writeFile(newurl, data, callback) + }, callback) + } + function write(callback) { + writeAs(url, callback) + } + this.load = load; + this.save = save; + this.remove = remove; + this.write = write; + this.writeAs = writeAs; + this.createByteArray = createByteArray; + this.loadContentXmlAsFragments = loadContentXmlAsFragments; + this.loadAsString = loadAsString; + this.loadAsDOM = loadAsDOM; + this.loadAsDataURL = loadAsDataURL; + this.getEntries = function() { + return entries.slice() + }; + filesize = -1; + if(entriesReadCallback === null) { + entries = []; + return + } + runtime.getFileSize(url, function(size) { + filesize = size; + if(filesize < 0) { + entriesReadCallback("File '" + url + "' cannot be read.", zip) + }else { + runtime.read(url, filesize - 22, 22, function(err, data) { + if(err || (entriesReadCallback === null || data === null)) { + entriesReadCallback(err, zip) + }else { + handleCentralDirectoryEnd(data, 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() +}; +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-2013 KO GmbH + + @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 . + + 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) { + 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() + }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, 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 + + @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 . + + 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.Namespaces = {namespaceMap:{db:"urn:oasis:names:tc:opendocument:xmlns:database:1.0", dc:"http://purl.org/dc/elements/1.1/", dr3d:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", draw:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", chart:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0", fo:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", form:"urn:oasis:names:tc:opendocument:xmlns:form:1.0", meta:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0", number:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", +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", 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 map = odf.Namespaces.namespaceMap, pmap = odf.Namespaces.prefixMap, prefix; + for(prefix in map) { + if(map.hasOwnProperty(prefix)) { + pmap[map[prefix]] = prefix + } + } +})(); +odf.Namespaces.forEachPrefix = function forEachPrefix(cb) { + var ns = odf.Namespaces.namespaceMap, prefix; + for(prefix in ns) { + if(ns.hasOwnProperty(prefix)) { + cb(prefix, ns[prefix]) + } + } +}; +odf.Namespaces.lookupNamespaceURI = function lookupNamespaceURI(prefix) { + var r = null; + if(odf.Namespaces.namespaceMap.hasOwnProperty(prefix)) { + r = (odf.Namespaces.namespaceMap[prefix]) + } + return r +}; +odf.Namespaces.lookupPrefix = function lookupPrefix(namespaceURI) { + var map = odf.Namespaces.prefixMap; + return map.hasOwnProperty(namespaceURI) ? map[namespaceURI] : null +}; +odf.Namespaces.lookupNamespaceURI.lookupNamespaceURI = odf.Namespaces.lookupNamespaceURI; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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; + 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") + }else { + r = isCharacterFrame(e) + } + } + return r + } + this.isCharacterElement = isCharacterElement; + 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(isCharacterElement(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(isCharacterElement(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(isCharacterElement(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(isCharacterElement(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(isCharacterElement(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(isCharacterElement(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(isCharacterElement(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 + + @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 . + + 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() { +}; +xmldom.XPathIterator.prototype.reset = function() { +}; +xmldom.XPathAtom; +function createXPathSingleton() { + var createXPathPathIterator, parsePredicates; + function isSmallestPositive(a, b, c) { + return a !== -1 && ((a < b || b === -1) && (a < c || c === -1)) + } + function parseXPathStep(xpath, pos, end, steps) { + var location = "", predicates = [], brapos = xpath.indexOf("[", pos), slapos = xpath.indexOf("/", pos), eqpos = xpath.indexOf("=", pos); + if(isSmallestPositive(slapos, brapos, eqpos)) { + location = xpath.substring(pos, slapos); + pos = slapos + 1 + }else { + if(isSmallestPositive(brapos, slapos, eqpos)) { + location = xpath.substring(pos, brapos); + pos = parsePredicates(xpath, brapos, predicates) + }else { + if(isSmallestPositive(eqpos, slapos, brapos)) { + location = xpath.substring(pos, eqpos); + pos = eqpos + }else { + location = xpath.substring(pos, end); + pos = end + } + } + } + steps.push({location:location, predicates:predicates}); + return pos + } + function parseXPath(xpath) { + var steps = [], p = 0, end = xpath.length, value; + while(p < end) { + p = parseXPathStep(xpath, p, end, steps); + if(p < end && xpath[p] === "=") { + value = xpath.substring(p + 1, end); + if(value.length > 2 && (value[0] === "'" || value[0] === '"')) { + value = value.slice(1, value.length - 1) + }else { + try { + value = parseInt(value, 10) + }catch(ignore) { + } + } + p = end + } + } + return{steps:steps, value:value} + } + parsePredicates = function parsePredicates(xpath, start, predicates) { + var pos = start, l = xpath.length, depth = 0; + while(pos < l) { + if(xpath[pos] === "]") { + depth -= 1; + if(depth <= 0) { + predicates.push(parseXPath(xpath.substring(start, pos))) + } + }else { + if(xpath[pos] === "[") { + if(depth <= 0) { + start = pos + 1 + } + depth += 1 + } + } + pos += 1 + } + return pos + }; + function XPathNodeIterator() { + var node = null, done = false; + this.setNode = function setNode(n) { + node = n + }; + this.reset = function() { + done = false + }; + this.next = function next() { + var val = done ? null : node; + done = true; + return val + } + } + function AttributeIterator(it, namespace, localName) { + this.reset = function reset() { + it.reset() + }; + this.next = function next() { + var node = it.next(); + while(node) { + if(node.nodeType === Node.ELEMENT_NODE) { + node = (node).getAttributeNodeNS(namespace, localName) + } + if(node) { + return node + } + node = it.next() + } + return node + } + } + function AllChildElementIterator(it, recurse) { + var root = it.next(), node = null; + this.reset = function reset() { + it.reset(); + root = it.next(); + node = null + }; + this.next = function next() { + while(root) { + if(node) { + if(recurse && node.firstChild) { + node = node.firstChild + }else { + while(!node.nextSibling && node !== root) { + node = node.parentNode + } + if(node === root) { + root = it.next() + }else { + node = node.nextSibling + } + } + }else { + do { + node = root.firstChild; + if(!node) { + root = it.next() + } + }while(root && !node) + } + if(node && node.nodeType === Node.ELEMENT_NODE) { + return node + } + } + return null + } + } + function ConditionIterator(it, condition) { + this.reset = function reset() { + it.reset() + }; + this.next = function next() { + var n = it.next(); + while(n && !condition(n)) { + n = it.next() + } + return n + } + } + function createNodenameFilter(it, name, namespaceResolver) { + var s = name.split(":", 2), namespace = namespaceResolver(s[0]), localName = s[1]; + return new ConditionIterator(it, function(node) { + return node.localName === localName && node.namespaceURI === namespace + }) + } + function createPredicateFilteredIterator(it, p, namespaceResolver) { + var nit = new XPathNodeIterator, pit = createXPathPathIterator(nit, p, namespaceResolver), value = p.value; + if(value === undefined) { + return new ConditionIterator(it, function(node) { + nit.setNode(node); + pit.reset(); + return pit.next() !== null + }) + } + return new ConditionIterator(it, function(node) { + nit.setNode(node); + pit.reset(); + var n = pit.next(); + return n ? n.nodeValue === value : false + }) + } + function item(p, i) { + return p[i] + } + createXPathPathIterator = function createXPathPathIterator(it, xpath, namespaceResolver) { + var i, j, step, location, s, p, ns; + for(i = 0;i < xpath.steps.length;i += 1) { + step = xpath.steps[i]; + location = step.location; + if(location === "") { + it = new AllChildElementIterator(it, false) + }else { + if(location[0] === "@") { + s = location.substr(1).split(":", 2); + ns = namespaceResolver(s[0]); + if(!ns) { + throw"No namespace associated with the prefix " + s[0]; + } + it = new AttributeIterator(it, ns, s[1]) + }else { + if(location !== ".") { + it = new AllChildElementIterator(it, false); + if(location.indexOf(":") !== -1) { + it = createNodenameFilter(it, location, namespaceResolver) + } + } + } + } + for(j = 0;j < step.predicates.length;j += 1) { + p = item(step.predicates, j); + it = createPredicateFilteredIterator(it, p, namespaceResolver) + } + } + return it + }; + function fallback(node, xpath, namespaceResolver) { + var it = new XPathNodeIterator, i, nodelist, parsedXPath; + it.setNode(node); + parsedXPath = parseXPath(xpath); + it = createXPathPathIterator(it, parsedXPath, namespaceResolver); + nodelist = []; + i = it.next(); + while(i) { + nodelist.push(i); + i = it.next() + } + return nodelist + } + function getODFElementsWithXPath(node, xpath, namespaceResolver) { + var doc = node.ownerDocument, nodes, elements = [], n = null; + if(!doc || typeof doc.evaluate !== "function") { + elements = fallback(node, xpath, namespaceResolver) + }else { + nodes = doc.evaluate(xpath, node, namespaceResolver, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); + n = nodes.iterateNext(); + while(n !== null) { + if(n.nodeType === Node.ELEMENT_NODE) { + elements.push(n) + } + n = nodes.iterateNext() + } + } + return elements + } + 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 + + @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 . + + 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 + + @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 . + + 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.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 + + @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 . + @licend + + @source: http://www.webodf.org/ + @source: https://github.com/kogmbh/WebODF/ +*/ +runtime.loadClass("odf.Namespaces"); +runtime.loadClass("core.DomUtils"); +odf.MetadataManager = function MetadataManager(metaElement) { + var domUtils = new core.DomUtils, metadata = {}; + function setMetadata(setProperties, removedProperties) { + if(setProperties) { + Object.keys(setProperties).forEach(function(key) { + metadata[key] = setProperties[key] + }); + domUtils.mapKeyValObjOntoNode(metaElement, setProperties, odf.Namespaces.lookupNamespaceURI) + } + if(removedProperties) { + removedProperties.forEach(function(name) { + delete metadata[name] + }); + domUtils.removeKeyElementsFromNode(metaElement, removedProperties, odf.Namespaces.lookupNamespaceURI) + } + } + this.setMetadata = setMetadata; + this.incrementEditingCycles = function() { + var cycles = parseInt(metadata["meta:editing-cycles"] || 0, 10) + 1; + setMetadata({"meta:editing-cycles":cycles}, null) + }; + function init() { + metadata = domUtils.getKeyValRepresentationOfNode(metaElement, odf.Namespaces.lookupPrefix) + } + init() +}; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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 + + @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 . + + 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 + + @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 . + + 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:", + "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:"}, elementstyles = {"text":[{ens:stylens, en:"tab-stop", ans:stylens, a:"leader-text-style"}, {ens:stylens, en:"drop-cap", ans:stylens, a:"style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"citation-body-style-name"}, {ens:textns, en:"notes-configuration", + ans:textns, a:"citation-style-name"}, {ens:textns, en:"a", ans:textns, a:"style-name"}, {ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"linenumbering-configuration", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-number", ans:textns, a:"style-name"}, {ens:textns, en:"ruby-text", ans:textns, a:"style-name"}, {ens:textns, en:"span", ans:textns, a:"style-name"}, {ens:textns, en:"a", ans:textns, a:"visited-style-name"}, {ens:stylens, en:"text-properties", + ans:stylens, a:"text-line-through-text-style"}, {ens:textns, en:"alphabetical-index-source", ans:textns, a:"main-entry-style-name"}, {ens:textns, en:"index-entry-bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-chapter", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-end", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-start", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-page-number", ans:textns, a:"style-name"}, {ens:textns, + en:"index-entry-span", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-tab-stop", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-text", ans:textns, a:"style-name"}, {ens:textns, en:"index-title-template", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-bullet", ans:textns, a:"style-name"}, {ens:textns, en:"outline-level-style", ans:textns, a:"style-name"}], "paragraph":[{ens:drawns, en:"caption", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"circle", ans:drawns, + a:"text-style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"control", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"ellipse", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"line", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"path", ans:drawns, a:"text-style-name"}, + {ens:drawns, en:"polygon", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"rect", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"text-style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"text-style-name"}, {ens:formns, en:"column", ans:formns, a:"text-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"next-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"paragraph-style-name"}, + {ens:tablens, en:"even-columns", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"even-rows", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"paragraph-style-name"}, + {ens:tablens, en:"odd-rows", ans:tablens, a:"paragraph-style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"default-style-name"}, {ens:textns, en:"alphabetical-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"h", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"index-source-style", ans:textns, a:"style-name"}, + {ens:textns, en:"object-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"p", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"user-index-entry-template", ans:textns, a:"style-name"}, {ens:stylens, en:"page-layout-properties", ans:stylens, a:"register-truth-ref-style-name"}], + "chart":[{ens:chartns, en:"axis", ans:chartns, a:"style-name"}, {ens:chartns, en:"chart", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-label", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-point", ans:chartns, a:"style-name"}, {ens:chartns, en:"equation", ans:chartns, a:"style-name"}, {ens:chartns, en:"error-indicator", ans:chartns, a:"style-name"}, {ens:chartns, en:"floor", ans:chartns, a:"style-name"}, {ens:chartns, en:"footer", ans:chartns, a:"style-name"}, {ens:chartns, en:"grid", + ans:chartns, a:"style-name"}, {ens:chartns, en:"legend", ans:chartns, a:"style-name"}, {ens:chartns, en:"mean-value", ans:chartns, a:"style-name"}, {ens:chartns, en:"plot-area", ans:chartns, a:"style-name"}, {ens:chartns, en:"regression-curve", ans:chartns, a:"style-name"}, {ens:chartns, en:"series", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-gain-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-loss-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-range-line", + ans:chartns, a:"style-name"}, {ens:chartns, en:"subtitle", ans:chartns, a:"style-name"}, {ens:chartns, en:"title", ans:chartns, a:"style-name"}, {ens:chartns, en:"wall", ans:chartns, a:"style-name"}], "section":[{ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index", ans:textns, a:"style-name"}, {ens:textns, en:"index-title", ans:textns, a:"style-name"}, {ens:textns, en:"object-index", + ans:textns, a:"style-name"}, {ens:textns, en:"section", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content", ans:textns, a:"style-name"}, {ens:textns, en:"table-index", ans:textns, a:"style-name"}, {ens:textns, en:"user-index", ans:textns, a:"style-name"}], "ruby":[{ens:textns, en:"ruby", ans:textns, a:"style-name"}], "table":[{ens:dbns, en:"query", ans:dbns, a:"style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"style-name"}, {ens:tablens, en:"background", ans:tablens, + a:"style-name"}, {ens:tablens, en:"table", ans:tablens, a:"style-name"}], "table-column":[{ens:dbns, en:"column", ans:dbns, a:"style-name"}, {ens:tablens, en:"table-column", ans:tablens, a:"style-name"}], "table-row":[{ens:dbns, en:"query", ans:dbns, a:"default-row-style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"default-row-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"style-name"}], "table-cell":[{ens:dbns, en:"column", ans:dbns, a:"default-cell-style-name"}, {ens:tablens, + en:"table-column", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-rows", ans:tablens, a:"style-name"}, + {ens:tablens, en:"first-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-rows", ans:tablens, a:"style-name"}, {ens:tablens, en:"table-cell", ans:tablens, a:"style-name"}], "graphic":[{ens:dr3dns, en:"cube", ans:drawns, a:"style-name"}, {ens:dr3dns, + en:"extrude", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:drawns, a:"style-name"}, {ens:drawns, en:"caption", ans:drawns, a:"style-name"}, {ens:drawns, en:"circle", ans:drawns, a:"style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"style-name"}, {ens:drawns, en:"control", ans:drawns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"style-name"}, {ens:drawns, + en:"ellipse", ans:drawns, a:"style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"style-name"}, {ens:drawns, en:"g", ans:drawns, a:"style-name"}, {ens:drawns, en:"line", ans:drawns, a:"style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:drawns, a:"style-name"}, {ens:drawns, en:"path", ans:drawns, a:"style-name"}, {ens:drawns, en:"polygon", ans:drawns, a:"style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"style-name"}, {ens:drawns, en:"rect", + ans:drawns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"style-name"}], "presentation":[{ens:dr3dns, en:"cube", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"extrude", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:presentationns, a:"style-name"}, {ens:drawns, en:"caption", + ans:presentationns, a:"style-name"}, {ens:drawns, en:"circle", ans:presentationns, a:"style-name"}, {ens:drawns, en:"connector", ans:presentationns, a:"style-name"}, {ens:drawns, en:"control", ans:presentationns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:presentationns, a:"style-name"}, {ens:drawns, en:"ellipse", ans:presentationns, a:"style-name"}, {ens:drawns, en:"frame", ans:presentationns, a:"style-name"}, {ens:drawns, en:"g", ans:presentationns, a:"style-name"}, {ens:drawns, en:"line", + ans:presentationns, a:"style-name"}, {ens:drawns, en:"measure", ans:presentationns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:presentationns, a:"style-name"}, {ens:drawns, en:"path", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polygon", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polyline", ans:presentationns, a:"style-name"}, {ens:drawns, en:"rect", ans:presentationns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:presentationns, a:"style-name"}, {ens:officens, + en:"annotation", ans:presentationns, a:"style-name"}], "drawing-page":[{ens:drawns, en:"page", ans:drawns, a:"style-name"}, {ens:presentationns, en:"notes", ans:drawns, a:"style-name"}, {ens:stylens, en:"handout-master", ans:drawns, a:"style-name"}, {ens:stylens, en:"master-page", ans:drawns, a:"style-name"}], "list-style":[{ens:textns, en:"list", ans:textns, a:"style-name"}, {ens:textns, en:"numbered-paragraph", ans:textns, a:"style-name"}, {ens:textns, en:"list-item", ans:textns, a:"style-override"}, + {ens:stylens, en:"style", ans:stylens, a:"list-style-name"}], "data":[{ens:stylens, en:"style", ans:stylens, a:"data-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"percentage-data-style-name"}, {ens:presentationns, en:"date-time-decl", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"database-display", ans:stylens, a:"data-style-name"}, {ens:textns, + en:"date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"editing-duration", ans:stylens, a:"data-style-name"}, {ens:textns, en:"expression", ans:stylens, a:"data-style-name"}, {ens:textns, en:"meta-field", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-time", ans:stylens, + a:"data-style-name"}, {ens:textns, en:"table-formula", ans:stylens, a:"data-style-name"}, {ens:textns, en:"time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-defined", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-input", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-input", ans:stylens, a:"data-style-name"}, {ens:textns, + en:"variable-set", ans:stylens, a:"data-style-name"}], "page-layout":[{ens:presentationns, en:"notes", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"handout-master", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"master-page", ans:stylens, a:"page-layout-name"}]}, elements, xpath = xmldom.XPath; + function hasDerivedStyles(odfbody, nsResolver, styleElement) { + var nodes, xp, styleName = styleElement.getAttributeNS(stylens, "name"), styleFamily = styleElement.getAttributeNS(stylens, "family"); + xp = "//style:*[@style:parent-style-name='" + styleName + "'][@style:family='" + styleFamily + "']"; + nodes = xpath.getODFElementsWithXPath(odfbody, xp, nsResolver); + if(nodes.length) { + return true + } + return false + } + function prefixUsedStyleNames(element, prefix) { + var i, stylename, a, e, ns, elname, elns, localName, length = 0; + elname = elements[element.localName]; + if(elname) { + elns = elname[element.namespaceURI]; + if(elns) { + length = elns.length + } + } + for(i = 0;i < length;i += 1) { + a = (elns[i]); + ns = a.ns; + localName = a.localname; + stylename = element.getAttributeNS(ns, localName); + if(stylename) { + element.setAttributeNS(ns, nsprefixes[ns] + localName, prefix + stylename) + } + } + e = element.firstElementChild; + while(e) { + prefixUsedStyleNames(e, prefix); + e = e.nextElementSibling + } + } + function prefixStyleName(styleElement, prefix) { + var stylename = styleElement.getAttributeNS(drawns, "name"), ns; + if(stylename) { + ns = drawns + }else { + stylename = styleElement.getAttributeNS(stylens, "name"); + if(stylename) { + ns = stylens + } + } + if(ns) { + styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", prefix + stylename) + } + } + function prefixStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) { + var s; + if(styleElementsRoot) { + s = styleElementsRoot.firstChild; + while(s) { + if(s.nodeType === Node.ELEMENT_NODE) { + prefixStyleName((s), prefix) + } + s = s.nextSibling + } + prefixUsedStyleNames(styleElementsRoot, prefix); + if(styleUsingElementsRoot) { + prefixUsedStyleNames(styleUsingElementsRoot, prefix) + } + } + } + function removeRegExpFromUsedStyleNames(element, regExp) { + var i, stylename, e, elname, elns, a, ns, localName, length = 0; + elname = elements[element.localName]; + if(elname) { + elns = elname[element.namespaceURI]; + if(elns) { + length = elns.length + } + } + for(i = 0;i < length;i += 1) { + a = (elns[i]); + ns = a.ns; + localName = a.localname; + stylename = element.getAttributeNS(ns, localName); + if(stylename) { + stylename = stylename.replace(regExp, ""); + element.setAttributeNS(ns, nsprefixes[ns] + localName, stylename) + } + } + e = element.firstElementChild; + while(e) { + removeRegExpFromUsedStyleNames(e, regExp); + e = e.nextElementSibling + } + } + function removeRegExpFromStyleName(styleElement, regExp) { + var stylename = styleElement.getAttributeNS(drawns, "name"), ns; + if(stylename) { + ns = drawns + }else { + stylename = styleElement.getAttributeNS(stylens, "name"); + if(stylename) { + ns = stylens + } + } + if(ns) { + stylename = stylename.replace(regExp, ""); + styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", stylename) + } + } + function removePrefixFromStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) { + var s, regExp = new RegExp("^" + prefix); + if(styleElementsRoot) { + s = styleElementsRoot.firstChild; + while(s) { + if(s.nodeType === Node.ELEMENT_NODE) { + removeRegExpFromStyleName((s), regExp) + } + s = s.nextSibling + } + removeRegExpFromUsedStyleNames(styleElementsRoot, regExp); + if(styleUsingElementsRoot) { + removeRegExpFromUsedStyleNames(styleUsingElementsRoot, regExp) + } + } + } + function determineStylesForNode(element, usedStyles) { + var i, stylename, elname, elns, a, ns, localName, keyname, length = 0, map; + elname = elements[element.localName]; + if(elname) { + elns = elname[element.namespaceURI]; + if(elns) { + length = elns.length + } + } + for(i = 0;i < length;i += 1) { + a = (elns[i]); + ns = a.ns; + localName = a.localname; + stylename = element.getAttributeNS(ns, localName); + if(stylename) { + usedStyles = usedStyles || {}; + keyname = a.keyname; + if(usedStyles.hasOwnProperty(keyname)) { + usedStyles[keyname][stylename] = 1 + }else { + map = {}; + map[stylename] = 1; + usedStyles[keyname] = map + } + } + } + return usedStyles + } + function determineUsedStyles(styleUsingElementsRoot, usedStyles) { + var i, e; + determineStylesForNode(styleUsingElementsRoot, usedStyles); + i = styleUsingElementsRoot.firstChild; + while(i) { + if(i.nodeType === Node.ELEMENT_NODE) { + e = (i); + determineUsedStyles(e, usedStyles) + } + i = i.nextSibling + } + } + function StyleDefinition(key, name, family) { + this.key = key; + this.name = name; + this.family = family; + this.requires = {} + } + function getStyleDefinition(stylename, stylefamily, knownStyles) { + var styleKey = stylename + '"' + stylefamily, styleDefinition = knownStyles[styleKey]; + if(!styleDefinition) { + styleDefinition = knownStyles[styleKey] = new StyleDefinition(styleKey, stylename, stylefamily) + } + return styleDefinition + } + function determineDependentStyles(element, styleScope, knownStyles) { + var i, stylename, elname, elns, a, ns, localName, e, referencedStyleFamily, referencedStyleDef, length = 0, newScopeName = element.getAttributeNS(stylens, "name"), newScopeFamily = element.getAttributeNS(stylens, "family"); + if(newScopeName && newScopeFamily) { + styleScope = getStyleDefinition(newScopeName, newScopeFamily, knownStyles) + } + if(styleScope) { + elname = elements[element.localName]; + if(elname) { + elns = elname[element.namespaceURI]; + if(elns) { + length = elns.length + } + } + for(i = 0;i < length;i += 1) { + a = (elns[i]); + ns = a.ns; + localName = a.localname; + stylename = element.getAttributeNS(ns, localName); + if(stylename) { + referencedStyleFamily = a.keyname; + referencedStyleDef = getStyleDefinition(stylename, referencedStyleFamily, knownStyles); + styleScope.requires[referencedStyleDef.key] = referencedStyleDef + } + } + } + e = element.firstElementChild; + while(e) { + determineDependentStyles(e, styleScope, knownStyles); + e = e.nextElementSibling + } + return knownStyles + } + function inverse() { + var i, l, keyname, list, item, e = {}, map, array, en, ens; + for(keyname in elementstyles) { + if(elementstyles.hasOwnProperty(keyname)) { + list = elementstyles[keyname]; + l = list.length; + for(i = 0;i < l;i += 1) { + item = list[i]; + en = item.en; + ens = item.ens; + if(e.hasOwnProperty(en)) { + map = e[en] + }else { + e[en] = map = {} + } + if(map.hasOwnProperty(ens)) { + array = map[ens] + }else { + map[ens] = array = [] + } + array.push({ns:item.ans, localname:item.a, keyname:keyname}) + } + } + } + return e + } + function mergeRequiredStyles(styleDependency, usedStyles) { + var family = usedStyles[styleDependency.family]; + if(!family) { + family = usedStyles[styleDependency.family] = {} + } + family[styleDependency.name] = 1; + Object.keys((styleDependency.requires)).forEach(function(requiredStyleKey) { + mergeRequiredStyles((styleDependency.requires[requiredStyleKey]), usedStyles) + }) + } + function mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles) { + var automaticStyles = determineDependentStyles(automaticStylesRoot, null, {}); + Object.keys(automaticStyles).forEach(function(styleKey) { + var automaticStyleDefinition = automaticStyles[styleKey], usedFamily = usedStyles[automaticStyleDefinition.family]; + if(usedFamily && usedFamily.hasOwnProperty(automaticStyleDefinition.name)) { + mergeRequiredStyles(automaticStyleDefinition, usedStyles) + } + }) + } + function collectUsedFontFaces(usedFontFaceDeclMap, styleElement) { + var localNames = ["font-name", "font-name-asian", "font-name-complex"], e, currentElement; + function collectByAttribute(localName) { + var fontFaceName = currentElement.getAttributeNS(stylens, localName); + if(fontFaceName) { + usedFontFaceDeclMap[fontFaceName] = true + } + } + e = styleElement && styleElement.firstElementChild; + while(e) { + currentElement = e; + localNames.forEach(collectByAttribute); + collectUsedFontFaces(usedFontFaceDeclMap, currentElement); + e = e.nextElementSibling + } + } + this.collectUsedFontFaces = collectUsedFontFaces; + function changeFontFaceNames(styleElement, fontFaceNameChangeMap) { + var localNames = ["font-name", "font-name-asian", "font-name-complex"], e, currentElement; + function changeFontFaceNameByAttribute(localName) { + var fontFaceName = currentElement.getAttributeNS(stylens, localName); + if(fontFaceName && fontFaceNameChangeMap.hasOwnProperty(fontFaceName)) { + currentElement.setAttributeNS(stylens, "style:" + localName, fontFaceNameChangeMap[fontFaceName]) + } + } + e = styleElement && styleElement.firstElementChild; + while(e) { + currentElement = e; + localNames.forEach(changeFontFaceNameByAttribute); + changeFontFaceNames(currentElement, fontFaceNameChangeMap); + e = e.nextElementSibling + } + } + this.changeFontFaceNames = changeFontFaceNames; + this.UsedStyleList = function(styleUsingElementsRoot, automaticStylesRoot) { + var usedStyles = {}; + this.uses = function(element) { + var localName = element.localName, name = element.getAttributeNS(drawns, "name") || element.getAttributeNS(stylens, "name"), keyName, map; + if(localName === "style") { + keyName = element.getAttributeNS(stylens, "family") + }else { + if(element.namespaceURI === numberns) { + keyName = "data" + }else { + keyName = localName + } + } + map = usedStyles[keyName]; + return map ? map[name] > 0 : false + }; + determineUsedStyles(styleUsingElementsRoot, usedStyles); + if(automaticStylesRoot) { + mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles) + } + }; + this.hasDerivedStyles = hasDerivedStyles; + this.prefixStyleNames = prefixStyleNames; + this.removePrefixFromStyleNames = removePrefixFromStyleNames; + this.determineStylesForNode = determineStylesForNode; + elements = inverse() +}; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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 + + @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 . + + 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) { + 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() { + }; + F.prototype = o; + return new F + } +} +xmldom.LSSerializer = function LSSerializer() { + var self = this; + function Namespaces(nsmap) { + function invertMap(map) { + var m = {}, i; + for(i in map) { + if(map.hasOwnProperty(i)) { + m[map[i]] = i + } + } + return m + } + var current = nsmap || {}, currentrev = invertMap(nsmap), levels = [current], levelsrev = [currentrev], level = 0; + this.push = function() { + level += 1; + current = levels[level] = Object.create(current); + currentrev = levelsrev[level] = Object.create(currentrev) + }; + this.pop = function() { + levels.pop(); + levelsrev.pop(); + level -= 1; + current = levels[level]; + currentrev = levelsrev[level] + }; + this.getLocalNamespaceDefinitions = function() { + return currentrev + }; + this.getQName = function(node) { + var ns = node.namespaceURI, i = 0, p; + if(!ns) { + return node.localName + } + p = currentrev[ns]; + if(p) { + return p + ":" + node.localName + } + do { + if(p || !node.prefix) { + p = "ns" + i; + i += 1 + }else { + p = node.prefix + } + if(current[p] === ns) { + break + } + if(!current[p]) { + current[p] = ns; + currentrev[ns] = p; + break + } + p = null + }while(p === null); + return p + ":" + node.localName + } + } + function escapeContent(value) { + return value.replace(/&/g, "&").replace(//g, ">").replace(/'/g, "'").replace(/"/g, """) + } + function serializeAttribute(qname, attr) { + var escapedValue = typeof attr.value === "string" ? escapeContent(attr.value) : attr.value, s = qname + '="' + escapedValue + '"'; + return s + } + function startElement(ns, qname, element) { + var s = "", atts = (element.attributes), length, i, attr, attstr = "", accept, prefix, nsmap; + s += "<" + qname; + length = atts.length; + for(i = 0;i < length;i += 1) { + attr = (atts.item(i)); + if(attr.namespaceURI !== "http://www.w3.org/2000/xmlns/") { + accept = self.filter ? self.filter.acceptNode(attr) : NodeFilter.FILTER_ACCEPT; + if(accept === NodeFilter.FILTER_ACCEPT) { + attstr += " " + serializeAttribute(ns.getQName(attr), attr) + } + } + } + nsmap = ns.getLocalNamespaceDefinitions(); + for(i in nsmap) { + if(nsmap.hasOwnProperty(i)) { + prefix = nsmap[i]; + if(!prefix) { + s += ' xmlns="' + i + '"' + }else { + if(prefix !== "xmlns") { + s += " xmlns:" + nsmap[i] + '="' + i + '"' + } + } + } + } + s += attstr + ">"; + return s + } + function serializeNode(ns, node) { + var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, child, qname; + if(accept === NodeFilter.FILTER_ACCEPT && node.nodeType === Node.ELEMENT_NODE) { + ns.push(); + qname = ns.getQName(node); + s += startElement(ns, qname, node) + } + if(accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) { + child = node.firstChild; + while(child) { + s += serializeNode(ns, child); + child = child.nextSibling + } + if(node.nodeValue) { + s += escapeContent(node.nodeValue) + } + } + if(qname) { + s += ""; + ns.pop() + } + return s + } + this.filter = null; + this.writeToString = function(node, nsmap) { + if(!node) { + return"" + } + var ns = new Namespaces(nsmap); + return serializeNode(ns, node) + } +}; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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 + + @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 . + + 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.Base64"); +runtime.loadClass("core.Zip"); +runtime.loadClass("xmldom.LSSerializer"); +runtime.loadClass("odf.StyleInfo"); +runtime.loadClass("odf.Namespaces"); +runtime.loadClass("odf.OdfNodeFilter"); +runtime.loadClass("odf.MetadataManager"); +(function() { + var styleInfo = new odf.StyleInfo, metadataManager, 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"; + function getDirectChild(node, ns, name) { + node = node ? node.firstChild : null; + while(node) { + if(node.localName === name && node.namespaceURI === ns) { + return(node) + } + node = node.nextSibling + } + return null + } + function getNodePosition(child) { + var i, l = nodeorder.length; + for(i = 0;i < l;i += 1) { + if(child.namespaceURI === officens && child.localName === nodeorder[i]) { + return i + } + } + return-1 + } + function OdfStylesFilter(styleUsingElementsRoot, automaticStyles) { + var usedStyleList = new styleInfo.UsedStyleList(styleUsingElementsRoot, automaticStyles), odfNodeFilter = new odf.OdfNodeFilter; + this.acceptNode = function(node) { + var result = odfNodeFilter.acceptNode(node); + if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode === automaticStyles && node.nodeType === Node.ELEMENT_NODE)) { + if(usedStyleList.uses((node))) { + result = NodeFilter.FILTER_ACCEPT + }else { + result = NodeFilter.FILTER_REJECT + } + } + return result + } + } + function OdfContentFilter(styleUsingElementsRoot, automaticStyles) { + var odfStylesFilter = new OdfStylesFilter(styleUsingElementsRoot, automaticStyles); + this.acceptNode = function(node) { + var result = odfStylesFilter.acceptNode(node); + if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode && (node.parentNode.namespaceURI === odf.Namespaces.textns && (node.parentNode.localName === "s" || node.parentNode.localName === "tab")))) { + result = NodeFilter.FILTER_REJECT + } + return result + } + } + function setChild(node, child) { + if(!child) { + return + } + var childpos = getNodePosition(child), pos, c = node.firstChild; + if(childpos === -1) { + return + } + while(c) { + pos = getNodePosition(c); + if(pos !== -1 && pos > childpos) { + break + } + c = c.nextSibling + } + node.insertBefore(child, c) + } + odf.ODFElement = function ODFElement() { + }; + odf.ODFDocumentElement = function ODFDocumentElement() { + }; + odf.ODFDocumentElement.prototype = new odf.ODFElement; + odf.ODFDocumentElement.prototype.constructor = odf.ODFDocumentElement; + odf.ODFDocumentElement.prototype.automaticStyles; + odf.ODFDocumentElement.prototype.body; + odf.ODFDocumentElement.prototype.fontFaceDecls = null; + odf.ODFDocumentElement.prototype.manifest = null; + odf.ODFDocumentElement.prototype.masterStyles; + odf.ODFDocumentElement.prototype.meta; + odf.ODFDocumentElement.prototype.settings = null; + odf.ODFDocumentElement.prototype.styles; + odf.ODFDocumentElement.namespaceURI = officens; + odf.ODFDocumentElement.localName = "document"; + odf.OdfPart = function OdfPart(name, mimetype, container, zip) { + var self = this; + this.size = 0; + this.type = null; + this.name = name; + this.container = container; + this.url = null; + this.mimetype = mimetype; + this.document = null; + this.onstatereadychange = null; + this.onchange; + this.EMPTY = 0; + this.LOADING = 1; + this.DONE = 2; + this.state = this.EMPTY; + this.data = ""; + this.load = function() { + if(zip === null) { + return + } + this.mimetype = mimetype; + zip.loadAsDataURL(name, mimetype, function(err, url) { + if(err) { + runtime.log(err) + } + self.url = url; + if(self.onchange) { + self.onchange(self) + } + if(self.onstatereadychange) { + self.onstatereadychange(self) + } + }) + } + }; + odf.OdfPart.prototype.load = function() { + }; + odf.OdfPart.prototype.getUrl = function() { + if(this.data) { + return"data:;base64," + base64.toBase64(this.data) + } + return null + }; + odf.OdfContainer = function OdfContainer(url, onstatereadychange) { + var self = this, zip, partMimetypes = {}, contentElement; + this.onstatereadychange = onstatereadychange; + this.onchange = null; + this.state = null; + this.rootElement; + function removeProcessingInstructions(element) { + var n = element.firstChild, next, e; + while(n) { + next = n.nextSibling; + if(n.nodeType === Node.ELEMENT_NODE) { + e = (n); + removeProcessingInstructions(e) + }else { + if(n.nodeType === Node.PROCESSING_INSTRUCTION_NODE) { + element.removeChild(n) + } + } + n = next + } + } + function setAutomaticStylesScope(stylesRootElement, scope) { + var n = stylesRootElement && stylesRootElement.firstChild; + while(n) { + if(n.nodeType === Node.ELEMENT_NODE) { + (n).setAttributeNS(webodfns, "scope", scope) + } + n = n.nextSibling + } + } + function unusedKey(key, map1, map2) { + var i = 0, postFixedKey; + key = key.replace(/\d+$/, ""); + postFixedKey = key; + while(map1.hasOwnProperty(postFixedKey) || map2.hasOwnProperty(postFixedKey)) { + i += 1; + postFixedKey = key + i + } + return postFixedKey + } + function mapByFontFaceName(fontFaceDecls) { + var fn, result = {}, fontname; + fn = fontFaceDecls.firstChild; + while(fn) { + if(fn.nodeType === Node.ELEMENT_NODE && (fn.namespaceURI === stylens && fn.localName === "font-face")) { + fontname = (fn).getAttributeNS(stylens, "name"); + result[fontname] = fn + } + fn = fn.nextSibling + } + return result + } + function mergeFontFaceDecls(targetFontFaceDeclsRootElement, sourceFontFaceDeclsRootElement) { + var e, s, fontFaceName, newFontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap, fontFaceNameChangeMap = {}; + targetFontFaceDeclsMap = mapByFontFaceName(targetFontFaceDeclsRootElement); + sourceFontFaceDeclsMap = mapByFontFaceName(sourceFontFaceDeclsRootElement); + e = sourceFontFaceDeclsRootElement.firstElementChild; + while(e) { + s = e.nextElementSibling; + if(e.namespaceURI === stylens && e.localName === "font-face") { + fontFaceName = e.getAttributeNS(stylens, "name"); + if(targetFontFaceDeclsMap.hasOwnProperty(fontFaceName)) { + if(!e.isEqualNode(targetFontFaceDeclsMap[fontFaceName])) { + newFontFaceName = unusedKey(fontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap); + e.setAttributeNS(stylens, "style:name", newFontFaceName); + targetFontFaceDeclsRootElement.appendChild(e); + targetFontFaceDeclsMap[newFontFaceName] = e; + delete sourceFontFaceDeclsMap[fontFaceName]; + fontFaceNameChangeMap[fontFaceName] = newFontFaceName + } + }else { + targetFontFaceDeclsRootElement.appendChild(e); + targetFontFaceDeclsMap[fontFaceName] = e; + delete sourceFontFaceDeclsMap[fontFaceName] + } + } + e = s + } + return fontFaceNameChangeMap + } + function cloneStylesInScope(stylesRootElement, scope) { + var copy = null, e, s, scopeAttrValue; + if(stylesRootElement) { + copy = stylesRootElement.cloneNode(true); + e = copy.firstElementChild; + while(e) { + s = e.nextElementSibling; + scopeAttrValue = e.getAttributeNS(webodfns, "scope"); + if(scopeAttrValue && scopeAttrValue !== scope) { + copy.removeChild(e) + } + e = s + } + } + return copy + } + function cloneFontFaceDeclsUsedInStyles(fontFaceDeclsRootElement, stylesRootElementList) { + var e, nextSibling, fontFaceName, copy = null, usedFontFaceDeclMap = {}; + if(fontFaceDeclsRootElement) { + stylesRootElementList.forEach(function(stylesRootElement) { + styleInfo.collectUsedFontFaces(usedFontFaceDeclMap, stylesRootElement) + }); + copy = fontFaceDeclsRootElement.cloneNode(true); + e = copy.firstElementChild; + while(e) { + nextSibling = e.nextElementSibling; + fontFaceName = e.getAttributeNS(stylens, "name"); + if(!usedFontFaceDeclMap[fontFaceName]) { + copy.removeChild(e) + } + e = nextSibling + } + } + return copy + } + function initializeMetadataManager(metaRootElement) { + metadataManager = new odf.MetadataManager(metaRootElement) + } + function importRootNode(xmldoc) { + var doc = self.rootElement.ownerDocument, node; + if(xmldoc) { + removeProcessingInstructions(xmldoc.documentElement); + try { + node = doc.importNode(xmldoc.documentElement, true) + }catch(ignore) { + } + } + return node + } + function setState(state) { + self.state = state; + if(self.onchange) { + self.onchange(self) + } + if(self.onstatereadychange) { + self.onstatereadychange(self) + } + } + function setRootElement(root) { + contentElement = null; + self.rootElement = (root); + root.fontFaceDecls = getDirectChild(root, officens, "font-face-decls"); + root.styles = getDirectChild(root, officens, "styles"); + 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") + } + function handleFlatXml(xmldoc) { + var root = importRootNode(xmldoc); + if(!root || (root.localName !== "document" || root.namespaceURI !== officens)) { + setState(OdfContainer.INVALID); + return + } + setRootElement((root)); + setState(OdfContainer.DONE) + } + function handleStylesXml(xmldoc) { + var node = importRootNode(xmldoc), root = self.rootElement, n; + if(!node || (node.localName !== "document-styles" || node.namespaceURI !== officens)) { + setState(OdfContainer.INVALID); + return + } + root.fontFaceDecls = getDirectChild(node, officens, "font-face-decls"); + setChild(root, root.fontFaceDecls); + n = getDirectChild(node, officens, "styles"); + root.styles = n || xmldoc.createElementNS(officens, "styles"); + setChild(root, root.styles); + n = getDirectChild(node, officens, "automatic-styles"); + root.automaticStyles = n || xmldoc.createElementNS(officens, "automatic-styles"); + setAutomaticStylesScope(root.automaticStyles, documentStylesScope); + setChild(root, root.automaticStyles); + node = getDirectChild(node, officens, "master-styles"); + root.masterStyles = node || xmldoc.createElementNS(officens, "master-styles"); + setChild(root, root.masterStyles); + styleInfo.prefixStyleNames(root.automaticStyles, automaticStylePrefix, root.masterStyles) + } + function handleContentXml(xmldoc) { + var node = importRootNode(xmldoc), root, automaticStyles, fontFaceDecls, fontFaceNameChangeMap, c; + if(!node || (node.localName !== "document-content" || node.namespaceURI !== officens)) { + setState(OdfContainer.INVALID); + return + } + root = self.rootElement; + fontFaceDecls = getDirectChild(node, officens, "font-face-decls"); + if(root.fontFaceDecls && fontFaceDecls) { + fontFaceNameChangeMap = mergeFontFaceDecls(root.fontFaceDecls, fontFaceDecls) + }else { + if(fontFaceDecls) { + root.fontFaceDecls = fontFaceDecls; + setChild(root, fontFaceDecls) + } + } + automaticStyles = getDirectChild(node, officens, "automatic-styles"); + setAutomaticStylesScope(automaticStyles, documentContentScope); + if(fontFaceNameChangeMap) { + styleInfo.changeFontFaceNames(automaticStyles, fontFaceNameChangeMap) + } + if(root.automaticStyles && automaticStyles) { + c = automaticStyles.firstChild; + while(c) { + root.automaticStyles.appendChild(c); + c = automaticStyles.firstChild + } + }else { + if(automaticStyles) { + root.automaticStyles = automaticStyles; + setChild(root, automaticStyles) + } + } + node = getDirectChild(node, officens, "body"); + if(node === null) { + throw" tag is mising."; + } + root.body = node; + setChild(root, root.body) + } + function handleMetaXml(xmldoc) { + var node = importRootNode(xmldoc), root; + if(!node || (node.localName !== "document-meta" || node.namespaceURI !== officens)) { + return + } + root = self.rootElement; + node = getDirectChild(node, officens, "meta"); + root.meta = node || xmldoc.createElementNS(officens, "meta"); + setChild(root, root.meta); + initializeMetadataManager(root.meta) + } + function handleSettingsXml(xmldoc) { + var node = importRootNode(xmldoc), root; + if(!node || (node.localName !== "document-settings" || node.namespaceURI !== officens)) { + return + } + root = self.rootElement; + root.settings = getDirectChild(node, officens, "settings"); + setChild(root, root.settings) + } + function handleManifestXml(xmldoc) { + var node = importRootNode(xmldoc), root, e; + if(!node || (node.localName !== "manifest" || node.namespaceURI !== manifestns)) { + return + } + root = self.rootElement; + root.manifest = (node); + e = root.manifest.firstElementChild; + while(e) { + if(e.localName === "file-entry" && e.namespaceURI === manifestns) { + partMimetypes[e.getAttributeNS(manifestns, "full-path")] = e.getAttributeNS(manifestns, "media-type") + } + e = e.nextElementSibling + } + } + function loadNextComponent(remainingComponents) { + var component = remainingComponents.shift(); + if(component) { + zip.loadAsDOM(component.path, function(err, xmldoc) { + component.handler(xmldoc); + if(err || self.state === OdfContainer.INVALID) { + return + } + loadNextComponent(remainingComponents) + }) + }else { + setState(OdfContainer.DONE) + } + } + function loadComponents() { + var componentOrder = [{path:"styles.xml", handler:handleStylesXml}, {path:"content.xml", handler:handleContentXml}, {path:"meta.xml", handler:handleMetaXml}, {path:"settings.xml", handler:handleSettingsXml}, {path:"META-INF/manifest.xml", handler:handleManifestXml}]; + loadNextComponent(componentOrder) + } + function createDocumentElement(name) { + var s = ""; + function defineNamespace(prefix, ns) { + s += " xmlns:" + prefix + '="' + ns + '"' + } + odf.Namespaces.forEachPrefix(defineNamespace); + return'' + } + function serializeMetaXml() { + var serializer = new xmldom.LSSerializer, s = createDocumentElement("document-meta"); + serializer.filter = new odf.OdfNodeFilter; + s += serializer.writeToString(self.rootElement.meta, odf.Namespaces.namespaceMap); + s += ""; + return s + } + function createManifestEntry(fullPath, mediaType) { + var element = document.createElementNS(manifestns, "manifest:file-entry"); + element.setAttributeNS(manifestns, "manifest:full-path", fullPath); + element.setAttributeNS(manifestns, "manifest:media-type", mediaType); + return element + } + function serializeManifestXml() { + var header = '\n', xml = '', manifest = (runtime.parseXML(xml)), manifestRoot = getDirectChild(manifest, manifestns, "manifest"), serializer = new xmldom.LSSerializer, fullPath; + for(fullPath in partMimetypes) { + if(partMimetypes.hasOwnProperty(fullPath)) { + manifestRoot.appendChild(createManifestEntry(fullPath, partMimetypes[fullPath])) + } + } + serializer.filter = new odf.OdfNodeFilter; + return header + serializer.writeToString(manifest, odf.Namespaces.namespaceMap) + } + 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); + s += ""; + return s + } + function serializeStylesXml() { + var fontFaceDecls, automaticStyles, masterStyles, nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, s = createDocumentElement("document-styles"); + automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentStylesScope); + masterStyles = (self.rootElement.masterStyles.cloneNode(true)); + fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [masterStyles, self.rootElement.styles, automaticStyles]); + styleInfo.removePrefixFromStyleNames(automaticStyles, automaticStylePrefix, masterStyles); + serializer.filter = new OdfStylesFilter(masterStyles, automaticStyles); + s += serializer.writeToString(fontFaceDecls, nsmap); + s += serializer.writeToString(self.rootElement.styles, nsmap); + s += serializer.writeToString(automaticStyles, nsmap); + s += serializer.writeToString(masterStyles, nsmap); + s += ""; + return s + } + function serializeContentXml() { + var fontFaceDecls, automaticStyles, nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, s = createDocumentElement("document-content"); + automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentContentScope); + fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [automaticStyles]); + serializer.filter = new OdfContentFilter(self.rootElement.body, automaticStyles); + s += serializer.writeToString(fontFaceDecls, nsmap); + s += serializer.writeToString(automaticStyles, nsmap); + s += serializer.writeToString(self.rootElement.body, nsmap); + s += ""; + return s + } + function createElement(type) { + var original = document.createElementNS(type.namespaceURI, type.localName), method, iface = new type.Type; + for(method in iface) { + if(iface.hasOwnProperty(method)) { + original[method] = iface[method] + } + } + return original + } + function loadFromXML(url, callback) { + runtime.loadXML(url, function(err, dom) { + if(err) { + callback(err) + }else { + handleFlatXml(dom) + } + }) + } + this.setRootElement = setRootElement; + this.getContentElement = function() { + var body; + if(!contentElement) { + body = self.rootElement.body; + contentElement = getDirectChild(body, officens, "text") || (getDirectChild(body, officens, "presentation") || getDirectChild(body, officens, "spreadsheet")) + } + if(!contentElement) { + throw"Could not find content element in ."; + } + return contentElement + }; + this.getDocumentType = function() { + var content = self.getContentElement(); + return content && content.localName + }; + this.getMetadataManager = function() { + return metadataManager + }; + this.getPart = function(partname) { + return new odf.OdfPart(partname, partMimetypes[partname], self, zip) + }; + this.getPartData = function(url, callback) { + zip.load(url, callback) + }; + function updateMetadataForSaving() { + var generatorString, window = runtime.getWindow(); + generatorString = "WebODF/" + (String(typeof webodf_version) !== "undefined" ? webodf_version : "FromSource"); + if(window) { + generatorString = generatorString + " " + window.navigator.userAgent + } + metadataManager.setMetadata({"meta:generator":generatorString}, null) + } + function createEmptyTextDocument() { + var emptyzip = new core.Zip("", null), data = runtime.byteArrayFromString("application/vnd.oasis.opendocument.text", "utf8"), root = self.rootElement, text = document.createElementNS(officens, "text"); + emptyzip.save("mimetype", data, false, new Date); + function addToplevelElement(memberName, realLocalName) { + var element; + if(!realLocalName) { + realLocalName = memberName + } + element = document.createElementNS(officens, realLocalName); + root[memberName] = element; + root.appendChild(element) + } + addToplevelElement("meta"); + addToplevelElement("settings"); + addToplevelElement("scripts"); + addToplevelElement("fontFaceDecls", "font-face-decls"); + addToplevelElement("styles"); + addToplevelElement("automaticStyles", "automatic-styles"); + addToplevelElement("masterStyles", "master-styles"); + addToplevelElement("body"); + root.body.appendChild(text); + initializeMetadataManager(root.meta); + setState(OdfContainer.DONE); + return emptyzip + } + function fillZip() { + var data, date = new Date; + updateMetadataForSaving(); + data = runtime.byteArrayFromString(serializeSettingsXml(), "utf8"); + zip.save("settings.xml", data, true, date); + data = runtime.byteArrayFromString(serializeMetaXml(), "utf8"); + zip.save("meta.xml", data, true, date); + data = runtime.byteArrayFromString(serializeStylesXml(), "utf8"); + zip.save("styles.xml", data, true, date); + data = runtime.byteArrayFromString(serializeContentXml(), "utf8"); + zip.save("content.xml", data, true, date); + data = runtime.byteArrayFromString(serializeManifestXml(), "utf8"); + zip.save("META-INF/manifest.xml", data, true, date) + } + function createByteArray(successCallback, errorCallback) { + fillZip(); + zip.createByteArray(successCallback, errorCallback) + } + this.createByteArray = createByteArray; + function saveAs(newurl, callback) { + fillZip(); + zip.writeAs(newurl, function(err) { + callback(err) + }) + } + this.saveAs = saveAs; + this.save = function(callback) { + saveAs(url, callback) + }; + this.getUrl = function() { + return url + }; + this.setBlob = function(filename, mimetype, content) { + var data = base64.convertBase64ToByteArray(content), date = new Date; + zip.save(filename, data, false, date); + if(partMimetypes.hasOwnProperty(filename)) { + runtime.log(filename + " has been overwritten.") + } + partMimetypes[filename] = mimetype + }; + this.removeBlob = function(filename) { + var foundAndRemoved = zip.remove(filename); + runtime.assert(foundAndRemoved, "file is not found: " + filename); + delete partMimetypes[filename] + }; + this.state = OdfContainer.LOADING; + this.rootElement = (createElement({Type:odf.ODFDocumentElement, namespaceURI:odf.ODFDocumentElement.namespaceURI, localName:odf.ODFDocumentElement.localName})); + if(url) { + zip = new core.Zip(url, function(err, zipobject) { + zip = zipobject; + if(err) { + loadFromXML(url, function(xmlerr) { + if(err) { + zip.error = err + "\n" + xmlerr; + setState(OdfContainer.INVALID) + } + }) + }else { + loadComponents() + } + }) + }else { + zip = createEmptyTextDocument() + } + }; + 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(url) { + return new odf.OdfContainer(url, null) + }; + return odf.OdfContainer +})(); +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.Base64"); +runtime.loadClass("xmldom.XPath"); +runtime.loadClass("odf.OdfContainer"); +(function() { + var xpath = xmldom.XPath, base64 = new core.Base64; + function getEmbeddedFontDeclarations(fontFaceDecls) { + var decls = {}, fonts, i, font, name, uris, href, family; + if(!fontFaceDecls) { + return decls + } + fonts = xpath.getODFElementsWithXPath(fontFaceDecls, "style:font-face[svg:font-face-src]", odf.Namespaces.lookupNamespaceURI); + for(i = 0;i < fonts.length;i += 1) { + font = fonts[i]; + name = font.getAttributeNS(odf.Namespaces.stylens, "name"); + family = font.getAttributeNS(odf.Namespaces.svgns, "font-family"); + uris = xpath.getODFElementsWithXPath(font, "svg:font-face-src/svg:font-face-uri", odf.Namespaces.lookupNamespaceURI); + if(uris.length > 0) { + href = uris[0].getAttributeNS(odf.Namespaces.xlinkns, "href"); + decls[name] = {href:href, family:family} + } + } + return decls + } + function addFontToCSS(name, font, fontdata, stylesheet) { + var cssFamily = font.family || name, rule = "@font-face { font-family: '" + cssFamily + "'; src: " + "url(data:application/x-font-ttf;charset=binary;base64," + base64.convertUTF8ArrayToBase64(fontdata) + ') format("truetype"); }'; + try { + stylesheet.insertRule(rule, stylesheet.cssRules.length) + }catch(e) { + runtime.log("Problem inserting rule in CSS: " + runtime.toJson(e) + "\nRule: " + rule) + } + } + function loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos, stylesheet, callback) { + var name, i = 0, n; + for(n in embeddedFontDeclarations) { + if(embeddedFontDeclarations.hasOwnProperty(n)) { + if(i === pos) { + name = n; + break + } + i += 1 + } + } + if(!name) { + if(callback) { + callback() + } + return + } + odfContainer.getPartData(embeddedFontDeclarations[name].href, function(err, fontdata) { + if(err) { + runtime.log(err) + }else { + if(!fontdata) { + runtime.log("missing font data for " + embeddedFontDeclarations[name].href) + }else { + addFontToCSS(name, embeddedFontDeclarations[name], fontdata, stylesheet) + } + } + loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos + 1, stylesheet, callback) + }) + } + function loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet) { + loadFontIntoCSS(embeddedFontDeclarations, odfContainer, 0, stylesheet) + } + odf.FontLoader = function FontLoader() { + this.loadFonts = function(odfContainer, stylesheet) { + var embeddedFontDeclarations, fontFaceDecls = odfContainer.rootElement.fontFaceDecls; + while(stylesheet.cssRules.length) { + stylesheet.deleteRule(stylesheet.cssRules.length - 1) + } + if(fontFaceDecls) { + embeddedFontDeclarations = getEmbeddedFontDeclarations(fontFaceDecls); + loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet) + } + } + }; + return odf.FontLoader +})(); +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("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 + + @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 . + + 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("core.LoopWatchDog"); +runtime.loadClass("odf.Namespaces"); +odf.TextStyleApplicatorFormatting = function() { +}; +odf.TextStyleApplicatorFormatting.prototype.getAppliedStylesForElement = function(textnode) { +}; +odf.TextStyleApplicatorFormatting.prototype.createDerivedStyleObject = function(parentStyleName, family, overrides) { +}; +odf.TextStyleApplicatorFormatting.prototype.updateStyle = function(styleNode, properties) { +}; +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 + } + this.isStyleApplied = function(textNode) { + var appliedStyle = formatting.getAppliedStylesForElement(textNode); + 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 + + @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 . + + 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"); +runtime.loadClass("odf.TextStyleApplicator"); +odf.Formatting = function Formatting() { + var self = this, 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) { + var result, builtInDefaultStyleAttributes = builtInDefaultStyleAttributesByFamily[styleFamily]; + if(builtInDefaultStyleAttributes) { + result = utils.mergeObjects({}, builtInDefaultStyleAttributes) + }else { + result = {} + } + return result + } + this.getSystemDefaultStyleAttributes = getSystemDefaultStyleAttributes; + this.setOdfContainer = function(odfcontainer) { + odfContainer = odfcontainer + }; + 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 getFontMap() { + var fontFaceDecls = odfContainer.rootElement.fontFaceDecls, fontFaceDeclsMap = {}, node, name, family; + node = fontFaceDecls && fontFaceDecls.firstElementChild; + while(node) { + name = node.getAttributeNS(stylens, "name"); + if(name) { + family = node.getAttributeNS(svgns, "font-family"); + if(family || node.getElementsByTagNameNS(svgns, "font-face-uri").length > 0) { + fontFaceDeclsMap[name] = family + } + } + node = node.nextElementSibling + } + return fontFaceDeclsMap + } + this.getFontMap = getFontMap; + this.getAvailableParagraphStyles = function() { + var node = odfContainer.rootElement.styles, p_family, p_name, p_displayName, paragraphStyles = []; + node = node && node.firstElementChild; + while(node) { + if(node.localName === "style" && node.namespaceURI === stylens) { + p_family = node.getAttributeNS(stylens, "family"); + if(p_family === "paragraph") { + p_name = node.getAttributeNS(stylens, "name"); + p_displayName = node.getAttributeNS(stylens, "display-name") || p_name; + if(p_name && p_displayName) { + paragraphStyles.push({name:p_name, displayName:p_displayName}) + } + } + } + node = node.nextElementSibling + } + return paragraphStyles + }; + this.isStyleUsed = function(styleElement) { + var hasDerivedStyles, isUsed, root = odfContainer.rootElement; + hasDerivedStyles = styleInfo.hasDerivedStyles(root, odf.Namespaces.lookupNamespaceURI, styleElement); + isUsed = (new styleInfo.UsedStyleList(root.styles)).uses(styleElement) || ((new styleInfo.UsedStyleList(root.automaticStyles)).uses(styleElement) || (new styleInfo.UsedStyleList(root.body)).uses(styleElement)); + return hasDerivedStyles || isUsed + }; + function getDefaultStyleElement(family) { + var node = odfContainer.rootElement.styles.firstElementChild; + while(node) { + if(node.namespaceURI === stylens && (node.localName === "default-style" && node.getAttributeNS(stylens, "family") === family)) { + return node + } + node = node.nextElementSibling + } + return null + } + this.getDefaultStyleElement = getDefaultStyleElement; + function getStyleElement(styleName, family, styleElements) { + var node, nodeStyleName, styleListElement, i; + styleElements = styleElements || [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles]; + for(i = 0;i < styleElements.length;i += 1) { + styleListElement = (styleElements[i]); + node = styleListElement.firstElementChild; + while(node) { + nodeStyleName = node.getAttributeNS(stylens, "name"); + if(node.namespaceURI === stylens && (node.localName === "style" && (node.getAttributeNS(stylens, "family") === family && nodeStyleName === styleName))) { + return node + } + if(family === "list-style" && (node.namespaceURI === textns && (node.localName === "list-style" && nodeStyleName === styleName))) { + return node + } + if(family === "data" && (node.namespaceURI === numberns && nodeStyleName === styleName)) { + return node + } + node = node.nextElementSibling + } + } + return null + } + this.getStyleElement = getStyleElement; + function getStyleAttributes(styleNode) { + var i, a, map, ai, propertiesMap = {}, propertiesNode = styleNode.firstElementChild; + while(propertiesNode) { + if(propertiesNode.namespaceURI === stylens) { + map = propertiesMap[propertiesNode.nodeName] = {}; + a = propertiesNode.attributes; + for(i = 0;i < a.length;i += 1) { + ai = (a.item(i)); + map[ai.name] = ai.value + } + } + propertiesNode = propertiesNode.nextElementSibling + } + a = styleNode.attributes; + for(i = 0;i < a.length;i += 1) { + ai = (a.item(i)); + propertiesMap[ai.name] = ai.value + } + return propertiesMap + } + this.getStyleAttributes = getStyleAttributes; + function getInheritedStyleAttributes(styleNode, includeSystemDefault) { + var styleListElement = odfContainer.rootElement.styles, parentStyleName, propertiesMap, inheritedPropertiesMap = {}, styleFamily = styleNode.getAttributeNS(stylens, "family"), node = styleNode; + while(node) { + propertiesMap = getStyleAttributes(node); + inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap); + parentStyleName = node.getAttributeNS(stylens, "parent-style-name"); + if(parentStyleName) { + node = getStyleElement(parentStyleName, styleFamily, [styleListElement]) + }else { + node = null + } + } + node = getDefaultStyleElement(styleFamily); + if(node) { + propertiesMap = getStyleAttributes(node); + inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap) + } + if(includeSystemDefault) { + propertiesMap = getSystemDefaultStyleAttributes(styleFamily); + if(propertiesMap) { + inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap) + } + } + return inheritedPropertiesMap + } + this.getInheritedStyleAttributes = getInheritedStyleAttributes; + this.getFirstCommonParentStyleNameOrSelf = function(styleName) { + var automaticStyleElementList = odfContainer.rootElement.automaticStyles, styleElementList = odfContainer.rootElement.styles, styleElement; + styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList]); + while(styleElement) { + styleName = styleElement.getAttributeNS(stylens, "parent-style-name"); + styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList]) + } + styleElement = getStyleElement(styleName, "paragraph", [styleElementList]); + if(!styleElement) { + return null + } + return styleName + }; + this.hasParagraphStyle = function(styleName) { + return Boolean(getStyleElement(styleName, "paragraph")) + }; + function buildStyleChain(node, collectedChains) { + var parent = (node.nodeType === Node.TEXT_NODE ? node.parentNode : node), nodeStyles, appliedStyles = [], chainKey = "", foundContainer = false; + while(parent) { + if(!foundContainer && odfUtils.isGroupingElement(parent)) { + foundContainer = true + } + nodeStyles = styleInfo.determineStylesForNode(parent); + if(nodeStyles) { + appliedStyles.push(nodeStyles) + } + parent = parent.parentElement + } + function chainStyles(usedStyleMap) { + Object.keys(usedStyleMap).forEach(function(styleFamily) { + Object.keys(usedStyleMap[styleFamily]).forEach(function(styleName) { + chainKey += "|" + styleFamily + ":" + styleName + "|" + }) + }) + } + if(foundContainer) { + appliedStyles.forEach(chainStyles); + if(collectedChains) { + collectedChains[chainKey] = appliedStyles + } + } + return foundContainer ? appliedStyles : undefined + } + 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; + styleElement = getStyleElement(styleName, styleFamily); + if(styleElement) { + parentStyle = getInheritedStyleAttributes((styleElement)); + mergedChildStyle = utils.mergeObjects(parentStyle, mergedChildStyle); + displayName = styleElement.getAttributeNS(stylens, "display-name") + }else { + runtime.log("No style element found for '" + styleName + "' of family '" + styleFamily + "'") + } + mergedChildStyle.orderedStyles.push({name:styleName, family:styleFamily, displayName:displayName}) + }) + }); + return mergedChildStyle + } + this.getAppliedStyles = function(textNodes) { + var styleChains = {}, styles = []; + textNodes.forEach(function(n) { + buildStyleChain(n, styleChains) + }); + Object.keys(styleChains).forEach(function(key) { + styles.push(calculateAppliedStyle(styleChains[key])) + }); + return styles + }; + this.getAppliedStylesForElement = function(node) { + var styleChain; + styleChain = buildStyleChain(node); + return styleChain ? calculateAppliedStyle(styleChain) : undefined + }; + this.applyStyle = function(memberId, textNodes, limits, info) { + var textStyles = new odf.TextStyleApplicator(new odf.ObjectNameGenerator((odfContainer), memberId), self, odfContainer.rootElement.automaticStyles); + textStyles.applyStyle(textNodes, limits, info) + }; + this.updateStyle = function(styleNode, properties) { + var fontName, fontFaceNode; + domUtils.mapObjOntoNode(styleNode, properties, odf.Namespaces.lookupNamespaceURI); + fontName = properties["style:text-properties"] && properties["style:text-properties"]["style:font-name"]; + if(fontName && !getFontMap().hasOwnProperty(fontName)) { + fontFaceNode = styleNode.ownerDocument.createElementNS(stylens, "style:font-face"); + fontFaceNode.setAttributeNS(stylens, "style:name", fontName); + fontFaceNode.setAttributeNS(svgns, "svg:font-family", fontName); + 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 { + newStyleObject = {"style:parent-style-name":parentStyleName} + } + newStyleObject["style:family"] = family; + utils.mergeObjects(newStyleObject, overrides); + return newStyleObject + }; + this.getDefaultTabStopDistance = function() { + var defaultParagraph = getDefaultStyleElement("paragraph"), paragraphProperties = defaultParagraph && defaultParagraph.firstElementChild, tabStopDistance; + while(paragraphProperties) { + if(paragraphProperties.namespaceURI === stylens && paragraphProperties.localName === "paragraph-properties") { + tabStopDistance = paragraphProperties.getAttributeNS(stylens, "tab-stop-distance") + } + paragraphProperties = paragraphProperties.nextElementSibling + } + if(!tabStopDistance) { + tabStopDistance = "1.25cm" + } + return odfUtils.parseNonNegativeLength(tabStopDistance) + }; + function getPageLayoutStyleElement(styleName, styleFamily) { + var masterPageName, layoutName, pageLayoutElements, node, i, styleElement = getStyleElement(styleName, styleFamily); + runtime.assert(styleFamily === "paragraph" || styleFamily === "table", "styleFamily has to be either paragraph or table"); + if(styleElement) { + masterPageName = styleElement.getAttributeNS(stylens, "master-page-name") || "Standard"; + node = odfContainer.rootElement.masterStyles.lastElementChild; + while(node) { + if(node.getAttributeNS(stylens, "name") === masterPageName) { + break + } + node = node.previousElementSibling + } + layoutName = node.getAttributeNS(stylens, "page-layout-name"); + pageLayoutElements = domUtils.getElementsByTagNameNS(odfContainer.rootElement.automaticStyles, stylens, "page-layout"); + for(i = 0;i < pageLayoutElements.length;i += 1) { + node = pageLayoutElements[i]; + if(node.getAttributeNS(stylens, "name") === layoutName) { + return(node) + } + } + } + return null + } + function lengthInCm(length, defaultValue) { + var result = odfUtils.parseLength(length), value = defaultValue; + if(result) { + switch(result.unit) { + case "cm": + value = result.value; + break; + case "mm": + value = result.value * 0.1; + break; + case "in": + value = result.value * 2.54; + break; + case "pt": + value = result.value * 0.035277778; + break; + case "pc": + ; + case "px": + ; + case "em": + break; + default: + runtime.log("Unit identifier: " + result.unit + " is not supported."); + break + } + } + return value + } + this.getContentSize = function(styleName, styleFamily) { + var pageLayoutElement, props, printOrientation, defaultOrientedPageWidth, defaultOrientedPageHeight, pageWidth, pageHeight, margin, marginLeft, marginRight, marginTop, marginBottom, padding, paddingLeft, paddingRight, paddingTop, paddingBottom; + pageLayoutElement = getPageLayoutStyleElement(styleName, styleFamily); + if(!pageLayoutElement) { + pageLayoutElement = getDirectChild(odfContainer.rootElement.styles, stylens, "default-page-layout") + } + props = getDirectChild(pageLayoutElement, stylens, "page-layout-properties"); + if(props) { + printOrientation = props.getAttributeNS(stylens, "print-orientation") || "portrait"; + if(printOrientation === "portrait") { + defaultOrientedPageWidth = defaultPageFormatSettings.width; + defaultOrientedPageHeight = defaultPageFormatSettings.height + }else { + defaultOrientedPageWidth = defaultPageFormatSettings.height; + defaultOrientedPageHeight = defaultPageFormatSettings.width + } + pageWidth = lengthInCm(props.getAttributeNS(fons, "page-width"), defaultOrientedPageWidth); + pageHeight = lengthInCm(props.getAttributeNS(fons, "page-height"), defaultOrientedPageHeight); + margin = lengthInCm(props.getAttributeNS(fons, "margin"), null); + if(margin === null) { + marginLeft = lengthInCm(props.getAttributeNS(fons, "margin-left"), defaultPageFormatSettings.margin); + marginRight = lengthInCm(props.getAttributeNS(fons, "margin-right"), defaultPageFormatSettings.margin); + marginTop = lengthInCm(props.getAttributeNS(fons, "margin-top"), defaultPageFormatSettings.margin); + marginBottom = lengthInCm(props.getAttributeNS(fons, "margin-bottom"), defaultPageFormatSettings.margin) + }else { + marginLeft = marginRight = marginTop = marginBottom = margin + } + padding = lengthInCm(props.getAttributeNS(fons, "padding"), null); + if(padding === null) { + paddingLeft = lengthInCm(props.getAttributeNS(fons, "padding-left"), defaultPageFormatSettings.padding); + paddingRight = lengthInCm(props.getAttributeNS(fons, "padding-right"), defaultPageFormatSettings.padding); + paddingTop = lengthInCm(props.getAttributeNS(fons, "padding-top"), defaultPageFormatSettings.padding); + paddingBottom = lengthInCm(props.getAttributeNS(fons, "padding-bottom"), defaultPageFormatSettings.padding) + }else { + paddingLeft = paddingRight = paddingTop = paddingBottom = padding + } + } + return{width:pageWidth - marginLeft - marginRight - paddingLeft - paddingRight, height:pageHeight - marginTop - marginBottom - paddingTop - paddingBottom} + } +}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.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 LoadingQueue() { + var queue = [], taskRunning = false; + function run(task) { + taskRunning = true; + runtime.setTimeout(function() { + try { + task() + }catch(e) { + runtime.log(String(e)) + } + taskRunning = false; + if(queue.length > 0) { + run(queue.pop()) + } + }, 10) + } + this.clearQueue = function() { + queue.length = 0 + }; + this.addToQueue = function(loadingTask) { + if(queue.length === 0 && !taskRunning) { + return run(loadingTask) + } + queue.push(loadingTask) + } + } + function PageSwitcher(css) { + var sheet = (css.sheet), position = 1; + function updateCSS() { + while(sheet.cssRules.length > 0) { + sheet.deleteRule(0) + } + sheet.insertRule("#shadowContent draw|page {display:none;}", 0); + sheet.insertRule("office|presentation draw|page {display:none;}", 1); + sheet.insertRule("#shadowContent draw|page:nth-of-type(" + position + ") {display:block;}", 2); + sheet.insertRule("office|presentation draw|page:nth-of-type(" + position + ") {display:block;}", 3) + } + this.showFirstPage = function() { + position = 1; + updateCSS() + }; + this.showNextPage = function() { + position += 1; + updateCSS() + }; + this.showPreviousPage = function() { + if(position > 1) { + position -= 1; + updateCSS() + } + }; + this.showPage = function(n) { + if(n > 0) { + position = n; + updateCSS() + } + }; + this.css = css; + this.destroy = function(callback) { + css.parentNode.removeChild(css); + callback() + } + } + function listenEvent(eventTarget, eventType, eventHandler) { + if(eventTarget.addEventListener) { + eventTarget.addEventListener(eventType, eventHandler, false) + }else { + if(eventTarget.attachEvent) { + eventType = "on" + eventType; + eventTarget.attachEvent(eventType, eventHandler) + }else { + eventTarget["on" + eventType] = eventHandler + } + } + } + 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, xmlns = odf.Namespaces.xmlns, presentationns = odf.Namespaces.presentationns, webodfhelperns = "urn:webodf:names:helper", window = runtime.getWindow(), xpath = xmldom.XPath, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils; + function clear(element) { + while(element.firstChild) { + element.removeChild(element.firstChild) + } + } + function handleStyles(odfcontainer, formatting, stylesxmlcss) { + var style2css = new odf.Style2CSS; + style2css.style2css(odfcontainer.getDocumentType(), (stylesxmlcss.sheet), formatting.getFontMap(), odfcontainer.rootElement.styles, odfcontainer.rootElement.automaticStyles) + } + function handleFonts(odfContainer, fontcss) { + var fontLoader = new odf.FontLoader; + fontLoader.loadFonts(odfContainer, (fontcss.sheet)) + } + function getMasterPageElement(odfContainer, masterPageName) { + 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)) { + break + } + } + return masterPageElement + } + 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)) { + element.parentNode.removeChild(element) + } + } + } + function getHeaderFooter(odfContainer, frame, headerFooterId) { + var headerFooter = null, i, declElements = odfContainer.rootElement.body.getElementsByTagNameNS(presentationns, headerFooterId + "-decl"), headerFooterName = frame.getAttributeNS(presentationns, "use-" + headerFooterId + "-name"), element; + if(headerFooterName && declElements.length > 0) { + for(i = 0;i < declElements.length;i += 1) { + element = (declElements[i]); + if(element.getAttributeNS(presentationns, "name") === headerFooterName) { + headerFooter = element.textContent; + break + } + } + } + return headerFooter + } + function setContainerValue(rootElement, ns, localName, value) { + var i, containerList, document = rootElement.ownerDocument, e; + containerList = rootElement.getElementsByTagNameNS(ns, localName); + for(i = 0;i < containerList.length;i += 1) { + clear(containerList[i]); + if(value) { + e = (containerList[i]); + e.appendChild(document.createTextNode(value)) + } + } + } + function setDrawElementPosition(styleid, frame, stylesheet) { + frame.setAttributeNS(webodfhelperns, "styleid", styleid); + var rule, anchor = frame.getAttributeNS(textns, "anchor-type"), x = frame.getAttributeNS(svgns, "x"), y = frame.getAttributeNS(svgns, "y"), width = frame.getAttributeNS(svgns, "width"), height = frame.getAttributeNS(svgns, "height"), minheight = frame.getAttributeNS(fons, "min-height"), minwidth = frame.getAttributeNS(fons, "min-width"); + if(anchor === "as-char") { + rule = "display: inline-block;" + }else { + if(anchor || (x || y)) { + rule = "position: absolute;" + }else { + if(width || (height || (minheight || minwidth))) { + rule = "display: block;" + } + } + } + if(x) { + rule += "left: " + x + ";" + } + if(y) { + rule += "top: " + y + ";" + } + if(width) { + rule += "width: " + width + ";" + } + if(height) { + rule += "height: " + height + ";" + } + if(minheight) { + rule += "min-height: " + minheight + ";" + } + if(minwidth) { + rule += "min-width: " + minwidth + ";" + } + if(rule) { + rule = "draw|" + frame.localName + '[webodfhelper|styleid="' + styleid + '"] {' + rule + "}"; + stylesheet.insertRule(rule, stylesheet.cssRules.length) + } + } + function getUrlFromBinaryDataElement(image) { + var node = image.firstChild; + while(node) { + if(node.namespaceURI === officens && node.localName === "binary-data") { + return"data:image/png;base64," + node.textContent.replace(/[\r\n\s]/g, "") + } + node = node.nextSibling + } + return"" + } + function setImage(id, container, image, stylesheet) { + image.setAttributeNS(webodfhelperns, "styleid", id); + var url = image.getAttributeNS(xlinkns, "href"), part; + function callback(url) { + var rule; + if(url) { + rule = "background-image: url(" + url + ");"; + rule = 'draw|image[webodfhelper|styleid="' + id + '"] {' + rule + "}"; + stylesheet.insertRule(rule, stylesheet.cssRules.length) + } + } + function onchange(p) { + callback(p.url) + } + if(url) { + try { + part = container.getPart(url); + part.onchange = onchange; + part.load() + }catch(e) { + runtime.log("slight problem: " + String(e)) + } + }else { + url = getUrlFromBinaryDataElement(image); + callback(url) + } + } + function formatParagraphAnchors(odfbody) { + var n, i, nodes = xpath.getODFElementsWithXPath(odfbody, ".//*[*[@text:anchor-type='paragraph']]", odf.Namespaces.lookupNamespaceURI); + for(i = 0;i < nodes.length;i += 1) { + n = nodes[i]; + if(n.setAttributeNS) { + n.setAttributeNS(webodfhelperns, "containsparagraphanchor", true) + } + } + } + function modifyTables(odffragment, documentns) { + var i, tableCells, node; + function modifyTableCell(node) { + if(node.hasAttributeNS(tablens, "number-columns-spanned")) { + node.setAttributeNS(documentns, "colspan", node.getAttributeNS(tablens, "number-columns-spanned")) + } + if(node.hasAttributeNS(tablens, "number-rows-spanned")) { + node.setAttributeNS(documentns, "rowspan", node.getAttributeNS(tablens, "number-rows-spanned")) + } + } + tableCells = odffragment.getElementsByTagNameNS(tablens, "table-cell"); + for(i = 0;i < tableCells.length;i += 1) { + node = (tableCells.item(i)); + 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) { + if(!lineBreak.hasChildNodes()) { + lineBreak.appendChild(document.createElement("br")) + } + }) + } + function expandSpaceElements(odffragment) { + var spaces, doc = odffragment.ownerDocument; + function expandSpaceElement(space) { + var j, count; + while(space.firstChild) { + space.removeChild(space.firstChild) + } + space.appendChild(doc.createTextNode(" ")); + count = parseInt(space.getAttributeNS(textns, "c"), 10); + if(count > 1) { + space.removeAttributeNS(textns, "c"); + for(j = 1;j < count;j += 1) { + space.parentNode.insertBefore(space.cloneNode(true), space) + } + } + } + spaces = domUtils.getElementsByTagNameNS(odffragment, textns, "s"); + spaces.forEach(expandSpaceElement) + } + function expandTabElements(odffragment) { + var tabs; + tabs = domUtils.getElementsByTagNameNS(odffragment, textns, "tab"); + tabs.forEach(function(tab) { + tab.textContent = "\t" + }) + } + function modifyDrawElements(odfbody, stylesheet) { + var node, drawElements = [], i; + node = odfbody.firstElementChild; + while(node && node !== odfbody) { + if(node.namespaceURI === drawns) { + drawElements[drawElements.length] = node + } + if(node.firstElementChild) { + node = node.firstElementChild + }else { + while(node && (node !== odfbody && !node.nextElementSibling)) { + node = node.parentElement + } + if(node && node.nextElementSibling) { + node = node.nextElementSibling + } + } + } + for(i = 0;i < drawElements.length;i += 1) { + node = drawElements[i]; + setDrawElementPosition("frame" + String(i), node, stylesheet) + } + formatParagraphAnchors(odfbody) + } + function cloneMasterPages(odfContainer, shadowContent, odfbody, stylesheet) { + var masterPageName, masterPageElement, styleId, clonedPageElement, clonedElement, pageNumber = 0, i, element, elementToClone, document = odfContainer.rootElement.ownerDocument; + element = odfbody.firstElementChild; + if(!(element && (element.namespaceURI === officens && (element.localName === "presentation" || element.localName === "drawing")))) { + return + } + element = element.firstElementChild; + while(element) { + masterPageName = element.getAttributeNS(drawns, "master-page-name"); + masterPageElement = getMasterPageElement(odfContainer, masterPageName); + if(masterPageElement) { + styleId = element.getAttributeNS(webodfhelperns, "styleid"); + clonedPageElement = document.createElementNS(drawns, "draw:page"); + elementToClone = masterPageElement.firstElementChild; + i = 0; + while(elementToClone) { + if(elementToClone.getAttributeNS(presentationns, "placeholder") !== "true") { + clonedElement = (elementToClone.cloneNode(true)); + clonedPageElement.appendChild(clonedElement); + setDrawElementPosition(styleId + "_" + i, clonedElement, stylesheet) + } + elementToClone = elementToClone.nextElementSibling; + i += 1 + } + dropTemplateDrawFrames(clonedPageElement); + shadowContent.appendChild(clonedPageElement); + pageNumber = String(shadowContent.getElementsByTagNameNS(drawns, "page").length); + setContainerValue(clonedPageElement, textns, "page-number", pageNumber); + setContainerValue(clonedPageElement, presentationns, "header", getHeaderFooter(odfContainer, (element), "header")); + setContainerValue(clonedPageElement, presentationns, "footer", getHeaderFooter(odfContainer, (element), "footer")); + setDrawElementPosition(styleId, clonedPageElement, stylesheet); + clonedPageElement.setAttributeNS(drawns, "draw:master-page-name", masterPageElement.getAttributeNS(stylens, "name")) + } + element = element.nextElementSibling + } + } + function setVideo(container, plugin) { + var video, source, url, doc = plugin.ownerDocument, part; + url = plugin.getAttributeNS(xlinkns, "href"); + function callback(url, mimetype) { + var ns = doc.documentElement.namespaceURI; + if(mimetype.substr(0, 6) === "video/") { + video = doc.createElementNS(ns, "video"); + video.setAttribute("controls", "controls"); + source = doc.createElementNS(ns, "source"); + if(url) { + source.setAttribute("src", url) + } + source.setAttribute("type", mimetype); + video.appendChild(source); + plugin.parentNode.appendChild(video) + }else { + plugin.innerHtml = "Unrecognised Plugin" + } + } + function onchange(p) { + callback(p.url, p.mimetype) + } + if(url) { + try { + part = container.getPart(url); + part.onchange = onchange; + part.load() + }catch(e) { + runtime.log("slight problem: " + String(e)) + } + }else { + runtime.log("using MP4 data fallback"); + url = getUrlFromBinaryDataElement(plugin); + callback(url, "video/mp4") + } + } + function getNumberRule(node) { + var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix") || "", prefix = node.getAttributeNS(stylens, "num-prefix") || "", rule = "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content; + content = prefix; + if(stylemap.hasOwnProperty(style)) { + content += " counter(list, " + stylemap[style] + ")" + }else { + if(style) { + content += "'" + style + "';" + }else { + content += " ''" + } + } + if(suffix) { + content += " '" + suffix + "'" + } + rule = "content: " + content + ";"; + return rule + } + function getImageRule() { + var rule = "content: none;"; + return rule + } + function getBulletRule(node) { + var bulletChar = node.getAttributeNS(textns, "bullet-char"); + return"content: '" + bulletChar + "';" + } + function getBulletsRule(node) { + var itemrule; + if(node) { + if(node.localName === "list-level-style-number") { + itemrule = getNumberRule(node) + }else { + if(node.localName === "list-level-style-image") { + itemrule = getImageRule() + }else { + if(node.localName === "list-level-style-bullet") { + itemrule = getBulletRule(node) + } + } + } + } + return itemrule + } + function loadLists(odffragment, stylesheet, documentns) { + var i, lists, node, id, continueList, styleName, rule, listMap = {}, parentList, listStyles, listStyleMap = {}, bulletRule; + listStyles = window.document.getElementsByTagNameNS(textns, "list-style"); + for(i = 0;i < listStyles.length;i += 1) { + node = (listStyles.item(i)); + styleName = node.getAttributeNS(stylens, "name"); + if(styleName) { + listStyleMap[styleName] = node + } + } + lists = odffragment.getElementsByTagNameNS(textns, "list"); + for(i = 0;i < lists.length;i += 1) { + node = (lists.item(i)); + id = node.getAttributeNS(xmlns, "id"); + if(id) { + continueList = node.getAttributeNS(textns, "continue-list"); + node.setAttributeNS(documentns, "id", id); + rule = "text|list#" + id + " > text|list-item > *:first-child:before {"; + styleName = node.getAttributeNS(textns, "style-name"); + if(styleName) { + node = listStyleMap[styleName]; + bulletRule = getBulletsRule((odfUtils.getFirstNonWhitespaceChild(node))) + } + if(continueList) { + parentList = listMap[continueList]; + while(parentList) { + parentList = listMap[parentList] + } + rule += "counter-increment:" + continueList + ";"; + if(bulletRule) { + bulletRule = bulletRule.replace("list", continueList); + rule += bulletRule + }else { + rule += "content:counter(" + continueList + ");" + } + }else { + continueList = ""; + if(bulletRule) { + bulletRule = bulletRule.replace("list", id); + rule += bulletRule + }else { + rule += "content: counter(" + id + ");" + } + rule += "counter-increment:" + id + ";"; + stylesheet.insertRule("text|list#" + id + " {counter-reset:" + id + "}", stylesheet.cssRules.length) + } + rule += "}"; + listMap[id] = continueList; + if(rule) { + stylesheet.insertRule(rule, stylesheet.cssRules.length) + } + } + } + } + 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)) + }else { + style = document.createElementNS(head.namespaceURI, "link"); + href = "webodf.css"; + if(runtime.currentDirectory) { + href = runtime.currentDirectory() + "/../" + href + } + style.setAttribute("href", href); + style.setAttribute("rel", "stylesheet") + } + style.setAttribute("type", "text/css"); + head.appendChild(style); + return(style) + } + function addStyleSheet(document) { + var head = (document.getElementsByTagName("head")[0]), style = document.createElementNS(head.namespaceURI, "style"), text = ""; + style.setAttribute("type", "text/css"); + style.setAttribute("media", "screen, print, handheld, projection"); + odf.Namespaces.forEachPrefix(function(prefix, ns) { + text += "@namespace " + prefix + " url(" + ns + ");\n" + }); + text += "@namespace webodfhelper url(" + webodfhelperns + ");\n"; + style.appendChild(document.createTextNode(text)); + head.appendChild(style); + return(style) + } + 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; + function loadImages(container, odffragment, stylesheet) { + var i, images, node; + function loadImage(name, container, node, stylesheet) { + loadingQueue.addToQueue(function() { + setImage(name, container, node, stylesheet) + }) + } + images = odffragment.getElementsByTagNameNS(drawns, "image"); + for(i = 0;i < images.length;i += 1) { + node = (images.item(i)); + loadImage("image" + String(i), container, node, stylesheet) + } + } + function loadVideos(container, odffragment) { + var i, plugins, node; + function loadVideo(container, node) { + loadingQueue.addToQueue(function() { + setVideo(container, node) + }) + } + plugins = odffragment.getElementsByTagNameNS(drawns, "plugin"); + for(i = 0;i < plugins.length;i += 1) { + node = (plugins.item(i)); + loadVideo(container, node) + } + } + function addEventListener(eventType, eventHandler) { + var handlers; + if(eventHandlers.hasOwnProperty(eventType)) { + handlers = eventHandlers[eventType] + }else { + handlers = eventHandlers[eventType] = [] + } + if(eventHandler && handlers.indexOf(eventHandler) === -1) { + handlers.push(eventHandler) + } + } + function fireEvent(eventType, args) { + if(!eventHandlers.hasOwnProperty(eventType)) { + return + } + var handlers = eventHandlers[eventType], i; + for(i = 0;i < handlers.length;i += 1) { + handlers[i].apply(null, args) + } + } + function fixContainerSize() { + var odfdoc = sizer.firstChild; + 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 + ")"; + element.style.width = Math.round(zoomLevel * sizer.offsetWidth) + "px"; + element.style.height = Math.round(zoomLevel * sizer.offsetHeight) + "px" + } + 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.appendChild(odfnode); + element.appendChild(sizer); + annotationsPane = (doc.createElementNS(element.namespaceURI, "div")); + annotationsPane.id = "annotationsPane"; + shadowContent = doc.createElementNS(element.namespaceURI, "div"); + shadowContent.id = "shadowContent"; + shadowContent.style.position = "absolute"; + shadowContent.style.top = 0; + shadowContent.style.left = 0; + container.getContentElement().appendChild(shadowContent); + 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); + loadImages(container, odfnode.body, css); + loadVideos(container, odfnode.body); + loadLists(odfnode.body, css, element.namespaceURI); + sizer.insertBefore(shadowContent, sizer.firstChild); + fixContainerSize() + } + 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}) + } + annotationViewManager.rerenderAnnotations() + } + function handleAnnotations(odfnode) { + if(allowAnnotations) { + if(!annotationsPane.parentNode) { + sizer.appendChild(annotationsPane); + fixContainerSize() + } + if(annotationViewManager) { + annotationViewManager.forgetAnnotations() + } + annotationViewManager = new gui.AnnotationViewManager(self, odfnode.body, annotationsPane); + modifyAnnotations(odfnode.body) + }else { + if(annotationsPane.parentNode) { + sizer.removeChild(annotationsPane); + annotationViewManager.forgetAnnotations(); + fixContainerSize() + } + } + } + function refreshOdf(suppressEvent) { + function callback() { + clear(element); + element.style.display = "inline-block"; + var odfnode = odfcontainer.rootElement; + element.ownerDocument.importNode(odfnode, true); + formatting.setOdfContainer(odfcontainer); + handleFonts(odfcontainer, fontcss); + handleStyles(odfcontainer, formatting, stylesxmlcss); + handleContent(odfcontainer, odfnode); + handleAnnotations(odfnode); + if(!suppressEvent) { + fireEvent("statereadychange", [odfcontainer]) + } + } + if(odfcontainer.state === odf.OdfContainer.DONE) { + callback() + }else { + runtime.log("WARNING: refreshOdf called but ODF was not DONE."); + runtime.setTimeout(function later_cb() { + if(odfcontainer.state === odf.OdfContainer.DONE) { + callback() + }else { + runtime.log("will be back later..."); + runtime.setTimeout(later_cb, 500) + } + }, 100) + } + } + this.refreshCSS = function() { + handleStyles(odfcontainer, formatting, stylesxmlcss); + fixContainerSize() + }; + this.refreshSize = function() { + fixContainerSize() + }; + this.odfContainer = function() { + return odfcontainer + }; + this.setOdfContainer = function(container, suppressEvent) { + odfcontainer = container; + refreshOdf(suppressEvent === true) + }; + function load(url) { + loadingQueue.clearQueue(); + element.innerHTML = runtime.tr("Loading") + " " + url + "..."; + element.removeAttribute("style"); + odfcontainer = new odf.OdfContainer(url, function(container) { + odfcontainer = container; + refreshOdf(false) + }) + } + this["load"] = load; + this.load = load; + this.save = function(callback) { + odfcontainer.save(callback) + }; + this.addListener = function(eventName, handler) { + switch(eventName) { + case "click": + listenEvent(element, eventName, handler); + break; + default: + addEventListener(eventName, handler); + break + } + }; + this.getFormatting = function() { + return formatting + }; + this.getAnnotationViewManager = function() { + return annotationViewManager + }; + this.refreshAnnotations = function() { + handleAnnotations(odfcontainer.rootElement) + }; + this.rerenderAnnotations = function() { + if(annotationViewManager) { + annotationViewManager.rerenderAnnotations() + } + }; + this.getSizer = function() { + return sizer + }; + this.enableAnnotations = function(allow) { + if(allow !== allowAnnotations) { + allowAnnotations = allow; + if(odfcontainer) { + handleAnnotations(odfcontainer.rootElement) + } + } + }; + this.addAnnotation = function(annotation) { + if(annotationViewManager) { + annotationViewManager.addAnnotation(annotation) + } + }; + this.forgetAnnotations = function() { + if(annotationViewManager) { + annotationViewManager.forgetAnnotations() + } + }; + this.setZoomLevel = function(zoom) { + zoomLevel = zoom; + fixContainerSize() + }; + this.getZoomLevel = function() { + return zoomLevel + }; + this.fitToContainingElement = function(width, height) { + var realWidth = element.offsetWidth / zoomLevel, realHeight = element.offsetHeight / zoomLevel; + zoomLevel = width / realWidth; + if(height / realHeight < zoomLevel) { + zoomLevel = height / realHeight + } + fixContainerSize() + }; + this.fitToWidth = function(width) { + var realWidth = element.offsetWidth / zoomLevel; + zoomLevel = width / realWidth; + fixContainerSize() + }; + this.fitSmart = function(width, height) { + var realWidth, realHeight, newScale; + realWidth = element.offsetWidth / zoomLevel; + realHeight = element.offsetHeight / zoomLevel; + newScale = width / realWidth; + if(height !== undefined) { + if(height / realHeight < newScale) { + newScale = height / realHeight + } + } + zoomLevel = Math.min(1, newScale); + fixContainerSize() + }; + this.fitToHeight = function(height) { + var realHeight = element.offsetHeight / zoomLevel; + zoomLevel = height / realHeight; + fixContainerSize() + }; + this.showFirstPage = function() { + pageSwitcher.showFirstPage() + }; + this.showNextPage = function() { + pageSwitcher.showNextPage() + }; + this.showPreviousPage = function() { + pageSwitcher.showPreviousPage() + }; + this.showPage = function(n) { + pageSwitcher.showPage(n); + fixContainerSize() + }; + this.getElement = function() { + return element + }; + this.addCssForFrameWithImage = function(frame) { + var frameName = frame.getAttributeNS(drawns, "name"), fc = frame.firstElementChild; + setDrawElementPosition(frameName, frame, (positioncss.sheet)); + if(fc) { + setImage(frameName + "img", odfcontainer, fc, (positioncss.sheet)) + } + }; + this.destroy = function(callback) { + var head = (doc.getElementsByTagName("head")[0]); + if(annotationsPane && annotationsPane.parentNode) { + annotationsPane.parentNode.removeChild(annotationsPane) + } + if(sizer) { + element.removeChild(sizer); + sizer = null + } + head.removeChild(webodfcss); + head.removeChild(fontcss); + head.removeChild(stylesxmlcss); + head.removeChild(positioncss); + pageSwitcher.destroy(callback) + }; + function init() { + webodfcss = addWebODFStyleSheet(doc); + pageSwitcher = new PageSwitcher(addStyleSheet(doc)); + fontcss = addStyleSheet(doc); + stylesxmlcss = addStyleSheet(doc); + positioncss = addStyleSheet(doc) + } + init() + } +})(); +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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"); +runtime.loadClass("odf.OdfUtils"); +gui.StyleHelper = function StyleHelper(formatting) { + var domUtils = new core.DomUtils, 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; + this.applyStyle = function(memberId, range, info) { + var nextTextNodes = domUtils.splitBoundaries(range), textNodes = odfUtils.getTextNodes(range, false), limits; + limits = {startContainer:range.startContainer, startOffset:range.startOffset, endContainer:range.endContainer, endOffset:range.endOffset}; + formatting.applyStyle(memberId, textNodes, limits, info); + nextTextNodes.forEach(domUtils.normalizeTextNodes) + }; + 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"]) + } +}; 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, @@ -2279,755 +10171,152 @@ core.RawDeflate = function() { }; this.deflate = zip_deflate }; -core.ByteArray = function ByteArray(data) { - this.pos = 0; - this.data = data; - this.readUInt32LE = function() { - this.pos += 4; - var d = this.data, pos = this.pos; - return d[--pos] << 24 | d[--pos] << 16 | d[--pos] << 8 | d[--pos] +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.readUInt16LE = function() { - this.pos += 2; - var d = this.data, pos = this.pos; - return d[--pos] << 8 | d[--pos] + 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 } }; -core.ByteArrayWriter = function ByteArrayWriter(encoding) { - var self = this, length = 0, bufferSize = 1024, data = new Uint8Array(new ArrayBuffer(bufferSize)); - function expand(extraLength) { - var newData; - if(extraLength > bufferSize - length) { - bufferSize = Math.max(2 * bufferSize, length + extraLength); - newData = new Uint8Array(new ArrayBuffer(bufferSize)); - newData.set(data); - data = newData - } - } - this.appendByteArrayWriter = function(writer) { - self.appendByteArray(writer.getByteArray()) - }; - this.appendByteArray = function(array) { - var l = array.length; - expand(l); - data.set(array, length); - length += l - }; - this.appendArray = function(array) { - var l = array.length; - expand(l); - data.set(array, length); - length += l - }; - this.appendUInt16LE = function(value) { - self.appendArray([value & 255, value >> 8 & 255]) - }; - this.appendUInt32LE = function(value) { - self.appendArray([value & 255, value >> 8 & 255, value >> 16 & 255, value >> 24 & 255]) - }; - this.appendString = function(string) { - self.appendByteArray(runtime.byteArrayFromString(string, encoding)) - }; - this.getLength = function() { - return length - }; - this.getByteArray = function() { - var a = new Uint8Array(new ArrayBuffer(length)); - a.set(data.subarray(0, length)); - return a - } -}; -core.RawInflate = function RawInflate() { - var zip_WSIZE = 32768; - var zip_STORED_BLOCK = 0; - var zip_STATIC_TREES = 1; - var zip_DYN_TREES = 2; - var zip_lbits = 9; - var zip_dbits = 6; - var zip_INBUFSIZ = 32768; - var zip_INBUF_EXTRA = 64; - var zip_slide; - var zip_wp; - var zip_fixed_tl = null; - var zip_fixed_td; - var zip_fixed_bl, fixed_bd; - var zip_bit_buf; - var zip_bit_len; - var zip_method; - var zip_eof; - var zip_copy_leng; - var zip_copy_dist; - var zip_tl, zip_td; - var zip_bl, zip_bd; - var zip_inflate_data; - var zip_inflate_pos; - var zip_MASK_BITS = new Array(0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535); - var zip_cplens = new Array(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); - var zip_cplext = new Array(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); - var zip_cpdist = new Array(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); - var zip_cpdext = new Array(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); - var zip_border = new Array(16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15); - var zip_HuftList = function() { - this.next = null; - this.list = null - }; - var zip_HuftNode = function() { - this.e = 0; - this.b = 0; - this.n = 0; - this.t = null - }; - var zip_HuftBuild = function(b, n, s, d, e, mm) { - this.BMAX = 16; - this.N_MAX = 288; - this.status = 0; - this.root = null; - this.m = 0; - var a; - var c = new Array(this.BMAX + 1); - var el; - var f; - var g; - var h; - var i; - var j; - var k; - var lx = new Array(this.BMAX + 1); - var p; - var pidx; - var q; - var r = new zip_HuftNode; - var u = new Array(this.BMAX); - var v = new Array(this.N_MAX); - var w; - var x = new Array(this.BMAX + 1); - var xp; - var y; - var z; - var o; - var tail; - tail = this.root = null; - for(i = 0;i < c.length;i++) { - c[i] = 0 - } - for(i = 0;i < lx.length;i++) { - lx[i] = 0 - } - for(i = 0;i < u.length;i++) { - u[i] = null - } - for(i = 0;i < v.length;i++) { - v[i] = 0 - } - for(i = 0;i < x.length;i++) { - x[i] = 0 - } - el = n > 256 ? b[256] : this.BMAX; - p = b; - pidx = 0; - i = n; - do { - c[p[pidx]]++; - pidx++ - }while(--i > 0); - if(c[0] == n) { - this.root = null; - this.m = 0; - this.status = 0; - return - } - for(j = 1;j <= this.BMAX;j++) { - if(c[j] != 0) { - break +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.") } - } - k = j; - if(mm < j) { - mm = j - } - for(i = this.BMAX;i != 0;i--) { - if(c[i] != 0) { - break - } - } - g = i; - if(mm > i) { - mm = i - } - for(y = 1 << j;j < i;j++, y <<= 1) { - if((y -= c[j]) < 0) { - this.status = 2; - this.m = mm; - return - } - } - if((y -= c[i]) < 0) { - this.status = 2; - this.m = mm; - return - } - c[i] += y; - x[1] = j = 0; - p = c; - pidx = 1; - xp = 2; - while(--i > 0) { - x[xp++] = j += p[pidx++] - } - p = b; - pidx = 0; - i = 0; - do { - if((j = p[pidx++]) != 0) { - v[x[j]++] = i - } - }while(++i < n); - n = x[g]; - x[0] = i = 0; - p = v; - pidx = 0; - h = -1; - w = lx[0] = 0; - q = null; - z = 0; - for(;k <= g;k++) { - a = c[k]; - while(a-- > 0) { - while(k > w + lx[1 + h]) { - w += lx[1 + h]; - h++; - z = (z = g - w) > mm ? mm : z; - if((f = 1 << (j = k - w)) > a + 1) { - f -= a + 1; - xp = k; - while(++j < z) { - if((f <<= 1) <= c[++xp]) { - break - } - f -= c[xp] - } - } - if(w + j > el && w < el) { - j = el - w - } - z = 1 << j; - lx[1 + h] = j; - q = new Array(z); - for(o = 0;o < z;o++) { - q[o] = new zip_HuftNode - } - if(tail == null) { - tail = this.root = new zip_HuftList - }else { - tail = tail.next = new zip_HuftList - } - tail.next = null; - tail.list = q; - u[h] = q; - if(h > 0) { - x[h] = i; - r.b = lx[h]; - r.e = 16 + j; - r.t = q; - j = (i & (1 << w) - 1) >> w - lx[h]; - u[h - 1][j].e = r.e; - u[h - 1][j].b = r.b; - u[h - 1][j].n = r.n; - u[h - 1][j].t = r.t - } - } - r.b = k - w; - if(pidx >= n) { - r.e = 99 - }else { - if(p[pidx] < s) { - r.e = p[pidx] < 256 ? 16 : 15; - r.n = p[pidx++] - }else { - r.e = e[p[pidx] - s]; - r.n = d[p[pidx++] - s] - } - } - f = 1 << k - w; - for(j = i >> w;j < z;j += f) { - q[j].e = r.e; - q[j].b = r.b; - q[j].n = r.n; - q[j].t = r.t - } - for(j = 1 << k - 1;(i & j) != 0;j >>= 1) { - i ^= j - } - i ^= j; - while((i & (1 << w) - 1) != x[h]) { - w -= lx[h]; - h-- - } - } - } - this.m = lx[1]; - this.status = y != 0 && g != 1 ? 1 : 0 - }; - var zip_GET_BYTE = function() { - if(zip_inflate_data.length == zip_inflate_pos) { - return-1 - } - return zip_inflate_data[zip_inflate_pos++] - }; - var zip_NEEDBITS = function(n) { - while(zip_bit_len < n) { - zip_bit_buf |= zip_GET_BYTE() << zip_bit_len; - zip_bit_len += 8 - } - }; - var zip_GETBITS = function(n) { - return zip_bit_buf & zip_MASK_BITS[n] - }; - var zip_DUMPBITS = function(n) { - zip_bit_buf >>= n; - zip_bit_len -= n - }; - var zip_inflate_codes = function(buff, off, size) { - var e; - var t; - var n; - if(size == 0) { - return 0 - } - n = 0; - for(;;) { - zip_NEEDBITS(zip_bl); - t = zip_tl.list[zip_GETBITS(zip_bl)]; - e = t.e; - while(e > 16) { - if(e == 99) { - return-1 - } - zip_DUMPBITS(t.b); - e -= 16; - zip_NEEDBITS(e); - t = t.t[zip_GETBITS(e)]; - e = t.e - } - zip_DUMPBITS(t.b); - if(e == 16) { - zip_wp &= zip_WSIZE - 1; - buff[off + n++] = zip_slide[zip_wp++] = t.n; - if(n == size) { - return size - } - continue - } - if(e == 15) { - break - } - zip_NEEDBITS(e); - zip_copy_leng = t.n + zip_GETBITS(e); - zip_DUMPBITS(e); - zip_NEEDBITS(zip_bd); - t = zip_td.list[zip_GETBITS(zip_bd)]; - e = t.e; - while(e > 16) { - if(e == 99) { - return-1 - } - zip_DUMPBITS(t.b); - e -= 16; - zip_NEEDBITS(e); - t = t.t[zip_GETBITS(e)]; - e = t.e - } - zip_DUMPBITS(t.b); - zip_NEEDBITS(e); - zip_copy_dist = zip_wp - t.n - zip_GETBITS(e); - zip_DUMPBITS(e); - while(zip_copy_leng > 0 && n < size) { - zip_copy_leng--; - zip_copy_dist &= zip_WSIZE - 1; - zip_wp &= zip_WSIZE - 1; - buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++] - } - if(n == size) { - return size - } - } - zip_method = -1; - return n - }; - var zip_inflate_stored = function(buff, off, size) { - var n; - n = zip_bit_len & 7; - zip_DUMPBITS(n); - zip_NEEDBITS(16); - n = zip_GETBITS(16); - zip_DUMPBITS(16); - zip_NEEDBITS(16); - if(n != (~zip_bit_buf & 65535)) { - return-1 - } - zip_DUMPBITS(16); - zip_copy_leng = n; - n = 0; - while(zip_copy_leng > 0 && n < size) { - zip_copy_leng--; - zip_wp &= zip_WSIZE - 1; - zip_NEEDBITS(8); - buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); - zip_DUMPBITS(8) - } - if(zip_copy_leng == 0) { - zip_method = -1 - } - return n - }; - var zip_fixed_bd; - var zip_inflate_fixed = function(buff, off, size) { - if(zip_fixed_tl == null) { - var i; - var l = new Array(288); - var h; - for(i = 0;i < 144;i++) { - l[i] = 8 - } - for(;i < 256;i++) { - l[i] = 9 - } - for(;i < 280;i++) { - l[i] = 7 - } - for(;i < 288;i++) { - l[i] = 8 - } - zip_fixed_bl = 7; - h = new zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext, zip_fixed_bl); - if(h.status != 0) { - alert("HufBuild error: " + h.status); - return-1 - } - zip_fixed_tl = h.root; - zip_fixed_bl = h.m; - for(i = 0;i < 30;i++) { - l[i] = 5 - } - zip_fixed_bd = 5; - h = new zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd); - if(h.status > 1) { - zip_fixed_tl = null; - alert("HufBuild error: " + h.status); - return-1 - } - zip_fixed_td = h.root; - zip_fixed_bd = h.m - } - zip_tl = zip_fixed_tl; - zip_td = zip_fixed_td; - zip_bl = zip_fixed_bl; - zip_bd = zip_fixed_bd; - return zip_inflate_codes(buff, off, size) - }; - var zip_inflate_dynamic = function(buff, off, size) { - var i; - var j; - var l; - var n; - var t; - var nb; - var nl; - var nd; - var ll = new Array(286 + 30); - var h; - for(i = 0;i < ll.length;i++) { - ll[i] = 0 - } - zip_NEEDBITS(5); - nl = 257 + zip_GETBITS(5); - zip_DUMPBITS(5); - zip_NEEDBITS(5); - nd = 1 + zip_GETBITS(5); - zip_DUMPBITS(5); - zip_NEEDBITS(4); - nb = 4 + zip_GETBITS(4); - zip_DUMPBITS(4); - if(nl > 286 || nd > 30) { - return-1 - } - for(j = 0;j < nb;j++) { - zip_NEEDBITS(3); - ll[zip_border[j]] = zip_GETBITS(3); - zip_DUMPBITS(3) - } - for(;j < 19;j++) { - ll[zip_border[j]] = 0 - } - zip_bl = 7; - h = new zip_HuftBuild(ll, 19, 19, null, null, zip_bl); - if(h.status != 0) { - return-1 - } - zip_tl = h.root; - zip_bl = h.m; - n = nl + nd; - i = l = 0; - while(i < n) { - zip_NEEDBITS(zip_bl); - t = zip_tl.list[zip_GETBITS(zip_bl)]; - j = t.b; - zip_DUMPBITS(j); - j = t.n; - if(j < 16) { - ll[i++] = l = j + if(odfcontainer.state === odf.OdfContainer.DONE) { + odfcontainer.saveAs(outputfilepath, function(err) { + callback(err) + }) }else { - if(j == 16) { - zip_NEEDBITS(2); - j = 3 + zip_GETBITS(2); - zip_DUMPBITS(2); - if(i + j > n) { - return-1 - } - while(j-- > 0) { - ll[i++] = l - } - }else { - if(j == 17) { - zip_NEEDBITS(3); - j = 3 + zip_GETBITS(3); - zip_DUMPBITS(3); - if(i + j > n) { - return-1 - } - while(j-- > 0) { - ll[i++] = 0 - } - l = 0 - }else { - zip_NEEDBITS(7); - j = 11 + zip_GETBITS(7); - zip_DUMPBITS(7); - if(i + j > n) { - return-1 - } - while(j-- > 0) { - ll[i++] = 0 - } - l = 0 - } - } + callback("Document was not completely loaded.") } } - zip_bl = zip_lbits; - h = new zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl); - if(zip_bl == 0) { - h.status = 1 - } - if(h.status != 0) { - return-1 - } - zip_tl = h.root; - zip_bl = h.m; - for(i = 0;i < nd;i++) { - ll[i] = ll[i + nl] - } - zip_bd = zip_dbits; - h = new zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd); - zip_td = h.root; - zip_bd = h.m; - if(zip_bd == 0 && nl > 257) { - return-1 - } - if(h.status != 0) { - return-1 - } - return zip_inflate_codes(buff, off, size) + var odfcontainer = new odf.OdfContainer(inputfilepath, onready); + return odfcontainer }; - var zip_inflate_start = function() { - var i; - if(zip_slide == null) { - zip_slide = new Array(2 * zip_WSIZE) + this.render = function(inputfilepath, document, callback) { + var body = document.getElementsByTagName("body")[0], odfcanvas; + while(body.firstChild) { + body.removeChild(body.firstChild) } - zip_wp = 0; - zip_bit_buf = 0; - zip_bit_len = 0; - zip_method = -1; - zip_eof = false; - zip_copy_leng = zip_copy_dist = 0; - zip_tl = null - }; - var zip_inflate_internal = function(buff, off, size) { - var n, i; - n = 0; - while(n < size) { - if(zip_eof && zip_method == -1) { - return n - } - if(zip_copy_leng > 0) { - if(zip_method != zip_STORED_BLOCK) { - while(zip_copy_leng > 0 && n < size) { - zip_copy_leng--; - zip_copy_dist &= zip_WSIZE - 1; - zip_wp &= zip_WSIZE - 1; - buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++] - } - }else { - while(zip_copy_leng > 0 && n < size) { - zip_copy_leng--; - zip_wp &= zip_WSIZE - 1; - zip_NEEDBITS(8); - buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); - zip_DUMPBITS(8) - } - if(zip_copy_leng == 0) { - zip_method = -1 - } - } - if(n == size) { - return n - } - } - if(zip_method == -1) { - if(zip_eof) { - break - } - zip_NEEDBITS(1); - if(zip_GETBITS(1) != 0) { - zip_eof = true - } - zip_DUMPBITS(1); - zip_NEEDBITS(2); - zip_method = zip_GETBITS(2); - zip_DUMPBITS(2); - zip_tl = null; - zip_copy_leng = 0 - } - switch(zip_method) { - case 0: - i = zip_inflate_stored(buff, off + n, size - n); - break; - case 1: - if(zip_tl != null) { - i = zip_inflate_codes(buff, off + n, size - n) - }else { - i = zip_inflate_fixed(buff, off + n, size - n) - } - break; - case 2: - if(zip_tl != null) { - i = zip_inflate_codes(buff, off + n, size - n) - }else { - i = zip_inflate_dynamic(buff, off + n, size - n) - } - break; - default: - i = -1; - break - } - if(i == -1) { - if(zip_eof) { - return 0 - } - return-1 - } - n += i - } - return n - }; - var zip_inflate = function(data, size) { - var i, j; - zip_inflate_start(); - zip_inflate_data = data; - zip_inflate_pos = 0; - var buff = new Uint8Array(new ArrayBuffer(size)); - zip_inflate_internal(buff, 0, size); - zip_inflate_data = null; - return buff - }; - this.inflate = zip_inflate + odfcanvas = new odf.OdfCanvas(body); + odfcanvas.addListener("statereadychange", function(err) { + callback(err) + }); + odfcanvas.load(inputfilepath) + } }; /* - Copyright (C) 2012 KO GmbH + Copyright (C) 2013 KO GmbH @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. + 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 this code. If not, see . - - 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. + along with WebODF. If not, see . @licend + @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -core.LoopWatchDog = function LoopWatchDog(timeout, maxChecks) { - var startTime = Date.now(), checks = 0; - function check() { - var t; - if(timeout) { - t = Date.now(); - if(t - startTime > timeout) { - runtime.log("alert", "watchdog timeout"); - throw"timeout!"; - } - } - if(maxChecks > 0) { - checks += 1; - if(checks > maxChecks) { - runtime.log("alert", "watchdog loop overflow"); - throw"loop overflow"; - } - } +ops.Member = function Member(memberId, properties) { + var props = {}; + function getMemberId() { + return memberId } - this.check = check -}; -core.Utils = function Utils() { - function hashString(value) { - var hash = 0, i, l; - for(i = 0, l = value.length;i < l;i += 1) { - hash = (hash << 5) - hash + value.charCodeAt(i); - hash |= 0 - } - return hash + function getProperties() { + return props } - this.hashString = hashString; - function mergeObjects(destination, source) { - if(source && Array.isArray(source)) { - destination = (destination || []).concat(source.map(function(obj) { - return mergeObjects({}, obj) - })) - }else { - if(source && typeof source === "object") { - destination = destination || {}; - Object.keys(source).forEach(function(p) { - destination[p] = mergeObjects(destination[p], source[p]) - }) - }else { - destination = source + 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] } - } - return destination + }) } - this.mergeObjects = mergeObjects + 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() }; /* @@ -3066,1661 +10355,311 @@ core.Utils = function Utils() { @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ +runtime.loadClass("core.DomUtils"); +runtime.loadClass("core.PositionFilter"); +runtime.loadClass("odf.OdfUtils"); (function() { - var browserQuirks; - function getBrowserQuirks() { - var range, directBoundingRect, rangeBoundingRect, testContainer, testElement, detectedQuirks, window, document; - if(browserQuirks === undefined) { - window = runtime.getWindow(); - document = window && window.document; - browserQuirks = {rangeBCRIgnoresElementBCR:false, unscaledRangeClientRects:false}; - if(document) { - testContainer = document.createElement("div"); - testContainer.style.position = "absolute"; - testContainer.style.left = "-99999px"; - testContainer.style.transform = "scale(2)"; - testContainer.style["-webkit-transform"] = "scale(2)"; - testElement = document.createElement("div"); - testContainer.appendChild(testElement); - document.body.appendChild(testContainer); - range = document.createRange(); - range.selectNode(testElement); - browserQuirks.rangeBCRIgnoresElementBCR = range.getClientRects().length === 0; - testElement.appendChild(document.createTextNode("Rect transform test")); - directBoundingRect = testElement.getBoundingClientRect(); - rangeBoundingRect = range.getBoundingClientRect(); - browserQuirks.unscaledRangeClientRects = Math.abs(directBoundingRect.height - rangeBoundingRect.height) > 2; - range.detach(); - document.body.removeChild(testContainer); - detectedQuirks = Object.keys(browserQuirks).map(function(quirk) { - return quirk + ":" + String(browserQuirks[quirk]) - }).join(", "); - runtime.log("Detected browser quirks - " + detectedQuirks) - } - } - return browserQuirks - } - core.DomUtils = function DomUtils() { - var sharedRange = null; - function getSharedRange(doc) { - var range; - if(sharedRange) { - range = sharedRange - }else { - sharedRange = range = (doc.createRange()) - } - return range - } - function findStablePoint(container, offset) { - var c = container; - if(offset < c.childNodes.length) { - c = c.childNodes.item(offset); - offset = 0; - while(c.firstChild) { - c = c.firstChild - } - }else { - while(c.lastChild) { - c = c.lastChild; - offset = c.nodeType === Node.TEXT_NODE ? c.textContent.length : c.childNodes.length + 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) { + this.steps = steps; + this.node = paragraphNode; + function positionInContainer(node) { + var position = 0; + while(node && node.previousSibling) { + position += 1; + node = node.previousSibling } + return position } - return{container:c, offset:offset} - } - function splitBoundaries(range) { - var modifiedNodes = [], end, splitStart, node, text; - if(range.startContainer.nodeType === Node.TEXT_NODE || range.endContainer.nodeType === Node.TEXT_NODE) { - end = range.endContainer && findStablePoint(range.endContainer, range.endOffset); - range.setEnd(end.container, end.offset); - node = range.endContainer; - if(range.endOffset !== 0 && node.nodeType === Node.TEXT_NODE) { - text = (node); - if(range.endOffset !== text.length) { - modifiedNodes.push(text.splitText(range.endOffset)); - modifiedNodes.push(text) - } - } - node = range.startContainer; - if(range.startOffset !== 0 && node.nodeType === Node.TEXT_NODE) { - text = (node); - if(range.startOffset !== text.length) { - splitStart = text.splitText(range.startOffset); - modifiedNodes.push(text); - modifiedNodes.push(splitStart); - range.setStart(splitStart, 0) - } - } - } - return modifiedNodes - } - this.splitBoundaries = splitBoundaries; - function containsRange(container, insideRange) { - return container.compareBoundaryPoints(Range.START_TO_START, insideRange) <= 0 && container.compareBoundaryPoints(Range.END_TO_END, insideRange) >= 0 - } - this.containsRange = containsRange; - function rangesIntersect(range1, range2) { - 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) - }else { - if(filterResult === NodeFilter.FILTER_REJECT) { + this.setIteratorPosition = function(iterator) { + iterator.setUnfilteredPosition(paragraphNode.parentNode, positionInContainer(paragraphNode)); + do { + if(filter.acceptPosition(iterator) === FILTER_ACCEPT) { break } - } - n = n.parentNode + }while(iterator.nextPosition()) } - elements.reverse(); - n = treeWalker.nextNode(); - while(n) { - elements.push(n); - n = treeWalker.nextNode() - } - return elements } - this.getNodesInRange = getNodesInRange; - function mergeTextNodes(node, nextNode) { - var mergedNode = null, text, nextText; - if(node.nodeType === Node.TEXT_NODE) { - text = (node); - if(text.length === 0) { - text.parentNode.removeChild(text); - if(nextNode.nodeType === Node.TEXT_NODE) { - mergedNode = nextNode + function RootBookmark(steps, rootNode) { + this.steps = steps; + this.node = rootNode; + this.setIteratorPosition = function(iterator) { + iterator.setUnfilteredPosition(rootNode, 0); + do { + if(filter.acceptPosition(iterator) === FILTER_ACCEPT) { + break } - }else { - if(nextNode.nodeType === Node.TEXT_NODE) { - nextText = (nextNode); - text.appendData(nextText.data); - nextNode.parentNode.removeChild(nextNode) - } - mergedNode = node - } - } - return mergedNode - } - function normalizeTextNodes(node) { - if(node && node.nextSibling) { - node = mergeTextNodes(node, node.nextSibling) - } - if(node && node.previousSibling) { - mergeTextNodes(node.previousSibling, node) + }while(iterator.nextPosition()) } } - this.normalizeTextNodes = normalizeTextNodes; - function rangeContainsNode(limits, node) { - var range = node.ownerDocument.createRange(), nodeRange = node.ownerDocument.createRange(), result; - range.setStart(limits.startContainer, limits.startOffset); - range.setEnd(limits.endContainer, limits.endOffset); - nodeRange.selectNodeContents(node); - result = containsRange(range, nodeRange); - range.detach(); - nodeRange.detach(); - return result + function getBucket(steps) { + return Math.floor(steps / bucketSize) * bucketSize } - this.rangeContainsNode = rangeContainsNode; - function mergeIntoParent(targetNode) { - var parent = targetNode.parentNode; - while(targetNode.firstChild) { - parent.insertBefore(targetNode.firstChild, targetNode) - } - parent.removeChild(targetNode); - return parent + function getDestinationBucket(steps) { + return Math.ceil(steps / bucketSize) * bucketSize } - this.mergeIntoParent = mergeIntoParent; - function removeUnwantedNodes(targetNode, shouldRemove) { - var parent = targetNode.parentNode, node = targetNode.firstChild, next; - while(node) { - next = node.nextSibling; - removeUnwantedNodes(node, shouldRemove); - node = next - } - if(shouldRemove(targetNode)) { - parent = mergeIntoParent(targetNode) - } - return parent + function clearNodeId(node) { + node.removeAttributeNS(coordinatens, "nodeId") } - this.removeUnwantedNodes = removeUnwantedNodes; - function getElementsByTagNameNS(node, namespace, tagName) { - return Array.prototype.slice.call(node.getElementsByTagNameNS(namespace, tagName)) + function getNodeId(node) { + return node.nodeType === Node.ELEMENT_NODE && node.getAttributeNS(coordinatens, "nodeId") } - this.getElementsByTagNameNS = getElementsByTagNameNS; - function rangeIntersectsNode(range, node) { - var nodeRange = node.ownerDocument.createRange(), result; - nodeRange.selectNodeContents(node); - result = rangesIntersect(range, nodeRange); - nodeRange.detach(); - return result + function setNodeId(node) { + var nodeId = nextNodeId; + node.setAttributeNS(coordinatens, "nodeId", nodeId.toString()); + nextNodeId += 1; + return nodeId } - this.rangeIntersectsNode = rangeIntersectsNode; - function containsNode(parent, descendant) { - return parent === descendant || (parent).contains((descendant)) + function isValidBookmarkForNode(node, bookmark) { + return bookmark.node === node } - this.containsNode = containsNode; - 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 - } - var comparison = c1.compareDocumentPosition(c2); - if(comparison === 2) { - comparison = -1 + function getNodeBookmark(node, steps) { + var nodeId = getNodeId(node) || setNodeId(node), existingBookmark; + existingBookmark = nodeToBookmark[nodeId]; + if(!existingBookmark) { + existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node) }else { - if(comparison === 4) { - comparison = 1 + if(!isValidBookmarkForNode(node, existingBookmark)) { + runtime.log("Cloned node detected. Creating new bookmark"); + nodeId = setNodeId(node); + existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(steps, node) }else { - if(comparison === 10) { - o1 = getPositionInContainingNode(c1, c2); - comparison = o1 < o2 ? 1 : -1 - }else { - o2 = getPositionInContainingNode(c2, c1); - comparison = o2 < o1 ? -1 : 1 + existingBookmark.steps = steps + } + } + return existingBookmark + } + function isFirstPositionInParagraph(node, offset) { + return offset === 0 && odfUtils.isParagraph(node) + } + 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 } } } - return comparison - } - this.comparePoints = comparePoints; - function adaptRangeDifferenceToZoomLevel(inputNumber, zoomLevel) { - if(getBrowserQuirks().unscaledRangeClientRects) { - return inputNumber - } - return inputNumber / zoomLevel - } - this.adaptRangeDifferenceToZoomLevel = adaptRangeDifferenceToZoomLevel; - function getBoundingClientRect(node) { - var doc = (node.ownerDocument), quirks = getBrowserQuirks(), range, element; - if(quirks.unscaledRangeClientRects === false || quirks.rangeBCRIgnoresElementBCR) { - if(node.nodeType === Node.ELEMENT_NODE) { - element = (node); - return element.getBoundingClientRect() + if(stablePoint) { + bookmark = getNodeBookmark(node, steps); + cacheBucket = getDestinationBucket(bookmark.steps); + existingCachePoint = stepToDomPoint[cacheBucket]; + if(!existingCachePoint || bookmark.steps > existingCachePoint.steps) { + stepToDomPoint[cacheBucket] = bookmark } } - range = getSharedRange(doc); - range.selectNode(node); - return range.getBoundingClientRect() - } - this.getBoundingClientRect = getBoundingClientRect; - function mapKeyValObjOntoNode(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(ns) { - element = node.getElementsByTagNameNS(ns, localName)[0]; - if(!element) { - element = node.ownerDocument.createElementNS(ns, key); - node.appendChild(element) - } - element.textContent = value - }else { - runtime.log("Key ignored: " + key) - } - }) - } - this.mapKeyValObjOntoNode = mapKeyValObjOntoNode; - function removeKeyElementsFromNode(node, propertyNames, nsResolver) { - propertyNames.forEach(function(propertyName) { - var parts = propertyName.split(":"), prefix = parts[0], localName = parts[1], ns = nsResolver(prefix), element; - if(ns) { - element = node.getElementsByTagNameNS(ns, localName)[0]; - if(element) { - element.parentNode.removeChild(element) - }else { - runtime.log("Element for " + propertyName + " not found.") - } - }else { - runtime.log("Property Name ignored: " + propertyName) - } - }) - } - this.removeKeyElementsFromNode = removeKeyElementsFromNode; - function getKeyValRepresentationOfNode(node, prefixResolver) { - var properties = {}, currentSibling = node.firstElementChild, prefix; - while(currentSibling) { - prefix = prefixResolver(currentSibling.namespaceURI); - if(prefix) { - properties[prefix + ":" + currentSibling.localName] = currentSibling.textContent - } - currentSibling = currentSibling.nextElementSibling + }; + this.setToClosestStep = function(steps, iterator) { + var cacheBucket = getBucket(steps), cachePoint; + while(!cachePoint && cacheBucket !== 0) { + cachePoint = stepToDomPoint[cacheBucket]; + cacheBucket -= bucketSize } - return properties - } - 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) { - element = node.getElementsByTagNameNS(ns, localName)[0] || node.ownerDocument.createElementNS(ns, key); - node.appendChild(element); - mapObjOntoNode(element, value, nsResolver) - }else { - if(ns) { - node.setAttributeNS(ns, key, value) + cachePoint = cachePoint || basePoint; + 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); + if(nodeId) { + bookmark = nodeToBookmark[nodeId]; + if(bookmark && !isValidBookmarkForNode(node, bookmark)) { + runtime.log("Cloned node detected. Creating new bookmark"); + bookmark = null; + clearNodeId(node) } } - }) - } - this.mapObjOntoNode = mapObjOntoNode; - function init(self) { - var appVersion, webKitOrSafari, ie, window = runtime.getWindow(); - if(window === null) { - return - } - appVersion = window.navigator.appVersion.toLowerCase(); - webKitOrSafari = appVersion.indexOf("chrome") === -1 && (appVersion.indexOf("applewebkit") !== -1 || appVersion.indexOf("safari") !== -1); - ie = appVersion.indexOf("msie"); - if(webKitOrSafari || ie) { - self.containsNode = containsNodeForBrokenWebKit + node = node.parentNode } + return bookmark } - init(this) - }; - return core.DomUtils -})(); -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 = null, 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) + this.setToClosestDomPoint = function(node, offset, iterator) { + var bookmark; + if(node === rootNode && offset === 0) { + bookmark = basePoint }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) 2013 KO GmbH - - @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 . - - 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.EventNotifier = function EventNotifier(eventIds) { - var eventListener = {}; - this.emit = function(eventId, args) { - var i, subscribers; - runtime.assert(eventListener.hasOwnProperty(eventId), 'unknown event fired "' + eventId + '"'); - subscribers = eventListener[eventId]; - for(i = 0;i < subscribers.length;i += 1) { - subscribers[i](args) - } - }; - 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.') - }; - this.unsubscribe = function(eventId, cb) { - var cbIndex; - runtime.assert(eventListener.hasOwnProperty(eventId), 'tried to unsubscribe from unknown event "' + eventId + '"'); - cbIndex = eventListener[eventId].indexOf(cb); - runtime.assert(cbIndex !== -1, 'tried to unsubscribe unknown callback from event "' + eventId + '"'); - if(cbIndex !== -1) { - eventListener[eventId].splice(cbIndex, 1) - } - runtime.log('event "' + eventId + '" unsubscribed.') - }; - function init() { - var i, eventId; - for(i = 0;i < eventIds.length;i += 1) { - eventId = eventIds[i]; - runtime.assert(!eventListener.hasOwnProperty(eventId), 'Duplicated event ids: "' + eventId + '" registered more than once.'); - eventListener[eventId] = [] - } - } - init() -}; -core.UnitTest = function UnitTest() { -}; -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 maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea"); - runtime.assert(!testarea, 'Unclean test environment, found a div with id "testarea".'); - testarea = maindoc.createElement("div"); - testarea.setAttribute("id", "testarea"); - maindoc.body.appendChild(testarea); - return testarea -}; -core.UnitTest.cleanupTestAreaDiv = function() { - var maindoc = runtime.getWindow().document, testarea = maindoc.getElementById("testarea"); - runtime.assert(!!testarea && testarea.parentNode === maindoc.body, 'Test environment broken, found no div with id "testarea" below body.'); - maindoc.body.removeChild(testarea) -}; -core.UnitTest.createOdtDocument = function(xml, namespaceMap) { - var xmlDoc = ""; - xmlDoc += " largestBookmark.steps ? bookmark : largestBookmark + }, basePoint) }else { - testFailed(a + " should be " + bv + " (of type " + typeof bv + "). Was " + av + " (of type " + typeof av + ").") - } - } - } - } - function shouldBeNonNull(t, a) { - var exception, av; - try { - av = eval(a) - }catch(e) { - exception = e - } - if(exception) { - testFailed(a + " should be non-null. Threw exception " + exception) - }else { - if(av !== null) { - testPassed(a + " is non-null.") - }else { - testFailed(a + " should be non-null. Was " + av) - } - } - } - function shouldBeNull(t, a) { - shouldBe(t, a, "null") - } - areObjectsEqual = function(a, b) { - var akeys = Object.keys(a), bkeys = Object.keys(b); - akeys.sort(); - bkeys.sort(); - return areArraysEqual(akeys, bkeys) && Object.keys(a).every(function(key) { - var aval = a[key], bval = b[key]; - if(!isResultCorrect(aval, bval)) { - testFailed(aval + " should be " + bval + " for key " + key); - return false - } - return true - }) - }; - this.areNodesEqual = areNodesEqual; - this.shouldBeNull = shouldBeNull; - this.shouldBeNonNull = shouldBeNonNull; - this.shouldBe = shouldBe; - this.countFailedTests = function() { - return failedTests - } -}; -core.UnitTester = function UnitTester() { - var failedTests = 0, results = {}; - function link(text, code) { - return"" + text + "" - } - 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, testNameString = "testName", inBrowser = runtime.type() === "BrowserRuntime"; - if(results.hasOwnProperty(testName)) { - runtime.log("Test " + testName + " has already run."); - return - } - if(inBrowser) { - runtime.log("Running " + link(testName, 'runSuite("' + testName + '");') + ": " + test.description() + "") - }else { - runtime.log("Running " + testName + ": " + test.description) - } - tests = test.tests(); - for(i = 0;i < tests.length;i += 1) { - t = tests[i]; - tname = Runtime.getFunctionName(t) || t[testNameString]; - if(testNames.length && testNames.indexOf(tname) === -1) { - continue - } - if(inBrowser) { - runtime.log("Running " + link(tname, 'runTest("' + testName + '","' + tname + '")') + "") - }else { - runtime.log("Running " + tname) - } - lastFailCount = runner.countFailedTests(); - test.setUp(); - t(); - test.tearDown(); - testResults[tname] = lastFailCount === runner.countFailedTests() - } - function runAsyncTests(todo) { - if(todo.length === 0) { - results[testName] = testResults; - failedTests += runner.countFailedTests(); - callback(); - return - } - t = todo[0]; - var fname = Runtime.getFunctionName(t); - runtime.log("Running " + fname); - lastFailCount = runner.countFailedTests(); - test.setUp(); - t(function() { - test.tearDown(); - testResults[fname] = lastFailCount === runner.countFailedTests(); - runAsyncTests(todo.slice(1)) - }) - } - runAsyncTests(test.asyncTests()) - }; - this.countFailedTests = function() { - return failedTests - }; - this.results = function() { - return results - } -}; -core.PositionIterator = function PositionIterator(root, whatToShow, filter, expandEntityReferences) { - var self = this, walker, currentPos, nodeFilter, TEXT_NODE = Node.TEXT_NODE, ELEMENT_NODE = Node.ELEMENT_NODE, FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT, FILTER_REJECT = NodeFilter.FILTER_REJECT; - function EmptyTextNodeFilter() { - this.acceptNode = function(node) { - var text = (node); - if(!node || node.nodeType === TEXT_NODE && text.length === 0) { - return FILTER_REJECT - } - return FILTER_ACCEPT - } - } - function FilteredEmptyTextNodeFilter(filter) { - this.acceptNode = function(node) { - var text = (node); - if(!node || node.nodeType === TEXT_NODE && text.length === 0) { - return FILTER_REJECT - } - return filter.acceptNode(node) - } - } - this.nextPosition = function() { - var currentNode = walker.currentNode, nodeType = currentNode.nodeType, text = (currentNode); - if(currentNode === root) { - return false - } - if(currentPos === 0 && nodeType === ELEMENT_NODE) { - if(walker.firstChild() === null) { - currentPos = 1 - } - }else { - if(nodeType === TEXT_NODE && currentPos + 1 < text.length) { - currentPos += 1 - }else { - if(walker.nextSibling() !== null) { - currentPos = 0 - }else { - if(walker.parentNode()) { - currentPos = 1 - }else { - return false - } - } - } - } - return true - }; - function setAtEnd() { - var text = (walker.currentNode), type = text.nodeType; - if(type === TEXT_NODE) { - currentPos = text.length - 1 - }else { - currentPos = type === ELEMENT_NODE ? 1 : 0 - } - } - function previousNode() { - if(walker.previousSibling() === null) { - if(!walker.parentNode() || walker.currentNode === root) { - walker.firstChild(); - return false - } - currentPos = 0 - }else { - setAtEnd() - } - return true - } - this.previousPosition = function() { - var moved = true, currentNode = walker.currentNode; - if(currentPos === 0) { - moved = previousNode() - }else { - if(currentNode.nodeType === TEXT_NODE) { - currentPos -= 1 - }else { - if(walker.lastChild() !== null) { - setAtEnd() - }else { - if(currentNode === root) { - moved = false - }else { - currentPos = 0 - } - } - } - } - return moved - }; - this.previousNode = previousNode; - this.container = function() { - var n = (walker.currentNode), t = n.nodeType; - if(currentPos === 0 && t !== TEXT_NODE) { - n = (n.parentNode) - } - return n - }; - this.rightNode = function() { - var n = walker.currentNode, text = (n), nodeType = n.nodeType; - if(nodeType === TEXT_NODE && currentPos === text.length) { - n = n.nextSibling; - while(n && nodeFilter(n) !== FILTER_ACCEPT) { - n = n.nextSibling - } - }else { - if(nodeType === ELEMENT_NODE && currentPos === 1) { - n = null - } - } - return n - }; - this.leftNode = function() { - var n = walker.currentNode; - if(currentPos === 0) { - n = n.previousSibling; - while(n && nodeFilter(n) !== FILTER_ACCEPT) { - n = n.previousSibling - } - }else { - if(n.nodeType === ELEMENT_NODE) { - n = n.lastChild; - while(n && nodeFilter(n) !== FILTER_ACCEPT) { - n = n.previousSibling - } - } - } - return n - }; - this.getCurrentNode = function() { - var n = (walker.currentNode); - return n - }; - this.unfilteredDomOffset = function() { - if(walker.currentNode.nodeType === TEXT_NODE) { - return currentPos - } - var c = 0, n = walker.currentNode; - if(currentPos === 1) { - n = n.lastChild - }else { - n = n.previousSibling - } - while(n) { - c += 1; - n = n.previousSibling - } - return c - }; - this.getPreviousSibling = function() { - var currentNode = walker.currentNode, sibling = walker.previousSibling(); - walker.currentNode = currentNode; - return sibling - }; - this.getNextSibling = function() { - var currentNode = walker.currentNode, sibling = walker.nextSibling(); - walker.currentNode = currentNode; - return sibling - }; - this.setUnfilteredPosition = function(container, offset) { - var filterResult, node, text; - runtime.assert(container !== null && container !== undefined, "PositionIterator.setUnfilteredPosition called without container"); - walker.currentNode = container; - if(container.nodeType === TEXT_NODE) { - currentPos = offset; - text = (container); - runtime.assert(offset <= text.length, "Error in setPosition: " + offset + " > " + text.length); - runtime.assert(offset >= 0, "Error in setPosition: " + offset + " < 0"); - if(offset === text.length) { - if(walker.nextSibling()) { - currentPos = 0 - }else { - if(walker.parentNode()) { - currentPos = 1 - }else { - runtime.assert(false, "Error in setUnfilteredPosition: position not valid.") - } - } - } - 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) { - 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 - }; - this.moveToEnd = function() { - walker.currentNode = root; - currentPos = 1 - }; - this.moveToEndOfNode = function(node) { - var text; - if(node.nodeType === TEXT_NODE) { - text = (node); - self.setUnfilteredPosition(text, text.length) - }else { - walker.currentNode = node; - currentPos = 1 - } - }; - this.getNodeFilter = function() { - return nodeFilter - }; - function init() { - var f; - if(filter) { - f = new FilteredEmptyTextNodeFilter(filter) - }else { - f = new EmptyTextNodeFilter - } - nodeFilter = (f.acceptNode); - nodeFilter.acceptNode = nodeFilter; - whatToShow = whatToShow || 4294967295; - 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; - if(walker.firstChild() === null) { - currentPos = 1 - } - } - 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] - } -}; -core.ScheduledTask = function ScheduledTask(fn, delay) { - var timeoutId, scheduled = false; - function execute() { - fn(); - scheduled = false - } - function cancel() { - if(scheduled) { - runtime.clearTimeout(timeoutId); - scheduled = false - } - } - this.trigger = function() { - if(!scheduled) { - timeoutId = runtime.setTimeout(execute, delay) - } - }; - this.triggerImmediate = function() { - cancel(); - execute() - }; - this.processRequests = function() { - if(scheduled) { - cancel(); - execute() - } - }; - this.cancel = cancel; - this.destroy = function(callback) { - cancel(); - callback() - } -}; -core.Async = function Async() { - this.forEach = function(items, f, callback) { - var i, l = items.length, itemsDone = 0; - function end(err) { - if(itemsDone !== l) { - if(err) { - itemsDone = l; - callback(err) - }else { - itemsDone += 1; - if(itemsDone === l) { - callback(null) - } - } - } - } - for(i = 0;i < l;i += 1) { - f(items[i], end) - } - }; - this.destroyAll = function(items, callback) { - function destroy(itemIndex, err) { - if(err) { - callback(err) - }else { - if(itemIndex < items.length) { - items[itemIndex](function(err) { - destroy(itemIndex + 1, err) - }) - }else { - callback() - } - } - } - destroy(0, undefined) - } -}; -/* - - WebODF - Copyright (c) 2010 Jos van den Oever - Licensed under the ... License: - - 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) { - var table = [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], crc = - 0, i, iTop = data.length, x = 0, y = 0; - crc = crc ^ -1; - for(i = 0;i < iTop;i += 1) { - y = (crc ^ data[i]) & 255; - x = table[y]; - crc = crc >>> 8 ^ x - } - return crc ^ -1 - } - function dosTime2Date(dostime) { - var year = (dostime >> 25 & 127) + 1980, month = (dostime >> 21 & 15) - 1, mday = dostime >> 16 & 31, hour = dostime >> 11 & 15, min = dostime >> 5 & 63, sec = (dostime & 31) << 1, d = new Date(year, month, mday, hour, min, sec); - return d - } - function date2DosTime(date) { - var y = date.getFullYear(); - return y < 1980 ? 0 : y - 1980 << 25 | date.getMonth() + 1 << 21 | date.getDate() << 16 | date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1 - } - function ZipEntry(url, stream) { - var sig, namelen, extralen, commentlen, compressionMethod, compressedSize, uncompressedSize, offset, entry = this; - function handleEntryData(data, callback) { - var estream = new core.ByteArray(data), esig = estream.readUInt32LE(), filenamelen, eextralen; - if(esig !== 67324752) { - callback("File entry signature is wrong." + esig.toString() + " " + data.length.toString(), null); - return - } - estream.pos += 22; - filenamelen = estream.readUInt16LE(); - eextralen = estream.readUInt16LE(); - estream.pos += filenamelen + eextralen; - if(compressionMethod) { - data = data.subarray(estream.pos, estream.pos + compressedSize); - if(compressedSize !== data.length) { - callback("The amount of compressed bytes read was " + data.length.toString() + " instead of " + compressedSize.toString() + " for " + entry.filename + " in " + url + ".", null); - return - } - data = inflate(data, uncompressedSize) - }else { - data = data.subarray(estream.pos, estream.pos + uncompressedSize) - } - if(uncompressedSize !== data.length) { - callback("The amount of bytes read was " + data.length.toString() + " instead of " + uncompressedSize.toString() + " for " + entry.filename + " in " + url + ".", null); - return - } - entry.data = data; - callback(null, data) - } - function load(callback) { - if(entry.data !== undefined) { - callback(null, entry.data); - return - } - var size = compressedSize + 34 + namelen + extralen + 256; - if(size + offset > filesize) { - size = filesize - offset - } - runtime.read(url, offset, size, function(err, data) { - if(err || data === null) { - callback(err, data) - }else { - handleEntryData(data, callback) - } - }) - } - this.load = load; - function set(filename, data, compressed, date) { - entry.filename = filename; - entry.data = data; - entry.compressed = compressed; - entry.date = date - } - this.set = set; - this.error = null; - if(!stream) { - return - } - sig = stream.readUInt32LE(); - if(sig !== 33639248) { - this.error = "Central directory entry has wrong signature at position " + (stream.pos - 4).toString() + ' for file "' + url + '": ' + stream.data.length.toString(); - return - } - stream.pos += 6; - compressionMethod = stream.readUInt16LE(); - this.date = dosTime2Date(stream.readUInt32LE()); - stream.readUInt32LE(); - compressedSize = stream.readUInt32LE(); - uncompressedSize = stream.readUInt32LE(); - namelen = stream.readUInt16LE(); - extralen = stream.readUInt16LE(); - commentlen = stream.readUInt16LE(); - stream.pos += 8; - offset = stream.readUInt32LE(); - this.filename = runtime.byteArrayToString(stream.data.subarray(stream.pos, stream.pos + namelen), "utf8"); - stream.pos += namelen + extralen + commentlen - } - function handleCentralDirectory(data, callback) { - var stream = new core.ByteArray(data), i, e; - entries = []; - for(i = 0;i < nEntries;i += 1) { - e = new ZipEntry(url, stream); - if(e.error) { - callback(e.error, zip); - return - } - entries[entries.length] = e - } - callback(null, zip) - } - function handleCentralDirectoryEnd(data, callback) { - if(data.length !== 22) { - callback("Central directory length should be 22.", zip); - return - } - var stream = new core.ByteArray(data), sig, disk, cddisk, diskNEntries, cdsSize, cdsOffset; - sig = stream.readUInt32LE(); - if(sig !== 101010256) { - callback("Central directory signature is wrong: " + sig.toString(), zip); - return - } - disk = stream.readUInt16LE(); - if(disk !== 0) { - callback("Zip files with non-zero disk numbers are not supported.", zip); - return - } - cddisk = stream.readUInt16LE(); - if(cddisk !== 0) { - callback("Zip files with non-zero disk numbers are not supported.", zip); - return - } - diskNEntries = stream.readUInt16LE(); - nEntries = stream.readUInt16LE(); - if(diskNEntries !== nEntries) { - callback("Number of entries is inconsistent.", zip); - return - } - cdsSize = stream.readUInt32LE(); - cdsOffset = stream.readUInt16LE(); - cdsOffset = filesize - 22 - cdsSize; - runtime.read(url, cdsOffset, filesize - cdsOffset, function(err, data) { - if(err || data === null) { - callback(err, zip) - }else { - handleCentralDirectory(data, callback) - } - }) - } - function load(filename, callback) { - var entry = null, e, i; - for(i = 0;i < entries.length;i += 1) { - e = entries[i]; - if(e.filename === filename) { - entry = e; - break - } - } - if(entry) { - if(entry.data) { - callback(null, entry.data) - }else { - entry.load(callback) - } - }else { - callback(filename + " not found.", null) - } - } - function loadAsString(filename, callback) { - load(filename, function(err, data) { - if(err || data === null) { - return callback(err, null) - } - var d = runtime.byteArrayToString(data, "utf8"); - callback(null, d) - }) - } - function loadContentXmlAsFragments(filename, handler) { - zip.loadAsString(filename, function(err, data) { - if(err) { - return handler.rootElementReady(err) - } - handler.rootElementReady(null, data, true) - }) - } - function loadAsDataURL(filename, mimetype, callback) { - load(filename, function(err, data) { - if(err || !data) { - return callback(err, null) - } - var p = data, chunksize = 45E3, i = 0, dataurl; - if(!mimetype) { - if(p[1] === 80 && (p[2] === 78 && p[3] === 71)) { - mimetype = "image/png" - }else { - if(p[0] === 255 && (p[1] === 216 && p[2] === 255)) { - mimetype = "image/jpeg" - }else { - if(p[0] === 71 && (p[1] === 73 && p[2] === 70)) { - mimetype = "image/gif" - }else { - mimetype = "" + bookmark = findBookmarkedAncestor(node, offset); + if(!bookmark) { + iterator.setUnfilteredPosition(node, offset); + while(!bookmark && iterator.previousNode()) { + bookmark = findBookmarkedAncestor(iterator.container(), iterator.unfilteredDomOffset()) } } } } - dataurl = "data:" + mimetype + ";base64,"; - while(i < data.length) { - dataurl += base64.convertUTF8ArrayToBase64(p.subarray(i, Math.min(i + chunksize, p.length))); - i += chunksize - } - callback(null, dataurl) - }) + bookmark = 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] + } + }); + Object.keys(updatedBuckets).forEach(function(cacheBucket) { + stepToDomPoint[cacheBucket] = updatedBuckets[cacheBucket] + }) + }; + function init() { + basePoint = new RootBookmark(0, rootNode) + } + init() } - function loadAsDOM(filename, callback) { - zip.loadAsString(filename, function(err, xmldata) { - if(err || xmldata === null) { - callback(err, null); - return - } - var parser = new DOMParser, dom = parser.parseFromString(xmldata, "text/xml"); - callback(null, dom) - }) - } - function save(filename, data, compressed, date) { - var i, entry; - for(i = 0;i < entries.length;i += 1) { - entry = entries[i]; - if(entry.filename === filename) { - entry.set(filename, data, compressed, date); - return + 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; + function verifyRootNode() { + var currentRootNode = getRootNode(); + if(currentRootNode !== rootNode) { + runtime.log("Undo detected. Resetting steps cache"); + rootNode = currentRootNode; + stepsCache = new StepsCache(rootNode, filter, bucketSize); + iterator = newIterator(rootNode) } } - entry = new ZipEntry(url); - entry.set(filename, data, compressed, date); - entries.push(entry) - } - function remove(filename) { - var i, entry; - for(i = 0;i < entries.length;i += 1) { - entry = entries[i]; - if(entry.filename === filename) { - entries.splice(i, 1); + this.convertStepsToDomPoint = function(steps) { + var stepsFromRoot, isWalkable; + if(steps < 0) { + runtime.log("warn", "Requested steps were negative (" + steps + ")"); + steps = 0 + } + verifyRootNode(); + stepsFromRoot = stepsCache.setToClosestStep(steps, iterator); + while(stepsFromRoot < steps && iterator.nextPosition()) { + isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT; + if(isWalkable) { + stepsFromRoot += 1 + } + stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable) + } + if(stepsFromRoot !== steps) { + runtime.log("warn", "Requested " + steps + " steps but only " + stepsFromRoot + " are available") + } + return{node:iterator.container(), offset:iterator.unfilteredDomOffset()} + }; + function roundToPreferredStep(iterator, roundDirection) { + if(!roundDirection || filter.acceptPosition(iterator) === FILTER_ACCEPT) { return true } - } - return false - } - function writeEntry(entry) { - var data = new core.ByteArrayWriter("utf8"), length = 0; - data.appendArray([80, 75, 3, 4, 20, 0, 0, 0, 0, 0]); - if(entry.data) { - length = entry.data.length - } - data.appendUInt32LE(date2DosTime(entry.date)); - data.appendUInt32LE(crc32(entry.data)); - data.appendUInt32LE(length); - data.appendUInt32LE(length); - data.appendUInt16LE(entry.filename.length); - data.appendUInt16LE(0); - data.appendString(entry.filename); - if(entry.data) { - data.appendByteArray(entry.data) - } - return data - } - function writeCODEntry(entry, offset) { - var data = new core.ByteArrayWriter("utf8"), length = 0; - data.appendArray([80, 75, 1, 2, 20, 0, 20, 0, 0, 0, 0, 0]); - if(entry.data) { - length = entry.data.length - } - data.appendUInt32LE(date2DosTime(entry.date)); - data.appendUInt32LE(crc32(entry.data)); - data.appendUInt32LE(length); - data.appendUInt32LE(length); - data.appendUInt16LE(entry.filename.length); - data.appendArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - data.appendUInt32LE(offset); - data.appendString(entry.filename); - return data - } - function loadAllEntries(position, callback) { - if(position === entries.length) { - callback(null); - return - } - var entry = entries[position]; - if(entry.data !== undefined) { - loadAllEntries(position + 1, callback); - return - } - entry.load(function(err) { - if(err) { - callback(err); - return + while(iterator.previousPosition()) { + if(filter.acceptPosition(iterator) === FILTER_ACCEPT) { + if(roundDirection(PREVIOUS_STEP, iterator.container(), iterator.unfilteredDomOffset())) { + return true + } + break + } } - loadAllEntries(position + 1, callback) - }) - } - function createByteArray(successCallback, errorCallback) { - loadAllEntries(0, function(err) { - if(err) { - errorCallback(err); - return + while(iterator.nextPosition()) { + if(filter.acceptPosition(iterator) === FILTER_ACCEPT) { + if(roundDirection(NEXT_STEP, iterator.container(), iterator.unfilteredDomOffset())) { + return true + } + break + } } - var data = new core.ByteArrayWriter("utf8"), i, e, codoffset, codsize, offsets = [0]; - for(i = 0;i < entries.length;i += 1) { - data.appendByteArrayWriter(writeEntry(entries[i])); - offsets.push(data.getLength()) + return false + } + this.convertDomPointToSteps = function(node, offset, roundDirection) { + var stepsFromRoot, beforeRoot, destinationNode, destinationOffset, rounding = 0, isWalkable; + verifyRootNode(); + if(!domUtils.containsNode(rootNode, node)) { + beforeRoot = domUtils.comparePoints(rootNode, 0, node, offset) < 0; + node = rootNode; + offset = beforeRoot ? 0 : rootNode.childNodes.length } - codoffset = data.getLength(); - for(i = 0;i < entries.length;i += 1) { - e = entries[i]; - data.appendByteArrayWriter(writeCODEntry(e, offsets[i])) + iterator.setUnfilteredPosition(node, offset); + if(!roundToPreferredStep(iterator, roundDirection)) { + iterator.setUnfilteredPosition(node, offset) } - codsize = data.getLength() - codoffset; - data.appendArray([80, 75, 5, 6, 0, 0, 0, 0]); - data.appendUInt16LE(entries.length); - data.appendUInt16LE(entries.length); - data.appendUInt32LE(codsize); - data.appendUInt32LE(codoffset); - data.appendArray([0, 0]); - successCallback(data.getByteArray()) - }) - } - function writeAs(newurl, callback) { - createByteArray(function(data) { - runtime.writeFile(newurl, data, callback) - }, callback) - } - function write(callback) { - writeAs(url, callback) - } - this.load = load; - this.save = save; - this.remove = remove; - this.write = write; - this.writeAs = writeAs; - this.createByteArray = createByteArray; - this.loadContentXmlAsFragments = loadContentXmlAsFragments; - this.loadAsString = loadAsString; - this.loadAsDOM = loadAsDOM; - this.loadAsDataURL = loadAsDataURL; - this.getEntries = function() { - return entries.slice() - }; - filesize = -1; - if(entriesReadCallback === null) { - entries = []; - return - } - runtime.getFileSize(url, function(size) { - filesize = size; - if(filesize < 0) { - entriesReadCallback("File '" + url + "' cannot be read.", zip) - }else { - runtime.read(url, filesize - 22, 22, function(err, data) { - if(err || (entriesReadCallback === null || data === null)) { - entriesReadCallback(err, zip) - }else { - handleCentralDirectoryEnd(data, entriesReadCallback) + destinationNode = iterator.container(); + destinationOffset = iterator.unfilteredDomOffset(); + stepsFromRoot = stepsCache.setToClosestDomPoint(destinationNode, destinationOffset, iterator); + if(domUtils.comparePoints(iterator.container(), iterator.unfilteredDomOffset(), destinationNode, destinationOffset) < 0) { + return stepsFromRoot > 0 ? stepsFromRoot - 1 : stepsFromRoot + } + while(!(iterator.container() === destinationNode && iterator.unfilteredDomOffset() === destinationOffset) && iterator.nextPosition()) { + isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT; + if(isWalkable) { + stepsFromRoot += 1 + } + stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable) + } + return stepsFromRoot + rounding + }; + this.prime = function() { + var stepsFromRoot, isWalkable; + verifyRootNode(); + stepsFromRoot = stepsCache.setToClosestStep(0, iterator); + while(iterator.nextPosition()) { + isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT; + if(isWalkable) { + stepsFromRoot += 1 + } + stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable) + } + }; + this.handleStepsInserted = function(eventArgs) { + verifyRootNode(); + stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) { + bucket.steps += eventArgs.length + }) + }; + this.handleStepsRemoved = function(eventArgs) { + verifyRootNode(); + stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) { + bucket.steps -= eventArgs.length; + if(bucket.steps < 0) { + bucket.steps = 0 } }) } - }) -}; -core.CSSUnits = function CSSUnits() { - var self = this, sizemap = {"in":1, "cm":2.54, "mm":25.4, "pt":72, "pc":12}; - this.convert = function(value, oldUnit, newUnit) { - return value * sizemap[newUnit] / sizemap[oldUnit] }; - this.convertMeasure = function(measure, newUnit) { - var value, oldUnit, newMeasure; - if(measure && newUnit) { - value = parseFloat(measure); - oldUnit = measure.replace(value.toString(), ""); - newMeasure = self.convert(value, oldUnit, newUnit).toString() - }else { - newMeasure = "" - } - return newMeasure - }; - this.getUnits = function(measure) { - return measure.substr(measure.length - 2, measure.length) - } -}; -xmldom.LSSerializerFilter = function LSSerializerFilter() { -}; -if(typeof Object.create !== "function") { - Object["create"] = function(o) { - var F = function() { - }; - F.prototype = o; - return new F - } -} -xmldom.LSSerializer = function LSSerializer() { - var self = this; - function Namespaces(nsmap) { - function invertMap(map) { - var m = {}, i; - for(i in map) { - if(map.hasOwnProperty(i)) { - m[map[i]] = i - } - } - return m - } - var current = nsmap || {}, currentrev = invertMap(nsmap), levels = [current], levelsrev = [currentrev], level = 0; - this.push = function() { - level += 1; - current = levels[level] = Object.create(current); - currentrev = levelsrev[level] = Object.create(currentrev) - }; - this.pop = function() { - levels[level] = undefined; - levelsrev[level] = undefined; - level -= 1; - current = levels[level]; - currentrev = levelsrev[level] - }; - this.getLocalNamespaceDefinitions = function() { - return currentrev - }; - this.getQName = function(node) { - var ns = node.namespaceURI, i = 0, p; - if(!ns) { - return node.localName - } - p = currentrev[ns]; - if(p) { - return p + ":" + node.localName - } - do { - if(p || !node.prefix) { - p = "ns" + i; - i += 1 - }else { - p = node.prefix - } - if(current[p] === ns) { - break - } - if(!current[p]) { - current[p] = ns; - currentrev[ns] = p; - break - } - p = null - }while(p === null); - return p + ":" + node.localName - } - } - function escapeContent(value) { - return value.replace(/&/g, "&").replace(//g, ">").replace(/'/g, "'").replace(/"/g, """) - } - function serializeAttribute(qname, attr) { - var escapedValue = typeof attr.value === "string" ? escapeContent(attr.value) : attr.value, s = qname + '="' + escapedValue + '"'; - return s - } - function startElement(ns, qname, element) { - var s = "", atts = (element.attributes), length, i, attr, attstr = "", accept, prefix, nsmap; - s += "<" + qname; - length = atts.length; - for(i = 0;i < length;i += 1) { - attr = (atts.item(i)); - if(attr.namespaceURI !== "http://www.w3.org/2000/xmlns/") { - accept = self.filter ? self.filter.acceptNode(attr) : NodeFilter.FILTER_ACCEPT; - if(accept === NodeFilter.FILTER_ACCEPT) { - attstr += " " + serializeAttribute(ns.getQName(attr), attr) - } - } - } - nsmap = ns.getLocalNamespaceDefinitions(); - for(i in nsmap) { - if(nsmap.hasOwnProperty(i)) { - prefix = nsmap[i]; - if(!prefix) { - s += ' xmlns="' + i + '"' - }else { - if(prefix !== "xmlns") { - s += " xmlns:" + nsmap[i] + '="' + i + '"' - } - } - } - } - s += attstr + ">"; - return s - } - function serializeNode(ns, node) { - var s = "", accept = self.filter ? self.filter.acceptNode(node) : NodeFilter.FILTER_ACCEPT, child, qname; - if(accept === NodeFilter.FILTER_ACCEPT && node.nodeType === Node.ELEMENT_NODE) { - ns.push(); - qname = ns.getQName(node); - s += startElement(ns, qname, node) - } - if(accept === NodeFilter.FILTER_ACCEPT || accept === NodeFilter.FILTER_SKIP) { - child = node.firstChild; - while(child) { - s += serializeNode(ns, child); - child = child.nextSibling - } - if(node.nodeValue) { - s += escapeContent(node.nodeValue) - } - } - if(qname) { - s += ""; - ns.pop() - } - return s - } - this.filter = null; - this.writeToString = function(node, nsmap) { - if(!node) { - return"" - } - var ns = new Namespaces(nsmap); - return serializeNode(ns, node) - } -}; + 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) { @@ -4777,8 +10716,8 @@ xmldom.RelaxNGParser = function RelaxNGParser() { } function copyAttributes(atts, name, names) { var a = {}, i, att; - for(i = 0;i < atts.length;i += 1) { - att = atts.item(i); + 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) @@ -4799,7 +10738,7 @@ xmldom.RelaxNGParser = function RelaxNGParser() { var text = "", ce; while(c) { if(c.nodeType === Node.ELEMENT_NODE && c.namespaceURI === rngns) { - ce = parse(c, elements, e); + ce = parse((c), elements, e); if(ce) { if(ce.name === "name") { names.push(nsmap[ce.a.ns] + ":" + ce.text); @@ -4898,7 +10837,7 @@ xmldom.RelaxNGParser = function RelaxNGParser() { if(name === "define" && a.combine) { ce = combineDefines(a.combine, a.name, e, siblings); if(ce) { - return + return null } } ce = {name:name}; @@ -5046,9 +10985,515 @@ xmldom.RelaxNGParser = function RelaxNGParser() { } 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) + }else { + if(number <= 0) { + moved = -selectionMover.movePointBackward(-number, extend) + } + } + 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() + } + init() +}; +ops.OdtCursor.RangeSelection = "Range"; +ops.OdtCursor.RegionSelection = "Region"; +(function() { + return ops.OdtCursor +})(); +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.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; + 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.getDOM = getDOM; + function isRoot(node) { + if(node.namespaceURI === odf.Namespaces.officens && node.localName === "text" || node.namespaceURI === odf.Namespaces.officens && node.localName === "annotation") { + return true + } + return false + } + function getRoot(node) { + while(node && !isRoot(node)) { + node = (node.parentNode) + } + return node + } + this.getRootElement = getRoot; + function RootFilter(anchor) { + this.acceptPosition = function(iterator) { + var node = iterator.container(), anchorNode; + if(typeof anchor === "string") { + anchorNode = cursors[anchor].getNode() + }else { + anchorNode = anchor + } + if(getRoot(node) === getRoot(anchorNode)) { + return FILTER_ACCEPT + } + return FILTER_REJECT + } + } + function getIteratorAtPosition(position) { + var iterator = gui.SelectionMover.createPositionIterator(getRootNode()), point = stepsTranslator.convertStepsToDomPoint(position); + iterator.setUnfilteredPosition(point.node, point.offset); + return iterator + } + this.getIteratorAtPosition = getIteratorAtPosition; + this.convertDomPointToCursorStep = function(node, offset, roundDirection) { + return stepsTranslator.convertDomPointToSteps(node, offset, roundDirection) + }; + this.convertDomToCursorRange = function(selection, constraint) { + var point1, point2, anchorConstraint = 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); + 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; + point1 = stepsTranslator.convertStepsToDomPoint(position); + if(length) { + point2 = stepsTranslator.convertStepsToDomPoint(position + length); + if(length > 0) { + range.setStart(point1.node, point1.offset); + range.setEnd(point2.node, point2.offset) + }else { + range.setStart(point2.node, point2.offset); + range.setEnd(point1.node, point1.offset) + } + }else { + range.setStart(point1.node, point1.offset) + } + return range + }; + function getTextNodeAtStep(steps, memberid) { + var iterator = getIteratorAtPosition(steps), node = iterator.container(), lastTextNode, nodeOffset = 0, cursorNode = null; + if(node.nodeType === Node.TEXT_NODE) { + lastTextNode = (node); + nodeOffset = iterator.unfilteredDomOffset() + }else { + lastTextNode = getDOM().createTextNode(""); + nodeOffset = 0; + node.insertBefore(lastTextNode, iterator.rightNode()) + } + if(memberid && (cursors[memberid] && self.getCursorPosition(memberid) === steps)) { + cursorNode = cursors[memberid].getNode(); + while(cursorNode.nextSibling && cursorNode.nextSibling.localName === "cursor") { + cursorNode.parentNode.insertBefore(cursorNode.nextSibling, cursorNode) + } + if(lastTextNode.length > 0 && lastTextNode.nextSibling !== cursorNode) { + lastTextNode = getDOM().createTextNode(""); + nodeOffset = 0 + } + cursorNode.parentNode.insertBefore(lastTextNode, cursorNode) + } + while(lastTextNode.previousSibling && lastTextNode.previousSibling.nodeType === Node.TEXT_NODE) { + lastTextNode.previousSibling.appendData(lastTextNode.data); + nodeOffset = lastTextNode.previousSibling.length; + lastTextNode = (lastTextNode.previousSibling); + lastTextNode.parentNode.removeChild(lastTextNode.nextSibling) + } + return{textNode:lastTextNode, offset:nodeOffset} + } + function getParagraphElement(node) { + return odfUtils.getParagraphElement(node) + } + function getStyleElement(styleName, styleFamily) { + return odfCanvas.getFormatting().getStyleElement(styleName, styleFamily) + } + this.getStyleElement = getStyleElement; + function getParagraphStyleElement(styleName) { + return getStyleElement(styleName, "paragraph") + } + function getParagraphStyleAttributes(styleName) { + var node = getParagraphStyleElement(styleName); + if(node) { + return odfCanvas.getFormatting().getInheritedStyleAttributes(node) + } + return null + } + function handleOperationExecuted(op) { + var spec = op.spec(), memberId = spec.memberid, date = (new Date(spec.timestamp)).toISOString(), metadataManager = odfCanvas.odfContainer().getMetadataManager(), fullName; + if(op.isEdit) { + fullName = self.getMember(memberId).getProperties().fullName; + metadataManager.setMetadata({"dc:creator":fullName, "dc:date":date}, null); + if(!lastEditingOp) { + metadataManager.incrementEditingCycles(); + if(!unsupportedMetadataRemoved) { + metadataManager.setMetadata(null, ["meta:editing-duration", "meta:document-statistic"]) + } + } + lastEditingOp = op + } + } + 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"); + space.appendChild(textNode.ownerDocument.createTextNode(" ")); + textNode.deleteData(offset, 1); + if(offset > 0) { + textNode = (textNode.splitText(offset)) + } + textNode.parentNode.insertBefore(space, textNode); + return space + } + function upgradeWhitespacesAtPosition(position) { + var iterator = getIteratorAtPosition(position), container, offset, i; + iterator.previousPosition(); + iterator.previousPosition(); + 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))) { + container = upgradeWhitespaceToElement((container), offset); + iterator.moveToEndOfNode(container) + } + iterator.nextPosition() + } + } + this.upgradeWhitespacesAtPosition = upgradeWhitespacesAtPosition; + this.downgradeWhitespacesAtPosition = function(position) { + var iterator = getIteratorAtPosition(position), container, offset, firstSpaceElementChild, lastSpaceElementChild; + container = iterator.container(); + offset = iterator.unfilteredDomOffset(); + while(!odfUtils.isCharacterElement(container) && container.childNodes[offset]) { + container = container.childNodes[offset]; + offset = 0 + } + if(container.nodeType === Node.TEXT_NODE) { + container = container.parentNode + } + if(odfUtils.isDowngradableSpaceElement(container)) { + firstSpaceElementChild = container.firstChild; + lastSpaceElementChild = container.lastChild; + domUtils.mergeIntoParent(container); + if(lastSpaceElementChild !== firstSpaceElementChild) { + domUtils.normalizeTextNodes(lastSpaceElementChild) + } + domUtils.normalizeTextNodes(firstSpaceElementChild) + } + }; + this.getParagraphStyleElement = getParagraphStyleElement; + this.getParagraphElement = getParagraphElement; + this.getParagraphStyleAttributes = getParagraphStyleAttributes; + this.getTextNodeAtStep = getTextNodeAtStep; + 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)) { + 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) + } + }else { + if(stepsSelectionLength === 0) { + cursorMoved = true; + cursor.move(0) + } + } + if(cursorMoved) { + self.emit(ops.OdtDocument.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 + }; + this.getCursorSelection = function(memberid) { + var cursor = cursors[memberid], focusPosition = 0, anchorPosition = 0; + if(cursor) { + focusPosition = stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0); + anchorPosition = stepsTranslator.convertDomPointToSteps(cursor.getAnchorNode(), 0) + } + return{position:anchorPosition, length:focusPosition - anchorPosition} + }; + this.getPositionFilter = function() { + return filter + }; + this.getOdfCanvas = function() { + return odfCanvas + }; + this.getRootNode = getRootNode; + this.addMember = function(member) { + runtime.assert(members[member.getMemberId()] === undefined, "This member already exists"); + members[member.getMemberId()] = member + }; + this.getMember = function(memberId) { + return members.hasOwnProperty(memberId) ? members[memberId] : null + }; + this.removeMember = function(memberId) { + delete members[memberId] + }; + this.getCursor = function(memberid) { + return cursors[memberid] + }; + this.getCursors = function() { + var list = [], i; + for(i in cursors) { + if(cursors.hasOwnProperty(i)) { + list.push(cursors[i]) + } + } + return list + }; + this.addCursor = function(cursor) { + runtime.assert(Boolean(cursor), "OdtDocument::addCursor without cursor"); + var distanceToFirstTextNode = cursor.getStepCounter().countSteps(1, filter), memberid = cursor.getMemberId(); + 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); + cursors[memberid] = cursor + }; + this.removeCursor = function(memberid) { + var cursor = cursors[memberid]; + if(cursor) { + cursor.removeFromOdtDocument(); + delete cursors[memberid]; + self.emit(ops.OdtDocument.signalCursorRemoved, memberid); + return true + } + return false + }; + this.getFormatting = function() { + return odfCanvas.getFormatting() + }; + this.emit = function(eventid, args) { + eventNotifier.emit(eventid, args) + }; + this.subscribe = function(eventid, cb) { + eventNotifier.subscribe(eventid, cb) + }; + this.unsubscribe = function(eventid, cb) { + eventNotifier.unsubscribe(eventid, cb) + }; + this.createRootFilter = function(inputMemberId) { + return new RootFilter(inputMemberId) + }; + this.close = function(callback) { + callback() + }; + this.destroy = function(callback) { + callback() + }; + function init() { + filter = new ops.TextPositionFilter(getRootNode); + odfUtils = new odf.OdfUtils; + domUtils = new core.DomUtils; + 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) + } + 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.signalUndoStackChanged = "undo/changed"; +ops.OdtDocument.signalStepsInserted = "steps/inserted"; +ops.OdtDocument.signalStepsRemoved = "steps/removed"; +(function() { + return ops.OdtDocument +})(); +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.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, notAllowed = {type:"notAllowed", nullable:false, hash:"notAllowed", textDeriv:function() { + 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 @@ -5058,7 +11503,7 @@ xmldom.RelaxNG = function RelaxNG() { return notAllowed }, endTagDeriv:function() { return notAllowed - }}, empty = {type:"empty", nullable:true, hash:"empty", textDeriv:function() { + }}, empty = {type:"empty", nullable:true, hash:"empty", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() { return notAllowed }, startTagOpenDeriv:function() { return notAllowed @@ -5068,7 +11513,7 @@ xmldom.RelaxNG = function RelaxNG() { return empty }, endTagDeriv:function() { return notAllowed - }}, text = {type:"text", nullable:true, hash:"text", textDeriv:function() { + }}, text = {type:"text", nullable:true, hash:"text", nc:undefined, p:undefined, p1:undefined, p2:undefined, textDeriv:function() { return text }, startTagOpenDeriv:function() { return notAllowed @@ -5078,43 +11523,46 @@ xmldom.RelaxNG = function RelaxNG() { return text }, endTagDeriv:function() { return notAllowed - }}, applyAfter, childDeriv, rootPattern; + }}; function memoize0arg(func) { - return function() { + function f() { var cache; - return function() { + function g() { if(cache === undefined) { cache = func() } return cache } - }() + return g + } + return f() } function memoize1arg(type, func) { - return function() { + function f() { var cache = {}, cachecount = 0; - return function(a) { + function g(a) { var ahash = a.hash || a.toString(), v; - v = cache[ahash]; - if(v !== undefined) { - return 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) { - return function() { + function f() { var cache = {}; - return function(node) { + function g(node) { var v, m; - m = cache[node.localName]; - if(m === undefined) { + if(!cache.hasOwnProperty(node.localName)) { cache[node.localName] = m = {} }else { + m = cache[node.localName]; v = m[node.namespaceURI]; if(v !== undefined) { return v @@ -5123,25 +11571,26 @@ xmldom.RelaxNG = function RelaxNG() { m[node.namespaceURI] = v = func(node); return v } - }() + return g + } + return f() } function memoize2arg(type, fastfunc, func) { - return function() { + function f() { var cache = {}, cachecount = 0; - return function(a, b) { + 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(); - m = cache[ahash]; - if(m === undefined) { + if(!cache.hasOwnProperty(ahash)) { cache[ahash] = m = {} }else { - v = m[bhash]; - if(v !== undefined) { - return v + m = cache[ahash]; + if(m.hasOwnProperty(bhash)) { + return m[bhash] } } m[bhash] = v = func(a, b); @@ -5149,33 +11598,34 @@ xmldom.RelaxNG = function RelaxNG() { cachecount += 1; return v } - }() + return g + } + return f() } function unorderedMemoize2arg(type, fastfunc, func) { - return function() { + function f() { var cache = {}, cachecount = 0; - return function(a, b) { - var v = fastfunc && fastfunc(a, b), ahash, bhash, m; + 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) { - m = ahash; + hash = ahash; ahash = bhash; - bhash = m; - m = a; + bhash = hash; + hash = a; a = b; - b = m + b = hash } - m = cache[ahash]; - if(m === undefined) { + if(!cache.hasOwnProperty(ahash)) { cache[ahash] = m = {} }else { - v = m[bhash]; - if(v !== undefined) { - return v + m = cache[ahash]; + if(m.hasOwnProperty(bhash)) { + return m[bhash] } } m[bhash] = v = func(a, b); @@ -5183,7 +11633,9 @@ xmldom.RelaxNG = function RelaxNG() { cachecount += 1; return v } - }() + return g + } + return f() } function getUniqueLeaves(leaves, pattern) { if(pattern.p1.type === "choice") { @@ -5209,7 +11661,7 @@ xmldom.RelaxNG = function RelaxNG() { } }, function(p1, p2) { function makeChoice(p1, p2) { - return{type:"choice", p1:p1, p2:p2, nullable:p1.nullable || p2.nullable, textDeriv:function(context, text) { + 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)) @@ -5251,7 +11703,7 @@ xmldom.RelaxNG = function RelaxNG() { return p1 } }, function(p1, p2) { - return{type:"interleave", p1:p1, p2:p2, nullable:p1.nullable && p2.nullable, textDeriv:function(context, text) { + 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) { @@ -5263,7 +11715,7 @@ xmldom.RelaxNG = function RelaxNG() { 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) { @@ -5351,14 +11803,14 @@ xmldom.RelaxNG = function RelaxNG() { return pattern.nullable && /^\s+$/.test(text) || pattern.textDeriv(context, text).nullable } createAttribute = memoize2arg("attribute", undefined, function(nc, p) { - return{type:"attribute", nullable:false, nc:nc, p:p, attDeriv:function(context, attribute) { + 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() { @@ -5826,4557 +12278,330 @@ xmldom.RelaxNG2 = function RelaxNG2() { nsmap = nsmap1 } }; -xmldom.XPathIterator = function XPathIterator() { -}; -xmldom.XPath = function() { - var createXPathPathIterator, parsePredicates; - function isSmallestPositive(a, b, c) { - return a !== -1 && ((a < b || b === -1) && (a < c || c === -1)) - } - function parseXPathStep(xpath, pos, end, steps) { - var location = "", predicates = [], brapos = xpath.indexOf("[", pos), slapos = xpath.indexOf("/", pos), eqpos = xpath.indexOf("=", pos); - if(isSmallestPositive(slapos, brapos, eqpos)) { - location = xpath.substring(pos, slapos); - pos = slapos + 1 - }else { - if(isSmallestPositive(brapos, slapos, eqpos)) { - location = xpath.substring(pos, brapos); - pos = parsePredicates(xpath, brapos, predicates) - }else { - if(isSmallestPositive(eqpos, slapos, brapos)) { - location = xpath.substring(pos, eqpos); - pos = eqpos - }else { - location = xpath.substring(pos, end); - pos = end - } - } - } - steps.push({location:location, predicates:predicates}); - return pos - } - function parseXPath(xpath) { - var steps = [], p = 0, end = xpath.length, value; - while(p < end) { - p = parseXPathStep(xpath, p, end, steps); - if(p < end && xpath[p] === "=") { - value = xpath.substring(p + 1, end); - if(value.length > 2 && (value[0] === "'" || value[0] === '"')) { - value = value.slice(1, value.length - 1) - }else { - try { - value = parseInt(value, 10) - }catch(ignore) { - } - } - p = end - } - } - return{steps:steps, value:value} - } - parsePredicates = function parsePredicates(xpath, start, predicates) { - var pos = start, l = xpath.length, depth = 0; - while(pos < l) { - if(xpath[pos] === "]") { - depth -= 1; - if(depth <= 0) { - predicates.push(parseXPath(xpath.substring(start, pos))) - } - }else { - if(xpath[pos] === "[") { - if(depth <= 0) { - start = pos + 1 - } - depth += 1 - } - } - pos += 1 - } - return pos - }; - xmldom.XPathIterator.prototype.next = function() { - }; - xmldom.XPathIterator.prototype.reset = function() { - }; - function XPathNodeIterator() { - var node, done = false; - this.setNode = function setNode(n) { - node = n - }; - this.reset = function() { - done = false - }; - this.next = function next() { - var val = done ? null : node; - done = true; - return val - } - } - function AttributeIterator(it, namespace, localName) { - this.reset = function reset() { - it.reset() - }; - this.next = function next() { - var node = it.next(); - while(node) { - node = node.getAttributeNodeNS(namespace, localName); - if(node) { - return node - } - node = it.next() - } - return node - } - } - function AllChildElementIterator(it, recurse) { - var root = it.next(), node = null; - this.reset = function reset() { - it.reset(); - root = it.next(); - node = null - }; - this.next = function next() { - while(root) { - if(node) { - if(recurse && node.firstChild) { - node = node.firstChild - }else { - while(!node.nextSibling && node !== root) { - node = node.parentNode - } - if(node === root) { - root = it.next() - }else { - node = node.nextSibling - } - } - }else { - do { - node = root.firstChild; - if(!node) { - root = it.next() - } - }while(root && !node) - } - if(node && node.nodeType === Node.ELEMENT_NODE) { - return node - } - } - return null - } - } - function ConditionIterator(it, condition) { - this.reset = function reset() { - it.reset() - }; - this.next = function next() { - var n = it.next(); - while(n && !condition(n)) { - n = it.next() - } - return n - } - } - function createNodenameFilter(it, name, namespaceResolver) { - var s = name.split(":", 2), namespace = namespaceResolver(s[0]), localName = s[1]; - return new ConditionIterator(it, function(node) { - return node.localName === localName && node.namespaceURI === namespace - }) - } - function createPredicateFilteredIterator(it, p, namespaceResolver) { - var nit = new XPathNodeIterator, pit = createXPathPathIterator(nit, p, namespaceResolver), value = p.value; - if(value === undefined) { - return new ConditionIterator(it, function(node) { - nit.setNode(node); - pit.reset(); - return pit.next() - }) - } - return new ConditionIterator(it, function(node) { - nit.setNode(node); - pit.reset(); - var n = pit.next(); - return n && n.nodeValue === value - }) - } - createXPathPathIterator = function createXPathPathIterator(it, xpath, namespaceResolver) { - var i, j, step, location, p; - for(i = 0;i < xpath.steps.length;i += 1) { - step = xpath.steps[i]; - location = step.location; - if(location === "") { - it = new AllChildElementIterator(it, false) - }else { - if(location[0] === "@") { - p = location.slice(1).split(":", 2); - it = new AttributeIterator(it, namespaceResolver(p[0]), p[1]) - }else { - if(location !== ".") { - it = new AllChildElementIterator(it, false); - if(location.indexOf(":") !== -1) { - it = createNodenameFilter(it, location, namespaceResolver) - } - } - } - } - for(j = 0;j < step.predicates.length;j += 1) { - p = step.predicates[j]; - it = createPredicateFilteredIterator(it, p, namespaceResolver) - } - } - return it - }; - function fallback(node, xpath, namespaceResolver) { - var it = new XPathNodeIterator, i, nodelist, parsedXPath; - it.setNode(node); - parsedXPath = parseXPath(xpath); - it = createXPathPathIterator(it, parsedXPath, namespaceResolver); - nodelist = []; - i = it.next(); - while(i) { - nodelist.push(i); - i = it.next() - } - return nodelist - } - function getODFElementsWithXPath(node, xpath, namespaceResolver) { - var doc = node.ownerDocument, nodes, elements = [], n = null; - if(!doc || !doc.evaluate) { - elements = fallback(node, xpath, namespaceResolver) - }else { - nodes = doc.evaluate(xpath, node, namespaceResolver, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); - n = nodes.iterateNext(); - while(n !== null) { - if(n.nodeType === Node.ELEMENT_NODE) { - elements.push(n) - } - n = nodes.iterateNext() - } - } - return elements - } - xmldom.XPath = function XPath() { - this.getODFElementsWithXPath = getODFElementsWithXPath - }; - return xmldom.XPath -}(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.AnnotationViewManager = function AnnotationViewManager(odfCanvas, 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"); - container.className = "annotationHighlight"; - container.setAttribute("annotation", annotationNode.getAttributeNS(odf.Namespaces.officens, "name")); - 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[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.parentNode, connectorHorizontal = annotationNote.nextSibling, connectorAngular = connectorHorizontal.nextSibling, annotationWrapper = annotationNote.parentNode, connectorAngle = 0, previousAnnotation = annotations[annotations.indexOf(annotation) - 1], previousRect, zoomLevel = odfCanvas.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.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 = odfCanvas.getSizer(); - if(show) { - annotationsPane.style.display = "inline-block"; - sizer.style.paddingRight = window.getComputedStyle(annotationsPane).width - }else { - annotationsPane.style.display = "none"; - sizer.style.paddingRight = 0 - } - odfCanvas.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) 2013 KO GmbH - - @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 . - - 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 - - @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 . - - 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.Namespaces = function() { - var dbns = "urn:oasis:names:tc:opendocument:xmlns:database:1.0", dcns = "http://purl.org/dc/elements/1.1/", metans = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0", 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", 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", namespaceMap = {"db":dbns, - "dc":dcns, "meta":metans, "dr3d":dr3dns, "draw":drawns, "chart":chartns, "fo":fons, "form":formns, "numberns":numberns, "office":officens, "presentation":presentationns, "style":stylens, "svg":svgns, "table":tablens, "text":textns, "xlink":xlinkns, "xml":xmlns}, namespaces; - function forEachPrefix(cb) { - var prefix; - for(prefix in namespaceMap) { - if(namespaceMap.hasOwnProperty(prefix)) { - cb(prefix, namespaceMap[prefix]) - } - } - } - function resolvePrefix(prefix) { - return namespaceMap[prefix] || null - } - function lookupPrefix(namespaceURI) { - var foundPrefix, prefix; - for(prefix in namespaceMap) { - if(namespaceMap.hasOwnProperty(prefix) && namespaceMap[prefix] === namespaceURI) { - foundPrefix = prefix; - break - } - } - return foundPrefix - } - resolvePrefix.lookupNamespaceURI = resolvePrefix; - namespaces = function Namespaces() { - }; - namespaces.forEachPrefix = forEachPrefix; - namespaces.resolvePrefix = resolvePrefix; - namespaces.lookupPrefix = lookupPrefix; - namespaces.namespaceMap = namespaceMap; - namespaces.dbns = dbns; - namespaces.dcns = dcns; - namespaces.metans = metans; - namespaces.dr3dns = dr3dns; - namespaces.drawns = drawns; - namespaces.chartns = chartns; - namespaces.fons = fons; - namespaces.formns = formns; - namespaces.numberns = numberns; - namespaces.officens = officens; - namespaces.presentationns = presentationns; - namespaces.stylens = stylens; - namespaces.svgns = svgns; - namespaces.tablens = tablens; - namespaces.textns = textns; - namespaces.xlinkns = xlinkns; - namespaces.xmlns = xmlns; - return namespaces -}(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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:", - "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:"}, elementstyles = {"text":[{ens:stylens, en:"tab-stop", ans:stylens, a:"leader-text-style"}, {ens:stylens, en:"drop-cap", ans:stylens, a:"style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"citation-body-style-name"}, {ens:textns, en:"notes-configuration", - ans:textns, a:"citation-style-name"}, {ens:textns, en:"a", ans:textns, a:"style-name"}, {ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"linenumbering-configuration", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-number", ans:textns, a:"style-name"}, {ens:textns, en:"ruby-text", ans:textns, a:"style-name"}, {ens:textns, en:"span", ans:textns, a:"style-name"}, {ens:textns, en:"a", ans:textns, a:"visited-style-name"}, {ens:stylens, en:"text-properties", - ans:stylens, a:"text-line-through-text-style"}, {ens:textns, en:"alphabetical-index-source", ans:textns, a:"main-entry-style-name"}, {ens:textns, en:"index-entry-bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-chapter", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-end", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-start", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-page-number", ans:textns, a:"style-name"}, {ens:textns, - en:"index-entry-span", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-tab-stop", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-text", ans:textns, a:"style-name"}, {ens:textns, en:"index-title-template", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-bullet", ans:textns, a:"style-name"}, {ens:textns, en:"outline-level-style", ans:textns, a:"style-name"}], "paragraph":[{ens:drawns, en:"caption", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"circle", ans:drawns, - a:"text-style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"control", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"ellipse", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"line", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"path", ans:drawns, a:"text-style-name"}, - {ens:drawns, en:"polygon", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"rect", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"text-style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"text-style-name"}, {ens:formns, en:"column", ans:formns, a:"text-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"next-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"paragraph-style-name"}, - {ens:tablens, en:"even-columns", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"even-rows", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"paragraph-style-name"}, - {ens:tablens, en:"odd-rows", ans:tablens, a:"paragraph-style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"default-style-name"}, {ens:textns, en:"alphabetical-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"h", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"index-source-style", ans:textns, a:"style-name"}, - {ens:textns, en:"object-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"p", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"user-index-entry-template", ans:textns, a:"style-name"}, {ens:stylens, en:"page-layout-properties", ans:stylens, a:"register-truth-ref-style-name"}], - "chart":[{ens:chartns, en:"axis", ans:chartns, a:"style-name"}, {ens:chartns, en:"chart", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-label", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-point", ans:chartns, a:"style-name"}, {ens:chartns, en:"equation", ans:chartns, a:"style-name"}, {ens:chartns, en:"error-indicator", ans:chartns, a:"style-name"}, {ens:chartns, en:"floor", ans:chartns, a:"style-name"}, {ens:chartns, en:"footer", ans:chartns, a:"style-name"}, {ens:chartns, en:"grid", - ans:chartns, a:"style-name"}, {ens:chartns, en:"legend", ans:chartns, a:"style-name"}, {ens:chartns, en:"mean-value", ans:chartns, a:"style-name"}, {ens:chartns, en:"plot-area", ans:chartns, a:"style-name"}, {ens:chartns, en:"regression-curve", ans:chartns, a:"style-name"}, {ens:chartns, en:"series", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-gain-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-loss-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-range-line", - ans:chartns, a:"style-name"}, {ens:chartns, en:"subtitle", ans:chartns, a:"style-name"}, {ens:chartns, en:"title", ans:chartns, a:"style-name"}, {ens:chartns, en:"wall", ans:chartns, a:"style-name"}], "section":[{ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index", ans:textns, a:"style-name"}, {ens:textns, en:"index-title", ans:textns, a:"style-name"}, {ens:textns, en:"object-index", - ans:textns, a:"style-name"}, {ens:textns, en:"section", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content", ans:textns, a:"style-name"}, {ens:textns, en:"table-index", ans:textns, a:"style-name"}, {ens:textns, en:"user-index", ans:textns, a:"style-name"}], "ruby":[{ens:textns, en:"ruby", ans:textns, a:"style-name"}], "table":[{ens:dbns, en:"query", ans:dbns, a:"style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"style-name"}, {ens:tablens, en:"background", ans:tablens, - a:"style-name"}, {ens:tablens, en:"table", ans:tablens, a:"style-name"}], "table-column":[{ens:dbns, en:"column", ans:dbns, a:"style-name"}, {ens:tablens, en:"table-column", ans:tablens, a:"style-name"}], "table-row":[{ens:dbns, en:"query", ans:dbns, a:"default-row-style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"default-row-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"style-name"}], "table-cell":[{ens:dbns, en:"column", ans:dbns, a:"default-cell-style-name"}, {ens:tablens, - en:"table-column", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-rows", ans:tablens, a:"style-name"}, - {ens:tablens, en:"first-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-rows", ans:tablens, a:"style-name"}, {ens:tablens, en:"table-cell", ans:tablens, a:"style-name"}], "graphic":[{ens:dr3dns, en:"cube", ans:drawns, a:"style-name"}, {ens:dr3dns, - en:"extrude", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:drawns, a:"style-name"}, {ens:drawns, en:"caption", ans:drawns, a:"style-name"}, {ens:drawns, en:"circle", ans:drawns, a:"style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"style-name"}, {ens:drawns, en:"control", ans:drawns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"style-name"}, {ens:drawns, - en:"ellipse", ans:drawns, a:"style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"style-name"}, {ens:drawns, en:"g", ans:drawns, a:"style-name"}, {ens:drawns, en:"line", ans:drawns, a:"style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:drawns, a:"style-name"}, {ens:drawns, en:"path", ans:drawns, a:"style-name"}, {ens:drawns, en:"polygon", ans:drawns, a:"style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"style-name"}, {ens:drawns, en:"rect", - ans:drawns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"style-name"}], "presentation":[{ens:dr3dns, en:"cube", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"extrude", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:presentationns, a:"style-name"}, {ens:drawns, en:"caption", - ans:presentationns, a:"style-name"}, {ens:drawns, en:"circle", ans:presentationns, a:"style-name"}, {ens:drawns, en:"connector", ans:presentationns, a:"style-name"}, {ens:drawns, en:"control", ans:presentationns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:presentationns, a:"style-name"}, {ens:drawns, en:"ellipse", ans:presentationns, a:"style-name"}, {ens:drawns, en:"frame", ans:presentationns, a:"style-name"}, {ens:drawns, en:"g", ans:presentationns, a:"style-name"}, {ens:drawns, en:"line", - ans:presentationns, a:"style-name"}, {ens:drawns, en:"measure", ans:presentationns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:presentationns, a:"style-name"}, {ens:drawns, en:"path", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polygon", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polyline", ans:presentationns, a:"style-name"}, {ens:drawns, en:"rect", ans:presentationns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:presentationns, a:"style-name"}, {ens:officens, - en:"annotation", ans:presentationns, a:"style-name"}], "drawing-page":[{ens:drawns, en:"page", ans:drawns, a:"style-name"}, {ens:presentationns, en:"notes", ans:drawns, a:"style-name"}, {ens:stylens, en:"handout-master", ans:drawns, a:"style-name"}, {ens:stylens, en:"master-page", ans:drawns, a:"style-name"}], "list-style":[{ens:textns, en:"list", ans:textns, a:"style-name"}, {ens:textns, en:"numbered-paragraph", ans:textns, a:"style-name"}, {ens:textns, en:"list-item", ans:textns, a:"style-override"}, - {ens:stylens, en:"style", ans:stylens, a:"list-style-name"}], "data":[{ens:stylens, en:"style", ans:stylens, a:"data-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"percentage-data-style-name"}, {ens:presentationns, en:"date-time-decl", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"database-display", ans:stylens, a:"data-style-name"}, {ens:textns, - en:"date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"editing-duration", ans:stylens, a:"data-style-name"}, {ens:textns, en:"expression", ans:stylens, a:"data-style-name"}, {ens:textns, en:"meta-field", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-time", ans:stylens, - a:"data-style-name"}, {ens:textns, en:"table-formula", ans:stylens, a:"data-style-name"}, {ens:textns, en:"time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-defined", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-input", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-input", ans:stylens, a:"data-style-name"}, {ens:textns, - en:"variable-set", ans:stylens, a:"data-style-name"}], "page-layout":[{ens:presentationns, en:"notes", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"handout-master", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"master-page", ans:stylens, a:"page-layout-name"}]}, elements, xpath = new xmldom.XPath; - function hasDerivedStyles(odfbody, nsResolver, styleElement) { - var nodes, xp, resolver = nsResolver("style"), styleName = styleElement.getAttributeNS(resolver, "name"), styleFamily = styleElement.getAttributeNS(resolver, "family"); - xp = "//style:*[@style:parent-style-name='" + styleName + "'][@style:family='" + styleFamily + "']"; - nodes = xpath.getODFElementsWithXPath(odfbody, xp, nsResolver); - if(nodes.length) { - return true - } - return false - } - function prefixUsedStyleNames(styleUsingElementsRoot, prefix) { - var elname = elements[styleUsingElementsRoot.localName], elns = elname && elname[styleUsingElementsRoot.namespaceURI], length = elns ? elns.length : 0, i, stylename, e; - for(i = 0;i < length;i += 1) { - stylename = styleUsingElementsRoot.getAttributeNS(elns[i].ns, elns[i].localname); - if(stylename) { - styleUsingElementsRoot.setAttributeNS(elns[i].ns, nsprefixes[elns[i].ns] + elns[i].localname, prefix + stylename) - } - } - i = styleUsingElementsRoot.firstChild; - while(i) { - if(i.nodeType === Node.ELEMENT_NODE) { - e = (i); - prefixUsedStyleNames(e, prefix) - } - i = i.nextSibling - } - } - function prefixStyleName(styleElement, prefix) { - var stylename = styleElement.getAttributeNS(drawns, "name"), ns; - if(stylename) { - ns = drawns - }else { - stylename = styleElement.getAttributeNS(stylens, "name"); - if(stylename) { - ns = stylens - } - } - if(ns) { - styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", prefix + stylename) - } - } - function prefixStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) { - var s; - if(styleElementsRoot) { - s = styleElementsRoot.firstChild; - while(s) { - if(s.nodeType === Node.ELEMENT_NODE) { - prefixStyleName((s), prefix) - } - s = s.nextSibling - } - prefixUsedStyleNames(styleElementsRoot, prefix); - if(styleUsingElementsRoot) { - prefixUsedStyleNames(styleUsingElementsRoot, prefix) - } - } - } - function removeRegExpFromUsedStyleNames(styleUsingElementsRoot, regExp) { - var elname = elements[styleUsingElementsRoot.localName], elns = elname && elname[styleUsingElementsRoot.namespaceURI], length = elns ? elns.length : 0, i, stylename, e; - for(i = 0;i < length;i += 1) { - stylename = styleUsingElementsRoot.getAttributeNS(elns[i].ns, elns[i].localname); - if(stylename) { - stylename = stylename.replace(regExp, ""); - styleUsingElementsRoot.setAttributeNS(elns[i].ns, nsprefixes[elns[i].ns] + elns[i].localname, stylename) - } - } - i = styleUsingElementsRoot.firstChild; - while(i) { - if(i.nodeType === Node.ELEMENT_NODE) { - e = (i); - removeRegExpFromUsedStyleNames(e, regExp) - } - i = i.nextSibling - } - } - function removeRegExpFromStyleName(styleElement, regExp) { - var stylename = styleElement.getAttributeNS(drawns, "name"), ns; - if(stylename) { - ns = drawns - }else { - stylename = styleElement.getAttributeNS(stylens, "name"); - if(stylename) { - ns = stylens - } - } - if(ns) { - stylename = stylename.replace(regExp, ""); - styleElement.setAttributeNS(ns, nsprefixes[ns] + "name", stylename) - } - } - function removePrefixFromStyleNames(styleElementsRoot, prefix, styleUsingElementsRoot) { - var s, regExp = new RegExp("^" + prefix); - if(styleElementsRoot) { - s = styleElementsRoot.firstChild; - while(s) { - if(s.nodeType === Node.ELEMENT_NODE) { - removeRegExpFromStyleName((s), regExp) - } - s = s.nextSibling - } - removeRegExpFromUsedStyleNames(styleElementsRoot, regExp); - if(styleUsingElementsRoot) { - removeRegExpFromUsedStyleNames(styleUsingElementsRoot, regExp) - } - } - } - function determineStylesForNode(node, usedStyles) { - var elname = elements[node.localName], elns = elname && elname[node.namespaceURI], length = elns ? elns.length : 0, stylename, keyname, map, i; - for(i = 0;i < length;i += 1) { - stylename = node.getAttributeNS(elns[i].ns, elns[i].localname); - if(stylename) { - usedStyles = usedStyles || {}; - keyname = elns[i].keyname; - map = usedStyles[keyname] = usedStyles[keyname] || {}; - map[stylename] = 1 - } - } - return usedStyles - } - function determineUsedStyles(styleUsingElementsRoot, usedStyles) { - var i, e; - determineStylesForNode(styleUsingElementsRoot, usedStyles); - i = styleUsingElementsRoot.firstChild; - while(i) { - if(i.nodeType === Node.ELEMENT_NODE) { - e = (i); - determineUsedStyles(e, usedStyles) - } - i = i.nextSibling - } - } - function StyleDefinition(key, name, family) { - this.key = key; - this.name = name; - this.family = family; - this.requires = {} - } - function getStyleDefinition(stylename, stylefamily, knownStyles) { - var styleKey = stylename + '"' + stylefamily, styleDefinition = knownStyles[styleKey]; - if(!styleDefinition) { - styleDefinition = knownStyles[styleKey] = new StyleDefinition(styleKey, stylename, stylefamily) - } - return styleDefinition - } - function determineDependentStyles(styleUsingElementsRoot, styleScope, knownStyles) { - var elname = elements[styleUsingElementsRoot.localName], elns = elname && elname[styleUsingElementsRoot.namespaceURI], length = elns ? elns.length : 0, newScopeName = styleUsingElementsRoot.getAttributeNS(stylens, "name"), newScopeFamily = styleUsingElementsRoot.getAttributeNS(stylens, "family"), referencedStyleName, referencedStyleFamily, referencedStyleDef, i, e; - if(newScopeName && newScopeFamily) { - styleScope = getStyleDefinition(newScopeName, newScopeFamily, knownStyles) - } - if(styleScope) { - for(i = 0;i < length;i += 1) { - referencedStyleName = styleUsingElementsRoot.getAttributeNS(elns[i].ns, elns[i].localname); - if(referencedStyleName) { - referencedStyleFamily = elns[i].keyname; - referencedStyleDef = getStyleDefinition(referencedStyleName, referencedStyleFamily, knownStyles); - styleScope.requires[referencedStyleDef.key] = referencedStyleDef - } - } - } - i = styleUsingElementsRoot.firstChild; - while(i) { - if(i.nodeType === Node.ELEMENT_NODE) { - e = (i); - determineDependentStyles(e, styleScope, knownStyles) - } - i = i.nextSibling - } - return knownStyles - } - function inverse(elementstyles) { - var keyname, i, l, list, item, e = {}, map, array; - for(keyname in elementstyles) { - if(elementstyles.hasOwnProperty(keyname)) { - list = elementstyles[keyname]; - l = list.length; - for(i = 0;i < l;i += 1) { - item = list[i]; - map = e[item.en] = e[item.en] || {}; - array = map[item.ens] = map[item.ens] || []; - array.push({ns:item.ans, localname:item.a, keyname:keyname}) - } - } - } - return e - } - function mergeRequiredStyles(styleDependency, usedStyles) { - var family = usedStyles[styleDependency.family]; - if(!family) { - family = usedStyles[styleDependency.family] = {} - } - family[styleDependency.name] = 1; - Object.keys((styleDependency.requires)).forEach(function(requiredStyleKey) { - mergeRequiredStyles((styleDependency.requires[requiredStyleKey]), usedStyles) - }) - } - function mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles) { - var automaticStyles = determineDependentStyles(automaticStylesRoot, null, {}); - Object.keys(automaticStyles).forEach(function(styleKey) { - var automaticStyleDefinition = automaticStyles[styleKey], usedFamily = usedStyles[automaticStyleDefinition.family]; - if(usedFamily && usedFamily.hasOwnProperty(automaticStyleDefinition.name)) { - mergeRequiredStyles(automaticStyleDefinition, usedStyles) - } - }) - } - function collectUsedFontFaces(usedFontFaceDeclMap, styleElementsRoot) { - var localNames = ["font-name", "font-name-asian", "font-name-complex"], currentNode; - function collectByAttribute(localName) { - var fontFaceName = currentNode.getAttributeNS(stylens, localName); - if(fontFaceName) { - usedFontFaceDeclMap[fontFaceName] = true - } - } - if(styleElementsRoot) { - currentNode = styleElementsRoot.firstChild; - while(currentNode) { - if(currentNode.nodeType === Node.ELEMENT_NODE) { - localNames.forEach(collectByAttribute); - collectUsedFontFaces(usedFontFaceDeclMap, (currentNode)) - } - currentNode = currentNode.nextSibling - } - } - } - this.collectUsedFontFaces = collectUsedFontFaces; - function changeFontFaceNames(styleElementsRoot, fontFaceNameChangeMap) { - var localNames = ["font-name", "font-name-asian", "font-name-complex"], currentNode; - function changeFontFaceNameByAttribute(localName) { - var fontFaceName = currentNode.getAttributeNS(stylens, localName); - if(fontFaceName && fontFaceNameChangeMap.hasOwnProperty(fontFaceName)) { - currentNode.setAttributeNS(stylens, "style:" + localName, fontFaceNameChangeMap[fontFaceName]) - } - } - if(styleElementsRoot) { - currentNode = styleElementsRoot.firstChild; - while(currentNode) { - if(currentNode.nodeType === Node.ELEMENT_NODE) { - localNames.forEach(changeFontFaceNameByAttribute); - changeFontFaceNames((currentNode), fontFaceNameChangeMap) - } - currentNode = currentNode.nextSibling - } - } - } - this.changeFontFaceNames = changeFontFaceNames; - this.UsedStyleList = function(styleUsingElementsRoot, automaticStylesRoot) { - var usedStyles = {}; - this.uses = function(element) { - var localName = element.localName, name = element.getAttributeNS(drawns, "name") || element.getAttributeNS(stylens, "name"), keyName, map; - if(localName === "style") { - keyName = element.getAttributeNS(stylens, "family") - }else { - if(element.namespaceURI === numberns) { - keyName = "data" - }else { - keyName = localName - } - } - map = usedStyles[keyName]; - return map ? map[name] > 0 : false - }; - determineUsedStyles(styleUsingElementsRoot, usedStyles); - if(automaticStylesRoot) { - mergeUsedAutomaticStyles(automaticStylesRoot, usedStyles) - } - }; - this.hasDerivedStyles = hasDerivedStyles; - this.prefixStyleNames = prefixStyleNames; - this.removePrefixFromStyleNames = removePrefixFromStyleNames; - this.determineStylesForNode = determineStylesForNode; - elements = inverse(elementstyles) -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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) { - var name = e && e.localName; - return name === "frame" && (e.namespaceURI === drawns && e.getAttributeNS(textns, "anchor-type") === "as-char") - } - this.isCharacterFrame = isCharacterFrame; - 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(e) { - var localName = e && e.localName; - if(/^(span|p|h|a|meta)$/.test(localName) && e.namespaceURI === textns || localName === "span" && e.className === "annotationHighlight") { - return true - } - return false - } - 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") - }else { - r = isCharacterFrame(e) - } - } - return r - } - this.isCharacterElement = isCharacterElement; - 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; - while(node) { - if(node.nodeType === Node.TEXT_NODE) { - if(node.length === 0) { - node = previousNode(node) - }else { - return!isODFWhitespace(node.data.substr(node.length - 1, 1)) - } - }else { - if(isCharacterElement(node)) { - r = isSpaceElement(node) === false; - node = null - }else { - node = previousNode(node) - } - } - } - return r - } - this.scanLeftForNonSpace = scanLeftForNonSpace; - function lookLeftForCharacter(node) { - var text, r = 0; - if(node.nodeType === Node.TEXT_NODE && node.length > 0) { - text = node.data; - if(!isODFWhitespace(text.substr(text.length - 1, 1))) { - r = 1 - }else { - if(text.length === 1) { - r = scanLeftForNonSpace(previousNode(node)) ? 2 : 0 - }else { - r = isODFWhitespace(text.substr(text.length - 2, 1)) ? 0 : 2 - } - } - }else { - if(isCharacterElement(node)) { - r = 1 - } - } - return r - } - this.lookLeftForCharacter = lookLeftForCharacter; - function lookRightForCharacter(node) { - var r = false; - if(node && (node.nodeType === Node.TEXT_NODE && node.length > 0)) { - r = !isODFWhitespace(node.data.substr(0, 1)) - }else { - if(isCharacterElement(node)) { - r = true - } - } - return r - } - this.lookRightForCharacter = lookRightForCharacter; - function scanLeftForAnyCharacter(node) { - var r = false; - node = node && lastChild(node); - while(node) { - if(node.nodeType === Node.TEXT_NODE && (node.length > 0 && !isODFWhitespace(node.data))) { - r = true; - break - } - if(isCharacterElement(node)) { - r = true; - break - } - node = previousNode(node) - } - return r - } - this.scanLeftForAnyCharacter = scanLeftForAnyCharacter; - function scanRightForAnyCharacter(node) { - var r = false; - node = node && firstChild(node); - while(node) { - if(node.nodeType === Node.TEXT_NODE && (node.length > 0 && !isODFWhitespace(node.data))) { - r = true; - break - } - if(isCharacterElement(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(isCharacterElement(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 getImpactedParagraphs(range) { - var outerContainer = (range.commonAncestorContainer), impactedParagraphs = []; - 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) - } - return impactedParagraphs.filter(function(n) { - return domUtils.rangeIntersectsNode(range, n) - }) - } - 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(isCharacterElement(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 - - @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 . - - 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 - - @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 . - - 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("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 - } - this.isStyleApplied = function(textNode) { - var appliedStyle = formatting.getAppliedStylesForElement(textNode); - 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(node) { - if(node.parentNode !== styledContainer) { - styledContainer.appendChild(node) - } - }); - 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[textProperties], "applyStyle without any text properties"); - textPropsOnly[textProperties] = info[textProperties]; - styleCache = new StyleManager(textPropsOnly); - styleLookup = new StyleLookup(textPropsOnly); - textNodes.forEach(function(n) { - isStyled = styleLookup.isStyleApplied(n); - if(isStyled === false) { - container = moveToNewSpan((n), limits); - styleCache.applyStyleToContainer(container) - } - }) - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.Style2CSS = function Style2CSS() { - var drawns = odf.Namespaces.drawns, fons = odf.Namespaces.fons, 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 = new xmldom.XPath, cssUnits = new core.CSSUnits; - function getStyleMap(stylesnode) { - var stylemap = {}, node, name, family, style; - if(!stylesnode) { - return stylemap - } - node = stylesnode.firstChild; - 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 && node.getAttributeNS(stylens, "name"); - if(!name) { - name = "" - } - style = stylemap[family] = stylemap[family] || {}; - style[name] = node - } - node = node.nextSibling - } - return stylemap - } - function findStyle(stylestree, name) { - if(!name || !stylestree) { - return null - } - if(stylestree[name]) { - return stylestree[name] - } - var n, style; - for(n in stylestree) { - if(stylestree.hasOwnProperty(n)) { - style = findStyle(stylestree[n].derivedStyles, name); - if(style) { - return style - } - } - } - return null - } - function addStyleToStyleTree(stylename, stylesmap, stylestree) { - var style = stylesmap[stylename], parentname, parentstyle; - if(!style) { +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 } - parentname = style.getAttributeNS(stylens, "parent-style-name"); - parentstyle = null; - if(parentname) { - parentstyle = findStyle(stylestree, parentname); - if(!parentstyle && stylesmap[parentname]) { - addStyleToStyleTree(parentname, stylesmap, stylestree); - parentstyle = stylesmap[parentname]; - stylesmap[parentname] = null + if(!blinking || reset) { + if(reset && blinkTimeout !== undefined) { + runtime.clearTimeout(blinkTimeout) } - } - if(parentstyle) { - if(!parentstyle.derivedStyles) { - parentstyle.derivedStyles = {} - } - parentstyle.derivedStyles[stylename] = style - }else { - stylestree[stylename] = style + blinking = true; + span.style.opacity = reset || span.style.opacity === "0" ? "1" : "0"; + blinkTimeout = runtime.setTimeout(function() { + blinking = false; + blink(false) + }, 500) } } - function addStyleMapToStyleTree(stylesmap, stylestree) { - var name; - for(name in stylesmap) { - if(stylesmap.hasOwnProperty(name)) { - addStyleToStyleTree(name, stylesmap, stylestree); - stylesmap[name] = null + 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 createSelector(family, name) { - var prefix = familynamespaceprefixes[family], namepart, selector; - if(prefix === null) { - return null - } - if(name) { - namepart = "[" + prefix + '|style-name="' + name + '"]' + function handleUpdate() { + var selectionRect = getSelectionRect(), zoomLevel = cursor.getOdtDocument().getOdfCanvas().getZoomLevel(), caretRect; + if(isShown && cursor.getSelectionType() === ops.OdtCursor.RangeSelection) { + span.style.visibility = "visible" }else { - namepart = "" + span.style.visibility = "hidden" } - if(prefix === "presentation") { - prefix = "draw"; - if(name) { - namepart = '[presentation|style-name="' + name + '"]' + 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 { - namepart = "" + cursorNode.removeChild(span); + callback() } - } - selector = prefix + "|" + familytagnames[family].join(namepart + "," + prefix + "|") + namepart; - return selector - } - function getSelectors(family, name, node) { - var selectors = [], n, ss, s; - selectors.push(createSelector(family, name)); - for(n in node.derivedStyles) { - if(node.derivedStyles.hasOwnProperty(n)) { - ss = getSelectors(family, n, node.derivedStyles[n]); - for(s in ss) { - if(ss.hasOwnProperty(s)) { - selectors.push(ss[s]) - } - } - } - } - return selectors - } - function getDirectChild(node, ns, name) { - if(!node) { - return null - } - var c = node.firstChild, e; - while(c) { - if(c.namespaceURI === ns && c.localName === name) { - e = (c); - return e - } - c = c.nextSibling - } - return null - } - 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 = "", r, value; - for(r in mapping) { - if(mapping.hasOwnProperty(r)) { - r = mapping[r]; - 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.resolvePrefix)[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 = "", imageProps, url, element, lineHeight; - rule += applySimpleMapping(props, paragraphPropertySimpleMapping); - imageProps = props.getElementsByTagNameNS(stylens, "background-image"); - if(imageProps.length > 0) { - url = imageProps.item(0).getAttributeNS(xlinkns, "href"); - if(url) { - rule += "background-image: url('odfkit:" + url + "');"; - element = (imageProps.item(0)); - rule += applySimpleMapping(element, 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 hexToRgb(hex) { - var result, shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - hex = hex.replace(shorthandRegex, function(m, r, g, b) { - return r + r + g + g + b + b - }); - 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 = getDirectChild(node, stylens, "text-properties"); - if(properties) { - rule += getTextProperties(properties) - } - properties = getDirectChild(node, stylens, "paragraph-properties"); - if(properties) { - rule += getParagraphProperties(properties) - } - properties = getDirectChild(node, stylens, "graphic-properties"); - if(properties) { - rule += getGraphicProperties(properties) - } - properties = getDirectChild(node, stylens, "drawing-page-properties"); - if(properties) { - rule += getDrawingPageProperties(properties) - } - properties = getDirectChild(node, stylens, "table-cell-properties"); - if(properties) { - rule += getTableCellProperties(properties) - } - properties = getDirectChild(node, stylens, "table-row-properties"); - if(properties) { - rule += getTableRowProperties(properties) - } - properties = getDirectChild(node, stylens, "table-column-properties"); - if(properties) { - rule += getTableColumnProperties(properties) - } - properties = getDirectChild(node, 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 = prefix || ""; - if(stylemap.hasOwnProperty(style)) { - content += " counter(list, " + stylemap[style] + ")" - }else { - if(style) { - content += "'" + style + "';" - }else { - content += " ''" - } - } - if(suffix) { - content += " '" + suffix + "'" - } - return"content: " + content + ";" - } - function getImageRule() { - var rule = "content: none;"; - return rule - } - 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 = utils.getFirstNonWhitespaceChild(node), listLevelLabelAlign = utils.getFirstNonWhitespaceChild(listLevelProps), labelAlignAttr, bulletIndent, listIndent, bulletWidth, rule; - if(listLevelLabelAlign) { - labelAlignAttr = listLevelLabelAlign.attributes; - bulletIndent = labelAlignAttr["fo:text-indent"] ? labelAlignAttr["fo:text-indent"].value : undefined; - listIndent = labelAlignAttr["fo:margin-left"] ? labelAlignAttr["fo:margin-left"].value : undefined - } - 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 - } - itemSelector = selector; - itemSelector += " > text|list-item > *:not(text|list):first-child"; - if(listIndent !== undefined) { - listItemRule = itemSelector + "{margin-left:" + listIndent + ";}"; - sheet.insertRule(listItemRule, sheet.cssRules.length) - } - selector += " > text|list-item > *:not(text|list):first-child:before"; - rule = itemrule; - rule = selector + "{" + rule + ";"; - rule += "counter-increment:list;"; - rule += "margin-left:" + bulletIndent + ";"; - rule += "width:" + bulletWidth + ";"; - rule += "display:inline-block}"; - try { - sheet.insertRule(rule, sheet.cssRules.length) - }catch(e) { - throw e; - } - } - function addPageStyleRules(sheet, node) { - var rule = "", imageProps, url, element, contentLayoutRule = "", pageSizeRule = "", props = node.getElementsByTagNameNS(stylens, "page-layout-properties")[0], masterStyles = props.parentNode.parentNode.parentNode.masterStyles, masterPages, masterStyleName = "", i; - rule += applySimpleMapping(props, pageContentPropertySimpleMapping); - imageProps = props.getElementsByTagNameNS(stylens, "background-image"); - if(imageProps.length > 0) { - url = imageProps.item(0).getAttributeNS(xlinkns, "href"); - if(url) { - rule += "background-image: url('odfkit:" + url + "');"; - element = (imageProps.item(0)); - rule += applySimpleMapping(element, bgImageSimpleMapping) - } - } - if(documentType === "presentation") { - if(masterStyles) { - masterPages = masterStyles.getElementsByTagNameNS(stylens, "master-page"); - for(i = 0;i < masterPages.length;i += 1) { - if(masterPages[i].getAttributeNS(stylens, "page-layout-name") === props.parentNode.getAttributeNS(stylens, "name")) { - masterStyleName = masterPages[i].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; - } - } - } - } - }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) - }else { - if(family === "page") { - addPageStyleRules(sheet, node) - }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, name, rule, 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) 2013 KO GmbH - - @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 . - @licend - - @source: http://www.webodf.org/ - @source: https://github.com/kogmbh/WebODF/ -*/ -runtime.loadClass("odf.Namespaces"); -runtime.loadClass("core.DomUtils"); -odf.MetadataManager = function MetadataManager(metaElement) { - var domUtils = new core.DomUtils, metadata = {}; - function setMetadata(setProperties, removedProperties) { - if(setProperties) { - Object.keys(setProperties).forEach(function(key) { - metadata[key] = setProperties[key] - }); - domUtils.mapKeyValObjOntoNode(metaElement, setProperties, odf.Namespaces.resolvePrefix) - } - if(removedProperties) { - removedProperties.forEach(function(name) { - delete metadata[name] - }); - domUtils.removeKeyElementsFromNode(metaElement, removedProperties, odf.Namespaces.resolvePrefix) - } - } - this.setMetadata = setMetadata; - this.incrementEditingCycles = function() { - var cycles = parseInt(metadata["meta:editing-cycles"] || 0, 10) + 1; - setMetadata({"meta:editing-cycles":cycles}, null) + }) }; function init() { - metadata = domUtils.getKeyValRepresentationOfNode(metaElement, odf.Namespaces.lookupPrefix) + 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() }; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.Base64"); -runtime.loadClass("core.Zip"); -runtime.loadClass("xmldom.LSSerializer"); -runtime.loadClass("odf.StyleInfo"); -runtime.loadClass("odf.Namespaces"); -runtime.loadClass("odf.OdfNodeFilter"); -runtime.loadClass("odf.MetadataManager"); -odf.OdfContainer = function() { - var styleInfo = new odf.StyleInfo, metadataManager, 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"; - function getDirectChild(node, ns, name) { - node = node ? node.firstChild : null; - while(node) { - if(node.localName === name && node.namespaceURI === ns) { - return(node) - } - node = node.nextSibling - } - return null - } - function getNodePosition(child) { - var i, l = nodeorder.length; - for(i = 0;i < l;i += 1) { - if(child.namespaceURI === officens && child.localName === nodeorder[i]) { - return i - } - } - return-1 - } - function OdfStylesFilter(styleUsingElementsRoot, automaticStyles) { - var usedStyleList = new styleInfo.UsedStyleList(styleUsingElementsRoot, automaticStyles), odfNodeFilter = new odf.OdfNodeFilter; - this.acceptNode = function(node) { - var result = odfNodeFilter.acceptNode(node); - if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode === automaticStyles && node.nodeType === Node.ELEMENT_NODE)) { - if(usedStyleList.uses((node))) { - result = NodeFilter.FILTER_ACCEPT - }else { - result = NodeFilter.FILTER_REJECT - } - } - return result - } - } - function OdfContentFilter(styleUsingElementsRoot, automaticStyles) { - var odfStylesFilter = new OdfStylesFilter(styleUsingElementsRoot, automaticStyles); - this.acceptNode = function(node) { - var result = odfStylesFilter.acceptNode(node); - if(result === NodeFilter.FILTER_ACCEPT && (node.parentNode && (node.parentNode.namespaceURI === odf.Namespaces.textns && (node.parentNode.localName === "s" || node.parentNode.localName === "tab")))) { - result = NodeFilter.FILTER_REJECT - } - return result - } - } - function setChild(node, child) { - if(!child) { - return - } - var childpos = getNodePosition(child), pos, c = node.firstChild; - if(childpos === -1) { - return - } - while(c) { - pos = getNodePosition(c); - if(pos !== -1 && pos > childpos) { - break - } - c = c.nextSibling - } - node.insertBefore(child, c) - } - function ODFElement() { - } - function ODFDocumentElement(odfcontainer) { - this.OdfContainer = odfcontainer - } - ODFDocumentElement.prototype = new ODFElement; - ODFDocumentElement.prototype.constructor = ODFDocumentElement; - ODFDocumentElement.namespaceURI = officens; - ODFDocumentElement.localName = "document"; - function OdfPart(name, mimetype, container, zip) { - var self = this; - this.size = 0; - this.type = null; - this.name = name; - this.container = container; - this.url = null; - this.mimetype = null; - this.document = null; - this.onreadystatechange = null; - this.onchange = null; - this.EMPTY = 0; - this.LOADING = 1; - this.DONE = 2; - this.state = this.EMPTY; - this.load = function() { - if(zip === null) { - return - } - this.mimetype = mimetype; - zip.loadAsDataURL(name, mimetype, function(err, url) { - if(err) { - runtime.log(err) - } - self.url = url; - if(self.onchange) { - self.onchange(self) - } - if(self.onstatereadychange) { - self.onstatereadychange(self) - } - }) - } - } - OdfPart.prototype.load = function() { - }; - OdfPart.prototype.getUrl = function() { - if(this.data) { - return"data:;base64," + base64.toBase64(this.data) - } - return null - }; - odf.OdfContainer = function OdfContainer(url, onstatereadychange) { - var self = this, zip, partMimetypes = {}, contentElement; - this.onstatereadychange = onstatereadychange; - this.onchange = null; - this.state = null; - this.rootElement = null; - function removeProcessingInstructions(element) { - var n = element.firstChild, next, e; - while(n) { - next = n.nextSibling; - if(n.nodeType === Node.ELEMENT_NODE) { - e = (n); - removeProcessingInstructions(e) - }else { - if(n.nodeType === Node.PROCESSING_INSTRUCTION_NODE) { - element.removeChild(n) - } - } - n = next - } - } - function setAutomaticStylesScope(stylesRootElement, scope) { - var n = stylesRootElement && stylesRootElement.firstChild; - while(n) { - if(n.nodeType === Node.ELEMENT_NODE) { - n.setAttributeNS(webodfns, "scope", scope) - } - n = n.nextSibling - } - } - function mergeFontFaceDecls(targetFontFaceDeclsRootElement, sourceFontFaceDeclsRootElement) { - var n, s, fontFaceName, newFontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap, fontFaceNameChangeMap = {}; - function unusedKey(key, map1, map2) { - var i = 0, postFixedKey; - key = key.replace(/\d+$/, ""); - postFixedKey = key; - while(map1.hasOwnProperty(postFixedKey) || map2.hasOwnProperty(postFixedKey)) { - i += 1; - postFixedKey = key + i - } - return postFixedKey - } - function mapByFontFaceName(fontFaceDecls) { - var fn, result = {}; - fn = fontFaceDecls.firstChild; - while(fn) { - if(fn.nodeType === Node.ELEMENT_NODE && (fn.namespaceURI === stylens && fn.localName === "font-face")) { - fontFaceName = fn.getAttributeNS(stylens, "name"); - result[fontFaceName] = fn - } - fn = fn.nextSibling - } - return result - } - targetFontFaceDeclsMap = mapByFontFaceName(targetFontFaceDeclsRootElement); - sourceFontFaceDeclsMap = mapByFontFaceName(sourceFontFaceDeclsRootElement); - n = sourceFontFaceDeclsRootElement.firstChild; - while(n) { - s = n.nextSibling; - if(n.nodeType === Node.ELEMENT_NODE && (n.namespaceURI === stylens && n.localName === "font-face")) { - fontFaceName = n.getAttributeNS(stylens, "name"); - if(targetFontFaceDeclsMap.hasOwnProperty(fontFaceName)) { - if(!n.isEqualNode(targetFontFaceDeclsMap[fontFaceName])) { - newFontFaceName = unusedKey(fontFaceName, targetFontFaceDeclsMap, sourceFontFaceDeclsMap); - n.setAttributeNS(stylens, "style:name", newFontFaceName); - targetFontFaceDeclsRootElement.appendChild(n); - targetFontFaceDeclsMap[newFontFaceName] = (n); - delete sourceFontFaceDeclsMap[fontFaceName]; - fontFaceNameChangeMap[fontFaceName] = newFontFaceName - } - }else { - targetFontFaceDeclsRootElement.appendChild(n); - targetFontFaceDeclsMap[fontFaceName] = (n); - delete sourceFontFaceDeclsMap[fontFaceName] - } - } - n = s - } - return fontFaceNameChangeMap - } - function cloneStylesInScope(stylesRootElement, scope) { - var copy = null, n, s, scopeAttrValue; - if(stylesRootElement) { - copy = stylesRootElement.cloneNode(true); - n = copy.firstChild; - while(n) { - s = n.nextSibling; - if(n.nodeType === Node.ELEMENT_NODE) { - scopeAttrValue = n.getAttributeNS(webodfns, "scope"); - if(scopeAttrValue && scopeAttrValue !== scope) { - copy.removeChild(n) - } - } - n = s - } - } - return copy - } - function cloneFontFaceDeclsUsedInStyles(fontFaceDeclsRootElement, stylesRootElementList) { - var copy = null, n, nextSibling, fontFaceName, usedFontFaceDeclMap = {}; - if(fontFaceDeclsRootElement) { - stylesRootElementList.forEach(function(stylesRootElement) { - styleInfo.collectUsedFontFaces(usedFontFaceDeclMap, stylesRootElement) +gui.EventManager = function EventManager(odtDocument) { + var canvasElement = odtDocument.getOdfCanvas().getElement(), window = runtime.getWindow(), bindToDirectHandler = {"beforecut":true, "beforepaste":true}, bindToWindow; + 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) }); - copy = fontFaceDeclsRootElement.cloneNode(true); - n = copy.firstChild; - while(n) { - nextSibling = n.nextSibling; - if(n.nodeType === Node.ELEMENT_NODE) { - fontFaceName = n.getAttributeNS(stylens, "name"); - if(!usedFontFaceDeclMap[fontFaceName]) { - copy.removeChild(n) - } - } - n = nextSibling - } + runtime.setTimeout(function() { + recentEvents.splice(recentEvents.indexOf(e), 1) + }, 0) } - return copy - } - function initializeMetadataManager(metaRootElement) { - metadataManager = new odf.MetadataManager(metaRootElement) - } - function importRootNode(xmldoc) { - var doc = self.rootElement.ownerDocument, node; - if(xmldoc) { - removeProcessingInstructions(xmldoc.documentElement); - try { - node = doc.importNode(xmldoc.documentElement, true) - }catch(ignore) { - } - } - return node - } - function setState(state) { - self.state = state; - if(self.onchange) { - self.onchange(self) - } - if(self.onstatereadychange) { - self.onstatereadychange(self) - } - } - function setRootElement(root) { - contentElement = null; - self.rootElement = root; - root.fontFaceDecls = getDirectChild(root, officens, "font-face-decls"); - root.styles = getDirectChild(root, officens, "styles"); - 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") - } - function handleFlatXml(xmldoc) { - var root = importRootNode(xmldoc); - if(!root || (root.localName !== "document" || root.namespaceURI !== officens)) { - setState(OdfContainer.INVALID); - return - } - setRootElement((root)); - setState(OdfContainer.DONE) - } - function handleStylesXml(xmldoc) { - var node = importRootNode(xmldoc), root = self.rootElement; - if(!node || (node.localName !== "document-styles" || node.namespaceURI !== officens)) { - setState(OdfContainer.INVALID); - return - } - root.fontFaceDecls = getDirectChild(node, officens, "font-face-decls"); - setChild(root, root.fontFaceDecls); - root.styles = getDirectChild(node, officens, "styles"); - setChild(root, root.styles); - root.automaticStyles = getDirectChild(node, officens, "automatic-styles"); - setAutomaticStylesScope(root.automaticStyles, documentStylesScope); - setChild(root, root.automaticStyles); - root.masterStyles = getDirectChild(node, officens, "master-styles"); - setChild(root, root.masterStyles); - styleInfo.prefixStyleNames(root.automaticStyles, automaticStylePrefix, root.masterStyles) - } - function handleContentXml(xmldoc) { - var node = importRootNode(xmldoc), root, automaticStyles, fontFaceDecls, fontFaceNameChangeMap, c; - if(!node || (node.localName !== "document-content" || node.namespaceURI !== officens)) { - setState(OdfContainer.INVALID); - return - } - root = self.rootElement; - fontFaceDecls = getDirectChild(node, officens, "font-face-decls"); - if(root.fontFaceDecls && fontFaceDecls) { - fontFaceNameChangeMap = mergeFontFaceDecls(root.fontFaceDecls, fontFaceDecls) - }else { - if(fontFaceDecls) { - root.fontFaceDecls = fontFaceDecls; - setChild(root, fontFaceDecls) - } - } - automaticStyles = getDirectChild(node, officens, "automatic-styles"); - setAutomaticStylesScope(automaticStyles, documentContentScope); - if(fontFaceNameChangeMap) { - styleInfo.changeFontFaceNames(automaticStyles, fontFaceNameChangeMap) - } - if(root.automaticStyles && automaticStyles) { - c = automaticStyles.firstChild; - while(c) { - root.automaticStyles.appendChild(c); - c = automaticStyles.firstChild - } - }else { - if(automaticStyles) { - root.automaticStyles = automaticStyles; - setChild(root, automaticStyles) - } - } - root.body = getDirectChild(node, officens, "body"); - setChild(root, root.body) - } - function handleMetaXml(xmldoc) { - var node = importRootNode(xmldoc), root; - if(!node || (node.localName !== "document-meta" || node.namespaceURI !== officens)) { - return - } - root = self.rootElement; - root.meta = getDirectChild(node, officens, "meta"); - setChild(root, root.meta); - initializeMetadataManager(root.meta) - } - function handleSettingsXml(xmldoc) { - var node = importRootNode(xmldoc), root; - if(!node || (node.localName !== "document-settings" || node.namespaceURI !== officens)) { - return - } - root = self.rootElement; - root.settings = getDirectChild(node, officens, "settings"); - setChild(root, root.settings) - } - function handleManifestXml(xmldoc) { - var node = importRootNode(xmldoc), root, n; - if(!node || (node.localName !== "manifest" || node.namespaceURI !== manifestns)) { - return - } - root = self.rootElement; - root.manifest = node; - n = root.manifest.firstChild; - while(n) { - if(n.nodeType === Node.ELEMENT_NODE && (n.localName === "file-entry" && n.namespaceURI === manifestns)) { - partMimetypes[n.getAttributeNS(manifestns, "full-path")] = n.getAttributeNS(manifestns, "media-type") - } - n = n.nextSibling - } - } - function loadNextComponent(remainingComponents) { - var component = remainingComponents.shift(), filepath, callback; - if(component) { - filepath = (component[0]); - callback = (component[1]); - zip.loadAsDOM(filepath, function(err, xmldoc) { - callback(xmldoc); - if(err || self.state === OdfContainer.INVALID) { - return - } - loadNextComponent(remainingComponents) - }) - }else { - setState(OdfContainer.DONE) - } - } - function loadComponents() { - var componentOrder = [["styles.xml", handleStylesXml], ["content.xml", handleContentXml], ["meta.xml", handleMetaXml], ["settings.xml", handleSettingsXml], ["META-INF/manifest.xml", handleManifestXml]]; - loadNextComponent(componentOrder) - } - function createDocumentElement(name) { - var s = ""; - odf.Namespaces.forEachPrefix(function(prefix, ns) { - s += " xmlns:" + prefix + '="' + ns + '"' - }); - return'' - } - function serializeMetaXml() { - var serializer = new xmldom.LSSerializer, s = createDocumentElement("document-meta"); - serializer.filter = new odf.OdfNodeFilter; - s += serializer.writeToString(self.rootElement.meta, odf.Namespaces.namespaceMap); - s += ""; - return s - } - function createManifestEntry(fullPath, mediaType) { - var element = document.createElementNS(manifestns, "manifest:file-entry"); - element.setAttributeNS(manifestns, "manifest:full-path", fullPath); - element.setAttributeNS(manifestns, "manifest:media-type", mediaType); - return element - } - function serializeManifestXml() { - var header = '\n', xml = '', manifest = (runtime.parseXML(xml)), manifestRoot = getDirectChild(manifest, manifestns, "manifest"), serializer = new xmldom.LSSerializer, fullPath; - for(fullPath in partMimetypes) { - if(partMimetypes.hasOwnProperty(fullPath)) { - manifestRoot.appendChild(createManifestEntry(fullPath, partMimetypes[fullPath])) - } - } - serializer.filter = new odf.OdfNodeFilter; - return header + serializer.writeToString(manifest, odf.Namespaces.namespaceMap) - } - 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); - s += ""; - return s - } - function serializeStylesXml() { - var nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, fontFaceDecls, automaticStyles, masterStyles, s = createDocumentElement("document-styles"); - automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentStylesScope); - masterStyles = self.rootElement.masterStyles && self.rootElement.masterStyles.cloneNode(true); - fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [masterStyles, self.rootElement.styles, automaticStyles]); - styleInfo.removePrefixFromStyleNames(automaticStyles, automaticStylePrefix, masterStyles); - serializer.filter = new OdfStylesFilter(masterStyles, automaticStyles); - s += serializer.writeToString(fontFaceDecls, nsmap); - s += serializer.writeToString(self.rootElement.styles, nsmap); - s += serializer.writeToString(automaticStyles, nsmap); - s += serializer.writeToString(masterStyles, nsmap); - s += ""; - return s - } - function serializeContentXml() { - var nsmap = odf.Namespaces.namespaceMap, serializer = new xmldom.LSSerializer, fontFaceDecls, automaticStyles, s = createDocumentElement("document-content"); - automaticStyles = cloneStylesInScope(self.rootElement.automaticStyles, documentContentScope); - fontFaceDecls = cloneFontFaceDeclsUsedInStyles(self.rootElement.fontFaceDecls, [automaticStyles]); - serializer.filter = new OdfContentFilter(self.rootElement.body, automaticStyles); - s += serializer.writeToString(fontFaceDecls, nsmap); - s += serializer.writeToString(automaticStyles, nsmap); - s += serializer.writeToString(self.rootElement.body, nsmap); - s += ""; - return s - } - function createElement(Type) { - var original = document.createElementNS(Type.namespaceURI, Type.localName), method, iface = new Type; - for(method in iface) { - if(iface.hasOwnProperty(method)) { - original[method] = iface[method] - } - } - return original - } - function loadFromXML(url, callback) { - runtime.loadXML(url, function(err, dom) { - if(err) { - callback(err) - }else { - handleFlatXml(dom) - } - }) - } - this.setRootElement = setRootElement; - this.getContentElement = function() { - var body; - if(!contentElement) { - body = self.rootElement.body; - contentElement = body.getElementsByTagNameNS(officens, "text")[0] || (body.getElementsByTagNameNS(officens, "presentation")[0] || body.getElementsByTagNameNS(officens, "spreadsheet")[0]) - } - return contentElement - }; - this.getDocumentType = function() { - var content = self.getContentElement(); - return content && content.localName - }; - this.getMetadataManager = function() { - return metadataManager - }; - this.getPart = function(partname) { - return new OdfPart(partname, partMimetypes[partname], self, zip) - }; - this.getPartData = function(url, callback) { - zip.load(url, callback) - }; - function updateMetadataForSaving() { - var generatorString, window = runtime.getWindow(); - generatorString = "WebODF/" + (String(typeof webodf_version) !== "undefined" ? webodf_version : "FromSource"); - if(window) { - generatorString = generatorString + " " + window.navigator.userAgent - } - metadataManager.setMetadata({"meta:generator":generatorString}) - } - function createEmptyTextDocument() { - var emptyzip = new core.Zip("", null), data = runtime.byteArrayFromString("application/vnd.oasis.opendocument.text", "utf8"), root = self.rootElement, text = document.createElementNS(officens, "text"); - emptyzip.save("mimetype", data, false, new Date); - function addToplevelElement(memberName, realLocalName) { - var element; - if(!realLocalName) { - realLocalName = memberName - } - element = document.createElementNS(officens, realLocalName); - root[memberName] = element; - root.appendChild(element) - } - addToplevelElement("meta"); - addToplevelElement("settings"); - addToplevelElement("scripts"); - addToplevelElement("fontFaceDecls", "font-face-decls"); - addToplevelElement("styles"); - addToplevelElement("automaticStyles", "automatic-styles"); - addToplevelElement("masterStyles", "master-styles"); - addToplevelElement("body"); - root.body.appendChild(text); - initializeMetadataManager(root.meta); - setState(OdfContainer.DONE); - return emptyzip - } - function fillZip() { - var data, date = new Date; - updateMetadataForSaving(); - data = runtime.byteArrayFromString(serializeSettingsXml(), "utf8"); - zip.save("settings.xml", data, true, date); - data = runtime.byteArrayFromString(serializeMetaXml(), "utf8"); - zip.save("meta.xml", data, true, date); - data = runtime.byteArrayFromString(serializeStylesXml(), "utf8"); - zip.save("styles.xml", data, true, date); - data = runtime.byteArrayFromString(serializeContentXml(), "utf8"); - zip.save("content.xml", data, true, date); - data = runtime.byteArrayFromString(serializeManifestXml(), "utf8"); - zip.save("META-INF/manifest.xml", data, true, date) - } - function createByteArray(successCallback, errorCallback) { - fillZip(); - zip.createByteArray(successCallback, errorCallback) - } - this.createByteArray = createByteArray; - function saveAs(newurl, callback) { - fillZip(); - zip.writeAs(newurl, function(err) { - callback(err) - }) - } - this.saveAs = saveAs; - this.save = function(callback) { - saveAs(url, callback) - }; - this.getUrl = function() { - return url - }; - this.setBlob = function(filename, mimetype, content) { - var data = base64.convertBase64ToByteArray(content), date = new Date; - zip.save(filename, data, false, date); - if(partMimetypes.hasOwnProperty(filename)) { - runtime.log(filename + " has been overwritten.") - } - partMimetypes[filename] = mimetype - }; - this.removeBlob = function(filename) { - var foundAndRemoved = zip.remove(filename); - runtime.assert(foundAndRemoved, "file is not found: " + filename); - delete partMimetypes[filename] - }; - this.state = OdfContainer.LOADING; - this.rootElement = createElement(ODFDocumentElement); - if(url) { - zip = new core.Zip(url, function(err, zipobject) { - zip = zipobject; - if(err) { - loadFromXML(url, function(xmlerr) { - if(err) { - zip.error = err + "\n" + xmlerr; - setState(OdfContainer.INVALID) - } - }) - }else { - loadComponents() - } - }) - }else { - zip = createEmptyTextDocument() - } - }; - 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(url) { - return new odf.OdfContainer(url, null) - }; - return odf.OdfContainer -}(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.Base64"); -runtime.loadClass("xmldom.XPath"); -runtime.loadClass("odf.OdfContainer"); -odf.FontLoader = function() { - var xpath = new xmldom.XPath, base64 = new core.Base64; - function getEmbeddedFontDeclarations(fontFaceDecls) { - var decls = {}, fonts, i, font, name, uris, href, family; - if(!fontFaceDecls) { - return decls - } - fonts = xpath.getODFElementsWithXPath(fontFaceDecls, "style:font-face[svg:font-face-src]", odf.Namespaces.resolvePrefix); - for(i = 0;i < fonts.length;i += 1) { - font = fonts[i]; - name = font.getAttributeNS(odf.Namespaces.stylens, "name"); - family = font.getAttributeNS(odf.Namespaces.svgns, "font-family"); - uris = xpath.getODFElementsWithXPath(font, "svg:font-face-src/svg:font-face-uri", odf.Namespaces.resolvePrefix); - if(uris.length > 0) { - href = uris[0].getAttributeNS(odf.Namespaces.xlinkns, "href"); - decls[name] = {href:href, family:family} - } - } - return decls - } - function addFontToCSS(name, font, fontdata, stylesheet) { - var cssFamily = font.family || name, rule = "@font-face { font-family: '" + cssFamily + "'; src: " + "url(data:application/x-font-ttf;charset=binary;base64," + base64.convertUTF8ArrayToBase64(fontdata) + ') format("truetype"); }'; - try { - stylesheet.insertRule(rule, stylesheet.cssRules.length) - }catch(e) { - runtime.log("Problem inserting rule in CSS: " + runtime.toJson(e) + "\nRule: " + rule) } } - function loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos, stylesheet, callback) { - var name, i = 0, n; - for(n in embeddedFontDeclarations) { - if(embeddedFontDeclarations.hasOwnProperty(n)) { - if(i === pos) { - name = n; - break - } - i += 1 + function WindowScrollState(window) { + var x = window.scrollX, y = window.scrollY; + this.restore = function() { + if(window.scrollX !== x || window.scrollY !== y) { + window.scrollTo(x, y) } } - if(!name) { - if(callback) { - callback() - } - return - } - odfContainer.getPartData(embeddedFontDeclarations[name].href, function(err, fontdata) { - if(err) { - runtime.log(err) - }else { - if(!fontdata) { - runtime.log("missing font data for " + embeddedFontDeclarations[name].href) - }else { - addFontToCSS(name, embeddedFontDeclarations[name], fontdata, stylesheet) - } - } - loadFontIntoCSS(embeddedFontDeclarations, odfContainer, pos + 1, stylesheet, callback) - }) - } - function loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet) { - loadFontIntoCSS(embeddedFontDeclarations, odfContainer, 0, stylesheet) - } - odf.FontLoader = function FontLoader() { - this.loadFonts = function(odfContainer, stylesheet) { - var embeddedFontDeclarations, fontFaceDecls = odfContainer.rootElement.fontFaceDecls; - while(stylesheet.cssRules.length) { - stylesheet.deleteRule(stylesheet.cssRules.length - 1) - } - if(fontFaceDecls) { - embeddedFontDeclarations = getEmbeddedFontDeclarations(fontFaceDecls); - loadFontsIntoCSS(embeddedFontDeclarations, odfContainer, stylesheet) - } - } - }; - return odf.FontLoader -}(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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("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], node, styleNames = {}; - styleElements.forEach(function(styleListElement) { - node = styleListElement.firstChild; - while(node) { - if(node.nodeType === Node.ELEMENT_NODE && (node.namespaceURI === stylens && node.localName === "style")) { - styleNames[node.getAttributeNS(stylens, "name")] = true - } - node = node.nextSibling + 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 } - }); - 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 - - @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 . - - 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"); -runtime.loadClass("odf.TextStyleApplicator"); -odf.Formatting = function Formatting() { - var self = this, 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) { - var result, builtInDefaultStyleAttributes = builtInDefaultStyleAttributesByFamily[styleFamily]; - if(builtInDefaultStyleAttributes) { - result = utils.mergeObjects({}, builtInDefaultStyleAttributes) - }else { - result = null - } - return result - } - this.getSystemDefaultStyleAttributes = getSystemDefaultStyleAttributes; - this.setOdfContainer = function(odfcontainer) { - odfContainer = odfcontainer - }; - function getFontMap() { - var fontFaceDecls = odfContainer.rootElement.fontFaceDecls, fontFaceDeclsMap = {}, node, name, family; - node = fontFaceDecls && fontFaceDecls.firstChild; - while(node) { - if(node.nodeType === Node.ELEMENT_NODE) { - name = node.getAttributeNS(stylens, "name"); - if(name) { - family = node.getAttributeNS(svgns, "font-family"); - if(family || node.getElementsByTagNameNS(svgns, "font-face-uri")[0]) { - fontFaceDeclsMap[name] = family - } - } - } - node = node.nextSibling - } - return fontFaceDeclsMap - } - this.getFontMap = getFontMap; - this.getAvailableParagraphStyles = function() { - var node = odfContainer.rootElement.styles && odfContainer.rootElement.styles.firstChild, p_family, p_name, p_displayName, paragraphStyles = [], style; - while(node) { - if(node.nodeType === Node.ELEMENT_NODE && (node.localName === "style" && node.namespaceURI === stylens)) { - style = node; - p_family = style.getAttributeNS(stylens, "family"); - if(p_family === "paragraph") { - p_name = style.getAttributeNS(stylens, "name"); - p_displayName = style.getAttributeNS(stylens, "display-name") || p_name; - if(p_name && p_displayName) { - paragraphStyles.push({name:p_name, displayName:p_displayName}) - } - } - } - node = node.nextSibling - } - return paragraphStyles - }; - this.isStyleUsed = function(styleElement) { - var hasDerivedStyles, isUsed; - hasDerivedStyles = styleInfo.hasDerivedStyles(odfContainer.rootElement, odf.Namespaces.resolvePrefix, styleElement); - isUsed = (new styleInfo.UsedStyleList(odfContainer.rootElement.styles)).uses(styleElement) || ((new styleInfo.UsedStyleList(odfContainer.rootElement.automaticStyles)).uses(styleElement) || (new styleInfo.UsedStyleList(odfContainer.rootElement.body)).uses(styleElement)); - return hasDerivedStyles || isUsed - }; - function getDefaultStyleElement(family) { - var node = odfContainer.rootElement.styles.firstChild; - while(node) { - if(node.nodeType === Node.ELEMENT_NODE && (node.namespaceURI === stylens && (node.localName === "default-style" && node.getAttributeNS(stylens, "family") === family))) { - return node - } - node = node.nextSibling - } - return null - } - this.getDefaultStyleElement = getDefaultStyleElement; - function getStyleElement(styleName, family, styleElements) { - var node, nodeStyleName, styleListElement; - styleElements = styleElements || [odfContainer.rootElement.automaticStyles, odfContainer.rootElement.styles]; - styleListElement = styleElements.shift(); - while(styleListElement) { - node = styleListElement.firstChild; - while(node) { - if(node.nodeType === Node.ELEMENT_NODE) { - nodeStyleName = node.getAttributeNS(stylens, "name"); - if(node.namespaceURI === stylens && (node.localName === "style" && (node.getAttributeNS(stylens, "family") === family && nodeStyleName === styleName))) { - return node - } - if(family === "list-style" && (node.namespaceURI === textns && (node.localName === "list-style" && nodeStyleName === styleName))) { - return node - } - if(family === "data" && (node.namespaceURI === numberns && nodeStyleName === styleName)) { - return node - } - } - node = node.nextSibling - } - styleListElement = styleElements.shift() - } - return null - } - this.getStyleElement = getStyleElement; - function getStyleAttributes(styleNode) { - var i, propertiesMap = {}, propertiesNode = styleNode.firstChild; - while(propertiesNode) { - if(propertiesNode.nodeType === Node.ELEMENT_NODE && propertiesNode.namespaceURI === stylens) { - propertiesMap[propertiesNode.nodeName] = {}; - for(i = 0;i < propertiesNode.attributes.length;i += 1) { - propertiesMap[propertiesNode.nodeName][propertiesNode.attributes[i].name] = propertiesNode.attributes[i].value - } - } - propertiesNode = propertiesNode.nextSibling - } - for(i = 0;i < styleNode.attributes.length;i += 1) { - propertiesMap[styleNode.attributes[i].name] = styleNode.attributes[i].value - } - return propertiesMap - } - this.getStyleAttributes = getStyleAttributes; - function getInheritedStyleAttributes(styleNode, includeSystemDefault) { - var styleListElement = odfContainer.rootElement.styles, parentStyleName, propertiesMap, inheritedPropertiesMap = {}, styleFamily = styleNode.getAttributeNS(stylens, "family"), node = styleNode; - while(node) { - propertiesMap = getStyleAttributes(node); - inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap); - parentStyleName = node.getAttributeNS(stylens, "parent-style-name"); - if(parentStyleName) { - node = getStyleElement(parentStyleName, styleFamily, [styleListElement]) - }else { - node = null - } - } - node = getDefaultStyleElement(styleFamily); - if(node) { - propertiesMap = getStyleAttributes(node); - inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap) - } - if(includeSystemDefault) { - propertiesMap = getSystemDefaultStyleAttributes(styleFamily); - if(propertiesMap) { - inheritedPropertiesMap = utils.mergeObjects(propertiesMap, inheritedPropertiesMap) - } - } - return inheritedPropertiesMap - } - this.getInheritedStyleAttributes = getInheritedStyleAttributes; - this.getFirstCommonParentStyleNameOrSelf = function(styleName) { - var automaticStyleElementList = odfContainer.rootElement.automaticStyles, styleElementList = odfContainer.rootElement.styles, styleElement; - styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList]); - while(styleElement) { - styleName = styleElement.getAttributeNS(stylens, "parent-style-name"); - styleElement = getStyleElement(styleName, "paragraph", [automaticStyleElementList]) - } - styleElement = getStyleElement(styleName, "paragraph", [styleElementList]); - if(!styleElement) { - return null - } - return styleName - }; - this.hasParagraphStyle = function(styleName) { - return Boolean(getStyleElement(styleName, "paragraph")) - }; - function buildStyleChain(node, collectedChains) { - var parent = node.nodeType === Node.TEXT_NODE ? node.parentNode : node, nodeStyles, appliedStyles = [], chainKey = "", foundContainer = false; - while(parent) { - if(!foundContainer && odfUtils.isGroupingElement(parent)) { - foundContainer = true - } - nodeStyles = styleInfo.determineStylesForNode((parent)); - if(nodeStyles) { - appliedStyles.push(nodeStyles) - } - parent = parent.parentNode - } - if(foundContainer) { - appliedStyles.forEach(function(usedStyleMap) { - Object.keys(usedStyleMap).forEach(function(styleFamily) { - Object.keys(usedStyleMap[styleFamily]).forEach(function(styleName) { - chainKey += "|" + styleFamily + ":" + styleName + "|" - }) - }) - }); - if(collectedChains) { - collectedChains[chainKey] = appliedStyles - } - } - return foundContainer ? appliedStyles : undefined - } - 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; - styleElement = getStyleElement(styleName, styleFamily); - if(styleElement) { - parentStyle = getInheritedStyleAttributes((styleElement)); - mergedChildStyle = utils.mergeObjects(parentStyle, mergedChildStyle); - displayName = styleElement.getAttributeNS(stylens, "display-name") - }else { - runtime.log("No style element found for '" + styleName + "' of family '" + styleFamily + "'") - } - mergedChildStyle.orderedStyles.push({name:styleName, family:styleFamily, displayName:displayName}) - }) - }); - return mergedChildStyle - } - this.getAppliedStyles = function(textNodes) { - var styleChains = {}, styles = []; - textNodes.forEach(function(n) { - buildStyleChain(n, styleChains) - }); - Object.keys(styleChains).forEach(function(key) { - styles.push(calculateAppliedStyle(styleChains[key])) - }); - return styles - }; - this.getAppliedStylesForElement = function(node) { - var styleChain; - styleChain = buildStyleChain(node); - return styleChain ? calculateAppliedStyle(styleChain) : undefined - }; - this.applyStyle = function(memberId, textNodes, limits, info) { - var textStyles = new odf.TextStyleApplicator(new odf.ObjectNameGenerator((odfContainer), memberId), self, odfContainer.rootElement.automaticStyles); - textStyles.applyStyle(textNodes, limits, info) - }; - this.updateStyle = function(styleNode, properties) { - var fontName, fontFaceNode; - domUtils.mapObjOntoNode(styleNode, properties, odf.Namespaces.resolvePrefix); - fontName = properties["style:text-properties"] && properties["style:text-properties"]["style:font-name"]; - if(fontName && !getFontMap().hasOwnProperty(fontName)) { - fontFaceNode = styleNode.ownerDocument.createElementNS(stylens, "style:font-face"); - fontFaceNode.setAttributeNS(stylens, "style:name", fontName); - fontFaceNode.setAttributeNS(svgns, "svg:font-family", fontName); - 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 { - newStyleObject = {"style:parent-style-name":parentStyleName} - } - newStyleObject["style:family"] = family; - utils.mergeObjects(newStyleObject, overrides); - return newStyleObject - }; - this.getDefaultTabStopDistance = function() { - var defaultParagraph = getDefaultStyleElement("paragraph"), paragraphProperties = defaultParagraph && defaultParagraph.getAttributeNS(stylens, "paragraph-properties"), tabStopDistance = paragraphProperties && paragraphProperties.getAttributeNS(stylens, "tab-stop-distance"); - if(!tabStopDistance) { - tabStopDistance = "1.25cm" - } - return odfUtils.parseNonNegativeLength(tabStopDistance) - }; - function getPageLayoutStyleElement(styleName, styleFamily) { - var styleElement = getStyleElement(styleName, styleFamily), masterPageName, layoutName, pageLayoutElements, node, i; - runtime.assert(styleFamily === "paragraph" || styleFamily === "table", "styleFamily has to be either paragraph or table"); - if(styleElement) { - masterPageName = styleElement.getAttributeNS(stylens, "master-page-name") || "Standard"; - node = odfContainer.rootElement.masterStyles.lastChild; - while(node && node.previousSibling) { - if(node.getAttributeNS(stylens, "name") === masterPageName) { - break - } - node = node.previousSibling - } - layoutName = node.getAttributeNS(stylens, "page-layout-name"); - pageLayoutElements = domUtils.getElementsByTagNameNS(odfContainer.rootElement.automaticStyles, stylens, "page-layout"); - for(i = 0;i < pageLayoutElements.length;i += 1) { - node = pageLayoutElements[i]; - if(node.getAttributeNS(stylens, "name") === layoutName) { - return(node) - } - } - } - return null - } - function lengthInCm(length, defaultValue) { - var result = odfUtils.parseLength(length), value = defaultValue; - if(result) { - switch(result.unit) { - case "cm": - value = result.value; - break; - case "mm": - value = result.value * 0.1; - break; - case "in": - value = result.value * 2.54; - break; - case "pt": - value = result.value * 0.035277778; - break; - case "pc": - ; - case "px": - ; - case "em": - break; - default: - runtime.log("Unit identifier: " + result.unit + " is not supported."); - break - } - } - return value - } - this.getContentSize = function(styleName, styleFamily) { - var pageLayoutElement, props, printOrientation, defaultOrientedPageWidth, defaultOrientedPageHeight, pageWidth, pageHeight, margin, marginLeft, marginRight, marginTop, marginBottom, padding, paddingLeft, paddingRight, paddingTop, paddingBottom; - pageLayoutElement = getPageLayoutStyleElement(styleName, styleFamily); - if(!pageLayoutElement) { - pageLayoutElement = odfContainer.rootElement.styles.getElementsByTagNameNS(stylens, "default-page-layout")[0] - } - if(pageLayoutElement) { - props = pageLayoutElement.getElementsByTagNameNS(stylens, "page-layout-properties")[0] - } - if(props) { - printOrientation = props.getAttributeNS(stylens, "print-orientation") || "portrait"; - if(printOrientation === "portrait") { - defaultOrientedPageWidth = defaultPageFormatSettings.width; - defaultOrientedPageHeight = defaultPageFormatSettings.height - }else { - defaultOrientedPageWidth = defaultPageFormatSettings.height; - defaultOrientedPageHeight = defaultPageFormatSettings.width - } - pageWidth = lengthInCm(props.getAttributeNS(fons, "page-width"), defaultOrientedPageWidth); - pageHeight = lengthInCm(props.getAttributeNS(fons, "page-height"), defaultOrientedPageHeight); - margin = lengthInCm(props.getAttributeNS(fons, "margin"), null); - if(margin === null) { - marginLeft = lengthInCm(props.getAttributeNS(fons, "margin-left"), defaultPageFormatSettings.margin); - marginRight = lengthInCm(props.getAttributeNS(fons, "margin-right"), defaultPageFormatSettings.margin); - marginTop = lengthInCm(props.getAttributeNS(fons, "margin-top"), defaultPageFormatSettings.margin); - marginBottom = lengthInCm(props.getAttributeNS(fons, "margin-bottom"), defaultPageFormatSettings.margin) - }else { - marginLeft = marginRight = marginTop = marginBottom = margin - } - padding = lengthInCm(props.getAttributeNS(fons, "padding"), null); - if(padding === null) { - paddingLeft = lengthInCm(props.getAttributeNS(fons, "padding-left"), defaultPageFormatSettings.padding); - paddingRight = lengthInCm(props.getAttributeNS(fons, "padding-right"), defaultPageFormatSettings.padding); - paddingTop = lengthInCm(props.getAttributeNS(fons, "padding-top"), defaultPageFormatSettings.padding); - paddingBottom = lengthInCm(props.getAttributeNS(fons, "padding-bottom"), defaultPageFormatSettings.padding) - }else { - paddingLeft = paddingRight = paddingTop = paddingBottom = padding - } - } - return{width:pageWidth - marginLeft - marginRight - paddingLeft - paddingRight, height:pageHeight - marginTop - marginBottom - paddingTop - paddingBottom} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.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.OdfCanvas = function() { - function LoadingQueue() { - var queue = [], taskRunning = false; - function run(task) { - taskRunning = true; - runtime.setTimeout(function() { - try { - task() - }catch(e) { - runtime.log(e) - } - taskRunning = false; - if(queue.length > 0) { - run(queue.pop()) - } - }, 10) - } - this.clearQueue = function() { - queue.length = 0 - }; - this.addToQueue = function(loadingTask) { - if(queue.length === 0 && !taskRunning) { - return run(loadingTask) - } - queue.push(loadingTask) - } - } - function PageSwitcher(css) { - var sheet = css.sheet, position = 1; - function updateCSS() { - while(sheet.cssRules.length > 0) { - sheet.deleteRule(0) - } - sheet.insertRule("#shadowContent draw|page {display:none;}", 0); - sheet.insertRule("office|presentation draw|page {display:none;}", 1); - sheet.insertRule("#shadowContent draw|page:nth-of-type(" + position + ") {display:block;}", 2); - sheet.insertRule("office|presentation draw|page:nth-of-type(" + position + ") {display:block;}", 3) - } - this.showFirstPage = function() { - position = 1; - updateCSS() - }; - this.showNextPage = function() { - position += 1; - updateCSS() - }; - this.showPreviousPage = function() { - if(position > 1) { - position -= 1; - updateCSS() - } - }; - this.showPage = function(n) { - if(n > 0) { - position = n; - updateCSS() - } - }; - this.css = css; - this.destroy = function(callback) { - css.parentNode.removeChild(css); - callback() } } function listenEvent(eventTarget, eventType, eventHandler) { - if(eventTarget.addEventListener) { - eventTarget.addEventListener(eventType, eventHandler, false) - }else { - if(eventTarget.attachEvent) { - eventType = "on" + eventType; - eventTarget.attachEvent(eventType, eventHandler) - }else { - eventTarget["on" + 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) - }else { - if(eventTarget.detachEvent) { - eventTarget.detachEvent(onVariant, eventHandler) - }else { - if(eventTarget[onVariant] === eventHandler) { - eventTarget[onVariant] = null - } - } + } + if(eventTarget[onVariant] === eventHandler) { + eventTarget[onVariant] = null } } - function SelectionWatcher(element) { - var selection = [], listeners = []; - function isAncestorOf(ancestor, descendant) { - while(descendant) { - if(descendant === ancestor) { - return true - } - descendant = descendant.parentNode - } - return false - } - function fallsWithin(element, range) { - return isAncestorOf(element, range.startContainer) && isAncestorOf(element, range.endContainer) - } - function getCurrentSelection() { - var s = [], current = runtime.getWindow().getSelection(), i, r; - for(i = 0;i < current.rangeCount;i += 1) { - r = current.getRangeAt(i); - if(r !== null && fallsWithin(element, r)) { - s.push(r) - } - } - return s - } - function rangesNotEqual(rangeA, rangeB) { - if(rangeA === rangeB) { - return false - } - if(rangeA === null || rangeB === null) { - return true - } - return rangeA.startContainer !== rangeB.startContainer || (rangeA.startOffset !== rangeB.startOffset || (rangeA.endContainer !== rangeB.endContainer || rangeA.endOffset !== rangeB.endOffset)) - } - function emitNewSelection() { - var i, l = listeners.length; - for(i = 0;i < l;i += 1) { - listeners[i](element, selection) - } - } - function copySelection(selection) { - var s = [selection.length], i, oldr, r, doc = element.ownerDocument; - for(i = 0;i < selection.length;i += 1) { - oldr = selection[i]; - r = doc.createRange(); - r.setStart(oldr.startContainer, oldr.startOffset); - r.setEnd(oldr.endContainer, oldr.endOffset); - s[i] = r - } - return s - } - function checkSelection() { - var s = getCurrentSelection(), i; - if(s.length === selection.length) { - for(i = 0;i < s.length;i += 1) { - if(rangesNotEqual(s[i], selection[i])) { - break - } - } - if(i === s.length) { - return - } - } - selection = s; - selection = copySelection(s); - emitNewSelection() - } - this.addListener = function(eventName, handler) { - var i, l = listeners.length; - for(i = 0;i < l;i += 1) { - if(listeners[i] === handler) { - return - } - } - listeners.push(handler) - }; - this.destroy = function(callback) { - removeEvent(element, "mouseup", checkSelection); - removeEvent(element, "keyup", checkSelection); - removeEvent(element, "keydown", checkSelection); - callback() - }; - listenEvent(element, "mouseup", checkSelection); - listenEvent(element, "keyup", checkSelection); - listenEvent(element, "keydown", checkSelection) - } - 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, xmlns = odf.Namespaces.xmlns, presentationns = odf.Namespaces.presentationns, webodfhelperns = "urn:webodf:names:helper", window = runtime.getWindow(), xpath = new xmldom.XPath, odfUtils = new odf.OdfUtils, domUtils = new core.DomUtils; - function clear(element) { - while(element.firstChild) { - element.removeChild(element.firstChild) - } - } - function handleStyles(odfcontainer, formatting, stylesxmlcss) { - var style2css = new odf.Style2CSS; - style2css.style2css(odfcontainer.getDocumentType(), stylesxmlcss.sheet, formatting.getFontMap(), odfcontainer.rootElement.styles, odfcontainer.rootElement.automaticStyles) - } - function handleFonts(odfContainer, fontcss) { - var fontLoader = new odf.FontLoader; - fontLoader.loadFonts(odfContainer, fontcss.sheet) - } - function getMasterPageElement(odfContainer, masterPageName) { - if(!masterPageName) { - return null - } - var masterStyles = odfContainer.rootElement.masterStyles, masterPageElements = masterStyles.getElementsByTagNameNS(stylens, "master-page"), masterPageElement = null, i; - for(i = 0;i < masterPageElements.length;i += 1) { - if(masterPageElements[i].getAttributeNS(stylens, "name") === masterPageName) { - masterPageElement = masterPageElements[i]; - break - } - } - return masterPageElement - } - 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)) { - element.parentNode.removeChild(element) - } - } - } - function getHeaderFooter(odfContainer, frame, headerFooterId) { - var headerFooter = null, i, declElements = odfContainer.rootElement.body.getElementsByTagNameNS(presentationns, headerFooterId + "-decl"), headerFooterName = frame.getAttributeNS(presentationns, "use-" + headerFooterId + "-name"); - if(headerFooterName && declElements.length > 0) { - for(i = 0;i < declElements.length;i += 1) { - if(declElements[i].getAttributeNS(presentationns, "name") === headerFooterName) { - headerFooter = declElements[i].textContent; - break - } - } - } - return headerFooter - } - function setContainerValue(rootElement, ns, localName, value) { - var i, containerList, document = rootElement.ownerDocument; - containerList = rootElement.getElementsByTagNameNS(ns, localName); - for(i = 0;i < containerList.length;i += 1) { - clear(containerList[i]); - if(value) { - containerList[i].appendChild(document.createTextNode(value)) - } - } - } - function setDrawElementPosition(styleid, frame, stylesheet) { - frame.setAttributeNS(webodfhelperns, "styleid", styleid); - var rule, anchor = frame.getAttributeNS(textns, "anchor-type"), x = frame.getAttributeNS(svgns, "x"), y = frame.getAttributeNS(svgns, "y"), width = frame.getAttributeNS(svgns, "width"), height = frame.getAttributeNS(svgns, "height"), minheight = frame.getAttributeNS(fons, "min-height"), minwidth = frame.getAttributeNS(fons, "min-width"); - if(anchor === "as-char") { - rule = "display: inline-block;" - }else { - if(anchor || (x || y)) { - rule = "position: absolute;" - }else { - if(width || (height || (minheight || minwidth))) { - rule = "display: block;" - } - } - } - if(x) { - rule += "left: " + x + ";" - } - if(y) { - rule += "top: " + y + ";" - } - if(width) { - rule += "width: " + width + ";" - } - if(height) { - rule += "height: " + height + ";" - } - if(minheight) { - rule += "min-height: " + minheight + ";" - } - if(minwidth) { - rule += "min-width: " + minwidth + ";" - } - if(rule) { - rule = "draw|" + frame.localName + '[webodfhelper|styleid="' + styleid + '"] {' + rule + "}"; - stylesheet.insertRule(rule, stylesheet.cssRules.length) - } - } - function getUrlFromBinaryDataElement(image) { - var node = image.firstChild; - while(node) { - if(node.namespaceURI === officens && node.localName === "binary-data") { - return"data:image/png;base64," + node.textContent.replace(/[\r\n\s]/g, "") - } - node = node.nextSibling - } - return"" - } - function setImage(id, container, image, stylesheet) { - image.setAttributeNS(webodfhelperns, "styleid", id); - var url = image.getAttributeNS(xlinkns, "href"), part; - function callback(url) { - var rule; - if(url) { - rule = "background-image: url(" + url + ");"; - rule = 'draw|image[webodfhelper|styleid="' + id + '"] {' + rule + "}"; - stylesheet.insertRule(rule, stylesheet.cssRules.length) - } - } - if(url) { - try { - part = container.getPart(url); - part.onchange = function(part) { - callback(part.url) - }; - part.load() - }catch(e) { - runtime.log("slight problem: " + e) + this.subscribe = function(eventName, handler) { + var delegate = window && bindToWindow[eventName]; + if(delegate) { + delegate.handlers.push(handler); + if(!delegate.isSubscribed) { + delegate.isSubscribed = true; + listenEvent((window), eventName, delegate.handleEvent); + listenEvent(canvasElement, eventName, delegate.handleEvent) } }else { - url = getUrlFromBinaryDataElement(image); - callback(url) + listenEvent(canvasElement, eventName, handler) } - } - function formatParagraphAnchors(odfbody) { - var n, i, nodes = xpath.getODFElementsWithXPath(odfbody, ".//*[*[@text:anchor-type='paragraph']]", odf.Namespaces.resolvePrefix); - for(i = 0;i < nodes.length;i += 1) { - n = nodes[i]; - if(n.setAttributeNS) { - n.setAttributeNS(webodfhelperns, "containsparagraphanchor", true) - } - } - } - function modifyTables(odffragment) { - var i, tableCells, node; - function modifyTableCell(node) { - if(node.hasAttributeNS(tablens, "number-columns-spanned")) { - node.setAttribute("colspan", node.getAttributeNS(tablens, "number-columns-spanned")) - } - if(node.hasAttributeNS(tablens, "number-rows-spanned")) { - node.setAttribute("rowspan", node.getAttributeNS(tablens, "number-rows-spanned")) - } - } - tableCells = odffragment.getElementsByTagNameNS(tablens, "table-cell"); - for(i = 0;i < tableCells.length;i += 1) { - node = (tableCells.item(i)); - 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.resolvePrefix); - if(bookmarks.length === 0) { - bookmarks = xpath.getODFElementsWithXPath(odffragment, "//text:bookmark[@text:name='" + url + "']", odf.Namespaces.resolvePrefix) - } - 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) { - if(!lineBreak.hasChildNodes()) { - lineBreak.appendChild(document.createElement("br")) - } - }) - } - function expandSpaceElements(odffragment) { - var spaces, doc = odffragment.ownerDocument; - function expandSpaceElement(space) { - var j, count; - while(space.firstChild) { - space.removeChild(space.firstChild) - } - space.appendChild(doc.createTextNode(" ")); - count = parseInt(space.getAttributeNS(textns, "c"), 10); - if(count > 1) { - space.removeAttributeNS(textns, "c"); - for(j = 1;j < count;j += 1) { - space.parentNode.insertBefore(space.cloneNode(true), space) - } - } - } - spaces = domUtils.getElementsByTagNameNS(odffragment, textns, "s"); - spaces.forEach(expandSpaceElement) - } - function expandTabElements(odffragment) { - var tabs; - tabs = domUtils.getElementsByTagNameNS(odffragment, textns, "tab"); - tabs.forEach(function(tab) { - tab.textContent = "\t" - }) - } - function modifyDrawElements(odfbody, stylesheet) { - var node, drawElements, i; - drawElements = []; - node = odfbody.firstChild; - while(node && node !== odfbody) { - if(node.namespaceURI === drawns) { - drawElements[drawElements.length] = node - } - if(node.firstChild) { - node = node.firstChild - }else { - while(node && (node !== odfbody && !node.nextSibling)) { - node = node.parentNode - } - if(node && node.nextSibling) { - node = node.nextSibling - } - } - } - for(i = 0;i < drawElements.length;i += 1) { - node = drawElements[i]; - setDrawElementPosition("frame" + String(i), node, stylesheet) - } - formatParagraphAnchors(odfbody) - } - function cloneMasterPages(odfContainer, shadowContent, odfbody, stylesheet) { - var masterPageName, masterPageElement, styleId, clonedPageElement, clonedElement, pageNumber = 0, i, element, elementToClone, document = odfContainer.rootElement.ownerDocument; - element = odfbody.firstElementChild; - if(!(element && (element.namespaceURI === officens && (element.localName === "presentation" || element.localName === "drawing")))) { - return - } - element = element.firstElementChild; - while(element) { - masterPageName = element.getAttributeNS(drawns, "master-page-name"); - masterPageElement = getMasterPageElement(odfContainer, masterPageName); - if(masterPageElement) { - styleId = element.getAttributeNS(webodfhelperns, "styleid"); - clonedPageElement = document.createElementNS(drawns, "draw:page"); - elementToClone = masterPageElement.firstElementChild; - i = 0; - while(elementToClone) { - if(elementToClone.getAttributeNS(presentationns, "placeholder") !== "true") { - clonedElement = elementToClone.cloneNode(true); - clonedPageElement.appendChild(clonedElement); - setDrawElementPosition(styleId + "_" + i, (clonedElement), stylesheet) - } - elementToClone = elementToClone.nextElementSibling; - i += 1 - } - dropTemplateDrawFrames(clonedPageElement); - shadowContent.appendChild(clonedPageElement); - pageNumber = String(shadowContent.getElementsByTagNameNS(drawns, "page").length); - setContainerValue(clonedPageElement, textns, "page-number", pageNumber); - setContainerValue(clonedPageElement, presentationns, "header", getHeaderFooter(odfContainer, (element), "header")); - setContainerValue(clonedPageElement, presentationns, "footer", getHeaderFooter(odfContainer, (element), "footer")); - setDrawElementPosition(styleId, clonedPageElement, stylesheet); - clonedPageElement.setAttributeNS(drawns, "draw:master-page-name", masterPageElement.getAttributeNS(stylens, "name")) - } - element = element.nextElementSibling - } - } - function setVideo(container, plugin) { - var video, source, url, doc = plugin.ownerDocument, part; - url = plugin.getAttributeNS(xlinkns, "href"); - function callback(url, mimetype) { - var ns = doc.documentElement.namespaceURI; - if(mimetype.substr(0, 6) === "video/") { - video = doc.createElementNS(ns, "video"); - video.setAttribute("controls", "controls"); - source = doc.createElementNS(ns, "source"); - source.setAttribute("src", url); - source.setAttribute("type", mimetype); - video.appendChild(source); - plugin.parentNode.appendChild(video) - }else { - plugin.innerHtml = "Unrecognised Plugin" - } - } - if(url) { - try { - part = container.getPart(url); - part.onchange = function(part) { - callback(part.url, part.mimetype) - }; - part.load() - }catch(e) { - runtime.log("slight problem: " + e) - } - }else { - runtime.log("using MP4 data fallback"); - url = getUrlFromBinaryDataElement(plugin); - callback(url, "video/mp4") - } - } - function getNumberRule(node) { - var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix"), prefix = node.getAttributeNS(stylens, "num-prefix"), rule = "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content; - content = prefix || ""; - if(stylemap.hasOwnProperty(style)) { - content += " counter(list, " + stylemap[style] + ")" - }else { - if(style) { - content += "'" + style + "';" - }else { - content += " ''" - } - } - if(suffix) { - content += " '" + suffix + "'" - } - rule = "content: " + content + ";"; - return rule - } - function getImageRule() { - var rule = "content: none;"; - return rule - } - function getBulletRule(node) { - var bulletChar = node.getAttributeNS(textns, "bullet-char"); - return"content: '" + bulletChar + "';" - } - function getBulletsRule(node) { - var itemrule; - if(node) { - if(node.localName === "list-level-style-number") { - itemrule = getNumberRule(node) - }else { - if(node.localName === "list-level-style-image") { - itemrule = getImageRule() - }else { - if(node.localName === "list-level-style-bullet") { - itemrule = getBulletRule(node) - } - } - } - } - return itemrule - } - function loadLists(odffragment, stylesheet) { - var i, lists, node, id, continueList, styleName, rule, listMap = {}, parentList, listStyles, listStyleMap = {}, bulletRule; - listStyles = window.document.getElementsByTagNameNS(textns, "list-style"); - for(i = 0;i < listStyles.length;i += 1) { - node = (listStyles.item(i)); - styleName = node.getAttributeNS(stylens, "name"); - if(styleName) { - listStyleMap[styleName] = node - } - } - lists = odffragment.getElementsByTagNameNS(textns, "list"); - for(i = 0;i < lists.length;i += 1) { - node = (lists.item(i)); - id = node.getAttributeNS(xmlns, "id"); - if(id) { - continueList = node.getAttributeNS(textns, "continue-list"); - node.setAttribute("id", id); - rule = "text|list#" + id + " > text|list-item > *:first-child:before {"; - styleName = node.getAttributeNS(textns, "style-name"); - if(styleName) { - node = listStyleMap[styleName]; - bulletRule = getBulletsRule((odfUtils.getFirstNonWhitespaceChild(node))) - } - if(continueList) { - parentList = listMap[continueList]; - while(parentList) { - continueList = parentList; - parentList = listMap[continueList] - } - rule += "counter-increment:" + continueList + ";"; - if(bulletRule) { - bulletRule = bulletRule.replace("list", continueList); - rule += bulletRule - }else { - rule += "content:counter(" + continueList + ");" - } - }else { - continueList = ""; - if(bulletRule) { - bulletRule = bulletRule.replace("list", id); - rule += bulletRule - }else { - rule += "content: counter(" + id + ");" - } - rule += "counter-increment:" + id + ";"; - stylesheet.insertRule("text|list#" + id + " {counter-reset:" + id + "}", stylesheet.cssRules.length) - } - rule += "}"; - listMap[id] = continueList; - if(rule) { - stylesheet.insertRule(rule, stylesheet.cssRules.length) - } - } - } - } - 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)) - }else { - style = document.createElementNS(head.namespaceURI, "link"); - href = "webodf.css"; - if(runtime.currentDirectory) { - href = runtime.currentDirectory() + "/../" + href - } - style.setAttribute("href", href); - style.setAttribute("rel", "stylesheet") - } - style.setAttribute("type", "text/css"); - head.appendChild(style); - return(style) - } - function addStyleSheet(document) { - var head = document.getElementsByTagName("head")[0], style = document.createElementNS(head.namespaceURI, "style"), text = ""; - style.setAttribute("type", "text/css"); - style.setAttribute("media", "screen, print, handheld, projection"); - odf.Namespaces.forEachPrefix(function(prefix, ns) { - text += "@namespace " + prefix + " url(" + ns + ");\n" - }); - text += "@namespace webodfhelper url(" + webodfhelperns + ");\n"; - style.appendChild(document.createTextNode(text)); - head.appendChild(style); - return(style) - } - 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, selectionWatcher = new SelectionWatcher(element), pageSwitcher, sizer, annotationsPane, allowAnnotations = false, annotationViewManager, webodfcss, fontcss, stylesxmlcss, positioncss, shadowContent, zoomLevel = 1, eventHandlers = {}, loadingQueue = new LoadingQueue; - function loadImages(container, odffragment, stylesheet) { - var i, images, node; - function loadImage(name, container, node, stylesheet) { - loadingQueue.addToQueue(function() { - setImage(name, container, node, stylesheet) - }) - } - images = odffragment.getElementsByTagNameNS(drawns, "image"); - for(i = 0;i < images.length;i += 1) { - node = (images.item(i)); - loadImage("image" + String(i), container, node, stylesheet) - } - } - function loadVideos(container, odffragment) { - var i, plugins, node; - function loadVideo(container, node) { - loadingQueue.addToQueue(function() { - setVideo(container, node) - }) - } - plugins = odffragment.getElementsByTagNameNS(drawns, "plugin"); - for(i = 0;i < plugins.length;i += 1) { - node = (plugins.item(i)); - loadVideo(container, node) - } - } - function addEventListener(eventType, eventHandler) { - var handlers = eventHandlers[eventType]; - if(handlers === undefined) { - handlers = eventHandlers[eventType] = [] - } - if(eventHandler && handlers.indexOf(eventHandler) === -1) { - handlers.push(eventHandler) - } - } - function fireEvent(eventType, args) { - if(!eventHandlers.hasOwnProperty(eventType)) { - return - } - var handlers = eventHandlers[eventType], i; - for(i = 0;i < handlers.length;i += 1) { - handlers[i].apply(null, args) - } - } - function fixContainerSize() { - var odfdoc = sizer.firstChild; - 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 + ")"; - element.style.width = Math.round(zoomLevel * sizer.offsetWidth) + "px"; - element.style.height = Math.round(zoomLevel * sizer.offsetHeight) + "px" - } - 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.appendChild(odfnode); - element.appendChild(sizer); - annotationsPane = doc.createElementNS(element.namespaceURI, "div"); - annotationsPane.id = "annotationsPane"; - shadowContent = doc.createElementNS(element.namespaceURI, "div"); - shadowContent.id = "shadowContent"; - shadowContent.style.position = "absolute"; - shadowContent.style.top = 0; - shadowContent.style.left = 0; - container.getContentElement().appendChild(shadowContent); - modifyDrawElements(odfnode.body, css); - cloneMasterPages(container, shadowContent, odfnode.body, css); - modifyTables(odfnode.body); - modifyLinks(odfnode.body); - modifyLineBreakElements(odfnode.body); - expandSpaceElements(odfnode.body); - expandTabElements(odfnode.body); - loadImages(container, odfnode.body, css); - loadVideos(container, odfnode.body); - loadLists(odfnode.body, css); - sizer.insertBefore(shadowContent, sizer.firstChild); - fixContainerSize() - } - 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}) - } - annotationViewManager.rerenderAnnotations() - } - function handleAnnotations(odfnode) { - if(allowAnnotations) { - if(!annotationsPane.parentNode) { - sizer.appendChild(annotationsPane); - fixContainerSize() - } - if(annotationViewManager) { - annotationViewManager.forgetAnnotations() - } - annotationViewManager = new gui.AnnotationViewManager(self, odfnode.body, annotationsPane); - modifyAnnotations(odfnode.body) - }else { - if(annotationsPane.parentNode) { - sizer.removeChild(annotationsPane); - annotationViewManager.forgetAnnotations(); - fixContainerSize() - } - } - } - function refreshOdf(suppressEvent) { - function callback() { - clear(element); - element.style.display = "inline-block"; - var odfnode = odfcontainer.rootElement; - element.ownerDocument.importNode(odfnode, true); - formatting.setOdfContainer(odfcontainer); - handleFonts(odfcontainer, fontcss); - handleStyles(odfcontainer, formatting, stylesxmlcss); - handleContent(odfcontainer, odfnode); - handleAnnotations(odfnode); - if(!suppressEvent) { - fireEvent("statereadychange", [odfcontainer]) - } - } - if(odfcontainer.state === odf.OdfContainer.DONE) { - callback() - }else { - runtime.log("WARNING: refreshOdf called but ODF was not DONE."); - runtime.setTimeout(function later_cb() { - if(odfcontainer.state === odf.OdfContainer.DONE) { - callback() - }else { - runtime.log("will be back later..."); - runtime.setTimeout(later_cb, 500) - } - }, 100) - } - } - this.refreshCSS = function() { - handleStyles(odfcontainer, formatting, stylesxmlcss); - fixContainerSize() - }; - this.refreshSize = function() { - fixContainerSize() - }; - this.odfContainer = function() { - return odfcontainer - }; - this.slidevisibilitycss = function() { - return pageSwitcher.css - }; - this.setOdfContainer = function(container, suppressEvent) { - odfcontainer = container; - refreshOdf(suppressEvent === true) - }; - function load(url) { - loadingQueue.clearQueue(); - element.innerHTML = runtime.tr("Loading") + " " + url + "..."; - element.removeAttribute("style"); - odfcontainer = new odf.OdfContainer(url, function(container) { - odfcontainer = container; - refreshOdf(false) - }) - } - this["load"] = load; - this.load = load; - this.save = function(callback) { - odfcontainer.save(callback) - }; - this.addListener = function(eventName, handler) { - switch(eventName) { - case "selectionchange": - selectionWatcher.addListener(eventName, handler); - break; - case "click": - listenEvent(element, eventName, handler); - break; - default: - addEventListener(eventName, handler); - break - } - }; - this.getFormatting = function() { - return formatting - }; - this.getAnnotationViewManager = function() { - return annotationViewManager - }; - this.refreshAnnotations = function() { - handleAnnotations(odfcontainer.rootElement) - }; - this.rerenderAnnotations = function() { - if(annotationViewManager) { - annotationViewManager.rerenderAnnotations() - } - }; - this.getSizer = function() { - return sizer - }; - this.enableAnnotations = function(allow) { - if(allow !== allowAnnotations) { - allowAnnotations = allow; - if(odfcontainer) { - handleAnnotations(odfcontainer.rootElement) - } - } - }; - this.addAnnotation = function(annotation) { - if(annotationViewManager) { - annotationViewManager.addAnnotation(annotation) - } - }; - this.forgetAnnotations = function() { - if(annotationViewManager) { - annotationViewManager.forgetAnnotations() - } - }; - this.setZoomLevel = function(zoom) { - zoomLevel = zoom; - fixContainerSize() - }; - this.getZoomLevel = function() { - return zoomLevel - }; - this.fitToContainingElement = function(width, height) { - var realWidth = element.offsetWidth / zoomLevel, realHeight = element.offsetHeight / zoomLevel; - zoomLevel = width / realWidth; - if(height / realHeight < zoomLevel) { - zoomLevel = height / realHeight - } - fixContainerSize() - }; - this.fitToWidth = function(width) { - var realWidth = element.offsetWidth / zoomLevel; - zoomLevel = width / realWidth; - fixContainerSize() - }; - this.fitSmart = function(width, height) { - var realWidth, realHeight, newScale; - realWidth = element.offsetWidth / zoomLevel; - realHeight = element.offsetHeight / zoomLevel; - newScale = width / realWidth; - if(height !== undefined) { - if(height / realHeight < newScale) { - newScale = height / realHeight - } - } - zoomLevel = Math.min(1, newScale); - fixContainerSize() - }; - this.fitToHeight = function(height) { - var realHeight = element.offsetHeight / zoomLevel; - zoomLevel = height / realHeight; - fixContainerSize() - }; - this.showFirstPage = function() { - pageSwitcher.showFirstPage() - }; - this.showNextPage = function() { - pageSwitcher.showNextPage() - }; - this.showPreviousPage = function() { - pageSwitcher.showPreviousPage() - }; - this.showPage = function(n) { - pageSwitcher.showPage(n); - fixContainerSize() - }; - this.getElement = function() { - return element - }; - this.addCssForFrameWithImage = function(frame) { - var frameName = frame.getAttributeNS(drawns, "name"); - setDrawElementPosition(frameName, frame, positioncss.sheet); - setImage(frameName + "img", odfcontainer, (frame.firstChild), positioncss.sheet) - }; - this.destroy = function(callback) { - var head = doc.getElementsByTagName("head")[0]; - if(annotationsPane && annotationsPane.parentNode) { - annotationsPane.parentNode.removeChild(annotationsPane) - } - if(sizer) { - element.removeChild(sizer) - } - head.removeChild(webodfcss); - head.removeChild(fontcss); - head.removeChild(stylesxmlcss); - head.removeChild(positioncss); - selectionWatcher.destroy(function(err) { - if(err) { - callback(err) - }else { - pageSwitcher.destroy(callback) - } - }) - }; - function init() { - webodfcss = addWebODFStyleSheet(doc); - pageSwitcher = new PageSwitcher(addStyleSheet(doc)); - fontcss = addStyleSheet(doc); - stylesxmlcss = addStyleSheet(doc); - positioncss = addStyleSheet(doc) - } - init() }; - return odf.OdfCanvas -}(); -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.") + this.unsubscribe = function(eventName, handler) { + var delegate = window && bindToWindow[eventName], handlerIndex = delegate && delegate.handlers.indexOf(handler); + if(delegate) { + if(handlerIndex !== -1) { + delegate.handlers.splice(handlerIndex, 1) } + }else { + removeEvent(canvasElement, eventName, handler) } - var odfcontainer = new odf.OdfContainer(inputfilepath, onready); - return odfcontainer }; - this.render = function(inputfilepath, document, callback) { - var body = document.getElementsByTagName("body")[0], odfcanvas; - while(body.firstChild) { - body.removeChild(body.firstChild) + function hasFocus() { + var activeElement = odtDocument.getDOM().activeElement; + return activeElement === canvasElement + } + this.hasFocus = hasFocus; + function findScrollableParent(element) { + while(element && (!element.scrollTop && !element.scrollLeft)) { + element = (element.parentNode) } - odfcanvas = new odf.OdfCanvas(body); - odfcanvas.addListener("statereadychange", function(err) { - callback(err) - }); - odfcanvas.load(inputfilepath) + if(element) { + return new ElementScrollState(element) + } + if(window) { + return new WindowScrollState(window) + } + return null } -}; -/* - - Copyright (C) 2013 KO GmbH - - @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 . - @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.focus = function() { + var scrollParent; + if(!hasFocus()) { + scrollParent = findScrollableParent(canvasElement); + canvasElement.focus(); + if(scrollParent) { + scrollParent.restore() } - }) - } - 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 + bindToWindow = {"mousedown":new EventDelegate, "mouseup":new EventDelegate} } 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 @@ -10414,19 +12639,203 @@ ops.Member = function Member(memberId, properties) { @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.Server = function Server() { +gui.UndoManager = function UndoManager() { }; -ops.Server.prototype.connect = function(timeout, cb) { +gui.UndoManager.prototype.subscribe = function(signal, callback) { }; -ops.Server.prototype.networkStatus = function() { +gui.UndoManager.prototype.unsubscribe = function(signal, callback) { }; -ops.Server.prototype.login = function(login, password, successCb, failCb) { +gui.UndoManager.prototype.setOdtDocument = function(newDocument) { }; -ops.Server.prototype.joinSession = function(userId, sessionId, successCb, failCb) { +gui.UndoManager.prototype.saveInitialState = function() { }; -ops.Server.prototype.leaveSession = function(sessionId, memberId, successCb, failCb) { +gui.UndoManager.prototype.resetInitialState = function() { }; -ops.Server.prototype.getGenesisUrl = function(sessionId) { +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 + + @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 . + + 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 + + @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 . + + 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() }; /* @@ -10465,14 +12874,86 @@ ops.Server.prototype.getGenesisUrl = function(sessionId) { @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("core.DomUtils"); +ops.OpAddAnnotation = function OpAddAnnotation() { + var memberid, timestamp, position, length, name, doc; + this.init = function(data) { + memberid = data.memberid; + timestamp = parseInt(data.timestamp, 10); + position = parseInt(data.position, 10); + length = parseInt(data.length, 10) || 0; + name = data.name + }; + this.isEdit = true; + function createAnnotationNode(odtDocument, date) { + var annotationNode, creatorNode, dateNode, listNode, listItemNode, paragraphNode; + 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); + creatorNode.textContent = odtDocument.getMember(memberid).getProperties().fullName; + dateNode = doc.createElementNS(odf.Namespaces.dcns, "dc:date"); + dateNode.appendChild(doc.createTextNode(date.toISOString())); + listNode = doc.createElementNS(odf.Namespaces.textns, "text:list"); + listItemNode = doc.createElementNS(odf.Namespaces.textns, "text:list-item"); + paragraphNode = doc.createElementNS(odf.Namespaces.textns, "text:p"); + listItemNode.appendChild(paragraphNode); + listNode.appendChild(listItemNode); + annotationNode.appendChild(creatorNode); + annotationNode.appendChild(dateNode); + annotationNode.appendChild(listNode); + return annotationNode + } + function createAnnotationEnd() { + var annotationEnd; + annotationEnd = doc.createElementNS(odf.Namespaces.officens, "office:annotation-end"); + annotationEnd.setAttributeNS(odf.Namespaces.officens, "office:name", name); + return annotationEnd + } + function insertNodeAtPosition(odtDocument, node, insertPosition) { + var previousNode, parentNode, domPosition = odtDocument.getTextNodeAtStep(insertPosition, memberid); + if(domPosition) { + previousNode = domPosition.textNode; + parentNode = previousNode.parentNode; + if(domPosition.offset !== previousNode.length) { + previousNode.splitText(domPosition.offset) + } + parentNode.insertBefore(node, previousNode.nextSibling); + if(previousNode.length === 0) { + parentNode.removeChild(previousNode) + } + } + } + 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 + } + if(length) { + annotation.end = createAnnotationEnd(); + if(!annotation.end) { + return false + } + insertNodeAtPosition(odtDocument, annotation.end, position + length) + } + insertNodeAtPosition(odtDocument, annotation.node, 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]; + selectedRange.selectNodeContents(paragraphElement); + cursor.setSelectedRange(selectedRange); + odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor) + } + odtDocument.getOdfCanvas().addAnnotation(annotation); + odtDocument.fixCursorPositions(); + return true + }; + this.spec = function() { + return{optype:"AddAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length, name:name} + } }; /* @@ -10532,6 +13013,52 @@ ops.OpAddCursor = function OpAddCursor() { return{optype:"AddCursor", memberid:memberid, timestamp:timestamp} } }; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + @licend + + @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) { + memberid = data.memberid; + timestamp = parseInt(data.timestamp, 10); + setProperties = data.setProperties + }; + this.isEdit = false; + this.execute = function(odtDocument) { + if(odtDocument.getMember(memberid)) { + return false + } + var member = new ops.Member(memberid, setProperties); + odtDocument.addMember(member); + odtDocument.emit(ops.OdtDocument.signalMemberAdded, member); + return true + }; + this.spec = function() { + return{optype:"AddMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties} + } +}; /* Copyright (C) 2012-2013 KO GmbH @@ -10569,108 +13096,44 @@ ops.OpAddCursor = function OpAddCursor() { @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -runtime.loadClass("core.DomUtils"); runtime.loadClass("odf.Namespaces"); -runtime.loadClass("odf.OdfUtils"); -gui.StyleHelper = function StyleHelper(formatting) { - var domUtils = new core.DomUtils, 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[range.startOffset] - } - nodes = [container] +ops.OpAddStyle = function OpAddStyle() { + var memberid, timestamp, styleName, styleFamily, isAutomaticStyle, setProperties, stylens = odf.Namespaces.stylens; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + styleName = data.styleName; + styleFamily = data.styleFamily; + isAutomaticStyle = data.isAutomaticStyle === "true" || data.isAutomaticStyle === true; + 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"); + if(!styleNode) { + return false + } + if(setProperties) { + formatting.updateStyle(styleNode, setProperties) + } + styleNode.setAttributeNS(stylens, "style:family", styleFamily); + styleNode.setAttributeNS(stylens, "style:name", styleName); + if(isAutomaticStyle) { + odfContainer.rootElement.automaticStyles.appendChild(styleNode) }else { - nodes = odfUtils.getTextNodes(range, true) + odfContainer.rootElement.styles.appendChild(styleNode) } - return formatting.getAppliedStyles(nodes) - } - this.getAppliedStyles = getAppliedStyles; - this.applyStyle = function(memberId, range, info) { - var nextTextNodes = domUtils.splitBoundaries(range), textNodes = odfUtils.getTextNodes(range, false), limits; - limits = {startContainer:range.startContainer, startOffset:range.startOffset, endContainer:range.endContainer, endOffset:range.endOffset}; - formatting.applyStyle(memberId, textNodes, limits, info); - nextTextNodes.forEach(domUtils.normalizeTextNodes) - }; - 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 nodes = odfUtils.getParagraphElements(range), isStyleChecked = {}, isDefaultParagraphStyleChecked = false, paragraphStyleName, paragraphStyleElement, paragraphStyleAttributes, properties; - 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() + odtDocument.getOdfCanvas().refreshCSS(); + if(!isAutomaticStyle) { + odtDocument.emit(ops.OdtDocument.signalCommonStyleCreated, {name:styleName, family:styleFamily}) } 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"]) + this.spec = function() { + return{optype:"AddStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily, isAutomaticStyle:isAutomaticStyle, setProperties:setProperties} } }; +ops.OpAddStyle.Spec; /* Copyright (C) 2012-2013 KO GmbH @@ -10742,230 +13205,7 @@ ops.OpApplyDirectStyling = function OpApplyDirectStyling() { return{optype:"ApplyDirectStyling", memberid:memberid, timestamp:timestamp, position:position, length:length, setProperties:setProperties} } }; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpRemoveCursor = function OpRemoveCursor() { - var memberid, timestamp; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp - }; - this.isEdit = false; - this.execute = function(odtDocument) { - if(!odtDocument.removeCursor(memberid)) { - return false - } - return true - }; - this.spec = function() { - return{optype:"RemoveCursor", memberid:memberid, timestamp:timestamp} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpMoveCursor = function OpMoveCursor() { - var memberid, timestamp, position, length, selectionType; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - position = data.position; - length = data.length || 0; - selectionType = data.selectionType || ops.OdtCursor.RangeSelection - }; - this.isEdit = false; - this.execute = function(odtDocument) { - var 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); - return true - }; - this.spec = function() { - return{optype:"MoveCursor", memberid:memberid, timestamp:timestamp, position:position, length:length, selectionType:selectionType} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpSetBlob = function OpSetBlob() { - var memberid, timestamp, filename, mimetype, content; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - filename = data.filename; - mimetype = data.mimetype; - content = data.content - }; - this.isEdit = true; - this.execute = function(odtDocument) { - odtDocument.getOdfCanvas().odfContainer().setBlob(filename, mimetype, content); - return true - }; - this.spec = function() { - return{optype:"SetBlob", memberid:memberid, timestamp:timestamp, filename:filename, mimetype:mimetype, content:content} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpRemoveBlob = function OpRemoveBlob() { - var memberid, timestamp, filename; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - filename = data.filename - }; - this.isEdit = true; - this.execute = function(odtDocument) { - odtDocument.getOdfCanvas().odfContainer().removeBlob(filename); - return true - }; - this.spec = function() { - return{optype:"RemoveBlob", memberid:memberid, timestamp:timestamp, filename:filename} - } -}; +ops.OpApplyDirectStyling.Spec; /* Copyright (C) 2012-2013 KO GmbH @@ -11307,6 +13547,365 @@ ops.OpInsertText = function OpInsertText() { return{optype:"InsertText", memberid:memberid, timestamp:timestamp, position:position, text:text} } }; +ops.OpInsertText.Spec; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpMoveCursor = function OpMoveCursor() { + var memberid, timestamp, position, length, selectionType; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + position = data.position; + length = data.length || 0; + selectionType = data.selectionType || ops.OdtCursor.RangeSelection + }; + this.isEdit = false; + this.execute = function(odtDocument) { + var 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); + return true + }; + this.spec = function() { + return{optype:"MoveCursor", memberid:memberid, timestamp:timestamp, position:position, length:length, selectionType:selectionType} + } +}; +ops.OpMoveCursor.Spec; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("core.DomUtils"); +ops.OpRemoveAnnotation = function OpRemoveAnnotation() { + var memberid, timestamp, position, length, domUtils; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + position = parseInt(data.position, 10); + length = parseInt(data.length, 10); + domUtils = new core.DomUtils + }; + this.isEdit = true; + this.execute = function(odtDocument) { + var iterator = odtDocument.getIteratorAtPosition(position), container = iterator.container(), annotationName, annotationNode, annotationEnd, cursors; + 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 + } + odtDocument.getOdfCanvas().forgetAnnotations(); + cursors = domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "cursor"); + while(cursors.length) { + annotationNode.parentNode.insertBefore(cursors.pop(), annotationNode) + } + annotationNode.parentNode.removeChild(annotationNode); + if(annotationEnd) { + annotationEnd.parentNode.removeChild(annotationEnd) + } + odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position:position > 0 ? position - 1 : position, length:length}); + odtDocument.fixCursorPositions(); + odtDocument.getOdfCanvas().refreshAnnotations(); + return true + }; + this.spec = function() { + return{optype:"RemoveAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length} + } +}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpRemoveBlob = function OpRemoveBlob() { + var memberid, timestamp, filename; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + filename = data.filename + }; + this.isEdit = true; + this.execute = function(odtDocument) { + odtDocument.getOdfCanvas().odfContainer().removeBlob(filename); + return true + }; + this.spec = function() { + return{optype:"RemoveBlob", memberid:memberid, timestamp:timestamp, filename:filename} + } +}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpRemoveCursor = function OpRemoveCursor() { + var memberid, timestamp; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp + }; + this.isEdit = false; + this.execute = function(odtDocument) { + if(!odtDocument.removeCursor(memberid)) { + return false + } + return true + }; + this.spec = function() { + return{optype:"RemoveCursor", memberid:memberid, timestamp:timestamp} + } +}; +ops.OpRemoveCursor.Spec; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + @licend + + @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) { + memberid = data.memberid; + timestamp = parseInt(data.timestamp, 10) + }; + this.isEdit = false; + this.execute = function(odtDocument) { + if(!odtDocument.getMember(memberid)) { + return false + } + odtDocument.removeMember(memberid); + odtDocument.emit(ops.OdtDocument.signalMemberRemoved, memberid); + return true + }; + this.spec = function() { + return{optype:"RemoveMember", memberid:memberid, timestamp:timestamp} + } +}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpRemoveStyle = function OpRemoveStyle() { + var memberid, timestamp, styleName, styleFamily; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + styleName = data.styleName; + styleFamily = data.styleFamily + }; + this.isEdit = true; + this.execute = function(odtDocument) { + var styleNode = odtDocument.getStyleElement(styleName, styleFamily); + if(!styleNode) { + return false + } + styleNode.parentNode.removeChild(styleNode); + odtDocument.getOdfCanvas().refreshCSS(); + odtDocument.emit(ops.OdtDocument.signalCommonStyleDeleted, {name:styleName, family:styleFamily}); + return true + }; + this.spec = function() { + return{optype:"RemoveStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily} + } +}; +ops.OpRemoveStyle.Spec; /* Copyright (C) 2012-2013 KO GmbH @@ -11472,6 +14071,130 @@ ops.OpRemoveText = function OpRemoveText() { return{optype:"RemoveText", memberid:memberid, timestamp:timestamp, position:position, length:length} } }; +ops.OpRemoveText.Spec; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpSetBlob = function OpSetBlob() { + var memberid, timestamp, filename, mimetype, content; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + filename = data.filename; + mimetype = data.mimetype; + content = data.content + }; + this.isEdit = true; + this.execute = function(odtDocument) { + odtDocument.getOdfCanvas().odfContainer().setBlob(filename, mimetype, content); + return true + }; + this.spec = function() { + return{optype:"SetBlob", memberid:memberid, timestamp:timestamp, filename:filename, mimetype:mimetype, content:content} + } +}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpSetParagraphStyle = function OpSetParagraphStyle() { + var memberid, timestamp, position, styleName, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0"; + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + position = data.position; + styleName = data.styleName + }; + this.isEdit = true; + this.execute = function(odtDocument) { + var iterator, paragraphNode; + iterator = odtDocument.getIteratorAtPosition(position); + paragraphNode = odtDocument.getParagraphElement(iterator.container()); + if(paragraphNode) { + if(styleName !== "") { + paragraphNode.setAttributeNS(textns, "text:style-name", styleName) + }else { + paragraphNode.removeAttributeNS(textns, "style-name") + } + odtDocument.getOdfCanvas().refreshSize(); + odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphNode, timeStamp:timestamp, memberId:memberid}); + odtDocument.getOdfCanvas().rerenderAnnotations(); + return true + } + return false + }; + this.spec = function() { + return{optype:"SetParagraphStyle", memberid:memberid, timestamp:timestamp, position:position, styleName:styleName} + } +}; +ops.OpSetParagraphStyle.Spec; /* Copyright (C) 2012-2013 KO GmbH @@ -11583,544 +14306,7 @@ ops.OpSplitParagraph = function OpSplitParagraph() { return{optype:"SplitParagraph", memberid:memberid, timestamp:timestamp, position:position} } }; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpSetParagraphStyle = function OpSetParagraphStyle() { - var memberid, timestamp, position, styleName, textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0"; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - position = data.position; - styleName = data.styleName - }; - this.isEdit = true; - this.execute = function(odtDocument) { - var iterator, paragraphNode; - iterator = odtDocument.getIteratorAtPosition(position); - paragraphNode = odtDocument.getParagraphElement(iterator.container()); - if(paragraphNode) { - if(styleName !== "") { - paragraphNode.setAttributeNS(textns, "text:style-name", styleName) - }else { - paragraphNode.removeAttributeNS(textns, "style-name") - } - odtDocument.getOdfCanvas().refreshSize(); - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {paragraphElement:paragraphNode, timeStamp:timestamp, memberId:memberid}); - odtDocument.getOdfCanvas().rerenderAnnotations(); - return true - } - return false - }; - this.spec = function() { - return{optype:"SetParagraphStyle", memberid:memberid, timestamp:timestamp, position:position, styleName:styleName} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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"); -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.resolvePrefix(attributeNameParts[0]), attributeNameParts[1]) - } - } - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - styleName = data.styleName; - setProperties = data.setProperties; - removedProperties = data.removedProperties - }; - this.isEdit = true; - this.execute = function(odtDocument) { - var formatting = odtDocument.getFormatting(), styleNode, 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]; - if(setProperties) { - formatting.updateStyle(styleNode, setProperties) - } - if(removedProperties) { - if(removedProperties[paragraphPropertiesName]) { - removedAttributesFromStyleNode(paragraphPropertiesNode, removedProperties[paragraphPropertiesName].attributes); - if(paragraphPropertiesNode.attributes.length === 0) { - styleNode.removeChild(paragraphPropertiesNode) - } - } - if(removedProperties[textPropertiesName]) { - removedAttributesFromStyleNode(textPropertiesNode, removedProperties[textPropertiesName].attributes); - if(textPropertiesNode.attributes.length === 0) { - styleNode.removeChild(textPropertiesNode) - } - } - removedAttributesFromStyleNode(styleNode, removedProperties.attributes) - } - odtDocument.getOdfCanvas().refreshCSS(); - odtDocument.emit(ops.OdtDocument.signalParagraphStyleModified, styleName); - odtDocument.getOdfCanvas().rerenderAnnotations(); - return true - } - return false - }; - this.spec = function() { - return{optype:"UpdateParagraphStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, setProperties:setProperties, removedProperties:removedProperties} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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"); -ops.OpAddStyle = function OpAddStyle() { - var memberid, timestamp, styleName, styleFamily, isAutomaticStyle, setProperties, stylens = odf.Namespaces.stylens; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - styleName = data.styleName; - styleFamily = data.styleFamily; - isAutomaticStyle = data.isAutomaticStyle === "true" || data.isAutomaticStyle === true; - 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"); - if(!styleNode) { - return false - } - if(setProperties) { - formatting.updateStyle(styleNode, setProperties) - } - styleNode.setAttributeNS(stylens, "style:family", styleFamily); - styleNode.setAttributeNS(stylens, "style:name", styleName); - if(isAutomaticStyle) { - odfContainer.rootElement.automaticStyles.appendChild(styleNode) - }else { - odfContainer.rootElement.styles.appendChild(styleNode) - } - odtDocument.getOdfCanvas().refreshCSS(); - if(!isAutomaticStyle) { - odtDocument.emit(ops.OdtDocument.signalCommonStyleCreated, {name:styleName, family:styleFamily}) - } - return true - }; - this.spec = function() { - return{optype:"AddStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily, isAutomaticStyle:isAutomaticStyle, setProperties:setProperties} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpRemoveStyle = function OpRemoveStyle() { - var memberid, timestamp, styleName, styleFamily; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - styleName = data.styleName; - styleFamily = data.styleFamily - }; - this.isEdit = true; - this.execute = function(odtDocument) { - var styleNode = odtDocument.getStyleElement(styleName, styleFamily); - if(!styleNode) { - return false - } - styleNode.parentNode.removeChild(styleNode); - odtDocument.getOdfCanvas().refreshCSS(); - odtDocument.emit(ops.OdtDocument.signalCommonStyleDeleted, {name:styleName, family:styleFamily}); - return true - }; - this.spec = function() { - return{optype:"RemoveStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, styleFamily:styleFamily} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpAddAnnotation = function OpAddAnnotation() { - var memberid, timestamp, position, length, name; - this.init = function(data) { - memberid = data.memberid; - timestamp = parseInt(data.timestamp, 10); - position = parseInt(data.position, 10); - length = parseInt(data.length, 10) || 0; - name = data.name - }; - this.isEdit = true; - function createAnnotationNode(odtDocument, date) { - var annotationNode, creatorNode, dateNode, listNode, listItemNode, paragraphNode, doc = odtDocument.getDOM(); - 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); - creatorNode.textContent = odtDocument.getMember(memberid).getProperties().fullName; - dateNode = doc.createElementNS(odf.Namespaces.dcns, "dc:date"); - dateNode.appendChild(doc.createTextNode(date.toISOString())); - listNode = doc.createElementNS(odf.Namespaces.textns, "text:list"); - listItemNode = doc.createElementNS(odf.Namespaces.textns, "text:list-item"); - paragraphNode = doc.createElementNS(odf.Namespaces.textns, "text:p"); - listItemNode.appendChild(paragraphNode); - listNode.appendChild(listItemNode); - annotationNode.appendChild(creatorNode); - annotationNode.appendChild(dateNode); - annotationNode.appendChild(listNode); - return annotationNode - } - function createAnnotationEnd(odtDocument) { - var annotationEnd, doc = odtDocument.getDOM(); - annotationEnd = doc.createElementNS(odf.Namespaces.officens, "office:annotation-end"); - annotationEnd.setAttributeNS(odf.Namespaces.officens, "office:name", name); - return annotationEnd - } - function insertNodeAtPosition(odtDocument, node, insertPosition) { - var previousNode, parentNode, domPosition = odtDocument.getTextNodeAtStep(insertPosition, memberid); - if(domPosition) { - previousNode = domPosition.textNode; - parentNode = previousNode.parentNode; - if(domPosition.offset !== previousNode.length) { - previousNode.splitText(domPosition.offset) - } - parentNode.insertBefore(node, previousNode.nextSibling); - if(previousNode.length === 0) { - parentNode.removeChild(previousNode) - } - } - } - this.execute = function(odtDocument) { - var annotation = {}, positionFilter = odtDocument.getPositionFilter(), cursor = odtDocument.getCursor(memberid), oldCursorPosition = odtDocument.getCursorPosition(memberid), lengthToMove = position - oldCursorPosition - 1, stepsToParagraph; - annotation.node = createAnnotationNode(odtDocument, new Date(timestamp)); - if(!annotation.node) { - return false - } - if(length) { - annotation.end = createAnnotationEnd(odtDocument); - if(!annotation.end) { - return false - } - insertNodeAtPosition(odtDocument, annotation.end, position + length) - } - insertNodeAtPosition(odtDocument, annotation.node, position); - odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position:position, length:length}); - if(cursor) { - stepsToParagraph = cursor.getStepCounter().countSteps(lengthToMove, positionFilter); - cursor.move(stepsToParagraph); - cursor.resetSelectionType(); - odtDocument.emit(ops.OdtDocument.signalCursorMoved, cursor) - } - odtDocument.getOdfCanvas().addAnnotation(annotation); - odtDocument.fixCursorPositions(); - return true - }; - this.spec = function() { - return{optype:"AddAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length, name:name} - } -}; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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("core.DomUtils"); -ops.OpRemoveAnnotation = function OpRemoveAnnotation() { - var memberid, timestamp, position, length, domUtils; - this.init = function(data) { - memberid = data.memberid; - timestamp = data.timestamp; - position = parseInt(data.position, 10); - length = parseInt(data.length, 10); - domUtils = new core.DomUtils - }; - this.isEdit = true; - this.execute = function(odtDocument) { - var iterator = odtDocument.getIteratorAtPosition(position), container = iterator.container(), annotationName, annotationNode, annotationEnd, cursors; - 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 - } - odtDocument.getOdfCanvas().forgetAnnotations(); - cursors = domUtils.getElementsByTagNameNS(annotationNode, "urn:webodf:names:cursor", "cursor"); - while(cursors.length) { - annotationNode.parentNode.insertBefore(cursors.pop(), annotationNode) - } - annotationNode.parentNode.removeChild(annotationNode); - if(annotationEnd) { - annotationEnd.parentNode.removeChild(annotationEnd) - } - odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position:position > 0 ? position - 1 : position, length:length}); - odtDocument.fixCursorPositions(); - odtDocument.getOdfCanvas().refreshAnnotations(); - return true - }; - this.spec = function() { - return{optype:"RemoveAnnotation", memberid:memberid, timestamp:timestamp, position:position, length:length} - } -}; -/* - - Copyright (C) 2013 KO GmbH - - @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 . - @licend - - @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) { - memberid = data.memberid; - timestamp = parseInt(data.timestamp, 10); - setProperties = data.setProperties - }; - this.isEdit = false; - this.execute = function(odtDocument) { - if(odtDocument.getMember(memberid)) { - return false - } - var member = new ops.Member(memberid, setProperties); - odtDocument.addMember(member); - odtDocument.emit(ops.OdtDocument.signalMemberAdded, member); - return true - }; - this.spec = function() { - return{optype:"AddMember", memberid:memberid, timestamp:timestamp, setProperties:setProperties} - } -}; +ops.OpSplitParagraph.Spec; /* Copyright (C) 2013 KO GmbH @@ -12157,11 +14343,11 @@ ops.OpUpdateMember = function OpUpdateMember() { }; this.isEdit = false; function updateCreators() { - var xpath = new xmldom.XPath, xp = "//dc:creator[@editinfo:memberid='" + memberid + "']", creators = xpath.getODFElementsWithXPath(doc.getRootNode(), xp, function(prefix) { + 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" } - return odf.Namespaces.resolvePrefix(prefix) + return odf.Namespaces.lookupNamespaceURI(prefix) }), i; for(i = 0;i < creators.length;i += 1) { creators[i].textContent = setProperties.fullName @@ -12213,50 +14399,6 @@ ops.OpUpdateMember = function OpUpdateMember() { @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) { - memberid = data.memberid; - timestamp = parseInt(data.timestamp, 10) - }; - this.isEdit = false; - this.execute = function(odtDocument) { - if(!odtDocument.getMember(memberid)) { - return false - } - odtDocument.removeMember(memberid); - odtDocument.emit(ops.OdtDocument.signalMemberRemoved, memberid); - return true - }; - this.spec = function() { - return{optype:"RemoveMember", memberid:memberid, timestamp:timestamp} - } -}; -/* - - Copyright (C) 2013 KO GmbH - - @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 . - @licend - - @source: http://www.webodf.org/ - @source: https://github.com/kogmbh/WebODF/ -*/ ops.OpUpdateMetadata = function OpUpdateMetadata() { var memberid, timestamp, setProperties, removedProperties; this.init = function(data) { @@ -12327,6 +14469,101 @@ 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]) + } + } + this.init = function(data) { + memberid = data.memberid; + timestamp = data.timestamp; + styleName = data.styleName; + setProperties = data.setProperties; + removedProperties = data.removedProperties + }; + this.isEdit = true; + this.execute = function(odtDocument) { + var formatting = odtDocument.getFormatting(), styleNode, 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]; + if(setProperties) { + formatting.updateStyle(styleNode, setProperties) + } + if(removedProperties) { + if(removedProperties[paragraphPropertiesName]) { + removedAttributesFromStyleNode(paragraphPropertiesNode, removedProperties[paragraphPropertiesName].attributes); + if(paragraphPropertiesNode.attributes.length === 0) { + styleNode.removeChild(paragraphPropertiesNode) + } + } + if(removedProperties[textPropertiesName]) { + removedAttributesFromStyleNode(textPropertiesNode, removedProperties[textPropertiesName].attributes); + if(textPropertiesNode.attributes.length === 0) { + styleNode.removeChild(textPropertiesNode) + } + } + removedAttributesFromStyleNode(styleNode, removedProperties.attributes) + } + odtDocument.getOdfCanvas().refreshCSS(); + odtDocument.emit(ops.OdtDocument.signalParagraphStyleModified, styleName); + odtDocument.getOdfCanvas().rerenderAnnotations(); + return true + } + return false + }; + this.spec = function() { + return{optype:"UpdateParagraphStyle", memberid:memberid, timestamp:timestamp, styleName:styleName, setProperties:setProperties, removedProperties:removedProperties} + } +}; +ops.OpUpdateParagraphStyle.Spec; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("ops.OpAddMember"); runtime.loadClass("ops.OpUpdateMember"); runtime.loadClass("ops.OpRemoveMember"); @@ -12374,7 +14611,7 @@ ops.OperationFactory = function OperationFactory() { }; /* - Copyright (C) 2012-2013 KO GmbH + Copyright (C) 2013 KO GmbH @licstart The JavaScript code in this page is free software: you can redistribute it @@ -12409,759 +14646,23 @@ ops.OperationFactory = function OperationFactory() { @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, 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) { - rectangle = useRightEdge ? clientRectangles[clientRectangles.length - 1] : clientRectangles[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 && container.childNodes[offset - 1]) { - 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() ? cursor.getSelectedRange().cloneRange() : rootNode.ownerDocument.createRange(), 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() { - odfUtils = new odf.OdfUtils; - domUtils = new core.DomUtils; - positionIterator = gui.SelectionMover.createPositionIterator(rootNode); - var range = rootNode.ownerDocument.createRange(); - range.setStart(positionIterator.container(), positionIterator.unfilteredDomOffset()); - range.collapse(true); - cursor.setSelectedRange(range) - } - init() +ops.OperationRouter = function OperationRouter() { }; -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) +ops.OperationRouter.prototype.setOperationFactory = function(f) { }; -(function() { - return gui.SelectionMover -})(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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("core.PositionFilter"); -runtime.loadClass("odf.OdfUtils"); -(function() { - var nextNodeId = 0; - 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) { - this.steps = steps; - this.node = paragraphNode; - function positionInContainer(node) { - var position = 0; - while(node && node.previousSibling) { - position += 1; - node = node.previousSibling - } - return position - } - this.setIteratorPosition = function(iterator) { - iterator.setUnfilteredPosition(paragraphNode.parentNode, positionInContainer(paragraphNode)); - do { - if(filter.acceptPosition(iterator) === FILTER_ACCEPT) { - break - } - }while(iterator.nextPosition()) - } - } - function RootBookmark(steps, rootNode) { - this.steps = steps; - this.node = rootNode; - this.setIteratorPosition = function(iterator) { - iterator.setUnfilteredPosition(rootNode, 0); - do { - if(filter.acceptPosition(iterator) === FILTER_ACCEPT) { - break - } - }while(iterator.nextPosition()) - } - } - function getBucket(steps) { - return Math.floor(steps / bucketSize) * bucketSize - } - function getDestinationBucket(steps) { - return Math.ceil(steps / bucketSize) * bucketSize - } - function clearNodeId(node) { - node.removeAttributeNS(coordinatens, "nodeId") - } - function getNodeId(node) { - return node.nodeType === Node.ELEMENT_NODE && node.getAttributeNS(coordinatens, "nodeId") - } - function setNodeId(node) { - var nodeId = nextNodeId; - node.setAttributeNS(coordinatens, "nodeId", nodeId.toString()); - nextNodeId += 1; - return nodeId - } - function isValidBookmarkForNode(node, bookmark) { - return bookmark.node === node - } - function getNodeBookmark(node, steps) { - var nodeId = getNodeId(node) || setNodeId(node), existingBookmark; - existingBookmark = nodeToBookmark[nodeId]; - if(!existingBookmark) { - existingBookmark = nodeToBookmark[nodeId] = new ParagraphBookmark(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) - }else { - existingBookmark.steps = steps - } - } - return existingBookmark - } - function isFirstPositionInParagraph(node, offset) { - return offset === 0 && odfUtils.isParagraph(node) - } - 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 - } - } - } - if(stablePoint) { - bookmark = getNodeBookmark(node, steps); - cacheBucket = getDestinationBucket(bookmark.steps); - existingCachePoint = stepToDomPoint[cacheBucket]; - if(!existingCachePoint || bookmark.steps > existingCachePoint.steps) { - stepToDomPoint[cacheBucket] = bookmark - } - } - }; - this.setToClosestStep = function(steps, iterator) { - var cacheBucket = getBucket(steps), cachePoint; - while(!cachePoint && cacheBucket !== 0) { - cachePoint = stepToDomPoint[cacheBucket]; - cacheBucket -= bucketSize - } - cachePoint = cachePoint || basePoint; - 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); - if(nodeId) { - bookmark = nodeToBookmark[nodeId]; - if(bookmark && !isValidBookmarkForNode(node, bookmark)) { - runtime.log("Cloned node detected. Creating new bookmark"); - bookmark = null; - clearNodeId(node) - } - } - node = node.parentNode - } - return bookmark - } - this.setToClosestDomPoint = function(node, offset, iterator) { - var bookmark; - if(node === rootNode && 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) - }else { - bookmark = findBookmarkedAncestor(node, offset); - if(!bookmark) { - iterator.setUnfilteredPosition(node, offset); - while(!bookmark && iterator.previousNode()) { - bookmark = findBookmarkedAncestor(iterator.container(), iterator.unfilteredDomOffset()) - } - } - } - } - bookmark = 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] - } - }); - Object.keys(updatedBuckets).forEach(function(cacheBucket) { - stepToDomPoint[cacheBucket] = updatedBuckets[cacheBucket] - }) - }; - function init() { - basePoint = new RootBookmark(0, rootNode) - } - init() - } - 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; - function verifyRootNode() { - var currentRootNode = getRootNode(); - if(currentRootNode !== rootNode) { - runtime.log("Undo detected. Resetting steps cache"); - rootNode = currentRootNode; - stepsCache = new StepsCache(rootNode, filter, bucketSize); - iterator = newIterator(rootNode) - } - } - this.convertStepsToDomPoint = function(steps) { - var stepsFromRoot, isWalkable; - if(steps < 0) { - runtime.log("warn", "Requested steps were negative (" + steps + ")"); - steps = 0 - } - verifyRootNode(); - stepsFromRoot = stepsCache.setToClosestStep(steps, iterator); - while(stepsFromRoot < steps && iterator.nextPosition()) { - isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT; - if(isWalkable) { - stepsFromRoot += 1 - } - stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable) - } - if(stepsFromRoot !== steps) { - runtime.log("warn", "Requested " + steps + " steps but only " + stepsFromRoot + " are available") - } - return{node:iterator.container(), offset:iterator.unfilteredDomOffset()} - }; - this.convertDomPointToSteps = function(node, offset, roundUp) { - var stepsFromRoot, beforeRoot, destinationNode, destinationOffset, rounding = 0, isWalkable; - verifyRootNode(); - if(!domUtils.containsNode(rootNode, node)) { - beforeRoot = domUtils.comparePoints(rootNode, 0, node, offset) < 0; - node = rootNode; - offset = beforeRoot ? 0 : rootNode.childNodes.length - } - iterator.setUnfilteredPosition(node, offset); - destinationNode = iterator.container(); - destinationOffset = iterator.unfilteredDomOffset(); - if(roundUp && filter.acceptPosition(iterator) !== FILTER_ACCEPT) { - rounding = 1 - } - stepsFromRoot = stepsCache.setToClosestDomPoint(node, offset, iterator); - if(domUtils.comparePoints(iterator.container(), iterator.unfilteredDomOffset(), destinationNode, destinationOffset) < 0) { - return stepsFromRoot > 0 && !roundUp ? stepsFromRoot - 1 : stepsFromRoot - } - while(!(iterator.container() === destinationNode && iterator.unfilteredDomOffset() === destinationOffset) && iterator.nextPosition()) { - isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT; - if(isWalkable) { - stepsFromRoot += 1 - } - stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable) - } - return stepsFromRoot + rounding - }; - this.prime = function() { - var stepsFromRoot, isWalkable; - verifyRootNode(); - stepsFromRoot = stepsCache.setToClosestStep(0, iterator); - while(iterator.nextPosition()) { - isWalkable = filter.acceptPosition(iterator) === FILTER_ACCEPT; - if(isWalkable) { - stepsFromRoot += 1 - } - stepsCache.updateCache(stepsFromRoot, iterator.container(), iterator.unfilteredDomOffset(), isWalkable) - } - }; - this.handleStepsInserted = function(eventArgs) { - verifyRootNode(); - stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) { - bucket.steps += eventArgs.length - }) - }; - this.handleStepsRemoved = function(eventArgs) { - verifyRootNode(); - stepsCache.updateCacheAtPoint(eventArgs.position, function(bucket) { - bucket.steps -= eventArgs.length; - if(bucket.steps < 0) { - bucket.steps = 0 - } - }) - } - }; - return ops.StepsTranslator -})(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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) { - 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 - } +ops.OperationRouter.prototype.setPlaybackFunction = function(playback_func) { +}; +ops.OperationRouter.prototype.push = function(operations) { +}; +ops.OperationRouter.prototype.close = function(callback) { +}; +ops.OperationRouter.prototype.subscribe = function(eventId, cb) { +}; +ops.OperationRouter.prototype.unsubscribe = function(eventId, cb) { +}; +ops.OperationRouter.prototype.hasLocalUnsyncedOps = function() { +}; +ops.OperationRouter.prototype.hasSessionHostConnection = function() { }; /* @@ -13847,2288 +15348,6 @@ ops.OperationTransformer = function OperationTransformer() { return{opsA:operations(opSpecsA), opsB:operations(transformedOpspecsB)} } }; -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) - }else { - if(number <= 0) { - moved = -selectionMover.movePointBackward(-number, extend) - } - } - 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() - } - init() -}; -ops.OdtCursor.RangeSelection = "Range"; -ops.OdtCursor.RegionSelection = "Region"; -(function() { - return ops.OdtCursor -})(); -/* - - Copyright (C) 2012 KO GmbH - - @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 . - - 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() -}; -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 -})(); -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() -}; -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() -}; -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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.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})); - cursorPosition += 1; - operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text})); - cursorPosition += text.length - }); - operations.push(createOp(new ops.OpRemoveText, {memberid:inputMemberId, position:originalCursorPosition, length:1})); - return operations - } -}; -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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) 2013 KO GmbH - - @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 . - - 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)) - } - return selectionStyles - } - function updatedCachedValues() { - var fontSize, diffMap; - currentSelectionStyles = getAppliedStyles(); - function noteChange(oldValue, newValue, id) { - if(oldValue !== newValue) { - if(diffMap === undefined) { - diffMap = {} - } - diffMap[id] = newValue - } - 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) - } - } - function onCursorAdded(cursor) { - if(cursor.getMemberId() === inputMemberId) { - updatedCachedValues() - } - } - function onCursorRemoved(memberId) { - if(memberId === inputMemberId) { - updatedCachedValues() - } - } - function onCursorMoved(cursor) { - if(cursor.getMemberId() === inputMemberId) { - updatedCachedValues() - } - } - function onParagraphStyleModified() { - updatedCachedValues() - } - function onParagraphChanged(args) { - var cursor = odtDocument.getCursor(inputMemberId); - if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) { - updatedCachedValues() - } - } - function toggle(predicate, toggleMethod) { - var cursor = odtDocument.getCursor(inputMemberId), appliedStyles; - if(!cursor) { - return false - } - appliedStyles = styleHelper.getAppliedStyles(cursor.getSelectedRange()); - toggleMethod(!predicate(appliedStyles)); - 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); - updatedCachedValues() - } - } - this.formatTextSelection = formatTextSelection; - function applyTextPropertyToSelection(propertyName, propertyValue) { - var textProperties = {}; - textProperties[propertyName] = propertyValue; - formatTextSelection(textProperties) - } - 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() - } - return styleOp - }; - function clearCursorStyle(op) { - var spec = op.spec(); - if(directCursorStyleProperties && spec.memberid === inputMemberId) { - if(spec.optype !== "SplitParagraph") { - directCursorStyleProperties = null; - updatedCachedValues() - } - } - } - 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 currentSelectionStyles - }; - 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.hasUnderline = function() { - return hasUnderlineValue - }; - this.hasStrikeThrough = function() { - return hasStrikeThroughValue - }; - this.fontSize = function() { - return fontSizeValue - }; - this.fontName = function() { - return fontNameValue - }; - 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); - odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified); - odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged); - odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle); - 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() - } - init() -}; -gui.DirectTextStyler.textStylingChanged = "textStyling/changed"; -(function() { - return gui.DirectTextStyler -})(); -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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("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 - } - 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) - } - } - function onCursorAdded(cursor) { - if(cursor.getMemberId() === inputMemberId) { - updatedCachedValues() - } - } - function onCursorRemoved(memberId) { - if(memberId === inputMemberId) { - updatedCachedValues() - } - } - function onCursorMoved(cursor) { - if(cursor.getMemberId() === inputMemberId) { - updatedCachedValues() - } - } - function onParagraphStyleModified() { - updatedCachedValues() - } - function onParagraphChanged(args) { - var cursor = odtDocument.getCursor(inputMemberId); - if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) { - updatedCachedValues() - } - } - this.isAlignedLeft = function() { - return isAlignedLeftValue - }; - this.isAlignedCenter = function() { - return isAlignedCenterValue - }; - this.isAlignedRight = function() { - return isAlignedRightValue - }; - this.isAlignedJustified = function() { - return isAlignedJustifiedValue - }; - function applyParagraphDirectStyling(applyDirectStyling) { - var range = odtDocument.getCursor(inputMemberId).getSelectedRange(), position = odtDocument.getCursorPosition(inputMemberId), paragraphs = odfUtils.getParagraphElements(range), formatting = odtDocument.getFormatting(); - paragraphs.forEach(function(paragraph) { - var paragraphStartPoint = position + odtDocument.getDistanceFromCursor(inputMemberId, paragraph, 0), paragraphStyleName = paragraph.getAttributeNS(odf.Namespaces.textns, "style-name"), newParagraphStyleName = objectNameGenerator.generateStyleName(), opAddStyle, opSetParagraphStyle, paragraphProperties; - paragraphStartPoint += 1; - if(paragraphStyleName) { - paragraphProperties = formatting.createDerivedStyleObject(paragraphStyleName, "paragraph", {}) - } - 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]) - }) - } - function applySimpleParagraphDirectStyling(styleOverrides) { - applyParagraphDirectStyling(function(paragraphStyle) { - return utils.mergeObjects(paragraphStyle, styleOverrides) - }) - } - function alignParagraph(alignment) { - applySimpleParagraphDirectStyling({"style:paragraph-properties":{"fo:text-align":alignment}}) - } - this.alignParagraphLeft = function() { - alignParagraph("left"); - return true - }; - this.alignParagraphCenter = function() { - alignParagraph("center"); - return true - }; - this.alignParagraphRight = function() { - alignParagraph("right"); - return true - }; - this.alignParagraphJustified = function() { - alignParagraph("justify"); - 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; - if(indent && indent.unit === tabStopDistance.unit) { - newIndent = indent.value + direction * tabStopDistance.value + indent.unit - }else { - newIndent = direction * tabStopDistance.value + tabStopDistance.unit - } - return utils.mergeObjects(paragraphStyle, {"style:paragraph-properties":{"fo:margin-left":newIndent}}) - } - this.indent = function() { - applyParagraphDirectStyling(modifyParagraphIndent.bind(null, 1)); - return true - }; - this.outdent = function() { - applyParagraphDirectStyling(modifyParagraphIndent.bind(null, -1)); - return true - }; - 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); - odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified); - odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged); - 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); - updatedCachedValues() - } - init() -}; -gui.DirectParagraphStyler.paragraphStylingChanged = "paragraphStyling/changed"; -(function() { - return gui.DirectParagraphStyler -})(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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) { - 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() - }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, 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 -})(); -runtime.loadClass("odf.Namespaces"); -runtime.loadClass("odf.ObjectNameGenerator"); -gui.ImageManager = function ImageManager(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; - op.init({memberid:inputMemberId, styleName:name, styleFamily:"graphic", isAutomaticStyle:false, 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"}}}); - return op - } - function createAddFrameStyleOp(styleName, parentStyleName) { - var op = new ops.OpAddStyle; - op.init({memberid:inputMemberId, styleName:styleName, styleFamily:"graphic", isAutomaticStyle:true, setProperties:{"style:parent-style-name":parentStyleName, "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"}}}); - return op - } - function getFileExtension(mimetype) { - mimetype = mimetype.toLowerCase(); - return fileExtensionByMimetype.hasOwnProperty(mimetype) ? fileExtensionByMimetype[mimetype] : null - } - function insertImageInternal(mimetype, content, widthInCm, heightInCm) { - var graphicsStyleName = "Graphics", stylesElement = odtDocument.getOdfCanvas().odfContainer().rootElement.styles, fileExtension = getFileExtension(mimetype), fileName, graphicsStyleElement, frameStyleName, op, operations = []; - runtime.assert(fileExtension !== null, "Image type is not supported: " + mimetype); - fileName = "Pictures/" + objectNameGenerator.generateImageName() + fileExtension; - op = new ops.OpSetBlob; - op.init({memberid:inputMemberId, filename:fileName, mimetype:mimetype, content:content}); - operations.push(op); - graphicsStyleElement = formatting.getStyleElement(graphicsStyleName, "graphic", [stylesElement]); - if(!graphicsStyleElement) { - op = createAddGraphicsStyleOp(graphicsStyleName); - operations.push(op) - } - frameStyleName = objectNameGenerator.generateStyleName(); - op = createAddFrameStyleOp(frameStyleName, graphicsStyleName); - operations.push(op); - op = new ops.OpInsertImage; - op.init({memberid:inputMemberId, position:odtDocument.getCursorPosition(inputMemberId), filename:fileName, frameWidth:widthInCm + "cm", frameHeight:heightInCm + "cm", frameStyleName:frameStyleName, frameName:objectNameGenerator.generateFrameName()}); - operations.push(op); - session.enqueue(operations) - } - function trimmedSize(originalSize, pageContentSize) { - var widthRatio = 1, heightRatio = 1, ratio; - if(originalSize.width > pageContentSize.width) { - widthRatio = pageContentSize.width / originalSize.width - } - if(originalSize.height > pageContentSize.height) { - heightRatio = pageContentSize.height / originalSize.height - } - ratio = Math.min(widthRatio, heightRatio); - return{width:originalSize.width * ratio, height:originalSize.height * ratio} - } - this.insertImage = function(mimetype, content, widthInPx, heightInPx) { - var paragraphElement, styleName, pageContentSize, originalSize, newSize; - runtime.assert(widthInPx > 0 && heightInPx > 0, "Both width and height of the image should be greater than 0px."); - paragraphElement = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()); - styleName = paragraphElement.getAttributeNS(textns, "style-name"); - if(!paragraphStyleToPageContentSizeMap.hasOwnProperty(styleName)) { - paragraphStyleToPageContentSizeMap[styleName] = formatting.getContentSize(styleName, "paragraph") - } - pageContentSize = paragraphStyleToPageContentSizeMap[styleName]; - originalSize = {width:widthInPx * cmPerPixel, height:heightInPx * cmPerPixel}; - newSize = trimmedSize(originalSize, pageContentSize); - insertImageInternal(mimetype, content, newSize.width, newSize.height) - } -}; -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" - } - } - hasSelection = false - }; - this.isSelectorElement = function(node) { - var selectorElement = document.getElementById(imageSelectorId); - if(!selectorElement) { - return false - } - return node === selectorElement || node.parentNode === selectorElement - } -}; -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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"); -gui.TextManipulator = function TextManipulator(session, inputMemberId, directStyleOp) { - var odtDocument = session.getOdtDocument(), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT; - function createOpRemoveSelection(selection) { - var op = new ops.OpRemoveText; - op.init({memberid:inputMemberId, position:selection.position, length:selection.length}); - return op - } - function toForwardSelection(selection) { - if(selection.length < 0) { - selection.position += selection.length; - selection.length = -selection.length - } - return selection - } - this.enqueueParagraphSplittingOps = function() { - var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, operations = []; - if(selection.length > 0) { - op = createOpRemoveSelection(selection); - operations.push(op) - } - op = new ops.OpSplitParagraph; - op.init({memberid:inputMemberId, position:selection.position}); - operations.push(op); - 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)); - iterator.setUnfilteredPosition(cursorNode, 0); - while(nextPosition()) { - if(rootConstrainedFilter.acceptPosition(iterator) === FILTER_ACCEPT) { - return true - } - } - return false - } - this.removeTextByBackspaceKey = function() { - var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null; - if(selection.length === 0) { - if(hasPositionInDirection(cursor.getNode(), false)) { - op = new ops.OpRemoveText; - op.init({memberid:inputMemberId, position:selection.position - 1, length:1}); - session.enqueue([op]) - } - }else { - op = createOpRemoveSelection(selection); - session.enqueue([op]) - } - return op !== null - }; - this.removeTextByDeleteKey = function() { - var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null; - if(selection.length === 0) { - if(hasPositionInDirection(cursor.getNode(), true)) { - op = new ops.OpRemoveText; - op.init({memberid:inputMemberId, position:selection.position, length:1}); - session.enqueue([op]) - } - }else { - op = createOpRemoveSelection(selection); - session.enqueue([op]) - } - return op !== null - }; - this.removeCurrentSelection = function() { - var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op; - if(selection.length !== 0) { - op = createOpRemoveSelection(selection); - session.enqueue([op]) - } - return true - }; - function insertText(text) { - var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, stylingOp, operations = []; - if(selection.length > 0) { - op = createOpRemoveSelection(selection); - operations.push(op) - } - op = new ops.OpInsertText; - op.init({memberid:inputMemberId, position:selection.position, text:text}); - operations.push(op); - if(directStyleOp) { - stylingOp = directStyleOp(selection.position, text.length); - if(stylingOp) { - operations.push(stylingOp) - } - } - session.enqueue(operations) - } - this.insertText = insertText -}; -(function() { - return gui.TextManipulator -})(); -/* - - Copyright (C) 2013 KO GmbH - - @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 . - @licend - - @source: http://www.webodf.org/ - @source: https://github.com/kogmbh/WebODF/ -*/ -runtime.loadClass("core.EventNotifier"); -runtime.loadClass("core.PositionFilter"); -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 = cursorNode && !isWithinAnnotation(cursorNode, odtDocument.getRootNode()); - if(newIsAnnotatable !== isAnnotatable) { - isAnnotatable = newIsAnnotatable; - eventNotifier.emit(gui.AnnotationController.annotatableChanged, isAnnotatable) - } - } - function onCursorAdded(cursor) { - if(cursor.getMemberId() === inputMemberId) { - updatedCachedValues() - } - } - function onCursorRemoved(memberId) { - if(memberId === inputMemberId) { - updatedCachedValues() - } - } - function onCursorMoved(cursor) { - if(cursor.getMemberId() === inputMemberId) { - updatedCachedValues() - } - } - 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() - }; - function init() { - odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded); - odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved); - odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved); - updatedCachedValues() - } - init() -}; -gui.AnnotationController.annotatableChanged = "annotatable/changed"; -(function() { - return gui.AnnotationController -})(); -gui.EventManager = function EventManager(odtDocument) { - var canvasElement = odtDocument.getOdfCanvas().getElement(), window = runtime.getWindow(), bindToDirectHandler = {"beforecut":true, "beforepaste":true}, bindToWindow; - 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 = window && bindToWindow[eventName]; - if(delegate) { - delegate.handlers.push(handler); - if(!delegate.isSubscribed) { - delegate.isSubscribed = true; - listenEvent((window), eventName, delegate.handleEvent); - listenEvent(canvasElement, eventName, delegate.handleEvent) - } - }else { - listenEvent(canvasElement, eventName, handler) - } - }; - this.unsubscribe = function(eventName, handler) { - var delegate = window && bindToWindow[eventName], handlerIndex = delegate && delegate.handlers.indexOf(handler); - if(delegate) { - if(handlerIndex !== -1) { - delegate.handlers.splice(handlerIndex, 1) - } - }else { - removeEvent(canvasElement, eventName, handler) - } - }; - function hasFocus() { - var activeElement = odtDocument.getDOM().activeElement; - return activeElement === canvasElement - } - this.hasFocus = hasFocus; - function findScrollableParent(element) { - while(element && (!element.scrollTop && !element.scrollLeft)) { - element = (element.parentNode) - } - if(element) { - return new ElementScrollState(element) - } - if(window) { - return new WindowScrollState(window) - } - return null - } - this.focus = function() { - var scrollParent; - if(!hasFocus()) { - scrollParent = findScrollableParent(canvasElement); - canvasElement.focus(); - if(scrollParent) { - scrollParent.restore() - } - } - }; - function init() { - bindToWindow = {"mousedown":new EventDelegate, "mouseup":new EventDelegate} - } - init() -}; -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 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, suppressFocusEvent = false, pasteHandler = new gui.PlainTextPasteboard(odtDocument, inputMemberId); - 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 - } - function cancelEvent(event) { - if(event.preventDefault) { - event.preventDefault() - }else { - 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(), result; - if(doc.caretRangeFromPoint) { - result = doc.caretRangeFromPoint(x, y); - return{container:result.startContainer, offset:result.startOffset} - } - if(doc.caretPositionFromPoint) { - result = doc.caretPositionFromPoint(x, y); - return{container:result.offsetNode, offset:result.offset} - } - return null - } - function expandToWordBoundaries(selection) { - var alphaNumeric = /[A-Za-z0-9]/, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), isForwardSelection = domUtils.comparePoints(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset) > 0, startPoint, endPoint, currentNode, c; - if(isForwardSelection) { - startPoint = {node:selection.anchorNode, offset:selection.anchorOffset}; - endPoint = {node:selection.focusNode, offset:selection.focusOffset} - }else { - startPoint = {node:selection.focusNode, offset:selection.focusOffset}; - endPoint = {node:selection.anchorNode, offset:selection.anchorOffset} - } - iterator.setUnfilteredPosition(startPoint.node, startPoint.offset); - 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 - } - } - startPoint.node = iterator.container(); - startPoint.offset = iterator.unfilteredDomOffset() - } - iterator.setUnfilteredPosition(endPoint.node, endPoint.offset); - 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()); - endPoint.node = iterator.container(); - endPoint.offset = iterator.unfilteredDomOffset(); - if(isForwardSelection) { - selection.anchorNode = startPoint.node; - selection.anchorOffset = startPoint.offset; - selection.focusNode = endPoint.node; - selection.focusOffset = endPoint.offset - }else { - selection.focusNode = startPoint.node; - selection.focusOffset = startPoint.offset; - selection.anchorNode = endPoint.node; - selection.anchorOffset = endPoint.offset - } - } - function expandToParagraphBoundaries(selection) { - var anchorParagraph = odtDocument.getParagraphElement(selection.anchorNode), focusParagraph = odtDocument.getParagraphElement(selection.focusNode); - if(anchorParagraph) { - selection.anchorNode = anchorParagraph; - selection.anchorOffset = 0 - } - if(focusParagraph) { - selection.focusNode = focusParagraph; - selection.focusOffset = focusParagraph.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 selectRange(selection, capturedDetails) { - var canvasElement = odtDocument.getOdfCanvas().getElement(), validSelection, clickCount = capturedDetails.detail, caretPos, anchorNodeInsideCanvas, focusNodeInsideCanvas, existingSelection, newSelection, op; - if(!selection) { - return - } - if(!selection.anchorNode && !selection.focusNode) { - caretPos = caretPositionFromPoint(capturedDetails.clientX, capturedDetails.clientY); - if(!caretPos) { - return - } - selection.anchorNode = (caretPos.container); - selection.anchorOffset = caretPos.offset; - selection.focusNode = selection.anchorNode; - selection.focusOffset = selection.anchorOffset - } - runtime.assert(selection.anchorNode !== null && selection.focusNode !== null, "anchorNode or focusNode is null"); - validSelection = (selection); - anchorNodeInsideCanvas = domUtils.containsNode(canvasElement, validSelection.anchorNode); - focusNodeInsideCanvas = domUtils.containsNode(canvasElement, validSelection.focusNode); - if(!anchorNodeInsideCanvas && !focusNodeInsideCanvas) { - return - } - if(anchorNodeInsideCanvas && focusNodeInsideCanvas) { - if(clickCount === 2) { - expandToWordBoundaries(validSelection) - }else { - if(clickCount >= 3) { - expandToParagraphBoundaries(validSelection) - } - } - } - newSelection = odtDocument.convertDomToCursorRange(validSelection.anchorNode, validSelection.anchorOffset, validSelection.focusNode, validSelection.focusOffset); - 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]) - } - eventManager.focus() - } - 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 maintainCursorSelection() { - var cursor = odtDocument.getCursor(inputMemberId), selection = window.getSelection(), imageElement, range; - if(cursor) { - imageSelector.clearSelection(); - if(cursor.getSelectionType() === ops.OdtCursor.RegionSelection) { - imageElement = odfUtils.getImageElements(cursor.getSelectedRange())[0]; - if(imageElement) { - imageSelector.select((imageElement.parentNode)) - } - } - if(eventManager.hasFocus()) { - range = cursor.getSelectedRange(); - if(selection.extend) { - if(cursor.hasForwardSelection()) { - selection.collapse(range.startContainer, range.startOffset); - selection.extend(range.endContainer, range.endOffset) - }else { - selection.collapse(range.endContainer, range.endOffset); - selection.extend(range.startContainer, range.startOffset) - } - }else { - suppressFocusEvent = true; - selection.removeAllRanges(); - selection.addRange(range.cloneRange()); - odtDocument.getOdfCanvas().getElement().setActive(); - runtime.setTimeout(function() { - suppressFocusEvent = false - }, 0) - } - } - }else { - imageSelector.clearSelection() - } - } - function delayedMaintainCursor() { - if(suppressFocusEvent === false) { - runtime.setTimeout(maintainCursorSelection, 0) - } - } - function stringFromKeyPress(event) { - if(event.which === null || event.which === undefined) { - return String.fromCharCode(event.keyCode) - } - if(event.which !== 0 && event.charCode !== 0) { - return String.fromCharCode(event.which) - } - return null - } - function handleCut(e) { - var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange(); - if(selectedRange.collapsed) { - return - } - if(clipboard.setDataFromRange(e, cursor.getSelectedRange())) { - textManipulator.removeCurrentSelection() - }else { - runtime.log("Cut operation failed") - } - } - function handleBeforeCut() { - var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange(); - return selectedRange.collapsed !== false - } - function handleCopy(e) { - var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange(); - if(selectedRange.collapsed) { - return - } - if(!clipboard.setDataFromRange(e, cursor.getSelectedRange())) { - runtime.log("Cut operation failed") - } - } - function handlePaste(e) { - var plainText; - if(window.clipboardData && window.clipboardData.getData) { - plainText = window.clipboardData.getData("Text") - }else { - if(e.clipboardData && e.clipboardData.getData) { - plainText = e.clipboardData.getData("text/plain") - } - } - if(plainText) { - textManipulator.removeCurrentSelection(); - session.enqueue(pasteHandler.createPasteOps(plainText)); - cancelEvent(e) - } - } - function handleBeforePaste() { - return false - } - function updateUndoStack(op) { - if(undoManager) { - undoManager.onOperationExecuted(op) - } - } - function forwardUndoStackChange(e) { - odtDocument.emit(ops.OdtDocument.signalUndoStackChanged, e) - } - function undo() { - if(undoManager) { - undoManager.moveBackward(1); - maintainCursorSelection(); - return true - } - return false - } - function redo() { - if(undoManager) { - undoManager.moveForward(1); - maintainCursorSelection(); - return true - } - return false - } - function filterMouseClicks(e) { - var target = getTarget(e); - clickStartedWithinContainer = target && domUtils.containsNode(odtDocument.getOdfCanvas().getElement(), target); - if(clickStartedWithinContainer) { - isMouseMoved = false; - mouseDownRootFilter = odtDocument.createRootFilter(target) - } - } - function cursorToSelection(cursor) { - var range = cursor.getSelectedRange(); - if(cursor.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 mutableSelection(selection) { - if(selection) { - return{anchorNode:selection.anchorNode, anchorOffset:selection.anchorOffset, focusNode:selection.focusNode, focusOffset:selection.focusOffset} - } - return null - } - function handleMouseClickEvent(event) { - var target = getTarget(event), eventDetails = {detail:event.detail, clientX:event.clientX, clientY:event.clientY, target:target}; - drawShadowCursorTask.processRequests(); - if(odfUtils.isImage(target) && odfUtils.isCharacterFrame(target.parentNode)) { - selectImage(target.parentNode) - }else { - if(clickStartedWithinContainer && !imageSelector.isSelectorElement(target)) { - if(isMouseMoved) { - selectRange(cursorToSelection(shadowCursor), event) - }else { - runtime.setTimeout(function() { - selectRange(mutableSelection(window.getSelection()), eventDetails) - }, 0) - } - } - } - clickStartedWithinContainer = false; - isMouseMoved = false - } - function handleContextMenu(e) { - handleMouseClickEvent(e) - } - function handleMouseUp(event) { - var target = getTarget(event), annotationNode = null; - if(target.className === "annotationRemoveButton") { - annotationNode = domUtils.getElementsByTagNameNS(target.parentNode, odf.Namespaces.officens, "annotation")[0]; - annotationController.removeAnnotation(annotationNode) - }else { - handleMouseClickEvent(event) - } - } - function updateShadowCursor() { - var selection = window.getSelection(), selectionRange, isForwardSelection; - if(clickStartedWithinContainer && selection.rangeCount > 0) { - isMouseMoved = true; - imageSelector.clearSelection(); - shadowCursorIterator.setUnfilteredPosition((selection.focusNode), selection.focusOffset); - if(mouseDownRootFilter.acceptPosition(shadowCursorIterator) === FILTER_ACCEPT) { - selectionRange = selection.getRangeAt(0).cloneRange(); - isForwardSelection = selection.anchorNode === selectionRange.startContainer && selection.anchorOffset === selectionRange.startOffset; - shadowCursor.setSelectedRange(selectionRange, isForwardSelection); - odtDocument.emit(ops.OdtDocument.signalCursorMoved, shadowCursor) - } - } - } - 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); - eventManager.subscribe("beforecut", handleBeforeCut); - eventManager.subscribe("cut", handleCut); - eventManager.subscribe("copy", handleCopy); - eventManager.subscribe("beforepaste", handleBeforePaste); - eventManager.subscribe("paste", handlePaste); - eventManager.subscribe("mousedown", filterMouseClicks); - eventManager.subscribe("mousemove", drawShadowCursorTask.trigger); - eventManager.subscribe("mouseup", handleMouseUp); - eventManager.subscribe("contextmenu", handleContextMenu); - eventManager.subscribe("focus", delayedMaintainCursor); - odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, maintainCursorSelection); - odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack); - op = new ops.OpAddCursor; - op.init({memberid:inputMemberId}); - session.enqueue([op]); - if(undoManager) { - undoManager.saveInitialState() - } - }; - 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, maintainCursorSelection); - eventManager.unsubscribe("keydown", keyDownHandler.handleEvent); - eventManager.unsubscribe("keypress", keyPressHandler.handleEvent); - eventManager.unsubscribe("keyup", dummyHandler); - 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", filterMouseClicks); - eventManager.unsubscribe("mouseup", handleMouseUp); - eventManager.unsubscribe("contextmenu", handleContextMenu); - eventManager.unsubscribe("focus", delayedMaintainCursor); - odtDocument.getOdfCanvas().getElement().classList.remove("virtualSelections") - }; - this.getInputMemberId = function() { - return inputMemberId - }; - this.getSession = function() { - return session - }; - this.setUndoManager = function(manager) { - if(undoManager) { - undoManager.unsubscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange) - } - undoManager = manager; - if(undoManager) { - undoManager.setOdtDocument(odtDocument); - undoManager.setPlaybackFunction(function(op) { - op.execute(odtDocument) - }); - undoManager.subscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange) - } - }; - this.getUndoManager = function() { - return undoManager - }; - this.getAnnotationController = function() { - return annotationController - }; - this.getDirectTextStyler = function() { - return directTextStyler - }; - this.getDirectParagraphStyler = function() { - return directParagraphStyler - }; - this.getImageManager = function() { - return imageManager - }; - this.getTextManipulator = function() { - return textManipulator - }; - this.getEventManager = function() { - return eventManager - }; - this.getKeyboardHandlers = function() { - return{keydown:keyDownHandler, keypress:keyPressHandler} - }; - this.destroy = function(callback) { - var destroyCallbacks = [drawShadowCursorTask.destroy, directTextStyler.destroy]; - if(directParagraphStyler) { - destroyCallbacks.push(directParagraphStyler.destroy) - } - 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); - 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)); - 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) - }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) - } - 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)) - } - init() - }; - return gui.SessionController -}(); -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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.OperationRouter = function OperationRouter() { -}; -ops.OperationRouter.prototype.setOperationFactory = function(f) { -}; -ops.OperationRouter.prototype.setPlaybackFunction = function(playback_func) { -}; -ops.OperationRouter.prototype.push = function(operations) { -}; -ops.OperationRouter.prototype.close = function(callback) { -}; /* Copyright (C) 2012 KO GmbH @@ -16184,54 +15403,18 @@ ops.TrivialOperationRouter = function TrivialOperationRouter() { }; this.close = function(cb) { cb() + }; + this.subscribe = function(eventId, cb) { + }; + this.unsubscribe = function(eventId, cb) { + }; + this.hasLocalUnsyncedOps = function() { + return false + }; + this.hasSessionHostConnection = function() { + return true } }; -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-2013 KO GmbH @@ -16363,427 +15546,6 @@ gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) { } init() }; -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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("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 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; - 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) { - return node - } - node = node.nextSibling - } - return null - } - function setAvatarInfoStyle(memberId, name, color) { - function setStyle(nodeName, rule, pseudoClass) { - var styleRule = createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) + rule, styleNode = getAvatarInfoStyle(nodeName, memberId, pseudoClass); - if(styleNode) { - styleNode.data = styleRule - }else { - avatarInfoStyles.appendChild(document.createTextNode(styleRule)) - } - } - setStyle("div.editInfoMarker", "{ background-color: " + color + "; }", ""); - setStyle("span.editInfoColor", "{ background-color: " + color + "; }", ""); - setStyle("span.editInfoAuthor", '{ content: "' + name + '"; }', ":before"); - setStyle("dc|creator", "{ background-color: " + color + "; }", ""); - setStyle("div.selectionOverlay", "{ background-color: " + color + ";}", "") - } - function highlightEdit(element, memberId, timestamp) { - var editInfo, editInfoMarker, id = "", editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0]; - if(editInfoNode) { - 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.setAttributeNS(editInfons, "id", id); - editInfoMap[id] = editInfoMarker - } - editInfoMarker.addEdit(memberId, new Date(timestamp)) - } - function setEditInfoMarkerVisibility(visible) { - var editInfoMarker, keyname; - for(keyname in editInfoMap) { - if(editInfoMap.hasOwnProperty(keyname)) { - editInfoMarker = editInfoMap[keyname]; - if(visible) { - editInfoMarker.show() - }else { - editInfoMarker.hide() - } - } - } - } - function setCaretAvatarVisibility(visible) { - caretManager.getCarets().forEach(function(caret) { - if(visible) { - caret.showHandle() - }else { - caret.hideHandle() - } - }) - } - this.showEditInfoMarkers = function() { - if(showEditInfoMarkers) { - return - } - showEditInfoMarkers = true; - setEditInfoMarkerVisibility(showEditInfoMarkers) - }; - this.hideEditInfoMarkers = function() { - if(!showEditInfoMarkers) { - return - } - showEditInfoMarkers = false; - setEditInfoMarkerVisibility(showEditInfoMarkers) - }; - this.showCaretAvatars = function() { - if(showCaretAvatars) { - return - } - showCaretAvatars = true; - setCaretAvatarVisibility(showCaretAvatars) - }; - this.hideCaretAvatars = function() { - if(!showCaretAvatars) { - return - } - showCaretAvatars = false; - setCaretAvatarVisibility(showCaretAvatars) - }; - this.getSession = function() { - return session - }; - this.getCaret = function(memberid) { - return caretManager.getCaret(memberid) - }; - function renderMemberData(member) { - var memberId = member.getMemberId(), properties = member.getProperties(); - setAvatarInfoStyle(memberId, properties.fullName, properties.color); - if(localMemberId === memberId) { - setAvatarInfoStyle("", "", properties.color) - } - } - function onCursorAdded(cursor) { - var memberId = cursor.getMemberId(), properties = session.getOdtDocument().getMember(memberId).getProperties(), caret; - caretManager.registerCursor(cursor, showCaretAvatars, blinkOnRangeSelect); - selectionViewManager.registerCursor(cursor, true); - caret = caretManager.getCaret(memberId); - if(caret) { - caret.setAvatarImageUrl(properties.imageUrl); - caret.setColor(properties.color) - } - runtime.log("+++ View here +++ eagerly created an Caret for '" + memberId + "'! +++") - } - function onCursorMoved(cursor) { - var memberId = cursor.getMemberId(), localSelectionView = selectionViewManager.getSelectionView(localMemberId), shadowSelectionView = selectionViewManager.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId), localCaret = caretManager.getCaret(localMemberId); - if(memberId === localMemberId) { - shadowSelectionView.hide(); - localSelectionView.show(); - if(localCaret) { - localCaret.show() - } - }else { - if(memberId === gui.ShadowCursor.ShadowCursorMemberId) { - shadowSelectionView.show(); - localSelectionView.hide(); - if(localCaret) { - localCaret.hide() - } - } - } - } - function onCursorRemoved(memberid) { - selectionViewManager.removeSelectionView(memberid) - } - 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.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(); - avatarInfoStyles.parentNode.removeChild(avatarInfoStyles); - (function destroyEditInfo(i, err) { - if(err) { - callback(err) - }else { - if(i < editInfoArray.length) { - editInfoArray[i].destroy(function(err) { - destroyEditInfo(i + 1, err) - }) - }else { - callback() - } - } - })(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); - 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"); - avatarInfoStyles.type = "text/css"; - avatarInfoStyles.media = "screen, print, handheld, projection"; - avatarInfoStyles.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);")); - avatarInfoStyles.appendChild(document.createTextNode("@namespace dc url(http://purl.org/dc/elements/1.1/);")); - head.appendChild(avatarInfoStyles) - } - init() - } - return SessionView -}(); -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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("gui.Caret"); -gui.CaretManager = function CaretManager(sessionController) { - var carets = {}, window = runtime.getWindow(), scrollIntoViewScheduled = false; - function getCaret(memberId) { - return carets.hasOwnProperty(memberId) ? carets[memberId] : null - } - function getCarets() { - return Object.keys(carets).map(function(memberid) { - return carets[memberid] - }) - } - function getCanvasElement() { - return sessionController.getSession().getOdtDocument().getOdfCanvas().getElement() - } - function removeCaret(memberId) { - if(memberId === sessionController.getInputMemberId()) { - getCanvasElement().removeAttribute("tabindex") - } - delete carets[memberId] - } - function refreshLocalCaretBlinking(cursor) { - var caret, memberId = cursor.getMemberId(); - if(memberId === sessionController.getInputMemberId()) { - caret = getCaret(memberId); - if(caret) { - caret.refreshCursorBlinking() - } - } - } - function executeEnsureCaretVisible() { - var caret = getCaret(sessionController.getInputMemberId()); - scrollIntoViewScheduled = false; - if(caret) { - caret.ensureVisible() - } - } - function scheduleCaretVisibilityCheck() { - var caret = getCaret(sessionController.getInputMemberId()); - if(caret) { - caret.handleUpdate(); - if(!scrollIntoViewScheduled) { - scrollIntoViewScheduled = true; - runtime.setTimeout(executeEnsureCaretVisible, 50) - } - } - } - function ensureLocalCaretVisible(info) { - if(info.memberId === sessionController.getInputMemberId()) { - scheduleCaretVisibilityCheck() - } - } - function focusLocalCaret() { - var caret = getCaret(sessionController.getInputMemberId()); - if(caret) { - caret.setFocus() - } - } - function blurLocalCaret() { - var caret = getCaret(sessionController.getInputMemberId()); - if(caret) { - caret.removeFocus() - } - } - function showLocalCaret() { - var caret = getCaret(sessionController.getInputMemberId()); - if(caret) { - caret.show() - } - } - function hideLocalCaret() { - var caret = getCaret(sessionController.getInputMemberId()); - if(caret) { - caret.hide() - } - } - this.registerCursor = function(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect) { - var memberid = cursor.getMemberId(), caret = new gui.Caret(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect); - 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() - }else { - cursor.handleUpdate = caret.handleUpdate - } - return caret - }; - this.getCaret = getCaret; - this.getCarets = getCarets; - this.destroy = function(callback) { - var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager(), caretArray = getCarets(); - odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible); - odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking); - odtDocument.unsubscribe(ops.OdtDocument.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 = {} - }; - 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); - eventManager.subscribe("focus", focusLocalCaret); - eventManager.subscribe("blur", blurLocalCaret); - window.addEventListener("focus", showLocalCaret, false); - window.addEventListener("blur", hideLocalCaret, false) - } - init() -}; /* Copyright (C) 2013 KO GmbH @@ -16821,320 +15583,24 @@ gui.CaretManager = function CaretManager(sessionController) { @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 - - @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 . - - 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 +gui.PlainTextPasteboard = function PlainTextPasteboard(odtDocument, inputMemberId) { + function createOp(op, data) { + op.init(data); + return op } - 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) 2013 KO GmbH - - @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 . - - 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("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 + 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})); + cursorPosition += 1; + operations.push(createOp(new ops.OpInsertText, {memberid:inputMemberId, position:cursorPosition, text:text})); + cursorPosition += text.length }); - 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() - } - 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() - }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() - } - return moved + operations.push(createOp(new ops.OpRemoveText, {memberid:inputMemberId, position:originalCursorPosition, length:1})); + return operations } }; -gui.TrivialUndoManager.signalDocumentRootReplaced = "documentRootReplaced"; -(function() { - return gui.TrivialUndoManager -})(); runtime.loadClass("core.DomUtils"); runtime.loadClass("odf.OdfUtils"); runtime.loadClass("odf.OdfNodeFilter"); @@ -17145,7 +15611,7 @@ gui.SelectionView = function SelectionView(cursor) { var newDocumentRoot = odtDocument.getRootNode(); if(documentRoot !== newDocumentRoot) { documentRoot = newDocumentRoot; - root = documentRoot.parentNode.parentNode.parentNode; + root = (documentRoot.parentNode.parentNode.parentNode); root.appendChild(overlayTop); root.appendChild(overlayMiddle); root.appendChild(overlayBottom) @@ -17263,7 +15729,7 @@ gui.SelectionView = function SelectionView(cursor) { 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; + 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) { @@ -17535,7 +16001,7 @@ gui.SelectionViewManager = function SelectionViewManager() { }; /* - Copyright (C) 2012-2013 KO GmbH + Copyright (C) 2013 KO GmbH @licstart The JavaScript code in this page is free software: you can redistribute it @@ -17570,353 +16036,166 @@ gui.SelectionViewManager = function SelectionViewManager() { @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; - function getRootNode() { - var element = odfCanvas.odfContainer().getContentElement(), localName = element && element.localName; - runtime.assert(localName === "text", "Unsupported content element type '" + localName + "' for OdtDocument"); - return element +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 getDOM() { - return(getRootNode().ownerDocument) + function mostRecentUndoState() { + return undoStates[undoStates.length - 1] } - this.getDOM = getDOM; - function isRoot(node) { - if(node.namespaceURI === odf.Namespaces.officens && node.localName === "text" || node.namespaceURI === odf.Namespaces.officens && node.localName === "annotation") { - return true - } - return false - } - function getRoot(node) { - while(node && !isRoot(node)) { - node = (node.parentNode) - } - return node - } - this.getRootElement = getRoot; - function RootFilter(anchor) { - this.acceptPosition = function(iterator) { - var node = iterator.container(), anchorNode; - if(typeof anchor === "string") { - anchorNode = cursors[anchor].getNode() - }else { - anchorNode = anchor - } - if(getRoot(node) === getRoot(anchorNode)) { - return FILTER_ACCEPT - } - return FILTER_REJECT + function completeCurrentUndoState() { + if(currentUndoState !== initialState && currentUndoState !== mostRecentUndoState()) { + undoStates.push(currentUndoState) } } - function getIteratorAtPosition(position) { - var iterator = gui.SelectionMover.createPositionIterator(getRootNode()), point = stepsTranslator.convertStepsToDomPoint(position); - iterator.setUnfilteredPosition(point.node, point.offset); - return iterator + function removeNode(node) { + var sibling = node.previousSibling || node.nextSibling; + node.parentNode.removeChild(node); + domUtils.normalizeTextNodes(sibling) } - this.getIteratorAtPosition = getIteratorAtPosition; - this.convertDomPointToCursorStep = function(node, offset) { - return stepsTranslator.convertDomPointToSteps(node, offset) - }; - this.convertDomToCursorRange = function(anchorNode, anchorOffset, focusNode, focusOffset) { - var point1, point2; - point1 = stepsTranslator.convertDomPointToSteps(anchorNode, anchorOffset); - if(anchorNode === focusNode && anchorOffset === focusOffset) { - point2 = point1 - }else { - point2 = stepsTranslator.convertDomPointToSteps(focusNode, focusOffset) - } - return{position:point1, length:point2 - point1} - }; - this.convertCursorToDomRange = function(position, length) { - var range = getDOM().createRange(), point1, point2; - point1 = stepsTranslator.convertStepsToDomPoint(position); - if(length) { - point2 = stepsTranslator.convertStepsToDomPoint(position + length); - if(length > 0) { - range.setStart(point1.node, point1.offset); - range.setEnd(point2.node, point2.offset) - }else { - range.setStart(point2.node, point2.offset); - range.setEnd(point1.node, point1.offset) - } - }else { - range.setStart(point1.node, point1.offset) - } - return range - }; - function getTextNodeAtStep(steps, memberid) { - var iterator = getIteratorAtPosition(steps), node = iterator.container(), lastTextNode, nodeOffset = 0, cursorNode = null; - if(node.nodeType === Node.TEXT_NODE) { - lastTextNode = (node); - nodeOffset = iterator.unfilteredDomOffset() - }else { - lastTextNode = getDOM().createTextNode(""); - nodeOffset = 0; - node.insertBefore(lastTextNode, iterator.rightNode()) - } - if(memberid && (cursors[memberid] && self.getCursorPosition(memberid) === steps)) { - cursorNode = cursors[memberid].getNode(); - while(cursorNode.nextSibling && cursorNode.nextSibling.localName === "cursor") { - cursorNode.parentNode.insertBefore(cursorNode.nextSibling, cursorNode) - } - if(lastTextNode.length > 0 && lastTextNode.nextSibling !== cursorNode) { - lastTextNode = getDOM().createTextNode(""); - nodeOffset = 0 - } - cursorNode.parentNode.insertBefore(lastTextNode, cursorNode) - } - while(lastTextNode.previousSibling && lastTextNode.previousSibling.nodeType === Node.TEXT_NODE) { - lastTextNode.previousSibling.appendData(lastTextNode.data); - nodeOffset = lastTextNode.previousSibling.length; - lastTextNode = (lastTextNode.previousSibling); - lastTextNode.parentNode.removeChild(lastTextNode.nextSibling) - } - return{textNode:lastTextNode, offset:nodeOffset} + function removeCursors(root) { + domUtils.getElementsByTagNameNS(root, cursorns, "cursor").forEach(removeNode); + domUtils.getElementsByTagNameNS(root, cursorns, "anchor").forEach(removeNode) } - function getParagraphElement(node) { - return odfUtils.getParagraphElement(node) - } - function getStyleElement(styleName, styleFamily) { - return odfCanvas.getFormatting().getStyleElement(styleName, styleFamily) - } - this.getStyleElement = getStyleElement; - function getParagraphStyleElement(styleName) { - return getStyleElement(styleName, "paragraph") - } - function getParagraphStyleAttributes(styleName) { - var node = getParagraphStyleElement(styleName); - if(node) { - return odfCanvas.getFormatting().getInheritedStyleAttributes(node) - } - return null - } - function handleOperationExecuted(op) { - var spec = op.spec(), memberId = spec.memberid, date = (new Date(spec.timestamp)).toISOString(), metadataManager = odfCanvas.odfContainer().getMetadataManager(), fullName; - if(op.isEdit) { - fullName = self.getMember(memberId).getProperties().fullName; - metadataManager.setMetadata({"dc:creator":fullName, "dc:date":date}, null); - if(!lastEditingOp) { - metadataManager.incrementEditingCycles(); - if(!unsupportedMetadataRemoved) { - metadataManager.setMetadata(null, ["meta:editing-duration", "meta:document-statistic"]) - } - } - lastEditingOp = op - } - } - 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"); - space.appendChild(textNode.ownerDocument.createTextNode(" ")); - textNode.deleteData(offset, 1); - if(offset > 0) { - textNode = (textNode.splitText(offset)) - } - textNode.parentNode.insertBefore(space, textNode); - return space - } - function upgradeWhitespacesAtPosition(position) { - var iterator = getIteratorAtPosition(position), container, offset, i; - iterator.previousPosition(); - iterator.previousPosition(); - 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))) { - container = upgradeWhitespaceToElement((container), offset); - iterator.moveToEndOfNode(container) - } - iterator.nextPosition() - } - } - this.upgradeWhitespacesAtPosition = upgradeWhitespacesAtPosition; - this.downgradeWhitespacesAtPosition = function(position) { - var iterator = getIteratorAtPosition(position), container, offset, firstSpaceElementChild, lastSpaceElementChild; - container = iterator.container(); - offset = iterator.unfilteredDomOffset(); - while(!odfUtils.isCharacterElement(container) && container.childNodes[offset]) { - container = container.childNodes[offset]; - offset = 0 - } - if(container.nodeType === Node.TEXT_NODE) { - container = container.parentNode - } - if(odfUtils.isDowngradableSpaceElement(container)) { - firstSpaceElementChild = container.firstChild; - lastSpaceElementChild = container.lastChild; - domUtils.mergeIntoParent(container); - if(lastSpaceElementChild !== firstSpaceElementChild) { - domUtils.normalizeTextNodes(lastSpaceElementChild) - } - domUtils.normalizeTextNodes(firstSpaceElementChild) - } - }; - this.getParagraphStyleElement = getParagraphStyleElement; - this.getParagraphElement = getParagraphElement; - this.getParagraphStyleAttributes = getParagraphStyleAttributes; - this.getTextNodeAtStep = getTextNodeAtStep; - 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)) { - 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) - } - }else { - if(stepsSelectionLength === 0) { - cursorMoved = true; - cursor.move(0) - } - } - if(cursorMoved) { - self.emit(ops.OdtDocument.signalCursorMoved, cursor) - } - rootConstrainedFilter.removeFilter("RootFilter") + function values(obj) { + return Object.keys(obj).map(function(key) { + return obj[key] }) - }; - 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 - }; - this.getCursorSelection = function(memberid) { - var cursor = cursors[memberid], focusPosition = 0, anchorPosition = 0; - if(cursor) { - focusPosition = stepsTranslator.convertDomPointToSteps(cursor.getNode(), 0); - anchorPosition = stepsTranslator.convertDomPointToSteps(cursor.getAnchorNode(), 0) - } - return{position:anchorPosition, length:focusPosition - anchorPosition} - }; - this.getPositionFilter = function() { - return filter - }; - this.getOdfCanvas = function() { - return odfCanvas - }; - this.getRootNode = getRootNode; - this.addMember = function(member) { - runtime.assert(members[member.getMemberId()] === undefined, "This member already exists"); - members[member.getMemberId()] = member - }; - this.getMember = function(memberId) { - return members.hasOwnProperty(memberId) ? members[memberId] : null - }; - this.removeMember = function(memberId) { - delete members[memberId] - }; - this.getCursor = function(memberid) { - return cursors[memberid] - }; - this.getCursors = function() { - var list = [], i; - for(i in cursors) { - if(cursors.hasOwnProperty(i)) { - list.push(cursors[i]) + } + 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 } } - return list - }; - this.addCursor = function(cursor) { - runtime.assert(Boolean(cursor), "OdtDocument::addCursor without cursor"); - var distanceToFirstTextNode = cursor.getStepCounter().countSteps(1, filter), memberid = cursor.getMemberId(); - 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); - cursors[memberid] = cursor - }; - this.removeCursor = function(memberid) { - var cursor = cursors[memberid]; - if(cursor) { - cursor.removeFromOdtDocument(); - delete cursors[memberid]; - self.emit(ops.OdtDocument.signalCursorRemoved, memberid); - return true + while(operations && remainingAddOps > 0) { + operations.reverse(); + operations.forEach(processOp); + operations = undoStates.pop() } - return false - }; - this.getFormatting = function() { - return odfCanvas.getFormatting() - }; - this.emit = function(eventid, args) { - eventNotifier.emit(eventid, args) - }; - this.subscribe = function(eventid, cb) { - eventNotifier.subscribe(eventid, cb) - }; - this.unsubscribe = function(eventid, cb) { - eventNotifier.unsubscribe(eventid, cb) - }; - this.createRootFilter = function(inputMemberId) { - return new RootFilter(inputMemberId) - }; - this.close = function(callback) { - callback() - }; - this.destroy = function(callback) { - callback() - }; - function init() { - filter = new ops.TextPositionFilter(getRootNode); - odfUtils = new odf.OdfUtils; - domUtils = new core.DomUtils; - 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) + 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() + } + 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() + }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() + } + return moved } - 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.signalUndoStackChanged = "undo/changed"; -ops.OdtDocument.signalStepsInserted = "steps/inserted"; -ops.OdtDocument.signalStepsRemoved = "steps/removed"; +gui.TrivialUndoManager.signalDocumentRootReplaced = "documentRootReplaced"; (function() { - return ops.OdtDocument + return gui.TrivialUndoManager })(); /* @@ -17969,8 +16248,11 @@ ops.Session = function Session(odfCanvas) { this.setOperationRouter = function(opRouter) { operationRouter = opRouter; opRouter.setPlaybackFunction(function(op) { - op.execute(odtDocument); - odtDocument.emit(ops.OdtDocument.signalOperationExecuted, op) + if(op.execute(odtDocument)) { + odtDocument.emit(ops.OdtDocument.signalOperationExecuted, op); + return true + } + return false }); opRouter.setOperationFactory(operationFactory) }; @@ -18000,6 +16282,1883 @@ ops.Session = function Session(odfCanvas) { } init() }; -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"; -var webodf_version = "0.4.2-1451-gc9cf878"; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + @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() + } + } + function onCursorRemoved(memberId) { + if(memberId === inputMemberId) { + updatedCachedValues() + } + } + function onCursorMoved(cursor) { + if(cursor.getMemberId() === inputMemberId) { + updatedCachedValues() + } + } + 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() + }; + function init() { + odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded); + odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved); + odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved); + updatedCachedValues() + } + init() +}; +gui.AnnotationController.annotatableChanged = "annotatable/changed"; +(function() { + return gui.AnnotationController +})(); +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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("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 + } + 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) + } + } + function onCursorAdded(cursor) { + if(cursor.getMemberId() === inputMemberId) { + updatedCachedValues() + } + } + function onCursorRemoved(memberId) { + if(memberId === inputMemberId) { + updatedCachedValues() + } + } + function onCursorMoved(cursor) { + if(cursor.getMemberId() === inputMemberId) { + updatedCachedValues() + } + } + function onParagraphStyleModified() { + updatedCachedValues() + } + function onParagraphChanged(args) { + var cursor = odtDocument.getCursor(inputMemberId); + if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) { + updatedCachedValues() + } + } + this.isAlignedLeft = function() { + return isAlignedLeftValue + }; + this.isAlignedCenter = function() { + return isAlignedCenterValue + }; + this.isAlignedRight = function() { + return isAlignedRightValue + }; + this.isAlignedJustified = function() { + return isAlignedJustifiedValue + }; + function roundUp(step) { + return step === ops.StepsTranslator.NEXT_STEP + } + function applyParagraphDirectStyling(applyDirectStyling) { + var range = odtDocument.getCursor(inputMemberId).getSelectedRange(), paragraphs = odfUtils.getParagraphElements(range), formatting = odtDocument.getFormatting(); + 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; + if(paragraphStyleName) { + paragraphProperties = formatting.createDerivedStyleObject(paragraphStyleName, "paragraph", {}) + } + 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]) + }) + } + function applySimpleParagraphDirectStyling(styleOverrides) { + applyParagraphDirectStyling(function(paragraphStyle) { + return utils.mergeObjects(paragraphStyle, styleOverrides) + }) + } + function alignParagraph(alignment) { + applySimpleParagraphDirectStyling({"style:paragraph-properties":{"fo:text-align":alignment}}) + } + this.alignParagraphLeft = function() { + alignParagraph("left"); + return true + }; + this.alignParagraphCenter = function() { + alignParagraph("center"); + return true + }; + this.alignParagraphRight = function() { + alignParagraph("right"); + return true + }; + this.alignParagraphJustified = function() { + alignParagraph("justify"); + 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; + if(indent && indent.unit === tabStopDistance.unit) { + newIndent = indent.value + direction * tabStopDistance.value + indent.unit + }else { + newIndent = direction * tabStopDistance.value + tabStopDistance.unit + } + return utils.mergeObjects(paragraphStyle, {"style:paragraph-properties":{"fo:margin-left":newIndent}}) + } + this.indent = function() { + applyParagraphDirectStyling(modifyParagraphIndent.bind(null, 1)); + return true + }; + this.outdent = function() { + applyParagraphDirectStyling(modifyParagraphIndent.bind(null, -1)); + return true + }; + 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); + odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified); + odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged); + 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); + updatedCachedValues() + } + init() +}; +gui.DirectParagraphStyler.paragraphStylingChanged = "paragraphStyling/changed"; +(function() { + return gui.DirectParagraphStyler +})(); +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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)) + } + return selectionStyles + } + function updatedCachedValues() { + var fontSize, diffMap; + currentSelectionStyles = getAppliedStyles(); + function noteChange(oldValue, newValue, id) { + if(oldValue !== newValue) { + if(diffMap === undefined) { + diffMap = {} + } + diffMap[id] = newValue + } + 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) + } + } + function onCursorAdded(cursor) { + if(cursor.getMemberId() === inputMemberId) { + updatedCachedValues() + } + } + function onCursorRemoved(memberId) { + if(memberId === inputMemberId) { + updatedCachedValues() + } + } + function onCursorMoved(cursor) { + if(cursor.getMemberId() === inputMemberId) { + updatedCachedValues() + } + } + function onParagraphStyleModified() { + updatedCachedValues() + } + function onParagraphChanged(args) { + var cursor = odtDocument.getCursor(inputMemberId); + if(cursor && odtDocument.getParagraphElement(cursor.getNode()) === args.paragraphElement) { + updatedCachedValues() + } + } + function toggle(predicate, toggleMethod) { + var cursor = odtDocument.getCursor(inputMemberId), appliedStyles; + if(!cursor) { + return false + } + appliedStyles = styleHelper.getAppliedStyles(cursor.getSelectedRange()); + toggleMethod(!predicate(appliedStyles)); + 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); + updatedCachedValues() + } + } + this.formatTextSelection = formatTextSelection; + function applyTextPropertyToSelection(propertyName, propertyValue) { + var textProperties = {}; + textProperties[propertyName] = propertyValue; + formatTextSelection(textProperties) + } + 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() + } + return styleOp + }; + function clearCursorStyle(op) { + var spec = op.spec(); + if(directCursorStyleProperties && spec.memberid === inputMemberId) { + if(spec.optype !== "SplitParagraph") { + directCursorStyleProperties = null; + updatedCachedValues() + } + } + } + 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 currentSelectionStyles + }; + 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.hasUnderline = function() { + return hasUnderlineValue + }; + this.hasStrikeThrough = function() { + return hasStrikeThroughValue + }; + this.fontSize = function() { + return fontSizeValue + }; + this.fontName = function() { + return fontNameValue + }; + 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); + odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified); + odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged); + odtDocument.unsubscribe(ops.OdtDocument.signalOperationExecuted, clearCursorStyle); + 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() + } + 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) { + 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; + op.init({memberid:inputMemberId, styleName:name, styleFamily:"graphic", isAutomaticStyle:false, 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"}}}); + return op + } + function createAddFrameStyleOp(styleName, parentStyleName) { + var op = new ops.OpAddStyle; + op.init({memberid:inputMemberId, styleName:styleName, styleFamily:"graphic", isAutomaticStyle:true, setProperties:{"style:parent-style-name":parentStyleName, "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"}}}); + return op + } + function getFileExtension(mimetype) { + mimetype = mimetype.toLowerCase(); + return fileExtensionByMimetype.hasOwnProperty(mimetype) ? fileExtensionByMimetype[mimetype] : null + } + function insertImageInternal(mimetype, content, widthInCm, heightInCm) { + var graphicsStyleName = "Graphics", stylesElement = odtDocument.getOdfCanvas().odfContainer().rootElement.styles, fileExtension = getFileExtension(mimetype), fileName, graphicsStyleElement, frameStyleName, op, operations = []; + runtime.assert(fileExtension !== null, "Image type is not supported: " + mimetype); + fileName = "Pictures/" + objectNameGenerator.generateImageName() + fileExtension; + op = new ops.OpSetBlob; + op.init({memberid:inputMemberId, filename:fileName, mimetype:mimetype, content:content}); + operations.push(op); + graphicsStyleElement = formatting.getStyleElement(graphicsStyleName, "graphic", [stylesElement]); + if(!graphicsStyleElement) { + op = createAddGraphicsStyleOp(graphicsStyleName); + operations.push(op) + } + frameStyleName = objectNameGenerator.generateStyleName(); + op = createAddFrameStyleOp(frameStyleName, graphicsStyleName); + operations.push(op); + op = new ops.OpInsertImage; + op.init({memberid:inputMemberId, position:odtDocument.getCursorPosition(inputMemberId), filename:fileName, frameWidth:widthInCm + "cm", frameHeight:heightInCm + "cm", frameStyleName:frameStyleName, frameName:objectNameGenerator.generateFrameName()}); + operations.push(op); + session.enqueue(operations) + } + function trimmedSize(originalSize, pageContentSize) { + var widthRatio = 1, heightRatio = 1, ratio; + if(originalSize.width > pageContentSize.width) { + widthRatio = pageContentSize.width / originalSize.width + } + if(originalSize.height > pageContentSize.height) { + heightRatio = pageContentSize.height / originalSize.height + } + ratio = Math.min(widthRatio, heightRatio); + return{width:originalSize.width * ratio, height:originalSize.height * ratio} + } + this.insertImage = function(mimetype, content, widthInPx, heightInPx) { + var paragraphElement, styleName, pageContentSize, originalSize, newSize; + runtime.assert(widthInPx > 0 && heightInPx > 0, "Both width and height of the image should be greater than 0px."); + paragraphElement = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()); + styleName = paragraphElement.getAttributeNS(textns, "style-name"); + if(!paragraphStyleToPageContentSizeMap.hasOwnProperty(styleName)) { + paragraphStyleToPageContentSizeMap[styleName] = formatting.getContentSize(styleName, "paragraph") + } + pageContentSize = paragraphStyleToPageContentSizeMap[styleName]; + originalSize = {width:widthInPx * cmPerPixel, height:heightInPx * cmPerPixel}; + newSize = trimmedSize(originalSize, pageContentSize); + insertImageInternal(mimetype, content, newSize.width, newSize.height) + } +}; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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"); +gui.TextManipulator = function TextManipulator(session, inputMemberId, directStyleOp) { + var odtDocument = session.getOdtDocument(), FILTER_ACCEPT = core.PositionFilter.FilterResult.FILTER_ACCEPT; + function createOpRemoveSelection(selection) { + var op = new ops.OpRemoveText; + op.init({memberid:inputMemberId, position:selection.position, length:selection.length}); + return op + } + function toForwardSelection(selection) { + if(selection.length < 0) { + selection.position += selection.length; + selection.length = -selection.length + } + return selection + } + this.enqueueParagraphSplittingOps = function() { + var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, operations = []; + if(selection.length > 0) { + op = createOpRemoveSelection(selection); + operations.push(op) + } + op = new ops.OpSplitParagraph; + op.init({memberid:inputMemberId, position:selection.position}); + operations.push(op); + 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)); + iterator.setUnfilteredPosition(cursorNode, 0); + while(nextPosition()) { + if(rootConstrainedFilter.acceptPosition(iterator) === FILTER_ACCEPT) { + return true + } + } + return false + } + this.removeTextByBackspaceKey = function() { + var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null; + if(selection.length === 0) { + if(hasPositionInDirection(cursor.getNode(), false)) { + op = new ops.OpRemoveText; + op.init({memberid:inputMemberId, position:selection.position - 1, length:1}); + session.enqueue([op]) + } + }else { + op = createOpRemoveSelection(selection); + session.enqueue([op]) + } + return op !== null + }; + this.removeTextByDeleteKey = function() { + var cursor = odtDocument.getCursor(inputMemberId), selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op = null; + if(selection.length === 0) { + if(hasPositionInDirection(cursor.getNode(), true)) { + op = new ops.OpRemoveText; + op.init({memberid:inputMemberId, position:selection.position, length:1}); + session.enqueue([op]) + } + }else { + op = createOpRemoveSelection(selection); + session.enqueue([op]) + } + return op !== null + }; + this.removeCurrentSelection = function() { + var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op; + if(selection.length !== 0) { + op = createOpRemoveSelection(selection); + session.enqueue([op]) + } + return true + }; + function insertText(text) { + var selection = toForwardSelection(odtDocument.getCursorSelection(inputMemberId)), op, stylingOp, operations = []; + if(selection.length > 0) { + op = createOpRemoveSelection(selection); + operations.push(op) + } + op = new ops.OpInsertText; + op.init({memberid:inputMemberId, position:selection.position, text:text}); + operations.push(op); + if(directStyleOp) { + stylingOp = directStyleOp(selection.position, text.length); + if(stylingOp) { + operations.push(stylingOp) + } + } + session.enqueue(operations) + } + this.insertText = insertText +}; +(function() { + return gui.TextManipulator +})(); +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 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, suppressFocusEvent = false, redrawRegionSelectionTask, pasteHandler = new gui.PlainTextPasteboard(odtDocument, inputMemberId), clickCount = 0; + 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 + } + function cancelEvent(event) { + if(event.preventDefault) { + event.preventDefault() + }else { + 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; + if(doc.caretRangeFromPoint) { + c = doc.caretRangeFromPoint(x, y); + result = {container:c.startContainer, offset:c.startOffset} + }else { + if(doc.caretPositionFromPoint) { + c = doc.caretPositionFromPoint(x, y); + if(c && c.offsetNode) { + result = {container:c.offsetNode, offset:c.offset} + } + } + } + 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]) + } + eventManager.focus() + } + 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 maintainCursorSelection() { + var cursor = odtDocument.getCursor(inputMemberId), selection = window.getSelection(), imageElement, range; + if(cursor) { + imageSelector.clearSelection(); + if(cursor.getSelectionType() === ops.OdtCursor.RegionSelection) { + range = cursor.getSelectedRange(); + imageElement = odfUtils.getImageElements(range)[0]; + if(imageElement) { + imageSelector.select((imageElement.parentNode)) + } + } + if(eventManager.hasFocus()) { + range = cursor.getSelectedRange(); + if(selection.extend) { + if(cursor.hasForwardSelection()) { + selection.collapse(range.startContainer, range.startOffset); + selection.extend(range.endContainer, range.endOffset) + }else { + selection.collapse(range.endContainer, range.endOffset); + selection.extend(range.startContainer, range.startOffset) + } + }else { + suppressFocusEvent = true; + selection.removeAllRanges(); + selection.addRange(range.cloneRange()); + (odtDocument.getOdfCanvas().getElement()).setActive(); + runtime.setTimeout(function() { + suppressFocusEvent = false + }, 0) + } + } + }else { + imageSelector.clearSelection() + } + } + function delayedMaintainCursor() { + if(suppressFocusEvent === false) { + runtime.setTimeout(maintainCursorSelection, 0) + } + } + function stringFromKeyPress(event) { + if(event.which === null || event.which === undefined) { + return String.fromCharCode(event.keyCode) + } + if(event.which !== 0 && event.charCode !== 0) { + return String.fromCharCode(event.which) + } + return null + } + function handleCut(e) { + var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange(); + if(selectedRange.collapsed) { + return + } + if(clipboard.setDataFromRange(e, selectedRange)) { + textManipulator.removeCurrentSelection() + }else { + runtime.log("Cut operation failed") + } + } + function handleBeforeCut() { + var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange(); + return selectedRange.collapsed !== false + } + function handleCopy(e) { + var cursor = odtDocument.getCursor(inputMemberId), selectedRange = cursor.getSelectedRange(); + if(selectedRange.collapsed) { + return + } + if(!clipboard.setDataFromRange(e, selectedRange)) { + runtime.log("Cut operation failed") + } + } + function handlePaste(e) { + var plainText; + if(window.clipboardData && window.clipboardData.getData) { + plainText = window.clipboardData.getData("Text") + }else { + if(e.clipboardData && e.clipboardData.getData) { + plainText = e.clipboardData.getData("text/plain") + } + } + if(plainText) { + textManipulator.removeCurrentSelection(); + session.enqueue(pasteHandler.createPasteOps(plainText)); + cancelEvent(e) + } + } + function handleBeforePaste() { + return false + } + function updateUndoStack(op) { + if(undoManager) { + undoManager.onOperationExecuted(op) + } + } + function forwardUndoStackChange(e) { + odtDocument.emit(ops.OdtDocument.signalUndoStackChanged, e) + } + function undo() { + if(undoManager) { + undoManager.moveBackward(1); + redrawRegionSelectionTask.trigger(); + return true + } + return false + } + function redo() { + if(undoManager) { + undoManager.moveForward(1); + redrawRegionSelectionTask.trigger(); + return true + } + return false + } + function updateShadowCursor() { + var selection = window.getSelection(), selectionRange = selection.rangeCount > 0 && selectionToRange(selection); + if(clickStartedWithinContainer && selectionRange) { + isMouseMoved = true; + imageSelector.clearSelection(); + shadowCursorIterator.setUnfilteredPosition((selection.focusNode), selection.focusOffset); + if(mouseDownRootFilter.acceptPosition(shadowCursorIterator) === FILTER_ACCEPT) { + if(clickCount === 2) { + expandToWordBoundaries(selectionRange.range) + }else { + if(clickCount >= 3) { + expandToParagraphBoundaries(selectionRange.range) + } + } + shadowCursor.setSelectedRange(selectionRange.range, selectionRange.hasForwardSelection); + odtDocument.emit(ops.OdtDocument.signalCursorMoved, shadowCursor) + } + } + } + function handleMouseDown(e) { + var target = getTarget(e), cursor = odtDocument.getCursor(inputMemberId); + clickStartedWithinContainer = target && domUtils.containsNode(odtDocument.getOdfCanvas().getElement(), target); + if(clickStartedWithinContainer) { + isMouseMoved = false; + mouseDownRootFilter = odtDocument.createRootFilter(target); + clickCount = e.detail; + if(cursor && e.shiftKey) { + window.getSelection().collapse(cursor.getAnchorNode(), 0) + } + if(clickCount > 1) { + updateShadowCursor() + } + } + } + function mutableSelection(selection) { + if(selection) { + return{anchorNode:selection.anchorNode, anchorOffset:selection.anchorOffset, focusNode:selection.focusNode, focusOffset:selection.focusOffset} + } + return null + } + function handleMouseClickEvent(event) { + var target = getTarget(event), eventDetails = {detail:event.detail, clientX:event.clientX, clientY:event.clientY, target:target}; + drawShadowCursorTask.processRequests(); + if(odfUtils.isImage(target) && odfUtils.isCharacterFrame(target.parentNode)) { + selectImage(target.parentNode) + }else { + if(clickStartedWithinContainer && !imageSelector.isSelectorElement(target)) { + if(isMouseMoved) { + selectRange(shadowCursor.getSelectedRange(), shadowCursor.hasForwardSelection(), event.detail) + }else { + runtime.setTimeout(function() { + var selection = mutableSelection(window.getSelection()), selectionRange, caretPos; + if(!selection.anchorNode && !selection.focusNode) { + caretPos = caretPositionFromPoint(eventDetails.clientX, eventDetails.clientY); + if(!caretPos) { + return + } + selection.anchorNode = (caretPos.container); + selection.anchorOffset = caretPos.offset; + selection.focusNode = selection.anchorNode; + selection.focusOffset = selection.anchorOffset + } + selectionRange = selectionToRange(selection); + selectRange(selectionRange.range, selectionRange.hasForwardSelection, eventDetails.detail) + }, 0) + } + } + } + clickCount = 0; + clickStartedWithinContainer = false; + isMouseMoved = false + } + function handleContextMenu(e) { + handleMouseClickEvent(e) + } + function handleMouseUp(event) { + var target = getTarget(event), annotationNode = null; + if(target.className === "annotationRemoveButton") { + annotationNode = domUtils.getElementsByTagNameNS(target.parentNode, odf.Namespaces.officens, "annotation")[0]; + annotationController.removeAnnotation(annotationNode) + }else { + handleMouseClickEvent(event) + } + } + 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); + 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("focus", delayedMaintainCursor); + odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, redrawRegionSelectionTask.trigger); + odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack); + op = new ops.OpAddCursor; + op.init({memberid:inputMemberId}); + session.enqueue([op]); + if(undoManager) { + undoManager.saveInitialState() + } + }; + 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); + 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("focus", delayedMaintainCursor); + odtDocument.getOdfCanvas().getElement().classList.remove("virtualSelections") + }; + this.getInputMemberId = function() { + return inputMemberId + }; + this.getSession = function() { + return session + }; + this.setUndoManager = function(manager) { + if(undoManager) { + undoManager.unsubscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange) + } + undoManager = manager; + if(undoManager) { + undoManager.setOdtDocument(odtDocument); + undoManager.setPlaybackFunction(function(op) { + op.execute(odtDocument) + }); + undoManager.subscribe(gui.UndoManager.signalUndoStackChanged, forwardUndoStackChange) + } + }; + this.getUndoManager = function() { + return undoManager + }; + this.getAnnotationController = function() { + return annotationController + }; + this.getDirectTextStyler = function() { + return directTextStyler + }; + this.getDirectParagraphStyler = function() { + return directParagraphStyler + }; + this.getImageManager = function() { + return imageManager + }; + this.getTextManipulator = function() { + return textManipulator + }; + this.getEventManager = function() { + return eventManager + }; + this.getKeyboardHandlers = function() { + return{keydown:keyDownHandler, keypress:keyPressHandler} + }; + this.destroy = function(callback) { + var destroyCallbacks = [drawShadowCursorTask.destroy, directTextStyler.destroy]; + if(directParagraphStyler) { + destroyCallbacks.push(directParagraphStyler.destroy) + } + 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(maintainCursorSelection, 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)); + 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) + }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) + } + 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)) + } + init() + }; + return gui.SessionController +}(); +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("gui.Caret"); +gui.CaretManager = function CaretManager(sessionController) { + var carets = {}, window = runtime.getWindow(), scrollIntoViewScheduled = false; + function getCaret(memberId) { + return carets.hasOwnProperty(memberId) ? carets[memberId] : null + } + function getCarets() { + return Object.keys(carets).map(function(memberid) { + return carets[memberid] + }) + } + function getCanvasElement() { + return sessionController.getSession().getOdtDocument().getOdfCanvas().getElement() + } + function removeCaret(memberId) { + if(memberId === sessionController.getInputMemberId()) { + getCanvasElement().removeAttribute("tabindex") + } + delete carets[memberId] + } + function refreshLocalCaretBlinking(cursor) { + var caret, memberId = cursor.getMemberId(); + if(memberId === sessionController.getInputMemberId()) { + caret = getCaret(memberId); + if(caret) { + caret.refreshCursorBlinking() + } + } + } + function executeEnsureCaretVisible() { + var caret = getCaret(sessionController.getInputMemberId()); + scrollIntoViewScheduled = false; + if(caret) { + caret.ensureVisible() + } + } + function scheduleCaretVisibilityCheck() { + var caret = getCaret(sessionController.getInputMemberId()); + if(caret) { + caret.handleUpdate(); + if(!scrollIntoViewScheduled) { + scrollIntoViewScheduled = true; + runtime.setTimeout(executeEnsureCaretVisible, 50) + } + } + } + function ensureLocalCaretVisible(info) { + if(info.memberId === sessionController.getInputMemberId()) { + scheduleCaretVisibilityCheck() + } + } + function focusLocalCaret() { + var caret = getCaret(sessionController.getInputMemberId()); + if(caret) { + caret.setFocus() + } + } + function blurLocalCaret() { + var caret = getCaret(sessionController.getInputMemberId()); + if(caret) { + caret.removeFocus() + } + } + function showLocalCaret() { + var caret = getCaret(sessionController.getInputMemberId()); + if(caret) { + caret.show() + } + } + function hideLocalCaret() { + var caret = getCaret(sessionController.getInputMemberId()); + if(caret) { + caret.hide() + } + } + this.registerCursor = function(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect) { + var memberid = cursor.getMemberId(), caret = new gui.Caret(cursor, caretAvatarInitiallyVisible, blinkOnRangeSelect); + 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() + }else { + cursor.handleUpdate = caret.handleUpdate + } + return caret + }; + this.getCaret = getCaret; + this.getCarets = getCarets; + this.destroy = function(callback) { + var odtDocument = sessionController.getSession().getOdtDocument(), eventManager = sessionController.getEventManager(), caretArray = getCarets(); + odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible); + odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking); + odtDocument.unsubscribe(ops.OdtDocument.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 = {} + }; + 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); + eventManager.subscribe("focus", focusLocalCaret); + eventManager.subscribe("blur", blurLocalCaret); + window.addEventListener("focus", showLocalCaret, false); + window.addEventListener("blur", hideLocalCaret, false) + } + init() +}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("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 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; + 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) { + return node + } + node = node.nextSibling + } + return null + } + function setAvatarInfoStyle(memberId, name, color) { + function setStyle(nodeName, rule, pseudoClass) { + var styleRule = createAvatarInfoNodeMatch(nodeName, memberId, pseudoClass) + rule, styleNode = getAvatarInfoStyle(nodeName, memberId, pseudoClass); + if(styleNode) { + styleNode.data = styleRule + }else { + avatarInfoStyles.appendChild(document.createTextNode(styleRule)) + } + } + setStyle("div.editInfoMarker", "{ background-color: " + color + "; }", ""); + setStyle("span.editInfoColor", "{ background-color: " + color + "; }", ""); + setStyle("span.editInfoAuthor", '{ content: "' + name + '"; }', ":before"); + setStyle("dc|creator", "{ background-color: " + color + "; }", ""); + setStyle("div.selectionOverlay", "{ background-color: " + color + ";}", "") + } + function highlightEdit(element, memberId, timestamp) { + var editInfo, editInfoMarker, id = "", editInfoNode = element.getElementsByTagNameNS(editInfons, "editinfo")[0]; + if(editInfoNode) { + 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.setAttributeNS(editInfons, "id", id); + editInfoMap[id] = editInfoMarker + } + editInfoMarker.addEdit(memberId, new Date(timestamp)) + } + function setEditInfoMarkerVisibility(visible) { + var editInfoMarker, keyname; + for(keyname in editInfoMap) { + if(editInfoMap.hasOwnProperty(keyname)) { + editInfoMarker = editInfoMap[keyname]; + if(visible) { + editInfoMarker.show() + }else { + editInfoMarker.hide() + } + } + } + } + function setCaretAvatarVisibility(visible) { + caretManager.getCarets().forEach(function(caret) { + if(visible) { + caret.showHandle() + }else { + caret.hideHandle() + } + }) + } + this.showEditInfoMarkers = function() { + if(showEditInfoMarkers) { + return + } + showEditInfoMarkers = true; + setEditInfoMarkerVisibility(showEditInfoMarkers) + }; + this.hideEditInfoMarkers = function() { + if(!showEditInfoMarkers) { + return + } + showEditInfoMarkers = false; + setEditInfoMarkerVisibility(showEditInfoMarkers) + }; + this.showCaretAvatars = function() { + if(showCaretAvatars) { + return + } + showCaretAvatars = true; + setCaretAvatarVisibility(showCaretAvatars) + }; + this.hideCaretAvatars = function() { + if(!showCaretAvatars) { + return + } + showCaretAvatars = false; + setCaretAvatarVisibility(showCaretAvatars) + }; + this.getSession = function() { + return session + }; + this.getCaret = function(memberid) { + return caretManager.getCaret(memberid) + }; + function renderMemberData(member) { + var memberId = member.getMemberId(), properties = member.getProperties(); + setAvatarInfoStyle(memberId, properties.fullName, properties.color); + if(localMemberId === memberId) { + setAvatarInfoStyle("", "", properties.color) + } + } + function onCursorAdded(cursor) { + var memberId = cursor.getMemberId(), properties = session.getOdtDocument().getMember(memberId).getProperties(), caret; + caretManager.registerCursor(cursor, showCaretAvatars, blinkOnRangeSelect); + selectionViewManager.registerCursor(cursor, true); + caret = caretManager.getCaret(memberId); + if(caret) { + caret.setAvatarImageUrl(properties.imageUrl); + caret.setColor(properties.color) + } + runtime.log("+++ View here +++ eagerly created an Caret for '" + memberId + "'! +++") + } + function onCursorMoved(cursor) { + var memberId = cursor.getMemberId(), localSelectionView = selectionViewManager.getSelectionView(localMemberId), shadowSelectionView = selectionViewManager.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId), localCaret = caretManager.getCaret(localMemberId); + if(memberId === localMemberId) { + shadowSelectionView.hide(); + if(localSelectionView) { + localSelectionView.show() + } + if(localCaret) { + localCaret.show() + } + }else { + if(memberId === gui.ShadowCursor.ShadowCursorMemberId) { + shadowSelectionView.show(); + if(localSelectionView) { + localSelectionView.hide() + } + if(localCaret) { + localCaret.hide() + } + } + } + } + function onCursorRemoved(memberid) { + selectionViewManager.removeSelectionView(memberid) + } + 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.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(); + avatarInfoStyles.parentNode.removeChild(avatarInfoStyles); + (function destroyEditInfo(i, err) { + if(err) { + callback(err) + }else { + if(i < editInfoArray.length) { + editInfoArray[i].destroy(function(err) { + destroyEditInfo(i + 1, err) + }) + }else { + callback() + } + } + })(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); + 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"); + avatarInfoStyles.type = "text/css"; + avatarInfoStyles.media = "screen, print, handheld, projection"; + avatarInfoStyles.appendChild(document.createTextNode("@namespace editinfo url(urn:webodf:names:editinfo);")); + avatarInfoStyles.appendChild(document.createTextNode("@namespace dc url(http://purl.org/dc/elements/1.1/);")); + head.appendChild(avatarInfoStyles) + } + 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"; diff --git a/js/3rdparty/webodf/webodf.js b/js/3rdparty/webodf/webodf.js index 306f4d94..f483b7d2 100644 --- a/js/3rdparty/webodf/webodf.js +++ b/js/3rdparty/webodf/webodf.js @@ -1,159 +1,56 @@ // Input 0 -/* - - - Copyright (C) 2012 KO GmbH - - @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 . - - 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/ -*/ -var core={},gui={},xmldom={},odf={},ops={}; +var webodf_version="0.4.2-1556-gf8a94ee"; // 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,c,m){};Runtime.prototype.readFile=function(g,l,c){};Runtime.prototype.readFileSync=function(g,l){};Runtime.prototype.loadXML=function(g,l){};Runtime.prototype.writeFile=function(g,l,c){}; -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.type=function(){};Runtime.prototype.getDOMImplementation=function(){};Runtime.prototype.parseXML=function(g){};Runtime.prototype.getWindow=function(){}; -Runtime.prototype.assert=function(g,l,c){};var IS_COMPILED_CODE=!0; -Runtime.byteArrayToString=function(g,l){function c(c){var b="",p,r=c.length;for(p=0;pk?d.push(k):(p+=1,a=c[p],194<=k&&224>k?d.push((k&31)<<6|a&63):(p+=1,e=c[p],224<=k&&240>k?d.push((k&15)<<12|(a&63)<<6|e&63):(p+=1,h=c[p],240<=k&&245>k&&(k=(k&7)<<18|(a&63)<<12|(e&63)<<6|h&63,k-=65536,d.push((k>>10)+55296,(k&1023)+56320))))),1E3===d.length&&(b+=String.fromCharCode.apply(null, -d),d.length=0);return b+String.fromCharCode.apply(null,d)}var f;"utf8"===l?f=m(g):("binary"!==l&&this.log("Unsupported encoding: "+l),f=c(g));return f};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(b,r){var d,k,a;void 0!==r?a=b:r=b;g?(k=g.ownerDocument,a&&(d=k.createElement("span"),d.className=a,d.appendChild(k.createTextNode(a)),g.appendChild(d),g.appendChild(k.createTextNode(" "))),d=k.createElement("span"),0e?(k[h]=e,h+=1):2048>e?(k[h]=192|e>>>6,k[h+1]=128|e&63,h+=2):(k[h]=224|e>>>12&15,k[h+1]=128|e>>>6&63,k[h+2]=128|e&63,h+=3)}else for("binary"!==c&&n.log("unknown encoding: "+c),d=b.length,k=new Uint8Array(new ArrayBuffer(d)),a=0;ak.status||0===k.status?d(null):d("Status "+String(k.status)+": "+k.responseText||k.statusText):d("File "+c+" is empty."))};a=r.buffer&&!k.sendAsBinary?r.buffer:n.byteArrayToString(r,"binary");try{k.sendAsBinary?k.sendAsBinary(a):k.send(a)}catch(e){n.log("HUH? "+e+" "+r),d(e.message)}};this.deleteFile=function(c,r){delete b[c];var d=new XMLHttpRequest;d.open("DELETE",c,!0);d.onreadystatechange=function(){4===d.readyState&& -(200>d.status&&300<=d.status?r(d.responseText):r(null))};d.send(null)};this.loadXML=function(b,c){var d=new XMLHttpRequest;d.open("GET",b,!0);d.overrideMimeType&&d.overrideMimeType("text/xml");d.onreadystatechange=function(){4===d.readyState&&(0!==d.status||d.responseText?200===d.status||0===d.status?c(null,d.responseXML):c(d.responseText,null):c("File "+b+" is empty.",null))};try{d.send(null)}catch(k){c(k.message,null)}};this.isFile=function(b,c){n.getFileSize(b,function(d){c(-1!==d)})};this.getFileSize= -function(c,r){if(b.hasOwnProperty(c)&&"string"!==typeof b[c])r(b[c].length);else{var d=new XMLHttpRequest;d.open("HEAD",c,!0);d.onreadystatechange=function(){if(4===d.readyState){var b=d.getResponseHeader("Content-Length");b?r(parseInt(b,10)):f(c,"binary",function(a,e){a?r(-1):r(e.length)})}};d.send(null)}};this.log=l;this.assert=function(b,c,d){if(!b)throw l("alert","ASSERTION FAILED:\n"+c),d&&d(),c;};this.setTimeout=function(b,c){return setTimeout(function(){b()},c)};this.clearTimeout=function(b){clearTimeout(b)}; -this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML=function(b){return(new DOMParser).parseFromString(b,"text/xml")};this.exit=function(b){l("Calling exit with code "+String(b)+", but exit() is not implemented.")};this.getWindow=function(){return window}} -function NodeJSRuntime(){function g(b){var d=b.length,k,a=new Uint8Array(new ArrayBuffer(d));for(k=0;k").implementation} -function RhinoRuntime(){function g(b,c){var f;void 0!==c?f=b:c=b;"alert"===f&&print("\n!!!!! ALERT !!!!!");print(c);"alert"===f&&print("!!!!! ALERT !!!!!")}var l=this,c=Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(),m,f,n="";c.setValidating(!1);c.setNamespaceAware(!0);c.setExpandEntityReferences(!1);c.setSchema(null);f=Packages.org.xml.sax.EntityResolver({resolveEntity:function(b,c){var f=new Packages.java.io.FileReader(c);return new Packages.org.xml.sax.InputSource(f)}});m=c.newDocumentBuilder(); -m.setEntityResolver(f);this.byteArrayFromString=function(b,c){var f=[],d,k=b.length;for(d=0;df?d.push(f):(h+=1,a=e[h],194<=f&&224>f?d.push((f&31)<<6|a&63):(h+=1,c=e[h],224<=f&&240>f?d.push((f&15)<<12|(a&63)<<6|c&63):(h+=1,p=e[h],240<=f&&245>f&&(f=(f&7)<<18|(a&63)<<12|(c&63)<<6|p&63,f-=65536,d.push((f>>10)+55296,(f&1023)+56320))))),1E3===d.length&&(b+=String.fromCharCode.apply(null, +d),d.length=0);return b+String.fromCharCode.apply(null,d)}var m;"utf8"===k?m=n(g):("binary"!==k&&this.log("Unsupported encoding: "+k),m=e(g));return m};Runtime.getVariable=function(g){try{return eval(g)}catch(k){}};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 k(h,b){var d,f,a;void 0!==b?a=h:b=h;g?(f=g.ownerDocument,a&&(d=f.createElement("span"),d.className=a,d.appendChild(f.createTextNode(a)),g.appendChild(d),g.appendChild(f.createTextNode(" "))),d=f.createElement("span"),0c?(f[p]=c,p+=1):2048>c?(f[p]=192|c>>>6,f[p+1]=128|c&63,p+=2):(f[p]=224|c>>>12&15,f[p+1]=128|c>>>6&63,f[p+2]=128|c&63,p+=3)}else for("binary"!==e&&q.log("unknown encoding: "+e),d=b.length,f=new Uint8Array(new ArrayBuffer(d)),a=0;af.status||0===f.status?d(null):d("Status "+String(f.status)+": "+f.responseText||f.statusText):d("File "+h+" is empty."))};a=e.buffer&&!f.sendAsBinary?e.buffer:q.byteArrayToString(e,"binary");try{f.sendAsBinary?f.sendAsBinary(a):f.send(a)}catch(c){q.log("HUH? "+c+" "+e),d(c.message)}};this.deleteFile=function(h,e){delete b[h];var d=new XMLHttpRequest;d.open("DELETE",h,!0);d.onreadystatechange=function(){4===d.readyState&& +(200>d.status&&300<=d.status?e(d.responseText):e(null))};d.send(null)};this.loadXML=function(b,e){var d=new XMLHttpRequest;d.open("GET",b,!0);d.overrideMimeType&&d.overrideMimeType("text/xml");d.onreadystatechange=function(){4===d.readyState&&(0!==d.status||d.responseText?200===d.status||0===d.status?e(null,d.responseXML):e(d.responseText,null):e("File "+b+" is empty.",null))};try{d.send(null)}catch(f){e(f.message,null)}};this.isFile=function(b,e){q.getFileSize(b,function(d){e(-1!==d)})};this.getFileSize= +function(h,e){if(b.hasOwnProperty(h)&&"string"!==typeof b[h])e(b[h].length);else{var d=new XMLHttpRequest;d.open("HEAD",h,!0);d.onreadystatechange=function(){if(4===d.readyState){var f=d.getResponseHeader("Content-Length");f?e(parseInt(f,10)):m(h,"binary",function(a,c){a?e(-1):e(c.length)})}};d.send(null)}};this.log=k;this.assert=function(b,e,d){if(!b)throw k("alert","ASSERTION FAILED:\n"+e),d&&d(),e;};this.setTimeout=function(b,e){return setTimeout(function(){b()},e)};this.clearTimeout=function(b){clearTimeout(b)}; +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(b){return(new DOMParser).parseFromString(b,"text/xml")};this.exit=function(b){k("Calling exit with code "+String(b)+", but exit() is not implemented.")};this.getWindow=function(){return window}} +function NodeJSRuntime(){function g(b){var d=b.length,f,a=new Uint8Array(new ArrayBuffer(d));for(f=0;f").implementation} +function RhinoRuntime(){function g(b,e){var d;void 0!==e?d=b:e=b;"alert"===d&&print("\n!!!!! ALERT !!!!!");print(e);"alert"===d&&print("!!!!! ALERT !!!!!")}var k=this,e={},n=e.javax.xml.parsers.DocumentBuilderFactory.newInstance(),m,q,b="";n.setValidating(!1);n.setNamespaceAware(!0);n.setExpandEntityReferences(!1);n.setSchema(null);q=e.org.xml.sax.EntityResolver({resolveEntity:function(b,m){var d=new e.java.io.FileReader(m);return new e.org.xml.sax.InputSource(d)}});m=n.newDocumentBuilder();m.setEntityResolver(q); +this.byteArrayFromString=function(b,e){var d,f=b.length,a=new Uint8Array(new ArrayBuffer(f));for(d=0;d>>18],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>12&63],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6&63],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e& -63];b===d+1?(e=a[b]<<4,h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e&63],h+="=="):b===d&&(e=a[b]<<10|a[b+1]<<2,h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>12],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6&63],h+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e&63],h+="=");return h}function c(a){a=a.replace(/[^A-Za-z0-9+\/]+/g, -"");var e=a.length,h=new Uint8Array(new ArrayBuffer(3*e)),b=a.length%4,d=0,c,k;for(c=0;c>16,h[d+1]=k>>8&255,h[d+2]=k&255,d+=3;e=3*e-[0,0,2,1][b];return h.subarray(0,e)}function m(a){var e,h,b=a.length,d=0,c=new Uint8Array(new ArrayBuffer(3*b));for(e=0;eh?c[d++]=h:(2048>h?c[d++]=192|h>>>6:(c[d++]=224|h>>>12&15,c[d++]=128|h>>>6&63),c[d++]=128|h&63);return c.subarray(0, -d)}function f(a){var e,h,b,d,c=a.length,k=new Uint8Array(new ArrayBuffer(c)),q=0;for(e=0;eh?k[q++]=h:(e+=1,b=a[e],224>h?k[q++]=(h&31)<<6|b&63:(e+=1,d=a[e],k[q++]=(h&15)<<12|(b&63)<<6|d&63));return k.subarray(0,q)}function n(a){return l(g(a))}function b(a){return String.fromCharCode.apply(String,c(a))}function p(a){return f(g(a))}function r(a){a=f(a);for(var e="",h=0;he?k+=String.fromCharCode(e):(c+=1,b=a.charCodeAt(c)&255,224>e?k+=String.fromCharCode((e&31)<<6|b&63):(c+=1,d=a.charCodeAt(c)&255,k+=String.fromCharCode((e&15)<<12|(b&63)<<6|d&63)));return k}function k(a,e){function h(){var k=c+1E5;k>a.length&&(k=a.length);b+=d(a,c,k);c=k;k=c===a.length;e(b,k)&&!k&&runtime.setTimeout(h,0)}var b="",c=0;1E5>a.length?e(d(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),h())}function a(a){return m(g(a))}function e(a){return String.fromCharCode.apply(String, -m(a))}function h(a){return String.fromCharCode.apply(String,m(g(a)))}var q=function(a){var e={},h,b;h=0;for(b=a.length;h>>8):(da(e&255),da(e>>>8))},qa=function(){t=(t<<5^h[z+3-1]&255)&8191;s=x[32768+t];x[z&32767]=s;x[32768+t]=z},aa=function(a,e){y>16-e?(v|=a<>16-y,y+=e-16):(v|=a<a;a++)h[a]=h[a+32768];K-=32768;z-=32768;w-=32768;for(a=0;8192>a;a++)e=x[32768+a],x[32768+a]=32768<=e?e-32768:0;for(a=0;32768>a;a++)e=x[a],x[a]=32768<=e?e-32768:0;b+=32768}F||(a=Aa(h,z+Q,b),0>=a?F=!0:Q+=a)},ya=function(a){var e=$,b=z,d,c=M,k=32506=ma&&(e>>=2);do if(d=a,h[d+c]===s&&h[d+c-1]===f&&h[d]===h[b]&&h[++d]===h[b+1]){b+= -2;d++;do++b;while(h[b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&h[++b]===h[++d]&&bc){K=a;c=d;if(258<=d)break;f=h[b+c-1];s=h[b+c]}a=x[a&32767]}while(a>k&&0!==--e);return c},ra=function(a,e){u[U++]=e;0===a?ba[e].fc++:(a--,ba[T[e]+256+1].fc++,ga[(256>a?P[a]:P[256+(a>>7)])&255].fc++,q[H++]=a,fa|=W);W<<=1;0===(U&7)&&(E[la++]=fa,fa=0,W=1);if(2d;d++)h+=ga[d].fc* -(5+oa[d]);h>>=3;if(H>=1,h<<=1;while(0<--e);return h>>1},Ea=function(a,e){var h=[];h.length=16;var b=0,d;for(d=1;15>=d;d++)b=b+N[d-1]<<1,h[d]=b;for(b=0;b<=e;b++)d=a[b].dl,0!==d&&(a[b].fc=Ba(h[d]++,d))},Da=function(a){var e=a.dyn_tree,h=a.static_tree,b=a.elems,d,c=-1, -k=b;Z=0;ka=573;for(d=0;dZ;)d=O[++Z]=2>c?++c:0,e[d].fc=1,ca[d]=0,ja--,null!==h&&(C-=h[d].dl);a.max_code=c;for(d=Z>>1;1<=d;d--)xa(e,d);do d=O[1],O[1]=O[Z--],xa(e,1),h=O[1],O[--ka]=d,O[--ka]=h,e[k].fc=e[d].fc+e[h].fc,ca[k]=ca[d]>ca[h]+1?ca[d]:ca[h]+1,e[d].dl=e[h].dl=k,O[1]=k++,xa(e,1);while(2<=Z);O[--ka]=O[1];k=a.dyn_tree;d=a.extra_bits;var b=a.extra_base,h=a.max_code,q=a.max_length,f=a.static_tree,s,g,l,p,B=0;for(g=0;15>=g;g++)N[g]=0;k[O[ka]].dl= -0;for(a=ka+1;573>a;a++)s=O[a],g=k[k[s].dl].dl+1,g>q&&(g=q,B++),k[s].dl=g,s>h||(N[g]++,l=0,s>=b&&(l=d[s-b]),p=k[s].fc,ja+=p*(g+l),null!==f&&(C+=p*(f[s].dl+l)));if(0!==B){do{for(g=q-1;0===N[g];)g--;N[g]--;N[g+1]+=2;N[q]--;B-=2}while(0h||(k[d].dl!==g&&(ja+=(g-k[d].dl)*k[d].fc,k[d].fc=g),s--)}Ea(e,c)},Fa=function(a,e){var h,b=-1,d,c=a[0].dl,k=0,q=7,f=4;0===c&&(q=138,f=3);a[e+1].dl=65535;for(h=0;h<=e;h++)d=c,c=a[h+1].dl,++k=k?V[17].fc++:V[18].fc++,k=0,b=d,0===c?(q=138,f=3):d===c?(q=6,f=3):(q=7,f=4))},Ga=function(){8h?P[h]:P[256+(h>>7)])&255,J(f,e),g=oa[f],0!==g&&(h-=ea[f],aa(h,g))),k>>=1;while(b=k?(J(17,V),aa(k-3,3)):(J(18,V),aa(k-11,7));k=0;b=d;0===c?(q=138,f=3):d===c?(q=6,f=3):(q=7,f=4)}},Ja=function(){var a;for(a=0;286>a;a++)ba[a].fc=0;for(a=0;30>a;a++)ga[a].fc=0;for(a=0;19>a;a++)V[a].fc=0;ba[256].fc=1;fa=U=H=la=ja=C=0;W=1},Ca=function(a){var e,b,d,c;c=z-w;E[la]=fa;Da(G);Da(I);Fa(ba,G.max_code);Fa(ga,I.max_code);Da(ha);for(d=18;3<=d&&0===V[va[d]].dl;d--); -ja+=3*(d+1)+14;e=ja+3+7>>3;b=C+3+7>>3;b<=e&&(e=b);if(c+4<=e&&0<=w)for(aa(0+a,3),Ga(),X(c),X(~c),d=0;db.len&&(f=b.len);for(g=0;gk-a&&(f=k-a);for(g=0;g -l;l++)for(L[l]=g,f=0;f<1<l;l++)for(ea[l]=g,f=0;f<1<>=7;30>l;l++)for(ea[l]=g<<7,f=0;f<1<=f;f++)N[f]=0;for(f=0;143>=f;)S[f++].dl=8,N[8]++;for(;255>=f;)S[f++].dl=9,N[9]++;for(;279>=f;)S[f++].dl=7,N[7]++;for(;287>=f;)S[f++].dl=8,N[8]++;Ea(S,287);for(f=0;30>f;f++)Y[f].dl=5,Y[f].fc=Ba(f,5);Ja()}for(f=0;8192>f;f++)x[32768+f]=0;ia=wa[R].max_lazy;ma=wa[R].good_length;$=wa[R].max_chain;w=z=0;Q=Aa(h,0,65536); -if(0>=Q)F=!0,Q=0;else{for(F=!1;262>Q&&!F;)ua();for(f=t=0;2>f;f++)t=(t<<5^h[f]&255)&8191}b=null;a=k=0;3>=R?(M=2,B=0):(B=2,A=0);e=!1}r=!0;if(0===Q)return e=!0,0}f=Ka(d,c,q);if(f===q)return q;if(e)return f;if(3>=R)for(;0!==Q&&null===b;){qa();0!==s&&32506>=z-s&&(B=ya(s),B>Q&&(B=Q));if(3<=B)if(l=ra(z-K,B-3),Q-=B,B<=ia){B--;do z++,qa();while(0!==--B);z++}else z+=B,B=0,t=h[z]&255,t=(t<<5^h[z+1]&255)&8191;else l=ra(0,h[z]&255),Q--,z++;l&&(Ca(0),w=z);for(;262>Q&&!F;)ua()}else for(;0!==Q&&null===b;){qa();M= -B;D=K;B=2;0!==s&&M=z-s&&(B=ya(s),B>Q&&(B=Q),3===B&&4096Q&&!F;)ua()}0===Q&&(0!==A&&ra(0,h[z-1]&255),Ca(1),e=!0);return f+Ka(d,f+c,q-f)};this.deflate=function(a,e){var c,k;sa=a;na=0;"undefined"===String(typeof e)&&(e=6);(c=e)?1>c?c=1:9c;c++)ba[c]=new g;ga=[];ga.length=61;for(c=0;61>c;c++)ga[c]=new g;S=[];S.length=288;for(c=0;288>c;c++)S[c]=new g;Y=[];Y.length=30;for(c=0;30>c;c++)Y[c]=new g;V=[];V.length=39;for(c=0;39>c;c++)V[c]=new g;G=new l;I=new l;ha=new l;N=[];N.length=16;O=[];O.length=573;ca=[];ca.length=573;T=[];T.length=256;P=[];P.length=512;L=[];L.length=29;ea=[];ea.length=30;E=[];E.length=1024}var s=Array(1024),B=[],m=[];for(c=La(s, -0,s.length);0>>18],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>12&63],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6&63],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c& +63];b===f+1?(c=a[b]<<4,d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c&63],d+="=="):b===f&&(c=a[b]<<10|a[b+1]<<2,d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>12],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c>>>6&63],d+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c&63],d+="=");return d}function e(a){a=a.replace(/[^A-Za-z0-9+\/]+/g, +"");var c=a.length,d=new Uint8Array(new ArrayBuffer(3*c)),b=a.length%4,f=0,p,e;for(p=0;p>16,d[f+1]=e>>8&255,d[f+2]=e&255,f+=3;c=3*c-[0,0,2,1][b];return d.subarray(0,c)}function n(a){var c,d,b=a.length,f=0,p=new Uint8Array(new ArrayBuffer(3*b));for(c=0;cd?p[f++]=d:(2048>d?p[f++]=192|d>>>6:(p[f++]=224|d>>>12&15,p[f++]=128|d>>>6&63),p[f++]=128|d&63);return p.subarray(0, +f)}function m(a){var c,d,b,f,p=a.length,l=new Uint8Array(new ArrayBuffer(p)),e=0;for(c=0;cd?l[e++]=d:(c+=1,b=a[c],224>d?l[e++]=(d&31)<<6|b&63:(c+=1,f=a[c],l[e++]=(d&15)<<12|(b&63)<<6|f&63));return l.subarray(0,e)}function q(a){return k(g(a))}function b(a){return String.fromCharCode.apply(String,e(a))}function h(a){return m(g(a))}function r(a){a=m(a);for(var c="",d=0;dc?l+=String.fromCharCode(c):(p+=1,b=a.charCodeAt(p)&255,224>c?l+=String.fromCharCode((c&31)<<6|b&63):(p+=1,f=a.charCodeAt(p)&255,l+=String.fromCharCode((c&15)<<12|(b&63)<<6|f&63)));return l}function f(a,c){function b(){var l=p+1E5;l>a.length&&(l=a.length);f+=d(a,p,l);p=l;l=p===a.length;c(f,l)&&!l&&runtime.setTimeout(b,0)}var f="",p=0;1E5>a.length?c(d(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),b())}function a(a){return n(g(a))}function c(a){return String.fromCharCode.apply(String, +n(a))}function p(a){return String.fromCharCode.apply(String,n(g(a)))}var l=function(a){var c={},d,b;d=0;for(b=a.length;df-m&&(f=Math.max(2*f,m+b),b=new Uint8Array(new ArrayBuffer(f)),b.set(n),n=b)}var c=this,m=0,f=1024,n=new Uint8Array(new ArrayBuffer(f));this.appendByteArrayWriter=function(b){c.appendByteArray(b.getByteArray())};this.appendByteArray=function(b){var c=b.length;l(c);n.set(b,m);m+=c};this.appendArray=function(b){var c=b.length;l(c);n.set(b,m);m+=c};this.appendUInt16LE=function(b){c.appendArray([b&255,b>>8&255])};this.appendUInt32LE=function(b){c.appendArray([b& -255,b>>8&255,b>>16&255,b>>24&255])};this.appendString=function(b){c.appendByteArray(runtime.byteArrayFromString(b,g))};this.getLength=function(){return m};this.getByteArray=function(){var b=new Uint8Array(new ArrayBuffer(m));b.set(n.subarray(0,m));return b}}; +core.ByteArrayWriter=function(g){function k(b){b>m-n&&(m=Math.max(2*m,n+b),b=new Uint8Array(new ArrayBuffer(m)),b.set(q),q=b)}var e=this,n=0,m=1024,q=new Uint8Array(new ArrayBuffer(m));this.appendByteArrayWriter=function(b){e.appendByteArray(b.getByteArray())};this.appendByteArray=function(b){var e=b.length;k(e);q.set(b,n);n+=e};this.appendArray=function(b){var e=b.length;k(e);q.set(b,n);n+=e};this.appendUInt16LE=function(b){e.appendArray([b&255,b>>8&255])};this.appendUInt32LE=function(b){e.appendArray([b& +255,b>>8&255,b>>16&255,b>>24&255])};this.appendString=function(b){e.appendByteArray(runtime.byteArrayFromString(b,g))};this.getLength=function(){return n};this.getByteArray=function(){var b=new Uint8Array(new ArrayBuffer(n));b.set(q.subarray(0,n));return b}}; // Input 6 -core.RawInflate=function(){var g,l,c=null,m,f,n,b,p,r,d,k,a,e,h,q,u,x,v=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],y=[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],w=[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],t=[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],s=[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],D=[16,17,18, -0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],A=function(){this.list=this.next=null},B=function(){this.n=this.b=this.e=0;this.t=null},M=function(a,e,h,b,d,c){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var k=Array(this.BMAX+1),q,f,g,s,l,p,m,r=Array(this.BMAX+1),n,w,u,t=new B,z=Array(this.BMAX);s=Array(this.N_MAX);var K,x=Array(this.BMAX+1),v,F,M;M=this.root=null;for(l=0;ll&&(c=l);for(v=1<(v-=k[p])){this.status=2;this.m=c;return}if(0>(v-=k[l]))this.status=2,this.m=c;else{k[l]+=v;x[1]=p=0;n=k;w=1;for(u=2;0<--l;)x[u++]=p+=n[w++];n=a;l=w=0;do 0!=(p=n[w++])&&(s[x[p]++]=l);while(++lK+r[1+s];){K+=r[1+s];s++;F=(F=g-K)>c?c:F;if((f=1<<(p=m-K))>a+1)for(f-=a+1,u=m;++pq&&K>K-r[s],z[s-1][p].e=t.e,z[s-1][p].b=t.b,z[s-1][p].n=t.n,z[s-1][p].t=t.t)}t.b=m-K;w>=e?t.e=99:n[w]n[w]?16:15,t.n=n[w++]): -(t.e=d[n[w]-h],t.n=b[n[w++]-h]);f=1<>K;p>=1)l^=p;for(l^=p;(l&(1<>=a;b-=a},Q=function(b,c,f){var s,B,m;if(0==f)return 0;for(m=0;;){z(h);B=a.list[K(h)];for(s=B.e;16 -f;f++)r[D[f]]=0;h=7;f=new M(r,19,19,null,null,h);if(0!=f.status)return-1;a=f.root;h=f.m;l=B+m;for(k=g=0;kf)r[k++]=g=f;else if(16==f){z(2);f=3+K(2);F(2);if(k+f>l)return-1;for(;0l)return-1;for(;0I;I++)G[I]=8;for(;256>I;I++)G[I]=9;for(;280>I;I++)G[I]=7;for(;288>I;I++)G[I]=8;f=7;I=new M(G,288,257,y,w,f);if(0!=I.status){alert("HufBuild error: "+I.status);S=-1;break b}c=I.root;f=I.m;for(I=0;30>I;I++)G[I]=5;$=5;I=new M(G,30,0,t,s,$); -if(1 - - @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 . - - 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.LoopWatchDog=function(g,l){var c=Date.now(),m=0;this.check=function(){var f;if(g&&(f=Date.now(),f-c>g))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0l))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}}; -// Input 8 -core.Utils=function(){function g(l,c){c&&Array.isArray(c)?l=(l||[]).concat(c.map(function(c){return g({},c)})):c&&"object"===typeof c?(l=l||{},Object.keys(c).forEach(function(m){l[m]=g(l[m],c[m])})):l=c;return l}this.hashString=function(g){var c=0,m,f;m=0;for(f=g.length;m @@ -191,23 +88,18 @@ core.Utils=function(){function g(l,c){c&&Array.isArray(c)?l=(l||[]).concat(c.map @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -(function(){function g(){var c,g,f,n,b;void 0===l&&(b=(c=runtime.getWindow())&&c.document,l={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1},b&&(n=b.createElement("div"),n.style.position="absolute",n.style.left="-99999px",n.style.transform="scale(2)",n.style["-webkit-transform"]="scale(2)",g=b.createElement("div"),n.appendChild(g),b.body.appendChild(n),c=b.createRange(),c.selectNode(g),l.rangeBCRIgnoresElementBCR=0===c.getClientRects().length,g.appendChild(b.createTextNode("Rect transform test")), -g=g.getBoundingClientRect(),f=c.getBoundingClientRect(),l.unscaledRangeClientRects=2=a.compareBoundaryPoints(Range.START_TO_START,e)&&0<=a.compareBoundaryPoints(Range.END_TO_END,e)}function l(a,e){return 0>=a.compareBoundaryPoints(Range.END_TO_START,e)&&0<= -a.compareBoundaryPoints(Range.START_TO_END,e)}function f(a,e){var h=null;a.nodeType===Node.TEXT_NODE&&(0===a.length?(a.parentNode.removeChild(a),e.nodeType===Node.TEXT_NODE&&(h=e)):(e.nodeType===Node.TEXT_NODE&&(a.appendData(e.data),e.parentNode.removeChild(e)),h=a));return h}function n(a){for(var e=a.parentNode;a.firstChild;)e.insertBefore(a.firstChild,a);e.removeChild(a);return e}function b(a,e){for(var h=a.parentNode,d=a.firstChild,c;d;)c=d.nextSibling,b(d,e),d=c;e(a)&&(h=n(a));return h}function p(a, -e){return a===e||Boolean(a.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function r(a,e){for(var h=0,b;a.parentNode!==e;)runtime.assert(null!==a.parentNode,"parent is null"),a=a.parentNode;for(b=e.firstChild;b!==a;)h+=1,b=b.nextSibling;return h}function d(a,e,h){Object.keys(e).forEach(function(b){var c=b.split(":"),k=c[1],f=h(c[0]),c=e[b];"object"===typeof c&&Object.keys(c).length?(b=a.getElementsByTagNameNS(f,k)[0]||a.ownerDocument.createElementNS(f,b),a.appendChild(b),d(b,c,h)): -f&&a.setAttributeNS(f,b,c)})}var k=null;this.splitBoundaries=function(a){var e=[],h,b;if(a.startContainer.nodeType===Node.TEXT_NODE||a.endContainer.nodeType===Node.TEXT_NODE){if(h=a.endContainer){h=a.endOffset;b=a.endContainer;if(h=a.compareBoundaryPoints(Range.START_TO_START,c)&&0<=a.compareBoundaryPoints(Range.END_TO_END,c)}function k(a,c){return 0>=a.compareBoundaryPoints(Range.END_TO_START,c)&&0<= +a.compareBoundaryPoints(Range.START_TO_END,c)}function m(a,c){var d=null;a.nodeType===Node.TEXT_NODE&&(0===a.length?(a.parentNode.removeChild(a),c.nodeType===Node.TEXT_NODE&&(d=c)):(c.nodeType===Node.TEXT_NODE&&(a.appendData(c.data),c.parentNode.removeChild(c)),d=a));return d}function q(a){for(var c=a.parentNode;a.firstChild;)c.insertBefore(a.firstChild,a);c.removeChild(a);return c}function b(a,c){for(var d=a.parentNode,f=a.firstChild,e;f;)e=f.nextSibling,b(f,c),f=e;c(a)&&(d=q(a));return d}function h(a, +c){return a===c||Boolean(a.compareDocumentPosition(c)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function r(a,c){for(var d=0,b;a.parentNode!==c;)runtime.assert(null!==a.parentNode,"parent is null"),a=a.parentNode;for(b=c.firstChild;b!==a;)d+=1,b=b.nextSibling;return d}function d(a,c,b){Object.keys(c).forEach(function(f){var e=f.split(":"),h=e[1],m=b(e[0]),e=c[f];"object"===typeof e&&Object.keys(e).length?(f=m?a.getElementsByTagNameNS(m,h)[0]||a.ownerDocument.createElementNS(m,f):a.getElementsByTagName(h)[0]|| +a.ownerDocument.createElement(f),a.appendChild(f),d(f,e,b)):m&&a.setAttributeNS(m,f,String(e))})}var f=null;this.splitBoundaries=function(a){var c=[],d,b;if(a.startContainer.nodeType===Node.TEXT_NODE||a.endContainer.nodeType===Node.TEXT_NODE){if(d=a.endContainer){d=a.endOffset;b=a.endContainer;if(d @@ -245,38 +137,86 @@ this.setSelectedRange=function(a,e){r&&r!==a&&r.detach();r=a;b=!1!==e;(d=a.colla @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -core.EventNotifier=function(g){var l={};this.emit=function(c,g){var f,n;runtime.assert(l.hasOwnProperty(c),'unknown event fired "'+c+'"');n=l[c];for(f=0;f + + @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 . + + 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.LoopWatchDog=function(g,k){var e=Date.now(),n=0;this.check=function(){var m;if(g&&(m=Date.now(),m-e>g))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0k))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}}; +// Input 10 +core.PositionIterator=function(g,k,e,n){function m(){this.acceptNode=function(a){return!a||a.nodeType===c&&0===a.length?u:l}}function q(a){this.acceptNode=function(d){return!d||d.nodeType===c&&0===d.length?u:a.acceptNode(d)}}function b(){var a=d.currentNode,b=a.nodeType;f=b===c?a.length-1:b===p?1:0}function h(){if(null===d.previousSibling()){if(!d.parentNode()||d.currentNode===g)return d.firstChild(),!1;f=0}else b();return!0}var r=this,d,f,a,c=Node.TEXT_NODE,p=Node.ELEMENT_NODE,l=NodeFilter.FILTER_ACCEPT, +u=NodeFilter.FILTER_REJECT;this.nextPosition=function(){var a=d.currentNode,b=a.nodeType;if(a===g)return!1;if(0===f&&b===p)null===d.firstChild()&&(f=1);else if(b===c&&f+1 "+b.length),runtime.assert(0<=e,"Error in setPosition: "+e+" < 0"),e===b.length&&(d.nextSibling()?f=0:d.parentNode()?f=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid.")),!0;p=a(b);for(h=b.parentNode;h&&h!==g&&p===l;)p=a(h),p!==l&&(d.currentNode=h),h=h.parentNode;ex&&(e=x);for(A=1<A){this.status=2;this.m=e;return}A-=p[x];if(0>A)this.status=2,this.m=e;else{p[x]+=A;z[1]=k=0;v=p;q=1;for(s=2;0<--x;)k+=v[q++],z[s++]=k;v=a;x=q=0;do k=v[q++],0!==k&&(g[z[k]++]=x);while(++xt+r[1+g];){t+= +r[1+g];g++;U=m-t;U=U>e?e:U;k=n-t;h=1<a+1)for(h-=a+1,s=n;++kl&&t>t-r[g],u[g-1][k].e=F.e,u[g-1][k].b=F.b,u[g-1][k].n=F.n,u[g-1][k].t=F.t)}F.b=n-t;q>=c?F.e=99:v[q]v[q]?16:15,F.n=v[q++]):(F.e=f[v[q]-d],F.n=b[v[q++]- +d]);h=1<>t;k>=1)x^=k;for(x^=k;(x&(1<>=d;c-=d}function m(a,c,d){var f,l,m;if(0===d)return 0;for(m=0;;){k(v);l=w.list[e(v)];for(f=l.e;16f;f++)s[P[f]]=0;v= +7;f=new g(s,19,19,null,null,v);if(0!==f.status)return-1;w=f.root;v=f.m;l=r+q;for(b=p=0;bf)s[b++]=p=f;else if(16===f){k(2);f=3+e(2);n(2);if(b+f>l)return-1;for(;0l)return-1;for(;0C;C++)I[C]=8;for(C=144;256>C;C++)I[C]=9;for(C=256;280>C;C++)I[C]=7;for(C=280;288>C;C++)I[C]=8;f=7;C=new g(I,288,257,x,R,f);if(0!==C.status){alert("HufBuild error: "+C.status);O=-1;break b}r=C.root;f=C.m;for(C=0;30>C;C++)I[C]= +5;A=5;C=new g(I,30,0,F,U,A);if(1";return runtime.parseXML(c)}; -core.UnitTestRunner=function(){function g(c){b+=1;runtime.log("fail",c)}function l(b,d){var c;try{if(b.length!==d.length)return g("array of length "+b.length+" should be "+d.length+" long"),!1;for(c=0;c1/e?"-0":String(e),g(d+" should be "+b+". Was "+c+".")):g(d+" should be "+b+" (of type "+typeof b+"). Was "+e+" (of type "+typeof e+").")}var b=0,p;p=function(b,d){var c=Object.keys(b),a=Object.keys(d);c.sort();a.sort();return l(c,a)&&Object.keys(b).every(function(a){var h=b[a],c=d[a];return f(h,c)?!0:(g(h+" should be "+c+" for key "+a),!1)})};this.areNodesEqual=m;this.shouldBeNull=function(b,d){n(b,d,"null")}; -this.shouldBeNonNull=function(b,d){var c,a;try{a=eval(d)}catch(e){c=e}c?g(d+" should be non-null. Threw exception "+c):null!==a?runtime.log("pass",d+" is non-null."):g(d+" should be non-null. Was "+a)};this.shouldBe=n;this.countFailedTests=function(){return b}}; -core.UnitTester=function(){function g(c,f){return""+c+""}var l=0,c={};this.runTests=function(m,f,n){function b(a){if(0===a.length)c[p]=k,l+=r.countFailedTests(),f();else{e=a[0];var h=Runtime.getFunctionName(e);runtime.log("Running "+h);q=r.countFailedTests();d.setUp();e(function(){d.tearDown();k[h]=q===r.countFailedTests();b(a.slice(1))})}}var p=Runtime.getFunctionName(m)||"",r=new core.UnitTestRunner,d=new m(r),k={},a,e,h,q,u="BrowserRuntime"=== -runtime.type();if(c.hasOwnProperty(p))runtime.log("Test "+p+" has already run.");else{u?runtime.log("Running "+g(p,'runSuite("'+p+'");')+": "+d.description()+""):runtime.log("Running "+p+": "+d.description);h=d.tests();for(a=0;aRunning "+g(m,'runTest("'+p+'","'+m+'")')+""):runtime.log("Running "+m),q=r.countFailedTests(),d.setUp(),e(),d.tearDown(),k[m]=q===r.countFailedTests()); -b(d.asyncTests())}};this.countFailedTests=function(){return l};this.results=function(){return c}}; +core.ScheduledTask=function(g,k){function e(){q&&(runtime.clearTimeout(m),q=!1)}function n(){e();g.apply(void 0,b);b=null}var m,q=!1,b=[];this.trigger=function(){b=Array.prototype.slice.call(arguments);q||(q=!0,m=runtime.setTimeout(n,k))};this.triggerImmediate=function(){b=Array.prototype.slice.call(arguments);n()};this.processRequests=function(){q&&n()};this.cancel=e;this.destroy=function(b){e();b()}}; // Input 13 -core.PositionIterator=function(g,l,c,m){function f(){this.acceptNode=function(a){return!a||a.nodeType===e&&0===a.length?u:q}}function n(a){this.acceptNode=function(b){return!b||b.nodeType===e&&0===b.length?u:a.acceptNode(b)}}function b(){var a=d.currentNode,b=a.nodeType;k=b===e?a.length-1:b===h?1:0}function p(){if(null===d.previousSibling()){if(!d.parentNode()||d.currentNode===g)return d.firstChild(),!1;k=0}else b();return!0}var r=this,d,k,a,e=Node.TEXT_NODE,h=Node.ELEMENT_NODE,q=NodeFilter.FILTER_ACCEPT, -u=NodeFilter.FILTER_REJECT;this.nextPosition=function(){var a=d.currentNode,b=a.nodeType;if(a===g)return!1;if(0===k&&b===h)null===d.firstChild()&&(k=1);else if(b===e&&k+1 "+b.length),runtime.assert(0<=h,"Error in setPosition: "+h+" < 0"),h===b.length&&(d.nextSibling()?k=0:d.parentNode()?k=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid.")),!0;c=a(b);for(f=b.parentNode;f&&f!==g&&c===q;)c=a(f),c!==q&&(d.currentNode=f),f=f.parentNode;h";return runtime.parseXML(e)}; +core.UnitTestRunner=function(){function g(e){b+=1;runtime.log("fail",e)}function k(b,d){var f;try{if(b.length!==d.length)return g("array of length "+b.length+" should be "+d.length+" long"),!1;for(f=0;f1/c?"-0":String(c),g(d+" should be "+b+". Was "+f+".")):g(d+" should be "+b+" (of type "+typeof b+"). Was "+c+" (of type "+typeof c+").")}var b=0,h;h=function(b,d){var f=Object.keys(b),a=Object.keys(d);f.sort();a.sort();return k(f,a)&&Object.keys(b).every(function(a){var f=b[a],e=d[a];return m(f,e)?!0:(g(f+" should be "+e+" for key "+a),!1)})};this.areNodesEqual=n;this.shouldBeNull=function(b,d){q(b,d,"null")};this.shouldBeNonNull=function(b,d){var f,a;try{a=eval(d)}catch(c){f= +c}f?g(d+" should be non-null. Threw exception "+f):null!==a?runtime.log("pass",d+" is non-null."):g(d+" should be non-null. Was "+a)};this.shouldBe=q;this.countFailedTests=function(){return b};this.name=function(b){var d,f,a=[],c=b.length;a.length=c;for(d=0;d"+e+""}var k=0,e={};this.runTests=function(n,m,q){function b(a){if(0===a.length)e[h]=f,k+=r.countFailedTests(),m();else{c=a[0].f;var p=a[0].name;runtime.log("Running "+p);l=r.countFailedTests();d.setUp();c(function(){d.tearDown();f[p]=l===r.countFailedTests();b(a.slice(1))})}}var h=Runtime.getFunctionName(n)||"",r=new core.UnitTestRunner,d=new n(r),f={},a,c,p,l,u="BrowserRuntime"===runtime.type(); +if(e.hasOwnProperty(h))runtime.log("Test "+h+" has already run.");else{u?runtime.log("Running "+g(h,'runSuite("'+h+'");')+": "+d.description()+""):runtime.log("Running "+h+": "+d.description);p=d.tests();for(a=0;aRunning "+g(n,'runTest("'+h+'","'+n+'")')+""):runtime.log("Running "+n),l=r.countFailedTests(),d.setUp(),c(),d.tearDown(),f[n]=l===r.countFailedTests());b(d.asyncTests())}};this.countFailedTests= +function(){return k};this.results=function(){return e}}; // Input 14 -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})(); +core.Utils=function(){function g(k,e){if(e&&Array.isArray(e)){k=k||[];if(!Array.isArray(k))throw"Destination is not an array.";k=k.concat(e.map(function(e){return g(null,e)}))}else if(e&&"object"===typeof e){k=k||{};if("object"!==typeof k)throw"Destination is not an object.";Object.keys(e).forEach(function(n){k[n]=g(k[n],e[n])})}else k=e;return k}this.hashString=function(g){var e=0,n,m;n=0;for(m=g.length;n>>8^c;return e^-1}function m(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 f(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 e,h,d,c,k,f,g,l=this;this.load=function(b){if(void 0!==l.data)b(null,l.data);else{var e=k+34+h+d+256;e+g>q&&(e=q-g);runtime.read(a,g,e,function(e,h){if(e||null===h)b(e,h);else a:{var d=h,g=new core.ByteArray(d),q=g.readUInt32LE(),s;if(67324752!==q)b("File entry signature is wrong."+q.toString()+" "+d.length.toString(),null);else{g.pos+=22;q=g.readUInt16LE();s=g.readUInt16LE();g.pos+=q+s; -if(c){d=d.subarray(g.pos,g.pos+k);if(k!==d.length){b("The amount of compressed bytes read was "+d.length.toString()+" instead of "+k.toString()+" for "+l.filename+" in "+a+".",null);break a}d=x(d,f)}else d=d.subarray(g.pos,g.pos+f);f!==d.length?b("The amount of bytes read was "+d.length.toString()+" instead of "+f.toString()+" for "+l.filename+" in "+a+".",null):(l.data=d,b(null,d))}}})}};this.set=function(a,b,e,d){l.filename=a;l.data=b;l.compressed=e;l.date=d};this.error=null;b&&(e=b.readUInt32LE(), -33639248!==e?this.error="Central directory entry has wrong signature at position "+(b.pos-4).toString()+' for file "'+a+'": '+b.data.length.toString():(b.pos+=6,c=b.readUInt16LE(),this.date=m(b.readUInt32LE()),b.readUInt32LE(),k=b.readUInt32LE(),f=b.readUInt32LE(),h=b.readUInt16LE(),d=b.readUInt16LE(),e=b.readUInt16LE(),b.pos+=8,g=b.readUInt32LE(),this.filename=runtime.byteArrayToString(b.data.subarray(b.pos,b.pos+h),"utf8"),b.pos+=h+d+e))}function b(a,b){if(22!==a.length)b("Central directory length should be 22.", -v);else{var e=new core.ByteArray(a),d;d=e.readUInt32LE();101010256!==d?b("Central directory signature is wrong: "+d.toString(),v):(d=e.readUInt16LE(),0!==d?b("Zip files with non-zero disk numbers are not supported.",v):(d=e.readUInt16LE(),0!==d?b("Zip files with non-zero disk numbers are not supported.",v):(d=e.readUInt16LE(),u=e.readUInt16LE(),d!==u?b("Number of entries is inconsistent.",v):(d=e.readUInt32LE(),e=e.readUInt16LE(),e=q-22-d,runtime.read(g,e,q-e,function(a,e){if(a||null===e)b(a,v);else a:{var d= -new core.ByteArray(e),c,k;h=[];for(c=0;cq?l("File '"+g+"' cannot be read.",v):runtime.read(g,q-22,22,function(a,e){a||null===l||null===e?l(a,v):b(e,l)})})}; +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,d,f=a.length,e=0,e=0;b=-1;for(d=0;d>>8^e;return b^-1}function n(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 m(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 q(a,c){var b,d,f,e,p,h,m,g=this;this.load=function(c){if(null!==g.data)c(null,g.data);else{var b=p+34+d+f+256;b+m>l&&(b=l-m);runtime.read(a,m,b,function(b,d){if(b||null===d)c(b,d);else a:{var f=d,l=new core.ByteArray(f),m=l.readUInt32LE(),k;if(67324752!==m)c("File entry signature is wrong."+m.toString()+" "+f.length.toString(),null);else{l.pos+=22;m=l.readUInt16LE();k=l.readUInt16LE();l.pos+=m+k;if(e){f= +f.subarray(l.pos,l.pos+p);if(p!==f.length){c("The amount of compressed bytes read was "+f.length.toString()+" instead of "+p.toString()+" for "+g.filename+" in "+a+".",null);break a}f=B(f,h)}else f=f.subarray(l.pos,l.pos+h);h!==f.length?c("The amount of bytes read was "+f.length.toString()+" instead of "+h.toString()+" for "+g.filename+" in "+a+".",null):(g.data=f,c(null,f))}}})}};this.set=function(a,c,b,d){g.filename=a;g.data=c;g.compressed=b;g.date=d};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,e=c.readUInt16LE(),this.date=n(c.readUInt32LE()),c.readUInt32LE(),p=c.readUInt32LE(),h=c.readUInt32LE(),d=c.readUInt16LE(),f=c.readUInt16LE(),b=c.readUInt16LE(),c.pos+=8,m=c.readUInt32LE(),this.filename=runtime.byteArrayToString(c.data.subarray(c.pos,c.pos+d),"utf8"),this.data=null,c.pos+=d+f+b))}function b(a,c){if(22!==a.length)c("Central directory length should be 22.", +w);else{var b=new core.ByteArray(a),d;d=b.readUInt32LE();101010256!==d?c("Central directory signature is wrong: "+d.toString(),w):(d=b.readUInt16LE(),0!==d?c("Zip files with non-zero disk numbers are not supported.",w):(d=b.readUInt16LE(),0!==d?c("Zip files with non-zero disk numbers are not supported.",w):(d=b.readUInt16LE(),u=b.readUInt16LE(),d!==u?c("Number of entries is inconsistent.",w):(d=b.readUInt32LE(),b=b.readUInt16LE(),b=l-22-d,runtime.read(g,b,l-b,function(a,b){if(a||null===b)c(a,w);else a:{var d= +new core.ByteArray(b),f,e;p=[];for(f=0;fl?k("File '"+g+"' cannot be read.",w):runtime.read(g,l-22,22,function(a,c){a||null===k||null===c?k(a,w): +b(c,k)})})}; +// Input 16 +gui.Avatar=function(g,k){var e=this,n,m,q;this.setColor=function(b){m.style.borderColor=b};this.setImageUrl=function(b){e.isVisible()?m.src=b:q=b};this.isVisible=function(){return"block"===n.style.display};this.show=function(){q&&(m.src=q,q=void 0);n.style.display="block"};this.hide=function(){n.style.display="none"};this.markAsFocussed=function(b){n.className=b?"active":""};this.destroy=function(b){g.removeChild(n);b()};(function(){var b=g.ownerDocument,e=b.documentElement.namespaceURI;n=b.createElementNS(e, +"div");m=b.createElementNS(e,"img");m.width=64;m.height=64;n.appendChild(m);n.style.width="64px";n.style.height="70px";n.style.position="absolute";n.style.top="-80px";n.style.left="-34px";n.style.display=k?"block":"none";g.appendChild(n)})()}; +// Input 17 +gui.EditInfoHandle=function(g){var k=[],e,n=g.ownerDocument,m=n.documentElement.namespaceURI;this.setEdits=function(g){k=g;var b,h,r,d;e.innerHTML="";for(g=0;g + + @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 . + + 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(){function g(e,g){g||(g=k.None);return e+":"+g}var k=gui.KeyboardHandler.Modifier,e=null,n={};this.setDefault=function(g){e=g};this.bind=function(e,k,b){e=g(e,k);runtime.assert(!1===n.hasOwnProperty(e),"tried to overwrite the callback handler of key combo: "+e);n[e]=b};this.unbind=function(e,k){var b=g(e,k);delete n[b]};this.reset=function(){e=null;n={}};this.handleEvent=function(m){var q=m.keyCode,b=k.None;m.metaKey&&(b|=k.Meta);m.ctrlKey&&(b|=k.Ctrl);m.altKey&&(b|=k.Alt); +m.shiftKey&&(b|=k.Shift);q=g(q,b);q=n[q];b=!1;q?b=q():null!==e&&(b=e(m));b&&(m.preventDefault?m.preventDefault():m.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 -core.CSSUnits=function(){var g=this,l={"in":1,cm:2.54,mm:25.4,pt:72,pc:12};this.convert=function(c,g,f){return c*l[f]/l[g]};this.convertMeasure=function(c,l){var f,n;c&&l?(f=parseFloat(c),n=c.replace(f.toString(),""),f=g.convert(f,n,l).toString()):f="";return f};this.getUnits=function(c){return c.substr(c.length-2,c.length)}}; +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.Namespaces={namespaceMap:{db:"urn:oasis:names:tc:opendocument:xmlns:database:1.0",dc:"http://purl.org/dc/elements/1.1/",dr3d:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",draw:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",chart:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0",fo:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",form:"urn:oasis:names:tc:opendocument:xmlns:form:1.0",meta:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0",number:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", +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",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,k=odf.Namespaces.prefixMap,e;for(e in g)g.hasOwnProperty(e)&&(k[g[e]]=e)})(); +odf.Namespaces.forEachPrefix=function(g){var k=odf.Namespaces.namespaceMap,e;for(e in k)k.hasOwnProperty(e)&&g(e,k[e])};odf.Namespaces.lookupNamespaceURI=function(g){var k=null;odf.Namespaces.namespaceMap.hasOwnProperty(g)&&(k=odf.Namespaces.namespaceMap[g]);return k};odf.Namespaces.lookupPrefix=function(g){var k=odf.Namespaces.prefixMap;return k.hasOwnProperty(g)?k[g]:null};odf.Namespaces.lookupNamespaceURI.lookupNamespaceURI=odf.Namespaces.lookupNamespaceURI; // Input 20 -xmldom.LSSerializerFilter=function(){}; -// Input 21 -"function"!==typeof Object.create&&(Object.create=function(g){var l=function(){};l.prototype=g;return new l}); -xmldom.LSSerializer=function(){function g(c){var g=c||{},b=function(b){var a={},e;for(e in b)b.hasOwnProperty(e)&&(a[b[e]]=e);return a}(c),l=[g],m=[b],d=0;this.push=function(){d+=1;g=l[d]=Object.create(g);b=m[d]=Object.create(b)};this.pop=function(){l[d]=void 0;m[d]=void 0;d-=1;g=l[d];b=m[d]};this.getLocalNamespaceDefinitions=function(){return b};this.getQName=function(d){var a=d.namespaceURI,e=0,h;if(!a)return d.localName;if(h=b[a])return h+":"+d.localName;do{h||!d.prefix?(h="ns"+e,e+=1):h=d.prefix; -if(g[h]===a)break;if(!g[h]){g[h]=a;b[a]=h;break}h=null}while(null===h);return h+":"+d.localName}}function l(c){return c.replace(/&/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")}function c(f,g){var b="",p=m.filter?m.filter.acceptNode(g):NodeFilter.FILTER_ACCEPT,r;if(p===NodeFilter.FILTER_ACCEPT&&g.nodeType===Node.ELEMENT_NODE){f.push();r=f.getQName(g);var d,k=g.attributes,a,e,h,q="",u;d="<"+r;a=k.length;for(e=0;e")}if(p===NodeFilter.FILTER_ACCEPT||p===NodeFilter.FILTER_SKIP){for(p=g.firstChild;p;)b+=c(f,p),p=p.nextSibling;g.nodeValue&&(b+=l(g.nodeValue))}r&&(b+="",f.pop());return b}var m=this;this.filter=null;this.writeToString=function(f,l){if(!f)return"";var b=new g(l);return c(b,f)}}; -// Input 22 -xmldom.RelaxNGParser=function(){function g(b,c){this.message=function(){c&&(b+=1===c.nodeType?" Element ":" Node ",b+=c.nodeName,c.nodeValue&&(b+=" with value '"+c.nodeValue+"'"),b+=".");return b}}function l(b){if(2>=b.e.length)return b;var c={name:b.name,e:b.e.slice(0,2)};return l({name:b.name,e:[c].concat(b.e.slice(2))})}function c(b){b=b.split(":",2);var c="",a;1===b.length?b=["",b[0]]:c=b[0];for(a in p)p[a]===c&&(b[0]=a);return b}function m(b,k){for(var a=0,e,h,f=b.name;b.e&&a=e.length)return b;0===c&&(c=0);for(var h=e.item(c);h.namespaceURI===d;){c+=1;if(c>=e.length)return b;h=e.item(c)}return h=p(a,b.attDeriv(a,e.item(c)),e,c+1)}function r(a,b,e){e.e[0].a?(a.push(e.e[0].text),b.push(e.e[0].a.ns)):r(a,b,e.e[0]);e.e[1].a?(a.push(e.e[1].text),b.push(e.e[1].a.ns)): -r(a,b,e.e[1])}var d="http://www.w3.org/2000/xmlns/",k,a,e,h,q,u,x,v,y,w,t={type:"notAllowed",nullable:!1,hash:"notAllowed",textDeriv:function(){return t},startTagOpenDeriv:function(){return t},attDeriv:function(){return t},startTagCloseDeriv:function(){return t},endTagDeriv:function(){return t}},s={type:"empty",nullable:!0,hash:"empty",textDeriv:function(){return t},startTagOpenDeriv:function(){return t},attDeriv:function(){return t},startTagCloseDeriv:function(){return s},endTagDeriv:function(){return t}}, -D={type:"text",nullable:!0,hash:"text",textDeriv:function(){return D},startTagOpenDeriv:function(){return t},attDeriv:function(){return t},startTagCloseDeriv:function(){return D},endTagDeriv:function(){return t}},A,B,M;k=m("choice",function(a,b){if(a===t)return b;if(b===t||a===b)return a},function(a,b){var e={},h;f(e,{p1:a,p2:b});b=a=void 0;for(h in e)e.hasOwnProperty(h)&&(void 0===a?a=e[h]:b=void 0===b?e[h]:k(b,e[h]));return function(a,b){return{type:"choice",p1:a,p2:b,nullable:a.nullable||b.nullable, -textDeriv:function(e,c){return k(a.textDeriv(e,c),b.textDeriv(e,c))},startTagOpenDeriv:c(function(e){return k(a.startTagOpenDeriv(e),b.startTagOpenDeriv(e))}),attDeriv:function(e,c){return k(a.attDeriv(e,c),b.attDeriv(e,c))},startTagCloseDeriv:g(function(){return k(a.startTagCloseDeriv(),b.startTagCloseDeriv())}),endTagDeriv:g(function(){return k(a.endTagDeriv(),b.endTagDeriv())})}}(a,b)});a=function(a,b,e){return function(){var c={},h=0;return function(d,k){var f=b&&b(d,k),g,l;if(void 0!==f)return f; -f=d.hash||d.toString();g=k.hash||k.toString();fNode.ELEMENT_NODE;){if(d!==Node.COMMENT_NODE&&(d!==Node.TEXT_NODE||!/^\s+$/.test(c.currentNode.nodeValue)))return[new g("Not allowed node of type "+ -d+".")];d=(f=c.nextSibling())?f.nodeType:0}if(!f)return[new g("Missing element "+b.names)];if(b.names&&-1===b.names.indexOf(n[f.namespaceURI]+":"+f.localName))return[new g("Found "+f.nodeName+" instead of "+b.names+".",f)];if(c.firstChild()){for(k=l(b.e[1],c,f);c.nextSibling();)if(d=c.currentNode.nodeType,!(c.currentNode&&c.currentNode.nodeType===Node.TEXT_NODE&&/^\s+$/.test(c.currentNode.nodeValue)||d===Node.COMMENT_NODE))return[new g("Spurious content.",c.currentNode)];if(c.parentNode()!==f)return[new g("Implementation error.")]}else k= -l(b.e[1],c,f);c.nextSibling();return k}var m,f,n;f=function(b,p,m,d){var k=b.name,a=null;if("text"===k)a:{for(var e=(b=p.currentNode)?b.nodeType:0;b!==m&&3!==e;){if(1===e){a=[new g("Element not allowed here.",b)];break a}e=(b=p.nextSibling())?b.nodeType:0}p.nextSibling();a=null}else if("data"===k)a=null;else if("value"===k)d!==b.text&&(a=[new g("Wrong value, should be '"+b.text+"', not '"+d+"'",m)]);else if("list"===k)a=null;else if("attribute"===k)a:{if(2!==b.e.length)throw"Attribute with wrong # of elements: "+ -b.e.length;k=b.localnames.length;for(a=0;a=k&&c.push(l(a.substring(b,d)))):"["===a[d]&&(0>=k&&(b=d+1),k+=1),d+=1;return d};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){};d=function(a,e,c){var d,k,g,l;for(d=0;d - - @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 . - - 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.AnnotationViewManager=function(g,l,c){function m(a){var b=a.node,c=a.end;a=r.createRange();c&&(a.setStart(b,b.childNodes.length),a.setEnd(c,0),c=d.getTextNodes(a,!1),c.forEach(function(a){var c=r.createElement("span");c.className="annotationHighlight";c.setAttribute("annotation",b.getAttributeNS(odf.Namespaces.officens,"name"));a.parentNode.insertBefore(c,a);c.appendChild(a)}));a.detach()}function f(a){var b=g.getSizer();a?(c.style.display="inline-block",b.style.paddingRight=k.getComputedStyle(c).width): -(c.style.display="none",b.style.paddingRight=0);g.refreshSize()}function n(){p.sort(function(a,b){return a.node.compareDocumentPosition(b.node)===Node.DOCUMENT_POSITION_FOLLOWING?-1:1})}function b(){var a;for(a=0;a=(l.getBoundingClientRect().top-n.bottom)/b?d.style.top=Math.abs(l.getBoundingClientRect().top-n.bottom)/b+20+"px":d.style.top="0px");k.style.left=f.getBoundingClientRect().width/b+"px";var f=k.style,l=k.getBoundingClientRect().left/b,m=k.getBoundingClientRect().top/b,n=d.getBoundingClientRect().left/b,r=d.getBoundingClientRect().top/b,t=0,s=0,t=n-l,t=t*t,s=r-m,s=s*s,l=Math.sqrt(t+s);f.width=l+"px";m=Math.asin((d.getBoundingClientRect().top- -k.getBoundingClientRect().top)/(b*parseFloat(k.style.width)));k.style.transform="rotate("+m+"rad)";k.style.MozTransform="rotate("+m+"rad)";k.style.WebkitTransform="rotate("+m+"rad)";k.style.msTransform="rotate("+m+"rad)"}}var p=[],r=l.ownerDocument,d=new odf.OdfUtils,k=runtime.getWindow();runtime.assert(Boolean(k),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=b;this.addAnnotation=function(a){f(!0);p.push({node:a.node,end:a.end});n();var e= -r.createElement("div"),c=r.createElement("div"),d=r.createElement("div"),k=r.createElement("div"),g=r.createElement("div"),l=a.node;e.className="annotationWrapper";l.parentNode.insertBefore(e,l);c.className="annotationNote";c.appendChild(l);g.className="annotationRemoveButton";c.appendChild(g);d.className="annotationConnector horizontal";k.className="annotationConnector angular";e.appendChild(c);e.appendChild(d);e.appendChild(k);a.end&&m(a);b()};this.forgetAnnotations=function(){for(;p.length;){var a= -p[0],b=p.indexOf(a),c=a.node,d=c.parentNode.parentNode;"div"===d.localName&&(d.parentNode.insertBefore(c,d),d.parentNode.removeChild(d));a=a.node.getAttributeNS(odf.Namespaces.officens,"name");a=r.querySelectorAll('span.annotationHighlight[annotation="'+a+'"]');d=c=void 0;for(c=0;c - - @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 . - - 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(){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 28 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.Namespaces=function(){function g(c){return l[c]||null}var l={db:"urn:oasis:names:tc:opendocument:xmlns:database:1.0",dc:"http://purl.org/dc/elements/1.1/",meta:"urn:oasis:names:tc:opendocument:xmlns:meta:1.0",dr3d:"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",draw:"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",chart:"urn:oasis:names:tc:opendocument:xmlns:chart:1.0",fo:"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",form:"urn:oasis:names:tc:opendocument:xmlns:form:1.0",numberns:"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", -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"},c;g.lookupNamespaceURI=g;c=function(){};c.forEachPrefix=function(c){for(var f in l)l.hasOwnProperty(f)&& -c(f,l[f])};c.resolvePrefix=g;c.lookupPrefix=function(c){var f,g;for(g in l)if(l.hasOwnProperty(g)&&l[g]===c){f=g;break}return f};c.namespaceMap=l;c.dbns="urn:oasis:names:tc:opendocument:xmlns:database:1.0";c.dcns="http://purl.org/dc/elements/1.1/";c.metans="urn:oasis:names:tc:opendocument:xmlns:meta:1.0";c.dr3dns="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0";c.drawns="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";c.chartns="urn:oasis:names:tc:opendocument:xmlns:chart:1.0";c.fons="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"; -c.formns="urn:oasis:names:tc:opendocument:xmlns:form:1.0";c.numberns="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0";c.officens="urn:oasis:names:tc:opendocument:xmlns:office:1.0";c.presentationns="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0";c.stylens="urn:oasis:names:tc:opendocument:xmlns:style:1.0";c.svgns="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";c.tablens="urn:oasis:names:tc:opendocument:xmlns:table:1.0";c.textns="urn:oasis:names:tc:opendocument:xmlns:text:1.0"; -c.xlinkns="http://www.w3.org/1999/xlink";c.xmlns="http://www.w3.org/XML/1998/namespace";return c}(); -// Input 29 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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(){function g(a,b){for(var c=A[a.localName],e=c&&c[a.namespaceURI],d=e?e.length:0,h,c=0;c @@ -589,19 +371,19 @@ Node.ELEMENT_NODE){var d=b,h=e,f=d.getAttributeNS(q,"name"),k=void 0;f?k=q:(f=d. @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===s}function l(a){return"frame"===(a&&a.localName)&&a.namespaceURI===s&&"as-char"===a.getAttributeNS(t,"anchor-type")}function c(a){var b=a&&a.localName;return("p"===b||"h"===b)&&a.namespaceURI===t}function m(a){for(;a&&!c(a);)a=a.parentNode;return a}function f(a){return/^[ \t\r\n]+$/.test(a)}function n(a){var b=a&&a.localName;return/^(span|p|h|a|meta)$/.test(b)&&a.namespaceURI===t||"span"===b&&"annotationHighlight"=== -a.className?!0:!1}function b(a){var b=a&&a.localName,c;c=!1;b&&(c=a.namespaceURI,c=c===t?"s"===b||"tab"===b||"line-break"===b:l(a));return c}function p(a){var b=a&&a.localName,c=!1;b&&(a=a.namespaceURI,a===t&&(c="s"===b));return c}function r(a){for(;null!==a.firstChild&&n(a);)a=a.firstChild;return a}function d(a){for(;null!==a.lastChild&&n(a);)a=a.lastChild;return a}function k(a){for(;!c(a)&&null===a.previousSibling;)a=a.parentNode;return c(a)?null:d(a.previousSibling)}function a(a){for(;!c(a)&&null=== -a.nextSibling;)a=a.parentNode;return c(a)?null:r(a.nextSibling)}function e(a){for(var c=!1;a;)if(a.nodeType===Node.TEXT_NODE)if(0===a.length)a=k(a);else return!f(a.data.substr(a.length-1,1));else b(a)?(c=!1===p(a),a=null):a=k(a);return c}function h(c){var e=!1;for(c=c&&r(c);c;){if(c.nodeType===Node.TEXT_NODE&&0a.value||"%"===a.unit)?null:a}function y(a){return(a=x(a))&&"%"!==a.unit?null:a}function w(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 t=odf.Namespaces.textns,s=odf.Namespaces.drawns,D=/^\s*$/,A=new core.DomUtils;this.isImage=g;this.isCharacterFrame=l;this.isTextSpan=function(a){return"span"===(a&&a.localName)&&a.namespaceURI===t};this.isParagraph=c;this.getParagraphElement=m;this.isWithinTrackedChanges=function(a,b){for(;a&&a!==b;){if(a.namespaceURI=== -t&&"tracked-changes"===a.localName)return!0;a=a.parentNode}return!1};this.isListItem=function(a){return"list-item"===(a&&a.localName)&&a.namespaceURI===t};this.isLineBreak=function(a){return"line-break"===(a&&a.localName)&&a.namespaceURI===t};this.isODFWhitespace=f;this.isGroupingElement=n;this.isCharacterElement=b;this.isSpaceElement=p;this.firstChild=r;this.lastChild=d;this.previousNode=k;this.nextNode=a;this.scanLeftForNonSpace=e;this.lookLeftForCharacter=function(a){var c;c=0;a.nodeType===Node.TEXT_NODE&& -0=b.value||"%"===b.unit)?null:b;return b||y(a)};this.parseFoLineHeight=function(a){return v(a)||y(a)};this.getImpactedParagraphs=function(a){var b= -a.commonAncestorContainer,e=[];for(b.nodeType===Node.ELEMENT_NODE&&(e=A.getElementsByTagNameNS(b,t,"p").concat(A.getElementsByTagNameNS(b,t,"h")));b&&!c(b);)b=b.parentNode;b&&e.push(b);return e.filter(function(b){return A.rangeIntersectsNode(a,b)})};this.getTextNodes=function(a,b){var c=a.startContainer.ownerDocument.createRange(),e;e=A.getNodesInRange(a,function(e){c.selectNodeContents(e);if(e.nodeType===Node.TEXT_NODE){if(b&&A.rangesIntersect(a,c)||A.containsRange(a,c))return Boolean(m(e)&&(!f(e.textContent)|| -u(e,0)))?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}else if(A.rangesIntersect(a,c)&&w(e))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});c.detach();return e};this.getTextElements=function(a,c,e){var d=a.startContainer.ownerDocument.createRange(),h;h=A.getNodesInRange(a,function(h){d.selectNodeContents(h);if(b(h.parentNode))return NodeFilter.FILTER_REJECT;if(h.nodeType===Node.TEXT_NODE){if(c&&A.rangesIntersect(a,d)||A.containsRange(a,d))if(e||Boolean(m(h)&&(!f(h.textContent)|| -u(h,0))))return NodeFilter.FILTER_ACCEPT}else if(b(h)){if(c&&A.rangesIntersect(a,d)||A.containsRange(a,d))return NodeFilter.FILTER_ACCEPT}else if(w(h)||n(h))return NodeFilter.FILTER_SKIP;return NodeFilter.FILTER_REJECT});d.detach();return h};this.getParagraphElements=function(a){var b=a.startContainer.ownerDocument.createRange(),e;e=A.getNodesInRange(a,function(e){b.selectNodeContents(e);if(c(e)){if(A.rangesIntersect(a,b))return NodeFilter.FILTER_ACCEPT}else if(w(e)||n(e))return NodeFilter.FILTER_SKIP; -return NodeFilter.FILTER_REJECT});b.detach();return e};this.getImageElements=function(a){var b=a.startContainer.ownerDocument.createRange(),c;c=A.getNodesInRange(a,function(c){b.selectNodeContents(c);return g(c)&&A.containsRange(a,b)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP});b.detach();return c}}; -// Input 31 +odf.OdfUtils=function(){function g(a){return"image"===(a&&a.localName)&&a.namespaceURI===s}function k(a){return null!==a&&a.nodeType===Node.ELEMENT_NODE&&"frame"===a.localName&&a.namespaceURI===s&&"as-char"===a.getAttributeNS(t,"anchor-type")}function e(a){var c=a&&a.localName;return("p"===c||"h"===c)&&a.namespaceURI===t}function n(a){for(;a&&!e(a);)a=a.parentNode;return a}function m(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===t||"span"===c&&"annotationHighlight"===a.className}function b(a){var c=a&&a.localName,b;b=!1;c&&(b=a.namespaceURI,b=b===t?"s"===c||"tab"===c||"line-break"===c:k(a));return b}function h(a){var c=a&&a.localName,b=!1;c&&(a=a.namespaceURI,a===t&&(b="s"===c));return b}function r(a){for(;null!==a.firstChild&&q(a);)a=a.firstChild;return a}function d(a){for(;null!==a.lastChild&&q(a);)a=a.lastChild;return a}function f(a){for(;!e(a)&&null===a.previousSibling;)a= +a.parentNode;return e(a)?null:d(a.previousSibling)}function a(a){for(;!e(a)&&null===a.nextSibling;)a=a.parentNode;return e(a)?null:r(a.nextSibling)}function c(a){for(var c=!1;a;)if(a.nodeType===Node.TEXT_NODE)if(0===a.length)a=f(a);else return!m(a.data.substr(a.length-1,1));else b(a)?(c=!1===h(a),a=null):a=f(a);return c}function p(c){var d=!1,f;for(c=c&&r(c);c;){f=c.nodeType===Node.TEXT_NODE?c.length:0;if(0a.value||"%"===a.unit)?null:a}function y(a){return(a=B(a))&&"%"!==a.unit?null:a}function v(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 t=odf.Namespaces.textns,s=odf.Namespaces.drawns,N=/^\s*$/,z=new core.DomUtils;this.isImage=g;this.isCharacterFrame=k;this.isTextSpan=function(a){return"span"===(a&&a.localName)&&a.namespaceURI===t};this.isParagraph= +e;this.getParagraphElement=n;this.isWithinTrackedChanges=function(a,c){for(;a&&a!==c;){if(a.namespaceURI===t&&"tracked-changes"===a.localName)return!0;a=a.parentNode}return!1};this.isListItem=function(a){return"list-item"===(a&&a.localName)&&a.namespaceURI===t};this.isLineBreak=function(a){return"line-break"===(a&&a.localName)&&a.namespaceURI===t};this.isODFWhitespace=m;this.isGroupingElement=q;this.isCharacterElement=b;this.isSpaceElement=h;this.firstChild=r;this.lastChild=d;this.previousNode=f; +this.nextNode=a;this.scanLeftForNonSpace=c;this.lookLeftForCharacter=function(a){var d,e=d=0;a.nodeType===Node.TEXT_NODE&&(e=a.length);0=c.value||"%"===c.unit)?null:c;return c||y(a)};this.parseFoLineHeight=function(a){return w(a)||y(a)};this.getImpactedParagraphs=function(a){var c,b,d;c=a.commonAncestorContainer;var f=[],p=[];for(c.nodeType===Node.ELEMENT_NODE&&(f=z.getElementsByTagNameNS(c,t,"p").concat(z.getElementsByTagNameNS(c,t,"h")));c&&!e(c);)c=c.parentNode;c&&f.push(c);b=f.length;for(c=0;c @@ -639,9 +421,249 @@ return NodeFilter.FILTER_REJECT});b.detach();return e};this.getImageElements=fun @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -runtime.loadClass("odf.OdfUtils"); -odf.TextSerializer=function(){function g(m){var f="",n=l.filter?l.filter.acceptNode(m):NodeFilter.FILTER_ACCEPT,b=m.nodeType,p;if(n===NodeFilter.FILTER_ACCEPT||n===NodeFilter.FILTER_SKIP)for(p=m.firstChild;p;)f+=g(p),p=p.nextSibling;n===NodeFilter.FILTER_ACCEPT&&(b===Node.ELEMENT_NODE&&c.isParagraph(m)?f+="\n":b===Node.TEXT_NODE&&m.textContent&&(f+=m.textContent));return f}var l=this,c=new odf.OdfUtils;this.filter=null;this.writeToString=function(c){if(!c)return"";c=g(c);"\n"===c[c.length-1]&&(c= -c.substr(0,c.length-1));return c}}; +ops.Server=function(){};ops.Server.prototype.connect=function(g,k){};ops.Server.prototype.networkStatus=function(){};ops.Server.prototype.login=function(g,k,e,n){};ops.Server.prototype.joinSession=function(g,k,e,n){};ops.Server.prototype.leaveSession=function(g,k,e,n){};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(b,a,c){return-1!==b&&(b=h&&c.push(k(b.substring(a,d)))):"["===b[d]&&(0>=h&&(a=d+1),h+=1),d+=1;return d};r=function(d,a,c){var e,l,g,k;for(e=0;e + + @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 . + + 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(){};gui.AnnotatableCanvas.prototype.refreshSize=function(){};gui.AnnotatableCanvas.prototype.getZoomLevel=function(){};gui.AnnotatableCanvas.prototype.getSizer=function(){}; +gui.AnnotationViewManager=function(g,k,e){function n(a){var c=a.node,b=a.end;a=r.createRange();b&&(a.setStart(c,c.childNodes.length),a.setEnd(b,0),b=d.getTextNodes(a,!1),b.forEach(function(a){var b=r.createElement("span"),d=c.getAttributeNS(odf.Namespaces.officens,"name");b.className="annotationHighlight";b.setAttribute("annotation",d);a.parentNode.insertBefore(b,a);b.appendChild(a)}));a.detach()}function m(a){var c=g.getSizer();a?(e.style.display="inline-block",c.style.paddingRight=f.getComputedStyle(e).width): +(e.style.display="none",c.style.paddingRight=0);g.refreshSize()}function q(){h.sort(function(a,c){return a.node.compareDocumentPosition(c.node)===Node.DOCUMENT_POSITION_FOLLOWING?-1:1})}function b(){var a;for(a=0;a=(m.getBoundingClientRect().top-n.bottom)/c?b.style.top=Math.abs(m.getBoundingClientRect().top-n.bottom)/c+20+"px":b.style.top="0px");f.style.left=d.getBoundingClientRect().width/c+"px";var d=f.style,m=f.getBoundingClientRect().left/c,k=f.getBoundingClientRect().top/c,n=b.getBoundingClientRect().left/c,q=b.getBoundingClientRect().top/c,r=0,s=0,r=n-m,r=r*r,s=q-k,s=s*s,m=Math.sqrt(r+s);d.width= +m+"px";k=Math.asin((b.getBoundingClientRect().top-f.getBoundingClientRect().top)/(c*parseFloat(f.style.width)));f.style.transform="rotate("+k+"rad)";f.style.MozTransform="rotate("+k+"rad)";f.style.WebkitTransform="rotate("+k+"rad)";f.style.msTransform="rotate("+k+"rad)"}}var h=[],r=k.ownerDocument,d=new odf.OdfUtils,f=runtime.getWindow();runtime.assert(Boolean(f),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=b;this.addAnnotation=function(a){m(!0); +h.push({node:a.node,end:a.end});q();var c=r.createElement("div"),d=r.createElement("div"),f=r.createElement("div"),e=r.createElement("div"),g=r.createElement("div"),k=a.node;c.className="annotationWrapper";k.parentNode.insertBefore(c,k);d.className="annotationNote";d.appendChild(k);g.className="annotationRemoveButton";d.appendChild(g);f.className="annotationConnector horizontal";e.className="annotationConnector angular";c.appendChild(d);c.appendChild(f);c.appendChild(e);a.end&&n(a);b()};this.forgetAnnotations= +function(){for(;h.length;){var a=h[0],c=h.indexOf(a),b=a.node,d=b.parentNode.parentNode;"div"===d.localName&&(d.parentNode.insertBefore(b,d),d.parentNode.removeChild(d));a=a.node.getAttributeNS(odf.Namespaces.officens,"name");a=r.querySelectorAll('span.annotationHighlight[annotation="'+a+'"]');d=b=void 0;for(b=0;b + + @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 . + + 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.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,k){function e(){w.setUnfilteredPosition(g.getNode(),0);return w}function n(a,c){var b,d=null;a&&0=c?d=m(a,c-1,b,!0):a.nodeType===Node.TEXT_NODE&& +0a?-1:1;for(a=Math.abs(a);0p?g.previousPosition():g.nextPosition());)if(X.check(),h.acceptPosition(g)===t&&(q+=1,n=g.container(),w=m(n,g.unfilteredDomOffset(),H),w.top!==I)){if(w.top!==Y&&Y!==I)break;Y=w.top;w=Math.abs(C-w.left);if(null===r||wa?(b=h.previousPosition,d=-1):(b=h.nextPosition,d=1);for(f=m(h.container(),h.unfilteredDomOffset(),n);b.call(h);)if(c.acceptPosition(h)===t){if(u.getParagraphElement(h.getCurrentNode())!==p)break;l=m(h.container(),h.unfilteredDomOffset(),n);if(l.bottom!==f.bottom&&(f=l.top>=f.top&&l.bottomf.bottom,!f))break;g+= +d;f=l}n.detach();return g}function l(a,c,b){runtime.assert(null!==a,"SelectionMover.countStepsToPosition called with element===null");var d=e(),f=d.container(),l=d.unfilteredDomOffset(),h=0,p=new core.LoopWatchDog(1E4);for(d.setUnfilteredPosition(a,c);b.acceptPosition(d)!==t&&d.previousPosition();)p.check();a=d.container();runtime.assert(Boolean(a),"SelectionMover.countStepsToPosition: positionIterator.container() returned null");c=d.unfilteredDomOffset();for(d.setUnfilteredPosition(f,l);b.acceptPosition(d)!== +t&&d.previousPosition();)p.check();f=B.comparePoints(a,c,d.container(),d.unfilteredDomOffset());if(0>f)for(;d.nextPosition()&&(p.check(),b.acceptPosition(d)===t&&(h+=1),d.container()!==a||d.unfilteredDomOffset()!==c););else if(0 + + @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 . + @licend + + @source: http://www.webodf.org/ + @source: https://github.com/kogmbh/WebODF/ +*/ +runtime.loadClass("odf.Namespaces");runtime.loadClass("core.DomUtils"); +odf.MetadataManager=function(g){function k(m,k){m&&(Object.keys(m).forEach(function(b){n[b]=m[b]}),e.mapKeyValObjOntoNode(g,m,odf.Namespaces.lookupNamespaceURI));k&&(k.forEach(function(b){delete n[b]}),e.removeKeyElementsFromNode(g,k,odf.Namespaces.lookupNamespaceURI))}var e=new core.DomUtils,n={};this.setMetadata=k;this.incrementEditingCycles=function(){var e=parseInt(n["meta:editing-cycles"]||0,10)+1;k({"meta:editing-cycles":e},null)};n=e.getKeyValRepresentationOfNode(g,odf.Namespaces.lookupPrefix)}; +// Input 30 +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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(){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 31 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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(g){this.derivedStyles={};this.element=g}; +odf.Style2CSS=function(){function g(a){var c,b,d,f={};if(!a)return f;for(a=a.firstElementChild;a;){if(b=a.namespaceURI!==l||"style"!==a.localName&&"default-style"!==a.localName?a.namespaceURI===w&&"list-style"===a.localName?"list":a.namespaceURI!==l||"page-layout"!==a.localName&&"default-page-layout"!==a.localName?void 0:"page":a.getAttributeNS(l,"family"))(c=a.getAttributeNS(l,"name"))||(c=""),f.hasOwnProperty(b)?d=f[b]:f[b]=d={},d[c]=a;a=a.nextElementSibling}return f}function k(a,c){if(a.hasOwnProperty(c))return a[c]; +var b,d=null;for(b in a)if(a.hasOwnProperty(b)&&(d=k(a[b].derivedStyles,c)))break;return d}function e(a,c,b){var d,f,h;if(!c.hasOwnProperty(a))return null;d=new odf.StyleTreeNode(c[a]);f=d.element.getAttributeNS(l,"parent-style-name");h=null;f&&(h=k(b,f)||e(f,c,b));h?h.derivedStyles[a]=d:b[a]=d;delete c[a];return d}function n(a,c){for(var b in a)a.hasOwnProperty(b)&&e(b,a,c)}function m(a,c,b){var d=[];b=b.derivedStyles;var f;var e=t[a],l;void 0===e?c=null:(l=c?"["+e+'|style-name="'+c+'"]':"","presentation"=== +e&&(e="draw",l=c?'[presentation|style-name="'+c+'"]':""),c=e+"|"+s[a].join(l+","+e+"|")+l);null!==c&&d.push(c);for(f in b)b.hasOwnProperty(f)&&(c=m(a,f,b[f]),d=d.concat(c));return d}function q(a,c,b){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==c||a.localName!==b);)a=a.nextElementSibling;return a}function b(a,c){var b="",d,f,e;for(d=0;dh.value&&(e="0.75pt"+p)}f[2]&&(b+=f[2]+":"+e+";")}return b}function h(a){return(a=q(a,l,"text-properties"))?O.parseFoFontSize(a.getAttributeNS(c,"font-size")):null}function r(a,c,b,d){return c+c+b+b+d+d}function d(a,b,d,f){b='text|list[text|style-name="'+b+'"]';var e=d.getAttributeNS(w,"level");d=q(d,l,"list-level-properties");d=q(d,l,"list-level-label-alignment");var h,p;d&&(h=d.getAttributeNS(c,"text-indent"),p=d.getAttributeNS(c, +"margin-left"));h||(h="-0.6cm");d="-"===h.charAt(0)?h.substring(1):"-"+h;for(e=e&&parseInt(e,10);1 text|list-item > text|list",e-=1;if(p){e=b+" > text|list-item > *:not(text|list):first-child";e+="{";e=e+("margin-left:"+p+";")+"}";try{a.insertRule(e,a.cssRules.length)}catch(g){runtime.log("cannot load rule: "+e)}}f=b+" > text|list-item > *:not(text|list):first-child:before{"+f+";";f=f+"counter-increment:list;"+("margin-left:"+h+";");f+="width:"+d+";";f+="display:inline-block}";try{a.insertRule(f, +a.cssRules.length)}catch(m){runtime.log("cannot load rule: "+f)}}function f(e,g,k,n){if("list"===g)for(var u=n.element.firstChild,s,t;u;){if(u.namespaceURI===w)if(s=u,"list-level-style-number"===u.localName){var G=s;t=G.getAttributeNS(l,"num-format");var T=G.getAttributeNS(l,"num-suffix")||"",G=G.getAttributeNS(l,"num-prefix")||"",$={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},W="";G&&(W+=' "'+G+'"');W=$.hasOwnProperty(t)?W+(" counter(list, "+$[t]+")"):t?W+(' "'+t+ +'"'):W+" ''";t="content:"+W+' "'+T+'"';d(e,k,s,t)}else"list-level-style-image"===u.localName?(t="content: none;",d(e,k,s,t)):"list-level-style-bullet"===u.localName&&(t="content: '"+s.getAttributeNS(w,"bullet-char")+"';",d(e,k,s,t));u=u.nextSibling}else if("page"===g){if(t=n.element,G=T=k="",u=q(t,l,"page-layout-properties"))if(s=t.getAttributeNS(l,"name"),k+=b(u,ja),(T=q(u,l,"background-image"))&&(G=T.getAttributeNS(y,"href"))&&(k=k+("background-image: url('odfkit:"+G+"');")+b(T,z)),"presentation"=== +ba)for(t=(t=q(t.parentNode.parentElement,p,"master-styles"))&&t.firstElementChild;t;){if(t.namespaceURI===l&&"master-page"===t.localName&&t.getAttributeNS(l,"page-layout-name")===s){G=t.getAttributeNS(l,"name");T="draw|page[draw|master-page-name="+G+"] {"+k+"}";G="office|body, draw|page[draw|master-page-name="+G+"] {"+b(u,ka)+" }";try{e.insertRule(T,e.cssRules.length),e.insertRule(G,e.cssRules.length)}catch(da){throw da;}}t=t.nextElementSibling}else if("text"===ba){T="office|text {"+k+"}";G="office|body {width: "+ +u.getAttributeNS(c,"page-width")+";}";try{e.insertRule(T,e.cssRules.length),e.insertRule(G,e.cssRules.length)}catch(S){throw S;}}}else{k=m(g,k,n).join(",");u="";if(s=q(n.element,l,"text-properties")){G=s;t=W="";T=1;s=""+b(G,N);$=G.getAttributeNS(l,"text-underline-style");"solid"===$&&(W+=" underline");$=G.getAttributeNS(l,"text-line-through-style");"solid"===$&&(W+=" line-through");W.length&&(s+="text-decoration:"+W+";");if(W=G.getAttributeNS(l,"font-name")||G.getAttributeNS(c,"font-family"))$=Z[W], +s+="font-family: "+($||W)+";";$=G.parentElement;if(G=h($)){for(;$;){if(G=h($)){if("%"!==G.unit){t="font-size: "+G.value*T+G.unit+";";break}T*=G.value/100}G=$;W=$="";$=null;"default-style"===G.localName?$=null:($=G.getAttributeNS(l,"parent-style-name"),W=G.getAttributeNS(l,"family"),$=C.getODFElementsWithXPath(K,$?"//style:*[@style:name='"+$+"'][@style:family='"+W+"']":"//style:default-style[@style:family='"+W+"']",odf.Namespaces.lookupNamespaceURI)[0])}t||(t="font-size: "+parseFloat(I)*T+Y.getUnits(I)+ +";");s+=t}u+=s}if(s=q(n.element,l,"paragraph-properties"))t=s,s=""+b(t,x),(T=q(t,l,"background-image"))&&(G=T.getAttributeNS(y,"href"))&&(s=s+("background-image: url('odfkit:"+G+"');")+b(T,z)),(t=t.getAttributeNS(c,"line-height"))&&"normal"!==t&&(t=O.parseFoLineHeight(t),s="%"!==t.unit?s+("line-height: "+t.value+t.unit+";"):s+("line-height: "+t.value/100+";")),u+=s;if(s=q(n.element,l,"graphic-properties"))G=s,s=""+b(G,R),t=G.getAttributeNS(a,"opacity"),T=G.getAttributeNS(a,"fill"),G=G.getAttributeNS(a, +"fill-color"),"solid"===T||"hatch"===T?G&&"none"!==G?(t=isNaN(parseFloat(t))?1:parseFloat(t)/100,T=G.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,r),(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)&&(s+="background-color: rgba("+G.r+","+G.g+","+G.b+","+t+");")):s+="background: none;":"none"===T&&(s+="background: none;"),u+=s;if(s=q(n.element,l,"drawing-page-properties"))t=""+b(s,R),"true"===s.getAttributeNS(v,"background-visible")&& +(t+="background: none;"),u+=t;if(s=q(n.element,l,"table-cell-properties"))s=""+b(s,F),u+=s;if(s=q(n.element,l,"table-row-properties"))s=""+b(s,P),u+=s;if(s=q(n.element,l,"table-column-properties"))s=""+b(s,U),u+=s;if(s=q(n.element,l,"table-properties"))t=s,s=""+b(t,A),t=t.getAttributeNS(B,"border-model"),"collapsing"===t?s+="border-collapse:collapse;":"separating"===t&&(s+="border-collapse:separate;"),u+=s;if(0!==u.length)try{e.insertRule(k+"{"+u+"}",e.cssRules.length)}catch(ga){throw ga;}}for(var D in n.derivedStyles)n.derivedStyles.hasOwnProperty(D)&& +f(e,g,D,n.derivedStyles[D])}var a=odf.Namespaces.drawns,c=odf.Namespaces.fons,p=odf.Namespaces.officens,l=odf.Namespaces.stylens,u=odf.Namespaces.svgns,B=odf.Namespaces.tablens,w=odf.Namespaces.textns,y=odf.Namespaces.xlinkns,v=odf.Namespaces.presentationns,t={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"]},N=[[c,"color","color"],[c,"background-color","background-color"],[c,"font-weight","font-weight"],[c,"font-style","font-style"]],z=[[l,"repeat","background-repeat"]],x=[[c,"background-color","background-color"],[c,"text-align","text-align"],[c,"text-indent","text-indent"],[c,"padding","padding"],[c,"padding-left","padding-left"],[c,"padding-right","padding-right"],[c,"padding-top","padding-top"],[c,"padding-bottom","padding-bottom"],[c,"border-left","border-left"],[c,"border-right", +"border-right"],[c,"border-top","border-top"],[c,"border-bottom","border-bottom"],[c,"margin","margin"],[c,"margin-left","margin-left"],[c,"margin-right","margin-right"],[c,"margin-top","margin-top"],[c,"margin-bottom","margin-bottom"],[c,"border","border"]],R=[[c,"background-color","background-color"],[c,"min-height","min-height"],[a,"stroke","border"],[u,"stroke-color","border-color"],[u,"stroke-width","border-width"],[c,"border","border"],[c,"border-left","border-left"],[c,"border-right","border-right"], +[c,"border-top","border-top"],[c,"border-bottom","border-bottom"]],F=[[c,"background-color","background-color"],[c,"border-left","border-left"],[c,"border-right","border-right"],[c,"border-top","border-top"],[c,"border-bottom","border-bottom"],[c,"border","border"]],U=[[l,"column-width","width"]],P=[[l,"row-height","height"],[c,"keep-together",null]],A=[[l,"width","width"],[c,"margin-left","margin-left"],[c,"margin-right","margin-right"],[c,"margin-top","margin-top"],[c,"margin-bottom","margin-bottom"]], +ja=[[c,"background-color","background-color"],[c,"padding","padding"],[c,"padding-left","padding-left"],[c,"padding-right","padding-right"],[c,"padding-top","padding-top"],[c,"padding-bottom","padding-bottom"],[c,"border","border"],[c,"border-left","border-left"],[c,"border-right","border-right"],[c,"border-top","border-top"],[c,"border-bottom","border-bottom"],[c,"margin","margin"],[c,"margin-left","margin-left"],[c,"margin-right","margin-right"],[c,"margin-top","margin-top"],[c,"margin-bottom", +"margin-bottom"]],ka=[[c,"page-width","width"],[c,"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,ba,K,I,C=xmldom.XPath,Y=new core.CSSUnits;this.style2css=function(a,c,b,d,e){for(var l,h,p,k;c.cssRules.length;)c.deleteRule(c.cssRules.length-1);l=null;d&&(l=d.ownerDocument,K=d.parentNode);e&&(l=e.ownerDocument,K=e.parentNode);if(l)for(k in odf.Namespaces.forEachPrefix(function(a,b){h="@namespace "+ +a+" url("+b+");";try{c.insertRule(h,c.cssRules.length)}catch(d){}}),Z=b,ba=a,I=runtime.getWindow().getComputedStyle(document.body,null).getPropertyValue("font-size")||"12pt",a=g(d),d=g(e),e={},t)if(t.hasOwnProperty(k))for(p in b=e[k]={},n(a[k],b),n(d[k],b),b)b.hasOwnProperty(p)&&f(c,k,p,b[p])}}; // Input 32 /* @@ -680,101 +702,77 @@ c.substr(0,c.length-1));return c}}; @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,c){function m(b){function c(a,b){return"object"===typeof a&&"object"===typeof b?Object.keys(a).every(function(d){return c(a[d],b[d])}):a===b}this.isStyleApplied=function(a){a=l.getAppliedStylesForElement(a);return c(b,a)}}function f(b){var f={};this.applyStyleToContainer=function(a){var e;e=a.getAttributeNS(p,"style-name");var h=a.ownerDocument;e=e||"";if(!f.hasOwnProperty(e)){var m=e,n;n=e?l.createDerivedStyleObject(e,"text",b):b;h=h.createElementNS(r,"style:style"); -l.updateStyle(h,n);h.setAttributeNS(r,"style:name",g.generateStyleName());h.setAttributeNS(r,"style:family","text");h.setAttributeNS("urn:webodf:names:scope","scope","document-content");c.appendChild(h);f[m]=h}e=f[e].getAttributeNS(r,"name");a.setAttributeNS(p,"text:style-name",e)}}function n(c,f){var a=c.ownerDocument,e=c.parentNode,h,g,l=new core.LoopWatchDog(1E4);g=[];"span"!==e.localName||e.namespaceURI!==p?(h=a.createElementNS(p,"text:span"),e.insertBefore(h,c),e=!1):(c.previousSibling&&!b.rangeContainsNode(f, -e.firstChild)?(h=e.cloneNode(!1),e.parentNode.insertBefore(h,e.nextSibling)):h=e,e=!0);g.push(c);for(a=c.nextSibling;a&&b.rangeContainsNode(f,a);)l.check(),g.push(a),a=a.nextSibling;g.forEach(function(a){a.parentNode!==h&&h.appendChild(a)});if(a&&e)for(g=h.cloneNode(!1),h.parentNode.insertBefore(g,h.nextSibling);a;)l.check(),e=a.nextSibling,g.appendChild(a),a=e;return h}var b=new core.DomUtils,p=odf.Namespaces.textns,r=odf.Namespaces.stylens;this.applyStyle=function(b,c,a){var e={},h,g,l,p;runtime.assert(a&& -a["style:text-properties"],"applyStyle without any text properties");e["style:text-properties"]=a["style:text-properties"];l=new f(e);p=new m(e);b.forEach(function(a){h=p.isStyleApplied(a);!1===h&&(g=n(a,c),l.applyStyleToContainer(g))})}}; +runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.Namespaces"); +odf.StyleInfo=function(){function g(a,c){var b,d,f,e,l,h=0;if(b=x[a.localName])if(f=b[a.namespaceURI])h=f.length;for(b=0;b - - @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 . - - 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.Style2CSS=function(){function g(a){var b={},c,e;if(!a)return b;for(a=a.firstChild;a;){if(e=a.namespaceURI!==q||"style"!==a.localName&&"default-style"!==a.localName?a.namespaceURI===v&&"list-style"===a.localName?"list":a.namespaceURI!==q||"page-layout"!==a.localName&&"default-page-layout"!==a.localName?void 0:"page":a.getAttributeNS(q,"family"))(c=a.getAttributeNS&&a.getAttributeNS(q,"name"))||(c=""),e=b[e]=b[e]||{},e[c]=a;a=a.nextSibling}return b}function l(a,b){if(!b||!a)return null;if(a[b])return a[b]; -var c,e;for(c in a)if(a.hasOwnProperty(c)&&(e=l(a[c].derivedStyles,b)))return e;return null}function c(a,b,e){var d=b[a],h,f;d&&(h=d.getAttributeNS(q,"parent-style-name"),f=null,h&&(f=l(e,h),!f&&b[h]&&(c(h,b,e),f=b[h],b[h]=null)),f?(f.derivedStyles||(f.derivedStyles={}),f.derivedStyles[a]=d):e[a]=d)}function m(a,b){for(var e in a)a.hasOwnProperty(e)&&(c(e,a,b),a[e]=null)}function f(a,b){var c=t[a],e;if(null===c)return null;e=b?"["+c+'|style-name="'+b+'"]':"";"presentation"===c&&(c="draw",e=b?'[presentation|style-name="'+ -b+'"]':"");return c+"|"+s[a].join(e+","+c+"|")+e}function n(a,b,c){var e=[],d,h;e.push(f(a,b));for(d in c.derivedStyles)if(c.derivedStyles.hasOwnProperty(d))for(h in b=n(a,d,c.derivedStyles[d]),b)b.hasOwnProperty(h)&&e.push(b[h]);return e}function b(a,b,c){if(!a)return null;for(a=a.firstChild;a;){if(a.namespaceURI===b&&a.localName===c)return b=a;a=a.nextSibling}return null}function p(a,b){var c="",e,d;for(e in b)if(b.hasOwnProperty(e)&&(e=b[e],d=a.getAttributeNS(e[0],e[1]))){d=d.trim();if(R.hasOwnProperty(e[1])){var h= -d.indexOf(" "),f=void 0,k=void 0;-1!==h?(f=d.substring(0,h),k=d.substring(h)):(f=d,k="");(f=ba.parseLength(f))&&"pt"===f.unit&&0.75>f.value&&(d="0.75pt"+k)}e[2]&&(c+=e[2]+":"+d+";")}return c}function r(a){return(a=b(a,q,"text-properties"))?ba.parseFoFontSize(a.getAttributeNS(h,"font-size")):null}function d(a){a=a.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,function(a,b,c,e){return b+b+c+c+e+e});return(a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(a))?{r:parseInt(a[1],16),g:parseInt(a[2],16),b:parseInt(a[3], -16)}:null}function k(a,b,c,e){b='text|list[text|style-name="'+b+'"]';var d=c.getAttributeNS(v,"level"),h;c=ba.getFirstNonWhitespaceChild(c);c=ba.getFirstNonWhitespaceChild(c);var f;c&&(h=c.attributes,f=h["fo:text-indent"]?h["fo:text-indent"].value:void 0,h=h["fo:margin-left"]?h["fo:margin-left"].value:void 0);f||(f="-0.6cm");c="-"===f.charAt(0)?f.substring(1):"-"+f;for(d=d&&parseInt(d,10);1 text|list-item > text|list",d-=1;d=b+" > text|list-item > *:not(text|list):first-child";void 0!== -h&&(h=d+"{margin-left:"+h+";}",a.insertRule(h,a.cssRules.length));e=b+" > text|list-item > *:not(text|list):first-child:before{"+e+";";e+="counter-increment:list;";e+="margin-left:"+f+";";e+="width:"+c+";";e+="display:inline-block}";try{a.insertRule(e,a.cssRules.length)}catch(k){throw k;}}function a(c,f,g,l){if("list"===f)for(var s=l.firstChild,m,t;s;){if(s.namespaceURI===v)if(m=s,"list-level-style-number"===s.localName){var u=m;t=u.getAttributeNS(q,"num-format");var P=u.getAttributeNS(q,"num-suffix"), -L={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},u=u.getAttributeNS(q,"num-prefix")||"",u=L.hasOwnProperty(t)?u+(" counter(list, "+L[t]+")"):t?u+("'"+t+"';"):u+" ''";P&&(u+=" '"+P+"'");t="content: "+u+";";k(c,g,m,t)}else"list-level-style-image"===s.localName?(t="content: none;",k(c,g,m,t)):"list-level-style-bullet"===s.localName&&(t="content: '"+m.getAttributeNS(v,"bullet-char")+"';",k(c,g,m,t));s=s.nextSibling}else if("page"===f)if(P=m=g="",s=l.getElementsByTagNameNS(q, -"page-layout-properties")[0],m=s.parentNode.parentNode.parentNode.masterStyles,P="",g+=p(s,$),t=s.getElementsByTagNameNS(q,"background-image"),0 @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. + 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 WebODF. If not, see . - @licend + along with this code. If not, see . + 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("core.DomUtils"); -odf.MetadataManager=function(g){function l(f,l){f&&(Object.keys(f).forEach(function(b){m[b]=f[b]}),c.mapKeyValObjOntoNode(g,f,odf.Namespaces.resolvePrefix));l&&(l.forEach(function(b){delete m[b]}),c.removeKeyElementsFromNode(g,l,odf.Namespaces.resolvePrefix))}var c=new core.DomUtils,m={};this.setMetadata=l;this.incrementEditingCycles=function(){var c=parseInt(m["meta:editing-cycles"]||0,10)+1;l({"meta:editing-cycles":c},null)};m=c.getKeyValRepresentationOfNode(g,odf.Namespaces.lookupPrefix)}; -// Input 35 +runtime.loadClass("odf.OdfUtils"); +odf.TextSerializer=function(){function g(n){var m="",q=k.filter?k.filter.acceptNode(n):NodeFilter.FILTER_ACCEPT,b=n.nodeType,h;if(q===NodeFilter.FILTER_ACCEPT||q===NodeFilter.FILTER_SKIP)for(h=n.firstChild;h;)m+=g(h),h=h.nextSibling;q===NodeFilter.FILTER_ACCEPT&&(b===Node.ELEMENT_NODE&&e.isParagraph(n)?m+="\n":b===Node.TEXT_NODE&&n.textContent&&(m+=n.textContent));return m}var k=this,e=new odf.OdfUtils;this.filter=null;this.writeToString=function(e){if(!e)return"";e=g(e);"\n"===e[e.length-1]&&(e= +e.substr(0,e.length-1));return e}}; +// Input 34 /* Copyright (C) 2012-2013 KO GmbH @@ -812,35 +810,20 @@ odf.MetadataManager=function(g){function l(f,l){f&&(Object.keys(f).forEach(funct @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -runtime.loadClass("core.Base64");runtime.loadClass("core.Zip");runtime.loadClass("xmldom.LSSerializer");runtime.loadClass("odf.StyleInfo");runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.OdfNodeFilter");runtime.loadClass("odf.MetadataManager"); -odf.OdfContainer=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=k.length;for(b=0;bc)break;d=d.nextSibling}a.insertBefore(b,d)}}}function n(a){this.OdfContainer= -a}function b(a,b,c,e){var d=this;this.size=0;this.type=null;this.name=a;this.container=c;this.onchange=this.onreadystatechange=this.document=this.mimetype=this.url=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.load=function(){null!==e&&(this.mimetype=b,e.loadAsDataURL(a,b,function(a,b){a&&runtime.log(a);d.url=b;if(d.onchange)d.onchange(d);if(d.onstatereadychange)d.onstatereadychange(d)}))}}var p=new odf.StyleInfo,r,d=odf.Namespaces.stylens,k="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "), -a=(new Date).getTime()+"_webodf_",e=new core.Base64;n.prototype=new function(){};n.prototype.constructor=n;n.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";n.localName="document";b.prototype.load=function(){};b.prototype.getUrl=function(){return this.data?"data:;base64,"+e.toBase64(this.data):null};odf.OdfContainer=function q(k,l){function v(a){for(var b=a.firstChild,c;b;)c=b.nextSibling,b.nodeType===Node.ELEMENT_NODE?v(b):b.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&a.removeChild(b), -b=c}function y(a,b){for(var c=a&&a.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&c.setAttributeNS("urn:webodf:names:scope","scope",b),c=c.nextSibling}function w(a,b){function c(a,b,e){var d=0,f;for(f=a=a.replace(/\d+$/,"");b.hasOwnProperty(f)||e.hasOwnProperty(f);)d+=1,f=a+d;return f}function e(a){var b={};for(a=a.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&a.namespaceURI===d&&"font-face"===a.localName&&(g=a.getAttributeNS(d,"name"),b[g]=a),a=a.nextSibling;return b}var f,k,g,l,m,s,p={};m=e(a);s= -e(b);for(f=b.firstChild;f;)k=f.nextSibling,f.nodeType===Node.ELEMENT_NODE&&f.namespaceURI===d&&"font-face"===f.localName&&(g=f.getAttributeNS(d,"name"),m.hasOwnProperty(g)?f.isEqualNode(m[g])||(l=c(g,m,s),f.setAttributeNS(d,"style:name",l),a.appendChild(f),m[l]=f,delete s[g],p[g]=l):(a.appendChild(f),m[g]=f,delete s[g])),f=k;return p}function t(a,b){var c=null,e,d,f;if(a)for(c=a.cloneNode(!0),e=c.firstChild;e;)d=e.nextSibling,e.nodeType===Node.ELEMENT_NODE&&(f=e.getAttributeNS("urn:webodf:names:scope", -"scope"))&&f!==b&&c.removeChild(e),e=d;return c}function s(a,b){var c=null,e,f,k,g={};if(a)for(b.forEach(function(a){p.collectUsedFontFaces(g,a)}),c=a.cloneNode(!0),e=c.firstChild;e;)f=e.nextSibling,e.nodeType===Node.ELEMENT_NODE&&(k=e.getAttributeNS(d,"name"),g[k]||c.removeChild(e)),e=f;return c}function D(a){var b=N.rootElement.ownerDocument,c;if(a){v(a.documentElement);try{c=b.importNode(a.documentElement,!0)}catch(e){}}return c}function A(a){N.state=a;if(N.onchange)N.onchange(N);if(N.onstatereadychange)N.onstatereadychange(N)} -function B(a){ka=null;N.rootElement=a;a.fontFaceDecls=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");a.styles=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");a.automaticStyles=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");a.masterStyles=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");a.body=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");a.meta=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", -"meta")}function M(b){b=D(b);var c=N.rootElement;b&&"document-styles"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI?(c.fontFaceDecls=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),f(c,c.fontFaceDecls),c.styles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),f(c,c.styles),c.automaticStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),y(c.automaticStyles,"document-styles"),f(c,c.automaticStyles), -c.masterStyles=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),f(c,c.masterStyles),p.prefixStyleNames(c.automaticStyles,a,c.masterStyles)):A(q.INVALID)}function z(a){a=D(a);var b,c,e;if(a&&"document-content"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI){b=N.rootElement;c=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");b.fontFaceDecls&&c?e=w(b.fontFaceDecls,c):c&&(b.fontFaceDecls=c,f(b,c));c=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", -"automatic-styles");y(c,"document-content");e&&p.changeFontFaceNames(c,e);if(b.automaticStyles&&c)for(e=c.firstChild;e;)b.automaticStyles.appendChild(e),e=c.firstChild;else c&&(b.automaticStyles=c,f(b,c));b.body=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");f(b,b.body)}else A(q.INVALID)}function K(a){a=D(a);var b;a&&"document-meta"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=N.rootElement,b.meta=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", -"meta"),f(b,b.meta),r=new odf.MetadataManager(b.meta))}function F(a){a=D(a);var b;a&&"document-settings"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=N.rootElement,b.settings=g(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),f(b,b.settings))}function Q(a){a=D(a);var b;if(a&&"manifest"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===a.namespaceURI)for(b=N.rootElement,b.manifest=a,a=b.manifest.firstChild;a;)a.nodeType=== -Node.ELEMENT_NODE&&"file-entry"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===a.namespaceURI&&(Z[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.nextSibling}function $(a){var b=a.shift(),c,e;b?(c=b[0],e=b[1],O.loadAsDOM(c,function(b,c){e(c);b||N.state===q.INVALID||$(a)})):A(q.DONE)}function ia(a){var b="";odf.Namespaces.forEachPrefix(function(a,c){b+= -" xmlns:"+a+'="'+c+'"'});return''}function R(){var a=new xmldom.LSSerializer,b=ia("document-meta");a.filter=new odf.OdfNodeFilter;b+=a.writeToString(N.rootElement.meta,odf.Namespaces.namespaceMap);return b+""}function ma(a,b){var c=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");c.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", -"manifest:full-path",a);c.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:media-type",b);return c}function ba(){var a=runtime.parseXML(''),b=g(a,"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest"),c=new xmldom.LSSerializer,e;for(e in Z)Z.hasOwnProperty(e)&&b.appendChild(ma(e,Z[e]));c.filter=new odf.OdfNodeFilter;return'\n'+ -c.writeToString(a,odf.Namespaces.namespaceMap)}function ga(){var a=new xmldom.LSSerializer,b=ia("document-settings");a.filter=new odf.OdfNodeFilter;b+=a.writeToString(N.rootElement.settings,odf.Namespaces.namespaceMap);return b+""}function S(){var b=odf.Namespaces.namespaceMap,e=new xmldom.LSSerializer,d,f,k,g=ia("document-styles");f=t(N.rootElement.automaticStyles,"document-styles");k=N.rootElement.masterStyles&&N.rootElement.masterStyles.cloneNode(!0);d=s(N.rootElement.fontFaceDecls, -[k,N.rootElement.styles,f]);p.removePrefixFromStyleNames(f,a,k);e.filter=new c(k,f);g+=e.writeToString(d,b);g+=e.writeToString(N.rootElement.styles,b);g+=e.writeToString(f,b);g+=e.writeToString(k,b);return g+""}function Y(){var a=odf.Namespaces.namespaceMap,b=new xmldom.LSSerializer,c,e,d=ia("document-content");e=t(N.rootElement.automaticStyles,"document-content");c=s(N.rootElement.fontFaceDecls,[e]);b.filter=new m(N.rootElement.body,e);d+=b.writeToString(c,a);d+=b.writeToString(e, -a);d+=b.writeToString(N.rootElement.body,a);return d+""}function V(a,b){runtime.loadXML(a,function(a,c){if(a)b(a);else{var e=D(c);e&&"document"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===e.namespaceURI?(B(e),A(q.DONE)):A(q.INVALID)}})}function G(){function a(b,c){var d;c||(c=b);d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",c);e[b]=d;e.appendChild(d)}var b=new core.Zip("",null),c=runtime.byteArrayFromString("application/vnd.oasis.opendocument.text", -"utf8"),e=N.rootElement,d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text");b.save("mimetype",c,!1,new Date);a("meta");a("settings");a("scripts");a("fontFaceDecls","font-face-decls");a("styles");a("automaticStyles","automatic-styles");a("masterStyles","master-styles");a("body");e.body.appendChild(d);r=new odf.MetadataManager(e.meta);A(q.DONE);return b}function I(){var a,b=new Date,c=runtime.getWindow();a="WebODF/"+("undefined"!==String(typeof webodf_version)?webodf_version: -"FromSource");c&&(a=a+" "+c.navigator.userAgent);r.setMetadata({"meta:generator":a});a=runtime.byteArrayFromString(ga(),"utf8");O.save("settings.xml",a,!0,b);a=runtime.byteArrayFromString(R(),"utf8");O.save("meta.xml",a,!0,b);a=runtime.byteArrayFromString(S(),"utf8");O.save("styles.xml",a,!0,b);a=runtime.byteArrayFromString(Y(),"utf8");O.save("content.xml",a,!0,b);a=runtime.byteArrayFromString(ba(),"utf8");O.save("META-INF/manifest.xml",a,!0,b)}function ha(a,b){I();O.writeAs(a,function(a){b(a)})} -var N=this,O,Z={},ka;this.onstatereadychange=l;this.rootElement=this.state=this.onchange=null;this.setRootElement=B;this.getContentElement=function(){var a;ka||(a=N.rootElement.body,ka=a.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")[0]||a.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","presentation")[0]||a.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet")[0]);return ka};this.getDocumentType=function(){var a= -N.getContentElement();return a&&a.localName};this.getMetadataManager=function(){return r};this.getPart=function(a){return new b(a,Z[a],N,O)};this.getPartData=function(a,b){O.load(a,b)};this.createByteArray=function(a,b){I();O.createByteArray(a,b)};this.saveAs=ha;this.save=function(a){ha(k,a)};this.getUrl=function(){return k};this.setBlob=function(a,b,c){c=e.convertBase64ToByteArray(c);O.save(a,c,!1,new Date);Z.hasOwnProperty(a)&&runtime.log(a+" has been overwritten.");Z[a]=b};this.removeBlob=function(a){var b= -O.remove(a);runtime.assert(b,"file is not found: "+a);delete Z[a]};this.state=q.LOADING;this.rootElement=function(a){var b=document.createElementNS(a.namespaceURI,a.localName),c;a=new a;for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}(n);O=k?new core.Zip(k,function(a,b){O=b;a?V(k,function(b){a&&(O.error=a+"\n"+b,A(q.INVALID))}):$([["styles.xml",M],["content.xml",z],["meta.xml",K],["settings.xml",F],["META-INF/manifest.xml",Q]])}):G()};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}(); +runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils"); +ops.TextPositionFilter=function(g){function k(h,g,d){var f,a;if(g&&(f=e.lookLeftForCharacter(g),1===f||2===f&&(e.scanRightForAnyCharacter(d)||e.scanRightForAnyCharacter(e.nextNode(h)))))return q;f=null===g&&e.isParagraph(h);a=e.lookRightForCharacter(d);if(f)return a?q:e.scanRightForAnyCharacter(d)?b:q;if(!a)return b;g=g||e.previousNode(h);return e.scanLeftForAnyCharacter(g)?b:q}var e=new odf.OdfUtils,n=Node.ELEMENT_NODE,m=Node.TEXT_NODE,q=core.PositionFilter.FilterResult.FILTER_ACCEPT,b=core.PositionFilter.FilterResult.FILTER_REJECT; +this.acceptPosition=function(h){var r=h.container(),d=r.nodeType,f,a,c;if(d!==n&&d!==m)return b;if(d===m){if(!e.isGroupingElement(r.parentNode)||e.isWithinTrackedChanges(r.parentNode,g()))return b;d=h.unfilteredDomOffset();f=r.data;runtime.assert(d!==f.length,"Unexpected offset.");if(0/g,">").replace(/'/g,"'").replace(/"/g,""")}function e(g,q){var b="",h=n.filter?n.filter.acceptNode(q):NodeFilter.FILTER_ACCEPT,r;if(h===NodeFilter.FILTER_ACCEPT&&q.nodeType===Node.ELEMENT_NODE){g.push();r=g.getQName(q);var d,f=q.attributes,a,c,p,l="",u;d="<"+r;a=f.length;for(c=0;c")}if(h===NodeFilter.FILTER_ACCEPT||h===NodeFilter.FILTER_SKIP){for(h=q.firstChild;h;)b+=e(g,h),h=h.nextSibling;q.nodeValue&&(b+=k(q.nodeValue))}r&&(b+="",g.pop());return b}var n=this;this.filter=null;this.writeToString=function(k,n){if(!k)return"";var b=new g(n);return e(b,k)}}; // Input 36 /* - Copyright (C) 2012-2013 KO GmbH + Copyright (C) 2013 KO GmbH @licstart The JavaScript code in this page is free software: you can redistribute it @@ -875,10 +858,9 @@ O.remove(a);runtime.assert(b,"file is not found: "+a);delete Z[a]};this.state=q. @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -runtime.loadClass("core.Base64");runtime.loadClass("xmldom.XPath");runtime.loadClass("odf.OdfContainer"); -odf.FontLoader=function(){function g(l,f,n,b,p){var r,d=0,k;for(k in l)if(l.hasOwnProperty(k)){if(d===n){r=k;break}d+=1}r?f.getPartData(l[r].href,function(a,e){if(a)runtime.log(a);else if(e){var d="@font-face { font-family: '"+(l[r].family||r)+"'; src: url(data:application/x-font-ttf;charset=binary;base64,"+c.convertUTF8ArrayToBase64(e)+') format("truetype"); }';try{b.insertRule(d,b.cssRules.length)}catch(k){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(k)+"\nRule: "+d)}}else runtime.log("missing font data for "+ -l[r].href);g(l,f,n+1,b,p)}):p&&p()}var l=new xmldom.XPath,c=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(c,f){for(var n=c.rootElement.fontFaceDecls;f.cssRules.length;)f.deleteRule(f.cssRules.length-1);if(n){var b={},p,r,d,k;if(n)for(n=l.getODFElementsWithXPath(n,"style:font-face[svg:font-face-src]",odf.Namespaces.resolvePrefix),p=0;pb)break;f=f.nextSibling}a.insertBefore(c,f)}}}var q=new odf.StyleInfo, +b,h=odf.Namespaces.stylens,r="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "),d=(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.OdfPart=function(a,c,b,d){var f=this;this.size=0;this.type=null;this.name=a;this.container=b;this.url=null;this.mimetype=c;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=c,d.loadAsDataURL(a,c,function(a,c){a&&runtime.log(a);f.url=c;if(f.onchange)f.onchange(f); +if(f.onstatereadychange)f.onstatereadychange(f)}))}};odf.OdfPart.prototype.load=function(){};odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+f.toBase64(this.data):null};odf.OdfContainer=function c(p,l){function k(c){for(var b=c.firstChild,d;b;)d=b.nextSibling,b.nodeType===Node.ELEMENT_NODE?k(b):b.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&c.removeChild(b),b=d}function r(c,b){for(var d=c&&c.firstChild;d;)d.nodeType===Node.ELEMENT_NODE&&d.setAttributeNS("urn:webodf:names:scope", +"scope",b),d=d.nextSibling}function w(c){var b={},d;for(c=c.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&c.namespaceURI===h&&"font-face"===c.localName&&(d=c.getAttributeNS(h,"name"),b[d]=c),c=c.nextSibling;return b}function y(c,b){var d=null,f,e,h;if(c)for(d=c.cloneNode(!0),f=d.firstElementChild;f;)e=f.nextElementSibling,(h=f.getAttributeNS("urn:webodf:names:scope","scope"))&&h!==b&&d.removeChild(f),f=e;return d}function v(c,b){var d,f,e,l=null,g={};if(c)for(b.forEach(function(c){q.collectUsedFontFaces(g, +c)}),l=c.cloneNode(!0),d=l.firstElementChild;d;)f=d.nextElementSibling,e=d.getAttributeNS(h,"name"),g[e]||l.removeChild(d),d=f;return l}function t(c){var b=H.rootElement.ownerDocument,d;if(c){k(c.documentElement);try{d=b.importNode(c.documentElement,!0)}catch(f){}}return d}function s(c){H.state=c;if(H.onchange)H.onchange(H);if(H.onstatereadychange)H.onstatereadychange(H)}function N(c){L=null;H.rootElement=c;c.fontFaceDecls=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"); +c.styles=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");c.automaticStyles=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");c.masterStyles=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");c.body=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");c.meta=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta")}function z(b){var f=t(b),e=H.rootElement,h;f&&"document-styles"===f.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"=== +f.namespaceURI?(e.fontFaceDecls=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),m(e,e.fontFaceDecls),h=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),e.styles=h||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),m(e,e.styles),h=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),e.automaticStyles=h||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),r(e.automaticStyles, +"document-styles"),m(e,e.automaticStyles),f=g(f,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),e.masterStyles=f||b.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),m(e,e.masterStyles),q.prefixStyleNames(e.automaticStyles,d,e.masterStyles)):s(c.INVALID)}function x(b){b=t(b);var d,f,e,l;if(b&&"document-content"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI){d=H.rootElement;e=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", +"font-face-decls");if(d.fontFaceDecls&&e){l=d.fontFaceDecls;var p,k,n,v,u={};f=w(l);v=w(e);for(e=e.firstElementChild;e;){p=e.nextElementSibling;if(e.namespaceURI===h&&"font-face"===e.localName)if(k=e.getAttributeNS(h,"name"),f.hasOwnProperty(k)){if(!e.isEqualNode(f[k])){n=k;for(var z=f,F=v,x=0,A=void 0,A=n=n.replace(/\d+$/,"");z.hasOwnProperty(A)||F.hasOwnProperty(A);)x+=1,A=n+x;n=A;e.setAttributeNS(h,"style:name",n);l.appendChild(e);f[n]=e;delete v[k];u[k]=n}}else l.appendChild(e),f[k]=e,delete v[k]; +e=p}l=u}else e&&(d.fontFaceDecls=e,m(d,e));f=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");r(f,"document-content");l&&q.changeFontFaceNames(f,l);if(d.automaticStyles&&f)for(l=f.firstChild;l;)d.automaticStyles.appendChild(l),l=f.firstChild;else f&&(d.automaticStyles=f,m(d,f));b=g(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===b)throw" tag is mising.";d.body=b;m(d,d.body)}else s(c.INVALID)}function R(c){var d=t(c),f;d&&"document-meta"=== +d.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===d.namespaceURI&&(f=H.rootElement,d=g(d,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),f.meta=d||c.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),m(f,f.meta),b=new odf.MetadataManager(f.meta))}function F(c){c=t(c);var b;c&&"document-settings"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===c.namespaceURI&&(b=H.rootElement,b.settings=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", +"settings"),m(b,b.settings))}function U(c){c=t(c);var b;if(c&&"manifest"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===c.namespaceURI)for(b=H.rootElement,b.manifest=c,c=b.manifest.firstElementChild;c;)"file-entry"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===c.namespaceURI&&(Q[c.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=c.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),c=c.nextElementSibling} +function P(b){var d=b.shift();d?X.loadAsDOM(d.path,function(f,e){d.handler(e);f||H.state===c.INVALID||P(b)}):s(c.DONE)}function A(c){var b="";odf.Namespaces.forEachPrefix(function(c,d){b+=" xmlns:"+c+'="'+d+'"'});return''}function ja(){var c=new xmldom.LSSerializer,b=A("document-meta");c.filter=new odf.OdfNodeFilter;b+=c.writeToString(H.rootElement.meta,odf.Namespaces.namespaceMap);return b+""}function ka(c, +b){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",c);d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:media-type",b);return d}function G(){var c=runtime.parseXML(''),b=g(c,"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", +"manifest"),d=new xmldom.LSSerializer,f;for(f in Q)Q.hasOwnProperty(f)&&b.appendChild(ka(f,Q[f]));d.filter=new odf.OdfNodeFilter;return'\n'+d.writeToString(c,odf.Namespaces.namespaceMap)}function Z(){var c=new xmldom.LSSerializer,b=A("document-settings");c.filter=new odf.OdfNodeFilter;b+=c.writeToString(H.rootElement.settings,odf.Namespaces.namespaceMap);return b+""}function O(){var c,b,f,h=odf.Namespaces.namespaceMap, +l=new xmldom.LSSerializer,g=A("document-styles");b=y(H.rootElement.automaticStyles,"document-styles");f=H.rootElement.masterStyles.cloneNode(!0);c=v(H.rootElement.fontFaceDecls,[f,H.rootElement.styles,b]);q.removePrefixFromStyleNames(b,d,f);l.filter=new e(f,b);g+=l.writeToString(c,h);g+=l.writeToString(H.rootElement.styles,h);g+=l.writeToString(b,h);g+=l.writeToString(f,h);return g+""}function ba(){var c,b,d=odf.Namespaces.namespaceMap,f=new xmldom.LSSerializer,e=A("document-content"); +b=y(H.rootElement.automaticStyles,"document-content");c=v(H.rootElement.fontFaceDecls,[b]);f.filter=new n(H.rootElement.body,b);e+=f.writeToString(c,d);e+=f.writeToString(b,d);e+=f.writeToString(H.rootElement.body,d);return e+""}function K(b,d){runtime.loadXML(b,function(b,f){if(b)d(b);else{var e=t(f);e&&"document"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===e.namespaceURI?(N(e),s(c.DONE)):s(c.INVALID)}})}function I(){function d(c,b){var f;b||(b=c); +f=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",b);h[c]=f;h.appendChild(f)}var f=new core.Zip("",null),e=runtime.byteArrayFromString("application/vnd.oasis.opendocument.text","utf8"),h=H.rootElement,l=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","text");f.save("mimetype",e,!1,new Date);d("meta");d("settings");d("scripts");d("fontFaceDecls","font-face-decls");d("styles");d("automaticStyles","automatic-styles");d("masterStyles","master-styles"); +d("body");h.body.appendChild(l);b=new odf.MetadataManager(h.meta);s(c.DONE);return f}function C(){var c,d=new Date,f=runtime.getWindow();c="WebODF/"+("undefined"!==String(typeof webodf_version)?webodf_version:"FromSource");f&&(c=c+" "+f.navigator.userAgent);b.setMetadata({"meta:generator":c},null);c=runtime.byteArrayFromString(Z(),"utf8");X.save("settings.xml",c,!0,d);c=runtime.byteArrayFromString(ja(),"utf8");X.save("meta.xml",c,!0,d);c=runtime.byteArrayFromString(O(),"utf8");X.save("styles.xml", +c,!0,d);c=runtime.byteArrayFromString(ba(),"utf8");X.save("content.xml",c,!0,d);c=runtime.byteArrayFromString(G(),"utf8");X.save("META-INF/manifest.xml",c,!0,d)}function Y(c,b){C();X.writeAs(c,function(c){b(c)})}var H=this,X,Q={},L;this.onstatereadychange=l;this.state=this.onchange=null;this.setRootElement=N;this.getContentElement=function(){var c;L||(c=H.rootElement.body,L=g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","presentation")|| +g(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!L)throw"Could not find content element in .";return L};this.getDocumentType=function(){var c=H.getContentElement();return c&&c.localName};this.getMetadataManager=function(){return b};this.getPart=function(c){return new odf.OdfPart(c,Q[c],H,X)};this.getPartData=function(c,b){X.load(c,b)};this.createByteArray=function(c,b){C();X.createByteArray(c,b)};this.saveAs=Y;this.save=function(c){Y(p,c)};this.getUrl=function(){return p}; +this.setBlob=function(c,b,d){d=f.convertBase64ToByteArray(d);X.save(c,d,!1,new Date);Q.hasOwnProperty(c)&&runtime.log(c+" has been overwritten.");Q[c]=b};this.removeBlob=function(c){var b=X.remove(c);runtime.assert(b,"file is not found: "+c);delete Q[c]};this.state=c.LOADING;this.rootElement=function(c){var b=document.createElementNS(c.namespaceURI,c.localName),d;c=new c.Type;for(d in c)c.hasOwnProperty(d)&&(b[d]=c[d]);return b}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentElement.namespaceURI, +localName:odf.ODFDocumentElement.localName});X=p?new core.Zip(p,function(b,d){X=d;b?K(p,function(d){b&&(X.error=b+"\n"+d,s(c.INVALID))}):P([{path:"styles.xml",handler:z},{path:"content.xml",handler:x},{path:"meta.xml",handler:R},{path:"settings.xml",handler:F},{path:"META-INF/manifest.xml",handler:U}])}):I()};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(c){return new odf.OdfContainer(c, +null)};return odf.OdfContainer})(); // Input 38 /* @@ -959,20 +964,10 @@ a.getAttributeNS(b,"href");a=a.substring(9,a.lastIndexOf("."));h[a]=!0}),a=new c @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");runtime.loadClass("odf.TextStyleApplicator"); -odf.Formatting=function(){function g(a){return(a=t[a])?w.mergeObjects({},a):null}function l(){for(var a=k.rootElement.fontFaceDecls,b={},c,d,a=a&&a.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&(c=a.getAttributeNS(h,"name"))&&((d=a.getAttributeNS(e,"font-family"))||a.getElementsByTagNameNS(e,"font-face-uri")[0])&&(b[c]=d),a=a.nextSibling;return b}function c(a){for(var b=k.rootElement.styles.firstChild;b;){if(b.nodeType===Node.ELEMENT_NODE&&b.namespaceURI===h&&"default-style"===b.localName&&b.getAttributeNS(h, -"family")===a)return b;b=b.nextSibling}return null}function m(a,b,c){var e,d;c=c||[k.rootElement.automaticStyles,k.rootElement.styles];for(e=c.shift();e;){for(e=e.firstChild;e;){if(e.nodeType===Node.ELEMENT_NODE&&(d=e.getAttributeNS(h,"name"),e.namespaceURI===h&&"style"===e.localName&&e.getAttributeNS(h,"family")===b&&d===a||"list-style"===b&&e.namespaceURI===q&&"list-style"===e.localName&&d===a||"data"===b&&e.namespaceURI===u&&d===a))return e;e=e.nextSibling}e=c.shift()}return null}function f(a){for(var b, -c={},e=a.firstChild;e;){if(e.nodeType===Node.ELEMENT_NODE&&e.namespaceURI===h)for(c[e.nodeName]={},b=0;b text|list-item > *:first-child:before {";if(E=J.getAttributeNS(M, -"style-name"))J=x[E],G=ia.getFirstNonWhitespaceChild(J),J=void 0,G&&("list-level-style-number"===G.localName?(J=G.getAttributeNS(D,"num-format"),E=G.getAttributeNS(D,"num-suffix"),I="",I={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},L=void 0,L=G.getAttributeNS(D,"num-prefix")||"",L=I.hasOwnProperty(J)?L+(" counter(list, "+I[J]+")"):J?L+("'"+J+"';"):L+" ''",E&&(L+=" '"+E+"'"),J=I="content: "+L+";"):"list-level-style-image"===G.localName?J="content: none;":"list-level-style-bullet"=== -G.localName&&(J="content: '"+G.getAttributeNS(M,"bullet-char")+"';")),G=J;if(R){for(J=v[R];J;)R=J,J=v[R];C+="counter-increment:"+R+";";G?(G=G.replace("list",R),C+=G):C+="content:counter("+R+");"}else R="",G?(G=G.replace("list",z),C+=G):C+="content: counter("+z+");",C+="counter-increment:"+z+";",g.insertRule("text|list#"+z+" {counter-reset:"+z+"}",g.cssRules.length);C+="}";v[z]=R;C&&g.insertRule(C,g.cssRules.length)}T.insertBefore(fa,T.firstChild);A();V(f);if(!a&&(f=[O],ja.hasOwnProperty("statereadychange")))for(g= -ja.statereadychange,G=0;G - - @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 . - @licend - - @source: http://www.webodf.org/ - @source: https://github.com/kogmbh/WebODF/ -*/ -ops.Member=function(g,l){var c={};this.getMemberId=function(){return g};this.getProperties=function(){return c};this.setProperties=function(g){Object.keys(g).forEach(function(f){c[f]=g[f]})};this.removeProperties=function(g){delete g.fullName;delete g.color;delete g.imageUrl;Object.keys(g).forEach(function(f){c.hasOwnProperty(f)&&delete c[f]})};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");c=l}; -// Input 42 -/* - - Copyright (C) 2013 KO GmbH + Copyright (C) 2012-2013 KO GmbH @licstart The JavaScript code in this page is free software: you can redistribute it @@ -1110,7 +1048,130 @@ ops.Member=function(g,l){var c={};this.getMemberId=function(){return g};this.get @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,c,m){};ops.Server.prototype.joinSession=function(g,l,c,m){};ops.Server.prototype.leaveSession=function(g,l,c,m){};ops.Server.prototype.getGenesisUrl=function(g){}; +runtime.loadClass("core.DomUtils");runtime.loadClass("core.LoopWatchDog");runtime.loadClass("odf.Namespaces");odf.TextStyleApplicatorFormatting=function(){};odf.TextStyleApplicatorFormatting.prototype.getAppliedStylesForElement=function(g){};odf.TextStyleApplicatorFormatting.prototype.createDerivedStyleObject=function(g,k,e){};odf.TextStyleApplicatorFormatting.prototype.updateStyle=function(g,k){}; +odf.TextStyleApplicator=function(g,k,e){function n(b){function f(a,c){return"object"===typeof a&&"object"===typeof c?Object.keys(a).every(function(b){return f(a[b],c[b])}):a===c}this.isStyleApplied=function(a){a=k.getAppliedStylesForElement(a);return f(b,a)}}function m(b){var f={};this.applyStyleToContainer=function(a){var c;c=a.getAttributeNS(h,"style-name");var p=a.ownerDocument;c=c||"";if(!f.hasOwnProperty(c)){var l=c,m;m=c?k.createDerivedStyleObject(c,"text",b):b;p=p.createElementNS(r,"style:style"); +k.updateStyle(p,m);p.setAttributeNS(r,"style:name",g.generateStyleName());p.setAttributeNS(r,"style:family","text");p.setAttributeNS("urn:webodf:names:scope","scope","document-content");e.appendChild(p);f[l]=p}c=f[c].getAttributeNS(r,"name");a.setAttributeNS(h,"text:style-name",c)}}function q(d,f){var a=d.ownerDocument,c=d.parentNode,e,l,g=new core.LoopWatchDog(1E4);l=[];"span"!==c.localName||c.namespaceURI!==h?(e=a.createElementNS(h,"text:span"),c.insertBefore(e,d),c=!1):(d.previousSibling&&!b.rangeContainsNode(f, +c.firstChild)?(e=c.cloneNode(!1),c.parentNode.insertBefore(e,c.nextSibling)):e=c,c=!0);l.push(d);for(a=d.nextSibling;a&&b.rangeContainsNode(f,a);)g.check(),l.push(a),a=a.nextSibling;l.forEach(function(a){a.parentNode!==e&&e.appendChild(a)});if(a&&c)for(l=e.cloneNode(!1),e.parentNode.insertBefore(l,e.nextSibling);a;)g.check(),c=a.nextSibling,l.appendChild(a),a=c;return e}var b=new core.DomUtils,h=odf.Namespaces.textns,r=odf.Namespaces.stylens;this.applyStyle=function(b,f,a){var c={},e,h,g,k;runtime.assert(a&& +a.hasOwnProperty("style:text-properties"),"applyStyle without any text properties");c["style:text-properties"]=a["style:text-properties"];g=new m(c);k=new n(c);b.forEach(function(a){e=k.isStyleApplied(a);!1===e&&(h=q(a,f),g.applyStyleToContainer(h))})}}; +// Input 41 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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");runtime.loadClass("odf.TextStyleApplicator"); +odf.Formatting=function(){function g(a){return(a=s[a])?t.mergeObjects({},a):{}}function k(a,c,b){for(a=a&&a.firstElementChild;a&&(a.namespaceURI!==c||a.localName!==b);)a=a.nextElementSibling;return a}function e(){for(var c=a.rootElement.fontFaceDecls,b={},d,f,c=c&&c.firstElementChild;c;){if(d=c.getAttributeNS(l,"name"))if((f=c.getAttributeNS(p,"font-family"))||0 + + @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 . + + 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.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){b=!0;runtime.setTimeout(function(){try{d()}catch(f){runtime.log(String(f))}b=!1;0 text|list-item > *:first-child:before {";if(Q=K.getAttributeNS(N,"style-name")){K=E[Q];J=P.getFirstNonWhitespaceChild(K);K=void 0;if(J)if("list-level-style-number"=== +J.localName){K=J.getAttributeNS(v,"num-format");Q=J.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=J.getAttributeNS(v,"num-prefix")||"",S=V.hasOwnProperty(K)?S+(" counter(list, "+V[K]+")"):K?S+("'"+K+"';"):S+" ''";Q&&(S+=" '"+Q+"'");K=V="content: "+S+";"}else"list-level-style-image"===J.localName?K="content: none;":"list-level-style-bullet"===J.localName&&(K="content: '"+J.getAttributeNS(N,"bullet-char")+"';"); +J=K}if(I){for(K=A[I];K;)K=A[K];D+="counter-increment:"+I+";";J?(J=J.replace("list",I),D+=J):D+="content:counter("+I+");"}else I="",J?(J=J.replace("list",O),D+=J):D+="content: counter("+O+");",D+="counter-increment:"+O+";",p.insertRule("text|list#"+O+" {counter-reset:"+O+"}",p.cssRules.length);D+="}";A[O]=I;D&&p.insertRule(D,p.cssRules.length)}L.insertBefore(da,L.firstChild);z();ba(k);if(!l&&(k=[H],ga.hasOwnProperty("statereadychange")))for(p=ga.statereadychange,J=0;J - - @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 . - - 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.OpAddCursor=function(){var g,l;this.init=function(c){g=c.memberid;l=c.timestamp};this.isEdit=!1;this.execute=function(c){var l=c.getCursor(g);if(l)return!1;l=new ops.OdtCursor(g,c);c.addCursor(l);c.emit(ops.OdtDocument.signalCursorAdded,l);return!0};this.spec=function(){return{optype:"AddCursor",memberid:g,timestamp:l}}}; -// Input 45 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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");runtime.loadClass("odf.OdfUtils"); -gui.StyleHelper=function(g){function l(b,c,f){var d=!0,k;for(k=0;k>>8):(Aa(c&255),Aa(c>>>8))},Ba=function(){t=(t<<5^p[F+3-1]&255)&8191;s=B[32768+t];B[F&32767]=s;B[32768+t]=F},V=function(a,c){y>16-c?(w|=a<>16-y,y+=c-16):(w|=a<a;a++)p[a]=p[a+32768];U-=32768;F-=32768;v-=32768;for(a=0;8192>a;a++)c=B[32768+a],B[32768+a]=32768<=c?c-32768:0;for(a=0;32768>a;a++)c=B[a],B[a]=32768<=c?c-32768:0;b+=32768}P||(a=na(p,F+A,b),0>=a?P=!0:A+=a)},oa=function(a){var c=ja,b=F,d,f=R,e=32506=Z&&(c>>=2);do if(d=a,p[d+f]===g&&p[d+f-1]===l&&p[d]===p[b]&&p[++d]===p[b+1]){b+= +2;d++;do++b;while(p[b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&p[++b]===p[++d]&&bf){U=a;f=d;if(258<=d)break;l=p[b+f-1];g=p[b+f]}a=B[a&32767]}while(a>e&&0!==--c);return f},Ca=function(a,c){u[S++]=c;0===a?O[c].fc++:(a--,O[ma[c]+256+1].fc++,ba[(256>a?T[a]:T[256+(a>>7)])&255].fc++,l[ga++]=a,fa|=E);E<<=1;0===(S&7)&&(da[D++]=fa,fa=0,E=1);if(2f;f++)b+=ba[f].fc* +(5+qa[f]);b>>=3;if(ga>=1,b<<=1;while(0<--c);return b>>1},xa=function(a,c){var b=[];b.length=16;var d=0,f;for(f=1;15>=f;f++)d=d+Q[f-1]<<1,b[f]=d;for(d=0;d<=c;d++)f=a[d].dl,0!==f&&(a[d].fc=Fa(b[f]++,f))},Da=function(a){var c=a.dyn_tree,b=a.static_tree,d=a.elems,f,e= +-1,h=d;ca=0;la=573;for(f=0;fca;)f=L[++ca]=2>e?++e:0,c[f].fc=1,aa[f]=0,pa--,null!==b&&(ha-=b[f].dl);a.max_code=e;for(f=ca>>1;1<=f;f--)va(c,f);do f=L[1],L[1]=L[ca--],va(c,1),b=L[1],L[--la]=f,L[--la]=b,c[h].fc=c[f].fc+c[b].fc,aa[h]=aa[f]>aa[b]+1?aa[f]:aa[b]+1,c[f].dl=c[b].dl=h,L[1]=h++,va(c,1);while(2<=ca);L[--la]=L[1];h=a.dyn_tree;f=a.extra_bits;var d=a.extra_base,b=a.max_code,l=a.max_length,g=a.static_tree,k,p,m,n,r=0;for(p=0;15>=p;p++)Q[p]= +0;h[L[la]].dl=0;for(a=la+1;573>a;a++)k=L[a],p=h[h[k].dl].dl+1,p>l&&(p=l,r++),h[k].dl=p,k>b||(Q[p]++,m=0,k>=d&&(m=f[k-d]),n=h[k].fc,pa+=n*(p+m),null!==g&&(ha+=n*(g[k].dl+m)));if(0!==r){do{for(p=l-1;0===Q[p];)p--;Q[p]--;Q[p+1]+=2;Q[l]--;r-=2}while(0b||(h[f].dl!==p&&(pa+=(p-h[f].dl)*h[f].fc,h[f].fc=p),k--)}xa(c,e)},ya=function(a,c){var b,d=-1,f,e=a[0].dl,h=0,l=7,g=4;0===e&&(l=138,g=3);a[c+1].dl=65535;for(b=0;b<=c;b++)f=e,e=a[b+1].dl,++h=h?C[17].fc++:C[18].fc++,h=0,d=f,0===e?(l=138,g=3):f===e?(l=6,g=3):(l=7,g=4))},Ga=function(){8b?T[b]:T[256+(b>>7)])&255,J(g,c),k=qa[g],0!==k&&(b-=W[g],V(b,k))),h>>=1;while(d=h?(J(17,C),V(h-3,3)):(J(18,C),V(h-11,7));h=0;d=f;0===e?(l=138,g=3):f===e?(l=6,g=3):(l=7,g=4)}},Ja=function(){var a;for(a=0;286>a;a++)O[a].fc=0;for(a=0;30>a;a++)ba[a].fc=0;for(a=0;19>a;a++)C[a].fc=0;O[256].fc=1;fa=S=ga=D=pa=ha=0;E=1},Ha=function(a){var c,b,d,f;f=F-v;da[D]=fa;Da(Y);Da(H);ya(O,Y.max_code);ya(ba,H.max_code);Da(X);for(d=18;3<=d&&0===C[wa[d]].dl;d--); +pa+=3*(d+1)+14;c=pa+3+7>>3;b=ha+3+7>>3;b<=c&&(c=b);if(f+4<=c&&0<=v)for(V(0+a,3),Ga(),ta(f),ta(~f),d=0;db.len&&(g=b.len);for(k=0;kf-a&&(g=f-a);for(k=0;kk;k++)for($[k]=g,l=0;l< +1<k;k++)for(W[k]=g,l=0;l<1<>=7;30>k;k++)for(W[k]=g<<7,l=0;l<1<=l;l++)Q[l]=0;for(l=0;143>=l;)K[l++].dl=8,Q[8]++;for(;255>=l;)K[l++].dl=9,Q[9]++;for(;279>=l;)K[l++].dl=7,Q[7]++;for(;287>=l;)K[l++].dl=8,Q[8]++;xa(K,287);for(l=0;30>l;l++)I[l].dl=5,I[l].fc=Fa(l,5);Ja()}for(l=0;8192>l;l++)B[32768+l]=0;ka=sa[G].max_lazy;Z=sa[G].good_length;ja=sa[G].max_chain;v=F=0;A=na(p,0,65536);if(0>=A)P=!0,A=0;else{for(P= +!1;262>A&&!P;)ea();for(l=t=0;2>l;l++)t=(t<<5^p[l]&255)&8191}b=null;a=f=0;3>=G?(R=2,x=0):(x=2,z=0);c=!1}r=!0;if(0===A)return c=!0,0}l=Ka(d,e,h);if(l===h)return h;if(c)return l;if(3>=G)for(;0!==A&&null===b;){Ba();0!==s&&32506>=F-s&&(x=oa(s),x>A&&(x=A));if(3<=x)if(k=Ca(F-U,x-3),A-=x,x<=ka){x--;do F++,Ba();while(0!==--x);F++}else F+=x,x=0,t=p[F]&255,t=(t<<5^p[F+1]&255)&8191;else k=Ca(0,p[F]&255),A--,F++;k&&(Ha(0),v=F);for(;262>A&&!P;)ea()}else for(;0!==A&&null===b;){Ba();R=x;N=U;x=2;0!==s&&R= +F-s&&(x=oa(s),x>A&&(x=A),3===x&&4096A&&!P;)ea()}0===A&&(0!==z&&Ca(0,p[F-1]&255),Ha(1),c=!0);return l+Ka(d,l+e,h-l)};this.deflate=function(a,c){var f,e;ia=a;Ea=0;"undefined"===String(typeof c)&&(c=6);(f=c)?1>f?f=1:9f;f++)O[f]=new g;ba=[];ba.length=61;for(f=0;61>f;f++)ba[f]=new g;K=[];K.length=288;for(f=0;288>f;f++)K[f]=new g;I=[];I.length=30;for(f=0;30>f;f++)I[f]=new g;C=[];C.length=39;for(f=0;39>f;f++)C[f]=new g;Y=new k;H=new k;X=new k;Q=[];Q.length=16;L=[];L.length=573;aa=[];aa.length=573;ma=[];ma.length=256;T=[];T.length=512;$=[];$.length=29;W=[];W.length=30;da=[];da.length=1024}var n=Array(1024),v=[],s=[];for(f=La(n,0,n.length);0 - - @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 . - - 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("gui.StyleHelper");runtime.loadClass("odf.OdfUtils"); -ops.OpApplyDirectStyling=function(){function g(b){var c=0<=f?m+f:m,d=b.getIteratorAtPosition(0<=f?m:m+f),c=f?b.getIteratorAtPosition(c):d;b=b.getDOM().createRange();b.setStart(d.container(),d.unfilteredDomOffset());b.setEnd(c.container(),c.unfilteredDomOffset());return b}var l,c,m,f,n,b=new odf.OdfUtils;this.init=function(b){l=b.memberid;c=b.timestamp;m=parseInt(b.position,10);f=parseInt(b.length,10);n=b.setProperties};this.isEdit=!0;this.execute=function(f){var m=g(f),d=b.getImpactedParagraphs(m); -(new gui.StyleHelper(f.getFormatting())).applyStyle(l,m,n);m.detach();f.getOdfCanvas().refreshCSS();f.fixCursorPositions();d.forEach(function(b){f.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:b,memberId:l,timeStamp:c})});f.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"ApplyDirectStyling",memberid:l,timestamp:c,position:m,length:f,setProperties:n}}}; +runtime.loadClass("odf.OdfCanvas"); +odf.CommandLineTools=function(){this.roundTrip=function(g,k,e){return new odf.OdfContainer(g,function(n){if(n.state===odf.OdfContainer.INVALID)return e("Document "+g+" is invalid.");n.state===odf.OdfContainer.DONE?n.saveAs(k,function(g){e(g)}):e("Document was not completely loaded.")})};this.render=function(g,k,e){for(k=k.getElementsByTagName("body")[0];k.firstChild;)k.removeChild(k.firstChild);k=new odf.OdfCanvas(k);k.addListener("statereadychange",function(g){e(g)});k.load(g)}}; // Input 47 /* - Copyright (C) 2012-2013 KO GmbH + Copyright (C) 2013 KO GmbH @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. + 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 this code. If not, see . - - 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. + along with WebODF. If not, see . @licend + @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.OpRemoveCursor=function(){var g,l;this.init=function(c){g=c.memberid;l=c.timestamp};this.isEdit=!1;this.execute=function(c){return c.removeCursor(g)?!0:!1};this.spec=function(){return{optype:"RemoveCursor",memberid:g,timestamp:l}}}; +ops.Member=function(g,k){var e={};this.getMemberId=function(){return g};this.getProperties=function(){return e};this.setProperties=function(g){Object.keys(g).forEach(function(k){e[k]=g[k]})};this.removeProperties=function(g){delete g.fullName;delete g.color;delete g.imageUrl;Object.keys(g).forEach(function(g){e.hasOwnProperty(g)&&delete e[g]})};runtime.assert(Boolean(g),"No memberId was supplied!");k.fullName||(k.fullName=runtime.tr("Unknown Author"));k.color||(k.color="black");k.imageUrl||(k.imageUrl= +"avatar-joe.png");e=k}; // Input 48 /* @@ -1350,85 +1305,32 @@ ops.OpRemoveCursor=function(){var g,l;this.init=function(c){g=c.memberid;l=c.tim @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.OpMoveCursor=function(){var g,l,c,m,f;this.init=function(n){g=n.memberid;l=n.timestamp;c=n.position;m=n.length||0;f=n.selectionType||ops.OdtCursor.RangeSelection};this.isEdit=!1;this.execute=function(l){var b=l.getCursor(g),p;if(!b)return!1;p=l.convertCursorToDomRange(c,m);b.setSelectedRange(p,0<=m);b.setSelectionType(f);l.emit(ops.OdtDocument.signalCursorMoved,b);return!0};this.spec=function(){return{optype:"MoveCursor",memberid:g,timestamp:l,position:c,length:m,selectionType:f}}}; +runtime.loadClass("core.DomUtils");runtime.loadClass("core.PositionFilter");runtime.loadClass("odf.OdfUtils"); +(function(){function g(e,g,m){function q(a,c){function b(a){for(var c=0;a&&a.previousSibling;)c+=1,a=a.previousSibling;return c}this.steps=a;this.node=c;this.setIteratorPosition=function(a){a.setUnfilteredPosition(c.parentNode,b(c));do if(g.acceptPosition(a)===u)break;while(a.nextPosition())}}function b(a){return a.nodeType===Node.ELEMENT_NODE&&a.getAttributeNS(d,"nodeId")}function h(a){var c=k;a.setAttributeNS(d,"nodeId",c.toString());k+=1;return c}function r(c,f){var h,l=null;for(c=c.childNodes[f]|| +c;!l&&c&&c!==e;)(h=b(c))&&(l=a[h])&&l.node!==c&&(runtime.log("Cloned node detected. Creating new bookmark"),l=null,c.removeAttributeNS(d,"nodeId")),c=c.parentNode;return l}var d="urn:webodf:names:steps",f={},a={},c=new odf.OdfUtils,p=new core.DomUtils,l,u=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.updateCache=function(d,e,l,g){var k;0===l&&c.isParagraph(e)?(k=!0,g||(d+=1)):e.hasChildNodes()&&e.childNodes[l]&&(e=e.childNodes[l],(k=c.isParagraph(e))&&(d+=1));k&&(l=b(e)||h(e),(g=a[l])?g.node=== +e?g.steps=d:(runtime.log("Cloned node detected. Creating new bookmark"),l=h(e),g=a[l]=new q(d,e)):g=a[l]=new q(d,e),l=g,d=Math.ceil(l.steps/m)*m,e=f[d],!e||l.steps>e.steps)&&(f[d]=l)};this.setToClosestStep=function(a,c){for(var b=Math.floor(a/m)*m,d;!d&&0!==b;)d=f[b],b-=m;d=d||l;d.setIteratorPosition(c);return d.steps};this.setToClosestDomPoint=function(a,c,b){var d;if(a===e&&0===c)d=l;else if(a===e&&c===e.childNodes.length)d=Object.keys(f).map(function(a){return f[a]}).reduce(function(a,c){return c.steps> +a.steps?c:a},l);else if(d=r(a,c),!d)for(b.setUnfilteredPosition(a,c);!d&&b.previousNode();)d=r(b.container(),b.unfilteredDomOffset());d=d||l;d.setIteratorPosition(b);return d.steps};this.updateCacheAtPoint=function(c,d){var h={};Object.keys(a).map(function(c){return a[c]}).filter(function(a){return a.steps>c}).forEach(function(c){var l=Math.ceil(c.steps/m)*m,g,k;if(p.containsNode(e,c.node)){if(d(c),g=Math.ceil(c.steps/m)*m,k=h[g],!k||c.steps>k.steps)h[g]=c}else delete a[b(c.node)];f[l]===c&&delete f[l]}); +Object.keys(h).forEach(function(a){f[a]=h[a]})};l=new function(a,c){this.steps=a;this.node=c;this.setIteratorPosition=function(a){a.setUnfilteredPosition(c,0);do if(g.acceptPosition(a)===u)break;while(a.nextPosition())}}(0,e)}var k=0;ops.StepsTranslator=function(e,k,m,q){function b(){var c=e();c!==r&&(runtime.log("Undo detected. Resetting steps cache"),r=c,d=new g(r,m,q),a=k(r))}function h(a,b){if(!b||m.acceptPosition(a)===c)return!0;for(;a.previousPosition();)if(m.acceptPosition(a)===c){if(b(0,a.container(), +a.unfilteredDomOffset()))return!0;break}for(;a.nextPosition();)if(m.acceptPosition(a)===c){if(b(1,a.container(),a.unfilteredDomOffset()))return!0;break}return!1}var r=e(),d=new g(r,m,q),f=new core.DomUtils,a=k(e()),c=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.convertStepsToDomPoint=function(f){var e,h;0>f&&(runtime.log("warn","Requested steps were negative ("+f+")"),f=0);b();for(e=d.setToClosestStep(f,a);ef.comparePoints(r,0,e,l),e=r,l=l?0:r.childNodes.length);a.setUnfilteredPosition(e,l);h(a,g)||a.setUnfilteredPosition(e,l);g=a.container();l=a.unfilteredDomOffset();e=d.setToClosestDomPoint(g,l,a);if(0>f.comparePoints(a.container(),a.unfilteredDomOffset(), +g,l))return 0c.steps&&(c.steps=0)})}};ops.StepsTranslator.PREVIOUS_STEP=0;ops.StepsTranslator.NEXT_STEP=1;return ops.StepsTranslator})(); // Input 49 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpSetBlob=function(){var g,l,c,m,f;this.init=function(n){g=n.memberid;l=n.timestamp;c=n.filename;m=n.mimetype;f=n.content};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().setBlob(c,m,f);return!0};this.spec=function(){return{optype:"SetBlob",memberid:g,timestamp:l,filename:c,mimetype:m,content:f}}}; +xmldom.RNG={}; +xmldom.RelaxNGParser=function(){function g(b,f){this.message=function(){f&&(b+=1===f.nodeType?" Element ":" Node ",b+=f.nodeName,f.nodeValue&&(b+=" with value '"+f.nodeValue+"'"),b+=".");return b}}function k(b){if(2>=b.e.length)return b;var f={name:b.name,e:b.e.slice(0,2)};return k({name:b.name,e:[f].concat(b.e.slice(2))})}function e(b){b=b.split(":",2);var f="",a;1===b.length?b=["",b[0]]:f=b[0];for(a in h)h[a]===f&&(b[0]=a);return b}function n(b,f){for(var a=0,c,h,l=b.name;b.e&&a - - @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 . - - 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.OpRemoveBlob=function(){var g,l,c;this.init=function(m){g=m.memberid;l=m.timestamp;c=m.filename};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().removeBlob(c);return!0};this.spec=function(){return{optype:"RemoveBlob",memberid:g,timestamp:l,filename:c}}}; +runtime.loadClass("core.Cursor");runtime.loadClass("gui.SelectionMover"); +ops.OdtCursor=function(g,k){var e=this,n={},m,q,b;this.removeFromOdtDocument=function(){b.remove()};this.move=function(b,g){var d=0;0=b&&(d=-q.movePointBackward(-b,g));e.handleUpdate();return d};this.handleUpdate=function(){};this.getStepCounter=function(){return q.getStepCounter()};this.getMemberId=function(){return g};this.getNode=function(){return b.getNode()};this.getAnchorNode=function(){return b.getAnchorNode()};this.getSelectedRange=function(){return b.getSelectedRange()}; +this.setSelectedRange=function(h,g){b.setSelectedRange(h,g);e.handleUpdate()};this.hasForwardSelection=function(){return b.hasForwardSelection()};this.getOdtDocument=function(){return k};this.getSelectionType=function(){return m};this.setSelectionType=function(b){n.hasOwnProperty(b)?m=b:runtime.log("Invalid selection type: "+b)};this.resetSelectionType=function(){e.setSelectionType(ops.OdtCursor.RangeSelection)};b=new core.Cursor(k.getDOM(),g);q=new gui.SelectionMover(b,k.getRootNode());n[ops.OdtCursor.RangeSelection]= +!0;n[ops.OdtCursor.RegionSelection]=!0;e.resetSelectionType()};ops.OdtCursor.RangeSelection="Range";ops.OdtCursor.RegionSelection="Region";(function(){return ops.OdtCursor})(); // Input 51 /* @@ -1467,10 +1369,106 @@ ops.OpRemoveBlob=function(){var g,l,c;this.init=function(m){g=m.memberid;l=m.tim @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.OpInsertImage=function(){var g,l,c,m,f,n,b,p,r=odf.Namespaces.drawns,d=odf.Namespaces.svgns,k=odf.Namespaces.textns,a=odf.Namespaces.xlinkns;this.init=function(a){g=a.memberid;l=a.timestamp;c=a.position;m=a.filename;f=a.frameWidth;n=a.frameHeight;b=a.frameStyleName;p=a.frameName};this.isEdit=!0;this.execute=function(e){var h=e.getOdfCanvas(),q=e.getTextNodeAtStep(c,g),u,x;if(!q)return!1;u=q.textNode;x=e.getParagraphElement(u);var q=q.offset!==u.length?u.splitText(q.offset):u.nextSibling,v=e.getDOM(), -y=v.createElementNS(r,"draw:image"),v=v.createElementNS(r,"draw:frame");y.setAttributeNS(a,"xlink:href",m);y.setAttributeNS(a,"xlink:type","simple");y.setAttributeNS(a,"xlink:show","embed");y.setAttributeNS(a,"xlink:actuate","onLoad");v.setAttributeNS(r,"draw:style-name",b);v.setAttributeNS(r,"draw:name",p);v.setAttributeNS(k,"text:anchor-type","as-char");v.setAttributeNS(d,"svg:width",f);v.setAttributeNS(d,"svg:height",n);v.appendChild(y);u.parentNode.insertBefore(v,q);e.emit(ops.OdtDocument.signalStepsInserted, -{position:c,length:1});0===u.length&&u.parentNode.removeChild(u);h.addCssForFrameWithImage(v);h.refreshCSS();e.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:x,memberId:g,timeStamp:l});h.rerenderAnnotations();return!0};this.spec=function(){return{optype:"InsertImage",memberid:g,timestamp:l,filename:m,position:c,frameWidth:f,frameHeight:n,frameStyleName:b,frameName:p}}}; +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 k(){var a=g.odfContainer().getContentElement(),c=a&&a.localName;runtime.assert("text"===c,"Unsupported content element type '"+c+"' for OdtDocument");return a}function e(){return k().ownerDocument}function n(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 m(c){this.acceptPosition=function(b){b=b.container();var d;d="string"===typeof c? +a[c].getNode():c;return n(b)===n(d)?l:u}}function q(a){var c=gui.SelectionMover.createPositionIterator(k());a=w.convertStepsToDomPoint(a);c.setUnfilteredPosition(a.node,a.offset);return c}function b(a,c){return g.getFormatting().getStyleElement(a,c)}function h(a){return b(a,"paragraph")}var r=this,d,f,a={},c={},p=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]),l=core.PositionFilter.FilterResult.FILTER_ACCEPT,u=core.PositionFilter.FilterResult.FILTER_REJECT,B,w,y;this.getDOM= +e;this.getRootElement=n;this.getIteratorAtPosition=q;this.convertDomPointToCursorStep=function(a,c,b){return w.convertDomPointToSteps(a,c,b)};this.convertDomToCursorRange=function(a,c){var b,d;b=c(a.anchorNode,a.anchorOffset);b=w.convertDomPointToSteps(a.anchorNode,a.anchorOffset,b);c||a.anchorNode!==a.focusNode||a.anchorOffset!==a.focusOffset?(d=c(a.focusNode,a.focusOffset),d=w.convertDomPointToSteps(a.focusNode,a.focusOffset,d)):d=b;return{position:b,length:d-b}};this.convertCursorToDomRange=function(a, +c){var b=e().createRange(),d,f;d=w.convertStepsToDomPoint(a);c?(f=w.convertStepsToDomPoint(a+c),0=f;f+=1){c=a.container();b=a.unfilteredDomOffset();if(c.nodeType===Node.TEXT_NODE&&" "===c.data[b]&&d.isSignificantWhitespace(c, +b)){runtime.assert(" "===c.data[b],"upgradeWhitespaceToElement: textNode.data[offset] should be a literal space");var e=c.ownerDocument.createElementNS(odf.Namespaces.textns,"text:s");e.appendChild(c.ownerDocument.createTextNode(" "));c.deleteData(b,1);0 + + @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 . + + 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.Operation=function(){};ops.Operation.prototype.init=function(g){};ops.Operation.prototype.execute=function(g){};ops.Operation.prototype.spec=function(){}; +// Input 53 +runtime.loadClass("xmldom.RelaxNGParser"); +xmldom.RelaxNG=function(){function g(a){return function(){var c;return function(){void 0===c&&(c=a());return c}}()}function k(a,c){return function(){var b={},d=0;return function(f){var e=f.hash||f.toString();if(b.hasOwnProperty(e))return b[e];b[e]=f=c(f);f.hash=a+d.toString();d+=1;return f}}()}function e(a){return function(){var c={};return function(b){var d,f;if(c.hasOwnProperty(b.localName)){if(f=c[b.localName],d=f[b.namespaceURI],void 0!==d)return d}else c[b.localName]=f={};return f[b.namespaceURI]= +d=a(b)}}()}function n(a,c,b){return function(){var d={},f=0;return function(e,h){var g=c&&c(e,h),l;if(void 0!==g)return g;l=e.hash||e.toString();g=h.hash||h.toString();if(d.hasOwnProperty(l)){if(l=d[l],l.hasOwnProperty(g))return l[g]}else d[l]=l={};l[g]=g=b(e,h);g.hash=a+f.toString();f+=1;return g}}()}function m(a,c){"choice"===c.p1.type?m(a,c.p1):a[c.p1.hash]=c.p1;"choice"===c.p2.type?m(a,c.p2):a[c.p2.hash]=c.p2}function q(a,c){return{type:"element",nc:a,nullable:!1,textDeriv:function(){return z}, +startTagOpenDeriv:function(b){return a.contains(b)?p(c,x):z},attDeriv:function(){return z},startTagCloseDeriv:function(){return this}}}function b(){return{type:"list",nullable:!1,hash:"list",textDeriv:function(){return x}}}function h(a,c,b,f){if(c===z)return z;if(f>=b.length)return c;0===f&&(f=0);for(var e=b.item(f);e.namespaceURI===d;){f+=1;if(f>=b.length)return c;e=b.item(f)}return e=h(a,c.attDeriv(a,b.item(f)),b,f+1)}function r(a,c,b){b.e[0].a?(a.push(b.e[0].text),c.push(b.e[0].a.ns)):r(a,c,b.e[0]); +b.e[1].a?(a.push(b.e[1].text),c.push(b.e[1].a.ns)):r(a,c,b.e[1])}var d="http://www.w3.org/2000/xmlns/",f,a,c,p,l,u,B,w,y,v,t,s,N,z={type:"notAllowed",nullable:!1,hash:"notAllowed",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return z},startTagOpenDeriv:function(){return z},attDeriv:function(){return z},startTagCloseDeriv:function(){return z},endTagDeriv:function(){return z}},x={type:"empty",nullable:!0,hash:"empty",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return z}, +startTagOpenDeriv:function(){return z},attDeriv:function(){return z},startTagCloseDeriv:function(){return x},endTagDeriv:function(){return z}},R={type:"text",nullable:!0,hash:"text",nc:void 0,p:void 0,p1:void 0,p2:void 0,textDeriv:function(){return R},startTagOpenDeriv:function(){return z},attDeriv:function(){return z},startTagCloseDeriv:function(){return R},endTagDeriv:function(){return z}};f=n("choice",function(a,c){if(a===z)return c;if(c===z||a===c)return a},function(a,c){var b={},d;m(b,{p1:a, +p2:c});c=a=void 0;for(d in b)b.hasOwnProperty(d)&&(void 0===a?a=b[d]:c=void 0===c?b[d]:f(c,b[d]));return function(a,c){return{type:"choice",nullable:a.nullable||c.nullable,hash:void 0,nc:void 0,p:void 0,p1:a,p2:c,textDeriv:function(b,d){return f(a.textDeriv(b,d),c.textDeriv(b,d))},startTagOpenDeriv:e(function(b){return f(a.startTagOpenDeriv(b),c.startTagOpenDeriv(b))}),attDeriv:function(b,d){return f(a.attDeriv(b,d),c.attDeriv(b,d))},startTagCloseDeriv:g(function(){return f(a.startTagCloseDeriv(), +c.startTagCloseDeriv())}),endTagDeriv:g(function(){return f(a.endTagDeriv(),c.endTagDeriv())})}}(a,c)});a=function(a,c,b){return function(){var d={},f=0;return function(e,h){var g=c&&c(e,h),l,k;if(void 0!==g)return g;l=e.hash||e.toString();g=h.hash||h.toString();lNode.ELEMENT_NODE;){if(d!==Node.COMMENT_NODE&&(d!==Node.TEXT_NODE||!/^\s+$/.test(e.currentNode.nodeValue)))return[new g("Not allowed node of type "+ +d+".")];d=(m=e.nextSibling())?m.nodeType:0}if(!m)return[new g("Missing element "+b.names)];if(b.names&&-1===b.names.indexOf(q[m.namespaceURI]+":"+m.localName))return[new g("Found "+m.nodeName+" instead of "+b.names+".",m)];if(e.firstChild()){for(f=k(b.e[1],e,m);e.nextSibling();)if(d=e.currentNode.nodeType,!(e.currentNode&&e.currentNode.nodeType===Node.TEXT_NODE&&/^\s+$/.test(e.currentNode.nodeValue)||d===Node.COMMENT_NODE))return[new g("Spurious content.",e.currentNode)];if(e.parentNode()!==m)return[new g("Implementation error.")]}else f= +k(b.e[1],e,m);e.nextSibling();return f}var n,m,q;m=function(b,h,n,d){var f=b.name,a=null;if("text"===f)a:{for(var c=(b=h.currentNode)?b.nodeType:0;b!==n&&3!==c;){if(1===c){a=[new g("Element not allowed here.",b)];break a}c=(b=h.nextSibling())?b.nodeType:0}h.nextSibling();a=null}else if("data"===f)a=null;else if("value"===f)d!==b.text&&(a=[new g("Wrong value, should be '"+b.text+"', not '"+d+"'",n)]);else if("list"===f)a=null;else if("attribute"===f)a:{if(2!==b.e.length)throw"Attribute with wrong # of elements: "+ +b.e.length;f=b.localnames.length;for(a=0;am(c,e))&&(e=f));a=e;c=g.getOdtDocument().getOdfCanvas().getZoomLevel();d&&g.getSelectionType()===ops.OdtCursor.RangeSelection? +b.style.visibility="visible":b.style.visibility="hidden";a?(b.style.top="0",e=p.getBoundingClientRect(b),8>a.height&&(a={top:a.top-(8-a.height)/2,height:8}),b.style.height=p.adaptRangeDifferenceToZoomLevel(a.height,c)+"px",b.style.top=p.adaptRangeDifferenceToZoomLevel(a.top-e.top,c)+"px"):(b.style.height="1em",b.style.top="5%")}var b,h,r,d=!0,f=!1,a=!1,c,p=new core.DomUtils;this.handleUpdate=q;this.refreshCursorBlinking=function(){e||g.getSelectedRange().collapsed?(f=!0,n(!0)):(f=!1,b.style.opacity= +"0")};this.setFocus=function(){f=!0;h.markAsFocussed(!0);n(!0)};this.removeFocus=function(){f=!1;h.markAsFocussed(!1);b.style.opacity="1"};this.show=function(){d=!0;q();h.markAsFocussed(!0)};this.hide=function(){d=!1;q();h.markAsFocussed(!1)};this.setAvatarImageUrl=function(a){h.setImageUrl(a)};this.setColor=function(a){b.style.borderColor=a;h.setColor(a)};this.getCursor=function(){return g};this.getFocusElement=function(){return b};this.toggleHandleVisibility=function(){h.isVisible()?h.hide():h.show()}; +this.showHandle=function(){h.show()};this.hideHandle=function(){h.hide()};this.ensureVisible=function(){var a,c,d,f,e=g.getOdtDocument().getOdfCanvas().getElement().parentNode,h;d=e.offsetWidth-e.clientWidth+5;f=e.offsetHeight-e.clientHeight+5;h=b.getBoundingClientRect();a=h.left-d;c=h.top-f;d=h.right+d;f=h.bottom+f;h=e.getBoundingClientRect();ch.bottom&&(e.scrollTop+=f-h.bottom);ah.right&&(e.scrollLeft+=d-h.right);q()};this.destroy=function(a){h.destroy(function(c){c? +a(c):(r.removeChild(b),a())})};(function(){var a=g.getOdtDocument().getDOM();b=a.createElementNS(a.documentElement.namespaceURI,"span");b.style.top="5%";r=g.getNode();r.appendChild(b);h=new gui.Avatar(r,k);q()})()}; +// Input 56 +gui.EventManager=function(g){function k(){var b=this,a=[];this.handlers=[];this.isSubscribed=!1;this.handleEvent=function(c){-1===a.indexOf(c)&&(a.push(c),b.handlers.forEach(function(a){a(c)}),runtime.setTimeout(function(){a.splice(a.indexOf(c),1)},0))}}function e(b){var a=b.scrollX,c=b.scrollY;this.restore=function(){b.scrollX===a&&b.scrollY===c||b.scrollTo(a,c)}}function n(b){var a=b.scrollTop,c=b.scrollLeft;this.restore=function(){if(b.scrollTop!==a||b.scrollLeft!==c)b.scrollTop=a,b.scrollLeft= +c}}function m(b,a,c){var d="on"+a,e=!1;b.attachEvent&&(e=b.attachEvent(d,c));!e&&b.addEventListener&&(b.addEventListener(a,c,!1),e=!0);e&&!r[a]||!b.hasOwnProperty(d)||(b[d]=c)}function q(){return g.getDOM().activeElement===b}var b=g.getOdfCanvas().getElement(),h=runtime.getWindow(),r={beforecut:!0,beforepaste:!0},d;this.subscribe=function(f,a){var c=h&&d[f];c?(c.handlers.push(a),c.isSubscribed||(c.isSubscribed=!0,m(h,f,c.handleEvent),m(b,f,c.handleEvent))):m(b,f,a)};this.unsubscribe=function(f,a){var c= +h&&d[f],e=c&&c.handlers.indexOf(a);c?-1!==e&&c.handlers.splice(e,1):(c=b,e="on"+f,c.detachEvent&&c.detachEvent(e,a),c.removeEventListener&&c.removeEventListener(f,a,!1),c[e]===a&&(c[e]=null))};this.hasFocus=q;this.focus=function(){var d;if(!q()){for(d=b;d&&!d.scrollTop&&!d.scrollLeft;)d=d.parentNode;d=d?new n(d):h?new e(h):null;b.focus();d&&d.restore()}};d={mousedown:new k,mouseup:new k}}; +// Input 57 +runtime.loadClass("gui.SelectionMover");gui.ShadowCursor=function(g){var k=g.getDOM().createRange(),e=!0;this.removeFromOdtDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return k};this.setSelectedRange=function(g,m){k=g;e=!1!==m};this.hasForwardSelection=function(){return e};this.getOdtDocument=function(){return g};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};k.setStart(g.getRootNode(),0)}; +gui.ShadowCursor.ShadowCursorMemberId="";(function(){return gui.ShadowCursor})(); +// Input 58 /* Copyright (C) 2013 KO GmbH @@ -1508,264 +1506,12 @@ y=v.createElementNS(r,"draw:image"),v=v.createElementNS(r,"draw:frame");y.setAtt @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.OpInsertTable=function(){function g(b,a){var c;if(1===d.length)c=d[0];else if(3===d.length)switch(b){case 0:c=d[0];break;case m-1:c=d[2];break;default:c=d[1]}else c=d[b];if(1===c.length)return c[0];if(3===c.length)switch(a){case 0:return c[0];case f-1:return c[2];default:return c[1]}return c[a]}var l,c,m,f,n,b,p,r,d;this.init=function(k){l=k.memberid;c=k.timestamp;n=k.position;m=k.initialRows;f=k.initialColumns;b=k.tableName;p=k.tableStyleName;r=k.tableColumnStyleName;d=k.tableCellStyleMatrix}; -this.isEdit=!0;this.execute=function(d){var a=d.getTextNodeAtStep(n),e=d.getRootNode();if(a){var h=d.getDOM(),q=h.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table"),u=h.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-column"),x,v,y,w;p&&q.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",p);b&&q.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:name",b);u.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0", -"table:number-columns-repeated",f);r&&u.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",r);q.appendChild(u);for(y=0;y - - @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 . - - 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.OpInsertText=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.position;m=f.text};this.isEdit=!0;this.execute=function(f){var n,b,p,r=null,d=f.getDOM(),k,a=0,e,h;f.upgradeWhitespacesAtPosition(c);if(n=f.getTextNodeAtStep(c,g)){b=n.textNode;r=b.nextSibling;p=b.parentNode;k=f.getParagraphElement(b);for(h=0;h - - @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 . - - 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("core.DomUtils"); -ops.OpRemoveText=function(){function g(c){function d(a){return p.hasOwnProperty(a.namespaceURI)||"br"===a.localName&&n.isLineBreak(a.parentNode)||a.nodeType===Node.TEXT_NODE&&p.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(p.hasOwnProperty(a.namespaceURI)||!f(a))return!1;a=a.nextSibling}return!0}function a(e){var h;e.nodeType===Node.TEXT_NODE?(h=e.parentNode,h.removeChild(e)): -h=b.removeUnwantedNodes(e,d);return!n.isParagraph(h)&&h!==c&&f(h)?a(h):h}this.isEmpty=f;this.mergeChildrenIntoParent=a}var l,c,m,f,n,b,p={};this.init=function(g){runtime.assert(0<=g.length,"OpRemoveText only supports positive lengths");l=g.memberid;c=g.timestamp;m=parseInt(g.position,10);f=parseInt(g.length,10);n=new odf.OdfUtils;b=new core.DomUtils;p[odf.Namespaces.dbns]=!0;p[odf.Namespaces.dcns]=!0;p[odf.Namespaces.dr3dns]=!0;p[odf.Namespaces.drawns]=!0;p[odf.Namespaces.chartns]=!0;p[odf.Namespaces.formns]= -!0;p[odf.Namespaces.numberns]=!0;p[odf.Namespaces.officens]=!0;p[odf.Namespaces.presentationns]=!0;p[odf.Namespaces.stylens]=!0;p[odf.Namespaces.svgns]=!0;p[odf.Namespaces.tablens]=!0;p[odf.Namespaces.textns]=!0};this.isEdit=!0;this.execute=function(p){var d,k,a,e,h=p.getCursor(l),q=new g(p.getRootNode());p.upgradeWhitespacesAtPosition(m);p.upgradeWhitespacesAtPosition(m+f);k=p.convertCursorToDomRange(m,f);b.splitBoundaries(k);d=p.getParagraphElement(k.startContainer);a=n.getTextElements(k,!1,!0); -e=n.getParagraphElements(k);k.detach();a.forEach(function(a){q.mergeChildrenIntoParent(a)});k=e.reduce(function(a,b){var c,e=!1,d=a,h=b,f,k=null;q.isEmpty(a)&&(e=!0,b.parentNode!==a.parentNode&&(f=b.parentNode,a.parentNode.insertBefore(b,a.nextSibling)),h=a,d=b,k=d.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo")[0]||d.firstChild);for(;h.hasChildNodes();)c=e?h.lastChild:h.firstChild,h.removeChild(c),"editinfo"!==c.localName&&d.insertBefore(c,k);f&&q.isEmpty(f)&&q.mergeChildrenIntoParent(f); -q.mergeChildrenIntoParent(h);return d});p.emit(ops.OdtDocument.signalStepsRemoved,{position:m,length:f});p.downgradeWhitespacesAtPosition(m);p.fixCursorPositions();p.getOdfCanvas().refreshSize();p.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:k||d,memberId:l,timeStamp:c});h&&(h.resetSelectionType(),p.emit(ops.OdtDocument.signalCursorMoved,h));p.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveText",memberid:l,timestamp:c,position:m,length:f}}}; -// Input 55 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpSplitParagraph=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.position;m=new odf.OdfUtils};this.isEdit=!0;this.execute=function(f){var n,b,p,r,d,k,a;f.upgradeWhitespacesAtPosition(c);n=f.getTextNodeAtStep(c,g);if(!n)return!1;b=f.getParagraphElement(n.textNode);if(!b)return!1;p=m.isListItem(b.parentNode)?b.parentNode:b;0===n.offset?(a=n.textNode.previousSibling,k=null):(a=n.textNode,k=n.offset>=n.textNode.length?null:n.textNode.splitText(n.offset));for(r=n.textNode;r!== -p;){r=r.parentNode;d=r.cloneNode(!1);k&&d.appendChild(k);if(a)for(;a&&a.nextSibling;)d.appendChild(a.nextSibling);else for(;r.firstChild;)d.appendChild(r.firstChild);r.parentNode.insertBefore(d,r.nextSibling);a=r;k=d}m.isListItem(k)&&(k=k.childNodes[0]);0===n.textNode.length&&n.textNode.parentNode.removeChild(n.textNode);f.emit(ops.OdtDocument.signalStepsInserted,{position:c,length:1});f.fixCursorPositions();f.getOdfCanvas().refreshSize();f.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:b, -memberId:g,timeStamp:l});f.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:k,memberId:g,timeStamp:l});f.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph",memberid:g,timestamp:l,position:c}}}; -// Input 56 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.OpSetParagraphStyle=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.position;m=f.styleName};this.isEdit=!0;this.execute=function(f){var n;n=f.getIteratorAtPosition(c);return(n=f.getParagraphElement(n.container()))?(""!==m?n.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","text:style-name",m):n.removeAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","style-name"),f.getOdfCanvas().refreshSize(),f.emit(ops.OdtDocument.signalParagraphChanged, -{paragraphElement:n,timeStamp:l,memberId:g}),f.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=function(){return{optype:"SetParagraphStyle",memberid:g,timestamp:l,position:c,styleName:m}}}; -// Input 57 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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"); -ops.OpUpdateParagraphStyle=function(){function g(b,c){var d,f,a=c?c.split(","):[];for(d=0;d - - @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 . - - 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"); -ops.OpAddStyle=function(){var g,l,c,m,f,n,b=odf.Namespaces.stylens;this.init=function(b){g=b.memberid;l=b.timestamp;c=b.styleName;m=b.styleFamily;f="true"===b.isAutomaticStyle||!0===b.isAutomaticStyle;n=b.setProperties};this.isEdit=!0;this.execute=function(g){var l=g.getOdfCanvas().odfContainer(),d=g.getFormatting(),k=g.getDOM().createElementNS(b,"style:style");if(!k)return!1;n&&d.updateStyle(k,n);k.setAttributeNS(b,"style:family",m);k.setAttributeNS(b,"style:name",c);f?l.rootElement.automaticStyles.appendChild(k): -l.rootElement.styles.appendChild(k);g.getOdfCanvas().refreshCSS();f||g.emit(ops.OdtDocument.signalCommonStyleCreated,{name:c,family:m});return!0};this.spec=function(){return{optype:"AddStyle",memberid:g,timestamp:l,styleName:c,styleFamily:m,isAutomaticStyle:f,setProperties:n}}}; +gui.UndoManager=function(){};gui.UndoManager.prototype.subscribe=function(g,k){};gui.UndoManager.prototype.unsubscribe=function(g,k){};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 59 /* - Copyright (C) 2012-2013 KO GmbH + Copyright (C) 2013 KO GmbH @licstart The JavaScript code in this page is free software: you can redistribute it @@ -1800,11 +1546,12 @@ l.rootElement.styles.appendChild(k);g.getOdfCanvas().refreshCSS();f||g.emit(ops. @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.OpRemoveStyle=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f.timestamp;c=f.styleName;m=f.styleFamily};this.isEdit=!0;this.execute=function(f){var g=f.getStyleElement(c,m);if(!g)return!1;g.parentNode.removeChild(g);f.getOdfCanvas().refreshCSS();f.emit(ops.OdtDocument.signalCommonStyleDeleted,{name:c,family:m});return!0};this.spec=function(){return{optype:"RemoveStyle",memberid:g,timestamp:l,styleName:c,styleFamily:m}}}; +gui.UndoStateRules=function(){function g(e){return e.spec().optype}function k(e){return e.isEdit}this.getOpType=g;this.isEditOperation=k;this.isPartOfOperationSet=function(e,n){if(e.isEdit){if(0===n.length)return!0;var m;if(m=n[n.length-1].isEdit)a:{m=n.filter(k);var q=g(e),b;b:switch(q){case "RemoveText":case "InsertText":b=!0;break b;default:b=!1}if(b&&q===g(m[0])){if(1===m.length){m=!0;break a}q=m[m.length-2].spec().position;m=m[m.length-1].spec().position;b=e.spec().position;if(m===b-(m-q)){m= +!0;break a}}m=!1}return m}return!0}}; // Input 60 /* - Copyright (C) 2012-2013 KO GmbH + Copyright (C) 2012 KO GmbH @licstart The JavaScript code in this page is free software: you can redistribute it @@ -1839,10 +1586,8 @@ ops.OpRemoveStyle=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=f. @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.OpAddAnnotation=function(){function g(b,c,f){var d=b.getTextNodeAtStep(f,l);d&&(b=d.textNode,f=b.parentNode,d.offset!==b.length&&b.splitText(d.offset),f.insertBefore(c,b.nextSibling),0===b.length&&f.removeChild(b))}var l,c,m,f,n;this.init=function(b){l=b.memberid;c=parseInt(b.timestamp,10);m=parseInt(b.position,10);f=parseInt(b.length,10)||0;n=b.name};this.isEdit=!0;this.execute=function(b){var p={},r=b.getPositionFilter(),d=b.getCursor(l),k=b.getCursorPosition(l),k=m-k-1,a=new Date(c),e,h,q, -u,x;x=b.getDOM();e=x.createElementNS(odf.Namespaces.officens,"office:annotation");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);h=x.createElementNS(odf.Namespaces.dcns,"dc:creator");h.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",l);h.textContent=b.getMember(l).getProperties().fullName;q=x.createElementNS(odf.Namespaces.dcns,"dc:date");q.appendChild(x.createTextNode(a.toISOString()));a=x.createElementNS(odf.Namespaces.textns,"text:list");u=x.createElementNS(odf.Namespaces.textns, -"text:list-item");x=x.createElementNS(odf.Namespaces.textns,"text:p");u.appendChild(x);a.appendChild(u);e.appendChild(h);e.appendChild(q);e.appendChild(a);p.node=e;if(!p.node)return!1;if(f){e=b.getDOM().createElementNS(odf.Namespaces.officens,"office:annotation-end");e.setAttributeNS(odf.Namespaces.officens,"office:name",n);p.end=e;if(!p.end)return!1;g(b,p.end,m+f)}g(b,p.node,m);b.emit(ops.OdtDocument.signalStepsInserted,{position:m,length:f});d&&(r=d.getStepCounter().countSteps(k,r),d.move(r),d.resetSelectionType(), -b.emit(ops.OdtDocument.signalCursorMoved,d));b.getOdfCanvas().addAnnotation(p);b.fixCursorPositions();return!0};this.spec=function(){return{optype:"AddAnnotation",memberid:l,timestamp:c,position:m,length:f,name:n}}}; +ops.EditInfo=function(g,k){function e(){var e=[],b;for(b in m)m.hasOwnProperty(b)&&e.push({memberid:b,time:m[b].time});e.sort(function(b,e){return b.time-e.time});return e}var n,m={};this.getNode=function(){return n};this.getOdtDocument=function(){return k};this.getEdits=function(){return m};this.getSortedEdits=function(){return e()};this.addEdit=function(e,b){m[e]={time:b}};this.clearEdits=function(){m={}};this.destroy=function(e){g.parentNode&&g.removeChild(n);e()};n=k.getDOM().createElementNS("urn:webodf:names:editinfo", +"editinfo");g.insertBefore(n,g.firstChild)}; // Input 61 /* @@ -1881,36 +1626,50 @@ b.emit(ops.OdtDocument.signalCursorMoved,d));b.getOdfCanvas().addAnnotation(p);b @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,c,m,f;this.init=function(n){g=n.memberid;l=n.timestamp;c=parseInt(n.position,10);m=parseInt(n.length,10);f=new core.DomUtils};this.isEdit=!0;this.execute=function(g){for(var b=g.getIteratorAtPosition(c).container(),l,r,d;b.namespaceURI!==odf.Namespaces.officens||"annotation"!==b.localName;)b=b.parentNode;if(null===b)return!1;(l=b.getAttributeNS(odf.Namespaces.officens,"name"))&&(r=f.getElementsByTagNameNS(g.getRootNode(),odf.Namespaces.officens,"annotation-end").filter(function(b){return l=== -b.getAttributeNS(odf.Namespaces.officens,"name")})[0]||null);g.getOdfCanvas().forgetAnnotations();for(d=f.getElementsByTagNameNS(b,"urn:webodf:names:cursor","cursor");d.length;)b.parentNode.insertBefore(d.pop(),b);b.parentNode.removeChild(b);r&&r.parentNode.removeChild(r);g.emit(ops.OdtDocument.signalStepsRemoved,{position:0 + Copyright (C) 2012-2013 KO GmbH @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. + 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 WebODF. If not, see . - @licend + along with this code. If not, see . + 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("ops.Member");ops.OpAddMember=function(){var g,l,c;this.init=function(m){g=m.memberid;l=parseInt(m.timestamp,10);c=m.setProperties};this.isEdit=!1;this.execute=function(l){if(l.getMember(g))return!1;var f=new ops.Member(g,c);l.addMember(f);l.emit(ops.OdtDocument.signalMemberAdded,f);return!0};this.spec=function(){return{optype:"AddMember",memberid:g,timestamp:l,setProperties:c}}}; +ops.OpAddCursor=function(){var g,k;this.init=function(e){g=e.memberid;k=e.timestamp};this.isEdit=!1;this.execute=function(e){var k=e.getCursor(g);if(k)return!1;k=new ops.OdtCursor(g,e);e.addCursor(k);e.emit(ops.OdtDocument.signalCursorAdded,k);return!0};this.spec=function(){return{optype:"AddCursor",memberid:g,timestamp:k}}}; // Input 63 /* @@ -1936,36 +1695,374 @@ runtime.loadClass("ops.Member");ops.OpAddMember=function(){var g,l,c;this.init=f @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -runtime.loadClass("ops.Member");runtime.loadClass("xmldom.XPath"); -ops.OpUpdateMember=function(){function g(){for(var b=new xmldom.XPath,c="//dc:creator[@editinfo:memberid='"+l+"']",b=b.getODFElementsWithXPath(n.getRootNode(),c,function(b){return"editinfo"===b?"urn:webodf:names:editinfo":odf.Namespaces.resolvePrefix(b)}),c=0;c + Copyright (C) 2012-2013 KO GmbH @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. + 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 WebODF. If not, see . - @licend + along with this code. If not, see . + 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("ops.Member");ops.OpRemoveMember=function(){var g,l;this.init=function(c){g=c.memberid;l=parseInt(c.timestamp,10)};this.isEdit=!1;this.execute=function(c){if(!c.getMember(g))return!1;c.removeMember(g);c.emit(ops.OdtDocument.signalMemberRemoved,g);return!0};this.spec=function(){return{optype:"RemoveMember",memberid:g,timestamp:l}}}; +runtime.loadClass("odf.Namespaces"); +ops.OpAddStyle=function(){var g,k,e,n,m,q,b=odf.Namespaces.stylens;this.init=function(b){g=b.memberid;k=b.timestamp;e=b.styleName;n=b.styleFamily;m="true"===b.isAutomaticStyle||!0===b.isAutomaticStyle;q=b.setProperties};this.isEdit=!0;this.execute=function(g){var k=g.getOdfCanvas().odfContainer(),d=g.getFormatting(),f=g.getDOM().createElementNS(b,"style:style");if(!f)return!1;q&&d.updateStyle(f,q);f.setAttributeNS(b,"style:family",n);f.setAttributeNS(b,"style:name",e);m?k.rootElement.automaticStyles.appendChild(f): +k.rootElement.styles.appendChild(f);g.getOdfCanvas().refreshCSS();m||g.emit(ops.OdtDocument.signalCommonStyleCreated,{name:e,family:n});return!0};this.spec=function(){return{optype:"AddStyle",memberid:g,timestamp:k,styleName:e,styleFamily:n,isAutomaticStyle:m,setProperties:q}}}; // Input 65 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("gui.StyleHelper");runtime.loadClass("odf.OdfUtils"); +ops.OpApplyDirectStyling=function(){function g(b){var e=0<=m?n+m:n,d=b.getIteratorAtPosition(0<=m?n:n+m),e=m?b.getIteratorAtPosition(e):d;b=b.getDOM().createRange();b.setStart(d.container(),d.unfilteredDomOffset());b.setEnd(e.container(),e.unfilteredDomOffset());return b}var k,e,n,m,q,b=new odf.OdfUtils;this.init=function(b){k=b.memberid;e=b.timestamp;n=parseInt(b.position,10);m=parseInt(b.length,10);q=b.setProperties};this.isEdit=!0;this.execute=function(h){var m=g(h),d=b.getImpactedParagraphs(m); +(new gui.StyleHelper(h.getFormatting())).applyStyle(k,m,q);m.detach();h.getOdfCanvas().refreshCSS();h.fixCursorPositions();d.forEach(function(b){h.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:b,memberId:k,timeStamp:e})});h.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"ApplyDirectStyling",memberid:k,timestamp:e,position:n,length:m,setProperties:q}}}; +// Input 66 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpInsertImage=function(){var g,k,e,n,m,q,b,h,r=odf.Namespaces.drawns,d=odf.Namespaces.svgns,f=odf.Namespaces.textns,a=odf.Namespaces.xlinkns;this.init=function(a){g=a.memberid;k=a.timestamp;e=a.position;n=a.filename;m=a.frameWidth;q=a.frameHeight;b=a.frameStyleName;h=a.frameName};this.isEdit=!0;this.execute=function(c){var p=c.getOdfCanvas(),l=c.getTextNodeAtStep(e,g),u,B;if(!l)return!1;u=l.textNode;B=c.getParagraphElement(u);var l=l.offset!==u.length?u.splitText(l.offset):u.nextSibling,w=c.getDOM(), +y=w.createElementNS(r,"draw:image"),w=w.createElementNS(r,"draw:frame");y.setAttributeNS(a,"xlink:href",n);y.setAttributeNS(a,"xlink:type","simple");y.setAttributeNS(a,"xlink:show","embed");y.setAttributeNS(a,"xlink:actuate","onLoad");w.setAttributeNS(r,"draw:style-name",b);w.setAttributeNS(r,"draw:name",h);w.setAttributeNS(f,"text:anchor-type","as-char");w.setAttributeNS(d,"svg:width",m);w.setAttributeNS(d,"svg:height",q);w.appendChild(y);u.parentNode.insertBefore(w,l);c.emit(ops.OdtDocument.signalStepsInserted, +{position:e,length:1});0===u.length&&u.parentNode.removeChild(u);p.addCssForFrameWithImage(w);p.refreshCSS();c.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:B,memberId:g,timeStamp:k});p.rerenderAnnotations();return!0};this.spec=function(){return{optype:"InsertImage",memberid:g,timestamp:k,filename:n,position:e,frameWidth:m,frameHeight:q,frameStyleName:b,frameName:h}}}; +// Input 67 +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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.OpInsertTable=function(){function g(b,a){var c;if(1===d.length)c=d[0];else if(3===d.length)switch(b){case 0:c=d[0];break;case n-1:c=d[2];break;default:c=d[1]}else c=d[b];if(1===c.length)return c[0];if(3===c.length)switch(a){case 0:return c[0];case m-1:return c[2];default:return c[1]}return c[a]}var k,e,n,m,q,b,h,r,d;this.init=function(f){k=f.memberid;e=f.timestamp;q=f.position;n=f.initialRows;m=f.initialColumns;b=f.tableName;h=f.tableStyleName;r=f.tableColumnStyleName;d=f.tableCellStyleMatrix}; +this.isEdit=!0;this.execute=function(d){var a=d.getTextNodeAtStep(q),c=d.getRootNode();if(a){var p=d.getDOM(),l=p.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table"),u=p.createElementNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:table-column"),B,w,y,v;h&&l.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",h);b&&l.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:name",b);u.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0", +"table:number-columns-repeated",m);r&&u.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:table:1.0","table:style-name",r);l.appendChild(u);for(y=0;y + + @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 . + + 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.OpInsertText=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.position;n=m.text};this.isEdit=!0;this.execute=function(m){var q,b,h,r=null,d=m.getDOM(),f,a=0,c,p;m.upgradeWhitespacesAtPosition(e);if(q=m.getTextNodeAtStep(e,g)){b=q.textNode;r=b.nextSibling;h=b.parentNode;f=m.getParagraphElement(b);for(p=0;p + + @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 . + + 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.OpMoveCursor=function(){var g,k,e,n,m;this.init=function(q){g=q.memberid;k=q.timestamp;e=q.position;n=q.length||0;m=q.selectionType||ops.OdtCursor.RangeSelection};this.isEdit=!1;this.execute=function(k){var b=k.getCursor(g),h;if(!b)return!1;h=k.convertCursorToDomRange(e,n);b.setSelectedRange(h,0<=n);b.setSelectionType(m);k.emit(ops.OdtDocument.signalCursorMoved,b);return!0};this.spec=function(){return{optype:"MoveCursor",memberid:g,timestamp:k,position:e,length:n,selectionType:m}}}; +// Input 70 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("core.DomUtils"); +ops.OpRemoveAnnotation=function(){var g,k,e,n,m;this.init=function(q){g=q.memberid;k=q.timestamp;e=parseInt(q.position,10);n=parseInt(q.length,10);m=new core.DomUtils};this.isEdit=!0;this.execute=function(g){for(var b=g.getIteratorAtPosition(e).container(),h,k,d;b.namespaceURI!==odf.Namespaces.officens||"annotation"!==b.localName;)b=b.parentNode;if(null===b)return!1;(h=b.getAttributeNS(odf.Namespaces.officens,"name"))&&(k=m.getElementsByTagNameNS(g.getRootNode(),odf.Namespaces.officens,"annotation-end").filter(function(b){return h=== +b.getAttributeNS(odf.Namespaces.officens,"name")})[0]||null);g.getOdfCanvas().forgetAnnotations();for(d=m.getElementsByTagNameNS(b,"urn:webodf:names:cursor","cursor");d.length;)b.parentNode.insertBefore(d.pop(),b);b.parentNode.removeChild(b);k&&k.parentNode.removeChild(k);g.emit(ops.OdtDocument.signalStepsRemoved,{position:0 + + @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 . + + 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.OpRemoveBlob=function(){var g,k,e;this.init=function(n){g=n.memberid;k=n.timestamp;e=n.filename};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().removeBlob(e);return!0};this.spec=function(){return{optype:"RemoveBlob",memberid:g,timestamp:k,filename:e}}}; +// Input 72 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpRemoveCursor=function(){var g,k;this.init=function(e){g=e.memberid;k=e.timestamp};this.isEdit=!1;this.execute=function(e){return e.removeCursor(g)?!0:!1};this.spec=function(){return{optype:"RemoveCursor",memberid:g,timestamp:k}}}; +// Input 73 /* Copyright (C) 2013 KO GmbH @@ -1990,9 +2087,308 @@ runtime.loadClass("ops.Member");ops.OpRemoveMember=function(){var g,l;this.init= @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.OpUpdateMetadata=function(){var g,l,c,m;this.init=function(f){g=f.memberid;l=parseInt(f.timestamp,10);c=f.setProperties;m=f.removedProperties};this.isEdit=!0;this.execute=function(f){f=f.getOdfCanvas().odfContainer().getMetadataManager();var g=[],b=["dc:date","dc:creator","meta:editing-cycles"];c&&b.forEach(function(b){if(c[b])return!1});m&&(b.forEach(function(b){if(-1!==g.indexOf(b))return!1}),g=m.attributes.split(","));f.setMetadata(c,g);return!0};this.spec=function(){return{optype:"UpdateMetadata", -memberid:g,timestamp:l,setProperties:c,removedProperties:m}}}; -// Input 66 +runtime.loadClass("ops.Member");ops.OpRemoveMember=function(){var g,k;this.init=function(e){g=e.memberid;k=parseInt(e.timestamp,10)};this.isEdit=!1;this.execute=function(e){if(!e.getMember(g))return!1;e.removeMember(g);e.emit(ops.OdtDocument.signalMemberRemoved,g);return!0};this.spec=function(){return{optype:"RemoveMember",memberid:g,timestamp:k}}}; +// Input 74 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpRemoveStyle=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.styleName;n=m.styleFamily};this.isEdit=!0;this.execute=function(g){var k=g.getStyleElement(e,n);if(!k)return!1;k.parentNode.removeChild(k);g.getOdfCanvas().refreshCSS();g.emit(ops.OdtDocument.signalCommonStyleDeleted,{name:e,family:n});return!0};this.spec=function(){return{optype:"RemoveStyle",memberid:g,timestamp:k,styleName:e,styleFamily:n}}}; +// Input 75 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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("core.DomUtils"); +ops.OpRemoveText=function(){function g(e){function d(a){return h.hasOwnProperty(a.namespaceURI)||"br"===a.localName&&q.isLineBreak(a.parentNode)||a.nodeType===Node.TEXT_NODE&&h.hasOwnProperty(a.parentNode.namespaceURI)}function f(a){if(q.isCharacterElement(a))return!1;if(a.nodeType===Node.TEXT_NODE)return 0===a.textContent.length;for(a=a.firstChild;a;){if(h.hasOwnProperty(a.namespaceURI)||!f(a))return!1;a=a.nextSibling}return!0}function a(c){var g;c.nodeType===Node.TEXT_NODE?(g=c.parentNode,g.removeChild(c)): +g=b.removeUnwantedNodes(c,d);return!q.isParagraph(g)&&g!==e&&f(g)?a(g):g}this.isEmpty=f;this.mergeChildrenIntoParent=a}var k,e,n,m,q,b,h={};this.init=function(g){runtime.assert(0<=g.length,"OpRemoveText only supports positive lengths");k=g.memberid;e=g.timestamp;n=parseInt(g.position,10);m=parseInt(g.length,10);q=new odf.OdfUtils;b=new core.DomUtils;h[odf.Namespaces.dbns]=!0;h[odf.Namespaces.dcns]=!0;h[odf.Namespaces.dr3dns]=!0;h[odf.Namespaces.drawns]=!0;h[odf.Namespaces.chartns]=!0;h[odf.Namespaces.formns]= +!0;h[odf.Namespaces.numberns]=!0;h[odf.Namespaces.officens]=!0;h[odf.Namespaces.presentationns]=!0;h[odf.Namespaces.stylens]=!0;h[odf.Namespaces.svgns]=!0;h[odf.Namespaces.tablens]=!0;h[odf.Namespaces.textns]=!0};this.isEdit=!0;this.execute=function(h){var d,f,a,c,p=h.getCursor(k),l=new g(h.getRootNode());h.upgradeWhitespacesAtPosition(n);h.upgradeWhitespacesAtPosition(n+m);f=h.convertCursorToDomRange(n,m);b.splitBoundaries(f);d=h.getParagraphElement(f.startContainer);a=q.getTextElements(f,!1,!0); +c=q.getParagraphElements(f);f.detach();a.forEach(function(a){l.mergeChildrenIntoParent(a)});f=c.reduce(function(a,c){var b,d=!1,f=a,e=c,g,h=null;l.isEmpty(a)&&(d=!0,c.parentNode!==a.parentNode&&(g=c.parentNode,a.parentNode.insertBefore(c,a.nextSibling)),e=a,f=c,h=f.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo")[0]||f.firstChild);for(;e.hasChildNodes();)b=d?e.lastChild:e.firstChild,e.removeChild(b),"editinfo"!==b.localName&&f.insertBefore(b,h);g&&l.isEmpty(g)&&l.mergeChildrenIntoParent(g); +l.mergeChildrenIntoParent(e);return f});h.emit(ops.OdtDocument.signalStepsRemoved,{position:n,length:m});h.downgradeWhitespacesAtPosition(n);h.fixCursorPositions();h.getOdfCanvas().refreshSize();h.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:f||d,memberId:k,timeStamp:e});p&&(p.resetSelectionType(),h.emit(ops.OdtDocument.signalCursorMoved,p));h.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"RemoveText",memberid:k,timestamp:e,position:n,length:m}}}; +// Input 76 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpSetBlob=function(){var g,k,e,n,m;this.init=function(q){g=q.memberid;k=q.timestamp;e=q.filename;n=q.mimetype;m=q.content};this.isEdit=!0;this.execute=function(g){g.getOdfCanvas().odfContainer().setBlob(e,n,m);return!0};this.spec=function(){return{optype:"SetBlob",memberid:g,timestamp:k,filename:e,mimetype:n,content:m}}}; +// Input 77 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpSetParagraphStyle=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.position;n=m.styleName};this.isEdit=!0;this.execute=function(m){var q;q=m.getIteratorAtPosition(e);return(q=m.getParagraphElement(q.container()))?(""!==n?q.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","text:style-name",n):q.removeAttributeNS("urn:oasis:names:tc:opendocument:xmlns:text:1.0","style-name"),m.getOdfCanvas().refreshSize(),m.emit(ops.OdtDocument.signalParagraphChanged, +{paragraphElement:q,timeStamp:k,memberId:g}),m.getOdfCanvas().rerenderAnnotations(),!0):!1};this.spec=function(){return{optype:"SetParagraphStyle",memberid:g,timestamp:k,position:e,styleName:n}}}; +// Input 78 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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.OpSplitParagraph=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=m.timestamp;e=m.position;n=new odf.OdfUtils};this.isEdit=!0;this.execute=function(m){var q,b,h,r,d,f,a;m.upgradeWhitespacesAtPosition(e);q=m.getTextNodeAtStep(e,g);if(!q)return!1;b=m.getParagraphElement(q.textNode);if(!b)return!1;h=n.isListItem(b.parentNode)?b.parentNode:b;0===q.offset?(a=q.textNode.previousSibling,f=null):(a=q.textNode,f=q.offset>=q.textNode.length?null:q.textNode.splitText(q.offset));for(r=q.textNode;r!== +h;){r=r.parentNode;d=r.cloneNode(!1);f&&d.appendChild(f);if(a)for(;a&&a.nextSibling;)d.appendChild(a.nextSibling);else for(;r.firstChild;)d.appendChild(r.firstChild);r.parentNode.insertBefore(d,r.nextSibling);a=r;f=d}n.isListItem(f)&&(f=f.childNodes[0]);0===q.textNode.length&&q.textNode.parentNode.removeChild(q.textNode);m.emit(ops.OdtDocument.signalStepsInserted,{position:e,length:1});m.fixCursorPositions();m.getOdfCanvas().refreshSize();m.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:b, +memberId:g,timeStamp:k});m.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:f,memberId:g,timeStamp:k});m.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph",memberid:g,timestamp:k,position:e}}}; +// Input 79 +/* + + Copyright (C) 2013 KO GmbH + + @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 . + @licend + + @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 b="//dc:creator[@editinfo:memberid='"+k+"']",b=xmldom.XPath.getODFElementsWithXPath(q.getRootNode(),b,function(b){return"editinfo"===b?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(b)}),e;for(e=0;e + + @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 . + @licend + + @source: http://www.webodf.org/ + @source: https://github.com/kogmbh/WebODF/ +*/ +ops.OpUpdateMetadata=function(){var g,k,e,n;this.init=function(m){g=m.memberid;k=parseInt(m.timestamp,10);e=m.setProperties;n=m.removedProperties};this.isEdit=!0;this.execute=function(g){g=g.getOdfCanvas().odfContainer().getMetadataManager();var k=[],b=["dc:date","dc:creator","meta:editing-cycles"];e&&b.forEach(function(b){if(e[b])return!1});n&&(b.forEach(function(b){if(-1!==k.indexOf(b))return!1}),k=n.attributes.split(","));g.setMetadata(e,k);return!0};this.spec=function(){return{optype:"UpdateMetadata", +memberid:g,timestamp:k,setProperties:e,removedProperties:n}}}; +// Input 81 +/* + + Copyright (C) 2012-2013 KO GmbH + + @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 . + + 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"); +ops.OpUpdateParagraphStyle=function(){function g(b,e){var d,f,a=e?e.split(","):[];for(d=0;d @@ -2032,546 +2428,93 @@ memberid:g,timestamp:l,setProperties:c,removedProperties:m}}}; */ 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(c){return function(){return new c}}var l;this.register=function(c,g){l[c]=g};this.create=function(c){var g=null,f=l[c.optype];f&&(g=f(c),g.init(c));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), +ops.OperationFactory=function(){function g(e){return function(){return new e}}var k;this.register=function(e,g){k[e]=g};this.create=function(e){var g=null,m=k[e.optype];m&&(g=m(e),g.init(e));return g};k={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 67 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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.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 c(){v.setUnfilteredPosition(g.getNode(),0);return v}function m(a,b){var c,e=null;a&&(c=b?a[a.length-1]:a[0]);c&&(e={top:c.top,left:b?c.right:c.left,bottom:c.bottom});return e}function f(a,b,c,e){var d=a.nodeType;c.setStart(a,b);c.collapse(!e);e=m(c.getClientRects(),!0===e);!e&&0a?-1:1;for(a=Math.abs(a);0m?q.previousPosition():q.nextPosition());)if(ha.check(),g.acceptPosition(q)===t&&(p+=1,n=q.container(),v=f(n,q.unfilteredDomOffset(),I),v.top!==Y)){if(v.top!==G&&G!==Y)break;G=v.top;v=Math.abs(V-v.left);if(null===r||va?(e=g.previousPosition,d=-1):(e=g.nextPosition,d=1);for(h=f(g.container(),g.unfilteredDomOffset(),n);e.call(g);)if(b.acceptPosition(g)===t){if(u.getParagraphElement(g.getCurrentNode())!==m)break;k=f(g.container(),g.unfilteredDomOffset(),n);if(k.bottom!==h.bottom&&(h=k.top>=h.top&&k.bottomh.bottom,!h))break;q+= -d;h=k}n.detach();return q}function q(a,b,e){runtime.assert(null!==a,"SelectionMover.countStepsToPosition called with element===null");var d=c(),h=d.container(),f=d.unfilteredDomOffset(),k=0,g=new core.LoopWatchDog(1E4);for(d.setUnfilteredPosition(a,b);e.acceptPosition(d)!==t&&d.previousPosition();)g.check();a=d.container();runtime.assert(Boolean(a),"SelectionMover.countStepsToPosition: positionIterator.container() returned null");b=d.unfilteredDomOffset();for(d.setUnfilteredPosition(h,f);e.acceptPosition(d)!== -t&&d.previousPosition();)g.check();h=x.comparePoints(a,b,d.container(),d.unfilteredDomOffset());if(0>h)for(;d.nextPosition()&&(g.check(),e.acceptPosition(d)===t&&(k+=1),d.container()!==a||d.unfilteredDomOffset()!==b););else if(0 - - @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 . - - 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("core.PositionFilter");runtime.loadClass("odf.OdfUtils"); -(function(){function g(c,g,f){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)===u)break;while(a.nextPosition())}}function b(a){return a.nodeType===Node.ELEMENT_NODE&&a.getAttributeNS(d,"nodeId")}function p(a){var b=l;a.setAttributeNS(d,"nodeId",b.toString());l+=1;return b}function r(e,h){var f,k=null;for(e=e.childNodes[h]|| -e;!k&&e&&e!==c;)(f=b(e))&&(k=a[f])&&k.node!==e&&(runtime.log("Cloned node detected. Creating new bookmark"),k=null,e.removeAttributeNS(d,"nodeId")),e=e.parentNode;return k}var d="urn:webodf:names:steps",k={},a={},e=new odf.OdfUtils,h=new core.DomUtils,q,u=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.updateCache=function(c,d,h,g){var l;0===h&&e.isParagraph(d)?(l=!0,g||(c+=1)):d.hasChildNodes()&&d.childNodes[h]&&(d=d.childNodes[h],(l=e.isParagraph(d))&&(c+=1));l&&(h=b(d)||p(d),(g=a[h])?g.node=== -d?g.steps=c:(runtime.log("Cloned node detected. Creating new bookmark"),h=p(d),g=a[h]=new n(c,d)):g=a[h]=new n(c,d),h=g,c=Math.ceil(h.steps/f)*f,d=k[c],!d||h.steps>d.steps)&&(k[c]=h)};this.setToClosestStep=function(a,b){for(var c=Math.floor(a/f)*f,e;!e&&0!==c;)e=k[c],c-=f;e=e||q;e.setIteratorPosition(b);return e.steps};this.setToClosestDomPoint=function(a,b,e){var d;if(a===c&&0===b)d=q;else if(a===c&&b===c.childNodes.length)d=Object.keys(k).map(function(a){return k[a]}).reduce(function(a,b){return b.steps> -a.steps?b:a},q);else if(d=r(a,b),!d)for(e.setUnfilteredPosition(a,b);!d&&e.previousNode();)d=r(e.container(),e.unfilteredDomOffset());d=d||q;d.setIteratorPosition(e);return d.steps};this.updateCacheAtPoint=function(e,d){var g={};Object.keys(a).map(function(b){return a[b]}).filter(function(a){return a.steps>e}).forEach(function(e){var l=Math.ceil(e.steps/f)*f,m,q;if(h.containsNode(c,e.node)){if(d(e),m=Math.ceil(e.steps/f)*f,q=g[m],!q||e.steps>q.steps)g[m]=e}else delete a[b(e.node)];k[l]===e&&delete k[l]}); -Object.keys(g).forEach(function(a){k[a]=g[a]})};q=new function(a,b){this.steps=a;this.node=b;this.setIteratorPosition=function(a){a.setUnfilteredPosition(b,0);do if(g.acceptPosition(a)===u)break;while(a.nextPosition())}}(0,c)}var l=0;ops.StepsTranslator=function(c,l,f,n){function b(){var a=c();a!==p&&(runtime.log("Undo detected. Resetting steps cache"),p=a,r=new g(p,f,n),k=l(p))}var p=c(),r=new g(p,f,n),d=new core.DomUtils,k=l(c()),a=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.convertStepsToDomPoint= -function(c){var d,g;0>c&&(runtime.log("warn","Requested steps were negative ("+c+")"),c=0);b();for(d=r.setToClosestStep(c,k);dd.comparePoints(p,0,c,h),c=p,h=l?0: -p.childNodes.length);k.setUnfilteredPosition(c,h);l=k.container();m=k.unfilteredDomOffset();g&&f.acceptPosition(k)!==a&&(n=1);c=r.setToClosestDomPoint(c,h,k);if(0>d.comparePoints(k.container(),k.unfilteredDomOffset(),l,m))return 0b.steps&&(b.steps=0)})}};return ops.StepsTranslator})(); -// Input 69 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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(g){function l(f,g,d){var k,a;if(g&&(k=c.lookLeftForCharacter(g),1===k||2===k&&(c.scanRightForAnyCharacter(d)||c.scanRightForAnyCharacter(c.nextNode(f)))))return n;k=null===g&&c.isParagraph(f);a=c.lookRightForCharacter(d);if(k)return a?n:c.scanRightForAnyCharacter(d)?b:n;if(!a)return b;g=g||c.previousNode(f);return c.scanLeftForAnyCharacter(g)?b:n}var c=new odf.OdfUtils,m=Node.ELEMENT_NODE,f=Node.TEXT_NODE,n=core.PositionFilter.FilterResult.FILTER_ACCEPT,b=core.PositionFilter.FilterResult.FILTER_REJECT; -this.acceptPosition=function(p){var r=p.container(),d=r.nodeType,k,a,e;if(d!==m&&d!==f)return b;if(d===f){if(!c.isGroupingElement(r.parentNode)||c.isWithinTrackedChanges(r.parentNode,g()))return b;d=p.unfilteredDomOffset();k=r.data;runtime.assert(d!==k.length,"Unexpected offset.");if(0 - - @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 . - @licend - - @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 c(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 m(a,b){a&&["style:parent-style-name","style:next-style-name"].forEach(function(c){a[c]===b&&delete a[c]})}function f(a){var b={};Object.keys(a).forEach(function(c){b[c]="object"===typeof a[c]?f(a[c]):a[c]});return b}function n(a, -b,c,d){var f,k,g=!1,l=!1,m,n,p=d&&d.attributes?d.attributes.split(","):[];a&&(c||0=c.position+c.length)){k=d?a:c;g=d?c:a;if(a.position!==c.position||a.length!==c.length)p=f(k),t=f(g);c=r(g,k,"style:text-properties");if(c.majorChanged||c.minorChanged)l=[],a=[],m=k.position+k.length,n=g.position+g.length,g.positionm?c.minorChanged&&(p=t,p.position=m,p.length=n-m,a.push(p),g.length=m-g.position):m>n&&c.majorChanged&&(p.position=n,p.length=m-n,l.push(p),k.length=n-k.position),k.setProperties&&b(k.setProperties)&&l.push(k),g.setProperties&&b(g.setProperties)&&a.push(g),d?(m=l,l=a):m=a}return{opSpecsA:m,opSpecsB:l}},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:d,RemoveCursor:d,RemoveStyle:d,RemoveText:function(a,b){var c=a.position+a.length,d=b.position+b.length,f=[a],k=[b];d<=a.position?a.position-=b.length:b.positionb.position)a.position+=b.text.length;else return c?b.position+=a.text.length:a.position+=b.text.length,null;return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:function(a,b){var c=l(b);a.positionb.position)a.position+=1;else return c?b.position+=a.text.length:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},MoveCursor:{MoveCursor:d,RemoveCursor:function(a,b){return{opSpecsA:a.memberid===b.memberid?[]:[a],opSpecsB:[b]}},RemoveMember:d,RemoveStyle:d,RemoveText:function(a,b){var c=l(a),d=a.position+a.length,f=b.position+b.length;f<= -a.position?a.position-=b.length:b.positionb.position)a.position+=1;else if(a.position===b.position)return c?b.position+=1:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},UpdateMember:{UpdateMetadata:d,UpdateParagraphStyle:d},UpdateMetadata:{UpdateMetadata:function(a, -c,d){var f,k=[a],g=[c];f=d?a:c;a=d?c:a;n(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null);f.setProperties&&b(f.setProperties)||f.removedProperties&&p(f.removedProperties)||(d?k=[]:g=[]);a.setProperties&&b(a.setProperties)||a.removedProperties&&p(a.removedProperties)||(d?g=[]:k=[]);return{opSpecsA:k,opSpecsB:g}},UpdateParagraphStyle:d},UpdateParagraphStyle:{UpdateParagraphStyle:function(a,c,d){var f,k=[a],g=[c];a.styleName===c.styleName&&(f=d?a:c,a=d? -c:a,r(a,f,"style:paragraph-properties"),r(a,f,"style:text-properties"),n(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null),f.setProperties&&b(f.setProperties)||f.removedProperties&&p(f.removedProperties)||(d?k=[]:g=[]),a.setProperties&&b(a.setProperties)||a.removedProperties&&p(a.removedProperties)||(d?g=[]:k=[]));return{opSpecsA:k,opSpecsB:g}}}};this.passUnchanged=d;this.extendTransformations=function(a){Object.keys(a).forEach(function(b){var c=a[b], -d,f=k.hasOwnProperty(b);runtime.log((f?"Extending":"Adding")+" map for optypeA: "+b);f||(k[b]={});d=k[b];Object.keys(c).forEach(function(a){var f=d.hasOwnProperty(a);runtime.assert(b<=a,"Wrong order:"+b+", "+a);runtime.log(" "+(f?"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=k[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 71 -/* - - Copyright (C) 2013 KO GmbH - - @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 . - @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(f){var g=[];f.forEach(function(b){g.push(c.create(b))});return g}function l(c,g){for(var b,p,r=[],d=[];0=b&&(d=-n.movePointBackward(-b,f));c.handleUpdate();return d};this.handleUpdate=function(){};this.getStepCounter=function(){return n.getStepCounter()};this.getMemberId=function(){return g};this.getNode=function(){return b.getNode()};this.getAnchorNode=function(){return b.getAnchorNode()};this.getSelectedRange=function(){return b.getSelectedRange()}; -this.setSelectedRange=function(f,g){b.setSelectedRange(f,g);c.handleUpdate()};this.hasForwardSelection=function(){return b.hasForwardSelection()};this.getOdtDocument=function(){return l};this.getSelectionType=function(){return f};this.setSelectionType=function(b){m.hasOwnProperty(b)?f=b:runtime.log("Invalid selection type: "+b)};this.resetSelectionType=function(){c.setSelectionType(ops.OdtCursor.RangeSelection)};b=new core.Cursor(l.getDOM(),g);n=new gui.SelectionMover(b,l.getRootNode());m[ops.OdtCursor.RangeSelection]= -!0;m[ops.OdtCursor.RegionSelection]=!0;c.resetSelectionType()};ops.OdtCursor.RangeSelection="Range";ops.OdtCursor.RegionSelection="Region";(function(){return ops.OdtCursor})(); -// Input 73 -/* - - Copyright (C) 2012 KO GmbH - - @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 . - - 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(g,l){function c(){var c=[],b;for(b in f)f.hasOwnProperty(b)&&c.push({memberid:b,time:f[b].time});c.sort(function(b,c){return b.time-c.time});return c}var m,f={};this.getNode=function(){return m};this.getOdtDocument=function(){return l};this.getEdits=function(){return f};this.getSortedEdits=function(){return c()};this.addEdit=function(c,b){f[c]={time:b}};this.clearEdits=function(){f={}};this.destroy=function(c){g.parentNode&&g.removeChild(m);c()};m=l.getDOM().createElementNS("urn:webodf:names:editinfo", -"editinfo");g.insertBefore(m,g.firstChild)}; -// Input 74 -runtime.loadClass("gui.SelectionMover");gui.ShadowCursor=function(g){var l=g.getDOM().createRange(),c=!0;this.removeFromOdtDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return l};this.setSelectedRange=function(g,f){l=g;c=!1!==f};this.hasForwardSelection=function(){return c};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 75 -gui.Avatar=function(g,l){var c=this,m,f,n;this.setColor=function(b){f.style.borderColor=b};this.setImageUrl=function(b){c.isVisible()?f.src=b:n=b};this.isVisible=function(){return"block"===m.style.display};this.show=function(){n&&(f.src=n,n=void 0);m.style.display="block"};this.hide=function(){m.style.display="none"};this.markAsFocussed=function(b){m.className=b?"active":""};this.destroy=function(b){g.removeChild(m);b()};(function(){var b=g.ownerDocument,c=b.documentElement.namespaceURI;m=b.createElementNS(c, -"div");f=b.createElementNS(c,"img");f.width=64;f.height=64;m.appendChild(f);m.style.width="64px";m.style.height="70px";m.style.position="absolute";m.style.top="-80px";m.style.left="-34px";m.style.display=l?"block":"none";g.appendChild(m)})()}; -// Input 76 -runtime.loadClass("core.DomUtils");runtime.loadClass("gui.Avatar");runtime.loadClass("ops.OdtCursor"); -gui.Caret=function(g,l,c){function m(c){k&&r.parentNode&&(!a||c)&&(c&&void 0!==e&&runtime.clearTimeout(e),a=!0,b.style.opacity=c||"0"===b.style.opacity?"1":"0",e=runtime.setTimeout(function(){a=!1;m(!1)},500))}function f(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 c=g.getNode(),e,k=null;c.previousSibling&&(e=c.previousSibling.nodeType===Node.TEXT_NODE?c.previousSibling.textContent.length: -c.previousSibling.childNodes.length,a.setStart(c.previousSibling,0f(c,k))&&(k=e));a=k;c=g.getOdtDocument().getOdfCanvas().getZoomLevel();d&&g.getSelectionType()===ops.OdtCursor.RangeSelection? -b.style.visibility="visible":b.style.visibility="hidden";a?(b.style.top="0",k=h.getBoundingClientRect(b),8>a.height&&(a={top:a.top-(8-a.height)/2,height:8}),b.style.height=h.adaptRangeDifferenceToZoomLevel(a.height,c)+"px",b.style.top=h.adaptRangeDifferenceToZoomLevel(a.top-k.top,c)+"px"):(b.style.height="1em",b.style.top="5%")}var b,p,r,d=!0,k=!1,a=!1,e,h=new core.DomUtils;this.handleUpdate=n;this.refreshCursorBlinking=function(){c||g.getSelectedRange().collapsed?(k=!0,m(!0)):(k=!1,b.style.opacity= -"0")};this.setFocus=function(){k=!0;p.markAsFocussed(!0);m(!0)};this.removeFocus=function(){k=!1;p.markAsFocussed(!1);b.style.opacity="1"};this.show=function(){d=!0;n();p.markAsFocussed(!0)};this.hide=function(){d=!1;n();p.markAsFocussed(!1)};this.setAvatarImageUrl=function(a){p.setImageUrl(a)};this.setColor=function(a){b.style.borderColor=a;p.setColor(a)};this.getCursor=function(){return g};this.getFocusElement=function(){return b};this.toggleHandleVisibility=function(){p.isVisible()?p.hide():p.show()}; -this.showHandle=function(){p.show()};this.hideHandle=function(){p.hide()};this.ensureVisible=function(){var a,c,d,e,f=g.getOdtDocument().getOdfCanvas().getElement().parentNode,k;d=f.offsetWidth-f.clientWidth+5;e=f.offsetHeight-f.clientHeight+5;k=b.getBoundingClientRect();a=k.left-d;c=k.top-e;d=k.right+d;e=k.bottom+e;k=f.getBoundingClientRect();ck.bottom&&(f.scrollTop+=e-k.bottom);ak.right&&(f.scrollLeft+=d-k.right);n()};this.destroy=function(a){p.destroy(function(c){c? -a(c):(r.removeChild(b),a())})};(function(){var a=g.getOdtDocument().getDOM();b=a.createElementNS(a.documentElement.namespaceURI,"span");b.style.top="5%";r=g.getNode();r.appendChild(b);p=new gui.Avatar(r,l);n()})()}; -// Input 77 -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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.PlainTextPasteboard=function(g,l){function c(c,f){c.init(f);return c}this.createPasteOps=function(m){var f=g.getCursorPosition(l),n=f,b=[];m.replace(/\r/g,"").split("\n").forEach(function(f){b.push(c(new ops.OpSplitParagraph,{memberid:l,position:n}));n+=1;b.push(c(new ops.OpInsertText,{memberid:l,position:n,text:f}));n+=f.length});b.push(c(new ops.OpRemoveText,{memberid:l,position:f,length:1}));return b}}; -// Input 78 -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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(){var g,l,c;this.setDataFromRange=function(c,f){var n=!0,b,p=c.clipboardData;b=runtime.getWindow();var r=f.startContainer.ownerDocument;!p&&b&&(p=b.clipboardData);p?(r=r.createElement("span"),r.appendChild(f.cloneContents()),b=p.setData("text/plain",l.writeToString(r)),n=n&&b,b=p.setData("text/html",g.writeToString(r,odf.Namespaces.namespaceMap)),n=n&&b,c.preventDefault()):n=!1;return n};g=new xmldom.LSSerializer;l=new odf.TextSerializer;c=new odf.OdfNodeFilter;g.filter=c;l.filter= -c}; -// Input 79 -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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(g,l){function c(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 m(a,b){var d=c(a[0],b);return a.every(function(a){return d===c(a,b)})?d:void 0}function f(){var a=t.getCursor(l),a=(a=a&&a.getSelectedRange())&&s.getAppliedStyles(a)||[];a[0]&&A&&(a[0]=w.mergeObjects(a[0],A));return a}function n(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b,c;B=f();M=a(M,B?s.isBold(B):!1,"isBold");z=a(z,B?s.isItalic(B):!1,"isItalic"); -K=a(K,B?s.hasUnderline(B):!1,"hasUnderline");F=a(F,B?s.hasStrikeThrough(B):!1,"hasStrikeThrough");b=B&&m(B,["style:text-properties","fo:font-size"]);Q=a(Q,b&&parseFloat(b),"fontSize");$=a($,B&&m(B,["style:text-properties","style:font-name"]),"fontName");c&&D.emit(gui.DirectTextStyler.textStylingChanged,c)}function b(a){a.getMemberId()===l&&n()}function p(a){a===l&&n()}function r(a){a.getMemberId()===l&&n()}function d(){n()}function k(a){var b=t.getCursor(l);b&&t.getParagraphElement(b.getNode())=== -a.paragraphElement&&n()}function a(a,b){var c=t.getCursor(l);if(!c)return!1;c=s.getAppliedStyles(c.getSelectedRange());b(!a(c));return!0}function e(a){var b=t.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])):(A=w.mergeObjects(A||{},c),n())}function h(a,b){var c={};c[a]=b;e(c)}function q(a){a=a.spec();A&&a.memberid===l&&"SplitParagraph"!==a.optype&&(A=null,n())}function u(a){h("fo:font-weight", -a?"bold":"normal")}function x(a){h("fo:font-style",a?"italic":"normal")}function v(a){h("style:text-underline-style",a?"solid":"none")}function y(a){h("style:text-line-through-style",a?"solid":"none")}var w=new core.Utils,t=g.getOdtDocument(),s=new gui.StyleHelper(t.getFormatting()),D=new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]),A,B=[],M=!1,z=!1,K=!1,F=!1,Q,$;this.formatTextSelection=e;this.createCursorStyleOp=function(a,b){var c=null;A&&(c=new ops.OpApplyDirectStyling,c.init({memberid:l, -position:a,length:b,setProperties:A}),A=null,n());return c};this.setBold=u;this.setItalic=x;this.setHasUnderline=v;this.setHasStrikethrough=y;this.setFontSize=function(a){h("fo:font-size",a+"pt")};this.setFontName=function(a){h("style:font-name",a)};this.getAppliedStyles=function(){return B};this.toggleBold=a.bind(this,s.isBold,u);this.toggleItalic=a.bind(this,s.isItalic,x);this.toggleUnderline=a.bind(this,s.hasUnderline,v);this.toggleStrikethrough=a.bind(this,s.hasStrikeThrough,y);this.isBold=function(){return M}; -this.isItalic=function(){return z};this.hasUnderline=function(){return K};this.hasStrikeThrough=function(){return F};this.fontSize=function(){return Q};this.fontName=function(){return $};this.subscribe=function(a,b){D.subscribe(a,b)};this.unsubscribe=function(a,b){D.unsubscribe(a,b)};this.destroy=function(a){t.unsubscribe(ops.OdtDocument.signalCursorAdded,b);t.unsubscribe(ops.OdtDocument.signalCursorRemoved,p);t.unsubscribe(ops.OdtDocument.signalCursorMoved,r);t.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, -d);t.unsubscribe(ops.OdtDocument.signalParagraphChanged,k);t.unsubscribe(ops.OdtDocument.signalOperationExecuted,q);a()};t.subscribe(ops.OdtDocument.signalCursorAdded,b);t.subscribe(ops.OdtDocument.signalCursorRemoved,p);t.subscribe(ops.OdtDocument.signalCursorMoved,r);t.subscribe(ops.OdtDocument.signalParagraphStyleModified,d);t.subscribe(ops.OdtDocument.signalParagraphChanged,k);t.subscribe(ops.OdtDocument.signalOperationExecuted,q);n()};gui.DirectTextStyler.textStylingChanged="textStyling/changed"; -(function(){return gui.DirectTextStyler})(); -// Input 80 -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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("odf.OdfUtils");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("gui.StyleHelper"); -gui.DirectParagraphStyler=function(g,l,c){function m(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b=h.getCursor(l),b=b&&b.getSelectedRange(),c;y=a(y,b?x.isAlignedLeft(b):!1,"isAlignedLeft");w=a(w,b?x.isAlignedCenter(b):!1,"isAlignedCenter");t=a(t,b?x.isAlignedRight(b):!1,"isAlignedRight");s=a(s,b?x.isAlignedJustified(b):!1,"isAlignedJustified");c&&v.emit(gui.DirectParagraphStyler.paragraphStylingChanged,c)}function f(a){a.getMemberId()===l&&m()}function n(a){a===l&&m()}function b(a){a.getMemberId()=== -l&&m()}function p(){m()}function r(a){var b=h.getCursor(l);b&&h.getParagraphElement(b.getNode())===a.paragraphElement&&m()}function d(a){var b=h.getCursor(l).getSelectedRange(),d=h.getCursorPosition(l),b=u.getParagraphElements(b),e=h.getFormatting();b.forEach(function(b){var f=d+h.getDistanceFromCursor(l,b,0),k=b.getAttributeNS(odf.Namespaces.textns,"style-name");b=c.generateStyleName();var m,f=f+1;k&&(m=e.createDerivedStyleObject(k,"paragraph",{}));m=a(m||{});k=new ops.OpAddStyle;k.init({memberid:l, -styleName:b,styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:m});m=new ops.OpSetParagraphStyle;m.init({memberid:l,styleName:b,position:f});g.enqueue([k,m])})}function k(a){d(function(b){return q.mergeObjects(b,a)})}function a(a){k({"style:paragraph-properties":{"fo:text-align":a}})}function e(a,b){var c=h.getFormatting().getDefaultTabStopDistance(),d=b["style:paragraph-properties"],d=(d=d&&d["fo:margin-left"])&&u.parseLength(d);return q.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 h=g.getOdtDocument(),q=new core.Utils,u=new odf.OdfUtils,x=new gui.StyleHelper(h.getFormatting()),v=new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]),y,w,t,s;this.isAlignedLeft=function(){return y};this.isAlignedCenter=function(){return w};this.isAlignedRight=function(){return t};this.isAlignedJustified=function(){return s};this.alignParagraphLeft=function(){a("left");return!0};this.alignParagraphCenter=function(){a("center"); -return!0};this.alignParagraphRight=function(){a("right");return!0};this.alignParagraphJustified=function(){a("justify");return!0};this.indent=function(){d(e.bind(null,1));return!0};this.outdent=function(){d(e.bind(null,-1));return!0};this.subscribe=function(a,b){v.subscribe(a,b)};this.unsubscribe=function(a,b){v.unsubscribe(a,b)};this.destroy=function(a){h.unsubscribe(ops.OdtDocument.signalCursorAdded,f);h.unsubscribe(ops.OdtDocument.signalCursorRemoved,n);h.unsubscribe(ops.OdtDocument.signalCursorMoved, -b);h.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,p);h.unsubscribe(ops.OdtDocument.signalParagraphChanged,r);a()};h.subscribe(ops.OdtDocument.signalCursorAdded,f);h.subscribe(ops.OdtDocument.signalCursorRemoved,n);h.subscribe(ops.OdtDocument.signalCursorMoved,b);h.subscribe(ops.OdtDocument.signalParagraphStyleModified,p);h.subscribe(ops.OdtDocument.signalParagraphChanged,r);m()};gui.DirectParagraphStyler.paragraphStylingChanged="paragraphStyling/changed";(function(){return gui.DirectParagraphStyler})(); -// Input 81 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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(){function g(c,g){g||(g=l.None);return c+":"+g}var l=gui.KeyboardHandler.Modifier,c=null,m={};this.setDefault=function(f){c=f};this.bind=function(c,l,b){c=g(c,l);runtime.assert(!1===m.hasOwnProperty(c),"tried to overwrite the callback handler of key combo: "+c);m[c]=b};this.unbind=function(c,l){var b=g(c,l);delete m[b]};this.reset=function(){c=null;m={}};this.handleEvent=function(f){var n=f.keyCode,b=l.None;f.metaKey&&(b|=l.Meta);f.ctrlKey&&(b|=l.Ctrl);f.altKey&&(b|=l.Alt); -f.shiftKey&&(b|=l.Shift);n=g(n,b);n=m[n];b=!1;n?b=n():null!==c&&(b=c(f));b&&(f.preventDefault?f.preventDefault():f.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 82 -runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.ObjectNameGenerator"); -gui.ImageManager=function(g,l,c){var m={"image/gif":".gif","image/jpeg":".jpg","image/png":".png"},f=odf.Namespaces.textns,n=g.getOdtDocument(),b=n.getFormatting(),p={};this.insertImage=function(r,d,k,a){var e;runtime.assert(0e.width&&(h=e.width/k);a>e.height&&(q=e.height/a);h=Math.min(h,q);e=k*h;k=a*h;q=n.getOdfCanvas().odfContainer().rootElement.styles;a=r.toLowerCase();var h=m.hasOwnProperty(a)?m[a]:null,u;a=[];runtime.assert(null!==h,"Image type is not supported: "+r);h="Pictures/"+c.generateImageName()+h;u=new ops.OpSetBlob;u.init({memberid:l,filename:h,mimetype:r,content:d});a.push(u);b.getStyleElement("Graphics","graphic",[q])||(r=new ops.OpAddStyle,r.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(r));r=c.generateStyleName();d=new ops.OpAddStyle;d.init({memberid:l,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"}}}); -a.push(d);u=new ops.OpInsertImage;u.init({memberid:l,position:n.getCursorPosition(l),filename:h,frameWidth:e+"cm",frameHeight:k+"cm",frameStyleName:r,frameName:c.generateFrameName()});a.push(u);g.enqueue(a)}}; // Input 83 -runtime.loadClass("odf.Namespaces"); -gui.ImageSelector=function(g){function l(){var b=g.getSizer(),c,l;c=f.createElement("div");c.id="imageSelector";c.style.borderWidth="1px";b.appendChild(c);m.forEach(function(b){l=f.createElement("div");l.className=b;c.appendChild(l)});return c}var c=odf.Namespaces.svgns,m="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),f=g.getElement().ownerDocument,n=!1;this.select=function(b){var m,r,d=f.getElementById("imageSelector");d||(d=l());n=!0;m=d.parentNode; -r=b.getBoundingClientRect();var k=m.getBoundingClientRect(),a=g.getZoomLevel();m=(r.left-k.left)/a-1;r=(r.top-k.top)/a-1;d.style.display="block";d.style.left=m+"px";d.style.top=r+"px";d.style.width=b.getAttributeNS(c,"width");d.style.height=b.getAttributeNS(c,"height")};this.clearSelection=function(){var b;n&&(b=f.getElementById("imageSelector"))&&(b.style.display="none");n=!1};this.isSelectorElement=function(b){var c=f.getElementById("imageSelector");return c?b===c||b.parentNode===c:!1}}; +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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.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,k){};ops.OperationRouter.prototype.unsubscribe=function(g,k){};ops.OperationRouter.prototype.hasLocalUnsyncedOps=function(){};ops.OperationRouter.prototype.hasSessionHostConnection=function(){}; // Input 84 /* Copyright (C) 2013 KO GmbH @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. + 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 this code. If not, see . - - 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. + along with WebODF. If not, see . @licend + @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -runtime.loadClass("core.PositionFilter"); -gui.TextManipulator=function(g,l,c){function m(b){var c=new ops.OpRemoveText;c.init({memberid:l,position:b.position,length:b.length});return c}function f(b){0>b.length&&(b.position+=b.length,b.length=-b.length);return b}function n(c,d){var f=new core.PositionFilterChain,a=gui.SelectionMover.createPositionIterator(b.getRootElement(c)),e=d?a.nextPosition:a.previousPosition;f.addFilter("BaseFilter",b.getPositionFilter());f.addFilter("RootFilter",b.createRootFilter(l));for(a.setUnfilteredPosition(c,0);e();)if(f.acceptPosition(a)=== -p)return!0;return!1}var b=g.getOdtDocument(),p=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.enqueueParagraphSplittingOps=function(){var c=f(b.getCursorSelection(l)),d,k=[];0a.length;c&&g(a);return c}function e(a,c){var b=[];a&&["style:parent-style-name","style:next-style-name"].forEach(function(d){a[d]===c&&b.push(d)});return b}function n(a,c){a&&["style:parent-style-name","style:next-style-name"].forEach(function(b){a[b]===c&&delete a[b]})}function m(a){var c={};Object.keys(a).forEach(function(b){c[b]="object"===typeof a[b]?m(a[b]):a[b]});return c}function q(a, +c,b,d){var f,e,g=!1,h=!1,k,m,n=d&&d.attributes?d.attributes.split(","):[];a&&(b||0=c.position+c.length)){f=d?a:c;e=d?c:a;if(a.position!==c.position||a.length!==c.length)n=m(f),q=m(e);c=r(e,f,"style:text-properties");if(c.majorChanged||c.minorChanged)g=[],a=[],h=f.position+f.length,k=e.position+e.length,e.positionh?c.minorChanged&&(n=q,n.position=h,n.length=k-h,a.push(n),e.length=h-e.position):h>k&&c.majorChanged&&(n.position=k,n.length=h-k,g.push(n),f.length=k-f.position),f.setProperties&&b(f.setProperties)&&g.push(f),e.setProperties&&b(e.setProperties)&&a.push(e),d?(h=g,g=a):h=a}return{opSpecsA:h,opSpecsB:g}},InsertText:function(a, +c){c.position<=a.position?a.position+=c.text.length:c.position<=a.position+a.length&&(a.length+=c.text.length);return{opSpecsA:[a],opSpecsB:[c]}},MoveCursor:d,RemoveCursor:d,RemoveStyle:d,RemoveText:function(a,c){var b=a.position+a.length,d=c.position+c.length,f=[a],e=[c];d<=a.position?a.position-=c.length:c.positionc.position)a.position+=c.text.length;else return b?c.position+=a.text.length:a.position+=c.text.length,null;return{opSpecsA:[a],opSpecsB:[c]}},MoveCursor:function(a,c){var b=k(c);a.positionc.position)a.position+=1;else return b?c.position+=a.text.length:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[c]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},MoveCursor:{MoveCursor:d,RemoveCursor:function(a,c){return{opSpecsA:a.memberid===c.memberid?[]:[a],opSpecsB:[c]}},RemoveMember:d,RemoveStyle:d,RemoveText:function(a,c){var b=k(a),d=a.position+a.length,f=c.position+c.length;f<= +a.position?a.position-=c.length:c.positionb.position)a.position+=1;else if(a.position===b.position)return d?b.position+=1:a.position+=1,null;return{opSpecsA:[a],opSpecsB:[b]}},UpdateMember:d,UpdateMetadata:d,UpdateParagraphStyle:d},UpdateMember:{UpdateMetadata:d,UpdateParagraphStyle:d},UpdateMetadata:{UpdateMetadata:function(a, +c,d){var f,e=[a],g=[c];f=d?a:c;a=d?c:a;q(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null);f.setProperties&&b(f.setProperties)||f.removedProperties&&h(f.removedProperties)||(d?e=[]:g=[]);a.setProperties&&b(a.setProperties)||a.removedProperties&&h(a.removedProperties)||(d?g=[]:e=[]);return{opSpecsA:e,opSpecsB:g}},UpdateParagraphStyle:d},UpdateParagraphStyle:{UpdateParagraphStyle:function(a,c,d){var f,e=[a],g=[c];a.styleName===c.styleName&&(f=d?a:c,a=d? +c:a,r(a,f,"style:paragraph-properties"),r(a,f,"style:text-properties"),q(a.setProperties||null,a.removedProperties||null,f.setProperties||null,f.removedProperties||null),f.setProperties&&b(f.setProperties)||f.removedProperties&&h(f.removedProperties)||(d?e=[]:g=[]),a.setProperties&&b(a.setProperties)||a.removedProperties&&h(a.removedProperties)||(d?g=[]:e=[]));return{opSpecsA:e,opSpecsB:g}}}};this.passUnchanged=d;this.extendTransformations=function(a){Object.keys(a).forEach(function(b){var d=a[b], +e,g=f.hasOwnProperty(b);runtime.log((g?"Extending":"Adding")+" map for optypeA: "+b);g||(f[b]={});e=f[b];Object.keys(d).forEach(function(a){var f=e.hasOwnProperty(a);runtime.assert(b<=a,"Wrong order:"+b+", "+a);runtime.log(" "+(f?"Overwriting":"Adding")+" entry for optypeB: "+a);e[a]=d[a]})})};this.transformOpspecVsOpspec=function(a,b){var d=a.optype<=b.optype,e;runtime.log("Crosstransforming:");runtime.log(runtime.toJson(a));runtime.log(runtime.toJson(b));d||(e=a,a=b,b=e);(e=(e=f[a.optype])&&e[b.optype])? +(e=e(a,b,!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 85 /* @@ -2597,85 +2540,10 @@ k,a=[];0 - - @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 . - - 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.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){}; -// Input 89 /* Copyright (C) 2012 KO GmbH @@ -2713,11 +2581,8 @@ ops.OperationRouter=function(){};ops.OperationRouter.prototype.setOperationFacto @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -ops.TrivialOperationRouter=function(){var g,l;this.setOperationFactory=function(c){g=c};this.setPlaybackFunction=function(c){l=c};this.push=function(c){c.forEach(function(c){c=c.spec();c.timestamp=(new Date).getTime();c=g.create(c);l(c)})};this.close=function(c){c()}}; -// Input 90 -gui.EditInfoHandle=function(g){var l=[],c,m=g.ownerDocument,f=m.documentElement.namespaceURI;this.setEdits=function(g){l=g;var b,p,r,d;c.innerHTML="";for(g=0;g @@ -2756,101 +2621,10 @@ d=m.createElementNS(f,"span"),d.className="editInfoTime",d.setAttributeNS("urn:w @source: https://github.com/kogmbh/WebODF/ */ runtime.loadClass("ops.EditInfo");runtime.loadClass("gui.EditInfoHandle"); -gui.EditInfoMarker=function(g,l){function c(c,f){return runtime.setTimeout(function(){b.style.opacity=c},f)}var m=this,f,n,b,p,r;this.addEdit=function(d,f){var a=Date.now()-f;g.addEdit(d,f);n.setEdits(g.getSortedEdits());b.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",d);p&&runtime.clearTimeout(p);r&&runtime.clearTimeout(r);1E4>a?(c(1,0),p=c(0.5,1E4-a),r=c(0.2,2E4-a)):1E4<=a&&2E4>a?(c(0.5,0),r=c(0.2,2E4-a)):c(0.2,0)};this.getEdits=function(){return g.getEdits()};this.clearEdits=function(){g.clearEdits(); -n.setEdits([]);b.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&b.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return g};this.show=function(){b.style.display="block"};this.hide=function(){m.hideHandle();b.style.display="none"};this.showHandle=function(){n.show()};this.hideHandle=function(){n.hide()};this.destroy=function(c){f.removeChild(b);n.destroy(function(b){b?c(b):g.destroy(c)})};(function(){var c=g.getOdtDocument().getDOM(); -b=c.createElementNS(c.documentElement.namespaceURI,"div");b.setAttribute("class","editInfoMarker");b.onmouseover=function(){m.showHandle()};b.onmouseout=function(){m.hideHandle()};f=g.getNode();f.appendChild(b);n=new gui.EditInfoHandle(f);l||m.hide()})()}; -// Input 92 -/* - - Copyright (C) 2012-2013 KO GmbH - - @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 . - - 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("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,c,m,f){function n(a,b,c){function d(b,c,e){c=b+'[editinfo|memberid="'+a+'"]'+e+c;a:{var f=u.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:u.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 b(a){var b,c;for(c in v)v.hasOwnProperty(c)&&(b=v[c],a?b.show():b.hide())}function p(a){m.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);l===b&&n("","",a.color)}function d(a){var b=a.getMemberId(),d=c.getOdtDocument().getMember(b).getProperties();m.registerCursor(a,w,t);f.registerCursor(a, -!0);if(a=m.getCaret(b))a.setAvatarImageUrl(d.imageUrl),a.setColor(d.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+b+"'! +++")}function k(a){a=a.getMemberId();var b=f.getSelectionView(l),c=f.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),d=m.getCaret(l);a===l?(c.hide(),b.show(),d&&d.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(c.show(),b.hide(),d&&d.hide())}function a(a){f.removeSelectionView(a)}function e(a){var b=a.paragraphElement,d=a.memberId;a=a.timeStamp; -var e,f="",g=b.getElementsByTagNameNS(x,"editinfo")[0];g?(f=g.getAttributeNS(x,"id"),e=v[f]):(f=Math.random().toString(),e=new ops.EditInfo(b,c.getOdtDocument()),e=new gui.EditInfoMarker(e,y),g=b.getElementsByTagNameNS(x,"editinfo")[0],g.setAttributeNS(x,"id",f),v[f]=e);e.addEdit(d,new Date(a))}function h(){D=!0}function q(){s=runtime.getWindow().setInterval(function(){D&&(f.rerenderSelectionViews(),D=!1)},200)}var u,x="urn:webodf:names:editinfo",v={},y=void 0!==g.editInfoMarkersInitiallyVisible? -Boolean(g.editInfoMarkersInitiallyVisible):!0,w=void 0!==g.caretAvatarsInitiallyVisible?Boolean(g.caretAvatarsInitiallyVisible):!0,t=void 0!==g.caretBlinksOnRangeSelect?Boolean(g.caretBlinksOnRangeSelect):!0,s,D=!1;this.showEditInfoMarkers=function(){y||(y=!0,b(y))};this.hideEditInfoMarkers=function(){y&&(y=!1,b(y))};this.showCaretAvatars=function(){w||(w=!0,p(w))};this.hideCaretAvatars=function(){w&&(w=!1,p(w))};this.getSession=function(){return c};this.getCaret=function(a){return m.getCaret(a)}; -this.destroy=function(b){var f=c.getOdtDocument(),g=Object.keys(v).map(function(a){return v[a]});f.unsubscribe(ops.OdtDocument.signalMemberAdded,r);f.unsubscribe(ops.OdtDocument.signalMemberUpdated,r);f.unsubscribe(ops.OdtDocument.signalCursorAdded,d);f.unsubscribe(ops.OdtDocument.signalCursorRemoved,a);f.unsubscribe(ops.OdtDocument.signalParagraphChanged,e);f.unsubscribe(ops.OdtDocument.signalCursorMoved,k);f.unsubscribe(ops.OdtDocument.signalParagraphChanged,h);f.unsubscribe(ops.OdtDocument.signalTableAdded, -h);f.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,h);runtime.getWindow().clearInterval(s);u.parentNode.removeChild(u);(function K(a,c){c?b(c):a - - @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 . - - 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("gui.Caret"); -gui.CaretManager=function(g){function l(a){return e.hasOwnProperty(a)?e[a]:null}function c(){return Object.keys(e).map(function(a){return e[a]})}function m(a){a===g.getInputMemberId()&&g.getSession().getOdtDocument().getOdfCanvas().getElement().removeAttribute("tabindex");delete e[a]}function f(a){a=a.getMemberId();a===g.getInputMemberId()&&(a=l(a))&&a.refreshCursorBlinking()}function n(){var a=l(g.getInputMemberId());q=!1;a&&a.ensureVisible()}function b(){var a=l(g.getInputMemberId());a&&(a.handleUpdate(), -q||(q=!0,runtime.setTimeout(n,50)))}function p(a){a.memberId===g.getInputMemberId()&&b()}function r(){var a=l(g.getInputMemberId());a&&a.setFocus()}function d(){var a=l(g.getInputMemberId());a&&a.removeFocus()}function k(){var a=l(g.getInputMemberId());a&&a.show()}function a(){var a=l(g.getInputMemberId());a&&a.hide()}var e={},h=runtime.getWindow(),q=!1;this.registerCursor=function(a,c,d){var f=a.getMemberId();c=new gui.Caret(a,c,d);e[f]=c;f===g.getInputMemberId()?(runtime.log("Starting to track input on new cursor of "+ -f),a.handleUpdate=b,g.getSession().getOdtDocument().getOdfCanvas().getElement().setAttribute("tabindex",-1),g.getEventManager().focus()):a.handleUpdate=c.handleUpdate;return c};this.getCaret=l;this.getCarets=c;this.destroy=function(b){var l=g.getSession().getOdtDocument(),n=g.getEventManager(),q=c();l.unsubscribe(ops.OdtDocument.signalParagraphChanged,p);l.unsubscribe(ops.OdtDocument.signalCursorMoved,f);l.unsubscribe(ops.OdtDocument.signalCursorRemoved,m);n.unsubscribe("focus",r);n.unsubscribe("blur", -d);h.removeEventListener("focus",k,!1);h.removeEventListener("blur",a,!1);(function t(a,c){c?b(c):aa?(e(1,0),h=e(0.5,1E4-a),r=e(0.2,2E4-a)):1E4<=a&&2E4>a?(e(0.5,0),r=e(0.2,2E4-a)):e(0.2,0)};this.getEdits=function(){return g.getEdits()};this.clearEdits=function(){g.clearEdits(); +q.setEdits([]);b.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&b.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return g};this.show=function(){b.style.display="block"};this.hide=function(){n.hideHandle();b.style.display="none"};this.showHandle=function(){q.show()};this.hideHandle=function(){q.hide()};this.destroy=function(d){m.removeChild(b);q.destroy(function(b){b?d(b):g.destroy(d)})};(function(){var d=g.getOdtDocument().getDOM(); +b=d.createElementNS(d.documentElement.namespaceURI,"div");b.setAttribute("class","editInfoMarker");b.onmouseover=function(){n.showHandle()};b.onmouseout=function(){n.hideHandle()};m=g.getNode();m.appendChild(b);q=new gui.EditInfoHandle(m);k||n.hide()})()}; +// Input 88 /* Copyright (C) 2013 KO GmbH @@ -2888,107 +2662,21 @@ d);h.removeEventListener("focus",k,!1);h.removeEventListener("blur",a,!1);(funct @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 95 -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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(){function g(c){return c.spec().optype}function l(c){return c.isEdit}this.getOpType=g;this.isEditOperation=l;this.isPartOfOperationSet=function(c,m){if(c.isEdit){if(0===m.length)return!0;var f;if(f=m[m.length-1].isEdit)a:{f=m.filter(l);var n=g(c),b;b:switch(n){case "RemoveText":case "InsertText":b=!0;break b;default:b=!1}if(b&&n===g(f[0])){if(1===f.length){f=!0;break a}n=f[f.length-2].spec().position;f=f[f.length-1].spec().position;b=c.spec().position;if(f===b-(f-n)){f= -!0;break a}}f=!1}return f}return!0}}; -// Input 96 -/* - - Copyright (C) 2013 KO GmbH - - @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 . - - 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("gui.UndoManager");runtime.loadClass("gui.UndoStateRules"); -gui.TrivialUndoManager=function(g){function l(){u.emit(gui.UndoManager.signalUndoStackChanged,{undoAvailable:b.hasUndoStates(),redoAvailable:b.hasRedoStates()})}function c(){e!==d&&e!==h[h.length-1]&&h.push(e)}function m(a){var b=a.previousSibling||a.nextSibling;a.parentNode.removeChild(a);p.normalizeTextNodes(b)}function f(a){return Object.keys(a).map(function(b){return a[b]})}function n(b){function c(a){var b=a.spec();if(g[b.memberid])switch(b.optype){case "AddCursor":d[b.memberid]||(d[b.memberid]= -a,delete g[b.memberid],h-=1);break;case "MoveCursor":e[b.memberid]||(e[b.memberid]=a)}}var d={},e={},g={},h,k=b.pop();a.getCursors().forEach(function(a){g[a.getMemberId()]=!0});for(h=Object.keys(g).length;k&&0 @@ -3027,12 +2715,12 @@ a);v.className=y.className=w.className="selectionOverlay";g.getOdtDocument().sub @source: https://github.com/kogmbh/WebODF/ */ runtime.loadClass("gui.SelectionView"); -gui.SelectionViewManager=function(){function g(){return Object.keys(l).map(function(c){return l[c]})}var l={};this.getSelectionView=function(c){return l.hasOwnProperty(c)?l[c]:null};this.getSelectionViews=g;this.removeSelectionView=function(c){l.hasOwnProperty(c)&&(l[c].destroy(function(){}),delete l[c])};this.hideSelectionView=function(c){l.hasOwnProperty(c)&&l[c].hide()};this.showSelectionView=function(c){l.hasOwnProperty(c)&&l[c].show()};this.rerenderSelectionViews=function(){Object.keys(l).forEach(function(c){l[c].visible()&& -l[c].rerender()})};this.registerCursor=function(c,g){var f=c.getMemberId(),n=new gui.SelectionView(c);g?n.show():n.hide();return l[f]=n};this.destroy=function(c){var l=g();(function n(b,g){g?c(g):b + Copyright (C) 2013 KO GmbH @licstart The JavaScript code in this page is free software: you can redistribute it @@ -3067,24 +2755,14 @@ l[c].rerender()})};this.registerCursor=function(c,g){var f=c.getMemberId(),n=new @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 c(){return l().ownerDocument}function m(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 f(b){this.acceptPosition=function(c){c=c.container();var d;d="string"===typeof b? -a[b].getNode():b;return m(c)===m(d)?q:u}}function n(a){var b=gui.SelectionMover.createPositionIterator(l());a=v.convertStepsToDomPoint(a);b.setUnfilteredPosition(a.node,a.offset);return b}function b(a,b){return g.getFormatting().getStyleElement(a,b)}function p(a){return b(a,"paragraph")}var r=this,d,k,a={},e={},h=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]),q=core.PositionFilter.FilterResult.FILTER_ACCEPT,u=core.PositionFilter.FilterResult.FILTER_REJECT,x,v,y;this.getDOM= -c;this.getRootElement=m;this.getIteratorAtPosition=n;this.convertDomPointToCursorStep=function(a,b){return v.convertDomPointToSteps(a,b)};this.convertDomToCursorRange=function(a,b,c,d){var e;e=v.convertDomPointToSteps(a,b);a=a===c&&b===d?e:v.convertDomPointToSteps(c,d);return{position:e,length:a-e}};this.convertCursorToDomRange=function(a,b){var d=c().createRange(),e,f;e=v.convertStepsToDomPoint(a);b?(f=v.convertStepsToDomPoint(a+b),0=e;e+=1){b=a.container();c=a.unfilteredDomOffset();if(b.nodeType===Node.TEXT_NODE&&" "===b.data[c]&&d.isSignificantWhitespace(b,c)){runtime.assert(" "===b.data[c],"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(c,1);0 @@ -3123,9 +2801,300 @@ ops.OdtDocument.signalUndoStackChanged="undo/changed";ops.OdtDocument.signalStep @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,c=new ops.OdtDocument(g),m=null;this.setOperationFactory=function(c){l=c;m&&m.setOperationFactory(l)};this.setOperationRouter=function(f){m=f;f.setPlaybackFunction(function(f){f.execute(c);c.emit(ops.OdtDocument.signalOperationExecuted,f)});f.setOperationFactory(l)};this.getOperationFactory=function(){return l};this.getOdtDocument=function(){return c};this.enqueue=function(c){m.push(c)};this.close=function(f){m.close(function(g){g?f(g):c.close(f)})}; -this.destroy=function(f){c.destroy(f)};this.setOperationRouter(new ops.TrivialOperationRouter)}; +ops.Session=function(g){var k=new ops.OperationFactory,e=new ops.OdtDocument(g),n=null;this.setOperationFactory=function(e){k=e;n&&n.setOperationFactory(k)};this.setOperationRouter=function(g){n=g;g.setPlaybackFunction(function(g){return g.execute(e)?(e.emit(ops.OdtDocument.signalOperationExecuted,g),!0):!1});g.setOperationFactory(k)};this.getOperationFactory=function(){return k};this.getOdtDocument=function(){return e};this.enqueue=function(e){n.push(e)};this.close=function(g){n.close(function(k){k? +g(k):e.close(g)})};this.destroy=function(g){e.destroy(g)};this.setOperationRouter(new ops.TrivialOperationRouter)}; +// Input 93 +/* + + Copyright (C) 2013 KO GmbH + + @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 . + @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,k){function e(){var f=b.getCursor(k),f=f&&f.getNode(),a=!1;if(f){a:{for(a=b.getRootNode();f&&f!==a;){if(f.namespaceURI===d&&"annotation"===f.localName){f=!0;break a}f=f.parentNode}f=!1}a=!f}a!==h&&(h=a,r.emit(gui.AnnotationController.annotatableChanged,h))}function n(b){b.getMemberId()===k&&e()}function m(b){b===k&&e()}function q(b){b.getMemberId()===k&&e()}var b=g.getOdtDocument(),h=!1,r=new core.EventNotifier([gui.AnnotationController.annotatableChanged]),d=odf.Namespaces.officens; +this.isAnnotatable=function(){return h};this.addAnnotation=function(){var d=new ops.OpAddAnnotation,a=b.getCursorSelection(k),c=a.length,a=a.position;h&&(a=0<=c?a:a+c,c=Math.abs(c),d.init({memberid:k,position:a,length:c,name:k+Date.now()}),g.enqueue([d]))};this.removeAnnotation=function(d){var a,c;a=b.convertDomPointToCursorStep(d,0)+1;c=b.convertDomPointToCursorStep(d,d.childNodes.length);d=new ops.OpRemoveAnnotation;d.init({memberid:k,position:a,length:c-a});c=new ops.OpMoveCursor;c.init({memberid:k, +position:0 + + @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 . + + 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("odf.OdfUtils");runtime.loadClass("ops.OpAddStyle");runtime.loadClass("ops.OpSetParagraphStyle");runtime.loadClass("gui.StyleHelper"); +gui.DirectParagraphStyler=function(g,k,e){function n(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b=l.getCursor(k),b=b&&b.getSelectedRange(),c;v=a(v,b?w.isAlignedLeft(b):!1,"isAlignedLeft");t=a(t,b?w.isAlignedCenter(b):!1,"isAlignedCenter");s=a(s,b?w.isAlignedRight(b):!1,"isAlignedRight");N=a(N,b?w.isAlignedJustified(b):!1,"isAlignedJustified");c&&y.emit(gui.DirectParagraphStyler.paragraphStylingChanged,c)}function m(a){a.getMemberId()===k&&n()}function q(a){a===k&&n()}function b(a){a.getMemberId()=== +k&&n()}function h(){n()}function r(a){var b=l.getCursor(k);b&&l.getParagraphElement(b.getNode())===a.paragraphElement&&n()}function d(a){return a===ops.StepsTranslator.NEXT_STEP}function f(a){var b=l.getCursor(k).getSelectedRange(),b=B.getParagraphElements(b),c=l.getFormatting();b.forEach(function(b){var f=l.convertDomPointToCursorStep(b,0,d),h=b.getAttributeNS(odf.Namespaces.textns,"style-name");b=e.generateStyleName();var m;h&&(m=c.createDerivedStyleObject(h,"paragraph",{}));m=a(m||{});h=new ops.OpAddStyle; +h.init({memberid:k,styleName:b,styleFamily:"paragraph",isAutomaticStyle:!0,setProperties:m});m=new ops.OpSetParagraphStyle;m.init({memberid:k,styleName:b,position:f});g.enqueue([h,m])})}function a(a){f(function(b){return u.mergeObjects(b,a)})}function c(b){a({"style:paragraph-properties":{"fo:text-align":b}})}function p(a,b){var c=l.getFormatting().getDefaultTabStopDistance(),d=b["style:paragraph-properties"],d=(d=d&&d["fo:margin-left"])&&B.parseLength(d);return u.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 l=g.getOdtDocument(),u=new core.Utils,B=new odf.OdfUtils,w=new gui.StyleHelper(l.getFormatting()),y=new core.EventNotifier([gui.DirectParagraphStyler.paragraphStylingChanged]),v,t,s,N;this.isAlignedLeft=function(){return v};this.isAlignedCenter=function(){return t};this.isAlignedRight=function(){return s};this.isAlignedJustified=function(){return N};this.alignParagraphLeft=function(){c("left");return!0};this.alignParagraphCenter=function(){c("center"); +return!0};this.alignParagraphRight=function(){c("right");return!0};this.alignParagraphJustified=function(){c("justify");return!0};this.indent=function(){f(p.bind(null,1));return!0};this.outdent=function(){f(p.bind(null,-1));return!0};this.subscribe=function(a,b){y.subscribe(a,b)};this.unsubscribe=function(a,b){y.unsubscribe(a,b)};this.destroy=function(a){l.unsubscribe(ops.OdtDocument.signalCursorAdded,m);l.unsubscribe(ops.OdtDocument.signalCursorRemoved,q);l.unsubscribe(ops.OdtDocument.signalCursorMoved, +b);l.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,h);l.unsubscribe(ops.OdtDocument.signalParagraphChanged,r);a()};l.subscribe(ops.OdtDocument.signalCursorAdded,m);l.subscribe(ops.OdtDocument.signalCursorRemoved,q);l.subscribe(ops.OdtDocument.signalCursorMoved,b);l.subscribe(ops.OdtDocument.signalParagraphStyleModified,h);l.subscribe(ops.OdtDocument.signalParagraphChanged,r);n()};gui.DirectParagraphStyler.paragraphStylingChanged="paragraphStyling/changed";(function(){return gui.DirectParagraphStyler})(); +// Input 95 +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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(g,k){function e(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 n(a,b){var c=e(a[0],b);return a.every(function(a){return c===e(a,b)})?c:void 0}function m(){var a=t.getCursor(k),a=(a=a&&a.getSelectedRange())&&s.getAppliedStyles(a)||[];a[0]&&z&&(a[0]=v.mergeObjects(a[0],z));return a}function q(){function a(b,d,e){b!==d&&(void 0===c&&(c={}),c[e]=d);return d}var b,c;x=m();R=a(R,x?s.isBold(x):!1,"isBold");F=a(F,x?s.isItalic(x):!1,"isItalic"); +U=a(U,x?s.hasUnderline(x):!1,"hasUnderline");P=a(P,x?s.hasStrikeThrough(x):!1,"hasStrikeThrough");b=x&&n(x,["style:text-properties","fo:font-size"]);A=a(A,b&&parseFloat(b),"fontSize");ja=a(ja,x&&n(x,["style:text-properties","style:font-name"]),"fontName");c&&N.emit(gui.DirectTextStyler.textStylingChanged,c)}function b(a){a.getMemberId()===k&&q()}function h(a){a===k&&q()}function r(a){a.getMemberId()===k&&q()}function d(){q()}function f(a){var b=t.getCursor(k);b&&t.getParagraphElement(b.getNode())=== +a.paragraphElement&&q()}function a(a,b){var c=t.getCursor(k);if(!c)return!1;c=s.getAppliedStyles(c.getSelectedRange());b(!a(c));return!0}function c(a){var b=t.getCursorSelection(k),c={"style:text-properties":a};0!==b.length?(a=new ops.OpApplyDirectStyling,a.init({memberid:k,position:b.position,length:b.length,setProperties:c}),g.enqueue([a])):(z=v.mergeObjects(z||{},c),q())}function p(a,b){var d={};d[a]=b;c(d)}function l(a){a=a.spec();z&&a.memberid===k&&"SplitParagraph"!==a.optype&&(z=null,q())}function u(a){p("fo:font-weight", +a?"bold":"normal")}function B(a){p("fo:font-style",a?"italic":"normal")}function w(a){p("style:text-underline-style",a?"solid":"none")}function y(a){p("style:text-line-through-style",a?"solid":"none")}var v=new core.Utils,t=g.getOdtDocument(),s=new gui.StyleHelper(t.getFormatting()),N=new core.EventNotifier([gui.DirectTextStyler.textStylingChanged]),z,x=[],R=!1,F=!1,U=!1,P=!1,A,ja;this.formatTextSelection=c;this.createCursorStyleOp=function(a,b){var c=null;z&&(c=new ops.OpApplyDirectStyling,c.init({memberid:k, +position:a,length:b,setProperties:z}),z=null,q());return c};this.setBold=u;this.setItalic=B;this.setHasUnderline=w;this.setHasStrikethrough=y;this.setFontSize=function(a){p("fo:font-size",a+"pt")};this.setFontName=function(a){p("style:font-name",a)};this.getAppliedStyles=function(){return x};this.toggleBold=a.bind(this,s.isBold,u);this.toggleItalic=a.bind(this,s.isItalic,B);this.toggleUnderline=a.bind(this,s.hasUnderline,w);this.toggleStrikethrough=a.bind(this,s.hasStrikeThrough,y);this.isBold=function(){return R}; +this.isItalic=function(){return F};this.hasUnderline=function(){return U};this.hasStrikeThrough=function(){return P};this.fontSize=function(){return A};this.fontName=function(){return ja};this.subscribe=function(a,b){N.subscribe(a,b)};this.unsubscribe=function(a,b){N.unsubscribe(a,b)};this.destroy=function(a){t.unsubscribe(ops.OdtDocument.signalCursorAdded,b);t.unsubscribe(ops.OdtDocument.signalCursorRemoved,h);t.unsubscribe(ops.OdtDocument.signalCursorMoved,r);t.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, +d);t.unsubscribe(ops.OdtDocument.signalParagraphChanged,f);t.unsubscribe(ops.OdtDocument.signalOperationExecuted,l);a()};t.subscribe(ops.OdtDocument.signalCursorAdded,b);t.subscribe(ops.OdtDocument.signalCursorRemoved,h);t.subscribe(ops.OdtDocument.signalCursorMoved,r);t.subscribe(ops.OdtDocument.signalParagraphStyleModified,d);t.subscribe(ops.OdtDocument.signalParagraphChanged,f);t.subscribe(ops.OdtDocument.signalOperationExecuted,l);q()};gui.DirectTextStyler.textStylingChanged="textStyling/changed"; +(function(){return gui.DirectTextStyler})(); +// Input 96 +runtime.loadClass("odf.Namespaces");runtime.loadClass("odf.ObjectNameGenerator"); +gui.ImageManager=function(g,k,e){var n={"image/gif":".gif","image/jpeg":".jpg","image/png":".png"},m=odf.Namespaces.textns,q=g.getOdtDocument(),b=q.getFormatting(),h={};this.insertImage=function(r,d,f,a){var c;runtime.assert(0c.width&&(p=c.width/f);a>c.height&&(l=c.height/a);p=Math.min(p,l);c=f*p;f=a*p;l=q.getOdfCanvas().odfContainer().rootElement.styles;a=r.toLowerCase();var p=n.hasOwnProperty(a)?n[a]:null,u;a=[];runtime.assert(null!==p,"Image type is not supported: "+r);p="Pictures/"+e.generateImageName()+p;u=new ops.OpSetBlob;u.init({memberid:k,filename:p,mimetype:r,content:d});a.push(u);b.getStyleElement("Graphics","graphic",[l])||(r=new ops.OpAddStyle,r.init({memberid:k,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(r));r=e.generateStyleName();d=new ops.OpAddStyle;d.init({memberid:k,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"}}}); +a.push(d);u=new ops.OpInsertImage;u.init({memberid:k,position:q.getCursorPosition(k),filename:p,frameWidth:c+"cm",frameHeight:f+"cm",frameStyleName:r,frameName:e.generateFrameName()});a.push(u);g.enqueue(a)}}; +// Input 97 +/* + + Copyright (C) 2013 KO GmbH + + @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 . + + 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"); +gui.TextManipulator=function(g,k,e){function n(b){var d=new ops.OpRemoveText;d.init({memberid:k,position:b.position,length:b.length});return d}function m(b){0>b.length&&(b.position+=b.length,b.length=-b.length);return b}function q(e,d){var f=new core.PositionFilterChain,a=gui.SelectionMover.createPositionIterator(b.getRootElement(e)),c=d?a.nextPosition:a.previousPosition;f.addFilter("BaseFilter",b.getPositionFilter());f.addFilter("RootFilter",b.createRootFilter(k));for(a.setUnfilteredPosition(e,0);c();)if(f.acceptPosition(a)=== +h)return!0;return!1}var b=g.getOdtDocument(),h=core.PositionFilter.FilterResult.FILTER_ACCEPT;this.enqueueParagraphSplittingOps=function(){var e=m(b.getCursorSelection(k)),d,f=[];0 + + @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 . + + 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("gui.Caret"); +gui.CaretManager=function(g){function k(a){return c.hasOwnProperty(a)?c[a]:null}function e(){return Object.keys(c).map(function(a){return c[a]})}function n(a){a===g.getInputMemberId()&&g.getSession().getOdtDocument().getOdfCanvas().getElement().removeAttribute("tabindex");delete c[a]}function m(a){a=a.getMemberId();a===g.getInputMemberId()&&(a=k(a))&&a.refreshCursorBlinking()}function q(){var a=k(g.getInputMemberId());l=!1;a&&a.ensureVisible()}function b(){var a=k(g.getInputMemberId());a&&(a.handleUpdate(), +l||(l=!0,runtime.setTimeout(q,50)))}function h(a){a.memberId===g.getInputMemberId()&&b()}function r(){var a=k(g.getInputMemberId());a&&a.setFocus()}function d(){var a=k(g.getInputMemberId());a&&a.removeFocus()}function f(){var a=k(g.getInputMemberId());a&&a.show()}function a(){var a=k(g.getInputMemberId());a&&a.hide()}var c={},p=runtime.getWindow(),l=!1;this.registerCursor=function(a,d,e){var f=a.getMemberId();d=new gui.Caret(a,d,e);c[f]=d;f===g.getInputMemberId()?(runtime.log("Starting to track input on new cursor of "+ +f),a.handleUpdate=b,g.getSession().getOdtDocument().getOdfCanvas().getElement().setAttribute("tabindex",-1),g.getEventManager().focus()):a.handleUpdate=d.handleUpdate;return d};this.getCaret=k;this.getCarets=e;this.destroy=function(b){var k=g.getSession().getOdtDocument(),l=g.getEventManager(),q=e();k.unsubscribe(ops.OdtDocument.signalParagraphChanged,h);k.unsubscribe(ops.OdtDocument.signalCursorMoved,m);k.unsubscribe(ops.OdtDocument.signalCursorRemoved,n);l.unsubscribe("focus",r);l.unsubscribe("blur", +d);p.removeEventListener("focus",f,!1);p.removeEventListener("blur",a,!1);(function t(a,c){c?b(c):a + + @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 . + + 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("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,k,e,n,m){function q(a,b,c){function d(b,c,e){c=b+'[editinfo|memberid="'+a+'"]'+e+c;a:{var f=u.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:u.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 b(a){var b,c;for(c in w)w.hasOwnProperty(c)&&(b=w[c],a?b.show():b.hide())}function h(a){n.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function r(a){var b=a.getMemberId();a=a.getProperties();q(b,a.fullName,a.color);k===b&&q("","",a.color)}function d(a){var b=a.getMemberId(),c=e.getOdtDocument().getMember(b).getProperties();n.registerCursor(a,v,t);m.registerCursor(a, +!0);if(a=n.getCaret(b))a.setAvatarImageUrl(c.imageUrl),a.setColor(c.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+b+"'! +++")}function f(a){a=a.getMemberId();var b=m.getSelectionView(k),c=m.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),d=n.getCaret(k);a===k?(c.hide(),b&&b.show(),d&&d.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(c.show(),b&&b.hide(),d&&d.hide())}function a(a){m.removeSelectionView(a)}function c(a){var b=a.paragraphElement,c=a.memberId;a=a.timeStamp; +var d,f="",g=b.getElementsByTagNameNS(B,"editinfo")[0];g?(f=g.getAttributeNS(B,"id"),d=w[f]):(f=Math.random().toString(),d=new ops.EditInfo(b,e.getOdtDocument()),d=new gui.EditInfoMarker(d,y),g=b.getElementsByTagNameNS(B,"editinfo")[0],g.setAttributeNS(B,"id",f),w[f]=d);d.addEdit(c,new Date(a))}function p(){N=!0}function l(){s=runtime.getWindow().setInterval(function(){N&&(m.rerenderSelectionViews(),N=!1)},200)}var u,B="urn:webodf:names:editinfo",w={},y=void 0!==g.editInfoMarkersInitiallyVisible? +Boolean(g.editInfoMarkersInitiallyVisible):!0,v=void 0!==g.caretAvatarsInitiallyVisible?Boolean(g.caretAvatarsInitiallyVisible):!0,t=void 0!==g.caretBlinksOnRangeSelect?Boolean(g.caretBlinksOnRangeSelect):!0,s,N=!1;this.showEditInfoMarkers=function(){y||(y=!0,b(y))};this.hideEditInfoMarkers=function(){y&&(y=!1,b(y))};this.showCaretAvatars=function(){v||(v=!0,h(v))};this.hideCaretAvatars=function(){v&&(v=!1,h(v))};this.getSession=function(){return e};this.getCaret=function(a){return n.getCaret(a)}; +this.destroy=function(b){var g=e.getOdtDocument(),h=Object.keys(w).map(function(a){return w[a]});g.unsubscribe(ops.OdtDocument.signalMemberAdded,r);g.unsubscribe(ops.OdtDocument.signalMemberUpdated,r);g.unsubscribe(ops.OdtDocument.signalCursorAdded,d);g.unsubscribe(ops.OdtDocument.signalCursorRemoved,a);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,c);g.unsubscribe(ops.OdtDocument.signalCursorMoved,f);g.unsubscribe(ops.OdtDocument.signalParagraphChanged,p);g.unsubscribe(ops.OdtDocument.signalTableAdded, +p);g.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,p);runtime.getWindow().clearInterval(s);u.parentNode.removeChild(u);(function U(a,c){c?b(c):a 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"; -// Input 102 -var webodf_version="0.4.2-1451-gc9cf878";