', {
+ 'class': NEWPAD_CLS + " dropdown-bar"
+ }).appendTo(toolbar.$top);*/
+ var $newPad = toolbar.$top.find('.'+NEWPAD_CLS).show();
+
+ var pads_options = [];
+ Config.availablePadTypes.forEach(function (p) {
+ if (p === 'drive') { return; }
+ if (!Cryptpad.isLoggedIn() && Config.registeredOnlyTypes &&
+ Config.registeredOnlyTypes.indexOf(p) !== -1) { return; }
+ pads_options.push({
+ tag: 'a',
+ attributes: {
+ 'target': '_blank',
+ 'href': '/' + p + '/',
+ },
+ content: $('').append(Cryptpad.getIcon(p)).html() + Messages.type[p]
+ });
+ });
+ var dropdownConfig = {
+ text: '', // Button initial text
+ options: pads_options, // Entries displayed in the menu
+ container: $newPad,
+ left: true,
+ feedback: /drive/.test(window.location.pathname)?
+ 'DRIVE_NEWPAD': 'NEWPAD',
+ };
+ var $newPadBlock = Cryptpad.createDropdown(dropdownConfig);
+ $newPadBlock.find('button').attr('title', Messages.newButtonTitle);
+ $newPadBlock.find('button').addClass('fa fa-th');
+ return $newPadBlock;
+ };
+
+ var createUserAdmin = function (toolbar, config) {
+ var $userAdmin = toolbar.$userAdmin.find('.'+USERADMIN_CLS).show();
+ var userMenuCfg = {
+ $initBlock: $userAdmin
+ };
+ if (!config.hideDisplayName) { // TODO: config.userAdmin.hideDisplayName?
+ $.extend(true, userMenuCfg, {
+ displayNameCls: USERNAME_CLS,
+ changeNameButtonCls: USERBUTTON_CLS,
+ });
+ }
+ if (config.readOnly !== 1) {
+ userMenuCfg.displayName = 1;
+ userMenuCfg.displayChangeName = 1;
+ }
+ Cryptpad.createUserAdminMenu(userMenuCfg);
+ $userAdmin.find('button').attr('title', Messages.userAccountButton);
+
+ var $userButton = toolbar.$userNameButton = $userAdmin.find('a.' + USERBUTTON_CLS);
+ $userButton.click(function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ Cryptpad.getLastName(function (err, lastName) {
+ if (err) { return void console.error("Cannot get last name", err); }
+ Cryptpad.prompt(Messages.changeNamePrompt, lastName || '', function (newName) {
+ if (newName === null && typeof(lastName) === "string") { return; }
+ if (newName === null) { newName = ''; }
+ else { Cryptpad.feedback('NAME_CHANGED'); }
+ Cryptpad.setAttribute('username', newName, function (err) {
+ if (err) {
+ console.log("Couldn't set username");
+ console.error(err);
+ return;
+ }
+ Cryptpad.changeDisplayName(newName, true);
+ });
+ });
+ });
+ });
+ Cryptpad.onDisplayNameChanged(function () {
+ window.setTimeout(function () {
+ Cryptpad.findCancelButton().click();
+ if (config.userList) {
+ updateUserList(toolbar, config);
+ return;
+ }
+ updateDisplayName(toolbar, config);
+ }, 0);
+ });
+
+ updateDisplayName(toolbar, config);
+
+ return $userAdmin;
+ };
+
+ // Events
+ var initClickEvents = function (toolbar, config) {
+ var removeDropdowns = function () {
+ toolbar.$toolbar.find('.cryptpad-dropdown').hide();
+ };
+ var cancelEditTitle = function (e) {
+ // Now we want to apply the title even if we click somewhere else
+ if ($(e.target).parents('.' + TITLE_CLS).length || !toolbar.title) {
+ return;
+ }
+ var $title = toolbar.title;
+ if (!$title.find('input').is(':visible')) { return; }
+
+ // Press enter
+ var ev = $.Event("keyup");
+ ev.which = 13;
+ $title.find('input').trigger(ev);
+ };
+ // Click in the main window
+ var w = config.ifrw || window;
+ $(w).on('click', removeDropdowns);
+ $(w).on('click', cancelEditTitle);
+ // Click in iframes
+ try {
+ if (w.$ && w.$('iframe').length) {
+ config.ifrw.$('iframe').each(function (i, el) {
+ $(el.contentWindow).on('click', removeDropdowns);
+ $(el.contentWindow).on('click', cancelEditTitle);
+ });
+ }
+ } catch (e) {
+ // empty try catch in case this iframe is problematic
+ }
+ };
+
+ // Notifications
+ var initNotifications = function (toolbar, config) {
+ // Display notifications when users are joining/leaving the session
+ var oldUserData;
+ if (!config.userList || !config.userList.list || !config.userList.userNetfluxId) { return; }
+ var userList = config.userList.list;
+ var userNetfluxId = config.userList.userNetfluxId;
+ if (typeof Cryptpad !== "undefined" && userList) {
+ var notify = function(type, name, oldname) {
+ // type : 1 (+1 user), 0 (rename existing user), -1 (-1 user)
+ if (typeof name === "undefined") { return; }
+ name = name || Messages.anonymous;
+ switch(type) {
+ case 1:
+ Cryptpad.log(Messages._getKey("notifyJoined", [name]));
+ break;
+ case 0:
+ oldname = (oldname === "") ? Messages.anonymous : oldname;
+ Cryptpad.log(Messages._getKey("notifyRenamed", [oldname, name]));
+ break;
+ case -1:
+ Cryptpad.log(Messages._getKey("notifyLeft", [name]));
+ break;
+ default:
+ console.log("Invalid type of notification");
+ break;
+ }
+ };
+
+ var userPresent = function (id, user, data) {
+ if (!(user && user.uid)) {
+ console.log('no uid');
+ return 0;
+ }
+ if (!data) {
+ console.log('no data');
+ return 0;
+ }
+
+ var count = 0;
+ Object.keys(data).forEach(function (k) {
+ if (data[k] && data[k].uid === user.uid) { count++; }
+ });
+ return count;
+ };
+
+ userList.change.push(function (newdata) {
+ // Notify for disconnected users
+ if (typeof oldUserData !== "undefined") {
+ for (var u in oldUserData) {
+ // if a user's uid is still present after having left, don't notify
+ if (userList.users.indexOf(u) === -1) {
+ var temp = JSON.parse(JSON.stringify(oldUserData[u]));
+ delete oldUserData[u];
+ if (userPresent(u, temp, newdata || oldUserData) < 1) {
+ notify(-1, temp.name);
+ }
+ }
+ }
+ }
+ // Update the "oldUserData" object and notify for new users and names changed
+ if (typeof newdata === "undefined") { return; }
+ if (typeof oldUserData === "undefined") {
+ oldUserData = JSON.parse(JSON.stringify(newdata));
+ return;
+ }
+ if (config.readOnly === 0 && !oldUserData[userNetfluxId]) {
+ oldUserData = JSON.parse(JSON.stringify(newdata));
+ return;
+ }
+ for (var k in newdata) {
+ if (k !== userNetfluxId && userList.users.indexOf(k) !== -1) {
+ if (typeof oldUserData[k] === "undefined") {
+ // if the same uid is already present in the userdata, don't notify
+ if (!userPresent(k, newdata[k], oldUserData)) {
+ notify(1, newdata[k].name);
+ }
+ } else if (oldUserData[k].name !== newdata[k].name) {
+ notify(0, newdata[k].name, oldUserData[k].name);
+ }
+ }
+ }
+ oldUserData = JSON.parse(JSON.stringify(newdata));
+ });
+ }
+ };
+
+
+
+ // Main
+
+ Bar.create = function (cfg) {
+ var config = cfg || {};
+ Cryptpad = config.common;
+ Messages = Cryptpad.Messages;
+ config.readOnly = (typeof config.readOnly !== "undefined") ? (config.readOnly ? 1 : 0) : -1;
+ config.displayed = config.displayed || [];
+
+ var toolbar = {};
+
+ toolbar.connected = false;
+ toolbar.firstConnection = true;
+
+ var $toolbar = toolbar.$toolbar = createRealtimeToolbar(config);
+ toolbar.$leftside = $toolbar.find('.'+Bar.constants.leftside);
+ toolbar.$rightside = $toolbar.find('.'+Bar.constants.rightside);
+ toolbar.$drawer = $toolbar.find('.'+Bar.constants.drawer);
+ toolbar.$top = $toolbar.find('.'+Bar.constants.top);
+ toolbar.$history = $toolbar.find('.'+Bar.constants.history);
+
+ toolbar.$userAdmin = $toolbar.find('.'+Bar.constants.userAdmin);
+
+ // Create the subelements
+ var tb = {};
+ tb['userlist'] = createUserList;
+ tb['share'] = createShare;
+ tb['fileshare'] = createFileShare;
+ tb['title'] = createTitle;
+ tb['pageTitle'] = createPageTitle;
+ tb['lag'] = $.noop;
+ tb['spinner'] = createSpinner;
+ tb['state'] = $.noop;
+ tb['limit'] = createLimit;
+ tb['upgrade'] = $.noop;
+ tb['newpad'] = createNewPad;
+ tb['useradmin'] = createUserAdmin;
+
+ var addElement = toolbar.addElement = function (arr, additionnalCfg, init) {
+ if (typeof additionnalCfg === "object") { $.extend(true, config, additionnalCfg); }
+ arr.forEach(function (el) {
+ if (typeof el !== "string" || !el.trim()) { return; }
+ if (typeof tb[el] === "function") {
+ if (!init && config.displayed.indexOf(el) !== -1) { return; } // Already done
+ toolbar[el] = tb[el](toolbar, config);
+ if (!init) { config.displayed.push(el); }
+ }
+ });
+ };
+
+ addElement(config.displayed, {}, true);
+ initUserList(toolbar, config);
+
+ toolbar['linkToMain'] = createLinkToMain(toolbar, config);
+
+ if (!config.realtime) { toolbar.connected = true; }
+
+ initClickEvents(toolbar, config);
+ initNotifications(toolbar, config);
+
+ var failed = toolbar.failed = function () {
+ toolbar.connected = false;
+
+ if (toolbar.spinner) {
+ toolbar.spinner.text(Messages.disconnected);
+ }
+ //checkLag(toolbar, config);
+ };
+ toolbar.reconnecting = function (userId) {
+ if (config.userList) { config.userList.userNetfluxId = userId; }
+ toolbar.connected = false;
+ if (toolbar.spinner) {
+ toolbar.spinner.text(Messages.reconnecting);
+ }
+ //checkLag(toolbar, config);
+ };
+
+ // On log out, remove permanently the realtime elements of the toolbar
+ Cryptpad.onLogout(function () {
+ failed();
+ if (toolbar.useradmin) { toolbar.useradmin.hide(); }
+ if (toolbar.userlist) { toolbar.userlist.hide(); }
+ });
+
+ return toolbar;
+ };
+
+ return Bar;
+});
diff --git a/www/pad2/main.js b/www/pad2/main.js
index e4874a532..d2f72835e 100644
--- a/www/pad2/main.js
+++ b/www/pad2/main.js
@@ -4,7 +4,7 @@ define([
'/bower_components/chainpad-crypto/crypto.js',
'/common/sframe-chainpad-netflux-inner.js',
'/bower_components/hyperjson/hyperjson.js',
- '/common/toolbar2.js',
+ '/common/toolbar3.js',
'/common/cursor.js',
'/bower_components/chainpad-json-validator/json-ot.js',
'/common/TypingTests.js',
@@ -470,10 +470,24 @@ define([
realtimeOptions.onInit = function (info) {
console.log('onInit');
+ var configTb = {
+ displayed: ['userlist'],
+ userList: cpNfInner.metadataMgr,
+ readOnly: readOnly,
+ ifrw: window,
+ realtime: info.realtime,
+ common: Cryptpad,
+ $container: $bar,
+ $contentContainer: $('#cke_1_contents'),
+ };
+ toolbar = info.realtime.toolbar = Toolbar.create(configTb);
// TODO
return;
- UserList = Cryptpad.createUserList(info, realtimeOptions.onLocal, Cryptget, Cryptpad);
+ // TODO UserList not needed anymore?
+ // --> selectTemplate
+ // --> select username on first visit
+ //UserList = Cryptpad.createUserList(info, realtimeOptions.onLocal, Cryptget, Cryptpad);
var titleCfg = { getHeadingText: getHeadingText };
Title = Cryptpad.createTitle(titleCfg, realtimeOptions.onLocal, Cryptpad);
@@ -651,6 +665,7 @@ define([
if (readOnly) { return; }
//TODO UserList.getLastName(toolbar.$userNameButton, newPad);
+ onLocal();
editor.focus();
if (newPad) {
cursor.setToEnd();