Merge pull request #112 from xwiki-labs/jquery-require2

Jquery require2
pull/1/head
ansuz 8 years ago committed by GitHub
commit ee99310e99

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<script data-bootload="/customize/main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>

@ -1,4 +1,5 @@
CKEDITOR.editorConfig = function( config ) { // jshint ignore:line
/* global CKEDITOR */
CKEDITOR.editorConfig = function( config ) {
var fixThings = false;
// https://dev.ckeditor.com/ticket/10907
config.needsBrFiller= fixThings;
@ -12,9 +13,29 @@ CKEDITOR.editorConfig = function( config ) { // jshint ignore:line
config.toolbarGroups= [{"name":"clipboard","groups":["clipboard","undo"]},{"name":"editing","groups":["find","selection"]},{"name":"links"},{"name":"insert"},{"name":"forms"},{"name":"tools"},{"name":"document","groups":["mode","document","doctools"]},{"name":"others"},{"name":"basicstyles","groups":["basicstyles","cleanup"]},{"name":"paragraph","groups":["list","indent","blocks","align","bidi"]},{"name":"styles"},{"name":"colors"}];
config.font_defaultLabel = 'Arial';
config.fontSize_defaultLabel = '16px';
config.fontSize_defaultLabel = '16';
config.contentsCss = '/customize/ckeditor-contents.css';
config.keystrokes = [
[ CKEDITOR.ALT + 121 /*F10*/, 'toolbarFocus' ],
[ CKEDITOR.ALT + 122 /*F11*/, 'elementsPathFocus' ],
[ CKEDITOR.SHIFT + 121 /*F10*/, 'contextMenu' ],
[ CKEDITOR.CTRL + 90 /*Z*/, 'undo' ],
[ CKEDITOR.CTRL + 89 /*Y*/, 'redo' ],
[ CKEDITOR.CTRL + CKEDITOR.SHIFT + 90 /*Z*/, 'redo' ],
[ CKEDITOR.CTRL + CKEDITOR.SHIFT + 76 /*L*/, 'link' ],
[ CKEDITOR.CTRL + 76 /*L*/, undefined ],
[ CKEDITOR.CTRL + 66 /*B*/, 'bold' ],
[ CKEDITOR.CTRL + 73 /*I*/, 'italic' ],
[ CKEDITOR.CTRL + 85 /*U*/, 'underline' ],
[ CKEDITOR.ALT + 109 /*-*/, 'toolbarCollapse' ]
];
//skin: 'moono-cryptpad,/pad/themes/moono-cryptpad/'
//skin: 'flat,/pad/themes/flat/'
//skin: 'moono-lisa,/pad/themes/moono-lisa/'

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<script data-bootload="/customize/main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<script data-bootload="/customize/main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>

@ -1074,59 +1074,6 @@ html.cp,
.cp .panel {
background-color: #cccccc;
}
.cp table {
border-collapse: collapse;
border-spacing: 0;
margin: 20px;
}
.cp tbody {
border: 1px solid #555;
}
.cp tbody tr {
text-align: center;
}
.cp tbody tr:first-of-type th {
font-size: 20px;
border-top: 0px;
font-weight: bold;
padding: 10px;
text-decoration: underline;
}
.cp tbody tr:first-of-type th.table-refresh {
color: #46E981;
text-decoration: none;
cursor: pointer;
}
.cp tbody tr:nth-child(odd) {
background-color: #ffffff;
}
.cp tbody tr th:first-of-type {
border-left: 0px;
}
.cp tbody tr th {
box-sizing: border-box;
border: 1px solid #555;
}
.cp tbody tr th,
.cp tbody tr td {
color: #555;
}
.cp tbody tr th.remove,
.cp tbody tr td.remove {
cursor: pointer;
}
.cp tbody tr th:last-child {
border-right: 0px;
}
.cp tbody td {
border-right: 1px solid #555;
padding: 12px;
padding-top: 0px;
padding-bottom: 0px;
}
.cp tbody td:last-child {
border-right: none;
}
.cp .bottom-left {
border-bottom-left-radius: 5px;
}
@ -1137,212 +1084,6 @@ html.cp,
color: #FA5858;
cursor: pointer !important;
}
.cp form.realtime,
.cp div.realtime {
padding: 0px;
margin: 0px;
}
.cp form.realtime > textarea,
.cp div.realtime > textarea {
width: 50%;
height: 15vh;
}
.cp form.realtime table,
.cp div.realtime table {
border-collapse: collapse;
width: calc(100% - 1px);
}
.cp form.realtime table tr td:first-child,
.cp div.realtime table tr td:first-child {
position: absolute;
left: 29px;
top: auto;
width: calc(30% - 50px);
}
.cp form.realtime table tr td,
.cp div.realtime table tr td {
padding: 0px;
margin: 0px;
}
.cp form.realtime table tr td div.text-cell,
.cp div.realtime table tr td div.text-cell {
padding: 0px;
margin: 0px;
height: 100%;
}
.cp form.realtime table tr td div.text-cell input,
.cp div.realtime table tr td div.text-cell input {
width: 80%;
width: 90%;
height: 100%;
border: 0px;
}
.cp form.realtime table tr td div.text-cell input[disabled],
.cp div.realtime table tr td div.text-cell input[disabled] {
background-color: transparent;
color: #000;
font-weight: bold;
}
.cp form.realtime table tr td.checkbox-cell,
.cp div.realtime table tr td.checkbox-cell {
margin: 0px;
padding: 0px;
height: 100%;
min-width: 150px;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain {
display: inline-block;
height: 100%;
width: 100%;
position: relative;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain label,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain label {
background-color: transparent;
display: block;
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable),
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) {
display: none;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover {
font-weight: bold;
background-color: #FA5858;
color: #000;
display: block;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after {
height: 100%;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover:after {
content: "✖";
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes {
background-color: #46E981;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes:after,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.yes:after {
content: "✔";
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.uncommitted,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.uncommitted {
background: #ddd;
}
.cp form.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.mine,
.cp div.realtime table tr td.checkbox-cell div.checkbox-contain input[type="checkbox"]:not(.editable) ~ .cover.mine {
display: none;
}
.cp form.realtime table input[type="text"],
.cp div.realtime table input[type="text"] {
height: auto;
border: 1px solid #fff;
width: 80%;
}
.cp form.realtime table thead td,
.cp div.realtime table thead td {
padding: 0px 5px;
background: #aaa;
border-radius: 20px 20px 0 0;
text-align: center;
}
.cp form.realtime table thead td input[type="text"],
.cp div.realtime table thead td input[type="text"] {
width: 100%;
box-sizing: border-box;
}
.cp form.realtime table thead td input[type="text"][disabled],
.cp div.realtime table thead td input[type="text"][disabled] {
color: #000;
padding: 1px 5px;
border: none;
}
.cp form.realtime table tbody .text-cell,
.cp div.realtime table tbody .text-cell {
background: #aaa;
}
.cp form.realtime table tbody .text-cell input[type="text"],
.cp div.realtime table tbody .text-cell input[type="text"] {
width: calc(100% - 50px);
}
.cp form.realtime table tbody .text-cell .edit,
.cp div.realtime table tbody .text-cell .edit {
float: right;
margin: 0 10px 0 0;
}
.cp form.realtime table tbody .text-cell .remove,
.cp div.realtime table tbody .text-cell .remove {
float: left;
margin: 0 0 0 10px;
}
.cp form.realtime table tbody td label,
.cp div.realtime table tbody td label {
border: 0.5px solid #555;
}
.cp form.realtime table .edit,
.cp div.realtime table .edit {
color: #000;
cursor: pointer;
float: left;
margin-left: 10px;
}
.cp form.realtime table .remove,
.cp div.realtime table .remove {
float: right;
margin-right: 10px;
}
.cp form.realtime table thead tr th input[type="text"][disabled],
.cp div.realtime table thead tr th input[type="text"][disabled] {
background-color: transparent;
color: #555;
font-weight: bold;
}
.cp form.realtime table thead tr th .remove,
.cp div.realtime table thead tr th .remove {
cursor: pointer;
font-size: 20px;
}
.cp form.realtime table tfoot tr,
.cp div.realtime table tfoot tr {
border: none;
}
.cp form.realtime table tfoot tr td,
.cp div.realtime table tfoot tr td {
border: none;
text-align: center;
}
.cp form.realtime table tfoot tr td .save,
.cp div.realtime table tfoot tr td .save {
padding: 15px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.cp form.realtime #adduser,
.cp div.realtime #adduser,
.cp form.realtime #addoption,
.cp div.realtime #addoption {
color: #46E981;
border: 1px solid #46E981;
padding: 15px;
cursor: pointer;
}
.cp form.realtime #adduser,
.cp div.realtime #adduser {
border-top-left-radius: 5px;
}
.cp form.realtime #addoption,
.cp div.realtime #addoption {
border-bottom-left-radius: 5px;
}
#cors-store {
display: none;
}

@ -1,9 +1,8 @@
define([
'jquery',
'/customize/application_config.js',
'/common/cryptpad-common.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, Cryptpad) {
var $ = window.$;
'/common/cryptpad-common.js'
], function ($, Config, Cryptpad) {
var APP = window.APP = {
Cryptpad: Cryptpad,
@ -191,4 +190,3 @@ define([
console.log("ready");
});
});

@ -23,12 +23,10 @@ var getLanguage = function () {
};
var language = getLanguage();
var req = ['/customize/translations/messages.js'];
var req = ['jquery', '/customize/translations/messages.js'];
if (language && map[language]) { req.push('/customize/translations/messages.' + language + '.js'); }
req.push('/bower_components/jquery/dist/jquery.min.js');
define(req, function(Default, Language) {
var $ = window.jQuery;
define(req, function($, Default, Language) {
var externalMap = JSON.parse(JSON.stringify(map));

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<script data-bootload="/customize/main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>

@ -163,12 +163,8 @@
if (typeof(module) !== 'undefined' && module.exports) {
module.exports = Frame;
}
else if ((typeof(define) !== 'undefined' && define !== null) &&
(define.amd !== null)) {
define([
'/bower_components/jquery/dist/jquery.min.js',
], function () {
} else if (typeof(define) === 'function' && define.amd) {
define(['jquery'], function ($) {
return Frame;
});
} else {

@ -1,8 +1,7 @@
define([
'/customize/share/frame.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Frame) {
var $ = window.jQuery;
'jquery',
'/customize/share/frame.js'
], function ($, Frame) {
var domain = 'https://beta.cryptpad.fr';
@ -123,4 +122,3 @@ define([
}].forEach(runTest);
});
});

@ -520,60 +520,6 @@ noscript {
/* Tables
* Currently only used by /poll/
*/
table {
border-collapse: collapse;
border-spacing: 0;
margin: 20px;
}
tbody {
border: 1px solid @poll-border-color;
tr {
text-align: center;
&:first-of-type th{
font-size: 20px;
border-top: 0px;
font-weight: bold;
padding: 10px;
text-decoration: underline;
&.table-refresh {
color: @cp-green;
text-decoration: none;
cursor: pointer;
}
}
&:nth-child(odd) {
background-color: @light-base;
}
th:first-of-type {
border-left: 0px;
}
th {
box-sizing: border-box;
border: 1px solid @poll-border-color;
}
th, td {
color: @fore;
&.remove {
cursor: pointer;
}
}
th:last-child {
border-right: 0px;
}
}
td {
border-right: 1px solid @poll-border-color;
padding: 12px;
padding-top: 0px;
padding-bottom: 0px;
&:last-child {
border-right: none;
}
}
}
// form things
.bottom-left {
@ -588,226 +534,6 @@ tbody {
color: @cp-red;
cursor: pointer !important;
}
form.realtime, div.realtime {
> input {
&[type="text"] {
}
}
> textarea {
width: 50%;
height: 15vh;
}
padding: 0px;
margin: 0px;
table {
border-collapse: collapse;
width: ~"calc(100% - 1px)";
tr {
td:first-child {
position:absolute;
left: 29px;
top: auto;
width: ~"calc(30% - 50px)";
}
td {
padding: 0px;
margin: 0px;
div.text-cell {
padding: 0px;
margin: 0px;
height: 100%;
input {
width: 80%;
width: 90%;
height: 100%;
border: 0px;
&[disabled] {
background-color: transparent;
color: @poll-fg;
font-weight: bold;
}
}
}
&.checkbox-cell {
margin: 0px;
padding: 0px;
height: 100%;
min-width: 150px;
div.checkbox-contain {
display: inline-block;
height: 100%;
width: 100%;
position: relative;
label {
background-color: transparent;
display: block;
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
input {
&[type="checkbox"] {
&:not(.editable) {
display: none;
~ .cover {
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;
}
}
}
}
}
}
}
}
}
input {
&[type="text"] {
height: auto;
border: 1px solid @base;
width: 80%;
}
}
thead {
td {
padding: 0px 5px;
background: @poll-th-bg;
border-radius: 20px 20px 0 0;
text-align: center;
input {
&[type="text"] {
width: 100%;
box-sizing: border-box;
&[disabled] {
color: @poll-fg;
padding: 1px 5px;
border: none;
}
}
}
}
}
tbody {
.text-cell {
background: @poll-td-bg;
//border-radius: 20px 0 0 20px;
input[type="text"] {
width: ~"calc(100% - 50px)";
}
.edit {
float:right;
margin: 0 10px 0 0;
}
.remove {
float: left;
margin: 0 0 0 10px;
}
}
td {
label {
border: .5px solid @poll-border-color;
}
}
}
.edit {
color: @poll-cover-color;
cursor: pointer;
float: left;
margin-left: 10px;
}
.remove {
float: right;
margin-right: 10px;
}
thead {
tr {
th {
input[type="text"][disabled] {
background-color: transparent;
color: @fore;
font-weight: bold;
}
.remove {
cursor: pointer;
font-size: 20px;
}
}
}
}
tbody {
tr {
td {
}
}
}
tfoot {
tr {
border: none;
td {
border: none;
text-align: center;
.save {
padding: 15px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
}
}
}
}
#adduser,
#addoption {
color: @cp-green;
border: 1px solid @cp-green;
padding: 15px;
cursor: pointer;
}
#adduser { .top-left; }
#addoption { .bottom-left; }
}
}
// hack for our cross-origin iframe

@ -1,5 +1,5 @@
.fontface(@family, @src, @style: normal, @weight: 400, @fmt: 'truetype'){
@font-face{
@font-face {
font-family: @family;
src: url(@src) format(@fmt);
font-weight: @weight;

@ -60,12 +60,6 @@
@slide-default-bg: #000;
@poll-th-bg: #aaa;
@poll-td-bg: #aaa;
@poll-border-color: #555;
@poll-cover-color: #000;
@poll-fg: #000;
@bg-loading: @old-base;
@color-loading: @old-fore;

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
{{script}}
</head>

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<script data-bootload="/customize/main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>

@ -290,10 +290,23 @@ define(function () {
out.fm_categoryError = "No se pudo abrir la categoría seleccionada, mostrando la raíz.";
out.settings_userFeedbackHint1 = "CryptPad suministra informaciones muy básicas al servidor, para ayudarnos a mejorar vuestra experiencia.";
out.settings_userFeedbackHint2 = "El contenido de tu pad nunca será compartido con el servidor.";
out.settings_userFeedback = "Activar feedback"; // "Disable user feedback"
out.settings_userFeedback = "Activar feedback";
out.settings_anonymous = "No has iniciado sesión. Tus ajustes se aplicarán solo a este navegador.";
out.blog = "Blog";
out.initialState = "<p>Esto es <strong>CryptPad</strong>, el editor collaborativo en tiempo real zero knowledge.<br>Lo que escribes aquí es cifrado, con lo cual solo las personas con el enlace pueden accederlo.<br>Incluso el servido no puede ver lo que escribes.</p><p><small><i>Lo que ves aquí, lo que escuchas aquí, cuando sales, se queda aquí</i></small></p><p>&nbsp;<br></p>";
out.initialState = [
'<span style="font-size:18px;"><p>',
'Esto es&nbsp;<strong>CryptPad</strong>, el editor collaborativo en tiempo real Zero Knowledge. Todo está guardado cuando escribes.',
'<br>',
'Comparte el enlace a este pad para editar con amigos o utiliza el botón <span style="background-color:#5cb85c;color:#ffffff;">&nbsp;Compartir&nbsp;</span> para obtener un <em>enlace solo lectura</em>&nbsp;que permite leer pero no escribir.',
'</p>',
'<p><span style="color:#808080;"><em>',
'Vamos, solo empezia a escribir...',
'</em></span></p></span>',
'<p>&nbsp;<br></p>'
].join('');
out.codeInitialState = "/*\n Esto es CryptPad, el editor collaborativo en tiempo real zero knowledge.\n Lo que escribes aquí es cifrado, con lo cual solo las personas con el enlace pueden accederlo.\n Incluso el servidor no puede ver lo que escribes.\n Lo que ves aquí, lo que escuchas aquí, cuando sales, se queda aquí\n*/";
out.slideInitialState = "# CryptSlide\n* Esto es CryptPad, el editor collaborativo en tiempo real zero knowledge.\n* Lo que escribes aquí es cifrado, con lo cual solo las personas con el enlace pueden accederlo.\n* Incluso el servidor no puede ver lo que escribes.\n* Lo que ves aquí, lo que escuchas aquí, cuando sales, se queda aquí\n\n---\n# Como utilizarlo\n1. Escribe tu contenido en Markdown\n - Puedes aprender más sobre Markdown [aquí](http://www.markdowntutorial.com/)\n2. Separa tus slides con ---\n3. Haz clic en \"Presentar\" para ver el resultado - Tus slides se actualizan en tiempo real";
out.driveReadmeTitle = "¿Qué es CryptDrive?";
@ -356,5 +369,29 @@ define(function () {
out.register_warning = "Zero Knowledge significa que no podemos recuperar tus datos si pierdes tu contraseña.";
out.register_alreadyRegistered = "Este usuario ya existe, ¿iniciar sesión?";
// 1.4.0 - Easter Bunny
out.button_newwhiteboard = "Nueva Pizarra";
out.wrongApp = "No se pudo mostrar el contenido de la sessión en tiempo real en tu navigador. Por favor, actualiza la página.";
out.synced = "Todo está guardado.";
out.saveTemplateButton = "Guardar como plantilla";
out.saveTemplatePrompt = "Élige un título para la plantilla";
out.templateSaved = "¡Plantilla guardada!";
out.selectTemplate = "Élige una plantilla o pulsa ESC";
out.slideOptionsTitle = "Personaliza tus diapositivas";
out.slideOptionsButton = "Guardar (enter)";
out.canvas_clear = "Limpiar";
out.canvas_delete = "Borrar selección";
out.canvas_disable = "No permitir dibujos";
out.canvas_enable = "Permitir dibujos";
out.canvas_width = "Talla";
out.canvas_opacity = "Opacidad";
out.settings_publicSigningKey = "Clave de Firma Pública";
out.settings_usage = "Utilización";
out.settings_usageTitle = "Vee el uso total de tus pads en MB";
out.settings_pinningNotAvailable = "Los pads pegados solo están disponibles para usuarios registrados.";
out.settings_pinningError = "Algo salió mal";
out.settings_usageAmount = "Tus pads pegados utilizan {0}MB";
return out;
});

@ -378,12 +378,12 @@ define(function () {
// Initial states
out.initialState = [
'<span style="font-size:18px;"><p>',
'<span style="font-size:16px;"><p>',
'Voici <strong>CryptPad</strong>, l\'éditeur collaboratif en temps-réel Zero Knowledge. Tout est sauvegardé dés que vous le tapez.',
'<br>',
'Partagez le lien vers ce pad avec des amis ou utilisez le bouton <span style="background-color:#5cb85c;color:#ffffff;">&nbsp;Partager&nbsp;</span> pour obtenir le <em>lien de lecture-seule</em>, qui permet la lecture mais non la modification.',
'</p>',
'<p><span style="color:#808080; font-size: 18px;">',
'<p><span style="color:#808080; font-size: 16px;">',
'<em>',
'Lancez-vous, commencez à taper...',
'</em></span></p></span>',

@ -300,6 +300,12 @@ define(function () {
out.settings_anonymous = "You are not logged in. Settings here are specific to this browser.";
out.settings_publicSigningKey = "Public Signing Key";
out.settings_usage = "Usage";
out.settings_usageTitle = "See the total size of your pinned pads in MB";
out.settings_pinningNotAvailable = "Pinned pads are only available to registered users.";
out.settings_pinningError = "Something went wrong";
out.settings_usageAmount = "Your pinned pads occupy {0}MB";
// index.html
@ -386,7 +392,7 @@ define(function () {
// Initial states
out.initialState = [
'<span style="font-size:18px;"><p>',
'<span style="font-size:16px;"><p>',
'This is&nbsp;<strong>CryptPad</strong>, the Zero Knowledge realtime collaborative editor. Everything is saved as you type.',
'<br>',
'Share the link to this pad to edit with friends or use the <span style="background-color:#5cb85c;color:#ffffff;">&nbsp;Share&nbsp;</span> button to share a <em>read-only link</em>&nbsp;which allows viewing but not editing.',

@ -17,7 +17,7 @@
"scripts": {
"lint": "jshint --config .jshintrc --exclude-path .jshintignore .",
"test": "node TestSelenium.js",
"style": "lessc ./customize.dist/src/less/cryptpad.less > ./customize.dist/main.css && lessc ./customize.dist/src/less/toolbar.less > ./customize.dist/toolbar.css && lessc ./www/drive/file.less > ./www/drive/file.css && lessc ./www/settings/main.less > ./www/settings/main.css && lessc ./www/slide/slide.less > ./www/slide/slide.css && lessc ./www/whiteboard/whiteboard.less > ./www/whiteboard/whiteboard.css",
"style": "lessc ./customize.dist/src/less/cryptpad.less > ./customize.dist/main.css && lessc ./customize.dist/src/less/toolbar.less > ./customize.dist/toolbar.css && lessc ./www/drive/file.less > ./www/drive/file.css && lessc ./www/settings/main.less > ./www/settings/main.css && lessc ./www/slide/slide.less > ./www/slide/slide.css && lessc ./www/whiteboard/whiteboard.less > ./www/whiteboard/whiteboard.css && lessc ./www/poll/poll.less > ./www/poll/poll.css",
"template": "cd customize.dist/src && node build.js"
}
}

@ -1,12 +1,10 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'/bower_components/jquery/dist/jquery.min.js',
'jquery',
'/bower_components/hyperjson/hyperjson.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'json.sortify',
'/common/cryptpad-common.js',
], function (jQuery, Hyperjson, TextPatcher, Sortify, Cryptpad) {
var $ = window.jQuery;
], function ($, Hyperjson, TextPatcher, Sortify, Cryptpad) {
window.Hyperjson = Hyperjson;
window.TextPatcher = TextPatcher;
window.Sortify = Sortify;

@ -1,8 +1,4 @@
define([
'/bower_components/jquery/dist/jquery.min.js',
], function () {
var $ = window.jQuery;
define(['jquery'], function ($) {
$('media').each(function () {
window.alert("media tag selection works!");
});

@ -1,8 +1,7 @@
define([
'/bower_components/hyperjson/hyperjson.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Hyperjson) {
var $ = window.jQuery;
'jquery',
'/bower_components/hyperjson/hyperjson.js'
], function ($, Hyperjson) {
var shjson = '["BODY",{"class":"cke_editable cke_editable_themed cke_contents_ltr cke_show_borders","spellcheck":"false"},[["P",{},["This is ",["STRONG",{},["CryptPad"]],", the zero knowledge realtime collaborative editor.",["BR",{},[]],"What you type here is encrypted so only people who have the link can access it.",["BR",{},[]],"Even the server cannot see what you type."]],["P",{},[["SMALL",{},[["I",{},["What you see here, what you hear here, when you leave here, let it stay here"]]]],["BR",{"type":"_moz"},[]]]]]]';
var hjson = JSON.parse(shjson);

@ -1,9 +1,8 @@
define([
'/bower_components/jquery/dist/jquery.min.js',
'jquery',
'/common/cryptpad-common.js',
'/customize/translations/messages.js',
], function (jQuery, Cryptpad, English) {
var $ = window.jQuery;
], function ($, Cryptpad, English) {
var $body = $('body');

@ -1,5 +1,5 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'jquery',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/textpatcher/TextPatcher.js',
@ -12,10 +12,8 @@ define([
'/common/themes.js',
'/common/visible.js',
'/common/notify.js',
'/bower_components/file-saver/FileSaver.min.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Crypto, Realtime, TextPatcher, Toolbar, JSONSortify, JsonOT, Cryptpad, Cryptget, Modes, Themes, Visible, Notify) {
var $ = window.jQuery;
'/bower_components/file-saver/FileSaver.min.js'
], function ($, Crypto, Realtime, TextPatcher, Toolbar, JSONSortify, JsonOT, Cryptpad, Cryptget, Modes, Themes, Visible, Notify) {
var saveAs = window.saveAs;
var Messages = Cryptpad.Messages;
@ -63,7 +61,7 @@ define([
styleActiveLine : true,
search: true,
highlightSelectionMatches: {showToken: /\w+/},
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
extraKeys: {"Shift-Ctrl-R": undefined},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
mode: "javascript",
@ -646,7 +644,7 @@ define([
return cursor;
};
var onRemote = config.onRemote = function (info) {
var onRemote = config.onRemote = function () {
if (initializing) { return; }
var scroll = editor.getScrollInfo();
@ -733,6 +731,7 @@ define([
var second = function (CM) {
Cryptpad.ready(function (err, env) {
andThen(CM);
Cryptpad.reportAppUsage();
});
Cryptpad.onError(function (info) {
if (info && info.type === "store") {

@ -1,7 +1,14 @@
// This is stage 1, it can be changed but you must bump the version of the project.
define([], function () {
// fix up locations so that relative urls work.
require.config({ baseUrl: window.location.pathname });
require.config({
baseUrl: window.location.pathname,
paths: {
// jquery declares itself as literally "jquery" so it cannot be pulled by path :(
"jquery": "/bower_components/jquery/dist/jquery.min",
// json.sortify same
"json.sortify": "/bower_components/json.sortify/dist/JSON.sortify"
}
});
require([document.querySelector('script[data-bootload]').getAttribute('data-bootload')]);
});

@ -1,7 +1,4 @@
define([
'/bower_components/jquery/dist/jquery.min.js',
], function () {
var $ = window.jQuery;
define(['jquery'], function ($) {
var Clipboard = {};
// copy arbitrary text to the clipboard
@ -13,7 +10,7 @@ define([
$('body').append($ta);
if (!($ta.length && $ta[0].select)) {
if (!($ta.length && $ta[0].select)) {
// console.log("oops");
return;
}

@ -0,0 +1,245 @@
define([
'/common/common-util.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/tweetnacl/nacl-fast.min.js'
], function (Util, Crypto) {
var Nacl = window.nacl;
var Hash = {};
var uint8ArrayToHex = Util.uint8ArrayToHex;
var hexToBase64 = Util.hexToBase64;
var base64ToHex = Util.base64ToHex;
// This implementation must match that on the server
// it's used for a checksum
Hash.hashChannelList = function (list) {
return Nacl.util.encodeBase64(Nacl.hash(Nacl.util
.decodeUTF8(JSON.stringify(list))));
};
var getEditHashFromKeys = Hash.getEditHashFromKeys = function (chanKey, keys) {
if (typeof keys === 'string') {
return chanKey + keys;
}
if (!keys.editKeyStr) { return; }
return '/1/edit/' + hexToBase64(chanKey) + '/' + Crypto.b64RemoveSlashes(keys.editKeyStr);
};
var getViewHashFromKeys = Hash.getViewHashFromKeys = function (chanKey, keys) {
if (typeof keys === 'string') {
return;
}
return '/1/view/' + hexToBase64(chanKey) + '/' + Crypto.b64RemoveSlashes(keys.viewKeyStr);
};
var parsePadUrl = Hash.parsePadUrl = function (href) {
var patt = /^https*:\/\/([^\/]*)\/(.*?)\//i;
var ret = {};
if (!href) { return ret; }
if (!/^https*:\/\//.test(href)) {
var idx = href.indexOf('/#');
ret.type = href.slice(1, idx);
ret.hash = href.slice(idx + 2);
return ret;
}
var hash = href.replace(patt, function (a, domain, type, hash) {
ret.domain = domain;
ret.type = type;
return '';
});
ret.hash = hash.replace(/#/g, '');
return ret;
};
var getRelativeHref = Hash.getRelativeHref = function (href) {
if (!href) { return; }
if (href.indexOf('#') === -1) { return; }
var parsed = parsePadUrl(href);
return '/' + parsed.type + '/#' + parsed.hash;
};
/*
* Returns all needed keys for a realtime channel
* - no argument: use the URL hash or create one if it doesn't exist
* - secretHash provided: use secretHash to find the keys
*/
var getSecrets = Hash.getSecrets = function (secretHash) {
var secret = {};
var generate = function () {
secret.keys = Crypto.createEditCryptor();
secret.key = Crypto.createEditCryptor().editKeyStr;
};
if (!secretHash && !/#/.test(window.location.href)) {
generate();
return secret;
} else {
var hash = secretHash || window.location.hash.slice(1);
if (hash.length === 0) {
generate();
return secret;
}
// old hash system : #{hexChanKey}{cryptKey}
// new hash system : #/{hashVersion}/{b64ChanKey}/{cryptKey}
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
// Old hash
secret.channel = hash.slice(0, 32);
secret.key = hash.slice(32);
}
else {
// New hash
var hashArray = hash.split('/');
if (hashArray.length < 4) {
Hash.alert("Unable to parse the key");
throw new Error("Unable to parse the key");
}
var version = hashArray[1];
if (version === "1") {
var mode = hashArray[2];
if (mode === 'edit') {
secret.channel = base64ToHex(hashArray[3]);
var keys = Crypto.createEditCryptor(hashArray[4].replace(/-/g, '/'));
secret.keys = keys;
secret.key = keys.editKeyStr;
if (secret.channel.length !== 32 || secret.key.length !== 24) {
Hash.alert("The channel key and/or the encryption key is invalid");
throw new Error("The channel key and/or the encryption key is invalid");
}
}
else if (mode === 'view') {
secret.channel = base64ToHex(hashArray[3]);
secret.keys = Crypto.createViewCryptor(hashArray[4].replace(/-/g, '/'));
if (secret.channel.length !== 32) {
Hash.alert("The channel key is invalid");
throw new Error("The channel key is invalid");
}
}
}
}
}
return secret;
};
var getHashes = Hash.getHashes = function (channel, secret) {
var hashes = {};
if (secret.keys.editKeyStr) {
hashes.editHash = getEditHashFromKeys(channel, secret.keys);
}
if (secret.keys.viewKeyStr) {
hashes.viewHash = getViewHashFromKeys(channel, secret.keys);
}
return hashes;
};
var createChannelId = Hash.createChannelId = function () {
var id = uint8ArrayToHex(Crypto.Nacl.randomBytes(16));
if (id.length !== 32 || /[^a-f0-9]/.test(id)) {
throw new Error('channel ids must consist of 32 hex characters');
}
return id;
};
var createRandomHash = Hash.createRandomHash = function () {
// 16 byte channel Id
var channelId = Util.hexToBase64(createChannelId());
// 18 byte encryption key
var key = Crypto.b64RemoveSlashes(Crypto.rand64(18));
return '/1/edit/' + [channelId, key].join('/');
};
var parseHash = Hash.parseHash = function (hash) {
var parsed = {};
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
// Old hash
parsed.channel = hash.slice(0, 32);
parsed.key = hash.slice(32);
parsed.version = 0;
return parsed;
}
var hashArr = hash.split('/');
if (hashArr[1] && hashArr[1] === '1') {
parsed.version = 1;
parsed.mode = hashArr[2];
parsed.channel = hashArr[3];
parsed.key = hashArr[4];
parsed.present = hashArr[5] && hashArr[5] === 'present';
return parsed;
}
return;
};
// STORAGE
var findWeaker = Hash.findWeaker = function (href, recents) {
var rHref = href || getRelativeHref(window.location.href);
var parsed = parsePadUrl(rHref);
if (!parsed.hash) { return false; }
var weaker;
recents.some(function (pad) {
var p = parsePadUrl(pad.href);
if (p.type !== parsed.type) { return; } // Not the same type
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
var pHash = parseHash(p.hash);
var parsedHash = parseHash(parsed.hash);
if (!parsedHash || !pHash) { return; }
if (pHash.version !== parsedHash.version) { return; }
if (pHash.channel !== parsedHash.channel) { return; }
if (pHash.mode === 'view' && parsedHash.mode === 'edit') {
weaker = pad.href;
return true;
}
return;
});
return weaker;
};
var findStronger = Hash.findStronger = function (href, recents) {
var rHref = href || getRelativeHref(window.location.href);
var parsed = parsePadUrl(rHref);
if (!parsed.hash) { return false; }
var stronger;
recents.some(function (pad) {
var p = parsePadUrl(pad.href);
if (p.type !== parsed.type) { return; } // Not the same type
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
var pHash = parseHash(p.hash);
var parsedHash = parseHash(parsed.hash);
if (!parsedHash || !pHash) { return; }
if (pHash.version !== parsedHash.version) { return; }
if (pHash.channel !== parsedHash.channel) { return; }
if (pHash.mode === 'edit' && parsedHash.mode === 'view') {
stronger = pad.href;
return true;
}
return;
});
return stronger;
};
var isNotStrongestStored = Hash.isNotStrongestStored = function (href, recents) {
return findStronger(href, recents);
};
var hrefToHexChannelId = Hash.hrefToHexChannelId = function (href) {
var parsed = Hash.parsePadUrl(href);
if (!parsed || !parsed.hash) { return; }
parsed = Hash.parseHash(parsed.hash);
if (parsed.version === 0) {
return parsed.channel;
} else if (parsed.version !== 1) {
console.error("parsed href had no version");
console.error(parsed);
return;
}
var channel = parsed.channel;
if (!channel) { return; }
var hex = base64ToHex(channel);
return hex;
};
return Hash;
});

@ -0,0 +1,220 @@
define([
'jquery',
'/customize/messages.js',
'/common/common-util.js',
'/customize/application_config.js',
'/bower_components/alertifyjs/dist/js/alertify.js'
], function ($, Messages, Util, AppConfig, Alertify) {
var UI = {};
/*
* Alertifyjs
*/
UI.Alertify = Alertify;
// set notification timeout
Alertify._$$alertify.delay = AppConfig.notificationTimeout || 5000;
var findCancelButton = UI.findCancelButton = function () {
return $('button.cancel');
};
var findOKButton = UI.findOKButton = function () {
return $('button.ok');
};
var listenForKeys = UI.listenForKeys = function (yes, no) {
var handler = function (e) {
switch (e.which) {
case 27: // cancel
if (typeof(no) === 'function') { no(e); }
no();
break;
case 13: // enter
if (typeof(yes) === 'function') { yes(e); }
break;
}
};
$(window).keyup(handler);
return handler;
};
var stopListening = UI.stopListening = function (handler) {
$(window).off('keyup', handler);
};
UI.alert = function (msg, cb, force) {
cb = cb || function () {};
if (force !== true) { msg = Util.fixHTML(msg); }
var close = function (e) {
findOKButton().click();
};
var keyHandler = listenForKeys(close, close);
Alertify.alert(msg, function (ev) {
cb(ev);
stopListening(keyHandler);
});
window.setTimeout(function () {
findOKButton().focus();
});
};
UI.prompt = function (msg, def, cb, opt, force) {
opt = opt || {};
cb = cb || function () {};
if (force !== true) { msg = Util.fixHTML(msg); }
var keyHandler = listenForKeys(function (e) { // yes
findOKButton().click();
}, function (e) { // no
findCancelButton().click();
});
Alertify
.defaultValue(def || '')
.okBtn(opt.ok || Messages.okButton || 'OK')
.cancelBtn(opt.cancel || Messages.cancelButton || 'Cancel')
.prompt(msg, function (val, ev) {
cb(val, ev);
stopListening(keyHandler);
}, function (ev) {
cb(null, ev);
stopListening(keyHandler);
});
};
UI.confirm = function (msg, cb, opt, force, styleCB) {
opt = opt || {};
cb = cb || function () {};
if (force !== true) { msg = Util.fixHTML(msg); }
var keyHandler = listenForKeys(function (e) {
findOKButton().click();
}, function (e) {
findCancelButton().click();
});
Alertify
.okBtn(opt.ok || Messages.okButton || 'OK')
.cancelBtn(opt.cancel || Messages.cancelButton || 'Cancel')
.confirm(msg, function () {
cb(true);
stopListening(keyHandler);
}, function () {
cb(false);
stopListening(keyHandler);
});
window.setTimeout(function () {
var $ok = findOKButton();
var $cancel = findCancelButton();
if (opt.okClass) { $ok.addClass(opt.okClass); }
if (opt.cancelClass) { $cancel.addClass(opt.cancelClass); }
if (opt.reverseOrder) {
$ok.insertBefore($ok.prev());
}
if (typeof(styleCB) === 'function') {
styleCB($ok.closest('.dialog'));
}
}, 0);
};
UI.log = function (msg) {
Alertify.success(Util.fixHTML(msg));
};
UI.warn = function (msg) {
Alertify.error(Util.fixHTML(msg));
};
/*
* spinner
*/
UI.spinner = function (parent) {
var $target = $('<span>', {
'class': 'fa fa-spinner fa-pulse fa-4x fa-fw'
}).hide();
$(parent).append($target);
return {
show: function () {
$target.show();
return this;
},
hide: function () {
$target.hide();
return this;
},
get: function () {
return $target;
},
};
};
var LOADING = 'loading';
var getRandomTip = function () {
if (!Messages.tips || !Object.keys(Messages.tips).length) { return ''; }
var keys = Object.keys(Messages.tips);
var rdm = Math.floor(Math.random() * keys.length);
return Messages.tips[keys[rdm]];
};
UI.addLoadingScreen = function (loadingText, hideTips) {
var $loading, $container;
if ($('#' + LOADING).length) {
$loading = $('#' + LOADING).show();
if (loadingText) {
$('#' + LOADING).find('p').text(loadingText);
}
$container = $loading.find('.loadingContainer');
} else {
$loading = $('<div>', {id: LOADING});
$container = $('<div>', {'class': 'loadingContainer'});
$container.append('<img class="cryptofist" src="/customize/cryptofist_small.png" />');
var $spinner = $('<div>', {'class': 'spinnerContainer'});
UI.spinner($spinner).show();
var $text = $('<p>').text(loadingText || Messages.loading);
$container.append($spinner).append($text);
$loading.append($container);
$('body').append($loading);
}
if (Messages.tips && !hideTips) {
var $loadingTip = $('<div>', {'id': 'loadingTip'});
var $tip = $('<span>', {'class': 'tips'}).text(getRandomTip()).appendTo($loadingTip);
$loadingTip.css({
'top': $('body').height()/2 + $container.height()/2 + 20 + 'px'
});
$('body').append($loadingTip);
}
};
UI.removeLoadingScreen = function (cb) {
$('#' + LOADING).fadeOut(750, cb);
$('#loadingTip').css('top', '');
window.setTimeout(function () {
$('#loadingTip').fadeOut(750);
}, 3000);
};
UI.errorLoadingScreen = function (error, transparent) {
if (!$('#' + LOADING).is(':visible')) { UI.addLoadingScreen(undefined, true); }
$('.spinnerContainer').hide();
if (transparent) { $('#' + LOADING).css('opacity', 0.8); }
$('#' + LOADING).find('p').html(error || Messages.error);
};
var importContent = UI.importContent = function (type, f) {
return function () {
var $files = $('<input type="file">').click();
$files.on('change', function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (e) { f(e.target.result, file); };
reader.readAsText(file, type);
});
};
};
return UI;
});

@ -0,0 +1,85 @@
define([], function () {
var Util = {};
var find = Util.find = function (map, path) {
return (map && path.reduce(function (p, n) {
return typeof(p[n]) !== 'undefined' && p[n];
}, map));
};
var fixHTML = Util.fixHTML = function (str) {
if (!str) { return ''; }
return str.replace(/[<>&"']/g, function (x) {
return ({ "<": "&lt;", ">": "&gt", "&": "&amp;", '"': "&#34;", "'": "&#39;" })[x];
});
};
var hexToBase64 = Util.hexToBase64 = function (hex) {
var hexArray = hex
.replace(/\r|\n/g, "")
.replace(/([\da-fA-F]{2}) ?/g, "0x$1 ")
.replace(/ +$/, "")
.split(" ");
var byteString = String.fromCharCode.apply(null, hexArray);
return window.btoa(byteString).replace(/\//g, '-').slice(0,-2);
};
var base64ToHex = Util.base64ToHex = function (b64String) {
var hexArray = [];
atob(b64String.replace(/-/g, '/')).split("").forEach(function(e){
var h = e.charCodeAt(0).toString(16);
if (h.length === 1) { h = "0"+h; }
hexArray.push(h);
});
return hexArray.join("");
};
var uint8ArrayToHex = Util.uint8ArrayToHex = function (a) {
// call slice so Uint8Arrays work as expected
return Array.prototype.slice.call(a).map(function (e, i) {
var n = Number(e & 0xff).toString(16);
if (n === 'NaN') {
throw new Error('invalid input resulted in NaN');
}
switch (n.length) {
case 0: return '00'; // just being careful, shouldn't happen
case 1: return '0' + n;
case 2: return n;
default: throw new Error('unexpected value');
}
}).join('');
};
var deduplicateString = Util.deduplicateString = function (array) {
var a = array.slice();
for(var i=0; i<a.length; i++) {
for(var j=i+1; j<a.length; j++) {
if(a[i] === a[j]) { a.splice(j--, 1); }
}
}
return a;
};
var getHash = Util.getHash = function () {
return window.location.hash.slice(1);
};
var replaceHash = Util.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;
};
/*
* Saving files
*/
var fixFileName = Util.fixFileName = function (filename) {
return filename.replace(/ /g, '-').replace(/[\/\?]/g, '_')
.replace(/_+/g, '_');
};
return Util;
});

@ -1,63 +0,0 @@
define([
'/common/virtual-dom.js',
'/bower_components/hyperjson/hyperjson.amd.js',
'/common/hyperscript.js'
], function (vdom, hyperjson, hyperscript) {
// complain if you don't find the required APIs
if (!(vdom && hyperjson && hyperscript)) { throw new Error(); }
// Generate a matrix of conversions
/*
convert.dom.to.hjson, convert.hjson.to.dom,
convert.dom.to.vdom, convert.vdom.to.dom,
convert.vdom.to.hjson, convert.hjson.to.vdom
and of course, identify functions in case you try to
convert a datatype to itself
*/
var convert = (function () {
var Self = function (x) {
return x;
},
methods = {
dom:{
dom: Self,
hjson: hyperjson.fromDOM,
vdom: function (D) {
return hyperjson.callOn(hyperjson.fromDOM(D), vdom.h);
}
},
hjson:{
hjson: Self,
dom: function (H) {
// hyperjson.fromDOM,
return hyperjson.callOn(H, hyperscript);
},
vdom: function (H) {
return hyperjson.callOn(H, vdom.h);
}
},
vdom:{
vdom: Self,
dom: function (V) {
return vdom.create(V);
},
hjson: function (V) {
return hyperjson.fromDOM(vdom.create(V));
}
}
},
convert = {};
Object.keys(methods).forEach(function (method) {
convert[method] = { to: methods[method] };
});
return convert;
}());
convert.core = {
vdom: vdom,
hyperjson: hyperjson,
hyperscript: hyperscript
};
return convert;
});

@ -1,10 +1,10 @@
define([
'jquery',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/common/cryptpad-common.js',
'/bower_components/textpatcher/TextPatcher.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Crypto, Realtime, Cryptpad, TextPatcher) {
'/bower_components/textpatcher/TextPatcher.js'
], function ($, Crypto, Realtime, Cryptpad, TextPatcher) {
var Messages = Cryptpad.Messages;
var noop = function () {};
var finish = function (S, err, doc) {

File diff suppressed because it is too large Load Diff

@ -2,10 +2,6 @@ define([
'/common/treesome.js',
'/bower_components/rangy/rangy-core.min.js'
], function (Tree, Rangy, saveRestore) {
//window.Rangy = Rangy;
//window.Tree = Tree;
// do some function for the start and end of the cursor
var log = function (x) { console.log(x); };
var error = function (x) { console.log(x); };
var verbose = function (x) { if (window.verboseMode) { console.log(x); } };
@ -27,108 +23,6 @@ define([
}
};
// TODO deprecate
// assumes a negative index
var seekLeft /* = cursor.seekLeft*/ = function (el, delta, current) {
var textLength;
var previous;
// normalize
if (-delta >= current) {
delta += current;
current = 0;
} else {
current += delta;
delta = 0;
}
while (delta) {
previous = el;
el = Tree.previousNode(el, inner);
if (el) {
textLength = el.textContent.length;
if (-delta > textLength) {
delta -= textLength;
} else {
current = textLength + delta;
delta = 0;
}
} else {
return {
el: previous,
offset: 0,
error: "out of bounds"
};
}
}
return {
el: el,
offset: current
};
};
// TODO deprecate
// seekRight assumes a positive delta
var seekRight = /* cursor.seekRight = */ function (el, delta, current) {
var textLength;
var previous;
// normalize
delta += current;
current = 0;
while (delta) {
if (el) {
textLength = el.textContent.length;
if (delta >= textLength) {
delta -= textLength;
previous = el;
el = Tree.nextNode(el, inner);
} else {
current = delta;
delta = 0;
}
} else {
// don't ever return a negative index
if (previous.textContent.length) {
textLength = previous.textContent.length - 1;
} else {
textLength = 0;
}
return {
el: previous,
offset: textLength,
error: "out of bounds"
};
}
}
return {
el: el,
offset: current
};
};
// TODO deprecate
var seekToDelta = /* cursor.seekToDelta = */ function (el, delta, current) {
var result = null;
if (el) {
if (delta < 0) {
return seekLeft(el, delta, current);
} else if (delta > 0) {
return seekRight(el, delta, current);
} else {
result = {
el: el,
offset: current
};
}
} else {
error("[cursor.seekToDelta] el is undefined");
}
return result;
};
/* cursor.update takes notes about wherever the cursor was last seen
in the event of a cursor loss, the information produced by side
effects of this function should be used to recover the cursor
@ -262,109 +156,6 @@ define([
};
};
/* getLength assumes that both nodes exist inside of the active editor. */
// unused currently
var getLength = cursor.getLength = function () {
if (Range.start.el === Range.end.el) {
if (Range.start.offset === Range.end.offset) { return 0; }
if (Range.start.offset < Range.end.offset) {
return Range.end.offset - Range.start.offset;
} else {
return Range.start.offset - Range.end.offset;
}
} else {
var order = Tree.orderOfNodes(Range.start.el, Range.end.el, inner);
var L;
var cur;
/* we know that the cursor elements are different, and that we
must traverse to find the total length. We also know the
order of the nodes (probably 1 or -1) */
if (order === 1) {
L = (Range.start.el.textContent.length - Range.start.offset);
cur = Tree.nextNode(Range.start.el, inner);
while (cur && cur !== Range.end.el) {
L += cur.textContent.length;
cur = Tree.nextNode(cur, inner);
}
L += Range.end.offset;
return L;
} else if (order === -1) {
L = (Range.end.el.textContent - Range.end.offset);
cur = Tree.nextNode(Range.end.el, inner);
while (cur && cur !== Range.start.el) {
L += cur.textContent.length;
cur = Tree.nextNode(cur, inner);
}
L += Range.start.offset;
return -L;
} else {
console.error("unexpected ordering of nodes...");
return null;
}
}
};
// previously used for testing
// TODO deprecate
var delta = /* cursor.delta = */ function (delta1, delta2) {
var sel = Rangy.getSelection(inner);
delta2 = (typeof delta2 !== 'undefined') ? delta2 : delta1;
// update returns errors if there are problems
// and updates the persistent Range object
var err = cursor.update(sel, inner);
if (err) { return err; }
// create a range to modify
var range = Rangy.createRange();
/*
The assumption below is that Range.(start|end).el
actually exists. This might not be the case.
TODO check if start and end elements are defined
*/
// using infromation about wherever you were last...
// move both parts by some delta
var start = seekToDelta(Range.start.el, delta1, Range.start.offset);
var end = seekToDelta(Range.end.el, delta2, Range.end.offset);
/* if range is backwards, cursor.delta fails
so check if they're in the expected order
before setting the new range */
var order = Tree.orderOfNodes(start.el, end.el, inner);
var backward;
// this could all be one line but nobody would be able to read it
if (order === -1) {
// definitely backward
backward = true;
} else if (order === 0) {
// might be backward, check offsets to know for sure
backward = (start.offset > end.offset);
} else {
// definitely not backward
backward = false;
}
if (backward) {
range.setStart(end.el, end.offset);
range.setEnd(start.el, start.offset);
} else {
range.setStart(start.el, start.offset);
range.setEnd(end.el, end.offset);
}
// actually set the cursor to the new range
sel.setSingleRange(range);
return {
startError: start.error,
endError: end.error
};
};
cursor.brFix = function () {
cursor.update();
var start = Range.start;

@ -1,7 +1,6 @@
define([
'/bower_components/jquery/dist/jquery.min.js',
], function () {
var $ = window.jQuery;
'jquery',
], function ($) {
var module = {};
var Messages = {};
@ -45,6 +44,23 @@ define([
return a;
};
var pushFileData = exp.pushData = function (data) {
Cryptpad.pinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) {
console.log(hash);
});
files[FILES_DATA].push(data);
};
var spliceFileData = exp.removeData = function (idx) {
var data = files[FILES_DATA][idx];
if (typeof data === "object") {
Cryptpad.unpinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) {
console.log(hash);
});
}
files[FILES_DATA].splice(idx, 1);
};
var comparePath = exp.comparePath = function (a, b) {
if (!a || !b || !$.isArray(a) || !$.isArray(b)) { return false; }
if (a.length !== b.length) { return false; }
@ -72,12 +88,15 @@ define([
var isPathInTrash = exp.isPathInTrash = function (path) {
return path[0] && path[0] === TRASH;
};
var isInTrashRoot = exp.isInTrashRoot = function (path) {
return path[0] === TRASH && path.length === 4;
};
var isPathInFilesData = exp.isPathInFilesData = function (path) {
return path[0] && path[0] === FILES_DATA;
};
var isFile = exp.isFile = function (element) {
var isFile = exp.isFile = function (element) {
return typeof(element) === "string";
};
@ -422,10 +441,6 @@ define([
return paths;
};
var isInTrashRoot = exp.isInTrashRoot = function (path) {
return path[0] === TRASH && path.length === 4;
};
var removePadAttribute = function (f) {
Object.keys(files).forEach(function (key) {
var hash = f.indexOf('#') !== -1 ? f.slice(f.indexOf('#') + 1) : null;
@ -459,7 +474,7 @@ define([
var idx = files[FILES_DATA].indexOf(f);
if (idx !== -1) {
debug("Removing", f, "from filesData");
files[FILES_DATA].splice(idx, 1);
spliceFileData(idx);
removePadAttribute(f.href);
}
});
@ -469,9 +484,9 @@ define([
var parentPath = path.slice();
var key = parentPath.pop();
var parentEl = exp.findElement(files, parentPath);
if (path.length === 4 && path[0] === TRASH) {
if (isInTrashRoot(path)) {
files[TRASH][path[1]].splice(path[2], 1);
} else if (path[0] === UNSORTED || path[0] === TEMPLATE) {
} else if (isPathInHrefArray(path)) {
parentEl.splice(key, 1);
} else {
parentEl[key] = undefined;
@ -745,7 +760,7 @@ define([
};
var pushNewFileData = function (href, title) {
files[FILES_DATA].push({
pushFileData({
href: href,
title: title,
atime: +new Date(),
@ -865,7 +880,7 @@ define([
var idx = files[FILES_DATA].indexOf(f);
if (idx !== -1) {
debug("Removing", f, "from filesData");
files[FILES_DATA].splice(idx, 1);
spliceFileData(idx);
// Remove the "padAttributes" stored in the realtime object for that pad
removePadAttribute(f.href);
}
@ -1009,7 +1024,7 @@ define([
return o.href === href;
});
if (!test) {
files[FILES_DATA].push(fileData);
pushFileData(fileData);
}
if (files[TEMPLATE].indexOf(href) === -1) {
files[TEMPLATE].push(href);
@ -1141,7 +1156,7 @@ define([
toClean.forEach(function (el) {
var idx = fd.indexOf(el);
if (idx !== -1) {
fd.splice(idx, 1);
spliceFileData(idx);
}
});
};

@ -1,10 +1,10 @@
define([
'jquery',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/bower_components/chainpad-crypto/crypto.js?v=0.1.5',
'/bower_components/textpatcher/TextPatcher.amd.js',
'/common/fileObject.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Listmap, Crypto, TextPatcher, FO) {
'/common/userObject.js',
], function ($, Listmap, Crypto, TextPatcher, FO) {
/*
This module uses localStorage, which is synchronous, but exposes an
asyncronous API. This is so that we can substitute other storage
@ -13,7 +13,6 @@ define([
To override these methods, create another file at:
/customize/storage.js
*/
var $ = window.jQuery;
var Store = {};
var store;
@ -86,21 +85,26 @@ define([
cb(void 0, Object.keys(storeObj));
};
ret.removeData = filesOp.removeData;
ret.pushData = filesOp.pushData;
ret.addPad = function (href, path, name) {
filesOp.addPad(href, path, name);
filesOp.add(href, path, name);
};
ret.forgetPad = function (href, cb) {
filesOp.forgetPad(href);
filesOp.forget(href);
cb();
};
ret.addTemplate = function (href) {
filesOp.addTemplate(href);
};
ret.listTemplates = function () {
return filesOp.listTemplates();
var templateFiles = filesOp.getFiles(['template']);
var res = [];
templateFiles.forEach(function (f) {
var data = filesOp.getFileData(f);
res.push(JSON.parse(JSON.stringify(data)));
});
return res;
};
ret.getProxy = function () {
@ -120,7 +124,7 @@ define([
};
ret.replaceHref = function (o, n) {
return filesOp.replaceHref(o, n);
return filesOp.replace(o, n);
};
var changeHandlers = ret.changeHandlers = [];

@ -1,12 +1,12 @@
define([
'jquery',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/bower_components/chainpad-crypto/crypto.js',
'/common/cryptpad-common.js',
'/common/credential.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
'/bower_components/scrypt-async/scrypt-async.min.js', // better load speed
'/bower_components/jquery/dist/jquery.min.js',
], function (Listmap, Crypto, Cryptpad, Cred) {
], function ($, Listmap, Crypto, Cryptpad, Cred) {
var Exports = {
Cred: Cred,
};

@ -1,8 +1,7 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'/common/cryptpad-common.js',
'/common/cryptget.js',
'/common/fileObject.js',
'/common/userObject.js',
'json.sortify'
], function (Cryptpad, Crypt, FO, Sortify) {
var exp = {};
@ -76,8 +75,8 @@ define([
console.error(msg || "Unable to find that path", path);
};
if (path[0] === FO.TRASH && path.length === 4) {
href = oldFo.getTrashElementData(path);
if (oldFo.isInTrashRoot(path)) {
href = oldFo.find(path.slice(0,3));
path.pop();
}
@ -156,13 +155,13 @@ define([
var newData = Cryptpad.getStore().getProxy();
var newFo = newData.fo;
var newRecentPads = proxy.drive[Cryptpad.storageKey];
var newFiles = newFo.getFilesDataFiles();
var oldFiles = oldFo.getFilesDataFiles();
var newFiles = newFo.getFiles([newFo.FILES_DATA]);
var oldFiles = oldFo.getFiles([newFo.FILES_DATA]);
oldFiles.forEach(function (href) {
// Do not migrate a pad if we already have it, it would create a duplicate in the drive
if (newFiles.indexOf(href) !== -1) { return; }
// If we have a stronger version, do not add the current href
if (Cryptpad.findStronger(href, newRecentPads)) { return; }
if (Cryptpad.findStronger(href, newRecentPads)) { console.log(href); return; }
// If we have a weaker version, replace the href by the new one
// NOTE: if that weaker version is in the trash, the strong one will be put in unsorted
var weaker = Cryptpad.findWeaker(href, newRecentPads);
@ -176,7 +175,7 @@ define([
return;
});
// Update the file in the drive
newFo.replaceHref(weaker, href);
newFo.replace(weaker, href);
return;
}
// Here it means we have a new href, so we should add it to the drive at its old location

File diff suppressed because it is too large Load Diff

@ -1,17 +1,29 @@
define([
'/common/rpc.js',
'/bower_components/tweetnacl/nacl-fast.min.js'
], function (Rpc) {
var Nacl = window.nacl;
var create = function (network, proxy, cb) {
if (!network) { return void cb('INVALID_NETWORK'); }
if (!proxy) { return void cb('INVALID_PROXY'); }
if (!network) {
window.setTimeout(function () {
cb('INVALID_NETWORK');
});
return;
}
if (!proxy) {
window.setTimeout(function () {
cb('INVALID_PROXY');
});
return;
}
var edPrivate = proxy.edPrivate;
var edPublic = proxy.edPublic;
if (!(edPrivate && edPublic)) { return void cb('INVALID_KEYS'); }
if (!(edPrivate && edPublic)) {
window.setTimeout(function () {
cb('INVALID_KEYS');
});
return;
}
Rpc.create(network, edPrivate, edPublic, function (e, rpc) {
if (e) { return void cb(e); }
@ -26,21 +38,26 @@ define([
// you can ask the server to pin a particular channel for you
exp.pin = function (channels, cb) {
if (!Array.isArray(channels)) {
window.setTimeout(function () {
cb('[TypeError] pin expects an array');
});
return;
}
rpc.send('PIN', channels, cb);
};
// you can also ask to unpin a particular channel
exp.unpin = function (channels, cb) {
if (!Array.isArray(channels)) {
window.setTimeout(function () {
cb('[TypeError] pin expects an array');
});
return;
}
rpc.send('UNPIN', channels, cb);
};
// This implementation must match that on the server
// it's used for a checksum
exp.hashChannelList = function (list) {
return Nacl.util.encodeBase64(Nacl.hash(Nacl.util
.decodeUTF8(JSON.stringify(list))));
};
// ask the server what it thinks your hash is
exp.getServerHash = function (cb) {
rpc.send('GET_HASH', edPublic, function (e, hash) {
@ -52,8 +69,14 @@ define([
};
// if local and remote hashes don't match, send a reset
exp.reset = function (list, cb) {
rpc.send('RESET', list, function (e, response) {
exp.reset = function (channels, cb) {
if (!Array.isArray(channels)) {
window.setTimeout(function () {
cb('[TypeError] pin expects an array');
});
return;
}
rpc.send('RESET', channels, function (e, response) {
cb(e, response[0]);
});
};
@ -66,7 +89,12 @@ define([
// get the combined size of all channels (in bytes) for all the
// channels which the server has pinned for your publicKey
exp.getFileListSize = function (cb) {
rpc.send('GET_TOTAL_SIZE', undefined, cb);
rpc.send('GET_TOTAL_SIZE', undefined, function (e, response) {
if (e) { return void cb(e); }
if (response && response.length) {
cb(void 0, response[0]);
}
});
};
cb(e, exp);

@ -1,29 +0,0 @@
define([], function () {
return function (n) {
n = n || 24; // default is 24 colours
var r = 0.6,
i = 0,
t = [],
rgb = [0,2,4];
while(i<n) { t.push(i++); }
var colours = t.map(function (c, I) {
return '#'+ rgb.map(function (j) {
var x = ((Math.sin(r*(I+22)+j)*127+128) *0x01<<0)
.toString(16);
return x.length<2?"0"+x:x;
}).join("");
});
var J = 0;
return function () {
var j = J++;
if (colours[j]) {
return colours[j];
}
J = 0;
return colours[0];
};
};
});

@ -1,12 +0,0 @@
define([
'/api/config',
], function (Config) {
var urlArgs = Config && Config.requireConf && Config.requireConf.urlArgs;
if (!urlArgs) { return; }
document.querySelectorAll('link[rel="stylesheet"][data-rewrite-href]').forEach(function (e) {
var href = e.getAttribute('data-rewrite-href');
href += (/\?/.test(href)?'&':'?') + urlArgs;
e.setAttribute('href', href);
});
});

@ -22,7 +22,7 @@ define(function () {
"isotope isotope.css",
"lesser-dark lesser-dark.css",
"liquibyte liquibyte.css",
"lol lol.css",
"LOL lol.css",
"material material.css",
"mbo mbo.css",
"mdn-like mdn-like.css",

@ -1,9 +1,8 @@
define([
'jquery',
'/customize/application_config.js',
'/api/config',
'/bower_components/jquery/dist/jquery.min.js'
], function (Config, ApiConfig) {
var $ = window.jQuery;
'/api/config'
], function ($, Config, ApiConfig) {
var Messages = {};

@ -1,91 +1,6 @@
define([], function () {
var tree = {};
// FIXME this isn't being used
var someElement = tree.some = function (root, predicate) {
// take the index of the last element in the current root
var last = root.childElementCount - 1;
// it might be a leaf node
if (last < 0) { return false; }
// otherwise it has children
while (last >= 0) {
// check from back to front
// check the node's children (depth first)
// if the predicate tests true, return true
if (tree.some(root.children[last], predicate)) {
return true;
} // otherwise none of the nodes inside it matched.
// check the node itself
if (predicate(root.children[last], last)) {
return true;
}
last--;
}
return false;
};
// FIXME this isn't being used
var someText = tree.someIncludingText = function (root, predicate) {
// take the index of the last element in the current root
var last = root.childNodes.length - 1;
// it might be a leaf node
if (last < 0) { return false; }
// otherwise it has children
while (last >= 0) {
// check from back to front
// check the node's children (depth first)
// if the predicate tests true, return true
if (tree.someIncludingText(root.childNodes[last], predicate)) {
return true;
} // otherwise none of the nodes inside it matched.
// check the node itself
if (predicate(root.childNodes[last], last)) {
return true;
}
last--;
}
return false;
};
// FIXME not being used
tree.findSameHierarchy = function (list, ancestor) {
var i = 0;
var success = true;
var last = list.length - 1;
var el;
tree.someIncludingText(ancestor, function (e) {
// don't out of bounds
if (i > last) {
// unsuccessful
success = false;
return true;
}
if (list[i] === (e.tagName||e.nodeName)) {
if (i === last) {
el = e;
return true;
}
i++;
} else {
// hierarchy has changed, what should we do?
success = false;
return true; // terminate
}
});
return success? el: false;
};
var indexOfNode = tree.indexOfNode = function (el) {
if (!(el && el.parentNode)) {
console.log("No parentNode found!");
@ -107,13 +22,6 @@ define([], function () {
return el.childNodes.length;
};
var parentsOf = tree.parentsOf = function (el, root) {
var P = [];
var p = el;
while (p !== root) { P.push((p = p.parentNode)); }
return P;
};
/* rightmost and leftmost return the deepest right and left
leaf nodes of a tree
*/

@ -0,0 +1,898 @@
define([
'jquery',
], function ($) {
var module = {};
var ROOT = module.ROOT = "root";
var UNSORTED = module.UNSORTED = "unsorted";
var TRASH = module.TRASH = "trash";
var TEMPLATE = module.TEMPLATE = "template";
var init = module.init = function (files, config) {
var exp = {};
var Cryptpad = config.Cryptpad;
var Messages = Cryptpad.Messages;
var FILES_DATA = module.FILES_DATA = exp.FILES_DATA = Cryptpad.storageKey;
var NEW_FOLDER_NAME = Messages.fm_newFolder;
var NEW_FILE_NAME = Messages.fm_newFile;
// Logging
var DEBUG = config.DEBUG || false;
var logging = function () {
console.log.apply(console, arguments);
};
var log = config.log || logging;
var logError = config.logError || logging;
var debug = config.debug || logging;
var error = exp.error = function() {
exp.fixFiles();
console.error.apply(console, arguments);
};
// TODO: workgroup
var workgroup = config.workgroup;
/*
* UTILS
*/
var getStructure = exp.getStructure = function () {
var a = {};
a[ROOT] = {};
a[UNSORTED] = [];
a[TRASH] = {};
a[FILES_DATA] = [];
a[TEMPLATE] = [];
return a;
};
var getHrefArray = function () {
return [UNSORTED, TEMPLATE];
};
var compareFiles = function (fileA, fileB) { return fileA === fileB; };
var isFile = exp.isFile = function (element) {
return typeof(element) === "string";
};
var isReadOnlyFile = exp.isReadOnlyFile = function (element) {
if (!isFile(element)) { return false; }
var parsed = Cryptpad.parsePadUrl(element);
if (!parsed) { return false; }
var hash = parsed.hash;
var pHash = Cryptpad.parseHash(hash);
if (pHash && !pHash.mode) { return; }
return pHash && pHash.mode === 'view';
};
var isFolder = exp.isFolder = function (element) {
return typeof(element) !== "string";
};
var isFolderEmpty = exp.isFolderEmpty = function (element) {
if (typeof(element) !== "object") { return false; }
return Object.keys(element).length === 0;
};
var hasSubfolder = exp.hasSubfolder = function (element, trashRoot) {
if (typeof(element) !== "object") { return false; }
var subfolder = 0;
var addSubfolder = function (el, idx) {
subfolder += isFolder(el.element) ? 1 : 0;
};
for (var f in element) {
if (trashRoot) {
if ($.isArray(element[f])) {
element[f].forEach(addSubfolder);
}
} else {
subfolder += isFolder(element[f]) ? 1 : 0;
}
}
return subfolder;
};
var hasFile = exp.hasFile = function (element, trashRoot) {
if (typeof(element) !== "object") { return false; }
var file = 0;
var addFile = function (el, idx) {
file += isFile(el.element) ? 1 : 0;
};
for (var f in element) {
if (trashRoot) {
if ($.isArray(element[f])) {
element[f].forEach(addFile);
}
} else {
file += isFile(element[f]) ? 1 : 0;
}
}
return file;
};
// Get data from AllFiles (Cryptpad_RECENTPADS)
var getFileData = exp.getFileData = function (file) {
if (!file) { return; }
var res;
files[FILES_DATA].some(function(arr) {
var href = arr.href;
if (href === file) {
res = arr;
return true;
}
return false;
});
return res;
};
// Data from filesData
var getTitle = exp.getTitle = function (href) {
if (workgroup) { debug("No titles in workgroups"); return; }
var data = getFileData(href);
if (!href || !data) {
error("getTitle called with a non-existing href: ", href);
return;
}
return data.title;
};
// PATHS
var comparePath = exp.comparePath = function (a, b) {
if (!a || !b || !$.isArray(a) || !$.isArray(b)) { return false; }
if (a.length !== b.length) { return false; }
var result = true;
var i = a.length - 1;
while (result && i >= 0) {
result = a[i] === b[i];
i--;
}
return result;
};
var isSubpath = exp.isSubpath = function (path, parentPath) {
var pathA = parentPath.slice();
var pathB = path.slice(0, pathA.length);
return comparePath(pathA, pathB);
};
var isPathIn = exp.isPathIn = function (path, categories) {
if (!categories) { return; }
var idx = categories.indexOf('hrefArray');
if (idx !== -1) {
categories.splice(idx, 1);
categories = categories.concat(getHrefArray());
}
return categories.some(function (c) {
return Array.isArray(path) && path[0] === c;
});
};
var isInTrashRoot = exp.isInTrashRoot = function (path) {
return path[0] === TRASH && path.length === 4;
};
// FIND
var findElement = function (root, pathInput) {
if (!pathInput) {
error("Invalid path:\n", pathInput, "\nin root\n", root);
return;
}
if (pathInput.length === 0) { return root; }
var path = pathInput.slice();
var key = path.shift();
if (typeof root[key] === "undefined") {
debug("Unable to find the key '" + key + "' in the root object provided:", root);
return;
}
return findElement(root[key], path);
};
var find = exp.find = function (path) {
return findElement(files, path);
};
// GET FILES
var getFilesRecursively = function (root, arr) {
for (var e in root) {
if (isFile(root[e])) {
if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); }
} else {
getFilesRecursively(root[e], arr);
}
}
};
var _getFiles = {};
_getFiles['array'] = function (cat) {
if (!files[cat]) { files[cat] = []; }
return files[cat].slice();
};
getHrefArray().forEach(function (c) {
_getFiles[c] = function () { return _getFiles['array'](c); };
});
_getFiles['hrefArray'] = function () {
var ret = [];
getHrefArray().forEach(function (c) {
ret = ret.concat(_getFiles[c]());
});
return Cryptpad.deduplicateString(ret);
};
_getFiles[ROOT] = function () {
var ret = [];
getFilesRecursively(files[ROOT], ret);
return ret;
};
_getFiles[TRASH] = function () {
var root = files[TRASH];
var ret = [];
var addFiles = function (el, idx) {
if (isFile(el.element)) {
if(ret.indexOf(el.element) === -1) { ret.push(el.element); }
} else {
getFilesRecursively(el.element, ret);
}
};
for (var e in root) {
if (!$.isArray(root[e])) {
error("Trash contains a non-array element");
return;
}
root[e].forEach(addFiles);
}
return ret;
};
_getFiles[FILES_DATA] = function () {
var ret = [];
files[FILES_DATA].forEach(function (el) {
if (el.href && ret.indexOf(el.href) === -1) {
ret.push(el.href);
}
});
return ret;
};
var getFiles = exp.getFiles = function (categories) {
var ret = [];
if (!categories || !categories.length) {
categories = [ROOT, 'hrefArray', TRASH, FILES_DATA];
}
categories.forEach(function (c) {
if (typeof _getFiles[c] === "function") {
ret = ret.concat(_getFiles[c]());
}
});
return Cryptpad.deduplicateString(ret);
};
// SEARCH
var _findFileInRoot = function (path, href) {
if (!isPathIn(path, [ROOT, TRASH])) { return []; }
var paths = [];
var root = find(path);
var addPaths = function (p) {
if (paths.indexOf(p) === -1) {
paths.push(p);
}
};
if (isFile(root)) {
if (compareFiles(href, root)) {
if (paths.indexOf(path) === -1) {
paths.push(path);
}
}
return paths;
}
for (var e in root) {
var nPath = path.slice();
nPath.push(e);
_findFileInRoot(nPath, href).forEach(addPaths);
}
return paths;
};
var _findFileInHrefArray = function (rootName, href) {
var unsorted = files[rootName].slice();
var ret = [];
var i = -1;
while ((i = unsorted.indexOf(href, i+1)) !== -1){
ret.push([rootName, i]);
}
return ret;
};
var _findFileInTrash = function (path, href) {
var root = find(path);
var paths = [];
var addPaths = function (p) {
if (paths.indexOf(p) === -1) {
paths.push(p);
}
};
if (path.length === 1 && typeof(root) === 'object') {
Object.keys(root).forEach(function (key) {
var arr = root[key];
if (!Array.isArray(arr)) { return; }
var nPath = path.slice();
nPath.push(key);
_findFileInTrash(nPath, href).forEach(addPaths);
});
}
if (path.length === 2) {
if (!Array.isArray(root)) { return []; }
root.forEach(function (el, i) {
var nPath = path.slice();
nPath.push(i);
nPath.push('element');
if (isFile(el.element)) {
if (compareFiles(href, el.element)) {
addPaths(nPath);
}
return;
}
_findFileInTrash(nPath, href).forEach(addPaths);
});
}
if (path.length >= 4) {
_findFileInRoot(path, href).forEach(addPaths);
}
return paths;
};
var findFile = exp.findFile = function (href) {
var rootpaths = _findFileInRoot([ROOT], href);
var unsortedpaths = _findFileInHrefArray(UNSORTED, href);
var templatepaths = _findFileInHrefArray(TEMPLATE, href);
var trashpaths = _findFileInTrash([TRASH], href);
return rootpaths.concat(unsortedpaths, templatepaths, trashpaths);
};
var search = exp.search = function (value) {
if (typeof(value) !== "string") { return []; }
var res = [];
// Search in ROOT
var findIn = function (root) {
Object.keys(root).forEach(function (k) {
if (isFile(root[k])) {
if (k.toLowerCase().indexOf(value.toLowerCase()) !== -1) {
res.push(root[k]);
}
return;
}
findIn(root[k]);
});
};
findIn(files[ROOT]);
// Search in TRASH
var trash = files[TRASH];
Object.keys(trash).forEach(function (k) {
if (k.toLowerCase().indexOf(value.toLowerCase()) !== -1) {
trash[k].forEach(function (el) {
if (isFile(el.element)) {
res.push(el.element);
}
});
}
trash[k].forEach(function (el) {
if (isFolder(el.element)) {
findIn(el.element);
}
});
});
// Search title
var allFilesList = files[FILES_DATA].slice();
allFilesList.forEach(function (t) {
if (t.title && t.title.toLowerCase().indexOf(value.toLowerCase()) !== -1) {
res.push(t.href);
}
});
// Search Href
var href = Cryptpad.getRelativeHref(value);
if (href) {
res.push(href);
}
res = Cryptpad.deduplicateString(res);
var ret = [];
res.forEach(function (l) {
var paths = findFile(l);
ret.push({
paths: findFile(l),
data: exp.getFileData(l)
});
});
return ret;
};
/**
* OPERATIONS
*/
var getAvailableName = function (parentEl, name) {
if (typeof(parentEl[name]) === "undefined") { return name; }
var newName = name;
var i = 1;
while (typeof(parentEl[newName]) !== "undefined") {
newName = name + "_" + i;
i++;
}
return newName;
};
// FILES DATA
var pushFileData = exp.pushData = function (data) {
Cryptpad.pinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) {
if (e) { console.log(e); return; }
console.log(hash);
});
files[FILES_DATA].push(data);
};
var spliceFileData = exp.removeData = function (idx) {
var data = files[FILES_DATA][idx];
if (typeof data === "object") {
Cryptpad.unpinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) {
if (e) { console.log(e); return; }
console.log(hash);
});
}
files[FILES_DATA].splice(idx, 1);
};
// MOVE
var pushToTrash = function (name, element, path) {
var trash = files[TRASH];
if (typeof(trash[name]) === "undefined") { trash[name] = []; }
var trashArray = trash[name];
var trashElement = {
element: element,
path: path
};
trashArray.push(trashElement);
};
var copyElement = function (elementPath, newParentPath) {
if (comparePath(elementPath, newParentPath)) { return; } // Nothing to do...
var element = find(elementPath);
var newParent = find(newParentPath);
// Never move a folder in one of its children
if (isSubpath(newParentPath, elementPath)) {
log(Messages.fo_moveFolderToChildError);
return;
}
// Move to Trash
if (isPathIn(newParentPath, [TRASH])) {
if (!elementPath || elementPath.length < 2 || elementPath[0] === TRASH) {
debug("Can't move an element from the trash to the trash: ", elementPath);
return;
}
var key = elementPath[elementPath.length - 1];
var elName = isPathIn(elementPath, ['hrefArray']) ? getTitle(element) : key;
var parentPath = elementPath.slice();
parentPath.pop();
pushToTrash(elName, element, parentPath);
return true;
}
// Move to hrefArray
if (isPathIn(newParentPath, ['hrefArray'])) {
if (isFolder(element)) {
log(Messages.fo_moveUnsortedError);
return;
} else {
if (elementPath[0] === newParentPath[0]) { return; }
var fileRoot = newParentPath[0];
if (files[fileRoot].indexOf(element) === -1) {
files[fileRoot].push(element);
}
return true;
}
}
// Move to root
var name;
if (isPathIn(elementPath, ['hrefArray'])) {
name = getTitle(element);
} else if (isInTrashRoot(elementPath)) {
// Element from the trash root: elementPath = [TRASH, "{dirName}", 0, 'element']
name = elementPath[1];
} else {
name = elementPath[elementPath.length-1];
}
var newName = !isPathIn(elementPath, [ROOT]) ? getAvailableName(newParent, name) : name;
if (typeof(newParent[newName]) !== "undefined") {
log(Messages.fo_unavailableName);
return;
}
newParent[newName] = element;
return true;
};
var move = exp.move = function (paths, newPath, cb) {
// Copy the elements to their new location
var toRemove = [];
paths.forEach(function (p) {
var parentPath = p.slice();
parentPath.pop();
if (comparePath(parentPath, newPath)) { return; }
copyElement(p, newPath);
toRemove.push(p);
});
exp.delete(toRemove, cb);
};
var restore = exp.restore = function (path, cb) {
if (!isInTrashRoot(path)) { return; }
var parentPath = path.slice();
parentPath.pop();
var oldPath = find(parentPath).path;
move([path], oldPath, cb);
};
// ADD
var add = exp.add = function (href, path, name, cb) {
if (!href) { return; }
var newPath = path, parentEl;
if (path && !Array.isArray(path)) {
newPath = decodeURIComponent(path).split(',');
}
// Add to href array
if (path && isPathIn(newPath, ['hrefArray'])) {
parentEl = find(newPath);
parentEl.push(href);
return;
}
// Add to root
if (path && isPathIn(newPath, [ROOT]) && name) {
parentEl = find(newPath);
if (parentEl) {
var newName = getAvailableName(parentEl, name);
parentEl[newName] = href;
return;
}
}
// No path: push to unsorted
var filesList = getFiles([ROOT, TRASH, 'hrefArray']);
if (filesList.indexOf(href) === -1) { files[UNSORTED].push(href); }
if (typeof cb === "function") { cb(); }
};
var addFile = exp.addFile = function (filePath, name, type, cb) {
var parentEl = findElement(files, filePath);
var fileName = getAvailableName(parentEl, name || NEW_FILE_NAME);
var href = '/' + type + '/#' + Cryptpad.createRandomHash();
parentEl[fileName] = href;
pushFileData({
href: href,
title: fileName,
atime: +new Date(),
ctime: +new Date()
});
var newPath = filePath.slice();
newPath.push(fileName);
cb({
newPath: newPath
});
};
var addFolder = exp.addFolder = function (folderPath, name, cb) {
var parentEl = find(folderPath);
var folderName = getAvailableName(parentEl, name || NEW_FOLDER_NAME);
parentEl[folderName] = {};
var newPath = folderPath.slice();
newPath.push(folderName);
cb({
newPath: newPath
});
};
// FORGET (move with href not path)
var forget = exp.forget = function (href) {
var paths = findFile(href);
move(paths, [TRASH]);
};
// DELETE
// Permanently delete multiple files at once using a list of paths
// NOTE: We have to be careful when removing elements from arrays (trash root, unsorted or template)
var removePadAttribute = function (f) {
Object.keys(files).forEach(function (key) {
var hash = f.indexOf('#') !== -1 ? f.slice(f.indexOf('#') + 1) : null;
if (hash && key.indexOf(hash) === 0) {
debug("Deleting pad attribute in the realtime object");
files[key] = undefined;
delete files[key];
}
});
};
var checkDeletedFiles = function () {
// Nothing in FILES_DATA for workgroups
if (workgroup) { return; }
var filesList = getFiles([ROOT, 'hrefArray', TRASH]);
var toRemove = [];
files[FILES_DATA].forEach(function (arr) {
var f = arr.href;
if (filesList.indexOf(f) === -1) {
toRemove.push(arr);
}
});
toRemove.forEach(function (f) {
var idx = files[FILES_DATA].indexOf(f);
if (idx !== -1) {
debug("Removing", f, "from filesData");
spliceFileData(idx);
removePadAttribute(f.href);
}
});
};
var deleteHrefs = function (hrefs) {
hrefs.forEach(function (obj) {
var idx = files[obj.root].indexOf(obj.href);
files[obj.root].splice(idx, 1);
});
};
var deleteMultipleTrashRoot = function (roots) {
roots.forEach(function (obj) {
var idx = files[TRASH][obj.name].indexOf(obj.el);
files[TRASH][obj.name].splice(idx, 1);
});
};
var deleteMultiplePermanently = function (paths, nocheck) {
var hrefPaths = paths.filter(function(x) { return isPathIn(x, ['hrefArray']); });
var rootPaths = paths.filter(function(x) { return isPathIn(x, [ROOT]); });
var trashPaths = paths.filter(function(x) { return isPathIn(x, [TRASH]); });
var hrefs = [];
hrefPaths.forEach(function (path) {
var href = find(path);
hrefs.push({
root: path[0],
href: href
});
});
deleteHrefs(hrefs);
rootPaths.forEach(function (path) {
var parentPath = path.slice();
var key = parentPath.pop();
var parentEl = find(parentPath);
parentEl[key] = undefined;
delete parentEl[key];
});
var trashRoot = [];
trashPaths.forEach(function (path) {
var parentPath = path.slice();
var key = parentPath.pop();
var parentEl = find(parentPath);
// Trash root: we have array here, we can't just splice with the path otherwise we might break the path
// of another element in the loop
if (path.length === 4) {
trashRoot.push({
name: path[1],
el: parentEl
});
return;
}
// Trash but not root: it's just a tree so remove the key
parentEl[key] = undefined;
delete parentEl[key];
});
deleteMultipleTrashRoot(trashRoot);
// In some cases, we want to remove pads from a location without removing them from
// FILES_DATA (replaceHref)
if (!nocheck) { checkDeletedFiles(); }
};
var deletePath = exp.delete = function (paths, cb, nocheck) {
deleteMultiplePermanently(paths, nocheck);
if (typeof cb === "function") { cb(); }
};
var emptyTrash = exp.emptyTrash = function (cb) {
files[TRASH] = {};
checkDeletedFiles();
if(cb) { cb(); }
};
// RENAME
var rename = exp.rename = function (path, newName, cb) {
if (path.length <= 1) {
logError('Renaming `root` is forbidden');
return;
}
if (!newName || newName.trim() === "") { return; }
// Copy the element path and remove the last value to have the parent path and the old name
var element = find(path);
var parentPath = path.slice();
var oldName = parentPath.pop();
if (oldName === newName) {
return;
}
var parentEl = find(parentPath);
if (typeof(parentEl[newName]) !== "undefined") {
log(Messages.fo_existingNameError);
return;
}
parentEl[newName] = element;
parentEl[oldName] = undefined;
delete parentEl[oldName];
cb();
};
// REPLACE
var replaceFile = function (path, o, n) {
var root = find(path);
if (isFile(root)) { return; }
for (var e in root) {
if (isFile(root[e])) {
if (compareFiles(o, root[e])) {
root[e] = n;
}
} else {
var nPath = path.slice();
nPath.push(e);
replaceFile(nPath, o, n);
}
}
};
// Replace a href by a stronger one everywhere in the drive (except FILES_DATA)
var replaceHref = exp.replace = function (o, n) {
if (!isFile(o) || !isFile(n)) { return; }
var paths = findFile(o);
// Remove all the occurences in the trash
// Replace all the occurences not in the trash
// If all the occurences are in the trash or no occurence, add the pad to unsorted
var allInTrash = true;
paths.forEach(function (p) {
if (p[0] === TRASH) {
exp.delete(p, null, true); // 3rd parameter means skip "checkDeletedFiles"
return;
} else {
allInTrash = false;
var parentPath = p.slice();
var key = parentPath.pop();
var parentEl = find(parentPath);
parentEl[key] = n;
}
});
if (allInTrash) {
add(n);
}
};
/**
* INTEGRITY CHECK
*/
var fixFiles = exp.fixFiles = function () {
// Explore the tree and check that everything is correct:
// * 'root', 'trash', 'unsorted' and 'filesData' exist and are objects
// * ROOT: Folders are objects, files are href
// * TRASH: Trash root contains only arrays, each element of the array is an object {element:.., path:..}
// * FILES_DATA: - Data (title, cdate, adte) are stored in filesData. filesData contains only href keys linking to object with title, cdate, adate.
// - Dates (adate, cdate) can be parsed/formatted
// - All files in filesData should be either in 'root', 'trash' or 'unsorted'. If that's not the case, copy the fily to 'unsorted'
// * UNSORTED: Contains only files (href), and does not contains files that are in ROOT
debug("Cleaning file system...");
var before = JSON.stringify(files);
var fixRoot = function (elem) {
if (typeof(files[ROOT]) !== "object") { debug("ROOT was not an object"); files[ROOT] = {}; }
var element = elem || files[ROOT];
for (var el in element) {
if (!isFile(element[el]) && !isFolder(element[el])) {
debug("An element in ROOT was not a folder nor a file. ", element[el]);
element[el] = undefined;
delete element[el];
} else if (isFolder(element[el])) {
fixRoot(element[el]);
}
}
};
var fixTrashRoot = function () {
if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; }
var tr = files[TRASH];
var toClean;
var addToClean = function (obj, idx) {
if (typeof(obj) !== "object") { toClean.push(idx); return; }
if (!isFile(obj.element) && !isFolder(obj.element)) { toClean.push(idx); return; }
if (!$.isArray(obj.path)) { toClean.push(idx); return; }
};
for (var el in tr) {
if (!$.isArray(tr[el])) {
debug("An element in TRASH root is not an array. ", tr[el]);
tr[el] = undefined;
delete tr[el];
} else {
toClean = [];
tr[el].forEach(addToClean);
for (var i = toClean.length-1; i>=0; i--) {
tr[el].splice(toClean[i], 1);
}
}
}
};
var fixUnsorted = function () {
if (!Array.isArray(files[UNSORTED])) { debug("UNSORTED was not an array"); files[UNSORTED] = []; }
files[UNSORTED] = Cryptpad.deduplicateString(files[UNSORTED].slice());
var us = files[UNSORTED];
var rootFiles = getFiles([ROOT, TEMPLATE]).slice();
var toClean = [];
us.forEach(function (el, idx) {
if (!isFile(el) || rootFiles.indexOf(el) !== -1) {
toClean.push(idx);
}
});
toClean.forEach(function (idx) {
us.splice(idx, 1);
});
};
var fixTemplate = function () {
if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; }
files[TEMPLATE] = Cryptpad.deduplicateString(files[TEMPLATE].slice());
var us = files[TEMPLATE];
var rootFiles = getFiles([ROOT, UNSORTED]).slice();
var toClean = [];
us.forEach(function (el, idx) {
if (!isFile(el) || rootFiles.indexOf(el) !== -1) {
toClean.push(idx);
}
});
toClean.forEach(function (idx) {
us.splice(idx, 1);
});
};
var fixFilesData = function () {
if (!$.isArray(files[FILES_DATA])) { debug("FILES_DATA was not an array"); files[FILES_DATA] = []; }
var fd = files[FILES_DATA];
var rootFiles = getFiles([ROOT, TRASH, 'hrefArray']);
var toClean = [];
fd.forEach(function (el, idx) {
if (!el || typeof(el) !== "object") {
debug("An element in filesData was not an object.", el);
toClean.push(el);
return;
}
if (rootFiles.indexOf(el.href) === -1) {
debug("An element in filesData was not in ROOT, UNSORTED or TRASH.", el);
files[UNSORTED].push(el.href);
return;
}
});
toClean.forEach(function (el) {
var idx = fd.indexOf(el);
if (idx !== -1) {
spliceFileData(idx);
}
});
};
fixRoot();
fixTrashRoot();
if (!workgroup) {
fixUnsorted();
fixTemplate();
fixFilesData();
}
if (JSON.stringify(files) !== before) {
debug("Your file system was corrupted. It has been cleaned so that the pads you visit can be stored safely");
return;
}
debug("File system was clean");
};
return exp;
};
return module;
});

@ -1,20 +1,19 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'jquery',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'json.sortify',
'/common/cryptpad-common.js',
'/common/fileObject.js',
'/common/userObject.js',
'/common/toolbar.js',
'/customize/application_config.js',
'/common/cryptget.js',
'/common/mergeDrive.js'
], function (Listmap, Crypto, TextPatcher, JSONSortify, Cryptpad, FO, Toolbar, AppConfig, Get, Merge) {
], function ($, Listmap, Crypto, TextPatcher, JSONSortify, Cryptpad, FO, Toolbar, AppConfig, Get, Merge) {
var module = window.MODULE = {};
var Messages = Cryptpad.Messages;
var $ = window.jQuery;
var saveAs = window.saveAs;
// Use `$(function () {});` to make sure the html is loaded before doing anything else
@ -264,9 +263,7 @@ define([
var removeInput = function (cancel) {
if (!cancel && $iframe.find('.element-row > input').length === 1) {
var $input = $iframe.find('.element-row > input');
filesOp.renameElement($input.data('path'), $input.val(), function () {
APP.refresh();
});
filesOp.rename($input.data('path'), $input.val(), APP.refresh);
}
$iframe.find('.element-row > input').remove();
$iframe.find('.element-row > span:hidden').removeAttr('style');
@ -332,9 +329,7 @@ define([
$input.on('keyup', function (e) {
if (e.which === 13) {
removeInput(true);
filesOp.renameElement(path, $input.val(), function () {
refresh();
});
filesOp.rename(path, $input.val(), refresh);
return;
}
if (e.which === 27) {
@ -371,6 +366,7 @@ define([
var filterContextMenu = function ($menu, paths) {
//var path = $element.data('path');
if (!paths || paths.length === 0) { console.error('no paths'); }
var hide = [];
var hasFolder = false;
@ -652,16 +648,12 @@ define([
var getElementName = function (path) {
// Trash root
if (filesOp.isInTrashRoot(path)) {
return path[0];
}
if (filesOp.isInTrashRoot(path)) { return path[0]; }
// Root or trash
if (filesOp.isPathInRoot(path) || filesOp.isPathInTrash(path)) {
return path[path.length - 1];
}
if (filesOp.isPathIn(path, [ROOT, TRASH])) { return path[path.length - 1]; }
// Unsorted or template
if (filesOp.isPathInUnsorted(path) || filesOp.isPathInTemplate(path)) {
var file = filesOp.findElement(files, path);
if (filesOp.isPathIn(path, ['hrefArray'])) {
var file = filesOp.find(path);
if (filesOp.isFile(file) && filesOp.getTitle(file)) {
return filesOp.getTitle(file);
}
@ -674,10 +666,10 @@ define([
var moveElements = function (paths, newPath, force, cb) {
if (!APP.editable) { return; }
var andThen = function () {
filesOp.moveElements(paths, newPath, cb);
filesOp.move(paths, newPath, cb);
};
// Cancel drag&drop from TRASH to TRASH
if (filesOp.comparePath(newPath, [TRASH]) && paths.length >= 1 && paths[0][0] === TRASH) {
if (filesOp.isPathIn(newPath, [TRASH]) && paths.length && paths[0][0] === TRASH) {
return;
}
// "force" is currently unused but may be configurable by user
@ -688,7 +680,7 @@ define([
var msg = Messages._getKey('fm_removeSeveralDialog', [paths.length]);
if (paths.length === 1) {
var path = paths[0];
var name = path[0] === UNSORTED ? filesOp.getTitle(filesOp.findElement(files, path)) : path[path.length - 1];
var name = path[0] === UNSORTED ? filesOp.getTitle(filesOp.find(path)) : path[path.length - 1];
msg = Messages._getKey('fm_removeDialog', [name]);
}
Cryptpad.confirm(msg, function (res) {
@ -707,7 +699,7 @@ define([
$selected.each(function (idx, elmt) {
var ePath = $(elmt).data('path');
if (ePath) {
var val = filesOp.findElement(files, ePath);
var val = filesOp.find(ePath);
if (!val) { return; } // Error? A ".selected" element in not in the object
paths.push({
path: ePath,
@ -721,7 +713,7 @@ define([
} else {
removeSelected();
$element.addClass('selected');
var val = filesOp.findElement(files, path);
var val = filesOp.find(path);
if (!val) { return; } // The element in not in the object
paths = [{
path: path,
@ -749,7 +741,7 @@ define([
var movedPaths = [];
var importedElements = [];
oldPaths.forEach(function (p) {
var el = filesOp.findElement(files, p.path);
var el = filesOp.find(p.path);
if (el && (stringify(el) === stringify(p.value.el) || !p.value || !p.value.el)) {
movedPaths.push(p.path);
} else {
@ -764,7 +756,8 @@ define([
moveElements(movedPaths, newPath, null, refresh);
}
if (importedElements && importedElements.length) {
filesOp.importElements(importedElements, newPath, refresh);
// TODO workgroup
//filesOp.importElements(importedElements, newPath, refresh);
}
};
@ -882,7 +875,7 @@ define([
newPath.push(key);
}
var element = filesOp.findElement(files, newPath);
var element = filesOp.find(newPath);
var $icon = !isFolder ? getFileIcon(element) : undefined;
var ro = filesOp.isReadOnlyFile(element);
// ro undefined mens it's an old hash which doesn't support read-only
@ -967,7 +960,7 @@ define([
// Create the title block with the "parent folder" button
var createTitle = function (path, noStyle) {
if (!path || path.length === 0) { return; }
var isTrash = filesOp.isPathInTrash(path);
var isTrash = filesOp.isPathIn(path, [TRASH]);
var $title = $('<span>', {'class': 'path unselectable'});
if (APP.mobile()) {
return $title;
@ -1119,17 +1112,17 @@ define([
refresh();
};
$block.find('a.newFolder').click(function () {
filesOp.createNewFolder(currentPath, null, onCreated);
filesOp.addFolder(currentPath, null, onCreated);
});
$block.find('a.newdoc').click(function (e) {
var type = $(this).attr('data-type') || 'pad';
var name = Cryptpad.getDefaultName({type: type});
filesOp.createNewFile(currentPath, name, type, onCreated);
filesOp.addFile(currentPath, name, type, onCreated);
});
} else {
$block.find('a.newdoc').click(function (e) {
var type = $(this).attr('data-type') || 'pad';
sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathInTrash(currentPath) ? '' : currentPath;
sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
window.open('/' + type + '/');
});
}
@ -1251,11 +1244,11 @@ define([
};
var allFilesSorted = function () {
return filesOp.getUnsortedFiles().length === 0;
return filesOp.getFiles([UNSORTED]).length === 0;
};
var sortElements = function (folder, path, oldkeys, prop, asc, useHref, useData) {
var root = filesOp.findElement(files, path);
var root = filesOp.find(path);
var test = folder ? filesOp.isFolder : filesOp.isFile;
var keys;
if (!useData) {
@ -1478,7 +1471,7 @@ define([
var $atime = $('<td>', {'class': 'col2'}).text(new Date(r.data.atime).toLocaleString());
var $ctimeName = $('<td>', {'class': 'label2'}).text(Messages.fm_creation);
var $ctime = $('<td>', {'class': 'col2'}).text(new Date(r.data.ctime).toLocaleString());
if (filesOp.isPathInHrefArray(path)) {
if (filesOp.isPathIn(path, ['hrefArray'])) {
path.pop();
path.push(r.data.title);
}
@ -1522,14 +1515,14 @@ define([
if (!path || path.length === 0) {
path = [ROOT];
}
var isInRoot = filesOp.isPathInRoot(path);
var isInRoot = filesOp.isPathIn(path, [ROOT]);
var isTrashRoot = filesOp.comparePath(path, [TRASH]);
var isUnsorted = filesOp.comparePath(path, [UNSORTED]);
var isTemplate = filesOp.comparePath(path, [TEMPLATE]);
var isAllFiles = filesOp.comparePath(path, [FILES_DATA]);
var isSearch = path[0] === SEARCH;
var root = isSearch ? undefined : filesOp.findElement(files, path);
var root = isSearch ? undefined : filesOp.find(path);
if (!isSearch && typeof(root) === "undefined") {
log(Messages.fm_unknownFolderError);
debug("Unable to locate the selected directory: ", path);
@ -1642,11 +1635,11 @@ define([
var $el = $(e);
if ($el.data('path')) {
var path = $el.data('path');
var element = filesOp.findElement(files, path);
var element = filesOp.find(path);
if (!filesOp.isFile(element)) { return; }
var data = filesOp.getFileData(element);
if (!data) { return; }
if (filesOp.isPathInHrefArray(path)) { $el.find('.name').attr('title', data.title).text(data.title); }
if (filesOp.isPathIn(path, ['hrefArray'])) { $el.find('.name').attr('title', data.title).text(data.title); }
$el.find('.title').attr('title', data.title).text(data.title);
$el.find('.atime').attr('title', getDate(data.atime)).text(getDate(data.atime));
$el.find('.ctime').attr('title', getDate(data.ctime)).text(getDate(data.ctime));
@ -1700,7 +1693,7 @@ define([
};
var createTree = function ($container, path) {
var root = filesOp.findElement(files, path);
var root = filesOp.find(path);
// don't try to display what doesn't exist
if (!root) { return; }
@ -1930,7 +1923,7 @@ define([
}
else if ($(this).hasClass('open_ro')) {
paths.forEach(function (p) {
var el = filesOp.findElement(files, p.path);
var el = filesOp.find(p.path);
if (filesOp.isFolder(el)) { return; }
var roUrl = getReadOnlyUrl(el);
openFile(roUrl, false);
@ -1942,11 +1935,11 @@ define([
module.newFolder = info.newPath;
module.displayDirectory(paths[0].path);
};
filesOp.createNewFolder(paths[0].path, null, onCreated);
filesOp.addFolder(paths[0].path, null, onCreated);
}
else if ($(this).hasClass("properties")) {
if (paths.length !== 1) { return; }
var el = filesOp.findElement(files, paths[0].path);
var el = filesOp.find(paths[0].path);
var prop = getProperties(el);
Cryptpad.alert('', undefined, true);
$('.alertify .msg').html(prop);
@ -1972,8 +1965,8 @@ define([
}
else if ($(this).hasClass('open_ro')) {
paths.forEach(function (p) {
var el = filesOp.findElement(files, p.path);
if (filesOp.isPathInFilesData(p.path)) { el = el.href; }
var el = filesOp.find(p.path);
if (filesOp.isPathIn(p.path, [FILES_DATA])) { el = el.href; }
if (!el || filesOp.isFolder(el)) { return; }
var roUrl = getReadOnlyUrl(el);
openFile(roUrl, false);
@ -1986,7 +1979,7 @@ define([
}
else if ($(this).hasClass("properties")) {
if (paths.length !== 1) { return; }
var el = filesOp.findElement(files, paths[0].path);
var el = filesOp.find(paths[0].path);
var prop = getProperties(el);
Cryptpad.alert('', undefined, true);
$('.alertify .msg').html(prop);
@ -2004,12 +1997,12 @@ define([
refresh();
};
if ($(this).hasClass("newfolder")) {
filesOp.createNewFolder(path, null, onCreated);
filesOp.addFolder(path, null, onCreated);
}
else if ($(this).hasClass("newdoc")) {
var type = $(this).data('type') || 'pad';
var name = Cryptpad.getDefaultName({type: type});
filesOp.createNewFile(path, name, type, onCreated);
filesOp.addFile(path, name, type, onCreated);
}
module.hideMenu();
});
@ -2046,7 +2039,7 @@ define([
if (path.length === 4) { name = path[1]; }
Cryptpad.confirm(Messages._getKey("fm_removePermanentlyDialog", [name]), function(res) {
if (!res) { return; }
filesOp.removeFromTrash(path, refresh);
filesOp.delete([path], refresh);
});
return;
}
@ -2055,8 +2048,7 @@ define([
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
Cryptpad.confirm(msg, function(res) {
if (!res) { return; }
filesOp.deletePathsPermanently(pathsList);
refresh();
filesOp.delete(pathsList, refresh);
});
}
else if ($(this).hasClass("restore")) {
@ -2064,13 +2056,12 @@ define([
if (path.length === 4) { name = path[1]; }
Cryptpad.confirm(Messages._getKey("fm_restoreDialog", [name]), function(res) {
if (!res) { return; }
filesOp.restoreTrash(path, refresh);
filesOp.restore(path, refresh);
});
}
else if ($(this).hasClass("properties")) {
if (paths.length !== 1) { return; }
if (path.length !== 4) { return; }
var element = filesOp.getTrashElementData(path);
if (paths.length !== 1 || path.length !== 4) { return; }
var element = filesOp.find(path.slice(0,3)); // element containing the oldpath
var sPath = stringifyPath(element.path);
Cryptpad.alert('<strong>' + Messages.fm_originalPath + "</strong>:<br>" + sPath, undefined, true);
}
@ -2094,20 +2085,17 @@ define([
$appContainer.on('keydown', function (e) {
// "Del"
if (e.which === 46) {
if (filesOp.isPathInFilesData(currentPath)) { return; } // We can't remove elements directly from filesData
if (filesOp.isPathIn(currentPath, [FILES_DATA])) { return; } // We can't remove elements directly from filesData
var $selected = $iframe.find('.selected');
if (!$selected.length) { return; }
var paths = [];
var isTrash = filesOp.isPathInTrash(currentPath);
var isTrash = filesOp.isPathIn(currentPath, [TRASH]);
$selected.each(function (idx, elmt) {
if (!$(elmt).data('path')) { return; }
paths.push($(elmt).data('path'));
});
// If we are in the trash or anon pad or if we are holding the "shift" key, delete permanently,
if (isTrash || e.shiftKey) {
//var cb = filesOp.removeFromTrash; // We're in the trash
//if (!isTrash) { cb = filesOp.deletePathPermanently; } // We're in root
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
if (paths.length === 1) {
msg = Messages.fm_removePermanentlyDialog;
@ -2116,8 +2104,7 @@ define([
Cryptpad.confirm(msg, function(res) {
$(ifrw).focus();
if (!res) { return; }
filesOp.deletePathsPermanently(paths);
refresh();
filesOp.delete(paths, refresh);
});
return;
}
@ -2143,10 +2130,8 @@ define([
if (path[0] !== 'drive') { return false; }
path = path.slice(1);
var cPath = currentPath.slice();
if ((filesOp.isPathInUnsorted(cPath) && filesOp.isPathInUnsorted(path)) ||
(filesOp.isPathInTemplate(cPath) && filesOp.isPathInTemplate(path)) ||
(path.length >= cPath.length && filesOp.isSubpath(path, cPath)) ||
(filesOp.isPathInTrash(cPath) && filesOp.isPathInTrash(path))) {
if ((filesOp.isPathIn(cPath, ['hrefArray', TRASH]) && cPath[0] === path[0]) ||
(path.length >= cPath.length && filesOp.isSubpath(path, cPath))) {
// Reload after a few ms to make sure all the change events have been received
onRefresh.refresh();
} else if (path.length && path[0] === FILES_DATA) {
@ -2159,10 +2144,8 @@ define([
if (path[0] !== 'drive') { return false; }
path = path.slice(1);
var cPath = currentPath.slice();
if ((filesOp.isPathInUnsorted(cPath) && filesOp.isPathInUnsorted(path)) ||
(filesOp.isPathInTemplate(cPath) && filesOp.isPathInTemplate(path)) ||
(path.length >= cPath.length && filesOp.isSubpath(path, cPath)) ||
(filesOp.isPathInTrash(cPath) && filesOp.isPathInTrash(path))) {
if ((filesOp.isPathIn(cPath, ['hrefArray', TRASH]) && cPath[0] === path[0]) ||
(path.length >= cPath.length && filesOp.isSubpath(path, cPath))) {
// Reload after a few to make sure all the change events have been received
onRefresh.to = window.setTimeout(refresh, 500);
}
@ -2243,6 +2226,7 @@ define([
// don't initialize until the store is ready.
Cryptpad.ready(function () {
Cryptpad.reportAppUsage();
APP.$bar = $iframe.find('#toolbar');
var storeObj = Cryptpad.getStore().getProxy && Cryptpad.getStore().getProxy().proxy ? Cryptpad.getStore().getProxy() : undefined;

@ -1,7 +1,6 @@
define([
'/bower_components/jquery/dist/jquery.min.js',
],function () {
var $ = window.jQuery;
'jquery'
],function ($) {
var Board = {};
var proxy;

@ -1,5 +1,6 @@
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/customize/messages.js',
'board.js',
'/bower_components/textpatcher/TextPatcher.js',
@ -8,10 +9,9 @@ define([
'/common/cryptpad-common.js',
'/common/visible.js',
'/common/notify.js',
'/bower_components/file-saver/FileSaver.min.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, Messages, Board, TextPatcher, Listmap, Crypto, Cryptpad, Visible, Notify) {
var $ = window.jQuery;
'/bower_components/file-saver/FileSaver.min.js'
], function ($, Config, Messages, Board, TextPatcher, Listmap, Crypto, Cryptpad, Visible, Notify) {
var saveAs = window.saveAs;
Cryptpad.styleAlerts();

@ -1,16 +1,14 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'json.sortify',
'ula.js',
'/bower_components/chainpad-json-validator/json-ot.js',
'/common/cryptpad-common.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, Realtime, Crypto, TextPatcher, Sortify, Formula, JsonOT, Cryptpad) {
var $ = window.jQuery;
'/common/cryptpad-common.js'
], function ($, Config, Realtime, Crypto, TextPatcher, Sortify, Formula, JsonOT, Cryptpad) {
var secret = Cryptpad.getSecrets();

@ -1,12 +1,11 @@
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'/common/cryptpad-common.js',
'/bower_components/jquery/dist/jquery.min.js'
], function (Config, Realtime, Crypto, TextPatcher, Cryptpad) {
var $ = window.jQuery;
'/common/cryptpad-common.js'
], function ($, Config, Realtime, Crypto, TextPatcher, Cryptpad) {
var secret = Cryptpad.getSecrets();

@ -1,11 +1,10 @@
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/bower_components/chainpad-crypto/crypto.js',
'/common/cryptpad-common.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, RtListMap, Crypto, Common) {
var $ = window.jQuery;
'/common/cryptpad-common.js'
], function ($, Config, RtListMap, Crypto, Common) {
var secret = Common.getSecrets();

@ -1,10 +1,8 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'jquery',
'/common/cryptpad-common.js',
'/common/pinpad.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Cryptpad, Pinpad) {
var $ = window.jQuery;
'/common/pinpad.js'
], function ($, Cryptpad, Pinpad) {
var APP = window.APP = {
Cryptpad: Cryptpad,
};

@ -1,8 +1,7 @@
define([
'/common/cryptget.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Crypt) {
var $ = window.jQuery;
'jquery',
'/common/cryptget.js'
], function ($, Crypt) {
var $target = $('#target');
var $dest = $('#dest');

@ -3,7 +3,7 @@
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="/common/render-sd.css" />
<link rel="stylesheet" href="render-sd.css" />
<script data-bootload="main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>
<style>
html, body {

@ -1,14 +1,13 @@
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/marked/marked.min.js',
'/bower_components/hyperjson/hyperjson.js',
'/common/cryptpad-common.js',
'/bower_components/jquery/dist/jquery.min.js',
'/bower_components/diff-dom/diffDOM.js',
], function (Config, Realtime, Crypto, Marked, Hyperjson, Cryptpad) {
var $ = window.jQuery;
], function ($, Config, Realtime, Crypto, Marked, Hyperjson, Cryptpad) {
var DiffDom = window.diffDOM;
var secret = Cryptpad.getSecrets();

@ -1,13 +1,12 @@
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'/common/cryptpad-common.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, Realtime, Crypto, TextPatcher, Cryptpad) {
'/common/cryptpad-common.js'
], function ($, Config, Realtime, Crypto, TextPatcher, Cryptpad) {
// TODO consider adding support for less.js
var $ = window.jQuery;
var $style = $('style').first(),
$edit = $('#edit');

@ -1,12 +1,11 @@
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/textpatcher/TextPatcher.amd.js',
'/common/cryptpad-common.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, Realtime, Crypto, TextPatcher, Cryptpad) {
var $ = window.jQuery;
'/common/cryptpad-common.js'
], function ($, Config, Realtime, Crypto, TextPatcher, Cryptpad) {
var secret = Cryptpad.getSecrets();

@ -1,9 +1,8 @@
define([
'jquery',
'/common/cryptget.js',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Crypt, Crypto) {
var $ = window.jQuery;
'/bower_components/chainpad-crypto/crypto.js'
], function ($, Crypt, Crypto) {
var Nacl = window.nacl;
var key = Nacl.randomBytes(32);
@ -49,14 +48,14 @@ define([
http://stackoverflow.com/questions/19959072/sending-binary-data-in-javascript-over-http
// Since we deal with Firefox and Chrome only
// Since we deal with Firefox and Chrome only
var bytesToSend = [253, 0, 128, 1];
var bytesArray = new Uint8Array(bytesToSend);
$.ajax({
url: '%your_service_url%',
type: 'POST',
contentType: 'application/octet-stream',
contentType: 'application/octet-stream',
data: bytesArray,
processData: false
});
@ -65,7 +64,7 @@ http://stackoverflow.com/questions/19959072/sending-binary-data-in-javascript-ov
};
var $file = $('input[type="file"]');
$file.on('change', function (e) {
$file.on('change', function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (e) {

@ -7,7 +7,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<script data-bootload="main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>
</head>

@ -1,9 +1,8 @@
define([
'jquery',
'/common/cryptpad-common.js',
'/common/login.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Cryptpad, Login) {
var $ = window.$;
'/common/login.js'
], function ($, Cryptpad, Login) {
var APP = window.APP = {
Cryptpad: Cryptpad,
@ -124,4 +123,3 @@ define([
});
});
});

@ -1,5 +1,5 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'jquery',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/hyperjson/hyperjson.js',
@ -15,12 +15,10 @@ define([
'/common/notify.js',
'/pad/links.js',
'/bower_components/file-saver/FileSaver.min.js',
'/bower_components/diff-dom/diffDOM.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Crypto, realtimeInput, Hyperjson,
'/bower_components/diff-dom/diffDOM.js'
], function ($, Crypto, realtimeInput, Hyperjson,
Toolbar, Cursor, JsonOT, TypingTest, JSONSortify, TextPatcher, Cryptpad, Cryptget,
Visible, Notify, Links) {
var $ = window.jQuery;
var saveAs = window.saveAs;
var Messages = Cryptpad.Messages;
@ -475,12 +473,12 @@ define([
}
};
var onRemote = realtimeOptions.onRemote = function (info) {
var onRemote = realtimeOptions.onRemote = function () {
if (initializing) { return; }
var oldShjson = stringifyDOM(inner);
var shjson = info.realtime.getUserDoc();
var shjson = module.realtime.getUserDoc();
// remember where the cursor is
cursor.update();
@ -679,7 +677,7 @@ define([
module.users = info.userList.users;
module.realtime = info.realtime;
var shjson = info.realtime.getUserDoc();
var shjson = module.realtime.getUserDoc();
var newPad = false;
if (shjson === '') { newPad = true; }
@ -810,6 +808,7 @@ define([
var second = function (Ckeditor) {
Cryptpad.ready(function (err, env) {
andThen(Ckeditor);
Cryptpad.reportAppUsage();
});
Cryptpad.onError(function (info) {
if (info && info.type === "store") {

@ -11,108 +11,8 @@
id="favicon" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="/customize/main.css" />
<link rel="stylesheet" href="./poll.css" />
<script data-bootload="main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
border: 0px;
}
.cryptpad-toolbar h2 {
font: normal normal normal 12px Arial, Helvetica, Tahoma, Verdana, Sans-Serif;
color: #000;
line-height: auto;
}
.cryptpad-toolbar {
display: inline-block;
}
.realtime {
display: block;
max-height: 100%;
max-width: 100%;
}
.realtime input[type="text"] {
height: 1em;
margin: 0px;
}
.text-cell input[type="text"] {
width: 400px;
}
input[type="text"][disabled], textarea[disabled] {
background-color: transparent;
font: white;
border: 0px;
}
table#table {
margin: 0px;
}
#tableContainer {
position: relative;
padding: 29px;
padding-right: 79px;
}
#tableContainer button {
height: 2rem;
display: none;
}
#publish {
display: none;
}
#publish, #admin {
margin-top: 15px;
margin-bottom: 15px;
}
#create-user {
position: absolute;
display: inline-block;
/*left: 0px;*/
top: 55px;
width: 50px;
overflow: hidden;
}
#create-option {
width: 50px;
}
#tableScroll {
overflow-y: hidden;
overflow-x: auto; margin-left: calc(30% - 50px + 29px); max-width: 70%; width: auto; display: inline-block;
}
#description {
padding: 15px;
margin: auto;
min-width: 80%;
width: 80%;
min-height: 5em;
font-size: 20px;
font-weight: bold;
}
#description[disabled] {
resize: none;
color: #000;
border: 1px solid #444;
}
#commit {
width: 100%;
}
#howItWorks {
width: 80%;
margin: auto;
}
div.upper {
width: 80%;
margin: auto;
}
</style>
</head>
<body>

@ -1,4 +1,5 @@
define([
'jquery',
'/bower_components/textpatcher/TextPatcher.js',
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/bower_components/chainpad-crypto/crypto.js',
@ -9,10 +10,8 @@ define([
'/common/toolbar.js',
'/common/visible.js',
'/common/notify.js',
'/bower_components/file-saver/FileSaver.min.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (TextPatcher, Listmap, Crypto, Cryptpad, Cryptget, Hyperjson, Renderer, Toolbar, Visible, Notify) {
var $ = window.jQuery;
'/bower_components/file-saver/FileSaver.min.js'
], function ($, TextPatcher, Listmap, Crypto, Cryptpad, Cryptget, Hyperjson, Renderer, Toolbar, Visible, Notify) {
var Messages = Cryptpad.Messages;
@ -25,6 +24,7 @@ define([
var secret = Cryptpad.getSecrets();
var readOnly = secret.keys && !secret.keys.editKeyStr;
// DEPRECATE_F
if (!secret.keys) {
secret.keys = secret.key;
}
@ -210,7 +210,7 @@ define([
};
/* Any time the realtime object changes, call this function */
var change = function (o, n, path, throttle) {
var change = function (o, n, path, throttle, cb) {
if (path && !Cryptpad.isArray(path)) {
return;
}
@ -259,8 +259,14 @@ define([
var displayedObj2 = mergeUncommitted(APP.proxy, APP.uncommitted);
var f = getFocus();
Render.updateTable(table, displayedObj2, conf);
APP.proxy.table.rowsOrder.forEach(function (rowId) {
$('input[data-rt-id="' + rowId +'"]').val(APP.proxy.table.rows[rowId] || '');
});
updateDisplayedTable();
setFocus(f);
if (typeof(cb) === "function") {
cb();
}
};
if (throttle) {
@ -280,7 +286,7 @@ define([
};
/* Called whenever an event is fired on an input element */
var handleInput = function (input) {
var handleInput = function (input, isKeyup) {
var type = input.type.toLowerCase();
var id = getRealtimeId(input);
@ -331,7 +337,9 @@ define([
});
} else if (isEdit) {
unlockRow(id, function () {
change();
change(null, null, null, null, function() {
$('input[data-rt-id="' + id + '"]').focus();
});
});
}
} else if (type === 'col') {
@ -344,7 +352,9 @@ define([
});
} else if (isEdit) {
unlockColumn(id, function () {
change();
change(null, null, null, null, function() {
$('input[data-rt-id="' + id + '"]').focus();
});
});
}
} else if (type === 'cell') {
@ -354,8 +364,8 @@ define([
}
};
var hideInputs = function (e) {
if ($(e.target).is('[type="text"]')) {
var hideInputs = function (e, isKeyup) {
if (!isKeyup && $(e.target).is('[type="text"]')) {
return;
}
$('.lock[data-rt-id!="' + APP.userid + '"]').html(lockHTML);
@ -388,6 +398,10 @@ define([
switch (nodeName) {
case 'INPUT':
if (isKeyup && (e.keyCode === 13 || e.keyCode === 27)) {
hideInputs(e, isKeyup);
return;
}
handleInput(target);
break;
case 'SPAN':
@ -546,20 +560,18 @@ define([
var $table = APP.$table = $(Render.asHTML(displayedObj, null, colsOrder, readOnly));
var $createRow = APP.$createRow = $('#create-option').click(function () {
//console.error("BUTTON CLICKED! LOL");
Render.createRow(proxy, function () {
change();
var order = APP.proxy.table.rowsOrder;
var last = order[order.length - 1];
var $newest = $('[data-rt-id="' + last + '"]');
$newest.val('');
window.setTimeout(change);
Render.createRow(proxy, function (empty, id) {
change(null, null, null, null, function() {
$('.edit[data-rt-id="' + id + '"]').click();
});
});
});
var $createCol = APP.$createCol = $('#create-user').click(function () {
Render.createColumn(proxy, function () {
change();
Render.createColumn(proxy, function (empty, id) {
change(null, null, null, null, function() {
$('.edit[data-rt-id="' + id + '"]').click();
});
});
});
@ -768,19 +780,11 @@ define([
}
Cryptpad.onDisplayNameChanged(setName);
Cryptpad.getPadTitle(function (err, title) {
if (err) {
error(err);
debug("Couldn't get pad title");
return;
}
updateTitle(title || defaultName);
});
};
// don't initialize until the store is ready.
Cryptpad.ready(function () {
Cryptpad.reportAppUsage();
var config = {
websocketURL: Cryptpad.getWebsocketURL(),
channel: secret.channel,
@ -838,4 +842,3 @@ define([
});
});

@ -0,0 +1,357 @@
html,
body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
border: 0px;
}
.cryptpad-toolbar h2 {
font: normal normal normal 12px Arial, Helvetica, Tahoma, Verdana, Sans-Serif;
color: #000;
line-height: auto;
}
.cryptpad-toolbar {
display: inline-block;
}
.realtime {
display: block;
max-height: 100%;
max-width: 100%;
}
.realtime input[type="text"] {
height: 1em;
margin: 0px;
}
.text-cell input[type="text"] {
width: 400px;
}
input[type="text"][disabled],
textarea[disabled] {
background-color: transparent;
font: white;
border: 0px;
}
table#table {
margin: 0px;
}
#tableContainer {
position: relative;
padding: 29px;
padding-right: 79px;
}
#tableContainer button {
height: 2rem;
display: none;
}
#publish {
display: none;
}
#publish,
#admin {
margin-top: 15px;
margin-bottom: 15px;
}
#create-user {
position: absolute;
display: inline-block;
/*left: 0px;*/
top: 55px;
width: 50px;
overflow: hidden;
}
#create-option {
width: 50px;
}
#tableScroll {
overflow-y: hidden;
overflow-x: auto;
margin-left: calc(30% - 50px + 29px);
max-width: 70%;
width: auto;
display: inline-block;
}
#description {
padding: 15px;
margin: auto;
min-width: 80%;
width: 80%;
min-height: 5em;
font-size: 20px;
font-weight: bold;
}
#description[disabled] {
resize: none;
color: #000;
border: 1px solid #444;
}
#commit {
width: 100%;
}
#howItWorks {
width: 80%;
margin: auto;
}
div.upper {
width: 80%;
margin: auto;
}
table {
border-collapse: collapse;
border-spacing: 0;
margin: 20px;
}
tbody {
border: 1px solid #555;
}
tbody tr {
text-align: center;
}
tbody tr:first-of-type th {
font-size: 20px;
border-top: 0px;
font-weight: bold;
padding: 10px;
text-decoration: underline;
}
tbody tr:first-of-type th.table-refresh {
color: #46E981;
text-decoration: none;
cursor: pointer;
}
tbody tr:nth-child(odd) {
background-color: #ffffff;
}
tbody tr th:first-of-type {
border-left: 0px;
}
tbody tr th {
box-sizing: border-box;
border: 1px solid #555;
}
tbody tr th,
tbody tr td {
color: #555;
}
tbody tr th.remove,
tbody tr td.remove {
cursor: pointer;
}
tbody tr th:last-child {
border-right: 0px;
}
tbody td {
border-right: 1px solid #555;
padding: 12px;
padding-top: 0px;
padding-bottom: 0px;
}
tbody td:last-child {
border-right: none;
}
form.realtime,
div.realtime {
padding: 0px;
margin: 0px;
}
form.realtime > textarea,
div.realtime > textarea {
width: 50%;
height: 15vh;
}
form.realtime table,
div.realtime table {
border-collapse: collapse;
width: calc(100% - 1px);
}
form.realtime table tr td:first-child,
div.realtime table tr td:first-child {
position: absolute;
left: 29px;
top: auto;
width: calc(30% - 50px);
}
form.realtime table tr td,
div.realtime table tr td {
padding: 0px;
margin: 0px;
}
form.realtime table tr td div.text-cell,
div.realtime table tr td div.text-cell {
padding: 0px;
margin: 0px;
height: 100%;
}
form.realtime table tr td div.text-cell input,
div.realtime table tr td div.text-cell input {
width: 80%;
width: 90%;
height: 100%;
border: 0px;
}
form.realtime table tr td div.text-cell input[disabled],
div.realtime table tr td div.text-cell input[disabled] {
background-color: transparent;
color: #000;
font-weight: bold;
}
form.realtime table tr td.checkbox-cell,
div.realtime table tr td.checkbox-cell {
margin: 0px;
padding: 0px;
height: 100%;
min-width: 150px;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain,
div.realtime table tr td.checkbox-cell div.checkbox-contain {
display: inline-block;
height: 100%;
width: 100%;
position: relative;
}
form.realtime table tr td.checkbox-cell div.checkbox-contain label,
div.realtime table tr td.checkbox-cell div.checkbox-contain label {
background-color: transparent;
display: block;
position: absolute;
top: 0px;
left: 0px;
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) {
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 {
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 {
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 {
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 {
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 {
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="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 input[type="text"],
div.realtime table input[type="text"] {
height: auto;
border: 1px solid #fff;
width: 80%;
}
form.realtime table thead td,
div.realtime table thead td {
padding: 0px 5px;
background: #aaa;
border-radius: 20px 20px 0 0;
text-align: center;
}
form.realtime table thead td input[type="text"],
div.realtime table thead td input[type="text"] {
width: 100%;
box-sizing: border-box;
}
form.realtime table thead td input[type="text"][disabled],
div.realtime table thead td input[type="text"][disabled] {
color: #000;
padding: 1px 5px;
border: none;
}
form.realtime table tbody .text-cell,
div.realtime table tbody .text-cell {
background: #aaa;
}
form.realtime table tbody .text-cell input[type="text"],
div.realtime table tbody .text-cell input[type="text"] {
width: calc(100% - 50px);
}
form.realtime table tbody .text-cell .edit,
div.realtime table tbody .text-cell .edit {
float: right;
margin: 0 10px 0 0;
}
form.realtime table tbody .text-cell .remove,
div.realtime table tbody .text-cell .remove {
float: left;
margin: 0 0 0 10px;
}
form.realtime table tbody td label,
div.realtime table tbody td label {
border: 0.5px solid #555;
}
form.realtime table .edit,
div.realtime table .edit {
color: #000;
cursor: pointer;
float: left;
margin-left: 10px;
}
form.realtime table .remove,
div.realtime table .remove {
float: right;
margin-right: 10px;
}
form.realtime table thead tr th input[type="text"][disabled],
div.realtime table thead tr th input[type="text"][disabled] {
background-color: transparent;
color: #555;
font-weight: bold;
}
form.realtime table thead tr th .remove,
div.realtime table thead tr th .remove {
cursor: pointer;
font-size: 20px;
}
form.realtime table tfoot tr,
div.realtime table tfoot tr {
border: none;
}
form.realtime table tfoot tr td,
div.realtime table tfoot tr td {
border: none;
text-align: center;
}
form.realtime table tfoot tr td .save,
div.realtime table tfoot tr td .save {
padding: 15px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
form.realtime #adduser,
div.realtime #adduser,
form.realtime #addoption,
div.realtime #addoption {
color: #46E981;
border: 1px solid #46E981;
padding: 15px;
cursor: pointer;
}
form.realtime #adduser,
div.realtime #adduser {
border-top-left-radius: 5px;
}
form.realtime #addoption,
div.realtime #addoption {
border-bottom-left-radius: 5px;
}

@ -0,0 +1,387 @@
@import "../../customize.dist/src/less/variables.less";
@import "../../customize.dist/src/less/mixins.less";
@poll-th-bg: #aaa;
@poll-td-bg: #aaa;
@poll-border-color: #555;
@poll-cover-color: #000;
@poll-fg: #000;
html, body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
border: 0px;
}
.cryptpad-toolbar h2 {
font: normal normal normal 12px Arial, Helvetica, Tahoma, Verdana, Sans-Serif;
color: #000;
line-height: auto;
}
.cryptpad-toolbar {
display: inline-block;
}
.realtime {
display: block;
max-height: 100%;
max-width: 100%;
}
.realtime input[type="text"] {
height: 1em;
margin: 0px;
}
.text-cell input[type="text"] {
width: 400px;
}
input[type="text"][disabled], textarea[disabled] {
background-color: transparent;
font: white;
border: 0px;
}
table#table {
margin: 0px;
}
#tableContainer {
position: relative;
padding: 29px;
padding-right: 79px;
}
#tableContainer button {
height: 2rem;
display: none;
}
#publish {
display: none;
}
#publish, #admin {
margin-top: 15px;
margin-bottom: 15px;
}
#create-user {
position: absolute;
display: inline-block;
/*left: 0px;*/
top: 55px;
width: 50px;
overflow: hidden;
}
#create-option {
width: 50px;
}
#tableScroll {
overflow-y: hidden;
overflow-x: auto;
margin-left: calc(~"30% - 50px + 29px");
max-width: 70%;
width: auto;
display: inline-block;
}
#description {
padding: 15px;
margin: auto;
min-width: 80%;
width: 80%;
min-height: 5em;
font-size: 20px;
font-weight: bold;
}
#description[disabled] {
resize: none;
color: #000;
border: 1px solid #444;
}
#commit {
width: 100%;
}
#howItWorks {
width: 80%;
margin: auto;
}
div.upper {
width: 80%;
margin: auto;
}
// from cryptpad.less
table {
border-collapse: collapse;
border-spacing: 0;
margin: 20px;
}
tbody {
border: 1px solid @poll-border-color;
tr {
text-align: center;
&:first-of-type th{
font-size: 20px;
border-top: 0px;
font-weight: bold;
padding: 10px;
text-decoration: underline;
&.table-refresh {
color: @cp-green;
text-decoration: none;
cursor: pointer;
}
}
&:nth-child(odd) {
background-color: @light-base;
}
th:first-of-type {
border-left: 0px;
}
th {
box-sizing: border-box;
border: 1px solid @poll-border-color;
}
th, td {
color: @fore;
&.remove {
cursor: pointer;
}
}
th:last-child {
border-right: 0px;
}
}
td {
border-right: 1px solid @poll-border-color;
padding: 12px;
padding-top: 0px;
padding-bottom: 0px;
&:last-child {
border-right: none;
}
}
}
form.realtime, div.realtime {
> input {
&[type="text"] {
}
}
> textarea {
width: 50%;
height: 15vh;
}
padding: 0px;
margin: 0px;
table {
border-collapse: collapse;
width: ~"calc(100% - 1px)";
tr {
td:first-child {
position:absolute;
left: 29px;
top: auto;
width: ~"calc(30% - 50px)";
}
td {
padding: 0px;
margin: 0px;
div.text-cell {
padding: 0px;
margin: 0px;
height: 100%;
input {
width: 80%;
width: 90%;
height: 100%;
border: 0px;
&[disabled] {
background-color: transparent;
color: @poll-fg;
font-weight: bold;
}
}
}
&.checkbox-cell {
margin: 0px;
padding: 0px;
height: 100%;
min-width: 150px;
div.checkbox-contain {
display: inline-block;
height: 100%;
width: 100%;
position: relative;
label {
background-color: transparent;
display: block;
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
input {
&[type="checkbox"] {
&:not(.editable) {
display: none;
~ .cover {
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;
}
}
}
}
}
}
}
}
}
input {
&[type="text"] {
height: auto;
border: 1px solid @base;
width: 80%;
}
}
thead {
td {
padding: 0px 5px;
background: @poll-th-bg;
border-radius: 20px 20px 0 0;
text-align: center;
input {
&[type="text"] {
width: 100%;
box-sizing: border-box;
&[disabled] {
color: @poll-fg;
padding: 1px 5px;
border: none;
}
}
}
}
}
tbody {
.text-cell {
background: @poll-td-bg;
//border-radius: 20px 0 0 20px;
input[type="text"] {
width: ~"calc(100% - 50px)";
}
.edit {
float:right;
margin: 0 10px 0 0;
}
.remove {
float: left;
margin: 0 0 0 10px;
}
}
td {
label {
border: .5px solid @poll-border-color;
}
}
}
.edit {
color: @poll-cover-color;
cursor: pointer;
float: left;
margin-left: 10px;
}
.remove {
float: right;
margin-right: 10px;
}
thead {
tr {
th {
input[type="text"][disabled] {
background-color: transparent;
color: @fore;
font-weight: bold;
}
.remove {
cursor: pointer;
font-size: 20px;
}
}
}
}
tbody {
tr {
td {
}
}
}
tfoot {
tr {
border: none;
td {
border: none;
text-align: center;
.save {
padding: 15px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
}
}
}
}
#adduser,
#addoption {
color: @cp-green;
border: 1px solid @cp-green;
padding: 15px;
cursor: pointer;
}
#adduser { .top-left; }
#addoption { .bottom-left; }
}

@ -1,11 +1,10 @@
define([
'jquery',
'/common/login.js',
'/common/cryptpad-common.js',
'/common/cryptget.js',
'/common/credential.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Login, Cryptpad, Crypt) {
var $ = window.jQuery;
'/common/credential.js'
], function ($, Login, Cryptpad, Crypt) {
var APP = window.APP = {
Login: Login,
@ -68,6 +67,12 @@ define([
proxy.edPublic = result.edPublic;
proxy.edPrivate = result.edPrivate;
// feedback API won't work because proxy wasn't loaded
$.ajax({
type: 'HEAD',
url: '/common/feedback.html?REGISTRATION=' + (+new Date()),
});
Cryptpad.whenRealtimeSyncs(result.realtime, function () {
Cryptpad.login(result.userHash, result.userName, function () {
if (sessionStorage.redirectTo) {

@ -8,7 +8,6 @@
<link rel="stylesheet" type="text/css" href="/customize/main.css" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="icon" type="image/png" href="/customize/main-favicon.png" id="favicon"/>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="main.css" />
<script data-bootload="main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>

@ -1,11 +1,10 @@
define([
'jquery',
'/common/cryptpad-common.js',
'/common/cryptget.js',
'/common/mergeDrive.js',
'/bower_components/file-saver/FileSaver.min.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Cryptpad, Crypt, Merge) {
var $ = window.jQuery;
'/bower_components/file-saver/FileSaver.min.js'
], function ($, Cryptpad, Crypt, Merge) {
var saveAs = window.saveAs;
var USERNAME_KEY = 'cryptpad.username';
@ -227,6 +226,40 @@ define([
return $div;
};
var bytesToMegabytes = function (bytes) {
return Math.floor((bytes / (1024 * 1024) * 100)) / 100;
};
var createUsageButton = function (obj) {
var proxy = obj.proxy;
var $div = $('<div>', { 'class': 'pinned-usage' })
.text(Messages.settings_usageTitle)
.append('<br>');
$('<button>', {
'class': 'btn btn-primary', // fa fa-hdd-o ?
})
.text(Messages.settings_usage)
.click(function () {
if (!(proxy.edPublic && proxy.edPrivate)) {
// suggest that they login/register
Cryptpad.alert(Messages.settings_pinningNotAvailable);
return;
}
Cryptpad.getPinnedUsage(function (e, bytes) {
if (e) {
Cryptpad.alert(Messages.settings_pinningError);
return;
}
Cryptpad.alert(Messages._getKey('settings_usageAmount', [bytesToMegabytes(bytes)]));
});
})
.appendTo($div);
return $div;
};
var createImportLocalPads = function (obj) {
if (!Cryptpad.isLoggedIn()) { return; }
var $div = $('<div>', {'class': 'importLocalPads'});
@ -271,6 +304,7 @@ define([
APP.$container.append(createBackupDrive(obj));
APP.$container.append(createImportLocalPads(obj));
APP.$container.append(createResetDrive(obj));
APP.$container.append(createUsageButton(obj));
APP.$container.append(createUserFeedbackToggle(obj));
obj.proxy.on('change', [], refresh);
obj.proxy.on('remove', [], refresh);
@ -308,6 +342,7 @@ define([
? Cryptpad.getStore().getProxy() : undefined;
andThen(storeObj);
Cryptpad.reportAppUsage();
});
});
@ -322,4 +357,3 @@ define([
}
});
});

@ -1,5 +1,5 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'jquery',
'/bower_components/chainpad-crypto/crypto.js',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/textpatcher/TextPatcher.js',
@ -13,10 +13,8 @@ define([
'/common/visible.js',
'/common/notify.js',
'/slide/slide.js',
'/bower_components/file-saver/FileSaver.min.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Crypto, Realtime, TextPatcher, Toolbar, JSONSortify, JsonOT, Cryptpad, Cryptget, Modes, Themes, Visible, Notify, Slide) {
var $ = window.jQuery;
'/bower_components/file-saver/FileSaver.min.js'
], function ($, Crypto, Realtime, TextPatcher, Toolbar, JSONSortify, JsonOT, Cryptpad, Cryptget, Modes, Themes, Visible, Notify, Slide) {
var saveAs = window.saveAs;
var Messages = Cryptpad.Messages;
@ -83,7 +81,7 @@ define([
styleActiveLine : true,
search: true,
highlightSelectionMatches: {showToken: /\w+/},
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
extraKeys: {"Shift-Ctrl-R": undefined},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
mode: "javascript",
@ -840,7 +838,7 @@ define([
return cursor;
};
var onRemote = config.onRemote = function (info) {
var onRemote = config.onRemote = function () {
if (initializing) { return; }
var scroll = editor.getScrollInfo();
@ -929,6 +927,7 @@ define([
var second = function (CM) {
Cryptpad.ready(function (err, env) {
andThen(CM);
Cryptpad.reportAppUsage();
});
Cryptpad.onError(function (info) {
if (info && info.type === "store") {

@ -1,9 +1,8 @@
define([
'jquery',
'/bower_components/marked/marked.min.js',
'/bower_components/diff-dom/diffDOM.js',
'/bower_components/jquery/dist/jquery.min.js',
],function (Marked) {
var $ = window.jQuery;
'/bower_components/diff-dom/diffDOM.js'
],function ($, Marked) {
var DiffDOM = window.diffDOM;
var renderer = new Marked.Renderer();

@ -1,9 +1,6 @@
require.config({ paths: {
'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify'
}});
define([
'/api/config?cb=' + Math.random().toString(16).substring(2),
'jquery',
'/api/config',
'/bower_components/chainpad-netflux/chainpad-netflux.js',
'/bower_components/chainpad-crypto/crypto.js',
'/common/toolbar.js',
@ -17,14 +14,12 @@ define([
'/common/notify.js',
'/customize/application_config.js',
'/bower_components/secure-fabric.js/dist/fabric.min.js',
'/bower_components/jquery/dist/jquery.min.js',
'/bower_components/file-saver/FileSaver.min.js',
], function (Config, Realtime, Crypto, Toolbar, TextPatcher, JSONSortify, JsonOT, Cryptpad, Cryptget, Colors, Visible, Notify, AppConfig) {
], function ($, Config, Realtime, Crypto, Toolbar, TextPatcher, JSONSortify, JsonOT, Cryptpad, Cryptget, Colors, Visible, Notify, AppConfig) {
var saveAs = window.saveAs;
var Messages = Cryptpad.Messages;
var module = window.APP = { };
var $ = module.$ = window.jQuery;
var module = window.APP = { $:$ };
var Fabric = module.Fabric = window.fabric;
$(function () {
@ -618,6 +613,7 @@ window.canvas = canvas;
Cryptpad.ready(function (err, env) {
andThen();
Cryptpad.reportAppUsage();
});
Cryptpad.onError(function (info) {
if (info) {

Loading…
Cancel
Save