UNPKG

node-webodf

Version:

WebODF - JavaScript Document Engine http://webodf.org/

279 lines (243 loc) 9.94 kB
/** * Copyright (C) 2014 KO GmbH <copyright@kogmbh.com> * * @licstart * This file is part of WebODF. * * WebODF is free software: you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License (GNU AGPL) * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * WebODF is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with WebODF. If not, see <http://www.gnu.org/licenses/>. * @licend * * @source: http://www.webodf.org/ * @source: https://github.com/kogmbh/WebODF/ */ /*global require, document, window, history, runtime, Wodo, alert*/ function createEditor() { "use strict"; var editor = null, serverFactory = null, server = null, editorOptions = { allFeaturesEnabled: true, collabEditingEnabled: true }, currentPageId = null, savingOverlay, disconnectedOverlay, hasLocalUnsyncedOpsOverlay, sessionList, userId, token, currentSessionId, currentMemberId; // TODO: just some quick hack done for testing, make nice (e.g. the position calculation is fragile) function addStatusOverlay(parentElement, symbolFileName, position) { var htmlns = document.documentElement.namespaceURI, imageElement, overlay; runtime.assert(parentElement, "heya, no such parentelement"); overlay = document.createElementNS(htmlns, "div"); imageElement = document.createElementNS(htmlns, "img"); imageElement.src = symbolFileName; overlay.appendChild(imageElement); overlay.style.position = "absolute"; overlay.style.top = 24 * position + "px"; overlay.style.opacity = "0.8"; overlay.style.display = "none"; parentElement.appendChild(overlay); return overlay; } /** * Switches the pages by hiding the old one and unhiding the new * @param {!string} pageId * @return {undefined} */ function switchToPage(pageId) { if (currentPageId) { document.getElementById(currentPageId).style.display = "none"; } currentPageId = pageId; document.getElementById(pageId).style.display = ""; } /** * @param {!string} * @return {undefined} */ function updateLocationWithSessionId(sessionId) { var location = String(document.location), pos = location.indexOf('#'); if (pos !== -1) { location = location.substr(0, pos); } if (sessionId) { location = location + '#' + sessionId; } history.replaceState( {}, "", location); } /*jslint emptyblock: true*/ /** * @return {undefined} */ function onEditingStarted() { // nothing to do right now } /*jslint emptyblock: false*/ /** * @return {undefined} */ function showSessions() { switchToPage("sessionListContainer"); sessionList.setUpdatesEnabled(true); updateLocationWithSessionId(""); } /** * @param {!boolean=} ignoreError * @return {undefined} */ function closeEditing(ignoreError) { editor.leaveSession(function () { server.leaveSession(currentSessionId, currentMemberId, function () { showSessions(); }, function () { if (ignoreError) { showSessions(); } // TODO: else report problem }); }); } /** * @return {undefined} */ function handleEditingError(error) { alert("Something went wrong:\n" + error); closeEditing(true); } /** * @param {!string} sessionId * @return {undefined} */ function joinSession(sessionId) { switchToPage("editorContainer"); sessionList.setUpdatesEnabled(false); updateLocationWithSessionId(sessionId); currentSessionId = sessionId; server.joinSession(userId, sessionId, function (memberId) { currentMemberId = memberId; if (!editor) { editorOptions.networkSecurityToken = token; editorOptions.closeCallback = closeEditing; Wodo.createCollabTextEditor('editorContainer', editorOptions, function (err, e) { var canvasContainerElement; if (err) { runtime.log(err); return; } editor = e; canvasContainerElement = editor.getCanvasContainerElement(); savingOverlay = addStatusOverlay(canvasContainerElement, "document-save.png", 0); hasLocalUnsyncedOpsOverlay = addStatusOverlay(canvasContainerElement, "vcs-locally-modified.png", 0); disconnectedOverlay = addStatusOverlay(canvasContainerElement, "network-disconnect.png", 1); editor.addEventListener(Wodo.EVENT_BEFORESAVETOFILE, function () { savingOverlay.style.display = ""; }); editor.addEventListener(Wodo.EVENT_SAVEDTOFILE, function () { savingOverlay.style.display = "none"; }); editor.addEventListener(Wodo.EVENT_HASLOCALUNSYNCEDOPERATIONSCHANGED, function (has) { hasLocalUnsyncedOpsOverlay.style.display = has ? "" : "none"; }); editor.addEventListener(Wodo.EVENT_HASSESSIONHOSTCONNECTIONCHANGED, function (has) { disconnectedOverlay.style.display = has ? "none" : ""; }); editor.addEventListener(Wodo.EVENT_UNKNOWNERROR, handleEditingError); // load the document and get called back when it's live editor.joinSession(serverFactory.createSessionBackend(sessionId, memberId, server), onEditingStarted); }); } else { editor.joinSession(serverFactory.createSessionBackend(sessionId, memberId, server), onEditingStarted); } }, function(err) { // TODO: handle error runtime.log(err); }); } /** * extract session id from the url-fragment * * @return {?string} */ function extractSessionId() { var sessionId = String(document.location), pos = sessionId.indexOf('#'); return (pos !== -1) ? sessionId.substr(pos + 1) : null; } /** * start the login process by offering a login/password prompt. * on success a list of sessions is offered. * * @return {undefined} */ function startLoginProcess() { runtime.assert(editor === null, "cannot boot with instantiated editor"); function loginSuccess(userData) { require(["webodf/editor/SessionListView"], function (SessionListView) { var sessionListDiv = document.getElementById("sessionList"), sessionId = extractSessionId(), sessionListView; runtime.log("connected:" + userData.full_name); userId = userData.uid; token = userData.securityToken || null; // add session listing sessionList = new serverFactory.createSessionList(server); sessionListView = new SessionListView(sessionList, sessionListDiv, joinSession); if (sessionId) { // TODO: check if session exists joinSession(sessionId); } else { switchToPage("sessionListContainer"); } // only done to make jslint see the var used return sessionListView; } ); } function loginFail(result) { alert("Login failed: " + result); } /** * @return {!boolean} */ function onLoginSubmit() { server.login(document.loginForm.login.value, document.loginForm.password.value, loginSuccess, loginFail); // block the submit button, we already dealt with the input return false; } // bring up the login form document.loginForm.Submit.onclick = onLoginSubmit; switchToPage("loginContainer"); document.loginForm.login.focus(); } // start the editor with network runtime.log("starting collaborative editor for [pullbox]."); require(["webodf/editor/backend/pullbox/ServerFactory"], function (ServerFactory) { serverFactory = new ServerFactory(); server = serverFactory.createServer(); // wait for a network connection to establish. // call the callback when done, when finally failed, or // when a timeout reached. // the parameter to the callback is a string with the possible // values: "unavailable", "timeout", "ready" server.connect(8000, function (state) { if (state === "ready") { startLoginProcess(); } }); }); }