', {
- 'class': 'text-cell',
- })
- .append($edit)
- .append($option)
- .append($remove);
+ if (isKeyup) {
+ console.log("Keyup!");
+ }
- proxy.table.rows[id] = value || "";
- addIfAbsent(proxy.table.rowsOrder, id);
+ if (!target) { return void console.log("NO TARGET"); }
- var $row = table.addRow($wrapper, Checkbox, id);
+ var nodeName = target && target.nodeName;
- if (module.ready) {
- scrollDown($row.height());
+ if (!$(target).parents('#table tbody').length || $(target).hasClass('edit')) {
+ hideInputs(e);
}
- return $option;
+ switch (nodeName) {
+ case 'INPUT':
+ handleInput(target);
+ break;
+ case 'SPAN':
+ //case 'LABEL':
+ handleSpan(target);
+ break;
+ case undefined:
+ //console.error(new Error("C'est pas possible!"));
+ break;
+ default:
+ console.log(target, nodeName);
+ break;
+ }
};
- $('#adduser').click(function () {
- if (!module.isEditable) { return; }
- var id = coluid();
-
- var msg = Messages.poll_addUser;
- Cryptpad.prompt(msg, "", function (name) {
- if (!(name && name.trim())) { return; }
- makeUser(module.rt.proxy, id, name).val(name);
- makeUserEditable(id, true).focus();
- });
- });
-
- $('#addoption').click(function () {
- if (!module.isEditable) { return; }
- var id = rowuid();
+ /*
+ Make sure that the realtime data structure has all the required fields
+ */
+ var prepareProxy = function (proxy, schema) {
+ if (proxy && proxy.version === 1) { return; }
+ console.log("Configuring proxy schema...");
- var msg = Messages.poll_addOption;
- Cryptpad.prompt(msg, "", function (option) {
- if (option === null || !option) { return; }
- makeOption(module.rt.proxy, id, option).val(option).focus();
- });
- //makeOption(module.rt.proxy, id).focus();
- });
+ proxy.info = schema.info;
+ proxy.table = schema.table;
+ proxy.version = 1;
+ };
- Wizard.$getOptions.click(function () {
- Cryptpad.confirm(Messages.wizardConfirm, function (yes) {
- if (!yes) { return; }
- var options = Wizard.computeSlots(function (a, b) {
- return a + ' ('+ b + ')';
- });
- var proxy = module.rt.proxy;
+ /*
- options.forEach(function (text) {
- var id = rowuid();
- makeOption(proxy, id, text).val(text);
- });
- Wizard.hide();
+ */
+ var publish = APP.publish = function (bool) {
+ if (!APP.ready) { return; }
+ if (APP.proxy.published !== bool) {
+ APP.proxy.published = bool;
+ }
+ setTablePublished(bool);
+ ['textarea'].forEach(function (sel) {
+ $(sel).attr('disabled', bool);
});
- });
-
- // notifications
- var unnotify = function () {
- if (!(module.tabNotification &&
- typeof(module.tabNotification.cancel) === 'function')) { return; }
- module.tabNotification.cancel();
};
- var notify = function () {
- if (!(Visible.isSupported() && !Visible.currently())) { return; }
- unnotify();
- module.tabNotification = Notify.tab(1000, 10);
- };
+ var userData = APP.userData = {}; // List of pretty names for all users (mapped with their ID)
+ var userList; // List of users still connected to the channel (server IDs)
+ var addToUserData = function(data) {
+ var users = userList ? userList.users : undefined;
+ //var userData = APP.proxy.info.userData;
+ for (var attrname in data) { userData[attrname] = data[attrname]; }
- var updateTitle = function (newTitle) {
- if (newTitle === document.title) { return; }
- // Change the title now, and set it back to the old value if there is an error
- var oldTitle = document.title;
- document.title = newTitle;
- Cryptpad.setPadTitle(newTitle, function (err, data) {
- if (err) {
- console.log("Couldn't set pad title");
- console.error(err);
- document.title = oldTitle;
- return;
- }
- });
- };
+ if (users && users.length) {
+ for (var userKey in userData) {
+ if (users.indexOf(userKey) === -1) { delete userData[userKey]; }
+ }
+ }
- // don't make changes until the interface is ready
- setEditable(false);
+ if(userList && typeof userList.onChange === "function") {
+ userList.onChange(userData);
+ }
- var ready = function (info) {
- module.users = info.userList.users;
+ APP.proxy.info.userData = userData;
+ };
- console.log("Your realtime object is ready");
- module.ready = true;
+ //var myData = {};
+ var getLastName = function (cb) {
+ Cryptpad.getAttribute('username', function (err, userName) {
+ cb(err, userName || '');
+ });
+ };
- var proxy = module.rt.proxy;
- var First = false;
+ var setName = APP.setName = function (newName) {
+ if (typeof(newName) !== 'string') { return; }
+ var myUserNameTemp = Cryptpad.fixHTML(newName.trim());
+ if(myUserNameTemp.length > 32) {
+ myUserNameTemp = myUserNameTemp.substr(0, 32);
+ }
+ var myUserName = myUserNameTemp;
+ var myID = APP.myID;
+ var myData = {};
+ myData[myID] = {
+ name: myUserName
+ };
+ addToUserData(myData);
+ Cryptpad.setAttribute('username', newName, function (err, data) {
+ if (err) {
+ console.error("Couldn't set username");
+ return;
+ }
+ APP.userName.lastName = myUserName;
+ //change();
+ });
+ };
- if (proxy.metadata && proxy.metadata.title) {
- updateTitle(proxy.metadata.title);
- }
+ var updateTitle = function (newTitle) {
+ if (newTitle === document.title) { return; }
+ // Change the title now, and set it back to the old value if there is an error
+ var oldTitle = document.title;
+ document.title = newTitle;
+ Cryptpad.renamePad(newTitle, function (err, data) {
+ if (err) {
+ console.log("Couldn't set pad title");
+ console.error(err);
+ document.title = oldTitle;
+ return;
+ }
+ document.title = data;
+ APP.$bar.find('.' + Toolbar.constants.title).find('span.title').text(data);
+ APP.$bar.find('.' + Toolbar.constants.title).find('input').val(data);
+ });
+ };
- // ensure that proxy.info and proxy.table exist
- ['info', 'table'].forEach(function (k) {
- if (typeof(proxy[k]) === 'undefined') {
- // you seem to be the first person to have visited this pad...
- First = true;
- proxy[k] = {};
- }
- });
+ var updateDefaultTitle = function (defaultTitle) {
+ defaultName = defaultTitle;
+ APP.$bar.find('.' + Toolbar.constants.title).find('input').attr("placeholder", defaultName);
+ };
+ var renameCb = function (err, title) {
+ if (err) { return; }
+ document.title = title;
+ APP.proxy.info.title = title;
+ };
- // table{cols,rows,cells}
- ['cols', 'rows', 'cells'].forEach(function (k) {
- if (typeof(proxy.table[k]) === 'undefined') { proxy.table[k] = {}; }
- });
+ var suggestName = function (fallback) {
+ return document.title || defaultName || "";
+ };
- // table{rowsOrder,colsOrder}
- ['rows', 'cols'].forEach(function (k) {
- var K = k + 'Order';
- if (typeof(proxy.table[K]) === 'undefined') {
- //console.log("Creating %s", K);
- proxy.table[K] = [];
+ var copyObject = function (obj) {
+ return JSON.parse(JSON.stringify(obj));
+ };
- Object.keys(proxy.table[k]).forEach(function (uid) {
- addIfAbsent(proxy.table[K], uid);
- });
- }
- });
+ // special UI elements
+ //var $title = $('#title').attr('placeholder', Messages.poll_titleHint || 'title'); TODO
+ var $description = $('#description').attr('placeholder', Messages.poll_descriptionHint || 'description');
- // HERE TODO make this idempotent so you can call it again
+ var ready = function (info, userid, readOnly) {
+ console.log("READY");
+ console.log('userid: %s', userid);
+
+ var proxy = APP.proxy;
+ var uncommitted = APP.uncommitted = {};
+ prepareProxy(proxy, copyObject(Render.Example));
+ prepareProxy(uncommitted, copyObject(Render.Example));
+ if (!readOnly && proxy.table.colsOrder.indexOf(userid) === -1 &&
+ uncommitted.table.colsOrder.indexOf(userid) === -1) {
+ uncommitted.table.colsOrder.unshift(userid);
+ }
- // cols
- proxy.table.colsOrder.forEach(function (uid) {
- var val = proxy.table.cols[uid];
- makeUser(proxy, uid, val).val(val);
+ var displayedObj = mergeUncommitted(proxy, uncommitted, false);
+
+ var colsOrder = sortColumns(displayedObj.table.colsOrder, userid);
+
+ var $table = APP.$table = $(Render.asHTML(displayedObj, null, colsOrder, readOnly));
+ var $createRow = APP.$createRow = $('#create-option').click(function () {
+ console.error("BUTTON CLICKED! LOL");
+ Render.createRow(proxy, function () {
+ change();
+ });
});
- // rows
- proxy.table.rowsOrder.forEach(function (uid) {
- var val = proxy.table.rows[uid];
- makeOption(proxy, uid, val).val(val);
+ var $createCol = APP.$createCol = $('#create-user').click(function () {
+ Render.createColumn(proxy, function () {
+ change();
+ });
});
- // cells
- Object.keys(proxy.table.cells).forEach(function (uid) {
- //var p = parseXY(uid);
- var box = document.getElementById(uid);
- if (!box) {
- console.log("Couldn't find an element with uid [%s]", uid);
- return;
- }
- var checked = box.checked = proxy.table.cells[uid] ? true : false;
- if (checked) {
- $(box).closest('.checkbox-contain').find('.cover').addClass('yes');
- }
+ // Commit button
+ var $commit = APP.$commit = $('#commit').click(function () {
+ var uncommittedCopy = JSON.parse(JSON.stringify(APP.uncommitted));
+ APP.uncommitted = {};
+ prepareProxy(APP.uncommitted, copyObject(Render.Example));
+ mergeUncommitted(proxy, uncommittedCopy, true);
+ APP.$commit.hide();
+ change();
});
- items.forEach(function ($item) {
- var id = $item.attr('id');
+ // #publish button is removed in readonly
+ var $publish = APP.$publish = $('#publish')
+ .click(function () {
+ publish(true);
+ });
- $item.on('change keyup', function () {
- var val = $item.val();
- proxy.info[id] = val;
+ // #publish button is removed in readonly
+ var $admin = APP.$admin = $('#admin')
+ .click(function () {
+ publish(false);
});
- if (typeof(proxy.info[id]) !== 'undefined') {
- $item.val(proxy.info[id]);
- }
- });
+ // Title
+ if (APP.proxy.info.defaultTitle) {
+ updateDefaultTitle(APP.proxy.info.defaultTitle);
+ } else {
+ APP.proxy.info.defaultTitle = defaultName;
+ }
+ updateTitle(APP.proxy.info.title || defaultName);
- // listen for visibility changes
- if (Visible.isSupported()) {
- Visible.onChange(function (yes) {
- if (yes) { unnotify(); }
- });
+ // Description
+ var resize = function () {
+ var lineCount = $description.val().split('\n').length;
+ $description.css('height', lineCount + 'rem');
+ };
+ $description.on('change keyup', function () {
+ var val = $description.val();
+ proxy.info.description = val;
+ resize();
+ });
+ resize();
+ if (typeof(proxy.info.description) !== 'undefined') {
+ $description.val(proxy.info.description);
}
- proxy
- .on('change', [], function () {
- notify();
- })
- .on('change', ['info'], function (o, n, p) {
- var $target = $('#' + p[1]);
- var el = $target[0];
- var selects;
- var op;
-
- if (el && ['textarea', 'text'].indexOf(el.type) !== -1) {
- op = TextPatcher.diff(o, n);
- selects = ['selectionStart', 'selectionEnd'].map(function (attr) {
- var before = el[attr];
- var after = TextPatcher.transformCursor(el[attr], op);
- return after;
- });
- $target.val(n);
+ $('#tableScroll').prepend($table);
+ updateDisplayedTable();
- if (op) {
- el.selectionStart = selects[0];
- el.selectionEnd = selects[1];
- }
- }
+ $table
+ .click(handleClick)
+ .on('keyup', function (e) { handleClick(e, true); });
- console.log("change: (%s, %s, [%s])", o, n, p.join(', '));
- })
- .on('change', ['table'], function (o, n, p) {
- var id = p[p.length -1];
- var type = p[1];
-
- if (typeof(o) === 'undefined' &&
- ['cols', 'rows', 'cells'].indexOf(type) !== -1) {
- switch (type) {
- case 'cols':
- makeUser(proxy, id, n);
- break;
- case 'rows':
- makeOption(proxy, id, n);
- break;
- case 'cells':
- //
- break;
- default:
- console.log("Unhandled table element creation");
- break;
+ proxy
+ .on('change', ['info'], function (o, n, p) {
+ if (p[1] === 'title') {
+ updateTitle(n);
+ } else if (p[1] === "userData") {
+ addToUserData(APP.proxy.info.userData);
+ } else if (p[1] === 'description') {
+ var op = TextPatcher.diff(o, n);
+ var el = $description[0];
+
+ var selects = ['selectionStart', 'selectionEnd'].map(function (attr) {
+ var before = el[attr];
+ var after = TextPatcher.transformCursor(el[attr], op);
+ return after;
+ });
+ $description.val(n);
+ if (op) {
+ el.selectionStart = selects[0];
+ el.selectionEnd = selects[1];
+ }
}
- }
- var el = document.getElementById(id);
- if (!el) {
- console.log("Couldn't find the element you wanted!");
- return;
- }
+ console.log("change: (%s, %s, [%s])", o, n, p.join(', '));
+ })
+ .on('change', ['table'], change)
+ .on('remove', [], change);
- switch (p[1]) {
- case 'cols':
- console.log("[Table.cols change] %s (%s => %s)@[%s]", id, o, n, p.slice(0, -1).join(', '));
- el.value = n;
- break;
- case 'rows':
- console.log("[Table.rows change] %s (%s => %s)@[%s]", id, o, n, p.slice(0, -1).join(', '));
- el.value = n;
- break;
- case 'cells':
- console.log("[Table.cell change] %s (%s => %s)@[%s]", id, o, n, p.slice(0, -1).join(', '));
- var checked = el.checked = proxy.table.cells[id] ? true: false;
-
- var $parent = $(el).closest('.checkbox-contain');
-
- if (!$parent.length) { console.log("couldn't find parent element of checkbox"); return; }
-
- if (checked) {
- $parent.find('.cover').addClass('yes');
- } else {
- $parent.find('.cover').removeClass('yes');
- }
- break;
- default:
- console.log("[Table change] (%s => %s)@[%s]", o, n, p.join(', '));
- break;
- }
- })
- .on('change', ['metadata'], function (o, n, p) {
- var newTitle = proxy.metadata.title;
- updateTitle(newTitle);
- })
- .on('remove', [], function (o, p, root) {
- //console.log("remove: (%s, [%s])", o, p.join(', '));
- //console.log(p, o, p.length);
-
- switch (p[1]) {
- case 'cols':
- console.log("[Table.cols removal] [%s]", p[2]);
- table.removeColumn(p[2]);
- return false;
- case 'rows':
- console.log("[Table.rows removal] [%s]", p[2]);
- table.removeRow(p[2]);
- return false;
- case 'rowsOrder':
- Object.keys(proxy.table.rows)
- .forEach(function (rowId) {
- if (proxy.table.rowsOrder.indexOf(rowId) === -1) {
- proxy.table.rows[rowId] = undefined;
- delete proxy.table.rows[rowId];
- }
- });
- break;
- case 'colsOrder':
- Object.keys(proxy.table.cols)
- .forEach(function (colId) {
- if (proxy.table.colsOrder.indexOf(colId) === -1) {
- proxy.table.cols[colId] = undefined;
- delete proxy.table.cols[colId];
- }
-
- });
- break;
- case 'cells':
- // cool story bro
- break;
- default:
- console.log("[Table removal] [%s]", p.join(', '));
- break;
+ addToUserData(APP.proxy.info.userData);
+
+ getLastName(function (err, lastName) {
+ APP.ready = true;
+
+ if (!proxy.published) {
+ publish(false);
+ } else {
+ publish(true);
}
+ Cryptpad.removeLoadingScreen();
- })
- .on('disconnect', function (info) {
- setEditable(false);
+ // Update the toolbar list:
+ // Add the current user in the metadata if he has edit rights
+ if (readOnly) { return; }
+ if (typeof(lastName) === 'string' && lastName.length) {
+ setName(lastName);
+ } else {
+ var myData = {};
+ myData[info.myId] = {
+ name: ""
+ };
+ addToUserData(myData);
+ APP.$userNameButton.click();
+ }
});
+ };
+ var create = function (info) {
+ var realtime = APP.realtime = info.realtime;
+ var myID = APP.myID = info.myID;
- var $toolbar = $('#toolbar');
+ var editHash;
+ var viewHash = Cryptpad.getViewHashFromKeys(info.channel, secret.keys);
- var Button = function (opt) {
- return $('