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;