cryptpad/www/poll/inner.js
2017-10-03 19:04:29 +02:00

1084 lines
39 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

define([
'jquery',
'/bower_components/textpatcher/TextPatcher.js',
'/common/toolbar3.js',
'/common/cryptpad-common.js',
'/common/common-util.js',
'/common/cryptget.js',
'/bower_components/nthen/index.js',
'/common/sframe-common.js',
'/common/common-realtime.js',
'/customize/application_config.js',
'/common/sframe-chainpad-listmap.js',
'/customize/pages.js',
'/poll/render.js',
'/common/diffMarked.js',
'/common/sframe-common-codemirror.js',
'cm/lib/codemirror',
'cm/mode/markdown/markdown',
'css!cm/lib/codemirror.css',
'/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less2/main.less',
], function (
$,
TextPatcher,
Toolbar,
Cryptpad,
Util,
Cryptget,
nThen,
SFCommon,
CommonRealtime,
AppConfig,
Listmap,
Pages,
Renderer,
DiffMd,
SframeCM,
CMeditor)
{
var Messages = Cryptpad.Messages;
var saveAs = window.saveAs;
var Render = Renderer(Cryptpad);
var APP = window.APP = {
Render: Render,
unlocked: {
row: [],
col: []
},
readOnly: false,
Cryptpad: Cryptpad,
mobile: function () { return $('body').width() <= 600; } // Menu and content area are not inline-block anymore for mobiles
};
var debug = $.noop; //console.log;
var HIDE_INTRODUCTION_TEXT = "hide-text";
var metadataMgr;
var Title;
var common;
var copyObject = function (obj) {
return JSON.parse(JSON.stringify(obj));
};
var getCSV = APP.getCSV = function () {
if (!APP.proxy) { return; }
var data = copyObject(APP.proxy.content);
var res = '';
var escapeStr = function (str) {
return '"' + str.replace(/"/g, '""') + '"';
};
[null].concat(data.rowsOrder).forEach(function (rowId, i) {
[null].concat(data.colsOrder).forEach(function (colId, j) {
// thead
if (i === 0) {
if (j === 0) { res += ','; return; }
if (!colId) { throw new Error("Invalid data"); }
res += escapeStr(data.cols[colId] || Messages.anonymous) + ',';
return;
}
// tbody
if (!rowId) { throw new Error("Invalid data"); }
if (j === 0) {
res += escapeStr(data.rows[rowId] || Messages.poll_optionPlaceholder) + ',';
return;
}
if (!colId) { throw new Error("Invalid data"); }
res += (data.cells[colId + '_' + rowId] || 3) + ',';
});
// last column: total
// thead
if (i === 0) {
res += escapeStr(Messages.poll_total) + '\n';
return;
}
// tbody
if (!rowId) { throw new Error("Invalid data"); }
res += APP.count[rowId] || '?';
res += '\n';
});
return res;
};
var exportFile = function () {
var csv = getCSV();
var suggestion = Title.suggestTitle(Title.defaultTitle);
Cryptpad.prompt(Messages.exportPrompt,
Cryptpad.fixFileName(suggestion) + '.csv', function (filename) {
if (!(typeof(filename) === 'string' && filename)) { return; }
var blob = new Blob([csv], {type: "application/csv;charset=utf-8"});
saveAs(blob, filename);
});
};
/*
Make sure that the realtime data structure has all the required fields
*/
var prepareProxy = function (proxy, schema) {
if (proxy && proxy.version === 1) { return; }
debug("Configuring proxy schema...");
proxy.metadata = proxy.metadata || schema.metadata;
Object.keys(schema.metadata).forEach(function (k) {
if (!proxy.metadata[k]) { proxy.metadata[k] = schema.metadata[k]; }
});
proxy.content = proxy.content || schema.content;
Object.keys(schema.content).forEach(function (k) {
if (!proxy.content[k]) { proxy.content[k] = schema.content[k]; }
});
proxy.version = 1;
proxy.type = 'poll';
};
/*
Set the user id (user column) in the pad attributes
*/
var setUserId = function (id, cb) {
cb = cb || $.noop;
APP.userid = id;
common.setPadAttribute('userid', id, function (e) {
if (e) {
console.error(e);
return void cb(e);
}
cb();
});
};
var sortColumns = function (order, firstcol) {
var colsOrder = order.slice();
// Never put at the first position an uncommitted column
if (APP.proxy.content.colsOrder.indexOf(firstcol) === -1) { return colsOrder; }
colsOrder.sort(function (a, b) {
return (a === firstcol) ? -1 :
((b === firstcol) ? 1 : 0);
});
return colsOrder;
};
var isUncommitted = function (id) {
var idArr = id.split('_');
var idx = idArr[0];
var idy = idArr[1] || idArr[0]; // if id is y-{...} (no 'x'), use idArr[0] as 'y' coordinate
return APP.uncommitted.content.colsOrder.indexOf(idx) !== -1 ||
APP.uncommitted.content.rowsOrder.indexOf(idy) !== -1;
};
var mergeUncommitted = function (proxy, uncommitted, commit) {
var newObj;
if (commit) {
newObj = proxy;
} else {
newObj = $.extend(true, {}, proxy);
}
// Merge uncommitted into the proxy
uncommitted.content.colsOrder = uncommitted.content.colsOrder || [];
uncommitted.content.colsOrder.forEach(function (x) {
if (newObj.content.colsOrder.indexOf(x) !== -1) { return; }
newObj.content.colsOrder.push(x);
});
for (var k in uncommitted.content.cols) {
if (!newObj.content.cols[k]) {
newObj.content.cols[k] = uncommitted.content.cols[k];
}
}
for (var l in uncommitted.content.cells) {
if (!newObj.content.cells[l]) {
newObj.content.cells[l] = uncommitted.content.cells[l];
}
}
// Uncommitted rows
uncommitted.content.rowsOrder = uncommitted.content.rowsOrder || [];
uncommitted.content.rowsOrder.forEach(function (x) {
if (newObj.content.rowsOrder.indexOf(x) !== -1) { return; }
newObj.content.rowsOrder.push(x);
});
for (var m in uncommitted.content.rows) {
if (!newObj.content.rows[m]) {
newObj.content.rows[m] = uncommitted.content.rows[m];
}
}
if (commit) {
APP.uncommited = {};
prepareProxy(APP.uncommitted, copyObject(Render.Example));
}
return newObj;
};
var styleUserColumn = function () {
var userid = APP.userid;
if (!userid) { return; }
// Enable input for the userid column
$('input[disabled="disabled"][data-rt-id^="' + userid + '"]').removeAttr('disabled')
.attr('placeholder', Messages.poll_userPlaceholder);
$('input[type="number"][data-rt-id^="' + userid + '"]').addClass('enabled');
$('.cp-app-poll-table-lock[data-rt-id="' + userid + '"]').remove();
$('[data-rt-id^="' + userid + '"]').closest('td')
.addClass("cp-app-poll-table-own");
$('.cp-app-poll-table-bookmark[data-rt-id="' + userid + '"]').css('visibility', '')
.addClass('cp-app-poll-table-bookmark-full')
.attr('title', Messages.poll_bookmarked_col);
};
var styleUncommittedColumn = function () {
var $scroll = $('#cp-app-poll-table-scroll');
var hasScroll = $scroll.width() < $scroll[0].scrollWidth;
APP.uncommitted.content.colsOrder.forEach(function(id) {
// Enable the checkboxes for the uncommitted column
$('input[disabled="disabled"][data-rt-id^="' + id + '"]').removeAttr('disabled');
$('input[type="number"][data-rt-id^="' + id + '"]').addClass('enabled');
$('.cp-app-poll-table-lock[data-rt-id="' + id + '"]').remove();
//.addClass('fa-unlock').removeClass('fa-lock').attr('title', Messages.poll_unlocked);
$('.cp-app-poll-table-remove[data-rt-id="' + id + '"]').remove();
$('.cp-app-poll-table-bookmark[data-rt-id="' + id + '"]').remove();
$('td.cp-app-poll-table-uncommitted .cover').addClass("cp-app-poll-table-uncommitted");
var $uncommittedCol = $('[data-rt-id^="' + id + '"]').closest('td');
$uncommittedCol.addClass("cp-app-poll-table-uncommitted");
if (hasScroll) {
$uncommittedCol.css('right', '100px');
}
});
APP.uncommitted.content.rowsOrder.forEach(function(id) {
// Enable the checkboxes for the uncommitted column
$('input[disabled="disabled"][data-rt-id="' + id + '"]').removeAttr('disabled');
$('.cp-app-poll-table-edit[data-rt-id="' + id + '"]').remove();
$('.cp-app-poll-table-remove[data-rt-id="' + id + '"]').remove();
$('[data-rt-id="' + id + '"]').closest('tr').addClass("cp-app-poll-table-uncommitted");
//$('td.uncommitted .cover').addClass("uncommitted");
//$('.uncommitted input[type="text"]').attr("placeholder", Messages.poll_userPlaceholder);
});
};
var unlockElements = function () {
APP.unlocked.row.forEach(function (id) {
var $input = $('input[type="text"][disabled="disabled"][data-rt-id="' + id + '"]').removeAttr('disabled');
$input.parent().parent().addClass('cp-app-poll-table-editing');
$('span.cp-app-poll-table-edit[data-rt-id="' + id + '"]').css('visibility', 'hidden');
});
APP.unlocked.col.forEach(function (id) {
var $input = $('input[disabled="disabled"][data-rt-id^="' + id + '"]')
.removeAttr('disabled');
$input.parent().addClass('cp-app-poll-table-editing');
$('input[type="number"][data-rt-id^="' + id + '"]').addClass('enabled');
$('.cp-app-poll-table-lock[data-rt-id="' + id + '"]').addClass('fa-unlock')
.removeClass('fa-lock').attr('title', Messages.poll_unlocked);
});
};
var updateTableButtons = function () {
var uncomColId = APP.uncommitted.content.colsOrder[0];
var uncomRowId = APP.uncommitted.content.rowsOrder[0];
var $createOption = APP.$table.find('tbody input[data-rt-id="' + uncomRowId+'"]')
.closest('td').find('> div');
$createOption.append(APP.$createRow);
var $createUser = APP.$table.find('thead input[data-rt-id="' + uncomColId + '"]')
.closest('td');
$createUser.prepend(APP.$createCol);
if (APP.proxy.content.colsOrder.indexOf(APP.userid) === -1) {
APP.$table.find('.cp-app-poll-table-bookmark').css('visibility', '');
}
//$('#cp-app-poll-create-user, #cp-app-poll-create-option').css('display', 'inline-flex');
if (!APP.proxy ||
!APP.proxy.content.rowsOrder ||
APP.proxy.content.rowsOrder.length === 0) {
//$('#create-user').hide();
}
var width = $('#cp-app-poll-table').outerWidth();
if (width) {
//$('#create-user').css('left', width + 30 + 'px');
}
};
var setTablePublished = function (bool) {
if (bool) {
if (APP.$publish) { APP.$publish.hide(); }
if (APP.$admin) { APP.$admin.show(); }
$('#cp-app-poll-form').addClass('cp-app-poll-published');
} else {
if (APP.$publish) { APP.$publish.show(); }
if (APP.$admin) { APP.$admin.hide(); }
$('#cp-app-poll-form').removeClass('cp-app-poll-published');
}
};
var addCount = function () {
var $scroll = $('#cp-app-poll-table-scroll');
var hasScroll = $scroll.width() < $scroll[0].scrollWidth;
var $countCol = $('tr td:last-child');
if (hasScroll) {
$countCol.css('right', '0');
}
var $thead = APP.$table.find('thead');
var $tr = APP.$table.find('tbody tr').first();
$thead.find('tr td').last()
.css({
'height': $thead.height()+'px',
'text-align': 'center',
'line-height': $thead.height()+'px'
})
.text(Messages.poll_total);
var winner = {
v: 0,
ids: []
};
APP.count = {};
APP.proxy.content.rowsOrder.forEach(function (rId) {
var count = Object.keys(APP.proxy.content.cells)
.filter(function (k) {
return k.indexOf(rId) !== -1 && APP.proxy.content.cells[k] === 1;
}).length;
if (count > winner.v) {
winner.v = count;
winner.ids = [rId];
} else if (count && count === winner.v) {
winner.ids.push(rId);
}
APP.count[rId] = count;
APP.$table.find('[data-rt-count-id="' + rId + '"]')
.text(count)
.css({
'height': $tr.height()+'px',
'line-height': $tr.height()+'px'
});
});
winner.ids.forEach(function (rId) {
$('[data-rt-id="' + rId + '"]').closest('td').addClass('cp-app-poll-table-winner');
$('[data-rt-count-id="' + rId + '"]').addClass('cp-app-poll-table-winner');
});
};
var updateDisplayedTable = function () {
styleUserColumn();
styleUncommittedColumn();
unlockElements();
updateTableButtons();
setTablePublished(APP.proxy.published);
addCount();
};
var unlockColumn = function (id, cb) {
if (APP.unlocked.col.indexOf(id) === -1) {
APP.unlocked.col.push(id);
}
if (typeof(cb) === "function") {
cb();
}
};
var unlockRow = function (id, cb) {
if (APP.unlocked.row.indexOf(id) === -1) {
APP.unlocked.row.push(id);
}
if (typeof(cb) === "function") {
cb();
}
};
var lockColumn = function (id, cb) {
var idx = APP.unlocked.col.indexOf(id);
if (idx !== -1) {
APP.unlocked.col.splice(idx, 1);
}
if (typeof(cb) === "function") {
cb();
}
};
var lockRow = function (id, cb) {
var idx = APP.unlocked.row.indexOf(id);
if (idx !== -1) {
APP.unlocked.row.splice(idx, 1);
}
if (typeof(cb) === "function") {
cb();
}
};
/* Any time the realtime object changes, call this function */
var change = function (o, n, path, throttle, cb) {
if (path && !Cryptpad.isArray(path)) {
return;
}
if (path && path.join) {
debug("Change from [%s] to [%s] at [%s]",
o, n, path.join(', '));
}
var table = APP.$table[0];
var displayedObj = mergeUncommitted(APP.proxy, APP.uncommitted);
var colsOrder = sortColumns(displayedObj.content.colsOrder, APP.userid);
var conf = {
cols: colsOrder,
readOnly: APP.readOnly
};
common.notify();
var getFocus = function () {
var active = document.activeElement;
if (!active) { return; }
return {
el: active,
id: $(active).attr('data-rt-id'),
start: active.selectionStart,
end: active.selectionEnd
};
};
var setFocus = function (obj) {
var el;
if (document.body.contains(obj.el)) { el = obj.el; }
else if($('input[data-rt-id="' + obj.id + '"]').length) {
el = $('input[data-rt-id="' + obj.id + '"]')[0];
}
else { return; }
el.focus();
if (obj.start) { el.selectionStart = obj.start; }
if (obj.end) { el.selectionEnd = obj.end; }
};
var updateTable = function () {
var displayedObj2 = mergeUncommitted(APP.proxy, APP.uncommitted);
var f = getFocus();
APP.$createRow.detach();
APP.$createCol.detach();
Render.updateTable(table, displayedObj2, conf);
// Fix autocomplete bug:
displayedObj2.content.rowsOrder.forEach(function (rowId) {
$('input[data-rt-id="' + rowId +'"]').val(displayedObj2.content.rows[rowId] || '');
});
displayedObj2.content.colsOrder.forEach(function (rowId) {
$('input[data-rt-id="' + rowId +'"]')
.val(displayedObj2.content.cols[rowId] || '');
});
updateDisplayedTable();
setFocus(f);
if (typeof(cb) === "function") {
cb();
}
};
if (throttle) {
if (APP.throttled) { window.clearTimeout(APP.throttled); }
updateTable();
APP.throttled = window.setTimeout(function () {
updateDisplayedTable();
}, throttle);
return;
}
window.setTimeout(updateTable);
};
var getRealtimeId = function (input) {
return input.getAttribute && input.getAttribute('data-rt-id');
};
var handleBookmark = function (id) {
setUserId(id === APP.userid ? '' : id, change);
};
/* Called whenever an event is fired on an input element */
var handleInput = function (input) {
var type = input.type.toLowerCase();
var id = getRealtimeId(input);
debug(input);
var object = APP.proxy;
var x = Render.getCoordinates(id)[0];
if (isUncommitted(id)) { object = APP.uncommitted; }
switch (type) {
case 'text':
debug("text[rt-id='%s'] [%s]", id, input.value);
Render.setValue(object, id, input.value);
change(null, null, null, 50);
break;
case 'number':
debug("checkbox[tr-id='%s'] %s", id, input.value);
if (APP.unlocked.col.indexOf(x) >= 0 || x === APP.userid) {
var value = parseInt(input.value);
if (isNaN(value)) {
console.error("Got NaN?!");
break;
}
Render.setValue(object, id, value);
change();
} else {
debug('checkbox locked');
}
break;
default:
debug("Input[type='%s']", type);
break;
}
};
var hideInputs = function (id) {
if (APP.readOnly) { return; }
if (id) {
var type = Render.typeofId(id);
console.log(type);
if (type === 'col') { return void lockColumn(id, change); }
if (type === 'row') { return void lockRow(id, change); }
return;
}
APP.unlocked.col = Cryptpad.deduplicateString([APP.userid].concat(APP.uncommitted.content.colsOrder).slice());
APP.unlocked.row = APP.uncommitted.content.rowsOrder.slice();
change();
};
/* Called whenever an event is fired on a span */
var handleSpan = function (span) {
if (!span) { return; }
var id = span.getAttribute('data-rt-id');
var type = Render.typeofId(id);
var isRemove = span.className && span.className.split(' ')
.indexOf('cp-app-poll-table-remove') !== -1;
var isEdit = span.className && span.className.split(' ')
.indexOf('cp-app-poll-table-edit') !== -1;
var isBookmark = span.className && span.className.split(' ')
.indexOf('cp-app-poll-table-bookmark') !== -1;
var isLock = span.className && span.className.split(' ')
.indexOf('cp-app-poll-table-lock') !== -1;
var isLocked = span.className && span.className.split(' ').indexOf('fa-lock') !== -1;
if (type === 'row') {
if (isRemove) {
Cryptpad.confirm(Messages.poll_removeOption, function (res) {
if (!res) { return; }
Render.removeRow(APP.proxy, id, function () {
change();
});
});
} else if (isEdit) {
unlockRow(id, function () {
change(null, null, null, null, function() {
$('input[data-rt-id="' + id + '"]').focus();
});
});
}
} else if (type === 'col') {
if (isRemove) {
Cryptpad.confirm(Messages.poll_removeUser, function (res) {
if (!res) { return; }
Render.removeColumn(APP.proxy, id, function () {
change();
if (id === APP.userid) { setUserId(''); }
});
});
} else if (isBookmark) {
handleBookmark(id);
} else if (isLock && isLocked) {
unlockColumn(id, function () {
change(null, null, null, null, function() {
$('input[data-rt-id="' + id + '"]').focus();
});
});
} else if (isLock) {
lockColumn(id, function () {
change(null, null, null, null, function() {
});
});
}
} else if (type === 'cell') {
change();
} else {
debug("UNHANDLED");
}
};
var handleClick = function (e, isKeyup) {
if (APP.readOnly) { 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"); }
var nodeName = target && target.nodeName;
switch (nodeName) {
case 'INPUT':
if (isKeyup && (e.keyCode === 13 || e.keyCode === 27)) {
var id = target.getAttribute('data-rt-id');
if ($(target).parents('.cp-app-poll-table-uncommitted').length
&& e.keyCode === 13) {
var type = Render.typeofId(id);
if (type === "row") { APP.$createRow.click(); }
else if (type === "col") { APP.$createCol.click(); }
break;
}
hideInputs(id);
break;
}
if ($(target).is('input[type="number"]')) {
// Nothing to do...
//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':
handleSpan(target);
break;
case undefined:
//console.error(new Error("C'est pas possible!"));
break;
default:
debug(target, nodeName);
break;
}
};
/*
*/
var updatePublishButton = function () {
if (!APP.ready || !APP.proxy || !APP.$publishButton) { return; }
var p = APP.proxy.published;
var msg = (p ? Messages.poll_admin_button : Messages.poll_publish_button);
APP.$publishButton.attr('title', msg);
if (p) {
APP.$publishButton.removeClass('fa-check').addClass('fa-pencil');
return;
}
APP.$publishButton.addClass('fa-check').removeClass('fa-pencil');
};
var publish = APP.publish = function (bool) {
if (!APP.readOnly) {
if (!APP.ready) { return; }
if (APP.proxy.published !== bool) {
APP.proxy.published = bool;
}
} else {
// If readOnly, always put the app in published mode
bool = true;
}
setTablePublished(bool);
/*['textarea'].forEach(function (sel) {
$(sel).attr('disabled', bool);
});*/
updatePublishButton();
};
var updateHelpButton = function () {
if (!APP.$helpButton) { return; }
var help = $('#cp-app-poll-help').is(':visible');
var msg = (help ? Messages.poll_hide_help_button : Messages.poll_show_help_button);
APP.$helpButton.attr('title', msg);
if (help) {
APP.$helpButton.addClass('cp-toolbar-button-active');
return;
}
APP.$helpButton.removeClass('cp-toolbar-button-active');
};
var showHelp = function(help) {
if (typeof help === 'undefined') {
help = !$('#cp-app-poll-help').is(':visible');
}
var msg = (help ? Messages.poll_hide_help_button : Messages.poll_show_help_button);
$('#cp-app-poll-help').toggle(help);
$('#cp-app-poll-action-help').text(msg);
updateHelpButton();
};
var setEditable = function (editable) {
APP.readOnly = !editable;
if (editable === false) {
// disable all the things
$('.icp-app-poll-realtime input, .cp-app-poll-realtime button, .cp-app-poll-upper button, .cp-app-poll-realtime textarea').attr('disabled', true);
$('span.cp-app-poll-table-edit, span.cp-app-poll-table-remove').hide();
$('span.cp-app-poll-table-lock').addClass('fa-lock').removeClass('fa-unlock')
.attr('title', Messages.poll_locked)
.css({'cursor': 'default'});
} else {
// enable
$('span.cp-app-poll-table-edit, span.cp-app-poll-table-remove').show();
$('span.cp-app-poll-table-lock').css({'cursor': ''});
$('.cp-app-poll-realtime button, .cp-app-poll-upper button, .cp-app-poll-realtime textarea').attr('disabled', false);
unlockElements();
}
};
var updatePublishedDescription = function () {
var v = APP.editor.getValue();
DiffMd.apply(DiffMd.render(v || Messages.poll_descriptionHint), APP.$descriptionPublished);
};
var updateDescription = function (old, n) {
var o = APP.$description.val();
SframeCM.setValueAndCursor(APP.editor, o, n, TextPatcher);
updatePublishedDescription();
common.notify();
};
var updateLocalDescription = function (n) {
APP.proxy.description = n;
updatePublishedDescription();
};
var onReady = function (info, userid) {
var proxy = APP.proxy;
var isNew = false;
var userDoc = JSON.stringify(proxy);
if (userDoc === "" || userDoc === "{}") { isNew = true; }
if (!isNew) {
if (proxy.info) {
// Migration??
proxy.metadata = proxy.info;
delete proxy.info;
}
if (proxy.table) {
// Migration??
proxy.content = proxy.table;
delete proxy.table;
}
if (proxy && proxy.metadata) {
metadataMgr.updateMetadata(proxy.metadata);
}
if (typeof (proxy) !== 'object' || Array.isArray(proxy) ||
(proxy.metadata && typeof(proxy.metadata.type) !== 'undefined' &&
proxy.metadata.type !== 'poll')) {
var errorText = Messages.typeError;
Cryptpad.errorLoadingScreen(errorText);
throw new Error(errorText);
}
} else {
Title.updateTitle(Title.defaultTitle);
}
if (typeof(proxy.type) === 'undefined') {
proxy.type = 'poll';
}
// Add uncommitted and unlock uncommited & own column
var uncommitted = APP.uncommitted = {};
prepareProxy(proxy, copyObject(Render.Example));
prepareProxy(uncommitted, copyObject(Render.Example));
if (!APP.readOnly) {
var coluid = Render.coluid();
if (proxy.content.colsOrder.indexOf(userid) === -1 &&
uncommitted.content.colsOrder.indexOf(userid) === -1) {
// The user doesn't have his own column: the new one should be his
coluid = userid;
} else {
// The user already has his own column: unlock it
unlockColumn(userid);
}
uncommitted.content.colsOrder.push(coluid);
unlockColumn(coluid);
var rowuid = Render.rowuid();
uncommitted.content.rowsOrder.push(rowuid);
unlockRow(coluid);
}
var displayedObj = mergeUncommitted(proxy, uncommitted, false);
var colsOrder = sortColumns(displayedObj.content.colsOrder, userid);
var $table = APP.$table = $(Render.asHTML(displayedObj, null, colsOrder, APP.readOnly));
var getUncommitted = function (type) {
var ret = {}, toRemove;
var uncommitted = APP.uncommitted.content;
if (type === 'col') {
ret.colsOrder = uncommitted.colsOrder.slice();
ret.cols = copyObject(uncommitted.cols);
// get only the cells corresponding to the committed rows
toRemove = Object.keys(uncommitted.cells).filter(function (coor) {
var c = Render.getCoordinates(coor);
return APP.proxy.content.rowsOrder.indexOf(c[1]) !== -1;
});
ret.cells = {};
toRemove.forEach(function (k) {
ret.cells[k] = uncommitted.cells[k];
delete uncommitted.cells[k];
});
uncommitted.colsOrder = [Render.coluid()];
uncommitted.cols = {};
return ret;
}
// Row
ret.rowsOrder = uncommitted.rowsOrder.slice();
ret.rows = copyObject(uncommitted.rows);
// get only the cells corresponding to the committed rows
toRemove = Object.keys(uncommitted.cells).filter(function (coor) {
var c = Render.getCoordinates(coor);
return APP.proxy.content.colsOrder.indexOf(c[1]) !== -1;
});
ret.cells = {};
toRemove.forEach(function (k) {
ret.cells[k] = uncommitted.cells[k];
delete uncommitted.cells[k];
});
uncommitted.rowsOrder = [Render.rowuid()];
uncommitted.rows = {};
console.log(JSON.stringify(ret, 0, 2));
return ret;
};
APP.$createCol = $('#cp-app-poll-create-user').click(function () {
var uncommittedCopy = { content: getUncommitted('col') };
var id = uncommittedCopy.content.colsOrder[0];
if (!APP.userid) { setUserId(id); }
mergeUncommitted(proxy, uncommittedCopy, true);
change(null, null, null, null, function() {
handleSpan($('.cp-app-poll-table-lock[data-rt-id="' + id + '"]')[0]);
});
});
APP.$createRow = $('#cp-app-poll-create-option').click(function () {
var uncommittedCopy = { content: getUncommitted('row') };
mergeUncommitted(proxy, uncommittedCopy, true);
change(null, null, null, null, function() {
var newId = APP.uncommitted.content.rowsOrder[0];
$('input[data-rt-id="' + newId + '"]').focus();
});
});
// Description
APP.editor.on('change', function () {
var val = APP.editor.getValue();
updateLocalDescription(val);
});
$('#cp-app-poll-table-scroll').html('').prepend($table);
updateDisplayedTable();
updateDescription(null, APP.proxy.description);
$table
.click(handleClick)
.on('keyup', function (e) { handleClick(e, true); });
$(window).click(function(e) {
if (e.which !== 1) { return; }
hideInputs();
});
proxy
.on('change', ['metadata'], function () {
metadataMgr.updateMetadata(proxy.metadata);
})
.on('change', ['content'], change)
.on('change', ['description'], updateDescription)
.on('remove', [], change);
// If the user's column is not committed, add his username
var $userInput = $('.cp-app-poll-table-uncommitted > input[data-rt-id^='+ APP.userid +']');
if ($userInput.val() === '') {
var uname = metadataMgr.getUserData().name;
APP.uncommitted.content.cols[APP.userid] = uname;
$userInput.val(uname);
}
APP.ready = true;
if (!proxy.published) {
publish(false);
} else {
publish(true);
}
Cryptpad.removeLoadingScreen();
if (isNew) {
common.openTemplatePicker();
}
};
var onDisconnect = function () {
setEditable(false);
Cryptpad.alert(Messages.common_connectionLost, undefined, true);
};
var onReconnect = function () {
setEditable(true);
Cryptpad.findOKButton().click();
};
var onCreate = function (info) {
APP.myID = info.myID;
if (APP.realtime !== info.realtime) {
APP.realtime = info.realtime;
APP.patchText = TextPatcher.create({
realtime: info.realtime,
logging: true,
});
}
metadataMgr = common.getMetadataMgr();
Title = common.createTitle();
var configTb = {
displayed: ['title', 'useradmin', 'spinner', 'share', 'userlist', 'newpad', 'limit'],
title: Title.getTitleConfig(),
metadataMgr: metadataMgr,
readOnly: APP.readOnly,
realtime: info.realtime,
common: Cryptpad,
sfCommon: common,
$container: APP.$bar,
$contentContainer: APP.$content
};
APP.toolbar = Toolbar.create(configTb);
Title.setToolbar(APP.toolbar);
var $rightside = APP.toolbar.$rightside;
metadataMgr.onChange(function () {
var md = copyObject(metadataMgr.getMetadata());
APP.proxy.metadata = md;
});
/* add a forget button */
var forgetCb = function (err) {
if (err) { return; }
setEditable(false);
};
var $forgetPad = common.createButton('forget', true, {}, forgetCb);
$rightside.append($forgetPad);
/* save as template */
if (!metadataMgr.getPrivateData().isTemplate) {
var templateObj = {
rt: info.realtime,
getTitle: function () { return metadataMgr.getMetadata().title; }
};
var $templateButton = common.createButton('template', true, templateObj);
$rightside.append($templateButton);
}
/* add an export button */
var $export = common.createButton('export', true, {}, exportFile);
$rightside.append($export);
var $help = common.createButton('', true).click(function () { showHelp(); })
.appendTo($rightside);
APP.$helpButton = $help;
updateHelpButton();
if (APP.readOnly) { publish(true); return; }
var $publish = common.createButton('', true)
.removeClass('fa-question').addClass('fa-check')
.click(function () { publish(!APP.proxy.published); }).appendTo($rightside);
APP.$publishButton = $publish;
updatePublishButton();
};
var main = function () {
nThen(function (waitFor) {
$(waitFor(function () {
Cryptpad.addLoadingScreen();
var $div = $('<div>').append(Pages['/poll/']());
$('body').append($div.html());
}));
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
}).nThen(function (waitFor) {
var privReady = Util.once(waitFor());
var metadataMgr = common.getMetadataMgr();
if (JSON.stringify(metadataMgr.getPrivateData()) !== '{}') {
privReady();
return;
}
metadataMgr.onChange(function () {
if (typeof(metadataMgr.getPrivateData().readOnly) === 'boolean') {
APP.readOnly = metadataMgr.getPrivateData().readOnly;
privReady();
}
});
}).nThen(function (/* waitFor */) {
APP.loggedIn = common.isLoggedIn();
APP.SFCommon = common;
APP.$body = $('body');
APP.$bar = $('#cp-toolbar');
APP.$content = $('#cp-app-poll-content');
APP.$descriptionPublished = $('#cp-app-poll-description-published');
APP.$description = $('#cp-app-poll-description')
.attr('placeholder', Messages.poll_descriptionHint || 'description');
APP.editor = CMeditor.fromTextArea(APP.$description[0], {
lineNumbers: true,
lineWrapping: true,
styleActiveLine : true,
mode: "markdown",
});
var listmapConfig = {
data: {},
common: common,
logLevel: 1
};
if (APP.readOnly) {
$('#cp-app-poll-create-user, #cp-app-poll-create-option').remove();
}
var rt = APP.rt = Listmap.create(listmapConfig);
APP.proxy = rt.proxy;
rt.proxy.on('create', onCreate)
.on('ready', function (info) {
common.getPadAttribute('userid', function (e, userid) {
if (e) { console.error(e); }
if (!userid) { userid = Render.coluid(); }
APP.userid = userid;
onReady(info, userid);
});
})
.on('disconnect', onDisconnect)
.on('reconnect', onReconnect);
common.getAttribute(['poll', HIDE_INTRODUCTION_TEXT], function (e, value) {
if (e) { console.error(e); }
if (!value) {
common.setAttribute(['poll', HIDE_INTRODUCTION_TEXT], "1", function (e) {
if (e) { console.error(e); }
});
showHelp(true);
} else {
showHelp(false);
}
});
});
};
main();
});