diff --git a/customize.dist/translations/messages.es.js b/customize.dist/translations/messages.es.js
index 57eb41f9e..ce4bcb788 100644
--- a/customize.dist/translations/messages.es.js
+++ b/customize.dist/translations/messages.es.js
@@ -452,6 +452,9 @@ define(function () {
out.poll_locked = "Cerrado";
out.poll_unlocked = "Abierto";
+ out.poll_show_help_button = "Mostrar ayuda";
+ out.poll_hide_help_button = "Esconder ayuda";
+
// 1.8.0 - Idopogo
out.common_connectionLost = "Connexión perdida
El documento está ahora en modo solo lectura hasta que la conexión vuelva.";
diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js
index bfc7d93de..41423fe57 100644
--- a/customize.dist/translations/messages.fr.js
+++ b/customize.dist/translations/messages.fr.js
@@ -207,6 +207,9 @@ define(function () {
out.poll_locked = "Verrouillé";
out.poll_unlocked = "Déverrouillé";
+ out.poll_show_help_button = "Afficher l'aide";
+ out.poll_hide_help_button = "Cacher l'aide";
+
// Canvas
out.canvas_clear = "Nettoyer";
out.canvas_delete = "Supprimer la sélection";
diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js
index 5ba42d97b..c549a6009 100644
--- a/customize.dist/translations/messages.js
+++ b/customize.dist/translations/messages.js
@@ -209,6 +209,9 @@ define(function () {
out.poll_locked = "Locked";
out.poll_unlocked = "Unlocked";
+ out.poll_show_help_button = "Show help";
+ out.poll_hide_help_button = "Hide help";
+
// Canvas
out.canvas_clear = "Clear";
out.canvas_delete = "Delete selection";
diff --git a/www/poll/index.html b/www/poll/index.html
index 31226d989..091086f5c 100644
--- a/www/poll/index.html
+++ b/www/poll/index.html
@@ -29,6 +29,7 @@
+
diff --git a/www/poll/main.js b/www/poll/main.js
index eb0edef26..4878b60a6 100644
--- a/www/poll/main.js
+++ b/www/poll/main.js
@@ -46,7 +46,8 @@ define([
editable: {
row: [],
col: []
- }
+ },
+ locked: false
};
var sortColumns = function (order, firstcol) {
@@ -97,7 +98,7 @@ define([
// Enable the checkboxes for the user's column (committed or not)
$('input[disabled="disabled"][data-rt-id^="' + id + '"]').removeAttr('disabled');
- $('input[type="checkbox"][data-rt-id^="' + id + '"]').addClass('enabled');
+ $('input[type="number"][data-rt-id^="' + id + '"]').addClass('enabled');
$('.lock[data-rt-id="' + id + '"]').addClass('fa-unlock').removeClass('fa-lock').attr('title', Messages.poll_unlocked);
if (isOwnColumnCommitted()) { return; }
@@ -108,12 +109,14 @@ define([
var unlockElements = function () {
APP.editable.row.forEach(function (id) {
- $('input[type="text"][disabled="disabled"][data-rt-id="' + id + '"]').removeAttr('disabled');
+ var $input = $('input[type="text"][disabled="disabled"][data-rt-id="' + id + '"]').removeAttr('disabled');
+ $input.parent().parent().addClass('editing');
$('span.edit[data-rt-id="' + id + '"]').css('visibility', 'hidden');
});
APP.editable.col.forEach(function (id) {
- $('input[disabled="disabled"][data-rt-id^="' + id + '"]').removeAttr('disabled');
- $('input[type="checkbox"][data-rt-id^="' + id + '"]').addClass('enabled');
+ var $input = $('input[disabled="disabled"][data-rt-id^="' + id + '"]').removeAttr('disabled');
+ $input.parent().addClass('editing');
+ $('input[type="number"][data-rt-id^="' + id + '"]').addClass('enabled');
$('.lock[data-rt-id="' + id + '"]').addClass('fa-unlock').removeClass('fa-lock').attr('title', Messages.poll_unlocked);
});
};
@@ -274,10 +277,17 @@ define([
Render.setValue(object, id, input.value);
change(null, null, null, 50);
break;
- case 'checkbox':
- debug("checkbox[tr-id='%s'] %s", id, input.checked);
+ case 'number':
+ debug("checkbox[tr-id='%s'] %s", id, input.value);
if (APP.editable.col.indexOf(x) >= 0 || x === APP.userid) {
- Render.setValue(object, id, input.checked);
+ var value = parseInt(input.value);
+
+ if (isNaN(value)) {
+ console.error("Got NaN?!");
+ break;
+ }
+
+ Render.setValue(object, id, value);
change();
} else {
debug('checkbox locked');
@@ -290,12 +300,14 @@ define([
};
var hideInputs = function (target, isKeyup) {
+ if (APP.locked) { return; }
if (!isKeyup && $(target).is('[type="text"]')) {
return;
}
$('.lock[data-rt-id!="' + APP.userid + '"]').addClass('fa-lock').removeClass('fa-unlock').attr('title', Messages.poll_locked);
var $cells = APP.$table.find('thead td:not(.uncommitted), tbody td');
$cells.find('[type="text"][data-rt-id!="' + APP.userid + '"]').attr('disabled', true);
+ $cells.removeClass('editing');
$('.edit[data-rt-id!="' + APP.userid + '"]').css('visibility', 'visible');
APP.editable.col = [APP.userid];
APP.editable.row = [];
@@ -349,9 +361,13 @@ define([
};
var handleClick = function (e, isKeyup) {
+ if (APP.locked) { return; }
+
e.stopPropagation();
if (!APP.ready) { return; }
+ if (!isKeyup && e.which !== 1) { return; } // only allow left clicks
+
var target = e && e.target;
if (!target) { return void debug("NO TARGET"); }
@@ -369,10 +385,19 @@ define([
hideInputs(target, isKeyup);
break;
}
+ if ($(target).is('input[type="number"]')) { console.error("number input focused?"); break; }
+
handleInput(target);
break;
+ case 'LABEL':
+ var input = $('input[type="number"][id=' + $(target).attr('for') + ']');
+ var value = parseInt(input.val());
+
+ input.val((value + 1) % 4);
+
+ handleInput(input[0]);
+ break;
case 'SPAN':
- //case 'LABEL':
if (shouldLock) {
break;
}
@@ -421,6 +446,15 @@ define([
});
};
+ var showHelp = function(help) {
+ if (typeof help === 'undefined') { help = !$('#howItWorks').is(':visible'); }
+
+ var msg = (help ? Messages.poll_hide_help_button : Messages.poll_show_help_button);
+
+ $('#howItWorks').toggle(help);
+ $('#help').text(msg).attr('title', msg);
+ };
+
var Title;
var UserList;
@@ -486,12 +520,16 @@ var ready = function (info, userid, readOnly) {
publish(true);
});
- // #publish button is removed in readonly
APP.$admin = $('#admin')
.click(function () {
publish(false);
});
+ APP.$help = $('#help')
+ .click(function () {
+ showHelp();
+ });
+
// Title
if (APP.proxy.info.defaultTitle) {
Title.updateDefaultTitle(APP.proxy.info.defaultTitle);
@@ -527,7 +565,10 @@ var ready = function (info, userid, readOnly) {
.click(handleClick)
.on('keyup', function (e) { handleClick(e, true); });
- $(window).click(hideInputs);
+ $(window).click(function(e) {
+ if (e.which !== 1) { return; }
+ hideInputs();
+ });
proxy
.on('change', ['info'], function (o, n, p) {
@@ -570,14 +611,33 @@ var ready = function (info, userid, readOnly) {
UserList.getLastName(APP.toolbar.$userNameButton, isNew);
};
+var setEditable = function (editable) {
+ APP.locked = !editable;
+
+ if (editable === false) {
+ // disable all the things
+ $('.realtime input, .realtime button, .upper button, .realtime textarea').attr('disabled', APP.locked);
+ $('span.edit, span.remove').hide();
+ $('span.lock').addClass('fa-lock').removeClass('fa-unlock')
+ .attr('title', Messages.poll_locked)
+ .css({'cursor': 'default'});
+ } else {
+ // enable
+ $('span.edit, span.remove').show();
+ $('span.lock').css({'cursor': ''});
+ $('.realtime button, .upper button, .realtime textarea').attr('disabled', APP.locked);
+ unlockElements();
+ }
+};
+
var disconnect = function () {
- //setEditable(false); // TODO
+ setEditable(false);
APP.toolbar.failed();
Cryptpad.alert(Messages.common_connectionLost, undefined, true);
};
var reconnect = function (info) {
- //setEditable(true); // TODO
+ setEditable(true);
APP.toolbar.reconnecting(info.myId);
Cryptpad.findOKButton().click();
};
@@ -632,7 +692,7 @@ var create = function (info) {
/* add a forget button */
var forgetCb = function (err) {
if (err) { return; }
- disconnect();
+ setEditable(false);
};
var $forgetPad = Cryptpad.createButton('forget', true, {}, forgetCb);
$rightside.append($forgetPad);
@@ -698,12 +758,13 @@ var create = function (info) {
Cryptpad.setAttribute(HIDE_INTRODUCTION_TEXT, "1", function (e) {
if (e) { console.error(e); }
});
- } else if (value === "1") {
- $('#howItWorks').hide();
+ showHelp(true);
+ } else {
+ showHelp(false);
}
});
- //Cryptpad.onLogout(function () { setEditable(false); }); TODO
+ Cryptpad.onLogout(function () { setEditable(false); });
});
Cryptpad.onError(function (info) {
if (info) {
diff --git a/www/poll/poll.css b/www/poll/poll.css
index 3e534d5e2..979f7f2b8 100644
--- a/www/poll/poll.css
+++ b/www/poll/poll.css
@@ -170,6 +170,10 @@ div.realtime table {
border-collapse: collapse;
width: calc(100% - 1px);
}
+form.realtime table .editing,
+div.realtime table .editing {
+ background-color: #88b8cc;
+}
form.realtime table tr td:first-child,
div.realtime table tr td:first-child {
position: absolute;
@@ -225,40 +229,63 @@ div.realtime table tr td.checkbox-cell div.checkbox-contain label {
height: 100%;
width: 100%;
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable),
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) {
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable),
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) {
display: none;
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover,
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover {
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover {
font-weight: bold;
- background-color: #FA5858;
color: #000;
display: block;
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after,
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after {
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover:after,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover:after {
height: 100%;
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after,
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after {
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.yes,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.yes {
+ background-color: #46E981;
+}
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.uncommitted,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.uncommitted {
+ background: #ddd;
+}
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.mine,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"]:not(.editable) ~ .cover.mine {
+ display: none;
+}
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover {
+ background-color: #FA5858;
+}
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover:after,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="0"] ~ .cover:after {
content: "✖";
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes,
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes {
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover {
background-color: #46E981;
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes:after,
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes:after {
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover:after,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="1"] ~ .cover:after {
content: "✔";
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.uncommitted,
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.uncommitted {
- background: #ddd;
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover {
+ background-color: #ff5;
}
-form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.mine,
-div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.mine {
- display: none;
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover:after,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="2"] ~ .cover:after {
+ content: "~";
+}
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover {
+ background-color: #ccc;
+}
+form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover:after,
+div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="number"][value="3"] ~ .cover:after {
+ content: "?";
}
form.realtime table input[type="text"],
div.realtime table input[type="text"] {
@@ -298,8 +325,8 @@ div.realtime table thead td input[type="text"][disabled] {
color: #000;
border: 1px solid transparent;
}
-form.realtime table tbody .text-cell,
-div.realtime table tbody .text-cell {
+form.realtime table tbody td:not(.editing) .text-cell,
+div.realtime table tbody td:not(.editing) .text-cell {
background: #aaa;
}
form.realtime table tbody .text-cell input[type="text"],
diff --git a/www/poll/poll.less b/www/poll/poll.less
index 699e96e03..95b5cfa52 100644
--- a/www/poll/poll.less
+++ b/www/poll/poll.less
@@ -4,10 +4,13 @@
@poll-th-bg: #aaa;
@poll-th-user-bg: #999;
@poll-td-bg: #aaa;
+@poll-editing: #88b8cc;
@poll-placeholder: #666;
@poll-border-color: #555;
@poll-cover-color: #000;
@poll-fg: #000;
+@poll-option-yellow: #ff5;
+@poll-option-gray: #ccc;
html, body {
width: 100%;
@@ -195,6 +198,9 @@ form.realtime, div.realtime {
table {
border-collapse: collapse;
width: ~"calc(100% - 1px)";
+ .editing {
+ background-color: @poll-editing;
+ }
tr {
td:first-child {
position:absolute;
@@ -247,7 +253,7 @@ form.realtime, div.realtime {
}
input {
- &[type="checkbox"] {
+ &[type="number"] {
&:not(.editable) {
display: none;
@@ -255,26 +261,21 @@ form.realtime, div.realtime {
display: block;
font-weight: bold;
- background-color: @cp-red;
color: @poll-cover-color;
&:after {
height: 100%;
}
- &:after { content: "✖"; }
-
display: block;
&.yes {
background-color: @cp-green;
- &:after { content: "✔"; }
}
&.uncommitted {
background: #ddd;
}
-
&.mine {
display: none;
}
@@ -282,6 +283,31 @@ form.realtime, div.realtime {
}
}
}
+
+ input[type="number"][value="0"] {
+ ~ .cover {
+ background-color: @cp-red;
+ &:after { content: "✖"; }
+ }
+ }
+ input[type="number"][value="1"] {
+ ~ .cover {
+ background-color: @cp-green;
+ &:after { content: "✔"; }
+ }
+ }
+ input[type="number"][value="2"] {
+ ~ .cover {
+ background-color: @poll-option-yellow;
+ &:after { content: "~"; }
+ }
+ }
+ input[type="number"][value="3"] {
+ ~ .cover {
+ background-color: @poll-option-gray;
+ &:after { content: "?"; }
+ }
+ }
}
}
}
@@ -327,8 +353,12 @@ form.realtime, div.realtime {
}
tbody {
+ td:not(.editing) {
+ .text-cell {
+ background: @poll-td-bg;
+ }
+ }
.text-cell {
- background: @poll-td-bg;
//border-radius: 20px 0 0 20px;
input[type="text"] {
width: ~"calc(100% - 50px)";
diff --git a/www/poll/render.js b/www/poll/render.js
index 8399d5b71..f84fdc964 100644
--- a/www/poll/render.js
+++ b/www/poll/render.js
@@ -70,7 +70,12 @@ var Renderer = function (Cryptpad) {
};
var getCellValue = Render.getCellValue = function (obj, cellId) {
- return Cryptpad.find(obj, ['table', 'cells'].concat([cellId]));
+ var value = Cryptpad.find(obj, ['table', 'cells'].concat([cellId]));
+ if (typeof value === 'boolean') {
+ return (value === true ? 1 : 0);
+ } else {
+ return value;
+ }
};
var setRowValue = Render.setRowValue = function (obj, rowId, value) {
@@ -234,16 +239,20 @@ var Renderer = function (Cryptpad) {
disabled: 'disabled'
}].concat(cols.map(function (col) {
var id = [col, rows[i-1]].join('_');
- var val = cells[id] || false;
+ var val = cells[id];
var result = {
'data-rt-id': id,
- type: 'checkbox',
+ type: 'number',
autocomplete: 'nope',
+ value: '3',
};
if (readOnly) {
result.disabled = "disabled";
}
- if (val) { result.checked = true; }
+ if (typeof val !== 'undefined') {
+ if (typeof val === 'boolean') { val = (val ? '1' : '0'); }
+ result.value = val;
+ }
return result;
}));
});
@@ -297,9 +306,6 @@ var Renderer = function (Cryptpad) {
attrs.id = cell['data-rt-id'];
var labelClass = 'cover';
- if (cell.checked) {
- labelClass += ' yes';
- }
// TODO implement Yes/No/Maybe/Undecided
return ['TD', {class:"checkbox-cell"}, [
@@ -326,7 +332,7 @@ var Renderer = function (Cryptpad) {
]];
}
- if (cell && cell.type === 'checkbox') {
+ if (cell && cell.type === 'number') {
return makeCheckbox(cell);
}
return ['TD', cell, []];
@@ -399,7 +405,7 @@ var Renderer = function (Cryptpad) {
preDiffApply: function (info) {
if (!diffIsInput(info)) { return; }
switch (getInputType(info)) {
- case 'checkbox':
+ case 'number':
//console.log('checkbox');
//console.log("[preDiffApply]", info);
break;