diff --git a/webodf/lib/gui/SessionController.js b/webodf/lib/gui/SessionController.js index 278875607..1e1236659 100644 --- a/webodf/lib/gui/SessionController.js +++ b/webodf/lib/gui/SessionController.js @@ -304,7 +304,7 @@ gui.SessionControllerOptions = function () { * @return {undefined} */ function forwardUndoStackChange(e) { - odtDocument.emit(ops.OdtDocument.signalUndoStackChanged, e); + odtDocument.DONOTUSE_emitSignalUndoStackChanged(e); } /** @@ -374,7 +374,7 @@ gui.SessionControllerOptions = function () { newSelectionRange.setEnd(shadowCursorIterator.container(), shadowCursorIterator.unfilteredDomOffset()); } shadowCursor.setSelectedRange(newSelectionRange, handleEnd === 'right'); - odtDocument.emit(ops.Document.signalCursorMoved, shadowCursor); + odtDocument.DONOTUSE_emitSignalCursorMoved(shadowCursor); } } } @@ -400,7 +400,7 @@ gui.SessionControllerOptions = function () { selectionController.expandToParagraphBoundaries(selectionRange.range); } shadowCursor.setSelectedRange(selectionRange.range, selectionRange.hasForwardSelection); - odtDocument.emit(ops.Document.signalCursorMoved, shadowCursor); + odtDocument.DONOTUSE_emitSignalCursorMoved(shadowCursor); } } } diff --git a/webodf/lib/gui/SessionView.js b/webodf/lib/gui/SessionView.js index d2b5dd484..dd72894be 100644 --- a/webodf/lib/gui/SessionView.js +++ b/webodf/lib/gui/SessionView.js @@ -410,7 +410,7 @@ gui.SessionViewOptions = function () { var annotationViewManager = odfCanvas.getAnnotationViewManager(); if (annotationViewManager) { annotationViewManager.rehighlightAnnotations(); - odtDocument.fixCursorPositions(); + odtDocument.fixCursorPositions(false); // TODO: workaround, ideally this would not be needed } } diff --git a/webodf/lib/ops/OdtDocument.js b/webodf/lib/ops/OdtDocument.js index af2b42628..ccb32cc7c 100644 --- a/webodf/lib/ops/OdtDocument.js +++ b/webodf/lib/ops/OdtDocument.js @@ -154,7 +154,7 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { initialDoc = rootElement.cloneNode(true); odfCanvas.refreshAnnotations(); // workaround AnnotationViewManager not fixing up cursor positions after creating the highlighting - self.fixCursorPositions(); + self.fixCursorPositions(false); return initialDoc; }; @@ -165,9 +165,6 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { var odfContainer = odfCanvas.odfContainer(), rootNode; - eventNotifier.unsubscribe(ops.OdtDocument.signalStepsInserted, stepsTranslator.handleStepsInserted); - eventNotifier.unsubscribe(ops.OdtDocument.signalStepsRemoved, stepsTranslator.handleStepsRemoved); - // TODO Replace with a neater hack for reloading the Odt tree // Once this is fixed, SelectionView.addOverlays can be removed odfContainer.setRootElement(documentElement); @@ -175,8 +172,6 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { odfCanvas.refreshCSS(); rootNode = getRootNode(); stepsTranslator = new ops.OdtStepsTranslator(rootNode, createPositionIterator(rootNode), filter, 500); - eventNotifier.subscribe(ops.OdtDocument.signalStepsInserted, stepsTranslator.handleStepsInserted); - eventNotifier.subscribe(ops.OdtDocument.signalStepsRemoved, stepsTranslator.handleStepsRemoved); }; /** @@ -449,15 +444,20 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { * document's metadata, such as dc:creator, * meta:editing-cycles, and dc:creator. * @param {!ops.Operation} op + * @param {!Array.} events + * @return {undefined} */ - function handleOperationExecuted(op) { + function finishOperationExecution(op, events) { var opspec = op.spec(), memberId = opspec.memberid, date = new Date(opspec.timestamp).toISOString(), odfContainer = odfCanvas.odfContainer(), - /**@type{!{setProperties: !Object, removedProperties: ?Array.}}*/ + /**@type{!ops.Operation.Event}*/ + changedMetadataEvent, + /**@type{!{setProperties: !Object, removedProperties: !Array.}}*/ changedMetadata, - fullName; + fullName, + i; // If the operation is an edit (that changes the // ODF that will be saved), then update metadata. @@ -468,13 +468,25 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { "dc:date": date }, null); - changedMetadata = { - setProperties: { - "dc:creator": fullName, - "dc:date": date - }, - removedProperties: [] - }; + // find any existing metadataupdated event or create one + for (i = 0; i < events.length; i += 1) { + if (events[i].eventid === ops.OdtDocument.signalMetadataUpdated) { + changedMetadataEvent = events[i]; + changedMetadata = /**@type{!{setProperties: !Object, removedProperties: !Array.}}*/(changedMetadataEvent.args); + break; + } + } + if (!changedMetadataEvent) { + changedMetadata = { setProperties: {}, removedProperties: [] }; + changedMetadataEvent = { + eventid: ops.OdtDocument.signalMetadataUpdated, + args: changedMetadata + }; + events.push(changedMetadataEvent); + } + + changedMetadata.setProperties["dc:creator"] = fullName; + changedMetadata.setProperties["dc:date"] = date; // If no previous op was found in this session, // then increment meta:editing-cycles by 1. @@ -492,10 +504,49 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { } lastEditingOp = op; - self.emit(ops.OdtDocument.signalMetadataUpdated, changedMetadata); } + + eventNotifier.emit(ops.OdtDocument.signalOperationEnd, op); + + events.forEach(function(event) { + eventNotifier.emit(event.eventid, event.args); + }); } + /** + * @param {!ops.Operation} op + * @return {!boolean} + */ + this.executeOperation = function(op) { + var events; + + eventNotifier.emit(ops.OdtDocument.signalOperationStart, op); + + events = op.execute(self); + if (events === null) { + return false; + } + + finishOperationExecution(op, events); + return true; + }; + + /** + * @param {*} args + * @return {undefined} + */ + this.prepareBatchProcessing = function(args) { + eventNotifier.emit(ops.OdtDocument.signalProcessingBatchStart, args); + }; + + /** + * @param {*} args + * @return {undefined} + */ + this.finishBatchProcessing = function (args) { + eventNotifier.emit(ops.OdtDocument.signalProcessingBatchEnd, args); + }; + /** * Upgrades literal whitespaces (' ') to , * when given a textNode containing the whitespace and an offset @@ -673,8 +724,14 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { * walkable positions; if not, move the cursor 1 filtered step backward * which guarantees walkable state for all cursors, * while keeping them inside the same root. An event will be raised for this cursor if it is moved + * @param {!Array.|!boolean} events array to add events for moved cursors, needs to be otherwise explicitely set to false + * @return {undefined} */ - this.fixCursorPositions = function () { + this.fixCursorPositions = function (events) { + var /** @type{!Array.}*/ movedCursors = []; + + runtime.assert(Array.isArray(events) || (typeof events === "boolean" && events === false), "second parameter to fixCursorPositions needs to be set to false or an event"); + Object.keys(cursors).forEach(function (memberId) { var cursor = cursors[memberId], root = getRoot(cursor.getNode()), @@ -717,9 +774,19 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { if (cursorMoved) { cursor.setSelectedRange(selectedRange, cursor.hasForwardSelection()); - self.emit(ops.Document.signalCursorMoved, cursor); + movedCursors.push(cursor); } }); + + if (events) { + movedCursors.forEach(function(cursor) { + events.push({ eventid: ops.Document.signalCursorMoved, args: cursor }); + }); + } else { + movedCursors.forEach(function(cursor) { + eventNotifier.emit(ops.Document.signalCursorMoved, cursor); + }); + } }; /** @@ -856,7 +923,6 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { if (cursor) { cursor.removeFromDocument(); delete cursors[memberid]; - self.emit(ops.Document.signalCursorRemoved, memberid); return true; } return false; @@ -890,15 +956,6 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { return odfCanvas.getFormatting(); }; - /** - * @param {!string} eventid - * @param {*} args - * @return {undefined} - */ - this.emit = function (eventid, args) { - eventNotifier.emit(eventid, args); - }; - /** * @param {!string} eventid * @param {!Function} cb @@ -942,6 +999,60 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { callback(); }; + /** + * Process steps being inserted into the document. Will add a steps inserted signal + * to the passed events list + * @param {!{position: !number}} args + * @param {!Array.} events + * @return {undefined} + */ + this.handleStepsInserted = function(args, events) { + stepsTranslator.handleStepsInserted(args); + // signal not used in webodf, but 3rd-party (NVivo) + events.push({ + eventid: ops.OdtDocument.signalStepsInserted, + args: args + }); + }; + + /** + * Process steps being removed from the document. Will emit a steps removed signal on + * behalf of the caller + * @param {!{position: !number}} args + * @param {!Array.} events + * @return {undefined} + */ + this.handleStepsRemoved = function(args, events) { + stepsTranslator.handleStepsRemoved(args); + // signal not used in webodf, but 3rd-party (NVivo) + events.push({ + eventid: ops.OdtDocument.signalStepsRemoved, + args: args + }); + }; + + /** + * Emit the signal that the passed cursor moved. + * TODO: get rid of this method, noone should be able to emit signals by direct calls, only by op execution + * @internal + * @param {!ops.OdtCursor} cursor + * @return {undefined} + */ + this.DONOTUSE_emitSignalCursorMoved = function(cursor) { + eventNotifier.emit(ops.Document.signalCursorMoved, cursor); + }; + + /** + * Emit the signal that the passed cursor moved. + * TODO: get rid of this method, noone should be able to emit signals by direct calls, only by op execution + * @internal + * @param {?Event} e + * @return {undefined} + */ + this.DONOTUSE_emitSignalUndoStackChanged = function(e) { + eventNotifier.emit(ops.OdtDocument.signalUndoStackChanged, e); + }; + /** * @return {undefined} */ @@ -951,9 +1062,6 @@ ops.OdtDocument = function OdtDocument(odfCanvas) { filter = new ops.TextPositionFilter(); stepUtils = new odf.StepUtils(); stepsTranslator = new ops.OdtStepsTranslator(rootNode, createPositionIterator(rootNode), filter, 500); - eventNotifier.subscribe(ops.OdtDocument.signalStepsInserted, stepsTranslator.handleStepsInserted); - eventNotifier.subscribe(ops.OdtDocument.signalStepsRemoved, stepsTranslator.handleStepsRemoved); - eventNotifier.subscribe(ops.OdtDocument.signalOperationEnd, handleOperationExecuted); eventNotifier.subscribe(ops.OdtDocument.signalProcessingBatchEnd, core.Task.processTasks); } init(); diff --git a/webodf/lib/ops/OpAddAnnotation.js b/webodf/lib/ops/OpAddAnnotation.js index 9feff3b62..8665a28b0 100644 --- a/webodf/lib/ops/OpAddAnnotation.js +++ b/webodf/lib/ops/OpAddAnnotation.js @@ -137,13 +137,15 @@ ops.OpAddAnnotation = function OpAddAnnotation() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), annotation, annotationEnd, cursor = odtDocument.getCursor(memberid), selectedRange, - paragraphElement; + paragraphElement, + events = []; doc = odtDocument.getDOMDocument(); @@ -158,7 +160,7 @@ ops.OpAddAnnotation = function OpAddAnnotation() { insertNodeAtPosition(odtDocument, annotationEnd, position + length); } insertNodeAtPosition(odtDocument, annotation, position); - odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position: position}); + odtDocument.handleStepsInserted({position: position}, events); // Move the cursor inside the new annotation, // by selecting the paragraph's range. @@ -168,14 +170,14 @@ ops.OpAddAnnotation = function OpAddAnnotation() { selectedRange.selectNodeContents(paragraphElement); cursor.setSelectedRange(selectedRange, false); cursor.setSelectionType(ops.OdtCursor.RangeSelection); - odtDocument.emit(ops.Document.signalCursorMoved, cursor); + events.push({eventid: ops.Document.signalCursorMoved, args: cursor}); } // Track this annotation odtDocument.getOdfCanvas().addAnnotation(annotation); - odtDocument.fixCursorPositions(); - odtDocument.emit(ops.OdtDocument.signalAnnotationAdded, { memberId: memberid, annotation: annotation }); + odtDocument.fixCursorPositions(events); + events.push({eventid: ops.OdtDocument.signalAnnotationAdded, args: { memberId: memberid, annotation: annotation }}); - return true; + return events; }; /** diff --git a/webodf/lib/ops/OpAddCursor.js b/webodf/lib/ops/OpAddCursor.js index a3ade9ea0..d909938b9 100644 --- a/webodf/lib/ops/OpAddCursor.js +++ b/webodf/lib/ops/OpAddCursor.js @@ -46,6 +46,7 @@ ops.OpAddCursor = function OpAddCursor() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -53,13 +54,13 @@ ops.OpAddCursor = function OpAddCursor() { // there should be none if (cursor) { - return false; + return null; } cursor = new ops.OdtCursor(memberid, odtDocument); odtDocument.addCursor(cursor); - odtDocument.emit(ops.Document.signalCursorAdded, cursor); - return true; + + return [{eventid: ops.Document.signalCursorAdded, args: cursor}]; }; /** diff --git a/webodf/lib/ops/OpAddMember.js b/webodf/lib/ops/OpAddMember.js index 5afce4329..6c4e84228 100644 --- a/webodf/lib/ops/OpAddMember.js +++ b/webodf/lib/ops/OpAddMember.js @@ -52,19 +52,19 @@ ops.OpAddMember = function OpAddMember() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), member; if (odtDocument.getMember(memberid)) { - return false; + return null; } member = new ops.Member(memberid, setProperties); odtDocument.addMember(member); - odtDocument.emit(ops.Document.signalMemberAdded, member); - return true; + return [{eventid: ops.Document.signalMemberAdded, args: member}]; }; /** diff --git a/webodf/lib/ops/OpAddStyle.js b/webodf/lib/ops/OpAddStyle.js index 0a2d83fed..3a37e68aa 100644 --- a/webodf/lib/ops/OpAddStyle.js +++ b/webodf/lib/ops/OpAddStyle.js @@ -56,6 +56,7 @@ ops.OpAddStyle = function OpAddStyle() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -65,7 +66,7 @@ ops.OpAddStyle = function OpAddStyle() { styleNode = dom.createElementNS(stylens, 'style:style'); if (!styleNode) { - return false; + return null; } if (setProperties) { @@ -83,9 +84,9 @@ ops.OpAddStyle = function OpAddStyle() { odtDocument.getOdfCanvas().refreshCSS(); if (!isAutomaticStyle) { - odtDocument.emit(ops.OdtDocument.signalCommonStyleCreated, {name: styleName, family: styleFamily}); + return [{eventid: ops.OdtDocument.signalCommonStyleCreated, args: {name: styleName, family: styleFamily}}]; } - return true; + return []; }; /** diff --git a/webodf/lib/ops/OpApplyDirectStyling.js b/webodf/lib/ops/OpApplyDirectStyling.js index 515b6427f..5e5b5de6e 100644 --- a/webodf/lib/ops/OpApplyDirectStyling.js +++ b/webodf/lib/ops/OpApplyDirectStyling.js @@ -80,28 +80,33 @@ ops.OpApplyDirectStyling = function OpApplyDirectStyling() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), range = odtDocument.convertCursorToDomRange(position, length), - impactedParagraphs = odfUtils.getParagraphElements(range); + impactedParagraphs = odfUtils.getParagraphElements(range), + events = []; applyStyle(odtDocument, range, setProperties); range.detach(); odtDocument.getOdfCanvas().refreshCSS(); - odtDocument.fixCursorPositions(); // The container splits may leave the cursor in an invalid spot + odtDocument.fixCursorPositions(events); // The container splits may leave the cursor in an invalid spot impactedParagraphs.forEach(function (n) { - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: n, - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: n, + memberId: memberid, + timeStamp: timestamp + } }); }); odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + return events; }; /** diff --git a/webodf/lib/ops/OpApplyHyperlink.js b/webodf/lib/ops/OpApplyHyperlink.js index 584c860ed..24aa11737 100644 --- a/webodf/lib/ops/OpApplyHyperlink.js +++ b/webodf/lib/ops/OpApplyHyperlink.js @@ -78,6 +78,7 @@ ops.OpApplyHyperlink = function OpApplyHyperlink() { /** * TODO: support adding image link * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -86,10 +87,11 @@ ops.OpApplyHyperlink = function OpApplyHyperlink() { boundaryNodes = domUtils.splitBoundaries(range), /**@type{!Array.}*/ modifiedParagraphs = [], - textNodes = odfUtils.getTextNodes(range, false); + textNodes = odfUtils.getTextNodes(range, false), + events = []; if (textNodes.length === 0) { - return false; + return null; } textNodes.forEach(function (node) { @@ -110,18 +112,21 @@ ops.OpApplyHyperlink = function OpApplyHyperlink() { boundaryNodes.forEach(domUtils.normalizeTextNodes); range.detach(); - odtDocument.fixCursorPositions(); + odtDocument.fixCursorPositions(events); odtDocument.getOdfCanvas().refreshSize(); odtDocument.getOdfCanvas().rerenderAnnotations(); modifiedParagraphs.forEach(function (paragraph) { - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: paragraph, - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: paragraph, + memberId: memberid, + timeStamp: timestamp + } }); }); - return true; + return events; }; /** diff --git a/webodf/lib/ops/OpInsertImage.js b/webodf/lib/ops/OpInsertImage.js index 190f433b9..8d6ca7ce1 100644 --- a/webodf/lib/ops/OpInsertImage.js +++ b/webodf/lib/ops/OpInsertImage.js @@ -80,15 +80,17 @@ ops.OpInsertImage = function OpInsertImage() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), odfCanvas = odtDocument.getOdfCanvas(), domPosition = odtDocument.getTextNodeAtStep(position, memberid), - textNode, refNode, paragraphElement, frameElement; + textNode, refNode, paragraphElement, frameElement, + events = []; if (!domPosition) { - return false; + return null; } textNode = domPosition.textNode; @@ -97,7 +99,7 @@ ops.OpInsertImage = function OpInsertImage() { textNode.splitText(domPosition.offset) : textNode.nextSibling; frameElement = createFrameElement(odtDocument.getDOMDocument()); textNode.parentNode.insertBefore(frameElement, refNode); - odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position: position}); + odtDocument.handleStepsInserted({position: position}, events); // clean up any empty text node which was created by odtDocument.getTextNodeAtStep if (textNode.length === 0) { @@ -106,13 +108,18 @@ ops.OpInsertImage = function OpInsertImage() { odfCanvas.addCssForFrameWithImage(frameElement); odfCanvas.refreshCSS(); - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: paragraphElement, - memberId: memberid, - timeStamp: timestamp - }); odfCanvas.rerenderAnnotations(); - return true; + + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: paragraphElement, + memberId: memberid, + timeStamp: timestamp + } + }); + + return events; }; /** diff --git a/webodf/lib/ops/OpInsertTable.js b/webodf/lib/ops/OpInsertTable.js index a60d8b042..c9a91115f 100644 --- a/webodf/lib/ops/OpInsertTable.js +++ b/webodf/lib/ops/OpInsertTable.js @@ -142,13 +142,15 @@ ops.OpInsertTable = function OpInsertTable() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), domPosition = odtDocument.getTextNodeAtStep(position), rootNode = odtDocument.getRootNode(), previousSibling, - tableNode; + tableNode, + events = []; if (domPosition) { tableNode = createTableNode(odtDocument.getDOMDocument()); @@ -157,19 +159,22 @@ ops.OpInsertTable = function OpInsertTable() { previousSibling = odfUtils.getParagraphElement(domPosition.textNode); rootNode.insertBefore(tableNode, previousSibling.nextSibling); // The parent table counts for 1 position, and 1 paragraph is added per cell - odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position: position}); + odtDocument.handleStepsInserted({position: position}, events); odtDocument.getOdfCanvas().refreshSize(); - odtDocument.emit(ops.OdtDocument.signalTableAdded, { - tableElement: tableNode, - memberId: memberid, - timeStamp: timestamp + odtDocument.getOdfCanvas().rerenderAnnotations(); + events.push({ + eventid: ops.OdtDocument.signalTableAdded, + args: { + tableElement: tableNode, + memberId: memberid, + timeStamp: timestamp + } }); - odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + return events; } - return false; + return null; }; /** diff --git a/webodf/lib/ops/OpInsertText.js b/webodf/lib/ops/OpInsertText.js index 14185dfc6..cd37ecbed 100644 --- a/webodf/lib/ops/OpInsertText.js +++ b/webodf/lib/ops/OpInsertText.js @@ -101,6 +101,7 @@ ops.OpInsertText = function OpInsertText() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -115,7 +116,8 @@ ops.OpInsertText = function OpInsertText() { toInsertIndex = 0, spaceElement, cursor = odtDocument.getCursor(memberid), - i; + i, + events = []; /** * @param {string} toInsertText @@ -186,7 +188,7 @@ ops.OpInsertText = function OpInsertText() { previousNode.parentNode.removeChild(previousNode); } - odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position: position}); + odtDocument.handleStepsInserted({position: position}, events); if (cursor && moveCursor) { // Explicitly place the cursor in the desired position after insertion @@ -196,23 +198,26 @@ ops.OpInsertText = function OpInsertText() { // the textnode + cursor reordering logic from OdtDocument's // getTextNodeAtStep. odtDocument.moveCursor(memberid, position + text.length, 0); - odtDocument.emit(ops.Document.signalCursorMoved, cursor); + events.push({eventid: ops.Document.signalCursorMoved, args: cursor}); } odtDocument.downgradeWhitespacesAtPosition(position); odtDocument.downgradeWhitespacesAtPosition(position + text.length); odtDocument.getOdfCanvas().refreshSize(); - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: paragraphElement, - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: paragraphElement, + memberId: memberid, + timeStamp: timestamp + } }); odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + return events; } - return false; + return null; }; /** diff --git a/webodf/lib/ops/OpMergeParagraph.js b/webodf/lib/ops/OpMergeParagraph.js index 90fb2468b..ac1cb5e7d 100644 --- a/webodf/lib/ops/OpMergeParagraph.js +++ b/webodf/lib/ops/OpMergeParagraph.js @@ -206,7 +206,7 @@ ops.OpMergeParagraph = function OpMergeParagraph() { /** * @param {!ops.Document} document - * @return {!boolean} + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{!ops.OdtDocument}*/(document), @@ -216,7 +216,8 @@ ops.OpMergeParagraph = function OpMergeParagraph() { rootNode = odtDocument.getRootNode(), collapseRules = new odf.CollapsingRules(rootNode), stepIterator = odtDocument.createStepIterator(rootNode, 0, [odtDocument.getPositionFilter()], rootNode), - downgradeOffset; + downgradeOffset, + events = []; // Asserting a specific order for destination + source makes it easier to decide which ends to upgrade runtime.assert(destinationStartPosition < sourceStartPosition, @@ -244,7 +245,7 @@ ops.OpMergeParagraph = function OpMergeParagraph() { collapseRules.mergeChildrenIntoParent(sourceParagraph); // Merging removes a single step between the boundary of the two paragraphs - odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position: sourceStartPosition - 1}); + odtDocument.handleStepsRemoved({position: sourceStartPosition - 1}, events); // Downgrade trailing spaces at the end of the destination paragraph, and the beginning of the source paragraph. // These are the only two places that might need downgrading as a result of the merge. @@ -267,20 +268,23 @@ ops.OpMergeParagraph = function OpMergeParagraph() { if (cursor && moveCursor) { odtDocument.moveCursor(memberid, sourceStartPosition - 1, 0); - odtDocument.emit(ops.Document.signalCursorMoved, cursor); + events.push({eventid: ops.Document.signalCursorMoved, args:cursor}); } - odtDocument.fixCursorPositions(); + odtDocument.fixCursorPositions(events); odtDocument.getOdfCanvas().refreshSize(); // TODO: signal also the deleted paragraphs, so e.g. SessionView can clean up the EditInfo - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: destinationParagraph, - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: destinationParagraph, + memberId: memberid, + timeStamp: timestamp + } }); odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + return events; }; /** diff --git a/webodf/lib/ops/OpMoveCursor.js b/webodf/lib/ops/OpMoveCursor.js index 5bf2eb6ef..c4acc2c4b 100644 --- a/webodf/lib/ops/OpMoveCursor.js +++ b/webodf/lib/ops/OpMoveCursor.js @@ -49,6 +49,7 @@ ops.OpMoveCursor = function OpMoveCursor() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -56,14 +57,14 @@ ops.OpMoveCursor = function OpMoveCursor() { selectedRange; if (!cursor) { - return false; + return null; } selectedRange = odtDocument.convertCursorToDomRange(position, length); cursor.setSelectedRange(selectedRange, length >= 0); cursor.setSelectionType(selectionType); - odtDocument.emit(ops.Document.signalCursorMoved, cursor); - return true; + + return [{eventid: ops.Document.signalCursorMoved, args: cursor}]; }; /** diff --git a/webodf/lib/ops/OpRemoveAnnotation.js b/webodf/lib/ops/OpRemoveAnnotation.js index 3a3031663..780d985b1 100644 --- a/webodf/lib/ops/OpRemoveAnnotation.js +++ b/webodf/lib/ops/OpRemoveAnnotation.js @@ -52,20 +52,22 @@ ops.OpRemoveAnnotation = function OpRemoveAnnotation() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), iterator = odtDocument.getIteratorAtPosition(position), container = iterator.container(), annotationNode, - annotationEnd; + annotationEnd, + events = []; while (!(container.namespaceURI === odf.Namespaces.officens && container.localName === 'annotation')) { container = container.parentNode; } if (container === null) { - return false; + return null; } annotationNode = /**@type{!odf.AnnotationElement}*/(container); @@ -90,11 +92,12 @@ ops.OpRemoveAnnotation = function OpRemoveAnnotation() { annotationEnd.parentNode.removeChild(annotationEnd); } // The specified position is the first walkable step in the annotation. The position is always just before the first point of change - odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position: position > 0 ? position - 1 : position}); + odtDocument.handleStepsRemoved({position: position > 0 ? position - 1 : position}, events); odtDocument.getOdfCanvas().rerenderAnnotations(); - odtDocument.fixCursorPositions(); - return true; + odtDocument.fixCursorPositions(events); + + return events; }; /** diff --git a/webodf/lib/ops/OpRemoveBlob.js b/webodf/lib/ops/OpRemoveBlob.js index 487e7ff1c..9be150fc4 100644 --- a/webodf/lib/ops/OpRemoveBlob.js +++ b/webodf/lib/ops/OpRemoveBlob.js @@ -47,11 +47,12 @@ ops.OpRemoveBlob = function OpRemoveBlob() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document); odtDocument.getOdfCanvas().odfContainer().removeBlob(filename); - return true; + return []; }; /** diff --git a/webodf/lib/ops/OpRemoveCursor.js b/webodf/lib/ops/OpRemoveCursor.js index 60eef7138..58e762742 100644 --- a/webodf/lib/ops/OpRemoveCursor.js +++ b/webodf/lib/ops/OpRemoveCursor.js @@ -46,14 +46,15 @@ ops.OpRemoveCursor = function OpRemoveCursor() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document); if (!odtDocument.removeCursor(memberid)) { - return false; + return null; } - return true; + return [{eventid:ops.Document.signalCursorRemoved, args: memberid}]; }; /** diff --git a/webodf/lib/ops/OpRemoveHyperlink.js b/webodf/lib/ops/OpRemoveHyperlink.js index 8106d7d24..efcbb2a98 100644 --- a/webodf/lib/ops/OpRemoveHyperlink.js +++ b/webodf/lib/ops/OpRemoveHyperlink.js @@ -50,26 +50,31 @@ ops.OpRemoveHyperlink = function OpRemoveHyperlink() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), range = odtDocument.convertCursorToDomRange(position, length), links = odfUtils.getHyperlinkElements(range), - node; + node, + events = []; runtime.assert(links.length === 1, "The given range should only contain a single link."); node = domUtils.mergeIntoParent(/**@type{!Node}*/(links[0])); range.detach(); - odtDocument.fixCursorPositions(); + odtDocument.fixCursorPositions(events); odtDocument.getOdfCanvas().refreshSize(); odtDocument.getOdfCanvas().rerenderAnnotations(); - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: odfUtils.getParagraphElement(node), - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: odfUtils.getParagraphElement(node), + memberId: memberid, + timeStamp: timestamp + } }); - return true; + return events; }; /** diff --git a/webodf/lib/ops/OpRemoveMember.js b/webodf/lib/ops/OpRemoveMember.js index e7b08aff1..b8be17c25 100644 --- a/webodf/lib/ops/OpRemoveMember.js +++ b/webodf/lib/ops/OpRemoveMember.js @@ -46,17 +46,16 @@ ops.OpRemoveMember = function OpRemoveMember() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document); if (!odtDocument.getMember(memberid)) { - return false; + return null; } odtDocument.removeMember(memberid); - odtDocument.emit(ops.Document.signalMemberRemoved, memberid); - - return true; + return [{ eventid: ops.Document.signalMemberRemoved, args: memberid}]; }; /** diff --git a/webodf/lib/ops/OpRemoveStyle.js b/webodf/lib/ops/OpRemoveStyle.js index e6dedade8..9cc23b890 100644 --- a/webodf/lib/ops/OpRemoveStyle.js +++ b/webodf/lib/ops/OpRemoveStyle.js @@ -48,20 +48,21 @@ ops.OpRemoveStyle = function OpRemoveStyle() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), styleNode = odtDocument.getFormatting().getStyleElement(styleName, styleFamily); if (!styleNode) { - return false; + return null; } styleNode.parentNode.removeChild(styleNode); odtDocument.getOdfCanvas().refreshCSS(); - odtDocument.emit(ops.OdtDocument.signalCommonStyleDeleted, {name: styleName, family: styleFamily}); - return true; + + return [{eventid: ops.OdtDocument.signalCommonStyleDeleted, args: {name: styleName, family: styleFamily}}]; }; /** diff --git a/webodf/lib/ops/OpRemoveText.js b/webodf/lib/ops/OpRemoveText.js index 0a09e22d5..f6314121a 100644 --- a/webodf/lib/ops/OpRemoveText.js +++ b/webodf/lib/ops/OpRemoveText.js @@ -55,6 +55,7 @@ ops.OpRemoveText = function OpRemoveText() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -62,7 +63,8 @@ ops.OpRemoveText = function OpRemoveText() { textNodes, paragraph, cursor = odtDocument.getCursor(memberid), - collapseRules = new odf.CollapsingRules(odtDocument.getRootNode()); + collapseRules = new odf.CollapsingRules(odtDocument.getRootNode()), + events = []; odtDocument.upgradeWhitespacesAtPosition(position); odtDocument.upgradeWhitespacesAtPosition(position + length); @@ -91,23 +93,26 @@ ops.OpRemoveText = function OpRemoveText() { } }); - odtDocument.emit(ops.OdtDocument.signalStepsRemoved, {position: position}); + odtDocument.handleStepsRemoved({position: position}, events); odtDocument.downgradeWhitespacesAtPosition(position); - odtDocument.fixCursorPositions(); + odtDocument.fixCursorPositions(events); odtDocument.getOdfCanvas().refreshSize(); - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: paragraph, - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: paragraph, + memberId: memberid, + timeStamp: timestamp + } }); if (cursor) { cursor.resetSelectionType(); - odtDocument.emit(ops.Document.signalCursorMoved, cursor); + events.push({eventid: ops.Document.signalCursorMoved, args: cursor}); } odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + return events; }; /** diff --git a/webodf/lib/ops/OpSetBlob.js b/webodf/lib/ops/OpSetBlob.js index 8978bd0fe..858c6ab59 100644 --- a/webodf/lib/ops/OpSetBlob.js +++ b/webodf/lib/ops/OpSetBlob.js @@ -49,11 +49,12 @@ ops.OpSetBlob = function OpSetBlob() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document); odtDocument.getOdfCanvas().odfContainer().setBlob(filename, mimetype, content); - return true; + return []; }; /** diff --git a/webodf/lib/ops/OpSetParagraphStyle.js b/webodf/lib/ops/OpSetParagraphStyle.js index 0c33350c0..d6947f0cc 100644 --- a/webodf/lib/ops/OpSetParagraphStyle.js +++ b/webodf/lib/ops/OpSetParagraphStyle.js @@ -71,6 +71,7 @@ ops.OpSetParagraphStyle = function OpSetParagraphStyle() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -89,16 +90,18 @@ ops.OpSetParagraphStyle = function OpSetParagraphStyle() { } odtDocument.getOdfCanvas().refreshSize(); - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: paragraphNode, - timeStamp: timestamp, - memberId: memberid - }); - odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + + return [{ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: paragraphNode, + timeStamp: timestamp, + memberId: memberid + } + }]; } - return false; + return null; }; /** diff --git a/webodf/lib/ops/OpSplitParagraph.js b/webodf/lib/ops/OpSplitParagraph.js index d84f6167a..1538e125d 100644 --- a/webodf/lib/ops/OpSplitParagraph.js +++ b/webodf/lib/ops/OpSplitParagraph.js @@ -71,22 +71,24 @@ ops.OpSplitParagraph = function OpSplitParagraph() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{!ops.OdtDocument}*/(document), domPosition, paragraphNode, targetNode, node, splitNode, splitChildNode, keptChildNode, - cursor = odtDocument.getCursor(memberid); + cursor = odtDocument.getCursor(memberid), + events = []; odtDocument.upgradeWhitespacesAtPosition(position); domPosition = odtDocument.getTextNodeAtStep(position); if (!domPosition) { - return false; + return null; } paragraphNode = odfUtils.getParagraphElement(domPosition.textNode); if (!paragraphNode) { - return false; + return null; } if (odfUtils.isListItem(paragraphNode.parentNode)) { @@ -168,29 +170,35 @@ ops.OpSplitParagraph = function OpSplitParagraph() { if (domPosition.textNode.length === 0) { domPosition.textNode.parentNode.removeChild(domPosition.textNode); } - odtDocument.emit(ops.OdtDocument.signalStepsInserted, {position: position}); + odtDocument.handleStepsInserted({position: position}, events); if (cursor && moveCursor) { odtDocument.moveCursor(memberid, position + 1, 0); - odtDocument.emit(ops.Document.signalCursorMoved, cursor); + events.push({eventid: ops.Document.signalCursorMoved, args: cursor}); } - odtDocument.fixCursorPositions(); + odtDocument.fixCursorPositions(events); odtDocument.getOdfCanvas().refreshSize(); // mark both paragraphs as edited - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: paragraphNode, - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: paragraphNode, + memberId: memberid, + timeStamp: timestamp + } }); - odtDocument.emit(ops.OdtDocument.signalParagraphChanged, { - paragraphElement: splitChildNode, - memberId: memberid, - timeStamp: timestamp + events.push({ + eventid: ops.OdtDocument.signalParagraphChanged, + args: { + paragraphElement: splitChildNode, + memberId: memberid, + timeStamp: timestamp + } }); odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + return events; }; /** diff --git a/webodf/lib/ops/OpUpdateMember.js b/webodf/lib/ops/OpUpdateMember.js index ce8f72597..b8c328ff8 100644 --- a/webodf/lib/ops/OpUpdateMember.js +++ b/webodf/lib/ops/OpUpdateMember.js @@ -77,12 +77,13 @@ ops.OpUpdateMember = function OpUpdateMember() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), member = odtDocument.getMember(memberid); if (!member) { - return false; + return null; } if (removedProperties) { @@ -95,8 +96,7 @@ ops.OpUpdateMember = function OpUpdateMember() { } } - odtDocument.emit(ops.Document.signalMemberUpdated, member); - return true; + return [{eventid: ops.Document.signalMemberUpdated, args: member}]; }; /** diff --git a/webodf/lib/ops/OpUpdateMetadata.js b/webodf/lib/ops/OpUpdateMetadata.js index aeb2f80c5..edfbc4a6f 100644 --- a/webodf/lib/ops/OpUpdateMetadata.js +++ b/webodf/lib/ops/OpUpdateMetadata.js @@ -56,6 +56,7 @@ ops.OpUpdateMetadata = function OpUpdateMetadata() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -68,12 +69,13 @@ ops.OpUpdateMetadata = function OpUpdateMetadata() { odfContainer.setMetadata(setProperties, removedPropertiesArray); - odtDocument.emit(ops.OdtDocument.signalMetadataUpdated, { - setProperties: setProperties !== null ? setProperties : {}, - removedProperties: removedPropertiesArray !== null ? removedPropertiesArray : [] - }); - - return true; + return [{ + eventid: ops.OdtDocument.signalMetadataUpdated, + args: { + setProperties: setProperties !== null ? setProperties : {}, + removedProperties: removedPropertiesArray !== null ? removedPropertiesArray : [] + } + }]; }; /** diff --git a/webodf/lib/ops/OpUpdateParagraphStyle.js b/webodf/lib/ops/OpUpdateParagraphStyle.js index 0345cb301..e82d86e49 100644 --- a/webodf/lib/ops/OpUpdateParagraphStyle.js +++ b/webodf/lib/ops/OpUpdateParagraphStyle.js @@ -76,6 +76,7 @@ ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() { /** * @param {!ops.Document} document + * @return {?Array.} */ this.execute = function (document) { var odtDocument = /**@type{ops.OdtDocument}*/(document), @@ -122,11 +123,10 @@ ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() { } odtDocument.getOdfCanvas().refreshCSS(); - odtDocument.emit(ops.OdtDocument.signalParagraphStyleModified, styleName); odtDocument.getOdfCanvas().rerenderAnnotations(); - return true; + return [{eventid:ops.OdtDocument.signalParagraphStyleModified, args: styleName}]; } - return false; + return null; }; /** diff --git a/webodf/lib/ops/Operation.js b/webodf/lib/ops/Operation.js index 3a682d212..450831bbb 100644 --- a/webodf/lib/ops/Operation.js +++ b/webodf/lib/ops/Operation.js @@ -33,6 +33,12 @@ ops.Operation = function Operation() { "use strict"; }; +/**@typedef{{ + eventid:!string, + args:* +}}*/ +ops.Operation.Event; + /** * @param {?} data * @return {undefined} @@ -55,7 +61,7 @@ ops.Operation.prototype.group; /** * @param {!ops.Document} document - * @return {!boolean} true if the operation was executed + * @return {?Array.} a list of events if the operation was executed, otherwise null */ ops.Operation.prototype.execute = function (document) {"use strict"; }; diff --git a/webodf/lib/ops/Session.js b/webodf/lib/ops/Session.js index 1685afffe..2fd5bb5e1 100644 --- a/webodf/lib/ops/Session.js +++ b/webodf/lib/ops/Session.js @@ -46,7 +46,7 @@ ops.Session = function Session(odfCanvas) { * @return {undefined} */ function forwardBatchStart(args) { - odtDocument.emit(ops.OdtDocument.signalProcessingBatchStart, args); + odtDocument.prepareBatchProcessing(args); } /** @@ -55,7 +55,7 @@ ops.Session = function Session(odfCanvas) { * @return {undefined} */ function forwardBatchEnd(args) { - odtDocument.emit(ops.OdtDocument.signalProcessingBatchEnd, args); + odtDocument.finishBatchProcessing(args); } /** @@ -81,12 +81,7 @@ ops.Session = function Session(odfCanvas) { operationRouter.subscribe(ops.OperationRouter.signalProcessingBatchStart, forwardBatchStart); operationRouter.subscribe(ops.OperationRouter.signalProcessingBatchEnd, forwardBatchEnd); opRouter.setPlaybackFunction(function (op) { - odtDocument.emit(ops.OdtDocument.signalOperationStart, op); - if (op.execute(odtDocument)) { - odtDocument.emit(ops.OdtDocument.signalOperationEnd, op); - return true; - } - return false; + return odtDocument.executeOperation(op); }); opRouter.setOperationFactory(operationFactory); }; diff --git a/webodf/tests/gui/DirectFormattingControllerTests.js b/webodf/tests/gui/DirectFormattingControllerTests.js index be6e8c805..1a22b334c 100644 --- a/webodf/tests/gui/DirectFormattingControllerTests.js +++ b/webodf/tests/gui/DirectFormattingControllerTests.js @@ -140,7 +140,7 @@ gui.DirectFormattingControllerTests = function DirectFormattingControllerTests(r domUtils.getElementsByTagNameNS(node, testns, '*').forEach(function(node) { node.parentNode.removeChild(node); }); - t.odtDocument.emit(ops.Document.signalCursorMoved, t.cursor); + t.odtDocument.DONOTUSE_emitSignalCursorMoved(t.cursor); } return node; } diff --git a/webodf/tests/gui/MetadataControllerTests.js b/webodf/tests/gui/MetadataControllerTests.js index dce0b07f6..dd97f1bbd 100644 --- a/webodf/tests/gui/MetadataControllerTests.js +++ b/webodf/tests/gui/MetadataControllerTests.js @@ -84,10 +84,8 @@ gui.MetadataControllerTests = function MetadataControllerTests(runner) { // need to set the timestamp, otherwise things fail in odtDocument opspec.timestamp = Date.now(); - timedOp = operationFactory.create(opspec); - if (timedOp.execute(odtDocument)) { - odtDocument.emit(ops.OdtDocument.signalOperationEnd, timedOp); - } + timedOp = /**@type {!ops.Operation}*/(operationFactory.create(opspec)); + odtDocument.executeOperation(timedOp); }); }; @@ -123,7 +121,7 @@ gui.MetadataControllerTests = function MetadataControllerTests(runner) { }); changes.removedProperties.forEach(function (key) { delete changedMetadata.setProperties[key]; - if (changedMetadata.removedProperties.indexOf(key) !== -1) { + if (changedMetadata.removedProperties.indexOf(key) === -1) { changedMetadata.removedProperties.push(key); } }); diff --git a/webodf/tests/manifest.json b/webodf/tests/manifest.json index cac860cd1..de0b3babb 100644 --- a/webodf/tests/manifest.json +++ b/webodf/tests/manifest.json @@ -49,7 +49,6 @@ "odf.ObjectNameGenerator", "odf.OdfCanvas", "odf.OdfContainer", - "ops.Document", "ops.OdtCursor", "ops.OdtDocument", "ops.Session" @@ -230,6 +229,7 @@ "ops.Document", "ops.Member", "ops.OdtDocument", + "ops.Operation", "ops.OperationFactory", "ops.OperationTestHelper", "xmldom.LSSerializer" diff --git a/webodf/tests/ops/OdtDocumentTests.js b/webodf/tests/ops/OdtDocumentTests.js index 5182b2189..3851ace4b 100644 --- a/webodf/tests/ops/OdtDocumentTests.js +++ b/webodf/tests/ops/OdtDocumentTests.js @@ -216,7 +216,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { setCursorPosition(1, 2); wrapInDiv(t.cursor.getAnchorNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; @@ -234,7 +234,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { setCursorPosition(1, 2); wrapInDiv(t.cursor.getNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; @@ -253,7 +253,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { wrapInDiv(t.cursor.getNode()); wrapInDiv(t.cursor.getAnchorNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; @@ -272,7 +272,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { wrapInDiv(t.cursor.getNode()); wrapInDiv(t.cursor.getAnchorNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; @@ -291,7 +291,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { wrapInDiv(t.cursor.getNode()); wrapInDiv(t.cursor.getAnchorNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; @@ -312,7 +312,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { wrapInDiv(t.cursor.getNode()); wrapInDiv(t.cursor.getAnchorNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; @@ -333,7 +333,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { wrapInDiv(t.cursor.getNode()); wrapInDiv(t.cursor.getAnchorNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; @@ -353,7 +353,7 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) { setCursorPosition(1); wrapInDiv(t.cursor.getNode()); - t.odtDocument.fixCursorPositions(); + t.odtDocument.fixCursorPositions(false); t.isWalkable = isCursorSelectionInWalkablePositions(); t.anchorInDiv = t.cursor.getAnchorNode().parentNode.localName === "div"; diff --git a/webodf/tests/ops/OperationTests.js b/webodf/tests/ops/OperationTests.js index 3ec12fe1b..b8d00e594 100644 --- a/webodf/tests/ops/OperationTests.js +++ b/webodf/tests/ops/OperationTests.js @@ -177,7 +177,8 @@ ops.OperationTests = function OperationTests(runner) { opsElement = before.nextElementSibling, after = opsElement.nextElementSibling, ops = [], - op, + opElement, opspec, + now = Date.now(), setup; runtime.assert(before.localName === "before", "Expected in " + name + "."); runtime.assert(checkWhitespace(before, "s", " "), "Unexpanded text:s element or text:c attribute found in " + name + "."); @@ -187,11 +188,20 @@ ops.OperationTests = function OperationTests(runner) { runtime.assert(checkWhitespace(after, "s", " "), "Unexpanded text:s element or text:c attribute found in " + name + "."); runtime.assert(checkWhitespace(after, "tab", "\t"), "Unexpanded text:tab element found in " + name + "."); opsTestHelper.removeInsignificantTextNodes(node); - op = opsElement.firstElementChild; - while (op) { - runtime.assert(op.localName === "op", "Expected in " + name + "."); - ops.push(parseOperation(op)); - op = op.nextElementSibling; + opElement = opsElement.firstElementChild; + while (opElement) { + runtime.assert(opElement.localName === "op", "Expected in " + name + "."); + opspec = parseOperation(opElement); + // default to Alice + if (!opspec.memberid) { + opspec.memberid = 'Alice'; + } + // default to now + if (!opspec.timestamp) { + opspec.timestamp = now; + } + ops.push(opspec); + opElement = opElement.nextElementSibling; } setup = self.setUps.hasOwnProperty(name) ? self.setUps[name]() : null; if (hasSetup) { @@ -288,11 +298,8 @@ ops.OperationTests = function OperationTests(runner) { // execute test ops for (i = 0; i < test.ops.length; i += 1) { - op = factory.create(test.ops[i]); - op.execute(t.odtDocument); - if (metabefore) { - t.odtDocument.emit(ops.OdtDocument.signalOperationEnd, op); - } + op = /**@type {!ops.Operation}*/(factory.create(test.ops[i])); + t.odtDocument.executeOperation(op); checkForEmptyTextNodes(t.odtDocument.getCanvas().getElement()); } @@ -403,18 +410,20 @@ ops.OperationTests = function OperationTests(runner) { } this.setUp = function () { - var testarea, properties; + var testarea; t = {}; testarea = core.UnitTest.provideTestAreaDiv(); t.odfcanvas = new odf.OdfCanvas(testarea); t.odfContainer = new odf.OdfContainer(odf.OdfContainer.DocumentType.TEXT, null); t.odfcanvas.setOdfContainer(t.odfContainer); t.odtDocument = new ops.OdtDocument(t.odfcanvas); - properties = new ops.MemberProperties(); - properties.color = "black"; - properties.fullName = "Alice"; - properties.imageUrl = ""; - t.odtDocument.addMember(new ops.Member('Alice', properties)); + ["Alice", "Bob", "Eve", "Joe"].forEach(function(name) { + var properties = new ops.MemberProperties(); + properties.color = "black"; + properties.fullName = name; + properties.imageUrl = ""; + t.odtDocument.addMember(new ops.Member(name, properties)); + }); }; this.tearDown = function () { t.odfcanvas.destroy(function () { return; }); diff --git a/webodf/tests/ops/TransformationTests.js b/webodf/tests/ops/TransformationTests.js index 6fdb1fa93..b1aac0591 100644 --- a/webodf/tests/ops/TransformationTests.js +++ b/webodf/tests/ops/TransformationTests.js @@ -458,13 +458,13 @@ ops.TransformationTests = function TransformationTests(runner) { // runtime.log("Going to apply:"+runtime.toJson(opspecs[i])); op = t.operationFactory.create(opspecs[i]); t.opResult = op.execute(odtDocument); - r.shouldBe(t, "t.opResult", "true"); + r.shouldBeNonNull(t, "t.opResult"); } // execute transformedOps for (i = 0; i < transformedOps.length; i += 1) { // runtime.log("Going to apply:"+runtime.toJson(transformedOps[i].spec())); t.opResult = transformedOps[i].execute(odtDocument); - r.shouldBe(t, "t.opResult", "true"); + r.shouldBeNonNull(t, "t.opResult"); } // check result