webodf update

pull/1/head
Tobias Hintze 11 years ago
parent 86952308ce
commit 3deb473927

@ -58,8 +58,9 @@ html, body, #mainContainer {
-webkit-transform-origin: top center;
-moz-transform-origin: top center;
-o-transform-origin: top center;
overflow: hidden;
border: 1px solid #ccc;
}
#collaboration {
@ -87,7 +88,7 @@ html, body, #mainContainer {
}
#people {
#members {
width: 70px;
padding: 2px;
text-align: center;
@ -120,14 +121,14 @@ html, body, #mainContainer {
box-shadow: 0px 0px 15px red;
}
#people > #nameInfo {
#members > #nameInfo {
padding-top: 3px;
padding-bottom: 3px;
width: 100%;
background-color: #eef;
}
#peopleList .userListButton {
#memberList .memberListButton {
margin-top: 5px;
padding-top: 3px;
margin-left: auto;
@ -141,7 +142,7 @@ html, body, #mainContainer {
cursor: pointer;
}
#peopleList .userListLabel {
#memberList .memberListLabel {
color: white;
border-radius: 5px;
padding: 2px;
@ -149,11 +150,11 @@ html, body, #mainContainer {
word-wrap: break-word;
text-align: center justify;
}
div.userListLabel[fullname]:before {
div.memberListLabel[fullname]:before {
content: attr(fullname) "";
}
#peopleList img {
#memberList img {
box-shadow: 0px 0px 5px rgb(90, 90, 90) inset;
background-color: rgb(200, 200, 200);
border-radius: 5px;
@ -164,7 +165,7 @@ div.userListLabel[fullname]:before {
margin: auto;
}
#peopleList img:hover {
#memberList img:hover {
opacity: 0.9;
}
@ -314,3 +315,4 @@ cursor div:after {
top: 100%;
left: 43%;
}

@ -36,14 +36,14 @@
define("webodf/editor/Editor", [
"dojo/i18n!webodf/editor/nls/myResources",
"webodf/editor/EditorSession",
"webodf/editor/UserList",
"webodf/editor/MemberList",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"webodf/editor/widgets"],
function (myResources,
EditorSession,
UserList,
MemberList,
BorderContainer,
ContentPane,
loadWidgets) {
@ -52,7 +52,7 @@ define("webodf/editor/Editor", [
/**
* @constructor
* @param {{networked:boolean=,
* memberid:string=,
* memberid:!string,
* loadCallback:function()=,
* saveCallback:function()=,
* cursorAddedCallback:function(!string)=,
@ -65,14 +65,13 @@ define("webodf/editor/Editor", [
var self = this,
// Private
userid,
memberid = args.memberid,
session,
editorSession,
userList,
memberList,
networked = args.networked === true,
opRouter,
userModel,
memberModel,
loadOdtFile = args.loadCallback,
saveOdtFile = args.saveCallback,
cursorAddedHandler = args.cursorAddedCallback,
@ -99,17 +98,17 @@ define("webodf/editor/Editor", [
*/
function initGuiAndDoc(initialDocumentUrl, editorReadyCallback) {
var odfElement, mainContainer,
editorPane, peoplePane,
editorPane, memberListPane,
inviteButton,
viewOptions = {
editInfoMarkersInitiallyVisible: networked,
caretAvatarsInitiallyVisible: networked,
caretBlinksOnRangeSelect: true
},
peopleListDiv = document.getElementById('peopleList');
memberListDiv = document.getElementById('memberList');
if (networked) {
runtime.assert(peopleListDiv, "missing peopleList div in HTML");
runtime.assert(memberListDiv, "missing memberList div in HTML");
}
runtime.loadClass('odf.OdfCanvas');
@ -158,19 +157,14 @@ define("webodf/editor/Editor", [
// Allow annotations
odfCanvas.enableAnnotations(true);
if (!memberid) {
// legacy - memberid should be passed in the constructor
memberid = (userid || 'undefined') + "___" + Date.now();
}
session = new ops.Session(odfCanvas);
editorSession = new EditorSession(session, memberid, {
viewOptions: viewOptions
});
editorSession.sessionController.setUndoManager(new gui.TrivialUndoManager());
if (peopleListDiv) {
userList = new UserList(editorSession, peopleListDiv);
if (memberListDiv) {
memberList = new MemberList(editorSession, memberListDiv);
}
if (registerCallbackForShutdown) {
@ -192,12 +186,12 @@ define("webodf/editor/Editor", [
}, 'editor');
mainContainer.addChild(editorPane);
if (networked && peopleListDiv) {
peoplePane = new ContentPane({
if (networked && memberListDiv) {
memberListPane = new ContentPane({
region: 'right',
title: translator("people")
}, 'people');
mainContainer.addChild(peoplePane);
title: translator("members")
}, 'members');
mainContainer.addChild(memberListPane);
}
mainContainer.startup();
@ -205,7 +199,7 @@ define("webodf/editor/Editor", [
if (window.inviteButtonProxy) {
inviteButton = document.getElementById('inviteButton');
if (inviteButton) {
inviteButton.innerText = translator("invitePeople");
inviteButton.innerText = translator("inviteMembers");
inviteButton.style.display = "block";
inviteButton.onclick = window.inviteButtonProxy.clicked;
}
@ -269,12 +263,12 @@ define("webodf/editor/Editor", [
*/
self.loadSession = function (sessionId, editorReadyCallback) {
initGuiAndDoc(server.getGenesisUrl(sessionId), function () {
// get router and user model
// get router and member model
opRouter = opRouter || serverFactory.createOperationRouter(sessionId, memberid, server);
session.setOperationRouter(opRouter);
userModel = userModel || serverFactory.createUserModel(server);
session.setUserModel(userModel);
memberModel = memberModel || serverFactory.createMemberModel(sessionId, server);
session.setMemberModel(memberModel);
opRouter.requestReplay(function done() {
var odtDocument = session.getOdtDocument();
@ -295,9 +289,9 @@ define("webodf/editor/Editor", [
});
};
// access to user model
self.getUserModel = function () {
return userModel;
// access to member model
self.getMemberModel = function () {
return memberModel;
};
}
return Editor;

@ -70,8 +70,8 @@ define("webodf/editor/EditorSession", [
formatting = odtDocument.getFormatting(),
styleHelper = new gui.StyleHelper(formatting),
eventNotifier = new core.EventNotifier([
EditorSession.signalUserAdded,
EditorSession.signalUserRemoved,
EditorSession.signalMemberAdded,
EditorSession.signalMemberRemoved,
EditorSession.signalCursorMoved,
EditorSession.signalParagraphChanged,
EditorSession.signalStyleCreated,
@ -164,7 +164,7 @@ define("webodf/editor/EditorSession", [
ncName = createNCName(name);
// create default paragraph style
// memberid is used to avoid id conflicts with ids created by other users
// memberid is used to avoid id conflicts with ids created by other members
result = ncName + "_" + ncMemberId;
// then loop until result is really unique
while (formatting.hasParagraphStyle(result)) {
@ -196,12 +196,12 @@ define("webodf/editor/EditorSession", [
// 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) {
self.emit(EditorSession.signalUserAdded, cursor.getMemberId());
self.emit(EditorSession.signalMemberAdded, cursor.getMemberId());
trackCursor(cursor);
});
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, function (memberId) {
self.emit(EditorSession.signalUserRemoved, memberId);
self.emit(EditorSession.signalMemberRemoved, memberId);
});
odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, function (cursor) {
@ -251,12 +251,12 @@ define("webodf/editor/EditorSession", [
eventNotifier.subscribe(eventid, cb);
};
this.getUserDetailsAndUpdates = function (memberId, subscriber) {
return session.getUserModel().getUserDetailsAndUpdates(memberId, subscriber);
this.getMemberDetailsAndUpdates = function (memberId, subscriber) {
return session.getMemberModel().getMemberDetailsAndUpdates(memberId, subscriber);
};
this.unsubscribeUserDetailsUpdates = function (memberId, subscriber) {
return session.getUserModel().unsubscribeUserDetailsUpdates(memberId, subscriber);
this.unsubscribeMemberDetailsUpdates = function (memberId, subscriber) {
return session.getMemberModel().unsubscribeMemberDetailsUpdates(memberId, subscriber);
};
this.getCursorPosition = function () {
@ -458,7 +458,7 @@ define("webodf/editor/EditorSession", [
this.deleteStyle = function (styleName) {
var op;
op = new ops.OpDeleteParagraphStyle();
op = new ops.OpRemoveParagraphStyle();
op.init({
memberid: memberid,
styleName: styleName
@ -541,8 +541,8 @@ define("webodf/editor/EditorSession", [
init();
};
/**@const*/EditorSession.signalUserAdded = "userAdded";
/**@const*/EditorSession.signalUserRemoved = "userRemoved";
/**@const*/EditorSession.signalMemberAdded = "memberAdded";
/**@const*/EditorSession.signalMemberRemoved = "memberRemoved";
/**@const*/EditorSession.signalCursorMoved = "cursorMoved";
/**@const*/EditorSession.signalParagraphChanged = "paragraphChanged";
/**@const*/EditorSession.signalStyleCreated = "styleCreated";

@ -33,32 +33,33 @@
* @source: http://gitorious.org/webodf/webodf/
*/
/*global define,runtime */
define("webodf/editor/UserList",
define("webodf/editor/MemberList",
["webodf/editor/EditorSession"],
function (EditorSession) {
"use strict";
return function UserList(editorSession, userListDiv) {
return function MemberList(editorSession, memberListDiv) {
var self = this;
editorSession.subscribe(EditorSession.signalUserAdded, function (memberId) {
self.addUser(memberId);
editorSession.subscribe(EditorSession.signalMemberAdded, function (memberId) {
self.addMember(memberId);
});
editorSession.subscribe(EditorSession.signalUserRemoved, function (memberId) {
self.removeUser(memberId);
editorSession.subscribe(EditorSession.signalMemberRemoved, function (memberId) {
self.removeMember(memberId);
});
/**
* @param {!string} memberId
*/
function updateAvatarButton(memberId, userDetails) {
var node = userListDiv.firstChild;
if (userDetails === null) {
// 'null' here means finally unknown user
function updateAvatarButton(memberId, memberDetails) {
var node = memberListDiv.firstChild;
if (memberDetails === null) {
// 'null' here means finally unknown member
// (and not that the data is still loading)
userDetails = {
memberDetails = {
memberid: memberId, fullname: "Unknown",
color: "black", imageurl: "avatar-joe.png"
};
@ -69,11 +70,11 @@ define("webodf/editor/UserList",
while (node) {
if (node.localName === "img") {
// update avatar image
node.src = userDetails.imageurl;
node.src = memberDetails.imageurl;
// update border color
node.style.borderColor = userDetails.color;
node.style.borderColor = memberDetails.color;
} else if (node.localName === "div") {
node.setAttribute('fullname', userDetails.fullname);
node.setAttribute('fullname', memberDetails.fullname);
}
node = node.nextSibling;
}
@ -87,15 +88,15 @@ define("webodf/editor/UserList",
* @param {!string} memberId
*/
function createAvatarButton(memberId) {
runtime.assert(userListDiv, "userListDiv unavailable");
var doc = userListDiv.ownerDocument,
runtime.assert(memberListDiv, "memberListDiv unavailable");
var doc = memberListDiv.ownerDocument,
htmlns = doc.documentElement.namespaceURI,
avatarDiv = doc.createElementNS(htmlns, "div"),
imageElement = doc.createElement("img"),
fullnameNode = doc.createElement("div");
avatarDiv.className = "userListButton";
fullnameNode.className = "userListLabel";
avatarDiv.className = "memberListButton";
fullnameNode.className = "memberListLabel";
avatarDiv.appendChild(imageElement);
avatarDiv.appendChild(fullnameNode);
avatarDiv.memberId = memberId; // TODO: namespace?
@ -112,7 +113,7 @@ define("webodf/editor/UserList",
caret.toggleHandleVisibility();
}
};
userListDiv.appendChild(avatarDiv);
memberListDiv.appendChild(avatarDiv);
// preset bogus data
// TODO: indicate loading state
@ -124,10 +125,10 @@ define("webodf/editor/UserList",
* @param {!string} memberId
*/
function removeAvatarButton(memberId) {
var node = userListDiv.firstChild;
var node = memberListDiv.firstChild;
while (node) {
if (node.memberId === memberId) {
userListDiv.removeChild(node);
memberListDiv.removeChild(node);
return;
}
node = node.nextSibling;
@ -137,16 +138,16 @@ define("webodf/editor/UserList",
/**
* @param {!string} memberId
*/
this.addUser = function (memberId) {
this.addMember = function (memberId) {
createAvatarButton(memberId);
editorSession.getUserDetailsAndUpdates(memberId, updateAvatarButton);
editorSession.getMemberDetailsAndUpdates(memberId, updateAvatarButton);
};
/**
* @param {!string} memberId
*/
this.removeUser = function (memberId) {
editorSession.unsubscribeUserDetailsUpdates(memberId, updateAvatarButton);
this.removeMember = function (memberId) {
editorSession.unsubscribeMemberDetailsUpdates(memberId, updateAvatarButton);
removeAvatarButton(memberId);
};
};

@ -1,159 +0,0 @@
/**
* @license
* Copyright (C) 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/
*/
/*global ops, runtime */
function PullBoxSessionList(server) {
"use strict";
var cachedSessionData = {},
subscribers = [],
/** HACK: allow to stop pulling, so that does not mess up the logs
* Remove before merging to master */
pullingActive = true;
function onSessionData(sessionData) {
var i,
isNew = ! cachedSessionData.hasOwnProperty(sessionData.id);
// cache
cachedSessionData[sessionData.id] = sessionData;
runtime.log("get session data for:"+sessionData.title+", is new:"+isNew);
for (i = 0; i < subscribers.length; i += 1) {
if (isNew) {
subscribers[i].onCreated(sessionData);
} else {
subscribers[i].onUpdated(sessionData);
}
}
}
function onSessionRemoved(sessionId) {
var i;
if (cachedSessionData.hasOwnProperty(sessionId)) {
delete cachedSessionData[sessionId];
for (i = 0; i < subscribers.length; i += 1) {
subscribers[i].onRemoved(sessionId);
}
}
}
function pullSessionList() {
if (!pullingActive) { return; }
server.call("session-list", function(responseData) {
var response = runtime.fromJson(responseData),
sessionList, i,
unupdatedSessions = {};
runtime.log("session-list reply: " + responseData);
if (response.hasOwnProperty("session_list")) {
// collect known sessions
for (i in cachedSessionData) {
if (cachedSessionData.hasOwnProperty(i)) {
unupdatedSessions[i] = ""; // some dummy value, unused
}
}
// add/update with all delivered sessions
sessionList = response.session_list;
for (i = 0; i < sessionList.length; i++) {
if (unupdatedSessions.hasOwnProperty(sessionList[i].id)) {
delete unupdatedSessions[sessionList[i].id];
}
onSessionData(sessionList[i]);
}
// remove unupdated sessions
for (i in unupdatedSessions) {
if (unupdatedSessions.hasOwnProperty(i)) {
onSessionRemoved(i);
}
}
// next update in 5 secs
runtime.getWindow().setTimeout(pullSessionList, 5000);
} else {
runtime.log("Meh, sessionlist data broken: " + responseData);
}
});
}
this.getSessions = function (subscriber) {
var i,
sessionList = [];
if (subscriber) {
subscribers.push(subscriber);
}
for (i in cachedSessionData) {
if (cachedSessionData.hasOwnProperty(i)) {
sessionList.push(cachedSessionData[i]);
}
}
return sessionList;
};
this.unsubscribe = function (subscriber) {
var i;
for (i=0; i<subscribers.length; i+=1) {
if (subscribers[i] === subscriber) {
break;
}
}
runtime.assert((i < subscribers.length),
"tried to unsubscribe when not subscribed.");
subscribers.splice(i,1);
};
this.stopPulling = function () {
pullingActive = false;
};
function init() {
pullSessionList();
}
init();
}

@ -1,50 +0,0 @@
/**
* @license
* 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/
*/
/*global ops, runtime */
/**
* A model which provides information about sessions.
* @interface
*/
SessionList = function SessionList() {"use strict"; };
/**
* @param {{onCreated:function(!Object),
* onUpdated:function(!Object),
* onRemoved:function(!string) }} subscriber
* @return {undefined}
*/
SessionList.prototype.getSessions = function (subscriber) {"use strict"; };

@ -248,26 +248,22 @@ var webodfEditor = (function () {
* and start the editor on the network.
*
* @param {!string} sessionId
* @param {!string} userid
* @param {!string} memberId
* @param {?string} token
* @param {?Object} editorOptions
* @param {?function(!Object)} editorReadyCallback
*/
function createNetworkedEditor(sessionId, userid, token, editorOptions, editorReadyCallback) {
function createNetworkedEditor(sessionId, memberId, token, editorOptions, editorReadyCallback) {
runtime.assert(sessionId, "sessionId needs to be specified");
runtime.assert(memberId, "memberId needs to be specified");
runtime.assert(editorInstance === null, "cannot boot with instanciated editor");
editorOptions = editorOptions || {};
editorOptions.memberid = userid + "___" + Date.now();
editorOptions.memberid = memberId;
editorOptions.networked = true;
editorOptions.networkSecurityToken = token;
// if pre-authentication has happened:
if (token) {
server.setToken(token);
}
require({ }, ["webodf/editor/Editor"],
function (Editor) {
// TODO: the networkSecurityToken needs to be retrieved via now.login
@ -280,7 +276,7 @@ var webodfEditor = (function () {
editorReadyCallback(editorInstance);
});
}
);
);
}
@ -365,7 +361,8 @@ var webodfEditor = (function () {
*
*/
function boot(args) {
var editorOptions = {}, loginProcedure = startLoginProcess;
var editorOptions = {},
loginProcedure = startLoginProcess;
runtime.assert(!booting, "editor creation already in progress");
args = args || {};
@ -399,13 +396,25 @@ var webodfEditor = (function () {
// start the editor with network
function handleNetworkedSituation() {
loginProcedure(function (sessionId, userid, token) {
createNetworkedEditor(sessionId, userid, token, editorOptions, function (ed) {
if (args.callback) {
args.callback(ed);
}
var joinSession = server.joinSession;
if (args.joinSession) {
joinSession = args.joinSession;
}
loginProcedure(function (sessionId, userId, token) {
// if pre-authentication has happened:
if (token) {
server.setToken(token);
}
);
joinSession(userId, sessionId, function(memberId) {
createNetworkedEditor(sessionId, memberId, token, editorOptions, function (ed) {
if (args.callback) {
args.callback(ed);
}
});
});
});
}

@ -54,10 +54,11 @@ ServerFactory.prototype.createServer = function () {"use strict"; };
ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server) {"use strict"; };
/**
* @param {!string} sessionId
* @param {!ops.Server} server
* @return {!ops.UserModel}
* @return {!ops.MemberModel}
*/
ServerFactory.prototype.createUserModel = function (server) {"use strict"; };
ServerFactory.prototype.createMemberModel = function (sessionId, server) {"use strict"; };
/**
* @param {!ops.Server} server

@ -41,7 +41,7 @@ define("webodf/editor/server/nowjs/serverFactory", [
"use strict";
runtime.loadClass("ops.NowjsServer");
runtime.loadClass("ops.NowjsUserModel");
runtime.loadClass("ops.NowjsMemberModel");
runtime.loadClass("ops.NowjsOperationRouter");
/**
@ -55,8 +55,8 @@ define("webodf/editor/server/nowjs/serverFactory", [
this.createOperationRouter = function (sid, mid, server) {
return new ops.NowjsOperationRouter(sid, mid, server);
};
this.createUserModel = function (server) {
return new ops.NowjsUserModel(server);
this.createMemberModel = function (sid, server) {
return new ops.NowjsMemberModel(server);
};
this.createSessionList = function (server) {
return new NowjsSessionList(server);

@ -41,7 +41,7 @@ define("webodf/editor/server/pullbox/serverFactory", [
"use strict";
runtime.loadClass("ops.PullBoxServer");
runtime.loadClass("ops.PullBoxUserModel");
runtime.loadClass("ops.PullBoxMemberModel");
runtime.loadClass("ops.PullBoxOperationRouter");
/**
@ -55,8 +55,8 @@ define("webodf/editor/server/pullbox/serverFactory", [
this.createOperationRouter = function (sid, mid, server) {
return new ops.PullBoxOperationRouter(sid, mid, server);
};
this.createUserModel = function (server) {
return new ops.PullBoxUserModel(server);
this.createMemberModel = function (sid, server) {
return new ops.PullBoxMemberModel(sid, server);
};
this.createSessionList = function (server) {
return new PullBoxSessionList(server);

@ -77,14 +77,16 @@ define("webodf/editor/server/pullbox/sessionList", [], function () {
function pullSessionList() {
if (!pullingActive) { return; }
server.call("session-list", function(responseData) {
server.call({
command: "query_sessiondata_list"
}, function(responseData) {
var response = runtime.fromJson(responseData),
sessionList, i,
unupdatedSessions = {};
runtime.log("session-list reply: " + responseData);
runtime.log("query_sessiondata_list reply: " + responseData);
if (response.hasOwnProperty("session_list")) {
if (response.hasOwnProperty("sessiondata_list")) {
// collect known sessions
for (i in cachedSessionData) {
if (cachedSessionData.hasOwnProperty(i)) {
@ -93,7 +95,7 @@ define("webodf/editor/server/pullbox/sessionList", [], function () {
}
// add/update with all delivered sessions
sessionList = response.session_list;
sessionList = response.sessiondata_list;
for (i = 0; i < sessionList.length; i++) {
if (unupdatedSessions.hasOwnProperty(sessionList[i].id)) {
delete unupdatedSessions[sessionList[i].id];

@ -2994,6 +2994,7 @@ core.Utils = function Utils() {
this.hashString = hashString
};
core.DomUtils = function DomUtils() {
var self = this;
function findStablePoint(container, offset) {
if(offset < container.childNodes.length) {
container = container.childNodes[offset];
@ -3108,7 +3109,26 @@ core.DomUtils = function DomUtils() {
var nodeLength = node.nodeType === Node.TEXT_NODE ? node.length : node.childNodes.length;
return range.comparePoint(node, 0) <= 0 && range.comparePoint(node, nodeLength) >= 0
}
this.rangeIntersectsNode = rangeIntersectsNode
this.rangeIntersectsNode = rangeIntersectsNode;
function containsNode(parent, descendant) {
return parent === descendant || parent.contains(descendant)
}
this.containsNode = containsNode;
function containsNodeForBrokenWebKit(parent, descendant) {
return parent === descendant || Boolean(parent.compareDocumentPosition(descendant) & Node.DOCUMENT_POSITION_CONTAINED_BY)
}
function init() {
var window = runtime.getWindow(), appVersion, webKitOrSafari;
if(window === null) {
return
}
appVersion = window.navigator.appVersion.toLowerCase();
webKitOrSafari = appVersion.indexOf("chrome") === -1 && (appVersion.indexOf("applewebkit") !== -1 || appVersion.indexOf("safari") !== -1);
if(webKitOrSafari) {
self.containsNode = containsNodeForBrokenWebKit
}
}
init()
};
runtime.loadClass("core.DomUtils");
core.Cursor = function Cursor(document, memberId) {
@ -5724,7 +5744,7 @@ xmldom.XPath = function() {
@source: http://www.webodf.org/
@source: http://gitorious.org/webodf/webodf/
*/
gui.AnnotationViewManager = function AnnotationViewManager(odfFragment, annotationsPane) {
gui.AnnotationViewManager = function AnnotationViewManager(odfCanvas, odfFragment, annotationsPane) {
var annotations = [], doc = odfFragment.ownerDocument, odfUtils = new odf.OdfUtils, CONNECTOR_MARGIN = 30, NOTE_MARGIN = 20, window = runtime.getWindow();
runtime.assert(Boolean(window), "Expected to be run in an environment which has a global window, like a browser.");
function wrapAnnotation(annotation) {
@ -5782,21 +5802,21 @@ gui.AnnotationViewManager = function AnnotationViewManager(odfFragment, annotati
return Math.sqrt(xs + ys)
}
function renderAnnotation(annotation) {
var annotationNote = annotation.node.parentNode, connectorHorizontal = annotationNote.nextSibling, connectorAngular = connectorHorizontal.nextSibling, annotationWrapper = annotationNote.parentNode, connectorAngle = 0, previousAnnotation = annotations[annotations.indexOf(annotation) - 1], previousRect, creatorNode = annotation.node.getElementsByTagNameNS(odf.Namespaces.dcns, "creator")[0], creatorName;
annotationNote.style.left = annotationsPane.getBoundingClientRect().left - annotationWrapper.getBoundingClientRect().left + "px";
annotationNote.style.width = annotationsPane.getBoundingClientRect().width + "px";
var annotationNote = annotation.node.parentNode, connectorHorizontal = annotationNote.nextSibling, connectorAngular = connectorHorizontal.nextSibling, annotationWrapper = annotationNote.parentNode, connectorAngle = 0, previousAnnotation = annotations[annotations.indexOf(annotation) - 1], previousRect, creatorNode = annotation.node.getElementsByTagNameNS(odf.Namespaces.dcns, "creator")[0], creatorName, zoomLevel = odfCanvas.getZoomLevel();
annotationNote.style.left = (annotationsPane.getBoundingClientRect().left - annotationWrapper.getBoundingClientRect().left) / zoomLevel + "px";
annotationNote.style.width = annotationsPane.getBoundingClientRect().width / zoomLevel + "px";
connectorHorizontal.style.width = parseFloat(annotationNote.style.left) - CONNECTOR_MARGIN + "px";
if(previousAnnotation) {
previousRect = previousAnnotation.node.parentNode.getBoundingClientRect();
if(annotationWrapper.getBoundingClientRect().top - previousRect.bottom <= NOTE_MARGIN) {
annotationNote.style.top = Math.abs(annotationWrapper.getBoundingClientRect().top - previousRect.bottom) + NOTE_MARGIN + "px"
if((annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel <= NOTE_MARGIN) {
annotationNote.style.top = Math.abs(annotationWrapper.getBoundingClientRect().top - previousRect.bottom) / zoomLevel + NOTE_MARGIN + "px"
}else {
annotationNote.style.top = "0px"
}
}
connectorAngular.style.left = connectorHorizontal.getBoundingClientRect().width + "px";
connectorAngular.style.width = lineDistance({x:connectorAngular.getBoundingClientRect().left, y:connectorAngular.getBoundingClientRect().top}, {x:annotationNote.getBoundingClientRect().left, y:annotationNote.getBoundingClientRect().top}) + "px";
connectorAngle = Math.asin((annotationNote.getBoundingClientRect().top - connectorAngular.getBoundingClientRect().top) / parseFloat(connectorAngular.style.width));
connectorAngular.style.left = connectorHorizontal.getBoundingClientRect().width / zoomLevel + "px";
connectorAngular.style.width = lineDistance({x:connectorAngular.getBoundingClientRect().left / zoomLevel, y:connectorAngular.getBoundingClientRect().top / zoomLevel}, {x:annotationNote.getBoundingClientRect().left / zoomLevel, y:annotationNote.getBoundingClientRect().top / zoomLevel}) + "px";
connectorAngle = Math.asin((annotationNote.getBoundingClientRect().top - connectorAngular.getBoundingClientRect().top) / (zoomLevel * parseFloat(connectorAngular.style.width)));
connectorAngular.style.transform = "rotate(" + connectorAngle + "rad)";
connectorAngular.style.MozTransform = "rotate(" + connectorAngle + "rad)";
connectorAngular.style.WebkitTransform = "rotate(" + connectorAngle + "rad)";
@ -8618,18 +8638,14 @@ odf.OdfCanvas = function() {
}
}
if(url) {
if(/^(?:http|https|ftp):\/\//.test(url)) {
callback(url)
}else {
try {
part = container.getPart(url);
part.onchange = function(part) {
callback(part.url)
};
part.load()
}catch(e) {
runtime.log("slight problem: " + e)
}
try {
part = container.getPart(url);
part.onchange = function(part) {
callback(part.url)
};
part.load()
}catch(e) {
runtime.log("slight problem: " + e)
}
}else {
url = getUrlFromBinaryDataElement(image);
@ -8917,7 +8933,7 @@ odf.OdfCanvas = function() {
}
odf.OdfCanvas = function OdfCanvas(element) {
runtime.assert(element !== null && element !== undefined, "odf.OdfCanvas constructor needs DOM element");
var 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;
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);
@ -9029,7 +9045,7 @@ odf.OdfCanvas = function() {
if(annotationManager) {
annotationManager.forgetAnnotations()
}
annotationManager = new gui.AnnotationViewManager(odfnode.body, annotationsPane);
annotationManager = new gui.AnnotationViewManager(self, odfnode.body, annotationsPane);
modifyAnnotations(odfnode.body)
}else {
if(annotationsPane.parentNode) {
@ -9331,6 +9347,8 @@ ops.Server.prototype.networkStatus = function() {
};
ops.Server.prototype.login = function(login, password, successCb, failCb) {
};
ops.Server.prototype.joinSession = function(userId, sessionId, successCb, failCb) {
};
ops.Server.prototype.getGenesisUrl = function(sessionId) {
};
/*
@ -9368,16 +9386,10 @@ ops.Server.prototype.getGenesisUrl = function(sessionId) {
@source: http://gitorious.org/webodf/webodf/
*/
ops.NowjsServer = function NowjsServer() {
var self = this, nowObject;
var nowObject;
this.getNowObject = function() {
return nowObject
};
function createOperationRouter(sid, mid) {
return new ops.NowjsOperationRouter(sid, mid, self)
}
function createUserModel() {
return new ops.NowjsUserModel(self)
}
this.getGenesisUrl = function(sessionId) {
return"/session/" + sessionId + "/genesis"
};
@ -9421,8 +9433,12 @@ ops.NowjsServer = function NowjsServer() {
nowObject.login(login, password, successCb, failCb)
}
};
this.createOperationRouter = createOperationRouter;
this.createUserModel = createUserModel
this.joinSession = function(userId, sessionId, successCb, failCb) {
nowObject.joinSession(userId, sessionId, function(memberId) {
nowObject.memberid = memberId;
successCb(memberId)
}, failCb)
}
};
/*
@ -9523,6 +9539,19 @@ ops.PullBoxServer = function PullBoxServer(args) {
failCb(responseData)
}
})
};
this.joinSession = function(userId, sessionId, successCb, failCb) {
call({command:"join_session", args:{user_id:userId, es_id:sessionId}}, function(responseData) {
var response = (runtime.fromJson(responseData));
runtime.log("join_session reply: " + responseData);
if(response.hasOwnProperty("success") && response.success) {
successCb(response.member_id)
}else {
if(failCb) {
failCb()
}
}
})
}
};
/*
@ -10635,7 +10664,7 @@ ops.OpSetParagraphStyle = function OpSetParagraphStyle() {
};
this.transform = function(otherOp, hasPriority) {
var otherOpspec = otherOp.spec(), otherOpType = otherOpspec.optype;
if(otherOpType === "DeleteParagraphStyle") {
if(otherOpType === "RemoveParagraphStyle") {
if(otherOpspec.styleName === styleName) {
styleName = ""
}
@ -10759,7 +10788,7 @@ ops.OpUpdateParagraphStyle = function OpUpdateParagraphStyle() {
}
}
}else {
if(otherOpType === "DeleteParagraphStyle") {
if(otherOpType === "RemoveParagraphStyle") {
if(otherOpspec.styleName === styleName) {
return[]
}
@ -10866,7 +10895,7 @@ ops.OpAddParagraphStyle = function OpAddParagraphStyle() {
};
this.transform = function(otherOp, hasPriority) {
var otherSpec = otherOp.spec();
if((otherSpec.optype === "UpdateParagraphStyle" || otherSpec.optype === "DeleteParagraphStyle") && otherSpec.styleName === styleName) {
if((otherSpec.optype === "UpdateParagraphStyle" || otherSpec.optype === "RemoveParagraphStyle") && otherSpec.styleName === styleName) {
return null
}
return[self]
@ -10949,8 +10978,8 @@ ops.OpAddParagraphStyle = function OpAddParagraphStyle() {
@source: http://www.webodf.org/
@source: http://gitorious.org/webodf/webodf/
*/
ops.OpDeleteParagraphStyle = function OpDeleteParagraphStyle() {
var self = this, optype = "DeleteParagraphStyle", memberid, timestamp, styleName;
ops.OpRemoveParagraphStyle = function OpRemoveParagraphStyle() {
var self = this, optype = "RemoveParagraphStyle", memberid, timestamp, styleName;
this.init = function(data) {
memberid = data.memberid;
timestamp = data.timestamp;
@ -11137,7 +11166,7 @@ runtime.loadClass("ops.OpSplitParagraph");
runtime.loadClass("ops.OpSetParagraphStyle");
runtime.loadClass("ops.OpUpdateParagraphStyle");
runtime.loadClass("ops.OpAddParagraphStyle");
runtime.loadClass("ops.OpDeleteParagraphStyle");
runtime.loadClass("ops.OpRemoveParagraphStyle");
runtime.loadClass("ops.OpAddAnnotation");
ops.OperationFactory = function OperationFactory() {
var specs;
@ -11158,7 +11187,7 @@ ops.OperationFactory = function OperationFactory() {
}
}
function init() {
specs = {AddCursor:constructor(ops.OpAddCursor), ApplyDirectStyling:constructor(ops.OpApplyDirectStyling), InsertTable:constructor(ops.OpInsertTable), InsertText:constructor(ops.OpInsertText), RemoveText:constructor(ops.OpRemoveText), SplitParagraph:constructor(ops.OpSplitParagraph), SetParagraphStyle:constructor(ops.OpSetParagraphStyle), UpdateParagraphStyle:constructor(ops.OpUpdateParagraphStyle), AddParagraphStyle:constructor(ops.OpAddParagraphStyle), DeleteParagraphStyle:constructor(ops.OpDeleteParagraphStyle),
specs = {AddCursor:constructor(ops.OpAddCursor), ApplyDirectStyling:constructor(ops.OpApplyDirectStyling), InsertTable:constructor(ops.OpInsertTable), InsertText:constructor(ops.OpInsertText), RemoveText:constructor(ops.OpRemoveText), SplitParagraph:constructor(ops.OpSplitParagraph), SetParagraphStyle:constructor(ops.OpSetParagraphStyle), UpdateParagraphStyle:constructor(ops.OpUpdateParagraphStyle), AddParagraphStyle:constructor(ops.OpAddParagraphStyle), RemoveParagraphStyle:constructor(ops.OpRemoveParagraphStyle),
MoveCursor:constructor(ops.OpMoveCursor), RemoveCursor:constructor(ops.OpRemoveCursor), AddAnnotation:constructor(ops.OpAddAnnotation)}
}
init()
@ -11555,7 +11584,7 @@ runtime.loadClass("ops.OpSplitParagraph");
runtime.loadClass("ops.OpSetParagraphStyle");
runtime.loadClass("ops.OpAddParagraphStyle");
runtime.loadClass("ops.OpUpdateParagraphStyle");
runtime.loadClass("ops.OpDeleteParagraphStyle");
runtime.loadClass("ops.OpRemoveParagraphStyle");
ops.OperationTransformer = function OperationTransformer() {
var operationFactory;
function transformOpVsOp(opA, opB) {
@ -11731,17 +11760,6 @@ ops.EditInfo = function EditInfo(container, odtDocument) {
return sortEdits()
};
this.addEdit = function(memberid, timestamp) {
var id, userid = memberid.split("___")[0];
if(!editHistory[memberid]) {
for(id in editHistory) {
if(editHistory.hasOwnProperty(id)) {
if(id.split("___")[0] === userid) {
delete editHistory[id];
break
}
}
}
}
editHistory[memberid] = {time:timestamp}
};
this.clearEdits = function() {
@ -11890,7 +11908,7 @@ gui.Caret = function Caret(cursor, avatarInitiallyVisible, blinkOnRangeSelect) {
caretOffsetTopLeft.y += caretElement.offsetTop;
return{left:caretOffsetTopLeft.x - margin, top:caretOffsetTopLeft.y - margin, right:caretOffsetTopLeft.x + caretElement.scrollWidth - 1 + margin, bottom:caretOffsetTopLeft.y + caretElement.scrollHeight - 1 + margin}
}
this.refreshCursor = function() {
this.refreshCursorBlinking = function() {
if(blinkOnRangeSelect || cursor.getSelectedRange().collapsed) {
shouldBlink = true;
blink(true)
@ -12168,6 +12186,8 @@ gui.Clipboard = function Clipboard() {
}
init()
};
runtime.loadClass("core.DomUtils");
runtime.loadClass("odf.OdfUtils");
runtime.loadClass("ops.OpAddCursor");
runtime.loadClass("ops.OpRemoveCursor");
runtime.loadClass("ops.OpMoveCursor");
@ -12181,7 +12201,8 @@ runtime.loadClass("gui.KeyboardHandler");
runtime.loadClass("gui.StyleHelper");
gui.SessionController = function() {
gui.SessionController = function SessionController(session, inputMemberId) {
var odtDocument = session.getOdtDocument(), odfUtils = new odf.OdfUtils, clipboard = new gui.Clipboard, clickHandler = new gui.ClickHandler, keyDownHandler = new gui.KeyboardHandler, keyPressHandler = new gui.KeyboardHandler, styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), keyboardMovementsFilter = new core.PositionFilterChain, baseFilter = odtDocument.getPositionFilter(), undoManager = null;
var window = (runtime.getWindow()), odtDocument = session.getOdtDocument(), domUtils = new core.DomUtils, odfUtils = new odf.OdfUtils, clipboard = new gui.Clipboard, clickHandler = new gui.ClickHandler, keyDownHandler = new gui.KeyboardHandler, keyPressHandler = new gui.KeyboardHandler, styleHelper = new gui.StyleHelper(odtDocument.getFormatting()), keyboardMovementsFilter = new core.PositionFilterChain, baseFilter = odtDocument.getPositionFilter(), undoManager = null;
runtime.assert(window !== null, "Expected to be run in an environment which has a global window, like a browser.");
keyboardMovementsFilter.addFilter("BaseFilter", baseFilter);
keyboardMovementsFilter.addFilter("RootFilter", odtDocument.createRootFilter(inputMemberId));
function listenEvent(eventTarget, eventType, eventHandler, includeDirect) {
@ -12258,21 +12279,67 @@ gui.SessionController = function() {
}
return null
}
function findClosestPosition(node) {
var canvasElement = odtDocument.getOdfCanvas().getElement(), newNode = odtDocument.getRootNode(), newOffset = 0, beforeCanvas, iterator;
beforeCanvas = canvasElement.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_PRECEDING;
if(!beforeCanvas) {
iterator = gui.SelectionMover.createPositionIterator(newNode);
iterator.moveToEnd();
newNode = iterator.container();
newOffset = iterator.unfilteredDomOffset()
}
return{node:newNode, offset:newOffset}
}
function getSelection(e) {
var canvasElement = odtDocument.getOdfCanvas().getElement(), selection = window.getSelection(), anchorNode, anchorOffset, focusNode, focusOffset, anchorNodeInsideCanvas, focusNodeInsideCanvas, caretPos, node;
if(selection.anchorNode === null && selection.focusNode === null) {
caretPos = caretPositionFromPoint(e.clientX, e.clientY);
if(!caretPos) {
return null
}
anchorNode = (caretPos.container);
anchorOffset = caretPos.offset;
focusNode = anchorNode;
focusOffset = anchorOffset
}else {
anchorNode = (selection.anchorNode);
anchorOffset = selection.anchorOffset;
focusNode = (selection.focusNode);
focusOffset = selection.focusOffset
}
runtime.assert(anchorNode !== null && focusNode !== null, "anchorNode is null or focusNode is null");
anchorNodeInsideCanvas = domUtils.containsNode(canvasElement, anchorNode);
focusNodeInsideCanvas = domUtils.containsNode(canvasElement, focusNode);
if(!anchorNodeInsideCanvas && !focusNodeInsideCanvas) {
return null
}
if(!anchorNodeInsideCanvas) {
node = findClosestPosition(anchorNode);
anchorNode = node.node;
anchorOffset = node.offset
}
if(!focusNodeInsideCanvas) {
node = findClosestPosition(focusNode);
focusNode = node.node;
focusOffset = node.offset
}
canvasElement.focus();
return{anchorNode:anchorNode, anchorOffset:anchorOffset, focusNode:focusNode, focusOffset:focusOffset}
}
function selectRange(e) {
runtime.setTimeout(function() {
var selection = runtime.getWindow().getSelection(), oldPosition = odtDocument.getCursorPosition(inputMemberId), range, caretPos, stepsToAnchor, stepsToFocus, op;
if(selection.anchorNode === null && selection.focusNode === null) {
caretPos = caretPositionFromPoint(e.clientX, e.clientY);
if(caretPos) {
range = odtDocument.getDOM().createRange();
range.setStart(caretPos.container, caretPos.offset);
range.collapse(true);
selection.addRange(range)
}
var selection = getSelection(e), oldPosition, stepsToAnchor, stepsToFocus, op;
if(selection === null) {
return
}
stepsToAnchor = countStepsToNode(selection.anchorNode, selection.anchorOffset);
stepsToFocus = countStepsToNode(selection.focusNode, selection.focusOffset);
if(selection.focusNode === selection.anchorNode && selection.focusOffset === selection.anchorOffset) {
stepsToFocus = stepsToAnchor
}else {
stepsToFocus = countStepsToNode(selection.focusNode, selection.focusOffset)
}
if(stepsToFocus !== null && stepsToFocus !== 0 || stepsToAnchor !== null && stepsToAnchor !== 0) {
oldPosition = odtDocument.getCursorPosition(inputMemberId);
op = createOpMoveCursor(oldPosition + stepsToAnchor, stepsToFocus - stepsToAnchor);
session.enqueue(op)
}
@ -12282,18 +12349,22 @@ gui.SessionController = function() {
selectRange(e)
}
function selectWord() {
var currentNode, i, c, op, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), cursorNode = odtDocument.getCursor(inputMemberId).getNode(), oldPosition = odtDocument.getCursorPosition(inputMemberId), alphaNumeric = /[A-Za-z0-9]/, stepsToStart = 0, stepsToEnd = 0;
var canvasElement = odtDocument.getOdfCanvas().getElement(), alphaNumeric = /[A-Za-z0-9]/, stepsToStart = 0, stepsToEnd = 0, iterator, cursorNode, oldPosition, currentNode, i, c, op;
if(!domUtils.containsNode(canvasElement, window.getSelection().focusNode)) {
return
}
iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
cursorNode = odtDocument.getCursor(inputMemberId).getNode();
iterator.setUnfilteredPosition(cursorNode, 0);
if(iterator.previousPosition()) {
currentNode = iterator.getCurrentNode();
if(currentNode.nodeType === Node.TEXT_NODE) {
for(i = currentNode.data.length - 1;i >= 0;i -= 1) {
c = currentNode.data[i];
if(alphaNumeric.test(c)) {
stepsToStart -= 1
}else {
if(!alphaNumeric.test(c)) {
break
}
stepsToStart -= 1
}
}
}
@ -12303,25 +12374,31 @@ gui.SessionController = function() {
if(currentNode.nodeType === Node.TEXT_NODE) {
for(i = 0;i < currentNode.data.length;i += 1) {
c = currentNode.data[i];
if(alphaNumeric.test(c)) {
stepsToEnd += 1
}else {
if(!alphaNumeric.test(c)) {
break
}
stepsToEnd += 1
}
}
}
if(stepsToStart !== 0 || stepsToEnd !== 0) {
oldPosition = odtDocument.getCursorPosition(inputMemberId);
op = createOpMoveCursor(oldPosition + stepsToStart, Math.abs(stepsToStart) + Math.abs(stepsToEnd));
session.enqueue(op)
}
}
function selectParagraph() {
var stepsToStart, stepsToEnd, op, iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode()), paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode()), oldPosition = odtDocument.getCursorPosition(inputMemberId);
var canvasElement = odtDocument.getOdfCanvas().getElement(), iterator, paragraphNode, oldPosition, stepsToStart, stepsToEnd, op;
if(!domUtils.containsNode(canvasElement, window.getSelection().focusNode)) {
return
}
paragraphNode = odtDocument.getParagraphElement(odtDocument.getCursor(inputMemberId).getNode());
stepsToStart = odtDocument.getDistanceFromCursor(inputMemberId, paragraphNode, 0);
iterator = gui.SelectionMover.createPositionIterator(odtDocument.getRootNode());
iterator.moveToEndOfNode(paragraphNode);
stepsToEnd = odtDocument.getDistanceFromCursor(inputMemberId, paragraphNode, iterator.unfilteredDomOffset());
if(stepsToStart !== 0 || stepsToEnd !== 0) {
oldPosition = odtDocument.getCursorPosition(inputMemberId);
op = createOpMoveCursor(oldPosition + stepsToStart, Math.abs(stepsToStart) + Math.abs(stepsToEnd));
session.enqueue(op)
}
@ -12540,7 +12617,7 @@ gui.SessionController = function() {
return true
}
function maintainCursorSelection() {
var cursor = odtDocument.getCursor(inputMemberId), selection = runtime.getWindow().getSelection();
var cursor = odtDocument.getCursor(inputMemberId), selection = window.getSelection();
if(cursor) {
selection.removeAllRanges();
selection.addRange(cursor.getSelectedRange().cloneRange())
@ -12583,7 +12660,7 @@ gui.SessionController = function() {
}
}
function handlePaste(e) {
var plainText, window = runtime.getWindow();
var plainText;
if(window.clipboardData && window.clipboardData.getData) {
plainText = window.clipboardData.getData("Text")
}else {
@ -12655,7 +12732,7 @@ gui.SessionController = function() {
listenEvent(canvasElement, "copy", handleCopy);
listenEvent(canvasElement, "beforepaste", handleBeforePaste, true);
listenEvent(canvasElement, "paste", handlePaste);
listenEvent(canvasElement, "mouseup", clickHandler.handleMouseUp);
listenEvent(window, "mouseup", clickHandler.handleMouseUp);
listenEvent(canvasElement, "contextmenu", handleContextMenu);
odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, maintainCursorSelection);
odtDocument.subscribe(ops.OdtDocument.signalOperationExecuted, updateUndoStack);
@ -12679,7 +12756,7 @@ gui.SessionController = function() {
removeEvent(canvasElement, "copy", handleCopy);
removeEvent(canvasElement, "paste", handlePaste);
removeEvent(canvasElement, "beforepaste", handleBeforePaste);
removeEvent(canvasElement, "mouseup", clickHandler.handleMouseUp);
removeEvent(window, "mouseup", clickHandler.handleMouseUp);
removeEvent(canvasElement, "contextmenu", handleContextMenu);
op = new ops.OpRemoveCursor;
op.init({memberid:inputMemberId});
@ -12711,7 +12788,7 @@ gui.SessionController = function() {
return undoManager
};
function init() {
var isMacOS = runtime.getWindow().navigator.appVersion.toLowerCase().indexOf("mac") !== -1, modifier = gui.KeyboardHandler.Modifier, keyCode = gui.KeyboardHandler.KeyCode;
var isMacOS = window.navigator.appVersion.toLowerCase().indexOf("mac") !== -1, modifier = gui.KeyboardHandler.Modifier, keyCode = gui.KeyboardHandler.KeyCode;
keyDownHandler.bind(keyCode.Tab, modifier.None, function() {
insertText("\t");
return true
@ -12779,15 +12856,49 @@ gui.SessionController = function() {
};
return gui.SessionController
}();
ops.UserModel = function UserModel() {
/*
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/
*/
ops.MemberModel = function MemberModel() {
};
ops.UserModel.prototype.getUserDetailsAndUpdates = function(memberId, subscriber) {
ops.MemberModel.prototype.getMemberDetailsAndUpdates = function(memberId, subscriber) {
};
ops.UserModel.prototype.unsubscribeUserDetailsUpdates = function(memberId, subscriber) {
ops.MemberModel.prototype.unsubscribeMemberDetailsUpdates = function(memberId, subscriber) {
};
/*
Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@ -12819,19 +12930,48 @@ ops.UserModel.prototype.unsubscribeUserDetailsUpdates = function(memberId, subsc
@source: http://www.webodf.org/
@source: http://gitorious.org/webodf/webodf/
*/
ops.TrivialUserModel = function TrivialUserModel() {
var users = {};
users.bob = {memberid:"bob", fullname:"Bob Pigeon", color:"red", imageurl:"avatar-pigeon.png"};
users.alice = {memberid:"alice", fullname:"Alice Bee", color:"green", imageurl:"avatar-flower.png"};
users.you = {memberid:"you", fullname:"I, Robot", color:"blue", imageurl:"avatar-joe.png"};
this.getUserDetailsAndUpdates = function(memberId, subscriber) {
var userid = memberId.split("___")[0];
subscriber(memberId, users[userid] || null)
ops.TrivialMemberModel = function TrivialMemberModel() {
this.getMemberDetailsAndUpdates = function(memberId, subscriber) {
subscriber(memberId, null)
};
this.unsubscribeUserDetailsUpdates = function(memberId, subscriber) {
this.unsubscribeMemberDetailsUpdates = function(memberId, subscriber) {
}
};
ops.NowjsUserModel = function NowjsUserModel(server) {
/*
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/
*/
ops.NowjsMemberModel = function NowjsMemberModel(server) {
var cachedUserData = {}, memberDataSubscribers = {}, nowObject = server.getNowObject();
function userIdFromMemberId(memberId) {
return memberId.split("___")[0]
@ -12846,7 +12986,7 @@ ops.NowjsUserModel = function NowjsUserModel(server) {
}
}
}
this.getUserDetailsAndUpdates = function(memberId, subscriber) {
this.getMemberDetailsAndUpdates = function(memberId, subscriber) {
var userId = userIdFromMemberId(memberId), userData = cachedUserData[userId], subscribers = memberDataSubscribers[userId] || [], i;
memberDataSubscribers[userId] = subscribers;
runtime.assert(subscriber !== undefined, "missing callback");
@ -12856,7 +12996,7 @@ ops.NowjsUserModel = function NowjsUserModel(server) {
}
}
if(i < subscribers.length) {
runtime.log("double subscription request for " + memberId + " in NowjsUserModel::getUserDetailsAndUpdates")
runtime.log("double subscription request for " + memberId + " in NowjsMemberModel::getMemberDetailsAndUpdates")
}else {
subscribers.push({memberId:memberId, subscriber:subscriber});
if(subscribers.length === 1) {
@ -12867,7 +13007,7 @@ ops.NowjsUserModel = function NowjsUserModel(server) {
subscriber(memberId, userData)
}
};
this.unsubscribeUserDetailsUpdates = function(memberId, subscriber) {
this.unsubscribeMemberDetailsUpdates = function(memberId, subscriber) {
var i, userId = userIdFromMemberId(memberId), subscribers = memberDataSubscribers[userId];
runtime.assert(subscriber !== undefined, "missing subscriber parameter or null");
runtime.assert(subscribers, "tried to unsubscribe when no one is subscribed ('" + memberId + "')");
@ -12926,61 +13066,53 @@ ops.NowjsUserModel = function NowjsUserModel(server) {
@source: http://www.webodf.org/
@source: http://gitorious.org/webodf/webodf/
*/
ops.PullBoxUserModel = function PullBoxUserModel(server) {
var cachedUserData = {}, memberDataSubscribers = {}, serverPullingActivated = false, pullingIntervall = 2E4;
function userIdFromMemberId(memberId) {
return memberId.split("___")[0]
}
function cacheUserDatum(userData) {
ops.PullBoxMemberModel = function PullBoxMemberModel(sessionId, server) {
var cachedMemberData = {}, memberDataSubscribers = {}, serverPullingActivated = false, pullingIntervall = 2E4;
function cacheMemberDatum(memberData) {
var subscribers, i;
subscribers = memberDataSubscribers[userData.userid];
subscribers = memberDataSubscribers[memberData.memberid];
if(subscribers) {
cachedUserData[userData.userid] = userData;
cachedMemberData[memberData.memberid] = memberData;
for(i = 0;i < subscribers.length;i += 1) {
subscribers[i].subscriber(subscribers[i].memberId, userData)
}
}
}
function pullUserData() {
var i, userIds = [];
for(i in memberDataSubscribers) {
if(memberDataSubscribers.hasOwnProperty(i)) {
userIds.push(i)
}
}
runtime.log("user-list request for : " + userIds.join(","));
server.call({command:"user-list", args:{user_ids:userIds}}, function(responseData) {
var response = (runtime.fromJson(responseData)), userList, newUserData, oldUserData;
runtime.log("user-list reply: " + responseData);
if(response.hasOwnProperty("userdata_list")) {
userList = response.userdata_list;
for(i = 0;i < userList.length;i += 1) {
newUserData = {userid:userList[i].uid, fullname:userList[i].fullname, imageurl:"/user/" + userList[i].avatarId + "/avatar.png", color:userList[i].color};
oldUserData = cachedUserData.hasOwnProperty(userList[i].uid) ? cachedUserData[userList[i].uid] : null;
if(!oldUserData || oldUserData.fullname !== newUserData.fullname || oldUserData.imageurl !== newUserData.imageurl || oldUserData.color !== newUserData.color) {
cacheUserDatum(newUserData)
subscribers[i](memberData.memberid, memberData)
}
}
}
function pullMemberData() {
var i, memberIds = Object.keys(memberDataSubscribers);
runtime.log("member-list request for : " + memberIds.join(","));
server.call({command:"query_memberdata_list", args:{es_id:sessionId, member_ids:memberIds}}, function(responseData) {
var response = (runtime.fromJson(responseData)), memberDataList, newMemberData, oldMemberData;
runtime.log("member-list reply: " + responseData);
if(response.hasOwnProperty("memberdata_list")) {
memberDataList = response.memberdata_list;
for(i = 0;i < memberDataList.length;i += 1) {
newMemberData = {memberid:memberDataList[i].member_id, fullname:memberDataList[i].display_name, imageurl:memberDataList[i].avatar_url, color:memberDataList[i].color};
oldMemberData = cachedMemberData.hasOwnProperty(newMemberData.memberid) ? cachedMemberData[newMemberData.memberid] : null;
if(!oldMemberData || oldMemberData.fullname !== newMemberData.fullname || oldMemberData.imageurl !== newMemberData.imageurl || oldMemberData.color !== newMemberData.color) {
cacheMemberDatum(newMemberData)
}
}
}else {
runtime.log("Meh, userlist data broken: " + responseData)
runtime.log("Meh, memberdata list broken: " + responseData)
}
})
}
function periodicPullUserData() {
function periodicPullMemberData() {
if(!serverPullingActivated) {
return
}
pullUserData();
runtime.setTimeout(periodicPullUserData, pullingIntervall)
pullMemberData();
runtime.setTimeout(periodicPullMemberData, pullingIntervall)
}
function activatePeriodicUserDataPulling() {
function activatePeriodicMemberDataPulling() {
if(serverPullingActivated) {
return
}
serverPullingActivated = true;
runtime.setTimeout(periodicPullUserData, pullingIntervall)
runtime.setTimeout(periodicPullMemberData, pullingIntervall)
}
function deactivatePeriodicUserDataPulling() {
function deactivatePeriodicMemberDataPulling() {
var key;
if(!serverPullingActivated) {
return
@ -12992,35 +13124,35 @@ ops.PullBoxUserModel = function PullBoxUserModel(server) {
}
serverPullingActivated = false
}
this.getUserDetailsAndUpdates = function(memberId, subscriber) {
var userId = userIdFromMemberId(memberId), userData = cachedUserData[userId], subscribers = memberDataSubscribers[userId] || [], i;
memberDataSubscribers[userId] = subscribers;
this.getMemberDetailsAndUpdates = function(memberId, subscriber) {
var memberData = cachedMemberData[memberId], subscribers = memberDataSubscribers[memberId] || [], i;
memberDataSubscribers[memberId] = subscribers;
runtime.assert(subscriber !== undefined, "missing callback");
for(i = 0;i < subscribers.length;i += 1) {
if(subscribers[i].subscriber === subscriber && subscribers[i].memberId === memberId) {
if(subscribers[i] === subscriber) {
break
}
}
if(i < subscribers.length) {
runtime.log("double subscription request for " + memberId + " in PullBoxUserModel::getUserDetailsAndUpdates")
runtime.log("double subscription request for " + memberId + " in PullBoxMemberModel::getMemberDetailsAndUpdates")
}else {
subscribers.push({memberId:memberId, subscriber:subscriber});
subscribers.push(subscriber);
if(subscribers.length === 1) {
pullUserData()
pullMemberData()
}
}
if(userData) {
subscriber(memberId, userData)
if(memberData) {
subscriber(memberId, memberData)
}
activatePeriodicUserDataPulling()
activatePeriodicMemberDataPulling()
};
this.unsubscribeUserDetailsUpdates = function(memberId, subscriber) {
var i, userId = userIdFromMemberId(memberId), subscribers = memberDataSubscribers[userId];
this.unsubscribeMemberDetailsUpdates = function(memberId, subscriber) {
var i, subscribers = memberDataSubscribers[memberId];
runtime.assert(subscriber !== undefined, "missing subscriber parameter or null");
runtime.assert(subscribers, "tried to unsubscribe when no one is subscribed ('" + memberId + "')");
if(subscribers) {
for(i = 0;i < subscribers.length;i += 1) {
if(subscribers[i].subscriber === subscriber && subscribers[i].memberId === memberId) {
if(subscribers[i] === subscriber) {
break
}
}
@ -13028,9 +13160,9 @@ ops.PullBoxUserModel = function PullBoxUserModel(server) {
subscribers.splice(i, 1);
if(subscribers.length === 0) {
runtime.log("no more subscribers for: " + memberId);
delete memberDataSubscribers[userId];
delete cachedUserData[userId];
deactivatePeriodicUserDataPulling()
delete memberDataSubscribers[memberId];
delete cachedMemberData[memberId];
deactivatePeriodicMemberDataPulling()
}
}
};
@ -13193,14 +13325,7 @@ ops.NowjsOperationRouter = function NowjsOperationRouter(sessionId, memberid, se
done_cb()
}
})
};
function init() {
nowObject.memberid = memberid;
nowObject.joinSession(sessionId, function(sessionJoinSuccess) {
runtime.assert(sessionJoinSuccess, "Trying to join a session which does not exists or where we are already in")
})
}
init()
};
/*
@ -13336,10 +13461,10 @@ ops.PullBoxOperationRouter = function PullBoxOperationRouter(sessionId, memberId
syncLock = true;
syncedClientOpspecs = unsyncedClientOpspecQueue;
unsyncedClientOpspecQueue = [];
server.call({command:"sync-ops", args:{es_id:sessionId, member_id:memberId, seq_head:String(lastServerSeq), client_ops:syncedClientOpspecs}}, function(responseData) {
server.call({command:"sync_ops", args:{es_id:sessionId, member_id:memberId, seq_head:String(lastServerSeq), client_ops:syncedClientOpspecs}}, function(responseData) {
var shouldRetryInstantly = false, response = (runtime.fromJson(responseData));
runtime.log("sync-ops reply: " + responseData);
if(response.result === "newOps") {
if(response.result === "new_ops") {
if(response.ops.length > 0) {
if(unsyncedClientOpspecQueue.length === 0) {
receiveOpSpecsFromNetwork(compressOpSpecs(response.ops))
@ -13347,18 +13472,18 @@ ops.PullBoxOperationRouter = function PullBoxOperationRouter(sessionId, memberId
runtime.log("meh, have new ops locally meanwhile, have to do transformations.");
hasUnresolvableConflict = !handleOpsSyncConflict(compressOpSpecs(response.ops))
}
lastServerSeq = response.headSeq
lastServerSeq = response.head_seq
}
}else {
if(response.result === "added") {
runtime.log("All added to server");
lastServerSeq = response.headSeq
lastServerSeq = response.head_seq
}else {
if(response.result === "conflict") {
unsyncedClientOpspecQueue = syncedClientOpspecs.concat(unsyncedClientOpspecQueue);
runtime.log("meh, server has new ops meanwhile, have to do transformations.");
hasUnresolvableConflict = !handleOpsSyncConflict(compressOpSpecs(response.ops));
lastServerSeq = response.headSeq;
lastServerSeq = response.head_seq;
if(!hasUnresolvableConflict) {
shouldRetryInstantly = true
}
@ -13423,15 +13548,7 @@ ops.PullBoxOperationRouter = function PullBoxOperationRouter(sessionId, memberId
playbackFunction(timedOp);
unsyncedClientOpspecQueue.push(opspec);
triggerPushingOps()
};
function init() {
server.call({command:"join-session", args:{session_id:sessionId, member_id:memberId}}, function(responseData) {
var response = Boolean(runtime.fromJson(responseData));
runtime.log("join-session reply: " + responseData);
runtime.assert(response, "Trying to join a session which does not exists or where we are already in")
})
}
init()
};
gui.EditInfoHandle = function EditInfoHandle(parentElement) {
var edits = [], handle, document = (parentElement.ownerDocument), htmlns = document.documentElement.namespaceURI, editinfons = "urn:webodf:names:editinfo";
@ -13561,7 +13678,7 @@ gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
};
/*
Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@ -13594,7 +13711,7 @@ gui.EditInfoMarker = function EditInfoMarker(editInfo, initialVisibility) {
@source: http://gitorious.org/webodf/webodf/
*/
runtime.loadClass("gui.Caret");
runtime.loadClass("ops.TrivialUserModel");
runtime.loadClass("ops.TrivialMemberModel");
runtime.loadClass("ops.EditInfo");
runtime.loadClass("gui.EditInfoMarker");
gui.SessionViewOptions = function() {
@ -13604,7 +13721,7 @@ gui.SessionViewOptions = function() {
};
gui.SessionView = function() {
function configOption(userValue, defaultValue) {
return userValue !== undefined ? userValue : defaultValue
return userValue !== undefined ? Boolean(userValue) : defaultValue
}
function SessionView(viewOptions, session, caretManager) {
var avatarInfoStyles, editInfons = "urn:webodf:names:editinfo", editInfoMap = {}, showEditInfoMarkers = configOption(viewOptions.editInfoMarkersInitiallyVisible, true), showCaretAvatars = configOption(viewOptions.caretAvatarsInitiallyVisible, true), blinkOnRangeSelect = configOption(viewOptions.caretBlinksOnRangeSelect, true);
@ -13708,26 +13825,26 @@ gui.SessionView = function() {
this.getCaret = function(memberid) {
return caretManager.getCaret(memberid)
};
function renderMemberData(memberId, userData) {
function renderMemberData(memberId, memberData) {
var caret = caretManager.getCaret(memberId);
if(userData === undefined) {
runtime.log('UserModel sent undefined data for member "' + memberId + '".');
if(memberData === undefined) {
runtime.log('MemberModel sent undefined data for member "' + memberId + '".');
return
}
if(userData === null) {
userData = {memberid:memberId, fullname:"Unknown Identity", color:"black", imageurl:"avatar-joe.png"}
if(memberData === null) {
memberData = {memberid:memberId, fullname:"Unknown Identity", color:"black", imageurl:"avatar-joe.png"}
}
if(caret) {
caret.setAvatarImageUrl(userData.imageurl);
caret.setColor(userData.color)
caret.setAvatarImageUrl(memberData.imageurl);
caret.setColor(memberData.color)
}
setAvatarInfoStyle(memberId, userData.fullname, userData.color)
setAvatarInfoStyle(memberId, memberData.fullname, memberData.color)
}
function onCursorAdded(cursor) {
var memberId = cursor.getMemberId(), userModel = session.getUserModel();
var memberId = cursor.getMemberId(), memberModel = session.getMemberModel();
caretManager.registerCursor(cursor, showCaretAvatars, blinkOnRangeSelect);
renderMemberData(memberId, null);
userModel.getUserDetailsAndUpdates(memberId, renderMemberData);
memberModel.getMemberDetailsAndUpdates(memberId, renderMemberData);
runtime.log("+++ View here +++ eagerly created an Caret for '" + memberId + "'! +++")
}
function onCursorRemoved(memberid) {
@ -13739,7 +13856,7 @@ gui.SessionView = function() {
}
}
if(!hasMemberEditInfo) {
session.getUserModel().unsubscribeUserDetailsUpdates(memberid, renderMemberData)
session.getMemberModel().unsubscribeMemberDetailsUpdates(memberid, renderMemberData)
}
}
function init() {
@ -13762,7 +13879,7 @@ gui.SessionView = function() {
}();
/*
Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
@licstart
The JavaScript code in this page is free software: you can redistribute it
@ -13797,35 +13914,44 @@ gui.SessionView = function() {
runtime.loadClass("gui.Caret");
gui.CaretManager = function CaretManager(sessionController) {
var carets = {};
function getCaret(memberId) {
return carets.hasOwnProperty(memberId) ? carets[memberId] : null
}
function getCanvasElement() {
return sessionController.getSession().getOdtDocument().getOdfCanvas().getElement()
}
function removeCaret(memberId) {
if(memberId === sessionController.getInputMemberId()) {
getCanvasElement().removeAttribute("tabindex", 0)
getCanvasElement().removeAttribute("tabindex")
}
delete carets[memberId]
}
function refreshCaret(cursor) {
var caret = carets[cursor.getMemberId()];
if(caret) {
caret.refreshCursor()
function refreshLocalCaretBlinking(cursor) {
var caret, memberId = cursor.getMemberId();
if(memberId === sessionController.getInputMemberId()) {
caret = getCaret(memberId);
if(caret) {
caret.refreshCursorBlinking()
}
}
}
function ensureLocalCaretVisible(info) {
var caret = carets[info.memberId];
if(info.memberId === sessionController.getInputMemberId() && caret) {
caret.ensureVisible()
var caret;
if(info.memberId === sessionController.getInputMemberId()) {
caret = getCaret(info.memberId);
if(caret) {
caret.ensureVisible()
}
}
}
function focusLocalCaret() {
var caret = carets[sessionController.getInputMemberId()];
var caret = getCaret(sessionController.getInputMemberId());
if(caret) {
caret.setFocus()
}
}
function blurLocalCaret() {
var caret = carets[sessionController.getInputMemberId()];
var caret = getCaret(sessionController.getInputMemberId());
if(caret) {
caret.removeFocus()
}
@ -13841,9 +13967,7 @@ gui.CaretManager = function CaretManager(sessionController) {
}
return caret
};
this.getCaret = function(memberid) {
return carets[memberid]
};
this.getCaret = getCaret;
this.getCarets = function() {
return Object.keys(carets).map(function(memberid) {
return carets[memberid]
@ -13852,7 +13976,7 @@ gui.CaretManager = function CaretManager(sessionController) {
function init() {
var session = sessionController.getSession(), odtDocument = session.getOdtDocument(), canvasElement = getCanvasElement();
odtDocument.subscribe(ops.OdtDocument.signalParagraphChanged, ensureLocalCaretVisible);
odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, refreshCaret);
odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, refreshLocalCaretBlinking);
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, removeCaret);
canvasElement.onfocus = focusLocalCaret;
canvasElement.onblur = blurLocalCaret
@ -15038,14 +15162,14 @@ ops.OdtDocument.signalUndoStackChanged = "undo/changed";
@source: http://www.webodf.org/
@source: http://gitorious.org/webodf/webodf/
*/
runtime.loadClass("ops.TrivialUserModel");
runtime.loadClass("ops.TrivialMemberModel");
runtime.loadClass("ops.TrivialOperationRouter");
runtime.loadClass("ops.OperationFactory");
runtime.loadClass("ops.OdtDocument");
ops.Session = function Session(odfCanvas) {
var self = this, operationFactory = new ops.OperationFactory, odtDocument = new ops.OdtDocument(odfCanvas), userModel = new ops.TrivialUserModel, operationRouter = null;
this.setUserModel = function(uModel) {
userModel = uModel
var self = this, operationFactory = new ops.OperationFactory, odtDocument = new ops.OdtDocument(odfCanvas), memberModel = new ops.TrivialMemberModel, operationRouter = null;
this.setMemberModel = function(uModel) {
memberModel = uModel
};
this.setOperationFactory = function(opFactory) {
operationFactory = opFactory;
@ -15061,8 +15185,8 @@ ops.Session = function Session(odfCanvas) {
});
opRouter.setOperationFactory(operationFactory)
};
this.getUserModel = function() {
return userModel
this.getMemberModel = function() {
return memberModel
};
this.getOperationFactory = function() {
return operationFactory

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