123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- /**
- * 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 window, document, alert, navigator, require, dojo, runtime, core, gui, ops, odf, WodoFromSource*/
- /**
- * Namespace of the Wodo.TextEditor
- * @namespace
- * @name Wodo
- */
- window.Wodo = window.Wodo || (function () {
- "use strict";
- function getInstallationPath() {
- /**
- * Sees to get the url of this script on top of the stack trace.
- * @param {!string|undefined} stack
- * @return {!string|undefined}
- */
- function getScriptUrlFromStack(stack) {
- var url, matches;
- if (typeof stack === "string" && stack) {
- /*jslint regexp: true*/
- matches = stack.match(/((?:http[s]?|file):\/\/[\/]?.+?\/[^:\)]*?)(?::\d+)(?::\d+)?/);
- /*jslint regexp: false*/
- url = matches && matches[1];
- }
- if (typeof url === "string" && url) {
- return url;
- }
- return undefined;
- }
- /**
- * Tries by various tricks to get the url of this script.
- * To be called if document.currentScript is not supported
- * @return {!string|undefined}
- */
- function getCurrentScriptElementSrcByTricks() {
- var scriptElements = document.getElementsByTagName("script");
- // if there is only one script, it must be this
- if (scriptElements.length === 1) {
- return scriptElements[0].src;
- }
- // otherwise get it from the stacktrace
- try {
- throw new Error();
- } catch (err) {
- return getScriptUrlFromStack(err.stack);
- }
- }
- var path = ".", scriptElementSrc,
- a, pathname, pos;
- if (document.currentScript && document.currentScript.src) {
- scriptElementSrc = document.currentScript.src;
- } else {
- scriptElementSrc = getCurrentScriptElementSrcByTricks();
- }
- if (scriptElementSrc) {
- a = document.createElement('a');
- a.href = scriptElementSrc;
- pathname = a.pathname;
- if (pathname.charAt(0) !== "/") {
- // Various versions of Internet Explorer seems to neglect the leading slash under some conditions
- // (not when watching it with the dev tools of course!). This was confirmed in IE10 + IE11
- pathname = "/" + pathname;
- }
- pos = pathname.lastIndexOf("/");
- if (pos !== -1) {
- path = pathname.substr(0, pos);
- }
- } else {
- alert("Could not estimate installation path of the Wodo.TextEditor.");
- }
- return path;
- }
- var /** @inner @const
- @type{!string} */
- installationPath = getInstallationPath(),
- /** @inner @type{!boolean} */
- isInitalized = false,
- /** @inner @type{!Array.<!function():undefined>} */
- pendingInstanceCreationCalls = [],
- /** @inner @type{!number} */
- instanceCounter = 0,
- // TODO: avatar image url needs base-url setting.
- // so far Wodo itself does not have a setup call,
- // but then the avatar is also not used yet here
- defaultUserData = {
- fullName: "",
- color: "black",
- imageUrl: "avatar-joe.png"
- },
- /** @inner @const
- @type{!Array.<!string>} */
- userDataFieldNames = ["fullName", "color", "imageUrl"],
- /** @inner @const
- @type{!string} */
- memberId = "localuser",
- // constructors
- BorderContainer, ContentPane, FullWindowZoomHelper, EditorSession, Tools,
- /** @inner @const
- @type{!string} */
- MODUS_FULLEDITING = "fullediting",
- /** @inner @const
- @type{!string} */
- MODUS_REVIEW = "review",
- /** @inner @const
- @type{!string} */
- EVENT_UNKNOWNERROR = "unknownError",
- /** @inner @const
- @type {!string} */
- EVENT_DOCUMENTMODIFIEDCHANGED = "documentModifiedChanged",
- /** @inner @const
- @type {!string} */
- EVENT_METADATACHANGED = "metadataChanged";
- window.dojoConfig = (function () {
- var WebODFEditorDojoLocale = "C";
- if (navigator && navigator.language && navigator.language.match(/^(de)/)) {
- WebODFEditorDojoLocale = navigator.language.substr(0, 2);
- }
- return {
- locale: WebODFEditorDojoLocale,
- paths: {
- "webodf/editor": installationPath,
- "dijit": installationPath + "/dijit",
- "dojox": installationPath + "/dojox",
- "dojo": installationPath + "/dojo",
- "resources": installationPath + "/resources"
- }
- };
- }());
- /**
- * @return {undefined}
- */
- function initTextEditor() {
- require([
- "dijit/layout/BorderContainer",
- "dijit/layout/ContentPane",
- "webodf/editor/FullWindowZoomHelper",
- "webodf/editor/EditorSession",
- "webodf/editor/Tools",
- "webodf/editor/Translator"],
- function (BC, CP, FWZH, ES, T, Translator) {
- var locale = navigator.language || "en-US",
- editorBase = dojo.config && dojo.config.paths && dojo.config.paths["webodf/editor"],
- translationsDir = editorBase + '/translations',
- t;
- BorderContainer = BC;
- ContentPane = CP;
- FullWindowZoomHelper = FWZH;
- EditorSession = ES;
- Tools = T;
- // TODO: locale cannot be set by the user, also different for different editors
- t = new Translator(translationsDir, locale, function (editorTranslator) {
- runtime.setTranslator(editorTranslator.translate);
- // Extend runtime with a convenient translation function
- runtime.translateContent = function (node) {
- var i,
- element,
- tag,
- placeholder,
- translatable = node.querySelectorAll("*[text-i18n]");
- for (i = 0; i < translatable.length; i += 1) {
- element = translatable[i];
- tag = element.localName;
- placeholder = element.getAttribute('text-i18n');
- if (tag === "label"
- || tag === "span"
- || /h\d/i.test(tag)) {
- element.textContent = runtime.tr(placeholder);
- }
- }
- };
- defaultUserData.fullName = runtime.tr("Unknown Author");
- isInitalized = true;
- pendingInstanceCreationCalls.forEach(function (create) { create(); });
- });
- // only done to make jslint see the var used
- return t;
- }
- );
- }
- /**
- * Creates a new record with userdata, and for all official fields
- * copies over the value from the original or, if not present there,
- * sets it to the default value.
- * @param {?Object.<!string,!string>|undefined} original, defaults to {}
- * @return {!Object.<!string,!string>}
- */
- function cloneUserData(original) {
- var result = {};
- if (!original) {
- original = {};
- }
- userDataFieldNames.forEach(function (fieldName) {
- result[fieldName] = original[fieldName] || defaultUserData[fieldName];
- });
- return result;
- }
- /**
- * @name TextEditor
- * @constructor
- * @param {!string} mainContainerElementId
- * @param {!Object.<!string,!*>} editorOptions
- */
- function TextEditor(mainContainerElementId, editorOptions) {
- instanceCounter = instanceCounter + 1;
- /**
- * Returns true if either all features are wanted and this one is not explicitely disabled
- * or if not all features are wanted by default and it is explicitely enabled
- * @param {?boolean|undefined} isFeatureEnabled explicit flag which enables a feature
- * @return {!boolean}
- */
- function isEnabled(isFeatureEnabled) {
- return editorOptions.allFeaturesEnabled ? (isFeatureEnabled !== false) : isFeatureEnabled;
- }
- var userData,
- //
- mainContainerElement = document.getElementById(mainContainerElementId),
- canvasElement,
- canvasContainerElement,
- toolbarElement,
- toolbarContainerElement, // needed because dijit toolbar overwrites direct classList
- editorElement,
- /** @inner @const
- @type{!string} */
- canvasElementId = "webodfeditor-canvas" + instanceCounter,
- /** @inner @const
- @type{!string} */
- canvasContainerElementId = "webodfeditor-canvascontainer" + instanceCounter,
- /** @inner @const
- @type{!string} */
- toolbarElementId = "webodfeditor-toolbar" + instanceCounter,
- /** @inner @const
- @type{!string} */
- editorElementId = "webodfeditor-editor" + instanceCounter,
- //
- fullWindowZoomHelper,
- //
- mainContainer,
- tools,
- odfCanvas,
- //
- editorSession,
- session,
- //
- loadOdtFile = editorOptions.loadCallback,
- saveOdtFile = editorOptions.saveCallback,
- saveAsOdtFile = editorOptions.saveAsCallback,
- downloadOdtFile = editorOptions.downloadCallback,
- close = editorOptions.closeCallback,
- //
- reviewModeEnabled = (editorOptions.modus === MODUS_REVIEW),
- directTextStylingEnabled = isEnabled(editorOptions.directTextStylingEnabled),
- directParagraphStylingEnabled = isEnabled(editorOptions.directParagraphStylingEnabled),
- paragraphStyleSelectingEnabled = (!reviewModeEnabled) && isEnabled(editorOptions.paragraphStyleSelectingEnabled),
- paragraphStyleEditingEnabled = (!reviewModeEnabled) && isEnabled(editorOptions.paragraphStyleEditingEnabled),
- imageEditingEnabled = (!reviewModeEnabled) && isEnabled(editorOptions.imageEditingEnabled),
- hyperlinkEditingEnabled = isEnabled(editorOptions.hyperlinkEditingEnabled),
- annotationsEnabled = reviewModeEnabled || isEnabled(editorOptions.annotationsEnabled),
- undoRedoEnabled = isEnabled(editorOptions.undoRedoEnabled),
- zoomingEnabled = isEnabled(editorOptions.zoomingEnabled),
- //
- pendingMemberId,
- pendingEditorReadyCallback,
- //
- eventNotifier = new core.EventNotifier([
- EVENT_UNKNOWNERROR,
- EVENT_DOCUMENTMODIFIEDCHANGED,
- EVENT_METADATACHANGED
- ]);
- runtime.assert(Boolean(mainContainerElement), "No id of an existing element passed to Wodo.createTextEditor(): " + mainContainerElementId);
- /**
- * @param {!Object} changes
- * @return {undefined}
- */
- function relayMetadataSignal(changes) {
- eventNotifier.emit(EVENT_METADATACHANGED, changes);
- }
- /**
- * @param {!Object} changes
- * @return {undefined}
- */
- function relayModifiedSignal(modified) {
- eventNotifier.emit(EVENT_DOCUMENTMODIFIEDCHANGED, modified);
- }
- /**
- * @return {undefined}
- */
- function createSession() {
- var viewOptions = {
- editInfoMarkersInitiallyVisible: false,
- caretAvatarsInitiallyVisible: false,
- caretBlinksOnRangeSelect: true
- };
- // create session around loaded document
- session = new ops.Session(odfCanvas);
- editorSession = new EditorSession(session, pendingMemberId, {
- viewOptions: viewOptions,
- directTextStylingEnabled: directTextStylingEnabled,
- directParagraphStylingEnabled: directParagraphStylingEnabled,
- paragraphStyleSelectingEnabled: paragraphStyleSelectingEnabled,
- paragraphStyleEditingEnabled: paragraphStyleEditingEnabled,
- imageEditingEnabled: imageEditingEnabled,
- hyperlinkEditingEnabled: hyperlinkEditingEnabled,
- annotationsEnabled: annotationsEnabled,
- zoomingEnabled: zoomingEnabled,
- reviewModeEnabled: reviewModeEnabled
- });
- if (undoRedoEnabled) {
- editorSession.sessionController.setUndoManager(new gui.TrivialUndoManager());
- editorSession.sessionController.getUndoManager().subscribe(gui.UndoManager.signalDocumentModifiedChanged, relayModifiedSignal);
- }
- // Relay any metadata changes to the Editor's consumer as an event
- editorSession.sessionController.getMetadataController().subscribe(gui.MetadataController.signalMetadataChanged, relayMetadataSignal);
- // and report back to caller
- pendingEditorReadyCallback();
- // reset
- pendingEditorReadyCallback = null;
- pendingMemberId = null;
- }
- /**
- * @return {undefined}
- */
- function startEditing() {
- runtime.assert(editorSession, "editorSession should exist here.");
- tools.setEditorSession(editorSession);
- editorSession.sessionController.insertLocalCursor();
- editorSession.sessionController.startEditing();
- }
- /**
- * @return {undefined}
- */
- function endEditing() {
- runtime.assert(editorSession, "editorSession should exist here.");
- tools.setEditorSession(undefined);
- editorSession.sessionController.endEditing();
- editorSession.sessionController.removeLocalCursor();
- }
- /**
- * Loads an ODT document into the editor.
- * @name TextEditor#openDocumentFromUrl
- * @function
- * @param {!string} docUrl url from which the ODT document can be loaded
- * @param {!function(!Error=):undefined} callback Called once the document has been opened, passes an error object in case of error
- * @return {undefined}
- */
- this.openDocumentFromUrl = function (docUrl, editorReadyCallback) {
- runtime.assert(docUrl, "document should be defined here.");
- runtime.assert(!pendingEditorReadyCallback, "pendingEditorReadyCallback should not exist here.");
- runtime.assert(!editorSession, "editorSession should not exist here.");
- runtime.assert(!session, "session should not exist here.");
- pendingMemberId = memberId;
- pendingEditorReadyCallback = function () {
- var op = new ops.OpAddMember();
- op.init({
- memberid: memberId,
- setProperties: userData
- });
- session.enqueue([op]);
- startEditing();
- if (editorReadyCallback) {
- editorReadyCallback();
- }
- };
- odfCanvas.load(docUrl);
- };
- /**
- * Closes the document, and does cleanup.
- * @name TextEditor#closeDocument
- * @function
- * @param {!function(!Error=):undefined} callback Called once the document has been closed, passes an error object in case of error
- * @return {undefined}
- */
- this.closeDocument = function (callback) {
- runtime.assert(session, "session should exist here.");
- endEditing();
- var op = new ops.OpRemoveMember();
- op.init({
- memberid: memberId
- });
- session.enqueue([op]);
- session.close(function (err) {
- if (err) {
- callback(err);
- } else {
- editorSession.sessionController.getMetadataController().unsubscribe(gui.MetadataController.signalMetadataChanged, relayMetadataSignal);
- editorSession.destroy(function (err) {
- if (err) {
- callback(err);
- } else {
- editorSession = undefined;
- session.destroy(function (err) {
- if (err) {
- callback(err);
- } else {
- session = undefined;
- callback();
- }
- });
- }
- });
- }
- });
- };
- /**
- * @name TextEditor#getDocumentAsByteArray
- * @function
- * @param {!function(err:?Error, file:!Uint8Array=):undefined} callback Called with the current document as ODT file as bytearray, passes an error object in case of error
- * @return {undefined}
- */
- this.getDocumentAsByteArray = function (callback) {
- var odfContainer = odfCanvas.odfContainer();
- if (odfContainer) {
- odfContainer.createByteArray(function (ba) {
- callback(null, ba);
- }, function (errorString) {
- callback(new Error(errorString || "Could not create bytearray from OdfContainer."));
- });
- } else {
- callback(new Error("No odfContainer set!"));
- }
- };
- /**
- * Sets the metadata fields from the given properties map.
- * Avoid setting certain fields since they are automatically set:
- * dc:creator
- * dc:date
- * meta:editing-cycles
- *
- * The following properties are never used and will be removed for semantic
- * consistency from the document:
- * meta:editing-duration
- * meta:document-statistic
- *
- * Setting any of the above mentioned fields using this method will have no effect.
- *
- * @name TextEditor#setMetadata
- * @function
- * @param {?Object.<!string, !string>} setProperties A flat object that is a string->string map of field name -> value.
- * @param {?Array.<!string>} removedProperties An array of metadata field names (prefixed).
- * @return {undefined}
- */
- this.setMetadata = function (setProperties, removedProperties) {
- runtime.assert(editorSession, "editorSession should exist here.");
- editorSession.sessionController.getMetadataController().setMetadata(setProperties, removedProperties);
- };
- /**
- * Returns the value of the requested document metadata field.
- * @name TextEditor#getMetadata
- * @function
- * @param {!string} property A namespace-prefixed field name, for example
- * dc:creator
- * @return {?string}
- */
- this.getMetadata = function (property) {
- runtime.assert(editorSession, "editorSession should exist here.");
- return editorSession.sessionController.getMetadataController().getMetadata(property);
- };
- /**
- * Sets the data for the person that is editing the document.
- * The supported fields are:
- * "fullName": the full name of the editing person
- * "color": color to use for the user specific UI elements
- * @name TextEditor#setUserData
- * @function
- * @param {?Object.<!string,!string>|undefined} data
- * @return {undefined}
- */
- function setUserData(data) {
- userData = cloneUserData(data);
- }
- this.setUserData = setUserData;
- /**
- * Returns the data set for the person that is editing the document.
- * @name TextEditor#getUserData
- * @function
- * @return {!Object.<!string,!string>}
- */
- this.getUserData = function () {
- return cloneUserData(userData);
- };
- /**
- * Sets the current state of the document to be either the unmodified state
- * or a modified state.
- * If @p modified is @true and the current state was already a modified state,
- * this call has no effect and also does not remove the unmodified flag
- * from the state which has it set.
- *
- * @name TextEditor#setDocumentModified
- * @function
- * @param {!boolean} modified
- * @return {undefined}
- */
- this.setDocumentModified = function (modified) {
- runtime.assert(editorSession, "editorSession should exist here.");
- if (undoRedoEnabled) {
- editorSession.sessionController.getUndoManager().setDocumentModified(modified);
- }
- };
- /**
- * Returns if the current state of the document matches the unmodified state.
- * @name TextEditor#isDocumentModified
- * @function
- * @return {!boolean}
- */
- this.isDocumentModified = function () {
- runtime.assert(editorSession, "editorSession should exist here.");
- if (undoRedoEnabled) {
- return editorSession.sessionController.getUndoManager().isDocumentModified();
- }
- return false;
- };
- /**
- * @return {undefined}
- */
- function setFocusToOdfCanvas() {
- editorSession.sessionController.getEventManager().focus();
- }
- /**
- * @param {!function(!Error=):undefined} callback passes an error object in case of error
- * @return {undefined}
- */
- function destroyInternal(callback) {
- mainContainerElement.removeChild(editorElement);
- callback();
- }
- /**
- * Destructs the editor object completely.
- * @name TextEditor#destroy
- * @function
- * @param {!function(!Error=):undefined} callback Called once the destruction has been completed, passes an error object in case of error
- * @return {undefined}
- */
- this.destroy = function (callback) {
- var destroyCallbacks = [];
- // 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);
- destroyCallbacks = destroyCallbacks.concat([
- fullWindowZoomHelper.destroy,
- tools.destroy,
- odfCanvas.destroy,
- destroyInternal
- ]);
- core.Async.destroyAll(destroyCallbacks, callback);
- };
- // TODO:
- // this.openDocumentFromByteArray = openDocumentFromByteArray; see also https://github.com/kogmbh/WebODF/issues/375
- // setReadOnly: setReadOnly,
- /**
- * Registers a callback which should be called if the given event happens.
- * @name TextEditor#addEventListener
- * @function
- * @param {!string} eventId
- * @param {!Function} callback
- * @return {undefined}
- */
- this.addEventListener = eventNotifier.subscribe;
- /**
- * Unregisters a callback for the given event.
- * @name TextEditor#removeEventListener
- * @function
- * @param {!string} eventId
- * @param {!Function} callback
- * @return {undefined}
- */
- this.removeEventListener = eventNotifier.unsubscribe;
- /**
- * @return {undefined}
- */
- function init() {
- var editorPane,
- /** @inner @const
- @type{!string} */
- documentns = document.documentElement.namespaceURI;
- /**
- * @param {!string} tagLocalName
- * @param {!string|undefined} id
- * @param {!string} className
- * @return {!Element}
- */
- function createElement(tagLocalName, id, className) {
- var element;
- element = document.createElementNS(documentns, tagLocalName);
- if (id) {
- element.id = id;
- }
- element.classList.add(className);
- return element;
- }
- // create needed tree structure
- canvasElement = createElement('div', canvasElementId, "webodfeditor-canvas");
- canvasContainerElement = createElement('div', canvasContainerElementId, "webodfeditor-canvascontainer");
- toolbarElement = createElement('span', toolbarElementId, "webodfeditor-toolbar");
- toolbarContainerElement = createElement('span', undefined, "webodfeditor-toolbarcontainer");
- editorElement = createElement('div', editorElementId, "webodfeditor-editor");
- // put into tree
- canvasContainerElement.appendChild(canvasElement);
- toolbarContainerElement.appendChild(toolbarElement);
- editorElement.appendChild(toolbarContainerElement);
- editorElement.appendChild(canvasContainerElement);
- mainContainerElement.appendChild(editorElement);
- // style all elements with Dojo's claro.
- // Not nice to do this on body, but then there is no other way known
- // to style also all dialogs, which are attached directly to body
- document.body.classList.add("claro");
- // prevent browser translation service messing up internal address system
- // TODO: this should be done more centrally, but where exactly?
- canvasElement.setAttribute("translate", "no");
- canvasElement.classList.add("notranslate");
- // create widgets
- mainContainer = new BorderContainer({}, mainContainerElementId);
- editorPane = new ContentPane({
- region: 'center'
- }, editorElementId);
- mainContainer.addChild(editorPane);
- mainContainer.startup();
- tools = new Tools(toolbarElementId, {
- onToolDone: setFocusToOdfCanvas,
- loadOdtFile: loadOdtFile,
- saveOdtFile: saveOdtFile,
- saveAsOdtFile: saveAsOdtFile,
- downloadOdtFile: downloadOdtFile,
- close: close,
- directTextStylingEnabled: directTextStylingEnabled,
- directParagraphStylingEnabled: directParagraphStylingEnabled,
- paragraphStyleSelectingEnabled: paragraphStyleSelectingEnabled,
- paragraphStyleEditingEnabled: paragraphStyleEditingEnabled,
- imageInsertingEnabled: imageEditingEnabled,
- hyperlinkEditingEnabled: hyperlinkEditingEnabled,
- annotationsEnabled: annotationsEnabled,
- undoRedoEnabled: undoRedoEnabled,
- zoomingEnabled: zoomingEnabled,
- aboutEnabled: true
- });
- odfCanvas = new odf.OdfCanvas(canvasElement);
- odfCanvas.enableAnnotations(annotationsEnabled, true);
- odfCanvas.addListener("statereadychange", createSession);
- fullWindowZoomHelper = new FullWindowZoomHelper(toolbarContainerElement, canvasContainerElement);
- setUserData(editorOptions.userData);
- }
- init();
- }
- function loadDojoAndStuff(callback) {
- var head = document.getElementsByTagName("head")[0],
- frag = document.createDocumentFragment(),
- link,
- script;
- // append two link and two script elements to the header
- link = document.createElement("link");
- link.rel = "stylesheet";
- link.href = installationPath + "/app/resources/app.css";
- link.type = "text/css";
- link.async = false;
- frag.appendChild(link);
- link = document.createElement("link");
- link.rel = "stylesheet";
- link.href = installationPath + "/wodotexteditor.css";
- link.type = "text/css";
- link.async = false;
- frag.appendChild(link);
- script = document.createElement("script");
- script.src = installationPath + "/dojo-amalgamation.js";
- script["data-dojo-config"] = "async: true";
- script.charset = "utf-8";
- script.type = "text/javascript";
- script.async = false;
- frag.appendChild(script);
- script = document.createElement("script");
- script.src = installationPath + "/webodf.js";
- script.charset = "utf-8";
- script.type = "text/javascript";
- script.async = false;
- script.onload = callback;
- frag.appendChild(script);
- head.appendChild(frag);
- }
- /**
- * Creates a text editor object and returns it on success in the passed callback.
- * @name Wodo#createTextEditor
- * @function
- * @param {!string} editorContainerElementId id of the existing div element which will contain the editor (should be empty before)
- * @param editorOptions options to configure the features of the editor. All entries are optional
- * @param [editorOptions.modus=Wodo.MODUS_FULLEDITING] set the editing modus. Current options: Wodo.MODUS_FULLEDITING, Wodo.MODUS_REVIEW
- * @param [editorOptions.loadCallback] parameter-less callback method, adds a "Load" button to the toolbar which triggers this method
- * @param [editorOptions.saveCallback] parameter-less callback method, adds a "Save" button to the toolbar which triggers this method
- * @param [editorOptions.saveAsCallback] parameter-less callback method, adds a "Save as" button to the toolbar which triggers this method
- * @param [editorOptions.downloadCallback] parameter-less callback method, adds a "Download" button to the right of the toolbar which triggers this method
- * @param [editorOptions.closeCallback] parameter-less callback method, adds a "Save" button to the toolbar which triggers this method
- * @param [editorOptions.allFeaturesEnabled=false] if set to 'true', switches the default for all features from 'false' to 'true'
- * @param [editorOptions.directTextStylingEnabled=false] if set to 'true', enables the direct styling of text (e.g. bold/italic or font)
- * @param [editorOptions.directParagraphStylingEnabled=false] if set to 'true', enables the direct styling of paragraphs (e.g. indentation or alignement)
- * @param [editorOptions.paragraphStyleSelectingEnabled=false] if set to 'true', enables setting of defined paragraph styles to paragraphs
- * @param [editorOptions.paragraphStyleEditingEnabled=false] if set to 'true', enables the editing of defined paragraph styles
- * @param [editorOptions.imageEditingEnabled=false] if set to 'true', enables the insertion of images
- * @param [editorOptions.hyperlinkEditingEnabled=false] if set to 'true', enables the editing of hyperlinks
- * @param [editorOptions.annotationsEnabled=false] if set to 'true', enables the display and the editing of annotations
- * @param [editorOptions.undoRedoEnabled=false] if set to 'true', enables the Undo and Redo of editing actions
- * @param [editorOptions.zoomingEnabled=false] if set to 'true', enables the zooming tool
- * @param [editorOptions.userData] data about the user editing the document
- * @param [editorOptions.userData.fullName] full name of the user, used for annotations and in the metadata of the document
- * @param [editorOptions.userData.color="black"] color to use for any user related indicators like cursor or annotations
- * @param {!function(err:?Error, editor:!TextEditor=):undefined} onEditorCreated
- * @return {undefined}
- */
- function createTextEditor(editorContainerElementId, editorOptions, onEditorCreated) {
- /**
- * @return {undefined}
- */
- function create() {
- var editor = new TextEditor(editorContainerElementId, editorOptions);
- onEditorCreated(null, editor);
- }
- if (!isInitalized) {
- pendingInstanceCreationCalls.push(create);
- // first request?
- if (pendingInstanceCreationCalls.length === 1) {
- if (String(typeof WodoFromSource) === "undefined") {
- loadDojoAndStuff(initTextEditor);
- } else {
- initTextEditor();
- }
- }
- } else {
- create();
- }
- }
- /**
- * @lends Wodo#
- */
- return {
- createTextEditor: createTextEditor,
- // flags
- /** Id of full editing modus */
- MODUS_FULLEDITING: MODUS_FULLEDITING,
- /** Id of review modus */
- MODUS_REVIEW: MODUS_REVIEW,
- /** Id of event for an unkown error */
- EVENT_UNKNOWNERROR: EVENT_UNKNOWNERROR,
- /** Id of event if documentModified state changes */
- EVENT_DOCUMENTMODIFIEDCHANGED: EVENT_DOCUMENTMODIFIEDCHANGED,
- /** Id of event if metadata changes */
- EVENT_METADATACHANGED: EVENT_METADATACHANGED
- };
- }());
|