Merge branch 'infiniteSpinner' into fileManager
This commit is contained in:
@@ -4,7 +4,8 @@ define([
|
||||
'/bower_components/hyperjson/hyperjson.js',
|
||||
'/bower_components/textpatcher/TextPatcher.amd.js',
|
||||
'json.sortify',
|
||||
], function (jQuery, Hyperjson, TextPatcher, Sortify) {
|
||||
'/common/cryptpad-common.js',
|
||||
], function (jQuery, Hyperjson, TextPatcher, Sortify, Cryptpad) {
|
||||
var $ = window.jQuery;
|
||||
window.Hyperjson = Hyperjson;
|
||||
window.TextPatcher = TextPatcher;
|
||||
@@ -140,6 +141,19 @@ define([
|
||||
strungJSON(orig);
|
||||
});
|
||||
|
||||
assert(function () {
|
||||
var missing = Cryptpad.Messages._checkTranslationState();
|
||||
|
||||
if (missing.length !== 0) {
|
||||
missing.forEach(function (msg) {
|
||||
console.log('* ' + msg);
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, "expected all translation keys in default language to be present in all translations. See console for details.");
|
||||
|
||||
var swap = function (str, dict) {
|
||||
return str.replace(/\{\{(.*?)\}\}/g, function (all, key) {
|
||||
return typeof dict[key] !== 'undefined'? dict[key] : all;
|
||||
|
||||
@@ -253,18 +253,21 @@ define([
|
||||
var clike = /^\s*(\/\*|\/\/)(.*)?(\*\/)*$/;
|
||||
if (clike.test(line)) {
|
||||
line.replace(clike, function (a, one, two) {
|
||||
if (!(two && two.replace)) { return; }
|
||||
text = two.replace(/\*\/\s*$/, '').trim();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO make one more pass for multiline comments
|
||||
});
|
||||
|
||||
return text.trim();
|
||||
};
|
||||
|
||||
var suggestName = function () {
|
||||
var suggestName = function (fallback) {
|
||||
if (document.title === defaultName) {
|
||||
return getHeadingText() || "";
|
||||
return getHeadingText() || fallback || "";
|
||||
} else {
|
||||
return document.title || getHeadingText() || defaultName;
|
||||
}
|
||||
@@ -275,7 +278,7 @@ define([
|
||||
|
||||
var ext = Modes.extensionOf(module.highlightMode);
|
||||
|
||||
var title = Cryptpad.fixFileName(suggestName()) + ext;
|
||||
var title = Cryptpad.fixFileName(suggestName('cryptpad')) + (ext || '.txt');
|
||||
|
||||
Cryptpad.prompt(Messages.exportPrompt, title, function (filename) {
|
||||
if (filename === null) { return; }
|
||||
@@ -495,9 +498,7 @@ define([
|
||||
}
|
||||
|
||||
// set the hash
|
||||
if (!readOnly) {
|
||||
window.location.hash = editHash;
|
||||
}
|
||||
if (!readOnly) { Cryptpad.replaceHash(editHash); }
|
||||
|
||||
Cryptpad.getPadTitle(function (err, title) {
|
||||
if (err) {
|
||||
@@ -686,6 +687,11 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
var onError = config.onError = function (info) {
|
||||
module.spinner.hide();
|
||||
Cryptpad.alert(Messages.websocketError);
|
||||
};
|
||||
|
||||
var realtime = module.realtime = Realtime.start(config);
|
||||
|
||||
editor.on('change', onLocal);
|
||||
|
||||
@@ -28,6 +28,7 @@ define([
|
||||
|
||||
var common = {
|
||||
User: User,
|
||||
Messages: Messages,
|
||||
};
|
||||
var store;
|
||||
var fsStore;
|
||||
@@ -238,6 +239,14 @@ define([
|
||||
return secret;
|
||||
};
|
||||
|
||||
var replaceHash = common.replaceHash = function (hash) {
|
||||
if (window.history && window.history.replaceState) {
|
||||
if (!/^#/.test(hash)) { hash = '#' + hash; }
|
||||
return void window.history.replaceState({}, window.document.title, hash);
|
||||
}
|
||||
window.location.hash = hash;
|
||||
};
|
||||
|
||||
var storageKey = common.storageKey = 'CryptPad_RECENTPADS';
|
||||
|
||||
/*
|
||||
@@ -580,6 +589,7 @@ define([
|
||||
$(function() {
|
||||
// Race condition : if document.body is undefined when alertify.js is loaded, Alertify
|
||||
// won't work. We have to reset it now to make sure it uses a correct "body"
|
||||
|
||||
Alertify.reset();
|
||||
if($('#pad-iframe').length) {
|
||||
var $iframe = $('#pad-iframe');
|
||||
@@ -869,6 +879,7 @@ define([
|
||||
var styleAlerts = common.styleAlerts = function (href) {
|
||||
var $link = $('link[href="/customize/alertify.css"]');
|
||||
if ($link.length) {
|
||||
return;
|
||||
$link.attr('href', '');
|
||||
$link.attr('href', '/customize/alertify.css');
|
||||
return;
|
||||
|
||||
@@ -313,12 +313,11 @@ define([
|
||||
}
|
||||
}
|
||||
else if (!firstConnection) {
|
||||
lagErrors++;
|
||||
// Display the red light at the 2nd failed attemp to get the lag
|
||||
if (lagErrors > 1) {
|
||||
//if (lagErrors > 1) {
|
||||
lagLight.addClass('lag-red');
|
||||
title = Messages.redLight;
|
||||
}
|
||||
//}
|
||||
}
|
||||
if (title) {
|
||||
lagLight.attr('title', title);
|
||||
|
||||
@@ -35,8 +35,23 @@ define([
|
||||
window.Toolbar = Toolbar;
|
||||
window.Hyperjson = Hyperjson;
|
||||
|
||||
var slice = function (coll) {
|
||||
return Array.prototype.slice.call(coll);
|
||||
};
|
||||
|
||||
var removeListeners = function (root) {
|
||||
slice(root.attributes).map(function (attr) {
|
||||
if (/^on/.test(attr.name)) {
|
||||
root.attributes.removeNamedItem(attr.name);
|
||||
}
|
||||
});
|
||||
slice(root.children).forEach(removeListeners);
|
||||
};
|
||||
|
||||
var hjsonToDom = function (H) {
|
||||
return Hyperjson.toDOM(H); //callOn(H, Hyperscript);
|
||||
var dom = Hyperjson.toDOM(H);
|
||||
removeListeners(dom);
|
||||
return dom;
|
||||
};
|
||||
|
||||
var module = window.REALTIME_MODULE = window.APP = {
|
||||
@@ -321,9 +336,9 @@ define([
|
||||
})) { return text; }
|
||||
};
|
||||
|
||||
var suggestName = function () {
|
||||
var suggestName = function (fallback) {
|
||||
if (document.title === defaultName) {
|
||||
return getHeadingText() || "";
|
||||
return getHeadingText() || fallback || "";
|
||||
} else {
|
||||
return document.title || getHeadingText() || defaultName;
|
||||
}
|
||||
@@ -510,7 +525,7 @@ define([
|
||||
|
||||
var exportFile = function () {
|
||||
var html = getHTML();
|
||||
var suggestion = suggestName();
|
||||
var suggestion = suggestName('cryptpad-document');
|
||||
Cryptpad.prompt(Messages.exportPrompt,
|
||||
Cryptpad.fixFileName(suggestion) + '.html', function (filename) {
|
||||
if (!(typeof(filename) === 'string' && filename)) { return; }
|
||||
@@ -601,9 +616,7 @@ define([
|
||||
}
|
||||
|
||||
// set the hash
|
||||
if (!readOnly) {
|
||||
window.location.hash = editHash;
|
||||
}
|
||||
if (!readOnly) { Cryptpad.replaceHash(editHash); }
|
||||
|
||||
Cryptpad.getPadTitle(function (err, title) {
|
||||
if (err) {
|
||||
@@ -678,6 +691,11 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
var onError = realtimeOptions.onError = function (info) {
|
||||
module.spinner.hide();
|
||||
Cryptpad.alert(Messages.websocketError);
|
||||
};
|
||||
|
||||
var onLocal = realtimeOptions.onLocal = function () {
|
||||
if (initializing) { return; }
|
||||
if (readOnly) { return; }
|
||||
|
||||
@@ -72,6 +72,23 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
var getLastName = module.getLastName = function (cb) {
|
||||
Cryptpad.getAttribute('username', function (err, userName) {
|
||||
cb(err, userName || '');
|
||||
});
|
||||
};
|
||||
|
||||
var setName = module.setName = function (uname, cb) {
|
||||
if (typeof(uname) !== 'string') {
|
||||
return void cb(new Error('expected string'));
|
||||
}
|
||||
uname = Cryptpad.fixHTML(uname.trim()).slice(0, 32);
|
||||
Cryptpad.setAttribute('username', uname, function (err, data) {
|
||||
if (err) { return void cb(err); }
|
||||
cb(void 0, uname);
|
||||
});
|
||||
};
|
||||
|
||||
module.Wizard = Wizard;
|
||||
|
||||
// special UI elements
|
||||
@@ -320,12 +337,19 @@ define([
|
||||
};
|
||||
|
||||
var scrollDown = module.scrollDown = function (px) {
|
||||
if (module.scrolling) { return; }
|
||||
|
||||
module.scrolling = true;
|
||||
|
||||
var top = $(window).scrollTop() + px + 'px';
|
||||
$('html, body').animate({
|
||||
scrollTop: top,
|
||||
}, {
|
||||
duration: 200,
|
||||
easing: 'swing',
|
||||
complete: function () {
|
||||
module.scrolling = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -397,7 +421,10 @@ define([
|
||||
addIfAbsent(proxy.table.rowsOrder, id);
|
||||
|
||||
var $row = table.addRow($wrapper, Checkbox, id);
|
||||
scrollDown($row.height());
|
||||
|
||||
if (module.ready) {
|
||||
scrollDown($row.height());
|
||||
}
|
||||
|
||||
return $option;
|
||||
};
|
||||
@@ -408,7 +435,7 @@ define([
|
||||
|
||||
var msg = Messages.poll_addUser;
|
||||
Cryptpad.prompt(msg, "", function (name) {
|
||||
if (name === null) { return; }
|
||||
if (!(name && name.trim())) { return; }
|
||||
makeUser(module.rt.proxy, id, name).val(name);
|
||||
makeUserEditable(id, true).focus();
|
||||
});
|
||||
@@ -439,7 +466,7 @@ define([
|
||||
var id = rowuid();
|
||||
makeOption(proxy, id, text).val(text);
|
||||
});
|
||||
//console.log(options);
|
||||
Wizard.hide();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -755,14 +782,16 @@ define([
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
if (!readOnly && module.viewHash) {
|
||||
/* add a 'links' button */
|
||||
/* add a 'links' button
|
||||
var $links = Cryptpad.createButton('readonly', true, {viewHash: module.viewHash})
|
||||
.text(Messages.getViewButton)
|
||||
.removeAttr('style')
|
||||
.attr('class', 'action button readonly');
|
||||
$toolbar.append($links);
|
||||
}
|
||||
*/
|
||||
|
||||
/* Import/Export buttons */
|
||||
/*
|
||||
@@ -815,7 +844,11 @@ define([
|
||||
|
||||
|
||||
setEditable(true);
|
||||
return;
|
||||
|
||||
// shortcircuiting before all of this code since it's not quite the
|
||||
// behaviour we want, and it's a bit of work to make it Do The Right Thing
|
||||
/*
|
||||
if (First) {
|
||||
// assume the first user to the poll wants to be the administrator...
|
||||
// TODO prompt them with questions to set up their poll...
|
||||
@@ -830,40 +863,34 @@ define([
|
||||
|
||||
module.activeColumn = '';
|
||||
var promptForName = function () {
|
||||
// HERE
|
||||
Cryptpad.prompt(Messages.promptName, "", function (name, ev) {
|
||||
if (name === null) {
|
||||
name = '';
|
||||
}
|
||||
|
||||
if (!module.isEditable) { return; }
|
||||
var followUp = function (name) {
|
||||
if (!name) { return; }
|
||||
var id = module.activeColumn = coluid();
|
||||
|
||||
Cryptpad.setPadAttribute('column', id, function (err) {
|
||||
if (err) {
|
||||
console.error("Couldn't remember your column id");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(id);
|
||||
if (err) { return void console.error("Couldn't remember your column id"); }
|
||||
makeUser(module.rt.proxy, id, name).focus().val(name);
|
||||
makeUserEditable(id, true);
|
||||
});
|
||||
};
|
||||
|
||||
getLastName(function (err, uname) {
|
||||
if (!uname) {
|
||||
return void Cryptpad.prompt(Messages.promptName, "", function (name, ev) {
|
||||
if (!(name || module.isEditable)) { return; }
|
||||
followUp(name);
|
||||
});
|
||||
}
|
||||
followUp(uname);
|
||||
});
|
||||
};
|
||||
|
||||
if (column === null) {
|
||||
//console.log("Looks like you're new to this poll, why don't you make a column");
|
||||
promptForName();
|
||||
return;
|
||||
}
|
||||
if (column === null) { return void promptForName(); }
|
||||
|
||||
// column might be defined, but that column might have been deleted...
|
||||
if (proxy.table.colsOrder.indexOf(column) === -1) {
|
||||
promptForName();
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (proxy.table.colsOrder.indexOf(column) === -1) { return void promptForName(); }
|
||||
});*/
|
||||
};
|
||||
|
||||
var config = {
|
||||
@@ -889,9 +916,7 @@ define([
|
||||
editHash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys);
|
||||
}
|
||||
// set the hash
|
||||
if (!readOnly) {
|
||||
window.location.hash = editHash;
|
||||
}
|
||||
if (!readOnly) { Cryptpad.replaceHash(editHash); }
|
||||
|
||||
module.patchText = TextPatcher.create({
|
||||
realtime: realtime,
|
||||
|
||||
@@ -585,7 +585,7 @@ define([
|
||||
|
||||
// set the hash
|
||||
if (!window.location.hash || window.location.hash === '#') {
|
||||
window.location.hash = editHash;
|
||||
Cryptpad.replaceHash(editHash);
|
||||
}
|
||||
|
||||
Cryptpad.getPadTitle(function (err, title) {
|
||||
@@ -786,6 +786,11 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
var onError = config.onError = function (info) {
|
||||
module.spinner.hide();
|
||||
Cryptpad.alert(Messages.websocketError);
|
||||
};
|
||||
|
||||
var realtime = module.realtime = Realtime.start(config);
|
||||
|
||||
editor.on('change', onLocal);
|
||||
|
||||
@@ -45,7 +45,7 @@ define([
|
||||
var unsafeTag = function (info) {
|
||||
if (['addAttribute', 'modifyAttribute'].indexOf(info.diff.action) !== -1) {
|
||||
if (/^on/.test(info.diff.name)) {
|
||||
console.log("Rejecting forbidden element attribute with name", info.diff.element.nodeName);
|
||||
console.log("Rejecting forbidden element attribute with name", info.diff.name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -91,12 +91,28 @@ define([
|
||||
return patch;
|
||||
};
|
||||
|
||||
var slice = function (coll) {
|
||||
return Array.prototype.slice.call(coll);
|
||||
};
|
||||
|
||||
/* remove listeners from the DOM */
|
||||
var removeListeners = function (root) {
|
||||
slice(root.attributes).map(function (attr) {
|
||||
if (/^on/.test(attr.name)) {
|
||||
root.attributes.removeNamedItem(attr.name);
|
||||
}
|
||||
});
|
||||
// all the way down
|
||||
slice(root.children).forEach(removeListeners);
|
||||
};
|
||||
|
||||
var draw = Slide.draw = function (i) {
|
||||
console.log("Trying to draw slide #%s", i);
|
||||
if (typeof(Slide.content[i]) !== 'string') { return; }
|
||||
|
||||
var c = Slide.content[i];
|
||||
var Dom = domFromHTML('<div id="content">' + Marked(c) + '</div>');
|
||||
removeListeners(Dom.body);
|
||||
var patch = makeDiff(domFromHTML($content[0].outerHTML), Dom);
|
||||
|
||||
if (typeof(patch) === 'string') {
|
||||
|
||||
Reference in New Issue
Block a user