First take on proper destruction of WebODF Editor instance

pull/1/head
Friedrich W. H. Kossebau 11 years ago
parent 9c0a0c854a
commit 8527506d90

@ -1,5 +1,3 @@
@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0);
html, body, #mainContainer {
width: 100%;
height: 100%;
@ -25,12 +23,6 @@ html, body, #mainContainer {
z-index: 4;
}
#menubar {
border: none;
overflow: hidden;
background-color: #E6E6E7;
}
#toolbar {
overflow: hidden;
}
@ -169,28 +161,6 @@ div.memberListLabel[fullname]:before {
opacity: 0.9;
}
#chat {
padding: 0px;
text-align: center;
position: relative;
}
#chat > #inputArea {
padding-top: 3px;
padding-bottom: 3px;
width: 100%;
background-color: #eee;
position: absolute;
bottom: 0px;
}
#inputArea > #widget_chatInput {
width: 95%;
border-radius: 10px;
padding: 3px;
box-shadow: inset 0 0 1px #888;
}
.dijitDialog {
border: none !important;
box-shadow: 0 1px 50px rgba(0, 0, 0, 0.25) !important;

@ -79,7 +79,7 @@ var documentsMain = {
documentsMain.webodfEditorInstance = new Editor({}, documentsMain.webodfServerInstance, serverFactory);
// load the document and get called back when it's live
documentsMain.webodfEditorInstance.loadSession(response.es_id, memberId, function() {
documentsMain.webodfEditorInstance.openSession(response.es_id, memberId, function() {
documentsMain.webodfEditorInstance.startEditing();
});
});
@ -150,21 +150,23 @@ var documentsMain = {
//close editor
documentsMain.webodfEditorInstance.endEditing();
documentsMain.webodfEditorInstance.closeDocument(function() {
documentsMain.webodfEditorInstance.close(function() {
// successfull shutdown - all is good.
// TODO: proper session leaving call to server, either by webodfServerInstance or custom
// documentsMain.webodfServerInstance.leaveSession(sessionId, memberId, function() {
documentsMain.webodfEditorInstance.destroy(function() {
// Fade out odf-toolbar
$('#odf-toolbar').fadeOut('slow');
// Fade out editor
$('#mainContainer').fadeOut('slow', function() {
$('#mainContainer').remove();
$('#odf-canvas').remove();
$('#odf-toolbar').remove();
$('.actions,#file_access_panel').fadeIn('slow');
$('.documentslist, #emptyfolder').fadeIn('slow');
$(document.body).removeClass('claro');
});
});
// });
});
},

@ -1,4 +1,5 @@
/**
* @license
* Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
*
* @licstart
@ -31,6 +32,7 @@
* @source: http://www.webodf.org/
* @source: http://gitorious.org/webodf/webodf/
*/
/*global runtime, define, document, odf, ops, window, gui, alert, saveAs, Blob */
define("webodf/editor/Editor", [
@ -66,6 +68,7 @@ define("webodf/editor/Editor", [
// Private
session,
editorSession,
mainContainer,
memberListView,
toolbarTools,
loadOdtFile = args.loadCallback,
@ -112,7 +115,7 @@ define("webodf/editor/Editor", [
/**
* create the editor, load the starting document,
* open the document,
* call editorReadyCallback once everything is done.
*
* @param {!string} docUrl
@ -120,7 +123,7 @@ define("webodf/editor/Editor", [
* @param {!function()} editorReadyCallback
* @return {undefined}
*/
this.loadDocument = function (docUrl, memberId, editorReadyCallback) {
this.openDocument = function (docUrl, memberId, editorReadyCallback) {
initDocLoading(docUrl, memberId, editorReadyCallback);
};
@ -151,8 +154,8 @@ define("webodf/editor/Editor", [
};
/**
* create the editor, load the starting document of an
* editing-session, request a replay of previous operations, call
* open the initial document of an editing-session,
* request a replay of previous operations, call
* editorReadyCallback once everything is done.
*
* @param {!string} sessionId
@ -160,7 +163,7 @@ define("webodf/editor/Editor", [
* @param {!function()} editorReadyCallback
* @return {undefined}
*/
this.loadSession = function (sessionId, memberId, editorReadyCallback) {
this.openSession = function (sessionId, memberId, editorReadyCallback) {
initDocLoading(server.getGenesisUrl(sessionId), memberId, function () {
var opRouter, memberModel;
// overwrite router and member model
@ -185,26 +188,27 @@ define("webodf/editor/Editor", [
* @param {!function(!Object=)} callback, passing an error object in case of error
* @return {undefined}
*/
this.closeDocument = function (callback) {
this.close = function (callback) {
runtime.assert(session, "session should exist here.");
if (memberListView) {
memberListView.setEditorSession(undefined);
}
// TODO: there is a better pattern for this instead of unrolling
session.getOperationRouter().close(function(err) {
editorSession.close(function(err) {
if (err) {
callback(err);
} else {
session.getMemberModel().close(function(err) {
session.close(function(err) {
if (err) {
callback(err);
} else {
editorSession.close(function(err) {
// now also destroy session, will not be reused for new document
if (memberListView) {
memberListView.setEditorSession(undefined);
}
editorSession.destroy(function(err) {
if (err) {
callback(err);
} else {
editorSession = undefined;
session.close(function(err) {
session.destroy(function(err) {
if (err) {
callback(err);
} else {
@ -245,10 +249,45 @@ define("webodf/editor/Editor", [
editorSession.sessionController.endEditing();
};
/**
* @param {!function(!Object=)} callback, passing an error object in case of error
* @return {undefined}
*/
this.destroy = function (callback) {
var destroyMemberListView = memberListView ? memberListView.destroy : function(cb) { cb(); };
// TODO: decide if some forced close should be done here instead of enforcing proper API usage
runtime.assert(!session, "session should not exist here.");
// TODO: investigate what else needs to be done
mainContainer.destroyRecursive(true);
destroyMemberListView(function(err) {
if (err) {
callback(err);
} else {
toolbarTools.destroy(function(err) {
if (err) {
callback(err);
} else {
odfCanvas.destroy(function(err) {
if (err) {
callback(err);
} else {
document.translator = null;
document.translateContent = null;
callback();
}
});
}
});
}
});
};
// init
function init() {
var mainContainer,
editorPane, memberListPane,
var editorPane, memberListPane,
inviteButton,
canvasElement = document.getElementById("canvas"),
memberListElement = document.getElementById('memberList'),
@ -317,11 +356,10 @@ define("webodf/editor/Editor", [
if (window.inviteButtonProxy) {
inviteButton = document.getElementById('inviteButton');
if (inviteButton) {
inviteButton.innerText = translator("inviteMembers");
inviteButton.style.display = "block";
inviteButton.onclick = window.inviteButtonProxy.clicked;
}
runtime.assert(inviteButton, 'missing "inviteButton" div in HTML');
inviteButton.innerText = translator("inviteMembers");
inviteButton.style.display = "block";
inviteButton.onclick = window.inviteButtonProxy.clicked;
}
toolbarTools = new ToolBarTools({

@ -32,7 +32,9 @@
* @source: http://www.webodf.org/
* @source: http://gitorious.org/webodf/webodf/
*/
/*global define, runtime, core, gui, ops, document */
define("webodf/editor/EditorSession", [
"dojo/text!resources/fonts/fonts.css"
], function (fontsCSS) { // fontsCSS is retrieved as a string, using dojo's text retrieval AMD plugin
@ -65,8 +67,10 @@ define("webodf/editor/EditorSession", [
currentParagraphNode = null,
currentNamedStyleName = null,
currentStyleName = null,
caretManager,
odtDocument = session.getOdtDocument(),
textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
fontStyles = document.createElement('style'),
formatting = odtDocument.getFormatting(),
styleHelper = new gui.StyleHelper(formatting),
eventNotifier = new core.EventNotifier([
@ -81,7 +85,8 @@ define("webodf/editor/EditorSession", [
this.sessionController = new gui.SessionController(session, localMemberId);
this.sessionView = new gui.SessionView(config.viewOptions, session, new gui.CaretManager(self.sessionController));
caretManager = new gui.CaretManager(self.sessionController);
this.sessionView = new gui.SessionView(config.viewOptions, session, caretManager);
this.availableFonts = [];
/*
@ -194,36 +199,34 @@ define("webodf/editor/EditorSession", [
checkParagraphStyleName();
}
// Custom signals, that make sense in the Editor context. We do not want to expose webodf's ops signals to random bits of the editor UI.
odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, function (cursor) {
function onCursorAdded(cursor) {
self.emit(EditorSession.signalMemberAdded, cursor.getMemberId());
trackCursor(cursor);
});
}
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, function (memberId) {
function onCursorRemoved(memberId) {
self.emit(EditorSession.signalMemberRemoved, memberId);
});
}
odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, function (cursor) {
function onCursorMoved(cursor) {
// Emit 'cursorMoved' only when *I* am moving the cursor, not the other users
if (cursor.getMemberId() === localMemberId) {
self.emit(EditorSession.signalCursorMoved, cursor);
trackCursor(cursor);
}
});
}
odtDocument.subscribe(ops.OdtDocument.signalStyleCreated, function (newStyleName) {
function onStyleCreated(newStyleName) {
self.emit(EditorSession.signalStyleCreated, newStyleName);
});
}
odtDocument.subscribe(ops.OdtDocument.signalStyleDeleted, function (styleName) {
function onStyleDeleted(styleName) {
self.emit(EditorSession.signalStyleDeleted, styleName);
});
}
odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, function (styleName) {
function onParagraphStyleModified(styleName) {
self.emit(EditorSession.signalParagraphStyleModified, styleName);
});
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, trackCurrentParagraph);
}
/**
* Call all subscribers for the given event with the specified argument
@ -527,24 +530,64 @@ define("webodf/editor/EditorSession", [
undoManager.moveForward(1);
};
this.subscribe(EditorSession.signalCursorMoved, trackCursor);
/**
* @param {!function(!Object=)} callback, passing an error object in case of error
* @return {undefined}
*/
this.close = function (callback) {
callback();
/*
self.sessionView.close(function(err) {
if (err) {
callback(err);
} else {
caretManager.close(function(err) {
if (err) {
callback(err);
} else {
self.sessionController.close(callback);
}
});
}
});
*/
};
/**
* @param {!function(!Object=)} callback, passing an error object in case of error
* @return {undefined}
*/
this.close = function(callback) {
self.sessionController.close(function(err) {
this.destroy = function(callback) {
var head = document.getElementsByTagName('head')[0];
head.removeChild(fontStyles);
odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
odtDocument.unsubscribe(ops.OdtDocument.signalStyleCreated, onStyleCreated);
odtDocument.unsubscribe(ops.OdtDocument.signalStyleDeleted, onStyleDeleted);
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, trackCurrentParagraph);
odtDocument.unsubscribe(ops.OdtDocument.signalUndoStackChanged, undoStackModified);
self.sessionView.destroy(function(err) {
if (err) {
callback(err);
} else {
delete self.sessionController;
self.sessionView.close(function(err) {
delete self.sessionView;
caretManager.destroy(function(err) {
if (err) {
callback(err);
} else {
delete self.sessionView;
callback();
self.sessionController.destroy(function(err) {
if (err) {
callback(err);
} else {
delete self.sessionController;
callback();
}
});
}
});
}
@ -552,12 +595,22 @@ define("webodf/editor/EditorSession", [
};
function init() {
var head = document.getElementsByTagName('head')[0],
fontStyles = document.createElement('style');
var head = document.getElementsByTagName('head')[0];
// TODO: fonts.css should be rather done by odfCanvas, or?
fontStyles.type = 'text/css';
fontStyles.media = 'screen, print, handheld, projection';
fontStyles.appendChild(document.createTextNode(fontsCSS));
head.appendChild(fontStyles);
// Custom signals, that make sense in the Editor context. We do not want to expose webodf's ops signals to random bits of the editor UI.
odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
odtDocument.subscribe(ops.OdtDocument.signalStyleCreated, onStyleCreated);
odtDocument.subscribe(ops.OdtDocument.signalStyleDeleted, onStyleDeleted);
odtDocument.subscribe(ops.OdtDocument.signalParagraphStyleModified, onParagraphStyleModified);
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, trackCurrentParagraph);
odtDocument.subscribe(ops.OdtDocument.signalUndoStackChanged, undoStackModified);
}

@ -152,17 +152,17 @@ define("webodf/editor/MemberListView",
function removeMember(memberId) {
editorSession.unsubscribeMemberDetailsUpdates(memberId, updateAvatarButton);
removeAvatarButton(memberId);
};
}
/**
* @param {!EditorSession} session
* @return {undefined}
*/
this.setEditorSession = function(session) {
var node = memberListDiv.firstChild, nextNode;
function disconnectFromEditorSession() {
var node, nextNode;
if (editorSession) {
// unsubscribe from editorSession
editorSession.unsubscribe(EditorSession.signalMemberAdded, addMember);
editorSession.unsubscribe(EditorSession.signalMemberRemoved, removeMember);
// remove all current avatars
node = memberListDiv.firstChild;
while (node) {
nextNode = node.nextSibling;
if (node.memberId) {
@ -171,15 +171,30 @@ define("webodf/editor/MemberListView",
memberListDiv.removeChild(node);
node = nextNode;
}
// unsubscribe from old editorSession
editorSession.unsubscribe(EditorSession.signalMemberAdded, addMember);
editorSession.unsubscribe(EditorSession.signalMemberRemoved, removeMember);
}
}
/**
* @param {!EditorSession} session
* @return {undefined}
*/
this.setEditorSession = function(session) {
disconnectFromEditorSession();
editorSession = session;
if (editorSession) {
editorSession.subscribe(EditorSession.signalMemberAdded, addMember);
editorSession.subscribe(EditorSession.signalMemberRemoved, removeMember);
}
};
/**
* @param {!function(!Object=)} callback, passing an error object in case of error
* @return {undefined}
*/
this.destroy = function (callback) {
disconnectFromEditorSession();
callback();
};
};
});

@ -49,9 +49,10 @@ ServerFactory.prototype.createServer = function () {"use strict"; };
* @param {!string} sessionId
* @param {!string} memberId
* @param {!ops.Server} server
* @param {!odf.OdfContainer} odfContainer TODO: needed for pullbox writing to server at end, find better solution
* @return {!ops.OperationRouter}
*/
ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server) {"use strict"; };
ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server, odfContainer) {"use strict"; };
/**
* @param {!string} sessionId

@ -81,6 +81,16 @@ define("webodf/editor/widgets", [
}
};
/**
* @param {!function(!Object=)} callback, passing an error object in case of error
* @return {undefined}
*/
this.destroy = function (callback) {
// TODO: investigate what else needs to be done
toolbar.destroyRecursive(true);
callback();
};
// init
ready(function () {
toolbar = new Toolbar({}, "toolbar");

@ -8479,7 +8479,11 @@ odf.OdfCanvas = function() {
updateCSS()
}
};
this.css = css
this.css = css;
this.destroy = function(callback) {
css.parentNode.removeChild(css);
callback()
}
}
function listenEvent(eventTarget, eventType, eventHandler) {
if(eventTarget.addEventListener) {
@ -8493,6 +8497,20 @@ odf.OdfCanvas = function() {
}
}
}
function removeEvent(eventTarget, eventType, eventHandler) {
var onVariant = "on" + eventType;
if(eventTarget.removeEventListener) {
eventTarget.removeEventListener(eventType, eventHandler, false)
}else {
if(eventTarget.detachEvent) {
eventTarget.detachEvent(onVariant, eventHandler)
}else {
if(eventTarget[onVariant] === eventHandler) {
eventTarget[onVariant] = null
}
}
}
}
function SelectionWatcher(element) {
var selection = [], listeners = [];
function isAncestorOf(ancestor, descendant) {
@ -8568,12 +8586,17 @@ odf.OdfCanvas = function() {
}
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, window = runtime.getWindow(), xpath = new xmldom.XPath, utils = new odf.OdfUtils, domUtils = new core.DomUtils, shadowContent, sizer, annotationsPane, allowAnnotations =
false, annotationManager;
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, window = runtime.getWindow(), xpath = new xmldom.XPath, utils = new odf.OdfUtils, domUtils = new core.DomUtils, shadowContent;
function clear(element) {
while(element.firstChild) {
element.removeChild(element.firstChild)
@ -8725,17 +8748,6 @@ odf.OdfCanvas = function() {
modifyTableCell(node)
}
}
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");
annotationManager.addAnnotation({node:annotationNodes[i], end:annotationEnds.filter(matchAnnotationEnd)[0] || null})
}
annotationManager.rerenderAnnotations()
}
function modifyLinks(odffragment) {
var i, links, node;
function modifyLink(node) {
@ -8984,12 +8996,7 @@ odf.OdfCanvas = function() {
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, fontcss, stylesxmlcss, positioncss, editable = false, zoomLevel = 1, eventHandlers = {}, editparagraph, loadingQueue = new LoadingQueue;
addWebODFStyleSheet(doc);
pageSwitcher = new PageSwitcher(addStyleSheet(doc));
fontcss = addStyleSheet(doc);
stylesxmlcss = addStyleSheet(doc);
positioncss = addStyleSheet(doc);
var self = this, doc = (element.ownerDocument), odfcontainer, formatting = new odf.Formatting, selectionWatcher = new SelectionWatcher(element), pageSwitcher, sizer, annotationsPane, allowAnnotations = false, annotationManager, webodfcss, fontcss, stylesxmlcss, positioncss, editable = false, zoomLevel = 1, eventHandlers = {}, editparagraph, loadingQueue = new LoadingQueue;
function loadImages(container, odffragment, stylesheet) {
var i, images, node;
function loadImage(name, container, node, stylesheet) {
@ -9084,6 +9091,17 @@ odf.OdfCanvas = function() {
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");
annotationManager.addAnnotation({node:annotationNodes[i], end:annotationEnds.filter(matchAnnotationEnd)[0] || null})
}
annotationManager.rerenderAnnotations()
}
function handleAnnotations(odfnode) {
if(allowAnnotations) {
if(!annotationsPane.parentNode) {
@ -9328,7 +9346,33 @@ odf.OdfCanvas = function() {
};
this.getElement = function() {
return element
};
this.destroy = function(callback) {
var head = doc.getElementsByTagName("head")[0];
if(annotationsPane.parentNode) {
annotationsPane.parentNode.removeChild(annotationsPane)
}
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
}();
@ -11916,6 +11960,10 @@ ops.EditInfo = function EditInfo(container, odtDocument) {
this.clearEdits = function() {
editHistory = {}
};
this.destroy = function(callback) {
container.removeChild(editInfoNode);
callback()
};
function init() {
var editInfons = "urn:webodf:names:editinfo", dom = odtDocument.getDOM();
editInfoNode = dom.createElementNS(editInfons, "editinfo");
@ -11951,6 +11999,10 @@ gui.Avatar = function Avatar(parentElement, avatarInitiallyVisible) {
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");
@ -12056,6 +12108,16 @@ gui.Caret = function Caret(cursor, avatarInitiallyVisible, blinkOnRangeSelect) {
}
}
};
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");
@ -12925,7 +12987,7 @@ gui.SessionController = function() {
this.getUndoManager = function() {
return undoManager
};
this.close = function(callback) {
this.destroy = function(callback) {
callback()
};
function init() {
@ -13230,6 +13292,10 @@ gui.EditInfoHandle = function EditInfoHandle(parentElement) {
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");
@ -13238,6 +13304,40 @@ gui.EditInfoHandle = function EditInfoHandle(parentElement) {
}
init()
};
/*
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
and/or modify it under the terms of the GNU Affero General Public License
(GNU AGPL) as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. The code is distributed
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
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: http://gitorious.org/webodf/webodf/
*/
runtime.loadClass("ops.EditInfo");
runtime.loadClass("gui.EditInfoHandle");
gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
@ -13303,6 +13403,16 @@ gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
this.hideHandle = function() {
handle.hide()
};
this.destroy = function(callback) {
editInfoNode.removeChild(marker);
handle.destroy(function(err) {
if(err) {
callback(err)
}else {
editInfo.destroy(callback)
}
})
};
function init() {
var dom = editInfo.getOdtDocument().getDOM(), htmlns = dom.documentElement.namespaceURI;
marker = dom.createElementNS(htmlns, "div");
@ -13504,16 +13614,39 @@ gui.SessionView = function() {
session.getMemberModel().unsubscribeMemberDetailsUpdates(memberid, renderMemberData)
}
}
this.close = function(callback) {
callback()
function onParagraphChanged(info) {
highlightEdit(info.paragraphElement, info.memberId, info.timeStamp)
}
this.destroy = function(callback) {
var odtDocument = session.getOdtDocument(), memberModel = session.getMemberModel(), editInfoArray = Object.keys(editInfoMap).map(function(keyname) {
return editInfoMap[keyname]
});
odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
caretManager.getCarets().forEach(function(caret) {
memberModel.unsubscribeMemberDetailsUpdates(caret.getCursor().getMemberId(), renderMemberData)
});
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.signalCursorAdded, onCursorAdded);
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, function(info) {
highlightEdit(info.paragraphElement, info.memberId, info.timeStamp)
});
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, onParagraphChanged);
avatarInfoStyles = document.createElementNS(head.namespaceURI, "style");
avatarInfoStyles.type = "text/css";
avatarInfoStyles.media = "screen, print, handheld, projection";
@ -13565,6 +13698,11 @@ gui.CaretManager = function CaretManager(sessionController) {
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()
}
@ -13616,13 +13754,30 @@ gui.CaretManager = function CaretManager(sessionController) {
return caret
};
this.getCaret = getCaret;
this.getCarets = function() {
return Object.keys(carets).map(function(memberid) {
return carets[memberid]
})
this.getCarets = getCarets;
this.destroy = function(callback) {
var odtDocument = sessionController.getSession().getOdtDocument(), canvasElement = getCanvasElement(), caretArray = getCarets();
odtDocument.unsubscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
canvasElement.onfocus = null;
canvasElement.onblur = null;
(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)
};
function init() {
var session = sessionController.getSession(), odtDocument = session.getOdtDocument(), canvasElement = getCanvasElement();
var odtDocument = sessionController.getSession().getOdtDocument(), canvasElement = getCanvasElement();
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
@ -14763,6 +14918,9 @@ ops.OdtDocument = function OdtDocument(odfCanvas) {
this.close = function(callback) {
callback()
};
this.destroy = function(callback) {
callback()
};
function init() {
filter = new TextPositionFilter;
odfUtils = new odf.OdfUtils
@ -14839,9 +14997,6 @@ ops.Session = function Session(odfCanvas) {
});
opRouter.setOperationFactory(operationFactory)
};
this.getOperationRouter = function() {
return operationRouter
};
this.getMemberModel = function() {
return memberModel
};
@ -14855,14 +15010,23 @@ ops.Session = function Session(odfCanvas) {
operationRouter.push(operation)
};
this.close = function(callback) {
odtDocument.close(function(err) {
operationRouter.close(function(err) {
if(err) {
callback(err)
}else {
callback()
memberModel.close(function(err) {
if(err) {
callback(err)
}else {
odtDocument.close(callback)
}
})
}
})
};
this.destroy = function(callback) {
odtDocument.destroy(callback)
};
function init() {
self.setOperationRouter(new ops.TrivialOperationRouter)
}

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save