mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-05-06 07:07:12 -04:00
Merge branch 'master' into serverModule
This commit is contained in:
commit
16735fe4fa
35 changed files with 935 additions and 904 deletions
|
@ -58,7 +58,7 @@ Here is the **[FAQ](https://github.com/Pita/etherpad-lite/wiki/FAQ)**
|
|||
|
||||
<ol>
|
||||
<li>Install the dependencies. We need gzip, git, curl, libssl develop libraries, python and gcc. <br><i>For Debian/Ubuntu</i> <code>apt-get install gzip git-core curl python libssl-dev build-essential</code><br>
|
||||
<i>For Fedora/CentOS</i> <code>yum install gzip git-core curl python openssl-dev && yum groupinstall "Development Tools"</code>
|
||||
<i>For Fedora/CentOS</i> <code>yum install gzip git-core curl python openssl-devel && yum groupinstall "Development Tools"</code>
|
||||
</li><br>
|
||||
<li>Install node.js
|
||||
<ol type="a">
|
||||
|
|
|
@ -4,6 +4,7 @@ var ueberDB = require("ueberDB");
|
|||
var mysql = require("mysql");
|
||||
var async = require("async");
|
||||
var Changeset = require("../node/utils/Changeset");
|
||||
var randomString = require("../node/utils/randomstring");
|
||||
var AttributePoolFactory = require("../node/utils/AttributePoolFactory");
|
||||
|
||||
var settingsFile = process.argv[2];
|
||||
|
@ -450,18 +451,3 @@ function parsePage(array, pageStart, offsets, data, json)
|
|||
start+=unitLength;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random String with the given length. Is needed to generate the Author Ids
|
||||
*/
|
||||
function randomString(len)
|
||||
{
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,13 @@ if [ ! $(echo $NPM_VERSION | cut -d "." -f 1) = "1" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
#check node version
|
||||
NODE_VERSION=$(node --version)
|
||||
if [ ! $(echo $NODE_VERSION | cut -d "." -f 1-2) = "v0.6" ]; then
|
||||
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.6.x" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#Does a settings.json exist? if no copy the template
|
||||
if [ ! -f "settings.json" ]; then
|
||||
echo "Copy the settings template to settings.json..."
|
||||
|
|
|
@ -22,6 +22,8 @@ var ERR = require("async-stacktrace");
|
|||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
|
||||
var randomString = require("../utils/randomstring");
|
||||
|
||||
/**
|
||||
* Checks if the author exists
|
||||
*/
|
||||
|
@ -177,18 +179,3 @@ exports.setAuthorName = function (author, name, callback)
|
|||
{
|
||||
db.setSub("globalAuthor:" + author, ["name"], name, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random String with the given length. Is needed to generate the Author Ids
|
||||
*/
|
||||
function randomString(len)
|
||||
{
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
var randomString = require("../utils/randomstring");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var padManager = require("./PadManager");
|
||||
|
@ -255,18 +256,3 @@ exports.listPads = function(groupID, callback)
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random String with the given length. Is needed to generate the Author Ids
|
||||
*/
|
||||
function randomString(len)
|
||||
{
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ var ERR = require("async-stacktrace");
|
|||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
|
||||
var randomString = require("../utils/randomstring");
|
||||
|
||||
/**
|
||||
* returns a read only id for a pad
|
||||
* @param {String} padId the id of the pad
|
||||
|
@ -70,18 +72,3 @@ exports.getPadId = function(readOnlyId, callback)
|
|||
{
|
||||
db.get("readonly2pad:" + readOnlyId, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random String with the given length. Is needed to generate the read only ids
|
||||
*/
|
||||
function randomString(len)
|
||||
{
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ var padManager = require("./PadManager");
|
|||
var sessionManager = require("./SessionManager");
|
||||
var settings = require("../utils/Settings")
|
||||
|
||||
var randomString = require("../utils/randomstring");
|
||||
|
||||
/**
|
||||
* This function controlls the access to a pad, it checks if the user can access a pad.
|
||||
* @param padID the pad the user wants to access
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
var ERR = require("async-stacktrace");
|
||||
var customError = require("../utils/customError");
|
||||
var randomString = require("../utils/randomstring");
|
||||
var db = require("./DB").db;
|
||||
var async = require("async");
|
||||
var groupMangager = require("./GroupManager");
|
||||
|
@ -358,21 +359,6 @@ function listSessionsWithDBKey (dbkey, callback)
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random String with the given length. Is needed to generate the SessionIDs
|
||||
*/
|
||||
function randomString(len)
|
||||
{
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
}
|
||||
|
||||
//checks if a number is an int
|
||||
function is_int(value)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ var ERR = require("async-stacktrace");
|
|||
var fs = require("fs");
|
||||
var api = require("../db/API");
|
||||
var padManager = require("../db/PadManager");
|
||||
var randomString = require("../utils/randomstring");
|
||||
|
||||
//ensure we have an apikey
|
||||
var apikey = null;
|
||||
|
@ -157,18 +158,3 @@ function callAPI(functionName, fields, req, res)
|
|||
//call the api function
|
||||
api[functionName](functionParams[0],functionParams[1],functionParams[2],functionParams[3],functionParams[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random String with the given length. Is needed to generate the Author Ids
|
||||
*/
|
||||
function randomString(len)
|
||||
{
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,33 @@ function init(additionalSetup){
|
|||
next();
|
||||
});
|
||||
|
||||
|
||||
//redirects browser to the pad's sanitized url if needed. otherwise, renders the html
|
||||
app.param('pad', function (req, res, next, padId) {
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(padId) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
}
|
||||
else
|
||||
{
|
||||
padManager.sanitizePadId(padId, function(sanitizedPadId) {
|
||||
//the pad id was sanitized, so we redirect to the sanitized version
|
||||
if(sanitizedPadId != padId)
|
||||
{
|
||||
var real_path = req.path.replace(/^\/p\/[^\/]+/, '/p/' + sanitizedPadId);
|
||||
res.header('Location', real_path);
|
||||
res.send('You should be redirected to <a href="' + real_path + '">' + real_path + '</a>', 302);
|
||||
}
|
||||
//the pad id was fine, so just render it
|
||||
else
|
||||
{
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//load modules that needs a initalized db
|
||||
readOnlyManager = require("./db/ReadOnlyManager");
|
||||
exporthtml = require("./utils/ExportHtml");
|
||||
|
@ -238,54 +265,23 @@ function init(additionalSetup){
|
|||
});
|
||||
});
|
||||
|
||||
//redirects browser to the pad's sanitized url if needed. otherwise, renders the html
|
||||
function goToPad(req, res, render) {
|
||||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(req.params.pad) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
}
|
||||
else
|
||||
{
|
||||
padManager.sanitizePadId(req.params.pad, function(padId) {
|
||||
//the pad id was sanitized, so we redirect to the sanitized version
|
||||
if(padId != req.params.pad)
|
||||
{
|
||||
var real_path = req.path.replace(/^\/p\/[^\/]+/, '/p/' + padId);
|
||||
res.header('Location', real_path);
|
||||
res.send('You should be redirected to <a href="' + real_path + '">' + real_path + '</a>', 302);
|
||||
}
|
||||
//the pad id was fine, so just render it
|
||||
else
|
||||
{
|
||||
render();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//serve pad.html under /p
|
||||
app.get('/p/:pad', function(req, res, next)
|
||||
{
|
||||
goToPad(req, res, function() {
|
||||
var filePath = path.normalize(__dirname + "/../static/pad.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
});
|
||||
|
||||
//serve timeslider.html under /p/$padname/timeslider
|
||||
app.get('/p/:pad/timeslider', function(req, res, next)
|
||||
{
|
||||
goToPad(req, res, function() {
|
||||
var filePath = path.normalize(__dirname + "/../static/timeslider.html");
|
||||
res.sendfile(filePath, { maxAge: exports.maxAge });
|
||||
});
|
||||
});
|
||||
|
||||
//serve timeslider.html under /p/$padname/timeslider
|
||||
app.get('/p/:pad/:rev?/export/:type', function(req, res, next)
|
||||
{
|
||||
goToPad(req, res, function() {
|
||||
var types = ["pdf", "doc", "txt", "html", "odt", "dokuwiki"];
|
||||
//send a 404 if we don't support this filetype
|
||||
if(types.indexOf(req.params.type) == -1)
|
||||
|
@ -309,12 +305,10 @@ function init(additionalSetup){
|
|||
exportHandler.doExport(req, res, req.params.pad, req.params.type);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
//handle import requests
|
||||
app.post('/p/:pad/import', function(req, res, next)
|
||||
{
|
||||
goToPad(req, res, function() {
|
||||
//if abiword is disabled, skip handling this request
|
||||
if(settings.abiword == null)
|
||||
{
|
||||
|
@ -327,7 +321,6 @@ function init(additionalSetup){
|
|||
importHandler.doImport(req, res, req.params.pad);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var apiLogger = log4js.getLogger("API");
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ var jsp = require("uglify-js").parser;
|
|||
var pro = require("uglify-js").uglify;
|
||||
var path = require('path');
|
||||
var Buffer = require('buffer').Buffer;
|
||||
var gzip = require('gzip');
|
||||
var zlib = require('zlib');
|
||||
var RequireKernel = require('require-kernel');
|
||||
var server = require('../server');
|
||||
var os = require('os');
|
||||
|
@ -233,10 +233,7 @@ function _handle(req, res, jsFilename, jsFiles) {
|
|||
//write the results compressed in a file
|
||||
function(callback)
|
||||
{
|
||||
//spawn a gzip process if we're on a unix system
|
||||
if(os.type().indexOf("Windows") == -1)
|
||||
{
|
||||
gzip(result, 9, function(err, compressedResult){
|
||||
zlib.gzip(result, function(err, compressedResult){
|
||||
//weird gzip bug that returns 0 instead of null if everything is ok
|
||||
err = err === 0 ? null : err;
|
||||
|
||||
|
@ -245,12 +242,6 @@ function _handle(req, res, jsFilename, jsFiles) {
|
|||
fs.writeFile(CACHE_DIR + "minified_" + jsFilename + ".gz", compressedResult, callback);
|
||||
});
|
||||
}
|
||||
//skip this step on windows
|
||||
else
|
||||
{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
],callback);
|
||||
}
|
||||
], function(err)
|
||||
|
@ -315,11 +306,6 @@ function tarCode(filesInOrder, files, write) {
|
|||
write("\n\n\n/*** File: static/js/" + filename + " ***/\n\n\n");
|
||||
write(isolateJS(files[filename], filename));
|
||||
}
|
||||
|
||||
for(var i = 0, ii = filesInOrder.length; i < filesInOrder.length; i++) {
|
||||
var filename = filesInOrder[i];
|
||||
write('require(' + JSON.stringify('/' + filename.replace(/^\/+/, '')) + ');\n');
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap the following code in a self executing function and assign exports to
|
||||
|
|
16
node/utils/randomstring.js
Normal file
16
node/utils/randomstring.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Generates a random String with the given length. Is needed to generate the Author, Group, readonly, session Ids
|
||||
*/
|
||||
var randomString = function randomString(len)
|
||||
{
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum, rnum + 1);
|
||||
}
|
||||
return randomstring;
|
||||
};
|
||||
|
||||
module.exports = randomString;
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"pad.js": [
|
||||
"jquery.js"
|
||||
, "pad.js"
|
||||
, "ace2_common.js"
|
||||
, "pad_utils.js"
|
||||
, "plugins.js"
|
||||
, "undo-xpopup.js"
|
||||
|
@ -16,7 +18,6 @@
|
|||
, "pad_impexp.js"
|
||||
, "pad_savedrevs.js"
|
||||
, "pad_connectionstatus.js"
|
||||
, "pad2.js"
|
||||
, "jquery-ui.js"
|
||||
, "chat.js"
|
||||
, "excanvas.js"
|
||||
|
@ -29,6 +30,7 @@
|
|||
, "json2.js"
|
||||
, "colorutils.js"
|
||||
, "draggable.js"
|
||||
, "ace2_common.js"
|
||||
, "pad_utils.js"
|
||||
, "pad_cookie.js"
|
||||
, "pad_editor.js"
|
||||
|
@ -44,5 +46,6 @@
|
|||
, "broadcast.js"
|
||||
, "broadcast_slider.js"
|
||||
, "broadcast_revisions.js"
|
||||
, "timeslider.js"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -18,14 +18,16 @@
|
|||
"express" : "2.5.0",
|
||||
"clean-css" : "0.2.4",
|
||||
"uglify-js" : "1.1.1",
|
||||
"gzip" : "0.1.0",
|
||||
"formidable" : "1.0.7",
|
||||
"log4js" : "0.3.9",
|
||||
"log4js" : "0.4.1",
|
||||
"jsdom-nocontextifiy" : "0.2.10",
|
||||
"async-stacktrace" : "0.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jshint" : "*"
|
||||
},
|
||||
"engines" : { "node" : ">=0.6.0",
|
||||
"npm" : ">=1.0"
|
||||
},
|
||||
"version" : "1.0.0"
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
*,html,body,p{ margin: 0; padding: 0; }
|
||||
.clear { clear: both; }
|
||||
html { font-size: 62.5%; }
|
||||
html { font-size: 62.5%; width: 100%; }
|
||||
body, textarea { font-family: Helvetica, Arial, sans-serif; }
|
||||
iframe {position:absolute;}
|
||||
|
||||
#users
|
||||
{
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
z-index:500;
|
||||
background-color: #000;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
width: 160px;
|
||||
|
@ -560,28 +560,6 @@ table#otheruserstable { display: none; }
|
|||
display: none; z-index: 55; }
|
||||
#revision-notifier .label { color: #777; font-weight: bold; }
|
||||
|
||||
/* We don't ever actually hide the wrapper, even when the panel is
|
||||
cloased, so that its contents can always be manipulated accurately. */
|
||||
|
||||
|
||||
#padoptions { position: absolute; top: 0; left: 0; font-size: 1.2em;
|
||||
color: #444; height: 100%; width: 100%; line-height: 15px; }
|
||||
#options-viewhead { font-weight: bold; position: absolute; top: 10px; left: 15px;
|
||||
width: auto; height: auto; }
|
||||
#padoptions label { display: block; }
|
||||
#padoptions input { padding: 0; margin: 0; }
|
||||
#options-colorscheck { position: absolute; left: 15px; top: 34px; width: 15px; height: 15px; }
|
||||
#options-colorslabel { position: absolute; left: 35px; top: 34px; }
|
||||
#options-linenoscheck { position: absolute; left: 15px; top: 57px; width: 15px; height: 15px; }
|
||||
#options-linenoslabel { position: absolute; left: 35px; top: 57px; }
|
||||
#options-fontlabel { position: absolute; left: 15px; top: 82px; }
|
||||
#viewfontmenu { position: absolute; top: 80px; left: 90px; width: 110px; }
|
||||
#options-viewexplain { position: absolute; left: 215px; top: 15px; width: 100px; height: 70px; font-size: .7em;
|
||||
padding-left: 10px; padding-top: 10px; border-left: 1px solid #ccc;
|
||||
line-height: 20px; font-weight: bold; color: #999; }
|
||||
#options-close { display: block; position: absolute; right: 7px; bottom: 8px;
|
||||
width: auto; height: auto; font-size: 85%; color: #444; }
|
||||
|
||||
#mainmodals { z-index: 600; /* higher than the modals themselves
|
||||
so that modals are on top in IE */ }
|
||||
.modalfield { font-size: 1.2em; padding: 1px; border: 1px solid #bbb;}
|
||||
|
@ -763,38 +741,8 @@ a#topbarmaximize {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
#embed, #readonly {
|
||||
display:none;
|
||||
position:absolute;
|
||||
top:40px;
|
||||
font-size:14px;
|
||||
width:400px;
|
||||
right: 20px;
|
||||
z-index: 500;
|
||||
background-color: #000;
|
||||
color: white;
|
||||
background-color: rgb(0,0,0);
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
padding: 10px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
#embedreadonly {
|
||||
float:right;
|
||||
}
|
||||
|
||||
#embedcode, #readonlyUrl, #linkcode {
|
||||
margin-left:10px;
|
||||
}
|
||||
|
||||
#embedinput, #readonlyInput, #linkinput {
|
||||
width:375px;
|
||||
height:24px;
|
||||
display:inline;
|
||||
margin-top: 10px;
|
||||
padding-left:4px;
|
||||
}
|
||||
|
||||
ul#colorpickerswatches
|
||||
{
|
||||
|
@ -850,6 +798,7 @@ ul#colorpickerswatches li:hover
|
|||
left:0px;
|
||||
top:25px;
|
||||
bottom:25px;
|
||||
z-index:1002;
|
||||
}
|
||||
|
||||
#chattext p
|
||||
|
@ -986,40 +935,8 @@ position: relative;
|
|||
top: -5px;
|
||||
}
|
||||
|
||||
#importexport{
|
||||
position:absolute;
|
||||
top:40px;
|
||||
font-size:14px;
|
||||
width:450px;
|
||||
right: 20px;
|
||||
z-index: 500;
|
||||
background-color: #000;
|
||||
color: white;
|
||||
background-color: rgb(0,0,0);
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
padding: 10px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
height:190px;
|
||||
display:none;
|
||||
}
|
||||
|
||||
#import{
|
||||
position:absolute;
|
||||
width:250px;
|
||||
left:10px;
|
||||
line-height:20px;
|
||||
}
|
||||
|
||||
#export{
|
||||
position:absolute;
|
||||
width:180px;
|
||||
right:10px;
|
||||
line-height:20px;
|
||||
}
|
||||
|
||||
.exporttype{
|
||||
line-height:20px;
|
||||
margin-top: 2px;
|
||||
background-repeat:no-repeat;
|
||||
padding-left:25px;
|
||||
background-image: url("../../static/img/etherpad_lite_icons.png");
|
||||
|
@ -1028,8 +945,8 @@ position: relative;
|
|||
}
|
||||
|
||||
#importexportline{
|
||||
border: dotted 1px;
|
||||
height: 185px;
|
||||
border-left: 1px solid #fff;
|
||||
height: 190px;
|
||||
position:absolute;
|
||||
width:0px;
|
||||
left:260px;
|
||||
|
@ -1069,10 +986,6 @@ position: relative;
|
|||
background-position: 0px -459px;
|
||||
}
|
||||
|
||||
#export a{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#importstatusball{
|
||||
display:none;
|
||||
}
|
||||
|
@ -1122,6 +1035,59 @@ background-repeat: no-repeat;
|
|||
margin-left: 1px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.buttonicon-bold {
|
||||
background-position: 0px -116px;
|
||||
}
|
||||
.buttonicon-italic {
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
.buttonicon-underline {
|
||||
background-position: 0px -236px;
|
||||
}
|
||||
.buttonicon-strikethrough {
|
||||
background-position: 0px -200px;
|
||||
}
|
||||
.buttonicon-insertorderedlist {
|
||||
background-position: 0px -477px
|
||||
}
|
||||
.buttonicon-insertunorderedlist {
|
||||
background-position: 0px -34px;
|
||||
}
|
||||
.buttonicon-indent {
|
||||
background-position: 0px -52px;
|
||||
}
|
||||
.buttonicon-outdent {
|
||||
background-position: 0px -134px;
|
||||
}
|
||||
.buttonicon-undo {
|
||||
background-position: 0px -255px;
|
||||
}
|
||||
.buttonicon-redo {
|
||||
background-position :0px -166px;
|
||||
}
|
||||
.buttonicon-clearauthorship {
|
||||
background-position: 0px -86px;
|
||||
}
|
||||
.buttonicon-settings {
|
||||
background-position: 0px -436px;
|
||||
}
|
||||
.buttonicon-import_export {
|
||||
background-position: 0px -68px;
|
||||
}
|
||||
.buttonicon-embed {
|
||||
background-position: 0px -18px;
|
||||
}
|
||||
.buttonicon-history {
|
||||
background-position: 0px -218px;
|
||||
}
|
||||
.buttonicon-chat {
|
||||
background-position: 0px -102px;
|
||||
display: inline-block;
|
||||
}
|
||||
.buttonicon-showusers {
|
||||
background-position: 0px -183px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#usericon
|
||||
{
|
||||
|
@ -1145,18 +1111,22 @@ width:33px !important;
|
|||
color: #999;
|
||||
}
|
||||
|
||||
label[for=readonlyinput] {
|
||||
margin: 0 10px 0 2px;
|
||||
}
|
||||
|
||||
|
||||
#qr_center {
|
||||
margin: 10px 10px auto 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#qrcode{
|
||||
margin-left:10px;
|
||||
#embedreadonlyqr {
|
||||
box-shadow: 0 0 10px #000;
|
||||
border-radius: 3px;
|
||||
-webkit-transition: all .2s ease-in-out;
|
||||
-moz-transition: all .2s ease-in-out;
|
||||
}
|
||||
|
||||
#embedreadonlyqr:hover {
|
||||
cursor: none;
|
||||
-moz-transform: scale(1.5);
|
||||
-webkit-transform: scale(1.5);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
|
@ -1245,3 +1215,78 @@ label[for=readonlyinput] {
|
|||
.rtl{
|
||||
direction:RTL;
|
||||
}
|
||||
|
||||
#chattext p {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* fix for misaligned labels */
|
||||
label {
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
}
|
||||
|
||||
.right {
|
||||
float:right;
|
||||
}
|
||||
|
||||
.popup {
|
||||
font-size: 14px;
|
||||
width: 450px;
|
||||
z-index: 500;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
background: #222;
|
||||
background: rgba(0,0,0,.7);
|
||||
background: -webkit-linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6));
|
||||
background: -moz-linear-gradient(rgba(0,0,0,.6), rgba(0,0,0,.7) 35px, rgba(0,0,0,.6));
|
||||
box-shadow: 0 0 8px #888;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.popup input[type=text] {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
display:block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.popup a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.popup h1 {
|
||||
font-size: 18px;
|
||||
}
|
||||
.popup h2 {
|
||||
font-size: 15px;
|
||||
}
|
||||
.popup p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.left_popup {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.right_popup {
|
||||
float: left;
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#settingsmenu, #importexport, #embed {
|
||||
position: absolute;
|
||||
top: 55px;
|
||||
right: 20px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.note {
|
||||
color: #ddd;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
@ -195,10 +195,8 @@ float:right;
|
|||
color: #222;
|
||||
}
|
||||
|
||||
#importexport{
|
||||
top:103px;
|
||||
width:185px;
|
||||
}
|
||||
#importexport { top: 118px; }
|
||||
#importexport .popup { width: 185px; }
|
||||
|
||||
ul { margin-left: 1.5em; }
|
||||
ul ul { margin-left: 0 !important; }
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<title>Etherpad Lite</title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
|
||||
<style>
|
||||
*{ margin:0;padding:0; }
|
||||
body {
|
||||
|
@ -108,15 +111,18 @@
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<link href="static/custom/index.css" rel="stylesheet">
|
||||
<script src="static/custom/index.js"></script>
|
||||
|
||||
<div id="container">
|
||||
<div id="button" onclick="go2Random()" class="translate">New Pad</div><br><div id="label" class="translate">or create/open a Pad with the name</div>
|
||||
<form action="#" onsubmit="go2Name();return false;">
|
||||
<input type="text" id="padname" autofocus>
|
||||
<input type="text" id="padname" autofocus x-webkit-speech>
|
||||
<input type="submit" value="OK">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function go2Name()
|
||||
{
|
||||
|
@ -145,4 +151,5 @@
|
|||
//start the costum js
|
||||
if(typeof costumStart == "function") costumStart();
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -237,11 +237,18 @@ function OUTER(gscope)
|
|||
bgcolor = fadeColor(bgcolor, info.fade);
|
||||
}
|
||||
|
||||
dynamicCSS.selectorStyle(getAuthorColorClassSelector(
|
||||
getAuthorClassName(author))).backgroundColor = bgcolor;
|
||||
// Text color
|
||||
var txtcolor = (colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.45) ? '#ffffff' : '#000000';
|
||||
|
||||
dynamicCSSTop.selectorStyle(getAuthorColorClassSelector(
|
||||
getAuthorClassName(author))).backgroundColor = bgcolor;
|
||||
var authorStyle = dynamicCSS.selectorStyle(getAuthorColorClassSelector(
|
||||
getAuthorClassName(author)));
|
||||
authorStyle.backgroundColor = bgcolor;
|
||||
authorStyle.color = txtcolor;
|
||||
|
||||
var authorStyleTop = dynamicCSSTop.selectorStyle(getAuthorColorClassSelector(
|
||||
getAuthorClassName(author)));
|
||||
authorStyleTop.backgroundColor = bgcolor;
|
||||
authorStyleTop.color = txtcolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3138,11 +3145,12 @@ function OUTER(gscope)
|
|||
// Such a div is what IE 6 creates naturally when you make a blank line
|
||||
// in a document of divs. However, when copy-and-pasted the div will
|
||||
// contain a space, so we note its emptiness with a property.
|
||||
lineElem.innerHTML = "";
|
||||
lineElem.innerHTML = " "; // Frist we set a value that isnt blank
|
||||
// a primitive-valued property survives copy-and-paste
|
||||
setAssoc(lineElem, "shouldBeEmpty", true);
|
||||
// an object property doesn't
|
||||
setAssoc(lineElem, "unpasted", {});
|
||||
lineElem.innerHTML = ""; // Then we make it blank.. New line and no space = Awesome :)
|
||||
};
|
||||
var lineClass = 'ace-line';
|
||||
result.appendSpan = function(txt, cls)
|
||||
|
|
|
@ -20,16 +20,17 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var global = this;
|
||||
|
||||
var makeCSSManager = require('/cssmanager_client').makeCSSManager;
|
||||
var domline = require('/domline_client').domline;
|
||||
var Changeset = require('/easysync2_client').Changeset;
|
||||
var AttribPool = require('/easysync2_client').AttribPool;
|
||||
var linestylefilter = require('/linestylefilter_client').linestylefilter;
|
||||
|
||||
function loadBroadcastJS()
|
||||
// These parameters were global, now they are injected. A reference to the
|
||||
// Timeslider controller would probably be more appropriate.
|
||||
function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider)
|
||||
{
|
||||
var changesetLoader = undefined;
|
||||
// just in case... (todo: this must be somewhere else in the client code.)
|
||||
// Below Array#map code was direct pasted by AppJet/Etherpad, licence unknown. Possible source: http://www.tutorialspoint.com/javascript/array_map.htm
|
||||
if (!Array.prototype.map)
|
||||
|
@ -423,7 +424,7 @@ function loadBroadcastJS()
|
|||
}));
|
||||
}
|
||||
|
||||
global.changesetLoader = {
|
||||
changesetLoader = {
|
||||
running: false,
|
||||
resolved: [],
|
||||
requestQueue1: [],
|
||||
|
@ -763,6 +764,8 @@ function loadBroadcastJS()
|
|||
}
|
||||
|
||||
receiveAuthorData(clientVars.historicalAuthorData);
|
||||
|
||||
return changesetLoader;
|
||||
}
|
||||
|
||||
exports.loadBroadcastJS = loadBroadcastJS;
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
// revision info is a skip list whos entries represent a particular revision
|
||||
// of the document. These revisions are connected together by various
|
||||
// changesets, or deltas, between any two revisions.
|
||||
var global = this;
|
||||
|
||||
function loadBroadcastRevisionsJS()
|
||||
{
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
var global = this;
|
||||
|
||||
function loadBroadcastSliderJS()
|
||||
// These parameters were global, now they are injected. A reference to the
|
||||
// Timeslider controller would probably be more appropriate.
|
||||
function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||
{
|
||||
var BroadcastSlider;
|
||||
|
||||
(function()
|
||||
{ // wrap this code in its own namespace
|
||||
|
@ -203,7 +205,7 @@ function loadBroadcastSliderJS()
|
|||
}
|
||||
}
|
||||
|
||||
global.BroadcastSlider = {
|
||||
BroadcastSlider = {
|
||||
onSlider: onSlider,
|
||||
getSliderPosition: getSliderPosition,
|
||||
setSliderPosition: setSliderPosition,
|
||||
|
@ -495,6 +497,8 @@ function loadBroadcastSliderJS()
|
|||
{
|
||||
$("#viewlatest").html(loc == BroadcastSlider.getSliderLength() ? "Viewing latest content" : "View latest content");
|
||||
})
|
||||
|
||||
return BroadcastSlider;
|
||||
}
|
||||
|
||||
exports.loadBroadcastSliderJS = loadBroadcastSliderJS;
|
||||
|
|
|
@ -21,17 +21,18 @@
|
|||
*/
|
||||
|
||||
var padutils = require('/pad_utils').padutils;
|
||||
var browser = require('/ace2_common').browser;
|
||||
var padcookie = require('/pad_cookie').padcookie;
|
||||
|
||||
var chat = (function()
|
||||
{
|
||||
var bottomMargin = "0px";
|
||||
var isStuck = false;
|
||||
var sDuration = 500;
|
||||
var hDuration = 750;
|
||||
var chatMentions = 0;
|
||||
var title = document.title;
|
||||
if ($.browser.mobile){
|
||||
sDuration = 0;
|
||||
hDuration = 0;
|
||||
if (browser.mobile){
|
||||
sDuration = hDuration = 0;
|
||||
}
|
||||
var self = {
|
||||
show: function ()
|
||||
|
@ -56,10 +57,11 @@ var chat = (function()
|
|||
{
|
||||
$("#focusprotector").hide();
|
||||
|
||||
if($.browser.mobile)
|
||||
bottommargin = "32px";
|
||||
|
||||
$("#chatbox").css({right: "20px", bottom: bottomMargin, left: "", top: ""});
|
||||
if(browser.mobile) {
|
||||
$("#chatbox").css({right: "0px", bottom: "32px", left: "", top: ""});
|
||||
} else {
|
||||
$("#chatbox").css({right: "20px", bottom: "0px", left: "", top: ""});
|
||||
}
|
||||
|
||||
self.scrollDown();
|
||||
}
|
||||
|
@ -68,6 +70,23 @@ var chat = (function()
|
|||
chatMentions = 0;
|
||||
document.title = title;
|
||||
},
|
||||
stickToScreen: function(fromInitialCall) // Make chat stick to right hand side of screen
|
||||
{
|
||||
chat.show();
|
||||
if(!isStuck || fromInitialCall) { // Stick it to
|
||||
padcookie.setPref("chatAlwaysVisible", true);
|
||||
$('#chatbox').css({"right":"0px", "top":"36px", "border-radius":"0px", "height":"auto", "border-right":"none", "border-left":"1px solid #ccc", "border-top":"none", "background-color":"#f1f1f1", "width":"185px"});
|
||||
$('#chattext').css({"top":"0px"});
|
||||
$('#editorcontainer').css({"right":"192px", "width":"auto"});
|
||||
isStuck = true;
|
||||
} else { // Unstick it
|
||||
padcookie.setPref("chatAlwaysVisible", false);
|
||||
$('#chatbox').css({"right":"20px", "top":"auto", "border-top-left-radius":"5px", "border-top-right-radius":"5px", "border-right":"1px solid #999", "height":"200px", "border-top":"1px solid #999", "background-color":"#f7f7f7"});
|
||||
$('#chattext').css({"top":"25px"});
|
||||
$('#editorcontainer').css({"right":"0px", "width":"100%"});
|
||||
isStuck = false;
|
||||
}
|
||||
},
|
||||
hide: function ()
|
||||
{
|
||||
$("#chatcounter").text("0");
|
||||
|
@ -177,3 +196,4 @@ var chat = (function()
|
|||
}());
|
||||
|
||||
exports.chat = chat;
|
||||
|
||||
|
|
|
@ -24,13 +24,14 @@
|
|||
|
||||
var socket;
|
||||
|
||||
var settings = {};
|
||||
settings.LineNumbersDisabled = false;
|
||||
settings.noColors = false;
|
||||
settings.useMonospaceFontGlobal = false;
|
||||
settings.globalUserName = false;
|
||||
settings.hideQRCode = false;
|
||||
settings.rtlIsTrue = false;
|
||||
// These jQuery things should create local references, but for now `require()`
|
||||
// assigns to the global `$` and augments it with plugins.
|
||||
require('/jquery');
|
||||
require('/jquery-ui');
|
||||
require('/farbtastic');
|
||||
require('/excanvas');
|
||||
require('/json2');
|
||||
require('/undo-xpopup');
|
||||
|
||||
var chat = require('/chat').chat;
|
||||
var getCollabClient = require('/collab_client').getCollabClient;
|
||||
|
@ -45,19 +46,6 @@ var padsavedrevs = require('/pad_savedrevs').padsavedrevs;
|
|||
var paduserlist = require('/pad_userlist').paduserlist;
|
||||
var padutils = require('/pad_utils').padutils;
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
//start the costum js
|
||||
if(typeof costumStart == "function") costumStart();
|
||||
getParams();
|
||||
handshake();
|
||||
});
|
||||
|
||||
$(window).unload(function()
|
||||
{
|
||||
pad.dispose();
|
||||
});
|
||||
|
||||
function createCookie(name, value, days, path)
|
||||
{
|
||||
if (days)
|
||||
|
@ -309,7 +297,7 @@ function handshake()
|
|||
clientVars.collab_client_vars.clientAgent = "Anonymous";
|
||||
|
||||
//initalize the pad
|
||||
pad.init();
|
||||
pad._afterHandshake();
|
||||
initalized = true;
|
||||
|
||||
// If the LineNumbersDisabled value is set to true then we need to hide the Line Numbers
|
||||
|
@ -358,7 +346,6 @@ function handshake()
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Bind the colorpicker
|
||||
var fb = $('#colorpicker').farbtastic({ callback: '#mycolorpickerpreview', width: 220});
|
||||
}
|
||||
|
@ -422,6 +409,23 @@ var pad = {
|
|||
},
|
||||
|
||||
init: function()
|
||||
{
|
||||
padutils.setupGlobalExceptionHandler();
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
//start the costum js
|
||||
if(typeof costumStart == "function") costumStart();
|
||||
getParams();
|
||||
handshake();
|
||||
});
|
||||
|
||||
$(window).unload(function()
|
||||
{
|
||||
pad.dispose();
|
||||
});
|
||||
},
|
||||
_afterHandshake: function()
|
||||
{
|
||||
pad.clientTimeOffset = new Date().getTime() - clientVars.serverTimestamp;
|
||||
|
||||
|
@ -447,10 +451,10 @@ var pad = {
|
|||
}
|
||||
|
||||
// order of inits is important here:
|
||||
padcookie.init(clientVars.cookiePrefsToSet);
|
||||
padcookie.init(clientVars.cookiePrefsToSet, this);
|
||||
|
||||
$("#widthprefcheck").click(pad.toggleWidthPref);
|
||||
$("#sidebarcheck").click(pad.toggleSidebar);
|
||||
// $("#sidebarcheck").click(pad.togglewSidebar);
|
||||
|
||||
pad.myUserInfo = {
|
||||
userId: clientVars.userId,
|
||||
|
@ -474,16 +478,16 @@ var pad = {
|
|||
initialTitle: clientVars.initialTitle,
|
||||
initialPassword: clientVars.initialPassword,
|
||||
guestPolicy: pad.padOptions.guestPolicy
|
||||
});
|
||||
padimpexp.init();
|
||||
padsavedrevs.init(clientVars.initialRevisionList);
|
||||
}, this);
|
||||
padimpexp.init(this);
|
||||
padsavedrevs.init(clientVars.initialRevisionList, this);
|
||||
|
||||
padeditor.init(postAceInit, pad.padOptions.view || {});
|
||||
padeditor.init(postAceInit, pad.padOptions.view || {}, this);
|
||||
|
||||
paduserlist.init(pad.myUserInfo);
|
||||
paduserlist.init(pad.myUserInfo, this);
|
||||
// padchat.init(clientVars.chatHistory, pad.myUserInfo);
|
||||
padconnectionstatus.init();
|
||||
padmodals.init();
|
||||
padmodals.init(this);
|
||||
|
||||
pad.collabClient = getCollabClient(padeditor.ace, clientVars.collab_client_vars, pad.myUserInfo, {
|
||||
colorPalette: pad.getColorPalette()
|
||||
|
@ -775,15 +779,17 @@ var pad = {
|
|||
|
||||
padsavedrevs.handleIsFullyConnected(isConnected);
|
||||
|
||||
pad.determineSidebarVisibility(isConnected && !isInitialConnect);
|
||||
// pad.determineSidebarVisibility(isConnected && !isInitialConnect);
|
||||
pad.determineChatVisibility(isConnected && !isInitialConnect);
|
||||
|
||||
},
|
||||
determineSidebarVisibility: function(asNowConnectedFeedback)
|
||||
/* determineSidebarVisibility: function(asNowConnectedFeedback)
|
||||
{
|
||||
if (pad.isFullyConnected())
|
||||
{
|
||||
var setSidebarVisibility = padutils.getCancellableAction("set-sidebar-visibility", function()
|
||||
{
|
||||
$("body").toggleClass('hidesidebar', !! padcookie.getPref('hideSidebar'));
|
||||
// $("body").toggleClass('hidesidebar', !! padcookie.getPref('hideSidebar'));
|
||||
});
|
||||
window.setTimeout(setSidebarVisibility, asNowConnectedFeedback ? 3000 : 0);
|
||||
}
|
||||
|
@ -793,6 +799,17 @@ var pad = {
|
|||
$("body").removeClass('hidesidebar');
|
||||
}
|
||||
},
|
||||
*/
|
||||
determineChatVisibility: function(asNowConnectedFeedback){
|
||||
var chatVisCookie = padcookie.getPref('chatAlwaysVisible');
|
||||
if(chatVisCookie){ // if the cookie is set for chat always visible
|
||||
chat.stickToScreen(true); // stick it to the screen
|
||||
$('#options-stickychat').prop("checked", true); // set the checkbox to on
|
||||
}
|
||||
else{
|
||||
$('#options-stickychat').prop("checked", false); // set the checkbox for off
|
||||
}
|
||||
},
|
||||
handleCollabAction: function(action)
|
||||
{
|
||||
if (action == "commitPerformed")
|
||||
|
@ -841,6 +858,7 @@ var pad = {
|
|||
$("#widthprefcheck").toggleClass('widthprefchecked', !! newValue).toggleClass('widthprefunchecked', !newValue);
|
||||
pad.handleWidthChange();
|
||||
},
|
||||
/*
|
||||
toggleSidebar: function()
|
||||
{
|
||||
var newValue = !padcookie.getPref('hideSidebar');
|
||||
|
@ -848,6 +866,7 @@ var pad = {
|
|||
$("#sidebarcheck").toggleClass('sidebarchecked', !newValue).toggleClass('sidebarunchecked', !! newValue);
|
||||
pad.determineSidebarVisibility();
|
||||
},
|
||||
*/
|
||||
handleWidthChange: function()
|
||||
{
|
||||
var isFullWidth = padcookie.getPref('fullWidth');
|
||||
|
@ -967,6 +986,21 @@ var alertBar = (function()
|
|||
return self;
|
||||
}());
|
||||
|
||||
function init() {
|
||||
return pad.init();
|
||||
}
|
||||
|
||||
var settings = {
|
||||
LineNumbersDisabled: false
|
||||
, noColors: false
|
||||
, useMonospaceFontGlobal: false
|
||||
, globalUserName: false
|
||||
, hideQRCode: false
|
||||
, rtlIsTrue: false
|
||||
};
|
||||
|
||||
pad.settings = settings;
|
||||
|
||||
exports.settings = settings;
|
||||
exports.createCookie = createCookie;
|
||||
exports.readCookie = readCookie;
|
||||
|
@ -976,4 +1010,5 @@ exports.getUrlVars = getUrlVars;
|
|||
exports.savePassword = savePassword;
|
||||
exports.handshake = handshake;
|
||||
exports.pad = pad;
|
||||
exports.init = init;
|
||||
exports.alertBar = alertBar;
|
|
@ -87,9 +87,9 @@ var padcookie = (function()
|
|||
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function(prefsToSet)
|
||||
init: function(prefsToSet, _pad)
|
||||
{
|
||||
pad = require('/pad2').pad; // Sidestep circular dependency (should be injected).
|
||||
pad = _pad;
|
||||
|
||||
var rawCookie = getRawCookie();
|
||||
if (rawCookie)
|
||||
|
|
|
@ -118,9 +118,9 @@ var paddocbar = (function()
|
|||
var self = {
|
||||
title: null,
|
||||
password: null,
|
||||
init: function(opts)
|
||||
init: function(opts, _pad)
|
||||
{
|
||||
pad = require('/pad2').pad; // Sidestep circular dependency (should be injected).
|
||||
pad = _pad;
|
||||
|
||||
panels = {
|
||||
impexp: {
|
||||
|
|
|
@ -108,17 +108,20 @@ var padeditbar = (function()
|
|||
{
|
||||
self.toogleDropDown("users");
|
||||
}
|
||||
else if (cmd == 'settings')
|
||||
{
|
||||
self.toogleDropDown("settingsmenu");
|
||||
}
|
||||
else if (cmd == 'embed')
|
||||
{
|
||||
self.setEmbedLinks();
|
||||
$('#embedinput').focus().select();
|
||||
$('#linkinput').focus().select();
|
||||
self.toogleDropDown("embed");
|
||||
}
|
||||
else if (cmd == 'import_export')
|
||||
{
|
||||
self.toogleDropDown("importexport");
|
||||
}
|
||||
|
||||
else if (cmd == 'save')
|
||||
{
|
||||
padsavedrevs.saveNow();
|
||||
|
@ -165,7 +168,7 @@ var padeditbar = (function()
|
|||
},
|
||||
toogleDropDown: function(moduleName)
|
||||
{
|
||||
var modules = ["embed", "users", "readonly", "importexport"];
|
||||
var modules = ["embed", "users", "readonly", "importexport", "settingsmenu"];
|
||||
|
||||
//hide all modules
|
||||
if(moduleName == "none")
|
||||
|
|
|
@ -32,11 +32,11 @@ var padeditor = (function()
|
|||
ace: null,
|
||||
// this is accessed directly from other files
|
||||
viewZoom: 100,
|
||||
init: function(readyFunc, initialViewOptions)
|
||||
init: function(readyFunc, initialViewOptions, _pad)
|
||||
{
|
||||
Ace2Editor = require('/ace').Ace2Editor;
|
||||
pad = require('/pad2').pad; // Sidestep circular dependency (should be injected).
|
||||
settings = require('/pad2').settings;
|
||||
pad = _pad;
|
||||
settings = pad.settings;
|
||||
|
||||
function aceReady()
|
||||
{
|
||||
|
@ -87,6 +87,11 @@ var padeditor = (function()
|
|||
if (value == "false") return false;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
self.ace.setProperty("showsauthorcolors", settings.noColors);
|
||||
|
||||
self.ace.setProperty("rtlIsTrue", settings.rtlIsTrue);
|
||||
|
||||
var v;
|
||||
|
||||
v = getOption('showLineNumbers', true);
|
||||
|
@ -100,10 +105,6 @@ var padeditor = (function()
|
|||
v = getOption('useMonospaceFont', false);
|
||||
self.ace.setProperty("textface", (v ? "monospace" : "Arial, sans-serif"));
|
||||
$("#viewfontmenu").val(v ? "monospace" : "normal");
|
||||
|
||||
self.ace.setProperty("showsauthorcolors", settings.noColors);
|
||||
|
||||
self.ace.setProperty("rtlIsTrue", settings.rtlIsTrue);
|
||||
},
|
||||
initViewZoom: function()
|
||||
{
|
||||
|
|
|
@ -236,13 +236,9 @@ var padimpexp = (function()
|
|||
/////
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function()
|
||||
init: function(_pad)
|
||||
{
|
||||
try {
|
||||
pad = require('/pad2').pad; // Sidestep circular dependency (should be injected).
|
||||
} catch (e) {
|
||||
// skip (doesn't require pad when required by timeslider)
|
||||
}
|
||||
pad = _pad;
|
||||
|
||||
//get /p/padname
|
||||
var pad_root_path = new RegExp(/.*\/p\/[^\/]+/).exec(document.location.pathname)
|
||||
|
|
|
@ -75,9 +75,9 @@ var padmodals = (function()
|
|||
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function()
|
||||
init: function(_pad)
|
||||
{
|
||||
pad = require('/pad2').pad; // Sidestep circular dependency (should be injected).
|
||||
pad = _pad;
|
||||
|
||||
self.initFeedback();
|
||||
self.initShareBox();
|
||||
|
|
|
@ -349,9 +349,9 @@ var padsavedrevs = (function()
|
|||
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function(initialRevisions)
|
||||
init: function(initialRevisions, _pad)
|
||||
{
|
||||
pad = require('/pad2').pad; // Sidestep circular dependency (should be injected).
|
||||
pad = _pad;
|
||||
self.newRevisionList(initialRevisions, true);
|
||||
|
||||
$("#savedrevs-savenow").click(function()
|
||||
|
|
|
@ -464,9 +464,9 @@ var paduserlist = (function()
|
|||
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function(myInitialUserInfo)
|
||||
init: function(myInitialUserInfo, _pad)
|
||||
{
|
||||
pad = require('/pad2').pad; // Sidestep circular dependency (should be injected).
|
||||
pad = _pad;
|
||||
|
||||
self.setMyUserInfo(myInitialUserInfo);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ var padutils = {
|
|||
},
|
||||
uniqueId: function()
|
||||
{
|
||||
var pad = require('/pad2').pad; // Sidestep circular dependency
|
||||
var pad = require('/pad').pad; // Sidestep circular dependency
|
||||
function encodeNum(n, width)
|
||||
{
|
||||
// returns string that is exactly 'width' chars, padding with zeros
|
||||
|
@ -110,24 +110,6 @@ var padutils = {
|
|||
var x = ua.split(' ')[0];
|
||||
return clean(x);
|
||||
},
|
||||
// "func" is a function over 0..(numItems-1) that is monotonically
|
||||
// "increasing" with index (false, then true). Finds the boundary
|
||||
// between false and true, a number between 0 and numItems inclusive.
|
||||
binarySearch: function(numItems, func)
|
||||
{
|
||||
if (numItems < 1) return 0;
|
||||
if (func(0)) return 0;
|
||||
if (!func(numItems - 1)) return numItems;
|
||||
var low = 0; // func(low) is always false
|
||||
var high = numItems - 1; // func(high) is always true
|
||||
while ((high - low) > 1)
|
||||
{
|
||||
var x = Math.floor((low + high) / 2); // x != low, x != high
|
||||
if (func(x)) high = x;
|
||||
else low = x;
|
||||
}
|
||||
return high;
|
||||
},
|
||||
// e.g. "Thu Jun 18 2009 13:09"
|
||||
simpleDateTime: function(date)
|
||||
{
|
||||
|
@ -227,7 +209,7 @@ var padutils = {
|
|||
},
|
||||
timediff: function(d)
|
||||
{
|
||||
var pad = require('/pad2').pad; // Sidestep circular dependency
|
||||
var pad = require('/pad').pad; // Sidestep circular dependency
|
||||
function format(n, word)
|
||||
{
|
||||
n = Math.round(n);
|
||||
|
@ -477,8 +459,11 @@ var padutils = {
|
|||
}
|
||||
};
|
||||
|
||||
var globalExceptionHandler = undefined;
|
||||
function setupGlobalExceptionHandler() {
|
||||
//send javascript errors to the server
|
||||
window.onerror = function test (msg, url, linenumber)
|
||||
if (!globalExceptionHandler) {
|
||||
globalExceptionHandler = function test (msg, url, linenumber)
|
||||
{
|
||||
var errObj = {errorInfo: JSON.stringify({msg: msg, url: url, linenumber: linenumber, userAgent: navigator.userAgent})};
|
||||
var loc = document.location;
|
||||
|
@ -488,5 +473,12 @@ window.onerror = function test (msg, url, linenumber)
|
|||
|
||||
return false;
|
||||
};
|
||||
window.onerror = globalExceptionHandler;
|
||||
}
|
||||
}
|
||||
|
||||
padutils.setupGlobalExceptionHandler = setupGlobalExceptionHandler;
|
||||
|
||||
padutils.binarySearch = require('/ace2_common').binarySearch;
|
||||
|
||||
exports.padutils = padutils;
|
||||
|
|
184
static/js/timeslider.js
Normal file
184
static/js/timeslider.js
Normal file
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// These jQuery things should create local references, but for now `require()`
|
||||
// assigns to the global `$` and augments it with plugins.
|
||||
require('/jquery');
|
||||
require('/json2');
|
||||
require('/undo-xpopup');
|
||||
|
||||
function createCookie(name,value,days)
|
||||
{
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||
var expires = "; expires="+date.toGMTString();
|
||||
}
|
||||
else var expires = "";
|
||||
document.cookie = name+"="+value+expires+"; path=/";
|
||||
}
|
||||
|
||||
function readCookie(name)
|
||||
{
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function randomString() {
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var string_length = 20;
|
||||
var randomstring = '';
|
||||
for (var i=0; i<string_length; i++) {
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum,rnum+1);
|
||||
}
|
||||
return "t." + randomstring;
|
||||
}
|
||||
|
||||
var socket, token, padId, export_links;
|
||||
|
||||
function init() {
|
||||
$(document).ready(function ()
|
||||
{
|
||||
//start the costum js
|
||||
if(typeof costumStart == "function") costumStart();
|
||||
|
||||
//get the padId out of the url
|
||||
var urlParts= document.location.pathname.split("/");
|
||||
padId = decodeURIComponent(urlParts[urlParts.length-2]);
|
||||
|
||||
//set the title
|
||||
document.title = document.title + " | " + padId.replace(/_+/g, ' ');
|
||||
|
||||
//ensure we have a token
|
||||
token = readCookie("token");
|
||||
if(token == null)
|
||||
{
|
||||
token = randomString();
|
||||
createCookie("token", token, 60);
|
||||
}
|
||||
|
||||
var loc = document.location;
|
||||
//get the correct port
|
||||
var port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port;
|
||||
//create the url
|
||||
var url = loc.protocol + "//" + loc.hostname + ":" + port + "/";
|
||||
//find out in which subfolder we are
|
||||
var resource = loc.pathname.substr(1,loc.pathname.indexOf("/p/")) + "socket.io";
|
||||
|
||||
//build up the socket io connection
|
||||
socket = io.connect(url, {resource: resource});
|
||||
|
||||
//send the ready message once we're connected
|
||||
socket.on('connect', function()
|
||||
{
|
||||
sendSocketMsg("CLIENT_READY", {});
|
||||
});
|
||||
|
||||
//route the incoming messages
|
||||
socket.on('message', function(message)
|
||||
{
|
||||
if(window.console) console.log(message);
|
||||
|
||||
if(message.type == "CLIENT_VARS")
|
||||
{
|
||||
handleClientVars(message);
|
||||
}
|
||||
else if(message.type == "CHANGESET_REQ")
|
||||
{
|
||||
changesetLoader.handleSocketResponse(message);
|
||||
}
|
||||
else if(message.accessStatus)
|
||||
{
|
||||
$("body").html("<h2>You have no permission to access this pad</h2>")
|
||||
}
|
||||
});
|
||||
|
||||
//get all the export links
|
||||
export_links = $('#export > .exportlink')
|
||||
|
||||
if(document.referrer.length > 0 && document.referrer.substring(document.referrer.lastIndexOf("/")-1,document.referrer.lastIndexOf("/")) === "p") {
|
||||
$("#returnbutton").attr("href", document.referrer);
|
||||
} else {
|
||||
$("#returnbutton").attr("href", document.location.href.substring(0,document.location.href.lastIndexOf("/")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//sends a message over the socket
|
||||
function sendSocketMsg(type, data)
|
||||
{
|
||||
var sessionID = readCookie("sessionID");
|
||||
var password = readCookie("password");
|
||||
|
||||
var msg = { "component" : "timeslider",
|
||||
"type": type,
|
||||
"data": data,
|
||||
"padId": padId,
|
||||
"token": token,
|
||||
"sessionID": sessionID,
|
||||
"password": password,
|
||||
"protocolVersion": 2};
|
||||
|
||||
socket.json.send(msg);
|
||||
}
|
||||
|
||||
var fireWhenAllScriptsAreLoaded = [];
|
||||
|
||||
var BroadcastSlider, changesetLoader;
|
||||
function handleClientVars(message)
|
||||
{
|
||||
//save the client Vars
|
||||
clientVars = message.data;
|
||||
|
||||
//load all script that doesn't work without the clientVars
|
||||
BroadcastSlider = require('/broadcast_slider').loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded);
|
||||
require('/broadcast_revisions').loadBroadcastRevisionsJS();
|
||||
changesetLoader = require('/broadcast').loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider);
|
||||
|
||||
//initialize export ui
|
||||
require('/pad_impexp').padimpexp.init();
|
||||
|
||||
//change export urls when the slider moves
|
||||
var export_rev_regex = /(\/\d+)?\/export/
|
||||
BroadcastSlider.onSlider(function(revno)
|
||||
{
|
||||
export_links.each(function()
|
||||
{
|
||||
this.setAttribute('href', this.href.replace(export_rev_regex, '/' + revno + '/export'));
|
||||
});
|
||||
});
|
||||
|
||||
//fire all start functions of these scripts, formerly fired with window.load
|
||||
for(var i=0;i < fireWhenAllScriptsAreLoaded.length;i++)
|
||||
{
|
||||
fireWhenAllScriptsAreLoaded[i]();
|
||||
}
|
||||
}
|
||||
|
||||
exports.init = init;
|
281
static/pad.html
281
static/pad.html
|
@ -1,211 +1,196 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<html>
|
||||
|
||||
<title>Etherpad Lite</title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title>Etherpad Lite</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<!-- CSS -->
|
||||
|
||||
<link href="../static/css/pad.css" rel="stylesheet">
|
||||
<!-- javascript -->
|
||||
<script type="text/javascript">
|
||||
// <![CDATA[
|
||||
<link href="../static/custom/pad.css" rel="stylesheet">
|
||||
<style title="dynamicsyntax"></style>
|
||||
|
||||
<script>
|
||||
var clientVars = {};
|
||||
// ]]>
|
||||
</script>
|
||||
<script src="../static/js/require-kernel.js"></script>
|
||||
<script src="../socket.io/socket.io.js"></script>
|
||||
<script src="../minified/pad.js"></script>
|
||||
<link href="../static/custom/pad.css" rel="stylesheet">
|
||||
<script src="../static/custom/pad.js"></script>
|
||||
<style type="text/css" title="dynamicsyntax"></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="editbar">
|
||||
|
||||
<ul id="menu_left">
|
||||
<li onClick="window.pad&&pad.editbarClick('bold');return false" >
|
||||
<a title="Bold (ctrl-B)">
|
||||
<div class="buttonicon" style="background-position:0px -116px"></div>
|
||||
<div class="buttonicon buttonicon-bold"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('italic'); return false;" >
|
||||
<a title="Italics (ctrl-I)">
|
||||
<div class="buttonicon" style="background-position:0px 0px"></div>
|
||||
<div class="buttonicon buttonicon-italic"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('underline');return false;" >
|
||||
<a title="Underline (ctrl-U)">
|
||||
<div class="buttonicon" style="background-position:0px -236px;margin-top:1px;"></div>
|
||||
<div class="buttonicon buttonicon-underline"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('strikethrough');return false;" >
|
||||
<a title="Strikethrough">
|
||||
<div class="buttonicon" style="background-position:0px -200px"></div>
|
||||
<div class="buttonicon buttonicon-strikethrough"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="separator"></li>
|
||||
<li onClick="window.pad&&pad.editbarClick('insertorderedlist');return false;" >
|
||||
<a title="Toggle Ordered List">
|
||||
<div class="buttonicon" style="background-position:0px -477px"></div>
|
||||
<div class="buttonicon buttonicon-insertorderedlist"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('insertunorderedlist');return false;" >
|
||||
<a title="Toggle Bullet List">
|
||||
<div class="buttonicon" style="background-position:0px -34px"></div>
|
||||
<div class="buttonicon buttonicon-insertunorderedlist"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('indent');return false;" >
|
||||
<a title="Indent">
|
||||
<div class="buttonicon" style="background-position:0px -52px"></div>
|
||||
<div class="buttonicon buttonicon-indent"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('outdent');return false;" >
|
||||
<a title="Unindent">
|
||||
<div class="buttonicon" style="background-position:0px -134px"></div>
|
||||
<div class="buttonicon buttonicon-outdent"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="separator"></li>
|
||||
<li onClick="window.pad&&pad.editbarClick('undo');return false;" >
|
||||
<a title="Undo (ctrl-Z)">
|
||||
<div class="buttonicon" style="background-position:0px -255px"></div>
|
||||
<div class="buttonicon buttonicon-undo"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('redo');return false;" >
|
||||
<a title="Redo (ctrl-Y)">
|
||||
<div class="buttonicon" style="background-position:0px -166px"></div>
|
||||
<div class="buttonicon buttonicon-redo"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="separator"></li>
|
||||
<li id="clearAuthorship" onClick="window.pad&&pad.editbarClick('clearauthorship');return false;" >
|
||||
<a title="Clear Authorship Colors">
|
||||
<div class="buttonicon" style="background-position:0px -86px"></div>
|
||||
<div class="buttonicon buttonicon-clearauthorship"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul id="menu_right">
|
||||
|
||||
<li onClick="window.pad&&pad.editbarClick('settings');return false;">
|
||||
<a id="settingslink" title="Settings of this pad">
|
||||
<div class="buttonicon buttonicon-settings"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('import_export');return false;">
|
||||
<a id="exportlink" title="Import/Export from/to different document formats">
|
||||
<div class="buttonicon" style="background-position:0px -68px"></div>
|
||||
<div class="buttonicon buttonicon-import_export"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li onClick="window.pad&&pad.editbarClick('embed');return false;" >
|
||||
<a id="embedlink" title="Share and Embed this pad">
|
||||
<div class="buttonicon" style="background-position:0px -18px"></div>
|
||||
<div class="buttonicon buttonicon-embed"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="separator"></li>
|
||||
<li id="timesliderlink" onClick="document.location = document.location.pathname+ '/timeslider'">
|
||||
<a title="Show the history of this pad">
|
||||
<div class="buttonicon" style="background-position:0px -218px"></div>
|
||||
<div class="buttonicon buttonicon-history"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li id="usericon" onClick="window.pad&&pad.editbarClick('showusers');return false;" >
|
||||
<a title="Show connected users">
|
||||
<div class="buttonicon" id="usericonback" style="background-position:0px -183px;display:inline-block;"></div>
|
||||
<div class="buttonicon buttonicon-showusers" id="usericonback"></div>
|
||||
<span id="online_count">1</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="users">
|
||||
<div id="connectionstatus">
|
||||
<!-- -->
|
||||
</div>
|
||||
|
||||
<div id="connectionstatus"></div>
|
||||
<div id="myuser">
|
||||
|
||||
<div id="mycolorpicker">
|
||||
<div id="colorpicker"></div>
|
||||
<!--
|
||||
<ul id="colorpickerswatches">
|
||||
</ul>
|
||||
-->
|
||||
<span id="mycolorpickersave">
|
||||
<a onclick="closeColorPicker()">Save</a>
|
||||
</span>
|
||||
<span id="mycolorpickercancel">
|
||||
<a onclick="closeColorPicker()">Cancel</a>
|
||||
</span>
|
||||
<span id="mycolorpickersave"><a onclick="closeColorPicker()">Save</a></span>
|
||||
<span id="mycolorpickercancel"><a onclick="closeColorPicker()">Cancel</a></span>
|
||||
<span id="mycolorpickerpreview" class="myswatchboxhoverable"></span>
|
||||
</div>
|
||||
|
||||
<div id="myswatchbox"><div id="myswatch"><!-- --></div></div>
|
||||
<div id="myusernameform"><input type="text" id="myusernameedit" disabled="disabled" /></div>
|
||||
<div id="mystatusform"><input type="text" id="mystatusedit" disabled="disabled" /></div>
|
||||
<div id="myswatchbox"><div id="myswatch"></div></div>
|
||||
<div id="myusernameform"><input type="text" id="myusernameedit" disabled="disabled"></div>
|
||||
<div id="mystatusform"><input type="text" id="mystatusedit" disabled="disabled"></div>
|
||||
</div>
|
||||
|
||||
<div id="otherusers">
|
||||
<div id="guestprompts"><!-- --></div>
|
||||
|
||||
<div id="guestprompts"></div>
|
||||
<table id="otheruserstable" cellspacing="0" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<div id="nootherusers">
|
||||
<div id="nootherusers"></div>
|
||||
</div>
|
||||
<div id="userlistbuttonarea"></div>
|
||||
</div>
|
||||
|
||||
<div id="userlistbuttonarea">
|
||||
<!--<a href="javascript:void(0)" id="sharebutton">Share</a>-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /padusers -->
|
||||
|
||||
|
||||
<!--<div id="users">
|
||||
|
||||
<!-- some example code so I can make the css --*>
|
||||
|
||||
</div>-->
|
||||
|
||||
<div id="editorcontainerbox">
|
||||
|
||||
<div id="editorcontainer">
|
||||
<!-- -->
|
||||
</div>
|
||||
<div id="editorloadingbox">
|
||||
Loading...
|
||||
<div id="editorcontainer"></div>
|
||||
<div id="editorloadingbox">Loading...</div>
|
||||
</div>
|
||||
|
||||
<div id="settingsmenu" class="popup">
|
||||
<h1>Pad settings</h1>
|
||||
<div class="left_popup">
|
||||
<h2>My view</h2>
|
||||
<p>
|
||||
<input type="checkbox" id="options-stickychat" onClick="chat.stickToScreen();">
|
||||
<label for="options-stickychat">Chat always on screen</label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="checkbox" id="options-colorscheck" checked>
|
||||
<label for="options-colorscheck">Authorship colors</label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="checkbox" id="options-linenoscheck" checked>
|
||||
<label for="options-linenoscheck">Line numbers</label>
|
||||
</p>
|
||||
<p>
|
||||
Font type:
|
||||
<select id="viewfontmenu">
|
||||
<option value="normal">Normal</option>
|
||||
<option value="monospace">Monospaced</option>
|
||||
</select>
|
||||
</p>
|
||||
</div>
|
||||
<div class="right_popup">
|
||||
<h2>Global view</h2>
|
||||
<p>Currently nothing.</p>
|
||||
<p class="note">These options affect everyone viewing this pad.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- import export code -->
|
||||
<div id="importexport">
|
||||
|
||||
<div id="import">
|
||||
Import from text file, HTML, PDF, Word, ODT or RTF:<br/><br/>
|
||||
<div id="importexport" class="popup">
|
||||
<div class="left_popup">
|
||||
<h2>Import from text file, HTML, PDF, Word, ODT or RTF</h2><br>
|
||||
<form id="importform" method="post" action="" target="importiframe" enctype="multipart/form-data">
|
||||
<div class="importformdiv" id="importformfilediv">
|
||||
<input type="file" name="file" size="15" id="importfileinput" />
|
||||
<input type="file" name="file" size="15" id="importfileinput">
|
||||
<div class="importmessage" id="importmessagefail"></div>
|
||||
</div>
|
||||
<div class="importmessage" id="importmessagesuccess">Successful!</div>
|
||||
<div class="importformdiv" id="importformsubmitdiv">
|
||||
<input type="hidden" name="padId" value="blpmaXT35R" />
|
||||
<input type="hidden" name="padId" value="blpmaXT35R">
|
||||
<span class="nowrap">
|
||||
<input type="submit" name="submit" value="Import Now" disabled="disabled" id="importsubmitinput" />
|
||||
<img alt="" id="importstatusball" src="../static/img/loading.gif" align="top" />
|
||||
<img alt="" id="importarrow" src="../static/img/leftarrow.png" align="top" />
|
||||
<input type="submit" name="submit" value="Import Now" disabled="disabled" id="importsubmitinput">
|
||||
<img alt="" id="importstatusball" src="../static/img/loading.gif" align="top">
|
||||
<img alt="" id="importarrow" src="../static/img/leftarrow.png" align="top">
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="importexportline"></div>
|
||||
|
||||
<div id="export">
|
||||
Export current pad as:
|
||||
<div class="right_popup">
|
||||
<h2>Export current pad as</h2>
|
||||
<a id="exporthtmla" target="_blank" class="exportlink"><div class="exporttype" id="exporthtml">HTML</div></a>
|
||||
<a id="exportplaina" target="_blank" class="exportlink"><div class="exporttype" id="exportplain">Plain text</div></a>
|
||||
<a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword">Microsoft Word</div></a>
|
||||
|
@ -213,40 +198,37 @@
|
|||
<a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen">OpenDocument</div></a>
|
||||
<a id="exportdokuwikia" target="_blank" class="exportlink"><div class="exporttype" id="exportdokuwiki">DokuWiki text</div></a>
|
||||
<a id="exportwordlea" target="_blank" onClick="padimpexp.export2Wordle();return false;" class="exportlink"><div class="exporttype" id="exportwordle">Wordle</div></a>
|
||||
<form id="wordlepost" name="wall" action="http://wordle.net/advanced" method="POST" style="margin-left:0px;">
|
||||
<div id="hidetext" style=""><textarea id="text" name="text" style="display:none;">Coming soon!</textarea></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- the embed code -->
|
||||
<div id="embed">
|
||||
<div id="embedreadonly">
|
||||
<input type="checkbox" id="readonlyinput" onClick="padeditbar.setEmbedLinks();"/><label for="readonlyinput">Read only</label>
|
||||
<div id="embed" class="popup">
|
||||
<div id="embedreadonly" class="right">
|
||||
<input type="checkbox" id="readonlyinput" onClick="padeditbar.setEmbedLinks();">
|
||||
<label for="readonlyinput">Read only</label>
|
||||
</div>
|
||||
Share:
|
||||
<br/>
|
||||
<h1>Share this pad</h1>
|
||||
<div id="linkcode">
|
||||
<label for="linkinput">Link:</label><input id="linkinput" type="text" value="">
|
||||
</div><br/>
|
||||
<h2>Link</h2>
|
||||
<input id="linkinput" type="text" value="">
|
||||
</div>
|
||||
<br>
|
||||
<div id="embedcode">
|
||||
<label for="embedinput">Embed code:</label><input id="embedinput" type="text" value="">
|
||||
</div><br/>
|
||||
<h2>Embed URL</h2>
|
||||
<input id="embedinput" type="text" value="">
|
||||
</div>
|
||||
<br>
|
||||
<div id="qrcode">
|
||||
<label for="embedreadonlyqr">QR code:</label><br/>
|
||||
<h2>QR code</h2>
|
||||
<div id="qr_center"><img id="embedreadonlyqr"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="chatthrob">
|
||||
|
||||
</div>
|
||||
<div id="chatthrob"></div>
|
||||
|
||||
<div id="chaticon">
|
||||
<a onClick="chat.show();return false;"
|
||||
title="Open the chat for this pad">
|
||||
<a onClick="chat.show();return false;" title="Open the chat for this pad">
|
||||
<span id="chatlabel">Chat</span>
|
||||
<div class="buttonicon" style="background-position:0px -102px;display:inline-block;"></div>
|
||||
<div class="buttonicon buttonicon-chat"></div>
|
||||
</a>
|
||||
<span id="chatcounter">0</span>
|
||||
</div>
|
||||
|
@ -256,95 +238,74 @@
|
|||
<div id="chattext" class="authorColors"></div>
|
||||
<div id="chatinputbox">
|
||||
<form>
|
||||
<input id="chatinput" type="text" maxlength="140"/>
|
||||
<input id="chatinput" type="text" maxlength="140">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="focusprotector"> </div>
|
||||
|
||||
<!-- /padeditor -->
|
||||
<div id="modaloverlay">
|
||||
<div id="modaloverlay-inner">
|
||||
<!-- -->
|
||||
<div id="modaloverlay-inner"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="mainmodals">
|
||||
<div id="connectionbox" class="modaldialog">
|
||||
<div id="connectionboxinner" class="modaldialog-inner">
|
||||
<div class="connecting">
|
||||
Connecting...
|
||||
</div>
|
||||
<div class="reconnecting">
|
||||
Reestablishing connection...
|
||||
</div>
|
||||
<div class="connecting">Connecting...</div>
|
||||
<div class="reconnecting">Reestablishing connection...</div>
|
||||
<div class="disconnected">
|
||||
<h2 class="h2_disconnect">Disconnected.</h2>
|
||||
<h2 class="h2_userdup">Opened in another window.</h2>
|
||||
<h2 class="h2_unauth">No Authorization.</h2>
|
||||
<div id="disconnected_looping">
|
||||
<p>
|
||||
<b>We're having trouble talking to the EtherPad lite synchronization server.</b>
|
||||
You may be connecting through an incompatible firewall or proxy server.
|
||||
</p>
|
||||
<p><b>We're having trouble talking to the EtherPad lite synchronization server.</b> You may be connecting through an incompatible firewall or proxy server.</p>
|
||||
</div>
|
||||
<div id="disconnected_initsocketfail">
|
||||
<p>
|
||||
<b>We were unable to connect to the EtherPad lite synchronization server.</b>
|
||||
This may be due to an incompatibility with your web browser or internet connection.
|
||||
</p>
|
||||
<p><b>We were unable to connect to the EtherPad lite synchronization server.</b> This may be due to an incompatibility with your web browser or internet connection.</p>
|
||||
</div>
|
||||
<div id="disconnected_userdup">
|
||||
<p>
|
||||
<b>You seem to have opened this pad in another browser window.</b>
|
||||
If you'd like to use this window instead, you can reconnect.
|
||||
</p>
|
||||
<p><b>You seem to have opened this pad in another browser window.</b> If you'd like to use this window instead, you can reconnect.</p>
|
||||
</div>
|
||||
<div id="disconnected_unknown">
|
||||
<p>
|
||||
<b>Lost connection with the EtherPad lite synchronization server.</b> This may be due to a loss of network connectivity.
|
||||
</p>
|
||||
<p><b>Lost connection with the EtherPad lite synchronization server.</b> This may be due to a loss of network connectivity.</p>
|
||||
</div>
|
||||
<div id="disconnected_slowcommit">
|
||||
<p>
|
||||
<b>Server not responding.</b> This may be due to network connectivity issues or high load on the server.
|
||||
</p>
|
||||
<p><b>Server not responding.</b> This may be due to network connectivity issues or high load on the server.</p>
|
||||
</div>
|
||||
<div id="disconnected_unauth">
|
||||
<p>
|
||||
Your browser's credentials or permissions have changed while viewing this pad. Try reconnecting.
|
||||
</p>
|
||||
<p>Your browser's credentials or permissions have changed while viewing this pad. Try reconnecting.</p>
|
||||
</div>
|
||||
<div id="disconnected_deleted">
|
||||
<p>
|
||||
This pad was deleted.
|
||||
</p>
|
||||
<p>This pad was deleted.</p>
|
||||
</div>
|
||||
<div id="reconnect_advise">
|
||||
<p>
|
||||
If this continues to happen, please let us know
|
||||
</p>
|
||||
<p>If this continues to happen, please let us know</p>
|
||||
</div>
|
||||
<div id="reconnect_form">
|
||||
<button id="forcereconnect">Reconnect Now</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="reconnectform" method="post" action="/ep/pad/reconnect" accept-charset="UTF-8" style="display: none;">
|
||||
<input type="hidden" class="padId" name="padId"/>
|
||||
<input type="hidden" class="diagnosticInfo" name="diagnosticInfo"/>
|
||||
<input type="hidden" class="missedChanges" name="missedChanges"/>
|
||||
<input type="hidden" class="padId" name="padId">
|
||||
<input type="hidden" class="diagnosticInfo" name="diagnosticInfo">
|
||||
<input type="hidden" class="missedChanges" name="missedChanges">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* TODO: These globals shouldn't exist. */
|
||||
pad = require('/pad2').pad;
|
||||
pad = require('/pad').pad;
|
||||
chat = require('/chat').chat;
|
||||
padeditbar = require('/pad_editbar').padeditbar;
|
||||
padimpexp = require('/pad_impexp').padimpexp;
|
||||
|
||||
(function () {
|
||||
require('/pad').init();
|
||||
}());
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -15,163 +15,6 @@
|
|||
|
||||
<link href="../../static/custom/timeslider.css" rel="stylesheet">
|
||||
<script src="../../static/custom/timeslider.js"></script>
|
||||
|
||||
<script>
|
||||
// <![CDATA[
|
||||
var clientVars = {};
|
||||
|
||||
/* TODO: These globals shouldn't exist. */
|
||||
padeditbar = require('/pad_editbar').padeditbar;
|
||||
padimpexp = require('/pad_impexp').padimpexp;
|
||||
|
||||
function createCookie(name,value,days)
|
||||
{
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||
var expires = "; expires="+date.toGMTString();
|
||||
}
|
||||
else var expires = "";
|
||||
document.cookie = name+"="+value+expires+"; path=/";
|
||||
}
|
||||
|
||||
function readCookie(name)
|
||||
{
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function randomString() {
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var string_length = 20;
|
||||
var randomstring = '';
|
||||
for (var i=0; i<string_length; i++) {
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomstring += chars.substring(rnum,rnum+1);
|
||||
}
|
||||
return "t." + randomstring;
|
||||
}
|
||||
|
||||
var socket, token, padId, export_links;
|
||||
|
||||
$(document).ready(function ()
|
||||
{
|
||||
//start the costum js
|
||||
if(typeof costumStart == "function") costumStart();
|
||||
|
||||
//get the padId out of the url
|
||||
var urlParts= document.location.pathname.split("/");
|
||||
padId = decodeURIComponent(urlParts[urlParts.length-2]);
|
||||
|
||||
//set the title
|
||||
document.title = document.title + " | " + padId.replace(/_+/g, ' ');
|
||||
|
||||
//ensure we have a token
|
||||
token = readCookie("token");
|
||||
if(token == null)
|
||||
{
|
||||
token = randomString();
|
||||
createCookie("token", token, 60);
|
||||
}
|
||||
|
||||
var loc = document.location;
|
||||
//get the correct port
|
||||
var port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port;
|
||||
//create the url
|
||||
var url = loc.protocol + "//" + loc.hostname + ":" + port + "/";
|
||||
//find out in which subfolder we are
|
||||
var resource = loc.pathname.substr(1,loc.pathname.indexOf("/p/")) + "socket.io";
|
||||
|
||||
//build up the socket io connection
|
||||
socket = io.connect(url, {resource: resource});
|
||||
|
||||
//send the ready message once we're connected
|
||||
socket.on('connect', function()
|
||||
{
|
||||
sendSocketMsg("CLIENT_READY", {});
|
||||
});
|
||||
|
||||
//route the incoming messages
|
||||
socket.on('message', function(message)
|
||||
{
|
||||
if(window.console) console.log(message);
|
||||
|
||||
if(message.type == "CLIENT_VARS")
|
||||
{
|
||||
handleClientVars(message);
|
||||
}
|
||||
else if(message.type == "CHANGESET_REQ")
|
||||
{
|
||||
changesetLoader.handleSocketResponse(message);
|
||||
}
|
||||
else if(message.accessStatus)
|
||||
{
|
||||
$("body").html("<h2>You have no permission to access this pad</h2>")
|
||||
}
|
||||
});
|
||||
|
||||
//get all the export links
|
||||
export_links = $('#export > .exportlink')
|
||||
});
|
||||
|
||||
//sends a message over the socket
|
||||
function sendSocketMsg(type, data)
|
||||
{
|
||||
var sessionID = readCookie("sessionID");
|
||||
var password = readCookie("password");
|
||||
|
||||
var msg = { "component" : "timeslider",
|
||||
"type": type,
|
||||
"data": data,
|
||||
"padId": padId,
|
||||
"token": token,
|
||||
"sessionID": sessionID,
|
||||
"password": password,
|
||||
"protocolVersion": 2};
|
||||
|
||||
socket.json.send(msg);
|
||||
}
|
||||
|
||||
var fireWhenAllScriptsAreLoaded = [];
|
||||
|
||||
function handleClientVars(message)
|
||||
{
|
||||
//save the client Vars
|
||||
clientVars = message.data;
|
||||
|
||||
//load all script that doesn't work without the clientVars
|
||||
require('/broadcast_slider').loadBroadcastSliderJS();
|
||||
require('/broadcast_revisions').loadBroadcastRevisionsJS();
|
||||
require('/broadcast').loadBroadcastJS();
|
||||
|
||||
//initialize export ui
|
||||
padimpexp.init();
|
||||
|
||||
//change export urls when the slider moves
|
||||
var export_rev_regex = /(\/\d+)?\/export/
|
||||
BroadcastSlider.onSlider(function(revno)
|
||||
{
|
||||
export_links.each(function()
|
||||
{
|
||||
this.setAttribute('href', this.href.replace(export_rev_regex, '/' + revno + '/export'));
|
||||
});
|
||||
});
|
||||
|
||||
//fire all start functions of these scripts, formerly fired with window.load
|
||||
for(var i=0;i < fireWhenAllScriptsAreLoaded.length;i++)
|
||||
{
|
||||
fireWhenAllScriptsAreLoaded[i]();
|
||||
}
|
||||
}
|
||||
|
||||
// ]]>
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body id="padbody" class="timeslider limwidth nonpropad nonprouser">
|
||||
|
@ -293,18 +136,11 @@
|
|||
<ul>
|
||||
<li onClick="window.padeditbar.toolbarClick('import_export');return false;">
|
||||
<a id="exportlink" title="Export to different document formats">
|
||||
<div class="buttonicon" style="background-position:0px -68px"></div>
|
||||
<div class="buttonicon buttonicon-import_export"></div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a id = "returnbutton">Return to pad</a>
|
||||
<script>
|
||||
if(document.referrer.length > 0 && document.referrer.substring(document.referrer.lastIndexOf("/")-1,document.referrer.lastIndexOf("/")) === "p") {
|
||||
$("#returnbutton").attr("href", document.referrer);
|
||||
} else {
|
||||
$("#returnbutton").attr("href", document.location.href.substring(0,document.location.href.lastIndexOf("/")));
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<div id="editbarinner" class="editbarinner">
|
||||
|
@ -352,7 +188,7 @@
|
|||
<!-- export code -->
|
||||
<div id="importexport">
|
||||
|
||||
<div id="export">
|
||||
<div id="export" class="popup">
|
||||
Export current version as:
|
||||
<a id="exporthtmla" target="_blank" class="exportlink"><div class="exporttype" id="exporthtml">HTML</div></a>
|
||||
<a id="exportplaina" target="_blank" class="exportlink"><div class="exporttype" id="exportplain">Plain text</div></a>
|
||||
|
@ -366,6 +202,18 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var clientVars = {};
|
||||
|
||||
/* TODO: These globals shouldn't exist. */
|
||||
padeditbar = require('/pad_editbar').padeditbar;
|
||||
padimpexp = require('/pad_impexp').padimpexp;
|
||||
|
||||
(function () {
|
||||
var TimeSlider = require('/timeslider').init();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue