First take on proper destruction of WebODF Editor instance
This commit is contained in:
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)
|
||||
}
|
||||
|
934
js/webodf.js
934
js/webodf.js
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user