big ugly commit that will be really hard to audit

This changeset applies new styles to the poll.

it also uses the new asynchronous wrappers around the localStorage api.
this is necessary because we're migrating to a storage system that will
use an async api.

The changes to the poll just happened to coincide with the async stuff.

My apologies to anyone who wants to read this whole thing
pull/1/head
ansuz 8 years ago
parent add84aeae6
commit 1f24d7126c

@ -28,8 +28,6 @@ define([
var now = new Date();
var hasRecent = false;
var memorySpan = Cryptpad.timeframe; // thirty days
var forgetPad = Cryptpad.forgetPad;
var padTypes = {
@ -45,23 +43,17 @@ define([
return title;
};
var recentPads = Cryptpad.getRecentPads();
recentPads.sort(Cryptpad.mostRecent);
var fixHTML = function (html) {
return html.replace(/</g, '&lt;');
};
var makeRecentPadsTable = function () {
var makeRecentPadsTable = function (recentPads) {
if (!recentPads.length) { return; }
recentPads.some(function (pad, index) {
if (!pad) { return; }
//console.log(pad);
// don't link to old pads
if (now.getTime() - new Date(pad.atime).getTime() > memorySpan) { return true; }
hasRecent = true;
// split up the uri
@ -92,13 +84,19 @@ define([
}).text('✖').click(function () {
Cryptpad.confirm(Messages.forgetPrompt + ' (' + fixHTML(shortTitle) + ')', function (yes) {
if (!yes) { return; }
forgetPad(pad.href);
$row.fadeOut(750, function () {
$row.remove();
if (!$table.find('tr').find('td').length) {
$table.remove();
$tryit.text(Messages.tryIt);
forgetPad(pad.href, function (err, data) {
if (err) {
console.log("Unable to forget pad");
console.log(err);
return;
}
$row.fadeOut(750, function () {
$row.remove();
if (!$table.find('tr').find('td').length) {
$table.remove();
$tryit.text(Messages.tryIt);
}
});
});
});
});
@ -116,13 +114,23 @@ define([
});
};
if (recentPads.length) {
recentPads.sort(Cryptpad.mostRecent);
makeRecentPadsTable();
}
if (hasRecent) {
$('table').attr('style', '');
$tryit.text(Messages.recentPads);
}
Cryptpad.getRecentPads(function (err, recentPads) {
if (err) {
console.log("unable to get recent pads");
console.error(err);
return;
}
if (recentPads.length) {
recentPads.sort(Cryptpad.mostRecent);
makeRecentPadsTable(recentPads);
}
if (hasRecent) {
$('table').attr('style', '');
$tryit.text(Messages.recentPads);
}
//recentPads.sort(Cryptpad.mostRecent);
});
});

@ -166,21 +166,30 @@ define([
name: myUserName
};
addToUserList(myData);
Cryptpad.setPadAttribute('username', myUserName);
onLocal();
Cryptpad.setPadAttribute('username', myUserName, function (err, data) {
if (err) {
console.log("Couldn't set username");
console.error(err);
return;
}
onLocal();
});
};
var getLastName = function () {
return Cryptpad.getPadAttribute('username') || '';
var getLastName = function (cb) {
Cryptpad.getPadAttribute('username', function (err, userName) {
cb(err, userName || '');
});
};
var createChangeName = function(id, $container) {
var buttonElmt = $container.find('#'+id)[0];
var lastName = getLastName();
buttonElmt.addEventListener("click", function() {
Cryptpad.prompt(Messages.changeNamePrompt, lastName, function (newName) {
setName(newName);
getLastName(function (err, lastName) {
buttonElmt.addEventListener("click", function() {
Cryptpad.prompt(Messages.changeNamePrompt, lastName, function (newName) {
setName(newName);
});
});
});
};
@ -228,8 +237,7 @@ define([
if (document.title === hash) {
return getHeadingText() || hash;
} else {
return document.title || getHeadingText() ||
Cryptpad.getPadTitle() || hash;
return document.title || getHeadingText() || hash;
}
};
@ -250,7 +258,6 @@ define([
};
var onInit = config.onInit = function (info) {
//Cryptpad.warn("Initializing realtime session...");
var $bar = $('#pad-iframe')[0].contentWindow.$('#cme_toolbox');
toolbarList = info.userList;
var config = {
@ -309,12 +316,28 @@ define([
Cryptpad.prompt(Messages.renamePrompt,
suggestion, function (title, ev) {
if (title === null) { return; }
if (Cryptpad.causesNamingConflict(title)) {
Cryptpad.alert(Messages.renameConflict);
return;
}
Cryptpad.setPadTitle(title);
document.title = title;
Cryptpad.causesNamingConflict(title, function (err, conflicts) {
if (err) {
console.log("Unable to determine if name caused a conflict");
console.error(err);
return;
}
if (conflicts) {
Cryptpad.alert(Messages.renameConflict);
return;
}
Cryptpad.setPadTitle(title, function (err, data) {
if (err) {
console.log("unable to set pad title");
console.log(err);
return;
}
document.title = title;
});
});
});
});
$rightside.append($setTitle);
@ -330,65 +353,104 @@ define([
var href = window.location.href;
Cryptpad.confirm(Messages.forgetPrompt, function (yes) {
if (!yes) { return; }
Cryptpad.forgetPad(href);
document.title = window.location.hash.slice(1,9);
Cryptpad.forgetPad(href, function (err, data) {
if (err) {
console.log("unable to forget pad");
console.error(err);
return;
}
document.title = window.location.hash.slice(1,9);
});
});
});
$rightside.append($forgetPad);
var lastLanguage = Cryptpad.getPadAttribute('language') || 'javascript';
// TODO use cb
var configureLanguage = function (cb) {
// FIXME this is async so make it happen as early as possible
Cryptpad.getPadAttribute('language', function (err, lastLanguage) {
if (err) {
console.log("Unable to get pad language");
}
/* Let the user select different syntax highlighting modes */
var syntaxDropdown = '<select title="syntax highlighting" id="language-mode">\n' +
Modes.list.map(function (o) {
var selected = o.mode === lastLanguage? ' selected="selected"' : '';
return '<option value="' + o.mode + '"'+selected+'>' + o.language + '</option>';
}).join('\n') +
'</select>';
lastLanguage = lastLanguage || 'javascript';
setMode(lastLanguage);
/* Let the user select different syntax highlighting modes */
var syntaxDropdown = '<select title="syntax highlighting" id="language-mode">\n' +
Modes.list.map(function (o) {
var selected = o.mode === lastLanguage? ' selected="selected"' : '';
return '<option value="' + o.mode + '"'+selected+'>' + o.language + '</option>';
}).join('\n') +
'</select>';
/* Remember the user's last choice of theme using localStorage */
var themeKey = 'CRYPTPAD_CODE_THEME';
var lastTheme = localStorage.getItem(themeKey) || 'default';
setMode(lastLanguage);
/* Let the user select different themes */
var $themeDropdown = $('<select>', {
title: 'color theme',
id: 'display-theme',
});
Themes.forEach(function (o) {
$themeDropdown.append($('<option>', {
selected: o.name === lastTheme,
}).val(o.name).text(o.name));
});
$rightside.append(syntaxDropdown);
var $language = module.$language = $bar.find('#language-mode').on('change', function () {
var mode = $language.val();
setMode(mode);
Cryptpad.setPadAttribute('language', mode, function (err, data) {
// TODO
});
});
cb();
});
};
$rightside.append(syntaxDropdown);
var $language = module.$language = $bar.find('#language-mode').on('change', function () {
var mode = $language.val();
setMode(mode);
Cryptpad.setPadAttribute('language', mode);
});
var configureTheme = function () {
/* Remember the user's last choice of theme using localStorage */
var themeKey = 'CRYPTPAD_CODE_THEME';
var lastTheme = localStorage.getItem(themeKey) || 'default';
/* Let the user select different themes */
var $themeDropdown = $('<select>', {
title: 'color theme',
id: 'display-theme',
});
Themes.forEach(function (o) {
$themeDropdown.append($('<option>', {
selected: o.name === lastTheme,
}).val(o.name).text(o.name));
});
$rightside.append($themeDropdown);
var $theme = $bar.find('select#display-theme');
$rightside.append($themeDropdown);
setTheme(lastTheme, $theme);
var $theme = $bar.find('select#display-theme');
setTheme(lastTheme, $theme);
$theme.on('change', function () {
var theme = $theme.val();
console.log("Setting theme to %s", theme);
setTheme(theme, $theme);
// remember user choices
localStorage.setItem(themeKey, theme);
});
};
$theme.on('change', function () {
var theme = $theme.val();
console.log("Setting theme to %s", theme);
setTheme(theme, $theme);
// remember user choices
localStorage.setItem(themeKey, theme);
configureLanguage(function () {
configureTheme();
});
window.location.hash = info.channel + secret.key;
var title = document.title = Cryptpad.getPadTitle();
Cryptpad.rememberPad(title);
Cryptpad.getPadTitle(function (err, title) {
if (err) {
console.log("Unable to get pad title");
console.error(err);
return;
}
document.title = title || window.location.hash.slice(1,9);
Cryptpad.rememberPad(title, function (err, data) {
if (err) {
console.log("Unable to set pad title");
console.error(err);
return;
}
});
});
};
var updateUserList = function(shjson) {
@ -446,10 +508,16 @@ define([
initializing = false;
//Cryptpad.log("Your document is ready");
var lastName = getLastName();
if (typeof(lastName) === 'string' && lastName.length) {
setName(lastName);
}
getLastName(function (err, lastName) {
if (err) {
console.log("Could not get previous name");
console.error(err);
return;
}
if (typeof(lastName) === 'string' && lastName.length) {
setName(lastName);
}
});
};
var cursorToPos = function(cursor, oldText) {

@ -1,9 +1,10 @@
define([
'/customize/messages.js',
'/customize/store.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/alertifyjs/dist/js/alertify.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Messages, Crypto, Alertify) {
], function (Messages, Store, Crypto, Alertify) {
/* This file exposes functionality which is specific to Cryptpad, but not to
any particular pad type. This includes functions for committing metadata
about pads to your local storage for future use and improved usability.
@ -28,8 +29,8 @@ define([
return secret;
};
var storageKey = common.storageKey = 'CryptPad_RECENTPADS';
//var timeframe = common.timeframe = 1000 * 60 * 60 * 24 * 30;
/*
the first time this gets called, your local storage will migrate to a
@ -75,35 +76,40 @@ define([
return window.location.hash.slice(1);
};
var setPadAttribute = common.setPadAttribute = function (attr, value) {
var hash = getHash();
localStorage.setItem([getHash(),attr].join('.'), value);
return value;
var setPadAttribute = common.setPadAttribute = function (attr, value, cb) {
Store.set([getHash(), attr].join('.'), value, function (err, data) {
cb(err, data);
})
};
var getPadAttribute = common.getPadAttribute = function (attr) {
return localStorage.getItem([getHash(),attr].join('.'));
var getPadAttribute = common.getPadAttribute = function (attr, cb) {
Store.get([getHash(), attr].join('.'), function (err, data) {
cb(err, data);
});
};
/* fetch and migrate your pad history from localStorage */
var getRecentPads = common.getRecentPads = function () {
var recentPadsStr = localStorage[storageKey];
var recentPads = [];
if (recentPadsStr) {
try {
recentPads = JSON.parse(recentPadsStr);
} catch (err) {
// couldn't parse the localStorage?
// just overwrite it.
var getRecentPads = common.getRecentPads = function (cb) {
Store.get(storageKey, function (err, recentPadsStr) {
var recentPads = [];
if (recentPadsStr) {
try {
recentPads = JSON.parse(recentPadsStr);
} catch (err) {
// couldn't parse the localStorage?
// just overwrite it.
}
}
}
return migrateRecentPads(recentPads);
cb(void 0, migrateRecentPads(recentPads));
});
};
/* commit a list of pads to localStorage */
var setRecentPads = common.setRecentPads = function (pads) {
localStorage.setItem(storageKey, JSON.stringify(pads));
var setRecentPads = common.setRecentPads = function (pads, cb) {
Store.set(storageKey, JSON.stringify(pads), function (err, data) {
cb(err, data);
});
};
/* Sort pads according to how recently they were accessed */
@ -111,98 +117,152 @@ define([
return new Date(b.atime).getTime() - new Date(a.atime).getTime();
};
var forgetPad = common.forgetPad = function (href) {
var recentPads = getRecentPads().filter(function (pad) {
return pad.href !== href;
});
setRecentPads(recentPads);
var forgetPad = common.forgetPad = function (href, cb) {
var hash;
href.replace(/#(.*)$/, function (h) { hash = h; });
if (!hash) { return; }
Object.keys(localStorage).forEach(function (k) {
if (k.indexOf(hash) === 0) { localStorage.removeItem(k); }
});
href.replace(/#(.*)$/, function (x, h) { hash = h; });
if (!hash) {
return;
}
getRecentPads(function (err, recentPads) {
setRecentPads(recentPads.filter(function (pad) {
return pad.href !== href;
}), function (err, data) {
if (err) {
cb(err);
return;
}
Store.dump(function (err, storage) {
if (err) {
cb(err);
return;
}
var toRemove = [];
Object.keys(storage).forEach(function (k) {
if (k.indexOf(hash) === 0) {
toRemove.push(k);
}
});
Store.removeBatch(toRemove, function (err, data) {
cb(err, data);
});
});
});
});
};
var rememberPad = common.rememberPad = window.rememberPad = function (title) {
var rememberPad = common.rememberPad = window.rememberPad = function (title, cb) {
// bail out early
if (!/#/.test(window.location.hash)) { return; }
var pads = getRecentPads();
getRecentPads(function (err, pads) {
if (err) {
cb(err);
return;
}
var now = new Date();
var href = window.location.href;
//var pads = getRecentPads();
var isUpdate = false;
var now = new Date();
var href = window.location.href;
var out = pads.map(function (pad) {
if (pad && pad.href === href) {
isUpdate = true;
// bump the atime
pad.atime = now;
var isUpdate = false;
pad.title = title;
}
return pad;
});
var out = pads.map(function (pad) {
if (pad && pad.href === href) {
isUpdate = true;
// bump the atime
pad.atime = now;
if (!isUpdate) {
// href, atime, name
out.push({
href: href,
atime: now,
ctime: now,
title: title || window.location.hash.slice(1,9),
pad.title = title;
}
return pad;
});
}
setRecentPads(out);
if (!isUpdate) {
// href, atime, name
out.push({
href: href,
atime: now,
ctime: now,
title: title || window.location.hash.slice(1,9),
});
}
setRecentPads(out, function (err, data) {
cb(err, data);
});
});
};
var setPadTitle = common.setPadTitle = function (name) {
var setPadTitle = common.setPadTitle = function (name, cb) {
var href = window.location.href;
var recent = getRecentPads();
var renamed = recent.map(function (pad) {
if (pad.href === href) {
// update the atime
pad.atime = new Date().toISOString();
// set the name
pad.title = name;
getRecentPads(function (err, recent) {
if (err) {
cb(err);
return;
}
return pad;
});
var renamed = recent.map(function (pad) {
if (pad.href === href) {
// update the atime
pad.atime = new Date().toISOString();
// set the name
pad.title = name;
}
return pad;
});
setRecentPads(renamed);
setRecentPads(renamed, function (err, data) {
cb(err, data);
});
});
};
var getPadTitle = common.getPadTitle = function () {
var getPadTitle = common.getPadTitle = function (cb) {
var href = window.location.href;
var hashSlice = window.location.hash.slice(1,9);
var title = '';
getRecentPads().some(function (pad) {
if (pad.href === href) {
title = pad.title || hashSlice;
return true;
getRecentPads(function (err, pads) {
if (err) {
cb(err);
return;
}
});
return title;
};
pads.some(function (pad) {
if (pad.href === href) {
title = pad.title || hashSlice;
return true;
}
});
var fixFileName = common.fixFileName = function (filename) {
return filename.replace(/ /g, '-').replace(/\//g, '_');
cb(void 0, title);
});
};
var causesNamingConflict = common.causesNamingConflict = function (title) {
var causesNamingConflict = common.causesNamingConflict = function (title, cb) {
var href = window.location.href;
return getRecentPads().some(function (pad) {
return pad.title === title &&
pad.href !== href;
getRecentPads(function (err, pads) {
if (err) {
cb(err);
return;
}
var conflicts = pads.some(function (pad) {
return pad.title === title &&
pad.href !== href;
});
cb(void 0, conflicts);
});
};
var fixFileName = common.fixFileName = function (filename) {
return filename.replace(/ /g, '-').replace(/\//g, '_');
};
var importContent = common.importContent = function (type, f) {
return function () {
var $files = $('<input type="file">').click();

@ -234,8 +234,10 @@ define([
myID = info.myID || null;
};
var getLastName = function () {
return Cryptpad.getPadAttribute('username') || '';
var getLastName = function (cb) {
Cryptpad.getPadAttribute('username', function (err, userName) {
cb(err, userName || '');
});
};
var setName = module.setName = function (newName) {
@ -251,15 +253,21 @@ define([
addToUserList(myData);
editor.fire('change');
Cryptpad.setPadAttribute('username', newName);
Cryptpad.setPadAttribute('username', newName, function (err, data) {
if (err) {
console.error("Couldn't set username");
}
});
};
var createChangeName = function(id, $container) {
var buttonElmt = $container.find('#'+id)[0];
var lastName = getLastName();
buttonElmt.addEventListener("click", function() {
Cryptpad.prompt(Messages.changeNamePrompt, lastName, function (newName) {
setName(newName);
//var lastName = getLastName();
getLastName(function (err, lastName) {
buttonElmt.addEventListener("click", function() {
Cryptpad.prompt(Messages.changeNamePrompt, lastName, function (newName) {
setName(newName);
});
});
});
};
@ -479,13 +487,21 @@ define([
Cryptpad.prompt(Messages.renamePrompt, suggestion, function (title) {
if (title === null) { return; }
if (Cryptpad.causesNamingConflict(title)) {
Cryptpad.alert(Messages.renameConflict);
return;
}
Cryptpad.setPadTitle(title);
document.title = title;
Cryptpad.causesNamingConflict(title, function (err, conflicts) {
if (conflicts) {
Cryptpad.alert(Messages.renameConflict);
return;
}
Cryptpad.setPadTitle(title, function (err, data) {
if (err) {
console.log("Couldn't set pad title");
console.error(err);
return;
}
document.title = title;
});
});
});
});
$rightside.append($rename);
@ -501,8 +517,9 @@ define([
var href = window.location.href;
Cryptpad.confirm(Messages.forgetPrompt, function (yes) {
if (!yes) { return; }
Cryptpad.forgetPad(href);
document.title = window.location.hash.slice(1,9);
Cryptpad.forgetPad(href, function (err, data) {
document.title = window.location.hash.slice(1,9);
});
});
});
$rightside.append($forgetPad);
@ -510,8 +527,21 @@ define([
// set the hash
window.location.hash = info.channel + secret.key;
var title = document.title = Cryptpad.getPadTitle();
Cryptpad.rememberPad(title);
Cryptpad.getPadTitle(function (err, title) {
if (err) {
console.error(err);
console.log("Couldn't get pad title");
return;
}
document.title = title || window.location.hash.slice(1, 9);
Cryptpad.rememberPad(title, function (err, data) {
if (err) {
console.log("Couldn't remember pad");
console.error(err);
}
});
});
Cryptpad.styleAlerts();
};
@ -536,10 +566,13 @@ define([
console.log("Unlocking editor");
setEditable(true);
initializing = false;
var lastName = getLastName();
if (typeof(lastName) === 'string' && lastName.length) {
setName(lastName);
}
getLastName(function (err, lastName) {
if (typeof(lastName) === 'string' && lastName.length) {
setName(lastName);
}
});
//var lastName = getLastName();
};
var onAbort = realtimeOptions.onAbort = function (info) {

@ -35,17 +35,21 @@
<div id="toolbar" class="buttons">
<sub><a href="/"></a></sub>
</div>
<h1>CryptPoll </h1>
<h2>Schedule or vote in <em>real time</em></h2>
<h1>CryptPoll</h1>
<h2>Zero Knowledge, <em>realtime</em> scheduling</h2>
<p>Enter your name in the input field below and check the box for times when you are available</p>
<p>Your settings are updated instantly, so you never need to save.</p>
<p>All your input is encrypted so only people who have the link can access it. Even the server cannot see what you change.</p>
<hr>
<br>
<form class="realtime">
<input type="text" id="title" placeholder="title"><br />
<textarea id="description" placeholder="description"></textarea>
<p>Enter your name in the input field below and check the box for times when you are available</p>
<!-- Table markup-->
<table id="table">

@ -78,15 +78,33 @@ define([
var proxy = module.rt.proxy;
var $div = $('<div>', {
'class': 'checkbox-contain',
});
var $label = $('<label>', {
'for': id,
});
var $check = Input({
id: id,
name: id,
type:'checkbox'
}).click(function () {
type:'checkbox',
}).on('change', function () {
console.log("(%s, %s) => %s", p.x, p.y, $check[0].checked);
proxy.table.cells[id] = $check[0].checked? 1: 0;
var checked = proxy.table.cells[id] = $check[0].checked? 1: 0;
if (checked) {
$label.addClass('yes');
}
else {
$label.removeClass('yes');
}
});
return $check;
$div.append($check);
$check.after($label);
return $div; //$check;
};
var Text = function () { return Input({type:'text'}); };
@ -163,7 +181,9 @@ define([
proxy.table.cols[id] = $user.val() || "";
});
var $wrapper = $('<div>')
var $wrapper = $('<div>', {
'class': 'text-cell',
})
.append($user)
.append($('<span>', {
'class': 'remove',
@ -198,7 +218,9 @@ define([
proxy.table.rows[id] = $option.val();
});
var $wrapper = $('<div>')
var $wrapper = $('<div>', {
'class': 'text-cell',
})
.append($option)
.append($('<span>', {
'class': 'remove',
@ -267,9 +289,15 @@ define([
var proxy = module.rt.proxy;
var First = false;
// ensure that proxy.info and proxy.table exist
['info', 'table'].forEach(function (k) {
if (typeof(proxy[k]) === 'undefined') { proxy[k] = {}; }
if (typeof(proxy[k]) === 'undefined') {
// you seem to be the first person to have visited this pad...
First = true;
proxy[k] = {};
}
});
// table{cols,rows,cells}
@ -305,8 +333,16 @@ define([
// cells
Object.keys(proxy.table.cells).forEach(function (uid) {
var p = parseXY(uid);
document.getElementById(uid).checked = proxy.table.cells[uid] ? true : false;
//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).parent().find('label').addClass('yes');
}
});
items.forEach(function ($item) {
@ -330,6 +366,9 @@ define([
}
proxy
.on('change', [], function () {
notify();
})
.on('change', ['info'], function (o, n, p) {
var $target = $('#' + p[1]);
var el = $target[0];
@ -352,7 +391,6 @@ define([
}
console.log("change: (%s, %s, [%s])", o, n, p.join(', '));
notify();
})
.on('change', ['table'], function (o, n, p) {
var id = p[p.length -1];
@ -393,7 +431,18 @@ define([
break;
case 'cells':
console.log("[Table.cell change] %s (%s => %s)@[%s]", id, o, n, p.slice(0, -1).join(', '));
el.checked = proxy.table.cells[id] ? true: false;
var checked = el.checked = proxy.table.cells[id] ? true: false;
var $parent = $(el).parent();
if (!$parent.length) { console.log("couldn't find parent element of checkbox"); return; }
if (checked) {
$parent.find('label').addClass('yes');
//$(el).parent().
} else {
$parent.find('label').removeClass('yes');
}
break;
default:
console.log("[Table change] (%s => %s)@[%s]", o, n, p.join(', '));
@ -401,14 +450,61 @@ define([
}
})
.on('remove', [], function (o, p, root) {
console.log("remove: (%s, [%s])", o, p.join(', '));
//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;
}
})
.on('disconnect', function (info) {
setEditable(false);
});
var title = document.title = Cryptpad.getPadTitle();
Cryptpad.rememberPad(title);
Cryptpad.getPadTitle(function (err, title) {
title = document.title = title || window.location.hash.slice(1, 9);
Cryptpad.rememberPad(title, function (err, data) {
if (err) {
console.log("unable to remember pad");
console.log(err);
return;
}
});
});
var $toolbar = $('#toolbar');
@ -434,8 +530,14 @@ define([
var href = window.location.href;
Cryptpad.confirm(Messages.forgetPrompt, function (yes) {
if (!yes) { return; }
Cryptpad.forgetPad(href);
document.title = window.location.hash.slice(1, 9);
Cryptpad.forgetPad(href, function (err, data) {
if (err) {
console.log("unable to forget pad");
console.error(err);
return;
}
document.title = window.location.hash.slice(1, 9);
});
});
}));
@ -448,12 +550,21 @@ define([
Cryptpad.prompt(Messages.renamePrompt,
suggestion, function (title, ev) {
if (title === null) { return; }
if (Cryptpad.causesNamingConflict(title)) {
Cryptpad.alert(Messages.renameConflict);
return;
}
Cryptpad.setPadTitle(title);
document.title = title;
Cryptpad.causesNamingConflict(title, function (err, conflicts) {
if (conflicts) {
Cryptpad.alert(Messages.renameConflict);
return;
}
Cryptpad.setPadTitle(title, function (err, data) {
if (err) {
console.log("unable to set pad title");
console.error(err);
return;
}
document.title = title;
});
});
});
}));
@ -469,6 +580,19 @@ define([
}));
setEditable(true);
if (First) {
// assume the first user to the poll wants to be the administrator...
// TODO prompt them with questions to set up their poll...
}
/* TODO
even if the user isn't the first, check their storage to see if
they've visited before and if they 'own' a column in the table.
if they do, make it editable and suggest that they fill it in.
if they have not visited, make a column for them.
don't propogate changes from this column until they make changes
*/
};
var config = {

@ -18,7 +18,9 @@ define([
$head.find('th').each(function (i) {
var colId = $(this).data('rt-uid');
$row.append($('<td>').append(Rest(xy(colId, uid))));
$row.append($('<td>', {
'class': 'checkbox-cell',
}).append(Rest(xy(colId, uid))));
});
rows.push(uid);
@ -35,7 +37,9 @@ define([
var $width = $body.find('tr').each(function (i) {
// each checkbox needs a uid corresponding to its role
var rowId = $(this).data('rt-uid');
$(this).append($('<td>').append(Rest(xy(uid, rowId))));
$(this).append($('<td>', {
'class': 'checkbox-cell',
}).append(Rest(xy(uid, rowId))));
});
cols.push(uid);
@ -92,6 +96,14 @@ define([
removeFromArray(rows, uid);
};
var colExists = function (uid) {
return cols.indexOf(uid) !== -1;
};
var rowExists = function (uid) {
return rows.indexOf(uid) !== -1;
};
return {
$: $t,
addRow: addRow,
@ -99,7 +111,9 @@ define([
removeRow: removeRow,
removeColumn: removeColumn,
rows: rows,
rowExists: rowExists,
cols: cols,
colExists: colExists,
};
};
return Table;

Loading…
Cancel
Save