mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-19 14:13:34 +01:00
lint: Put opening brace on same line as function
Normally I would let `eslint --fix` do this for me, but there's a bug that causes: const x = function () { // ... }; to become: const x = () => { // ... }; which ESLint thinks is a syntax error. (It probably is; I don't know enough about the automatic semicolon insertion rules to be confident.)
This commit is contained in:
parent
cc988bd67b
commit
7df3ded66f
66 changed files with 1036 additions and 2072 deletions
|
@ -59,11 +59,9 @@ npm.load({}, async function() {
|
|||
var atext = Changeset.makeAText("\n")
|
||||
|
||||
//run trough all revisions
|
||||
async.forEachSeries(revisions, function(revNum, callback)
|
||||
{
|
||||
async.forEachSeries(revisions, function(revNum, callback) {
|
||||
//console.log('Fetching', revNum)
|
||||
db.db.get("pad:"+padId+":revs:" + revNum, function(err, revision)
|
||||
{
|
||||
db.db.get("pad:"+padId+":revs:" + revNum, function(err, revision) {
|
||||
if(err) return callback(err);
|
||||
|
||||
//check if there is a atext in the keyRevisions
|
||||
|
|
|
@ -49,25 +49,20 @@ var padIDs;
|
|||
|
||||
async.series([
|
||||
//get all padids out of the database...
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
log("get all padIds out of the database...");
|
||||
|
||||
etherpadDB.query("SELECT ID FROM PAD_META", [], function(err, _padIDs)
|
||||
{
|
||||
etherpadDB.query("SELECT ID FROM PAD_META", [], function(err, _padIDs) {
|
||||
padIDs = _padIDs;
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
log("done");
|
||||
|
||||
//create a queue with a concurrency 100
|
||||
var queue = async.queue(function (padId, callback)
|
||||
{
|
||||
convertPad(padId, function(err)
|
||||
{
|
||||
var queue = async.queue(function (padId, callback) {
|
||||
convertPad(padId, function(err) {
|
||||
incrementPadStats();
|
||||
callback(err);
|
||||
});
|
||||
|
@ -82,8 +77,7 @@ async.series([
|
|||
queue.push(padIDs[i].ID);
|
||||
}
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
], function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
//write the groups
|
||||
|
@ -108,15 +102,13 @@ async.series([
|
|||
process.exit(0);
|
||||
});
|
||||
|
||||
function log(str)
|
||||
{
|
||||
function log(str) {
|
||||
console.log((Date.now() - startTime)/1000 + "\t" + str);
|
||||
}
|
||||
|
||||
var padsDone = 0;
|
||||
|
||||
function incrementPadStats()
|
||||
{
|
||||
function incrementPadStats() {
|
||||
padsDone++;
|
||||
|
||||
if(padsDone%100 == 0)
|
||||
|
@ -130,8 +122,7 @@ var proID2groupID = {};
|
|||
var proID2subdomain = {};
|
||||
var groups = {};
|
||||
|
||||
function convertPad(padId, callback)
|
||||
{
|
||||
function convertPad(padId, callback) {
|
||||
var changesets = [];
|
||||
var changesetsMeta = [];
|
||||
var chatMessages = [];
|
||||
|
@ -142,16 +133,13 @@ function convertPad(padId, callback)
|
|||
|
||||
async.series([
|
||||
//get all needed db values
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
async.parallel([
|
||||
//get the pad revisions
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
var sql = "SELECT * FROM `PAD_CHAT_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_CHAT_META` WHERE ID=?)";
|
||||
|
||||
etherpadDB.query(sql, [padId], function(err, results)
|
||||
{
|
||||
etherpadDB.query(sql, [padId], function(err, results) {
|
||||
if(!err)
|
||||
{
|
||||
try
|
||||
|
@ -168,12 +156,10 @@ function convertPad(padId, callback)
|
|||
});
|
||||
},
|
||||
//get the chat entries
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
var sql = "SELECT * FROM `PAD_REVS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVS_META` WHERE ID=?)";
|
||||
|
||||
etherpadDB.query(sql, [padId], function(err, results)
|
||||
{
|
||||
etherpadDB.query(sql, [padId], function(err, results) {
|
||||
if(!err)
|
||||
{
|
||||
try
|
||||
|
@ -190,12 +176,10 @@ function convertPad(padId, callback)
|
|||
});
|
||||
},
|
||||
//get the pad revisions meta data
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
var sql = "SELECT * FROM `PAD_REVMETA_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVMETA_META` WHERE ID=?)";
|
||||
|
||||
etherpadDB.query(sql, [padId], function(err, results)
|
||||
{
|
||||
etherpadDB.query(sql, [padId], function(err, results) {
|
||||
if(!err)
|
||||
{
|
||||
try
|
||||
|
@ -212,12 +196,10 @@ function convertPad(padId, callback)
|
|||
});
|
||||
},
|
||||
//get the attribute pool of this pad
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
var sql = "SELECT `JSON` FROM `PAD_APOOL` WHERE `ID` = ?";
|
||||
|
||||
etherpadDB.query(sql, [padId], function(err, results)
|
||||
{
|
||||
etherpadDB.query(sql, [padId], function(err, results) {
|
||||
if(!err)
|
||||
{
|
||||
try
|
||||
|
@ -230,12 +212,10 @@ function convertPad(padId, callback)
|
|||
});
|
||||
},
|
||||
//get the authors informations
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
var sql = "SELECT * FROM `PAD_AUTHORS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_AUTHORS_META` WHERE ID=?)";
|
||||
|
||||
etherpadDB.query(sql, [padId], function(err, results)
|
||||
{
|
||||
etherpadDB.query(sql, [padId], function(err, results) {
|
||||
if(!err)
|
||||
{
|
||||
try
|
||||
|
@ -252,12 +232,10 @@ function convertPad(padId, callback)
|
|||
});
|
||||
},
|
||||
//get the pad information
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
var sql = "SELECT JSON FROM `PAD_META` WHERE ID=?";
|
||||
|
||||
etherpadDB.query(sql, [padId], function(err, results)
|
||||
{
|
||||
etherpadDB.query(sql, [padId], function(err, results) {
|
||||
if(!err)
|
||||
{
|
||||
try
|
||||
|
@ -270,8 +248,7 @@ function convertPad(padId, callback)
|
|||
});
|
||||
},
|
||||
//get the subdomain
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
//skip if this is no proPad
|
||||
if(padId.indexOf("$") == -1)
|
||||
{
|
||||
|
@ -284,8 +261,7 @@ function convertPad(padId, callback)
|
|||
|
||||
var sql = "SELECT subDomain FROM pro_domains WHERE ID = ?";
|
||||
|
||||
etherpadDB.query(sql, [proID], function(err, results)
|
||||
{
|
||||
etherpadDB.query(sql, [proID], function(err, results) {
|
||||
if(!err)
|
||||
{
|
||||
subdomain = results[0].subDomain;
|
||||
|
@ -296,8 +272,7 @@ function convertPad(padId, callback)
|
|||
}
|
||||
], callback);
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
function(callback) {
|
||||
//saves all values that should be written to the database
|
||||
var values = {};
|
||||
|
||||
|
@ -425,8 +400,7 @@ function convertPad(padId, callback)
|
|||
* The offsets describes the length of a unit in the page, the data are
|
||||
* all values behind each other
|
||||
*/
|
||||
function parsePage(array, pageStart, offsets, data, json)
|
||||
{
|
||||
function parsePage(array, pageStart, offsets, data, json) {
|
||||
var start = 0;
|
||||
var lengths = offsets.split(",");
|
||||
|
||||
|
|
|
@ -25,8 +25,7 @@ require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) {
|
|||
}
|
||||
|
||||
log("initializing db");
|
||||
db.init(function(err)
|
||||
{
|
||||
db.init(function(err) {
|
||||
//there was an error while initializing the database, output it and stop
|
||||
if(err)
|
||||
{
|
||||
|
@ -71,8 +70,7 @@ require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) {
|
|||
});
|
||||
});
|
||||
|
||||
function log(str)
|
||||
{
|
||||
function log(str) {
|
||||
console.log((Date.now() - startTime)/1000 + "\t" + str);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,8 +101,7 @@ Example returns:
|
|||
}
|
||||
|
||||
*/
|
||||
exports.getAttributePool = async function(padID)
|
||||
{
|
||||
exports.getAttributePool = async function(padID) {
|
||||
let pad = await getPadSafe(padID, true);
|
||||
return { pool: pad.pool };
|
||||
}
|
||||
|
@ -120,8 +119,7 @@ Example returns:
|
|||
}
|
||||
|
||||
*/
|
||||
exports.getRevisionChangeset = async function(padID, rev)
|
||||
{
|
||||
exports.getRevisionChangeset = async function(padID, rev) {
|
||||
// try to parse the revision number
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
|
@ -155,8 +153,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {text:"Welcome Text"}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getText = async function(padID, rev)
|
||||
{
|
||||
exports.getText = async function(padID, rev) {
|
||||
// try to parse the revision number
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
|
@ -193,8 +190,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
{code: 1, message:"text too long", data: null}
|
||||
*/
|
||||
exports.setText = async function(padID, text)
|
||||
{
|
||||
exports.setText = async function(padID, text) {
|
||||
// text is required
|
||||
if (typeof text !== "string") {
|
||||
throw new customError("text is not a string", "apierror");
|
||||
|
@ -218,8 +214,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
{code: 1, message:"text too long", data: null}
|
||||
*/
|
||||
exports.appendText = async function(padID, text)
|
||||
{
|
||||
exports.appendText = async function(padID, text) {
|
||||
// text is required
|
||||
if (typeof text !== "string") {
|
||||
throw new customError("text is not a string", "apierror");
|
||||
|
@ -240,8 +235,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {text:"Welcome <strong>Text</strong>"}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getHTML = async function(padID, rev)
|
||||
{
|
||||
exports.getHTML = async function(padID, rev) {
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
}
|
||||
|
@ -273,8 +267,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.setHTML = async function(padID, html)
|
||||
{
|
||||
exports.setHTML = async function(padID, html) {
|
||||
// html string is required
|
||||
if (typeof html !== "string") {
|
||||
throw new customError("html is not a string", "apierror");
|
||||
|
@ -310,8 +303,7 @@ Example returns:
|
|||
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getChatHistory = async function(padID, start, end)
|
||||
{
|
||||
exports.getChatHistory = async function(padID, start, end) {
|
||||
if (start && end) {
|
||||
if (start < 0) {
|
||||
throw new customError("start is below zero", "apierror");
|
||||
|
@ -356,8 +348,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.appendChatMessage = async function(padID, text, authorID, time)
|
||||
{
|
||||
exports.appendChatMessage = async function(padID, text, authorID, time) {
|
||||
// text is required
|
||||
if (typeof text !== "string") {
|
||||
throw new customError("text is not a string", "apierror");
|
||||
|
@ -386,8 +377,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {revisions: 56}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getRevisionsCount = async function(padID)
|
||||
{
|
||||
exports.getRevisionsCount = async function(padID) {
|
||||
// get the pad
|
||||
let pad = await getPadSafe(padID, true);
|
||||
return { revisions: pad.getHeadRevisionNumber() };
|
||||
|
@ -401,8 +391,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {savedRevisions: 42}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getSavedRevisionsCount = async function(padID)
|
||||
{
|
||||
exports.getSavedRevisionsCount = async function(padID) {
|
||||
// get the pad
|
||||
let pad = await getPadSafe(padID, true);
|
||||
return { savedRevisions: pad.getSavedRevisionsNumber() };
|
||||
|
@ -416,8 +405,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {savedRevisions: [2, 42, 1337]}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.listSavedRevisions = async function(padID)
|
||||
{
|
||||
exports.listSavedRevisions = async function(padID) {
|
||||
// get the pad
|
||||
let pad = await getPadSafe(padID, true);
|
||||
return { savedRevisions: pad.getSavedRevisionsList() };
|
||||
|
@ -431,8 +419,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.saveRevision = async function(padID, rev)
|
||||
{
|
||||
exports.saveRevision = async function(padID, rev) {
|
||||
// check if rev is a number
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
|
@ -463,8 +450,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {lastEdited: 1340815946602}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getLastEdited = async function(padID)
|
||||
{
|
||||
exports.getLastEdited = async function(padID) {
|
||||
// get the pad
|
||||
let pad = await getPadSafe(padID, true);
|
||||
let lastEdited = await pad.getLastEdit();
|
||||
|
@ -479,8 +465,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"pad does already exist", data: null}
|
||||
*/
|
||||
exports.createPad = async function(padID, text)
|
||||
{
|
||||
exports.createPad = async function(padID, text) {
|
||||
if (padID) {
|
||||
// ensure there is no $ in the padID
|
||||
if (padID.indexOf("$") !== -1) {
|
||||
|
@ -505,8 +490,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.deletePad = async function(padID)
|
||||
{
|
||||
exports.deletePad = async function(padID) {
|
||||
let pad = await getPadSafe(padID, true);
|
||||
await pad.remove();
|
||||
}
|
||||
|
@ -519,8 +503,7 @@ exports.deletePad = async function(padID)
|
|||
{code:0, message:"ok", data:null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.restoreRevision = async function(padID, rev)
|
||||
{
|
||||
exports.restoreRevision = async function(padID, rev) {
|
||||
// check if rev is a number
|
||||
if (rev === undefined) {
|
||||
throw new customError("rev is not defined", "apierror");
|
||||
|
@ -588,8 +571,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {padID: destinationID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.copyPad = async function(sourceID, destinationID, force)
|
||||
{
|
||||
exports.copyPad = async function(sourceID, destinationID, force) {
|
||||
let pad = await getPadSafe(sourceID, true);
|
||||
await pad.copy(destinationID, force);
|
||||
}
|
||||
|
@ -603,8 +585,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {padID: destinationID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.copyPadWithoutHistory = async function(sourceID, destinationID, force)
|
||||
{
|
||||
exports.copyPadWithoutHistory = async function(sourceID, destinationID, force) {
|
||||
let pad = await getPadSafe(sourceID, true);
|
||||
await pad.copyPadWithoutHistory(destinationID, force);
|
||||
}
|
||||
|
@ -618,8 +599,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {padID: destinationID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.movePad = async function(sourceID, destinationID, force)
|
||||
{
|
||||
exports.movePad = async function(sourceID, destinationID, force) {
|
||||
let pad = await getPadSafe(sourceID, true);
|
||||
await pad.copy(destinationID, force);
|
||||
await pad.remove();
|
||||
|
@ -633,8 +613,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getReadOnlyID = async function(padID)
|
||||
{
|
||||
exports.getReadOnlyID = async function(padID) {
|
||||
// we don't need the pad object, but this function does all the security stuff for us
|
||||
await getPadSafe(padID, true);
|
||||
|
||||
|
@ -652,8 +631,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {padID: padID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getPadID = async function(roID)
|
||||
{
|
||||
exports.getPadID = async function(roID) {
|
||||
// get the PadId
|
||||
let padID = await readOnlyManager.getPadId(roID);
|
||||
if (padID === null) {
|
||||
|
@ -671,8 +649,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.setPublicStatus = async function(padID, publicStatus)
|
||||
{
|
||||
exports.setPublicStatus = async function(padID, publicStatus) {
|
||||
// ensure this is a group pad
|
||||
checkGroupPad(padID, "publicStatus");
|
||||
|
||||
|
@ -695,8 +672,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {publicStatus: true}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getPublicStatus = async function(padID)
|
||||
{
|
||||
exports.getPublicStatus = async function(padID) {
|
||||
// ensure this is a group pad
|
||||
checkGroupPad(padID, "publicStatus");
|
||||
|
||||
|
@ -713,8 +689,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {authorIDs : ["a.s8oes9dhwrvt0zif", "a.akf8finncvomlqva"]}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.listAuthorsOfPad = async function(padID)
|
||||
{
|
||||
exports.listAuthorsOfPad = async function(padID) {
|
||||
// get the pad
|
||||
let pad = await getPadSafe(padID, true);
|
||||
let authorIDs = pad.getAllAuthors();
|
||||
|
@ -757,8 +732,7 @@ Example returns:
|
|||
{"code":0,"message":"ok","data":null}
|
||||
{"code":4,"message":"no or wrong API Key","data":null}
|
||||
*/
|
||||
exports.checkToken = async function()
|
||||
{
|
||||
exports.checkToken = async function() {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -769,8 +743,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {chatHead: 42}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getChatHead = async function(padID)
|
||||
{
|
||||
exports.getChatHead = async function(padID) {
|
||||
// get the pad
|
||||
let pad = await getPadSafe(padID, true);
|
||||
return { chatHead: pad.chatHead };
|
||||
|
@ -843,14 +816,12 @@ exports.getStats = async function() {
|
|||
/******************************/
|
||||
|
||||
// checks if a number is an int
|
||||
function is_int(value)
|
||||
{
|
||||
function is_int(value) {
|
||||
return (parseFloat(value) == parseInt(value, 10)) && !isNaN(value)
|
||||
}
|
||||
|
||||
// gets a pad safe
|
||||
async function getPadSafe(padID, shouldExist, text)
|
||||
{
|
||||
async function getPadSafe(padID, shouldExist, text) {
|
||||
// check if padID is a string
|
||||
if (typeof padID !== "string") {
|
||||
throw new customError("padID is not a string", "apierror");
|
||||
|
@ -880,8 +851,7 @@ async function getPadSafe(padID, shouldExist, text)
|
|||
|
||||
// checks if a rev is a legal number
|
||||
// pre-condition is that `rev` is not undefined
|
||||
function checkValidRev(rev)
|
||||
{
|
||||
function checkValidRev(rev) {
|
||||
if (typeof rev !== "number") {
|
||||
rev = parseInt(rev, 10);
|
||||
}
|
||||
|
@ -905,8 +875,7 @@ function checkValidRev(rev)
|
|||
}
|
||||
|
||||
// checks if a padID is part of a group
|
||||
function checkGroupPad(padID, field)
|
||||
{
|
||||
function checkGroupPad(padID, field) {
|
||||
// ensure this is a group pad
|
||||
if (padID && padID.indexOf("$") === -1) {
|
||||
throw new customError(`You can only get/set the ${field} of pads that belong to a group`, "apierror");
|
||||
|
|
|
@ -38,8 +38,7 @@ exports.getColorPalette = function() {
|
|||
/**
|
||||
* Checks if the author exists
|
||||
*/
|
||||
exports.doesAuthorExist = async function(authorID)
|
||||
{
|
||||
exports.doesAuthorExist = async function(authorID) {
|
||||
let author = await db.get("globalAuthor:" + authorID);
|
||||
|
||||
return author !== null;
|
||||
|
@ -52,8 +51,7 @@ exports.doesAuthorExists = exports.doesAuthorExist;
|
|||
* Returns the AuthorID for a token.
|
||||
* @param {String} token The token
|
||||
*/
|
||||
exports.getAuthor4Token = async function(token)
|
||||
{
|
||||
exports.getAuthor4Token = async function(token) {
|
||||
let author = await mapAuthorWithDBKey("token2author", token);
|
||||
|
||||
// return only the sub value authorID
|
||||
|
@ -65,8 +63,7 @@ exports.getAuthor4Token = async function(token)
|
|||
* @param {String} token The mapper
|
||||
* @param {String} name The name of the author (optional)
|
||||
*/
|
||||
exports.createAuthorIfNotExistsFor = async function(authorMapper, name)
|
||||
{
|
||||
exports.createAuthorIfNotExistsFor = async function(authorMapper, name) {
|
||||
let author = await mapAuthorWithDBKey("mapper2author", authorMapper);
|
||||
|
||||
if (name) {
|
||||
|
@ -83,8 +80,7 @@ exports.createAuthorIfNotExistsFor = async function(authorMapper, name)
|
|||
* @param {String} mapperkey The database key name for this mapper
|
||||
* @param {String} mapper The mapper
|
||||
*/
|
||||
async function mapAuthorWithDBKey (mapperkey, mapper)
|
||||
{
|
||||
async function mapAuthorWithDBKey (mapperkey, mapper) {
|
||||
// try to map to an author
|
||||
let author = await db.get(mapperkey + ":" + mapper);
|
||||
|
||||
|
@ -111,8 +107,7 @@ async function mapAuthorWithDBKey (mapperkey, mapper)
|
|||
* Internal function that creates the database entry for an author
|
||||
* @param {String} name The name of the author
|
||||
*/
|
||||
exports.createAuthor = function(name)
|
||||
{
|
||||
exports.createAuthor = function(name) {
|
||||
// create the new author name
|
||||
let author = "a." + randomString(16);
|
||||
|
||||
|
@ -134,8 +129,7 @@ exports.createAuthor = function(name)
|
|||
* Returns the Author Obj of the author
|
||||
* @param {String} author The id of the author
|
||||
*/
|
||||
exports.getAuthor = function(author)
|
||||
{
|
||||
exports.getAuthor = function(author) {
|
||||
// NB: result is already a Promise
|
||||
return db.get("globalAuthor:" + author);
|
||||
}
|
||||
|
@ -144,8 +138,7 @@ exports.getAuthor = function(author)
|
|||
* Returns the color Id of the author
|
||||
* @param {String} author The id of the author
|
||||
*/
|
||||
exports.getAuthorColorId = function(author)
|
||||
{
|
||||
exports.getAuthorColorId = function(author) {
|
||||
return db.getSub("globalAuthor:" + author, ["colorId"]);
|
||||
}
|
||||
|
||||
|
@ -154,8 +147,7 @@ exports.getAuthorColorId = function(author)
|
|||
* @param {String} author The id of the author
|
||||
* @param {String} colorId The color id of the author
|
||||
*/
|
||||
exports.setAuthorColorId = function(author, colorId)
|
||||
{
|
||||
exports.setAuthorColorId = function(author, colorId) {
|
||||
return db.setSub("globalAuthor:" + author, ["colorId"], colorId);
|
||||
}
|
||||
|
||||
|
@ -163,8 +155,7 @@ exports.setAuthorColorId = function(author, colorId)
|
|||
* Returns the name of the author
|
||||
* @param {String} author The id of the author
|
||||
*/
|
||||
exports.getAuthorName = function(author)
|
||||
{
|
||||
exports.getAuthorName = function(author) {
|
||||
return db.getSub("globalAuthor:" + author, ["name"]);
|
||||
}
|
||||
|
||||
|
@ -173,8 +164,7 @@ exports.getAuthorName = function(author)
|
|||
* @param {String} author The id of the author
|
||||
* @param {String} name The name of the author
|
||||
*/
|
||||
exports.setAuthorName = function(author, name)
|
||||
{
|
||||
exports.setAuthorName = function(author, name) {
|
||||
return db.setSub("globalAuthor:" + author, ["name"], name);
|
||||
}
|
||||
|
||||
|
@ -182,8 +172,7 @@ exports.setAuthorName = function(author, name)
|
|||
* Returns an array of all pads this author contributed to
|
||||
* @param {String} author The id of the author
|
||||
*/
|
||||
exports.listPadsOfAuthor = async function(authorID)
|
||||
{
|
||||
exports.listPadsOfAuthor = async function(authorID) {
|
||||
/* There are two other places where this array is manipulated:
|
||||
* (1) When the author is added to a pad, the author object is also updated
|
||||
* (2) When a pad is deleted, each author of that pad is also updated
|
||||
|
@ -208,8 +197,7 @@ exports.listPadsOfAuthor = async function(authorID)
|
|||
* @param {String} author The id of the author
|
||||
* @param {String} padID The id of the pad the author contributes to
|
||||
*/
|
||||
exports.addPad = async function(authorID, padID)
|
||||
{
|
||||
exports.addPad = async function(authorID, padID) {
|
||||
// get the entry
|
||||
let author = await db.get("globalAuthor:" + authorID);
|
||||
|
||||
|
@ -236,8 +224,7 @@ exports.addPad = async function(authorID, padID)
|
|||
* @param {String} author The id of the author
|
||||
* @param {String} padID The id of the pad the author contributes to
|
||||
*/
|
||||
exports.removePad = async function(authorID, padID)
|
||||
{
|
||||
exports.removePad = async function(authorID, padID) {
|
||||
let author = await db.get("globalAuthor:" + authorID);
|
||||
|
||||
if (author === null) return;
|
||||
|
|
|
@ -24,8 +24,7 @@ var db = require("./DB");
|
|||
var padManager = require("./PadManager");
|
||||
var sessionManager = require("./SessionManager");
|
||||
|
||||
exports.listAllGroups = async function()
|
||||
{
|
||||
exports.listAllGroups = async function() {
|
||||
let groups = await db.get("groups");
|
||||
groups = groups || {};
|
||||
|
||||
|
@ -33,8 +32,7 @@ exports.listAllGroups = async function()
|
|||
return { groupIDs };
|
||||
}
|
||||
|
||||
exports.deleteGroup = async function(groupID)
|
||||
{
|
||||
exports.deleteGroup = async function(groupID) {
|
||||
let group = await db.get("group:" + groupID);
|
||||
|
||||
// ensure group exists
|
||||
|
@ -82,16 +80,14 @@ exports.deleteGroup = async function(groupID)
|
|||
await db.set("groups", newGroups);
|
||||
}
|
||||
|
||||
exports.doesGroupExist = async function(groupID)
|
||||
{
|
||||
exports.doesGroupExist = async function(groupID) {
|
||||
// try to get the group entry
|
||||
let group = await db.get("group:" + groupID);
|
||||
|
||||
return (group != null);
|
||||
}
|
||||
|
||||
exports.createGroup = async function()
|
||||
{
|
||||
exports.createGroup = async function() {
|
||||
// search for non existing groupID
|
||||
var groupID = "g." + randomString(16);
|
||||
|
||||
|
@ -111,8 +107,7 @@ exports.createGroup = async function()
|
|||
return { groupID };
|
||||
}
|
||||
|
||||
exports.createGroupIfNotExistsFor = async function(groupMapper)
|
||||
{
|
||||
exports.createGroupIfNotExistsFor = async function(groupMapper) {
|
||||
// ensure mapper is optional
|
||||
if (typeof groupMapper !== "string") {
|
||||
throw new customError("groupMapper is not a string", "apierror");
|
||||
|
@ -137,8 +132,7 @@ exports.createGroupIfNotExistsFor = async function(groupMapper)
|
|||
return result;
|
||||
}
|
||||
|
||||
exports.createGroupPad = async function(groupID, padName, text)
|
||||
{
|
||||
exports.createGroupPad = async function(groupID, padName, text) {
|
||||
// create the padID
|
||||
let padID = groupID + "$" + padName;
|
||||
|
||||
|
@ -166,8 +160,7 @@ exports.createGroupPad = async function(groupID, padName, text)
|
|||
return { padID };
|
||||
}
|
||||
|
||||
exports.listPads = async function(groupID)
|
||||
{
|
||||
exports.listPads = async function(groupID) {
|
||||
let exists = await exports.doesGroupExist(groupID);
|
||||
|
||||
// ensure the group exists
|
||||
|
|
|
@ -109,8 +109,7 @@ let padList = {
|
|||
* @param id A String with the id of the pad
|
||||
* @param {Function} callback
|
||||
*/
|
||||
exports.getPad = async function(id, text)
|
||||
{
|
||||
exports.getPad = async function(id, text) {
|
||||
// check if this is a valid padId
|
||||
if (!exports.isValidPadId(id)) {
|
||||
throw new customError(id + " is not a valid padId", "apierror");
|
||||
|
@ -147,16 +146,14 @@ exports.getPad = async function(id, text)
|
|||
return pad;
|
||||
}
|
||||
|
||||
exports.listAllPads = async function()
|
||||
{
|
||||
exports.listAllPads = async function() {
|
||||
let padIDs = await padList.getPads();
|
||||
|
||||
return { padIDs };
|
||||
}
|
||||
|
||||
// checks if a pad exists
|
||||
exports.doesPadExist = async function(padId)
|
||||
{
|
||||
exports.doesPadExist = async function(padId) {
|
||||
let value = await db.get("pad:" + padId);
|
||||
|
||||
return (value != null && value.atext);
|
||||
|
@ -192,8 +189,7 @@ exports.sanitizePadId = async function sanitizePadId(padId) {
|
|||
return padId;
|
||||
}
|
||||
|
||||
exports.isValidPadId = function(padId)
|
||||
{
|
||||
exports.isValidPadId = function(padId) {
|
||||
return /^(g.[a-zA-Z0-9]{16}\$)?[^$]{1,50}$/.test(padId);
|
||||
}
|
||||
|
||||
|
@ -208,7 +204,6 @@ exports.removePad = async (padId) => {
|
|||
}
|
||||
|
||||
// removes a pad from the cache
|
||||
exports.unloadPad = function(padId)
|
||||
{
|
||||
exports.unloadPad = function(padId) {
|
||||
globalPads.remove(padId);
|
||||
}
|
||||
|
|
|
@ -27,8 +27,7 @@ var randomString = require("../utils/randomstring");
|
|||
* checks if the id pattern matches a read-only pad id
|
||||
* @param {String} the pad's id
|
||||
*/
|
||||
exports.isReadOnlyId = function(id)
|
||||
{
|
||||
exports.isReadOnlyId = function(id) {
|
||||
return id.indexOf("r.") === 0;
|
||||
}
|
||||
|
||||
|
@ -36,8 +35,7 @@ exports.isReadOnlyId = function(id)
|
|||
* returns a read only id for a pad
|
||||
* @param {String} padId the id of the pad
|
||||
*/
|
||||
exports.getReadOnlyId = async function (padId)
|
||||
{
|
||||
exports.getReadOnlyId = async function (padId) {
|
||||
// check if there is a pad2readonly entry
|
||||
let readOnlyId = await db.get("pad2readonly:" + padId);
|
||||
|
||||
|
@ -55,8 +53,7 @@ exports.getReadOnlyId = async function (padId)
|
|||
* returns the padId for a read only id
|
||||
* @param {String} readOnlyId read only id
|
||||
*/
|
||||
exports.getPadId = function(readOnlyId)
|
||||
{
|
||||
exports.getPadId = function(readOnlyId) {
|
||||
return db.get("readonly2pad:" + readOnlyId);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,8 +47,7 @@ const DENY = Object.freeze({accessStatus: 'deny'});
|
|||
* WARNING: Tokens and session IDs MUST be kept secret, otherwise users will be able to impersonate
|
||||
* each other (which might allow them to gain privileges).
|
||||
*/
|
||||
exports.checkAccess = async function(padID, sessionCookie, token, userSettings)
|
||||
{
|
||||
exports.checkAccess = async function(padID, sessionCookie, token, userSettings) {
|
||||
if (!padID) {
|
||||
authLogger.debug('access denied: missing padID');
|
||||
return DENY;
|
||||
|
|
|
@ -78,8 +78,7 @@ exports.findAuthorID = async (groupID, sessionCookie) => {
|
|||
return sessionInfo.authorID;
|
||||
};
|
||||
|
||||
exports.doesSessionExist = async function(sessionID)
|
||||
{
|
||||
exports.doesSessionExist = async function(sessionID) {
|
||||
//check if the database entry of this session exists
|
||||
let session = await db.get("session:" + sessionID);
|
||||
return (session !== null);
|
||||
|
@ -88,8 +87,7 @@ exports.doesSessionExist = async function(sessionID)
|
|||
/**
|
||||
* Creates a new session between an author and a group
|
||||
*/
|
||||
exports.createSession = async function(groupID, authorID, validUntil)
|
||||
{
|
||||
exports.createSession = async function(groupID, authorID, validUntil) {
|
||||
// check if the group exists
|
||||
let groupExists = await groupManager.doesGroupExist(groupID);
|
||||
if (!groupExists) {
|
||||
|
@ -172,8 +170,7 @@ exports.createSession = async function(groupID, authorID, validUntil)
|
|||
return { sessionID };
|
||||
}
|
||||
|
||||
exports.getSessionInfo = async function(sessionID)
|
||||
{
|
||||
exports.getSessionInfo = async function(sessionID) {
|
||||
// check if the database entry of this session exists
|
||||
let session = await db.get("session:" + sessionID);
|
||||
|
||||
|
@ -189,8 +186,7 @@ exports.getSessionInfo = async function(sessionID)
|
|||
/**
|
||||
* Deletes a session
|
||||
*/
|
||||
exports.deleteSession = async function(sessionID)
|
||||
{
|
||||
exports.deleteSession = async function(sessionID) {
|
||||
// ensure that the session exists
|
||||
let session = await db.get("session:" + sessionID);
|
||||
if (session == null) {
|
||||
|
@ -221,8 +217,7 @@ exports.deleteSession = async function(sessionID)
|
|||
}
|
||||
}
|
||||
|
||||
exports.listSessionsOfGroup = async function(groupID)
|
||||
{
|
||||
exports.listSessionsOfGroup = async function(groupID) {
|
||||
// check that the group exists
|
||||
let exists = await groupManager.doesGroupExist(groupID);
|
||||
if (!exists) {
|
||||
|
@ -233,8 +228,7 @@ exports.listSessionsOfGroup = async function(groupID)
|
|||
return sessions;
|
||||
}
|
||||
|
||||
exports.listSessionsOfAuthor = async function(authorID)
|
||||
{
|
||||
exports.listSessionsOfAuthor = async function(authorID) {
|
||||
// check that the author exists
|
||||
let exists = await authorManager.doesAuthorExist(authorID)
|
||||
if (!exists) {
|
||||
|
@ -247,8 +241,7 @@ exports.listSessionsOfAuthor = async function(authorID)
|
|||
|
||||
// this function is basically the code listSessionsOfAuthor and listSessionsOfGroup has in common
|
||||
// required to return null rather than an empty object if there are none
|
||||
async function listSessionsWithDBKey(dbkey)
|
||||
{
|
||||
async function listSessionsWithDBKey(dbkey) {
|
||||
// get the group2sessions entry
|
||||
let sessionObject = await db.get(dbkey);
|
||||
let sessions = sessionObject ? sessionObject.sessionIDs : null;
|
||||
|
@ -272,7 +265,6 @@ async function listSessionsWithDBKey(dbkey)
|
|||
}
|
||||
|
||||
// checks if a number is an int
|
||||
function is_int(value)
|
||||
{
|
||||
function is_int(value) {
|
||||
return (parseFloat(value) == parseInt(value)) && !isNaN(value);
|
||||
}
|
||||
|
|
|
@ -158,8 +158,7 @@ exports.version = version;
|
|||
* @req express request object
|
||||
* @res express response object
|
||||
*/
|
||||
exports.handle = async function(apiVersion, functionName, fields, req, res)
|
||||
{
|
||||
exports.handle = async function(apiVersion, functionName, fields, req, res) {
|
||||
// say goodbye if this is an unknown API version
|
||||
if (!(apiVersion in version)) {
|
||||
throw new createHTTPError.NotFound('no such api version');
|
||||
|
|
|
@ -49,8 +49,7 @@ const tempDirectory = os.tmpdir();
|
|||
/**
|
||||
* do a requested export
|
||||
*/
|
||||
async function doExport(req, res, padId, readOnlyId, type)
|
||||
{
|
||||
async function doExport(req, res, padId, readOnlyId, type) {
|
||||
// avoid naming the read-only file as the original pad's id
|
||||
var fileName = readOnlyId ? readOnlyId : padId;
|
||||
|
||||
|
@ -131,8 +130,7 @@ async function doExport(req, res, padId, readOnlyId, type)
|
|||
}
|
||||
}
|
||||
|
||||
exports.doExport = function(req, res, padId, readOnlyId, type)
|
||||
{
|
||||
exports.doExport = function(req, res, padId, readOnlyId, type) {
|
||||
doExport(req, res, padId, readOnlyId, type).catch(err => {
|
||||
if (err !== "stop") {
|
||||
throw err;
|
||||
|
|
|
@ -57,8 +57,7 @@ const tmpDirectory = os.tmpdir();
|
|||
/**
|
||||
* do a requested import
|
||||
*/
|
||||
async function doImport(req, res, padId)
|
||||
{
|
||||
async function doImport(req, res, padId) {
|
||||
var apiLogger = log4js.getLogger("ImportHandler");
|
||||
|
||||
// pipe to a file
|
||||
|
@ -265,8 +264,7 @@ async function doImport(req, res, padId)
|
|||
}
|
||||
}
|
||||
|
||||
exports.doImport = function (req, res, padId)
|
||||
{
|
||||
exports.doImport = function (req, res, padId) {
|
||||
/**
|
||||
* NB: abuse the 'req' object by storing an additional
|
||||
* 'directDatabaseAccess' property on it so that it can
|
||||
|
|
|
@ -80,8 +80,7 @@ let socketio;
|
|||
* This Method is called by server.js to tell the message handler on which socket it should send
|
||||
* @param socket_io The Socket
|
||||
*/
|
||||
exports.setSocketIO = function(socket_io)
|
||||
{
|
||||
exports.setSocketIO = function(socket_io) {
|
||||
socketio=socket_io;
|
||||
}
|
||||
|
||||
|
@ -99,8 +98,7 @@ exports.handleConnect = (socket) => {
|
|||
/**
|
||||
* Kicks all sessions from a pad
|
||||
*/
|
||||
exports.kickSessionsFromPad = function(padID)
|
||||
{
|
||||
exports.kickSessionsFromPad = function(padID) {
|
||||
if(typeof socketio.sockets['clients'] !== 'function')
|
||||
return;
|
||||
|
||||
|
@ -355,8 +353,7 @@ async function handleChatMessage(socket, message) {
|
|||
* @param text the text of the chat message
|
||||
* @param padId the padId to send the chat message to
|
||||
*/
|
||||
exports.sendChatMessageToPadClients = async function(time, userId, text, padId)
|
||||
{
|
||||
exports.sendChatMessageToPadClients = async function(time, userId, text, padId) {
|
||||
// get the pad
|
||||
let pad = await padManager.getPad(padId);
|
||||
|
||||
|
@ -688,8 +685,7 @@ async function handleUserChanges(socket, message) {
|
|||
stopWatch.end();
|
||||
}
|
||||
|
||||
exports.updatePadClients = async function(pad)
|
||||
{
|
||||
exports.updatePadClients = async function(pad) {
|
||||
// skip this if no-one is on this pad
|
||||
const roomSockets = _getRoomSockets(pad.id);
|
||||
if (roomSockets.length === 0) return;
|
||||
|
@ -837,8 +833,7 @@ async function handleSwitchToPad(socket, message, _authorID) {
|
|||
}
|
||||
|
||||
// Creates/replaces the auth object in the given session info.
|
||||
function createSessionInfoAuth(sessionInfo, message)
|
||||
{
|
||||
function createSessionInfoAuth(sessionInfo, message) {
|
||||
// Remember this information since we won't
|
||||
// have the cookie in further socket.io messages.
|
||||
// This information will be used to check if
|
||||
|
@ -1250,8 +1245,7 @@ async function handleChangesetRequest(socket, message) {
|
|||
* Tries to rebuild the getChangestInfo function of the original Etherpad
|
||||
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L144
|
||||
*/
|
||||
async function getChangesetInfo(padId, startNum, endNum, granularity)
|
||||
{
|
||||
async function getChangesetInfo(padId, startNum, endNum, granularity) {
|
||||
let pad = await padManager.getPad(padId);
|
||||
let head_revision = pad.getHeadRevisionNumber();
|
||||
|
||||
|
@ -1344,8 +1338,7 @@ async function getChangesetInfo(padId, startNum, endNum, granularity)
|
|||
* Tries to rebuild the getPadLines function of the original Etherpad
|
||||
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L263
|
||||
*/
|
||||
async function getPadLines(padId, revNum)
|
||||
{
|
||||
async function getPadLines(padId, revNum) {
|
||||
let pad = await padManager.getPad(padId);
|
||||
|
||||
// get the atext
|
||||
|
@ -1367,8 +1360,7 @@ async function getPadLines(padId, revNum)
|
|||
* Tries to rebuild the composePadChangeset function of the original Etherpad
|
||||
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L241
|
||||
*/
|
||||
async function composePadChangesets (padId, startNum, endNum)
|
||||
{
|
||||
async function composePadChangesets (padId, startNum, endNum) {
|
||||
let pad = await padManager.getPad(padId);
|
||||
|
||||
// fetch all changesets we need
|
||||
|
|
|
@ -37,8 +37,7 @@ var socket;
|
|||
/**
|
||||
* adds a component
|
||||
*/
|
||||
exports.addComponent = function(moduleName, module)
|
||||
{
|
||||
exports.addComponent = function(moduleName, module) {
|
||||
// save the component
|
||||
components[moduleName] = module;
|
||||
|
||||
|
@ -53,8 +52,7 @@ exports.setSocketIO = function(_socket) {
|
|||
// save this socket internaly
|
||||
socket = _socket;
|
||||
|
||||
socket.sockets.on('connection', function(client)
|
||||
{
|
||||
socket.sockets.on('connection', function(client) {
|
||||
// wrap the original send function to log the messages
|
||||
client._send = client.send;
|
||||
client.send = function(message) {
|
||||
|
|
|
@ -12,24 +12,20 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
})
|
||||
|
||||
//serve index.html under /
|
||||
args.app.get('/', function(req, res)
|
||||
{
|
||||
args.app.get('/', function(req, res) {
|
||||
res.send(eejs.require('ep_etherpad-lite/templates/index.html', {req}));
|
||||
});
|
||||
|
||||
//serve javascript.html
|
||||
args.app.get('/javascript', function(req, res)
|
||||
{
|
||||
args.app.get('/javascript', function(req, res) {
|
||||
res.send(eejs.require('ep_etherpad-lite/templates/javascript.html', {req}));
|
||||
});
|
||||
|
||||
|
||||
//serve robots.txt
|
||||
args.app.get('/robots.txt', function(req, res)
|
||||
{
|
||||
args.app.get('/robots.txt', function(req, res) {
|
||||
var filePath = path.join(settings.root, "src", "static", "skins", settings.skinName, "robots.txt");
|
||||
res.sendFile(filePath, function(err)
|
||||
{
|
||||
res.sendFile(filePath, function(err) {
|
||||
//there is no custom robots.txt, send the default robots.txt which dissallows all
|
||||
if(err)
|
||||
{
|
||||
|
@ -40,8 +36,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
});
|
||||
|
||||
//serve pad.html under /p
|
||||
args.app.get('/p/:pad', function(req, res, next)
|
||||
{
|
||||
args.app.get('/p/:pad', function(req, res, next) {
|
||||
// The below might break for pads being rewritten
|
||||
const isReadOnly =
|
||||
req.url.indexOf("/p/r.") === 0 || !webaccess.userCanModify(req.params.pad, req);
|
||||
|
@ -59,8 +54,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
});
|
||||
|
||||
//serve timeslider.html under /p/$padname/timeslider
|
||||
args.app.get('/p/:pad/timeslider', function(req, res, next)
|
||||
{
|
||||
args.app.get('/p/:pad/timeslider', function(req, res, next) {
|
||||
hooks.callAll("padInitToolbar", {
|
||||
toolbar: toolbar
|
||||
});
|
||||
|
@ -72,12 +66,10 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
});
|
||||
|
||||
//serve favicon.ico from all path levels except as a pad name
|
||||
args.app.get( /\/favicon.ico$/, function(req, res)
|
||||
{
|
||||
args.app.get( /\/favicon.ico$/, function(req, res) {
|
||||
var filePath = path.join(settings.root, "src", "static", "skins", settings.skinName, "favicon.ico");
|
||||
|
||||
res.sendFile(filePath, function(err)
|
||||
{
|
||||
res.sendFile(filePath, function(err) {
|
||||
//there is no custom favicon, send the default favicon
|
||||
if(err)
|
||||
{
|
||||
|
|
|
@ -30,27 +30,23 @@ if(os.type().indexOf("Windows") > -1)
|
|||
{
|
||||
var stdoutBuffer = "";
|
||||
|
||||
doConvertTask = function(task, callback)
|
||||
{
|
||||
doConvertTask = function(task, callback) {
|
||||
//span an abiword process to perform the conversion
|
||||
var abiword = spawn(settings.abiword, ["--to=" + task.destFile, task.srcFile]);
|
||||
|
||||
//delegate the processing of stdout to another function
|
||||
abiword.stdout.on('data', function (data)
|
||||
{
|
||||
abiword.stdout.on('data', function (data) {
|
||||
//add data to buffer
|
||||
stdoutBuffer+=data.toString();
|
||||
});
|
||||
|
||||
//append error messages to the buffer
|
||||
abiword.stderr.on('data', function (data)
|
||||
{
|
||||
abiword.stderr.on('data', function (data) {
|
||||
stdoutBuffer += data.toString();
|
||||
});
|
||||
|
||||
//throw exceptions if abiword is dieing
|
||||
abiword.on('exit', function (code)
|
||||
{
|
||||
abiword.on('exit', function (code) {
|
||||
if(code != 0) {
|
||||
return callback(`Abiword died with exit code ${code}`);
|
||||
}
|
||||
|
@ -64,8 +60,7 @@ if(os.type().indexOf("Windows") > -1)
|
|||
});
|
||||
};
|
||||
|
||||
exports.convertFile = function(srcFile, destFile, type, callback)
|
||||
{
|
||||
exports.convertFile = function(srcFile, destFile, type, callback) {
|
||||
doConvertTask({"srcFile": srcFile, "destFile": destFile, "type": type}, callback);
|
||||
};
|
||||
}
|
||||
|
@ -82,21 +77,18 @@ else
|
|||
var firstPrompt = true;
|
||||
|
||||
//append error messages to the buffer
|
||||
abiword.stderr.on('data', function (data)
|
||||
{
|
||||
abiword.stderr.on('data', function (data) {
|
||||
stdoutBuffer += data.toString();
|
||||
});
|
||||
|
||||
//abiword died, let's restart abiword and return an error with the callback
|
||||
abiword.on('exit', function (code)
|
||||
{
|
||||
abiword.on('exit', function (code) {
|
||||
spawnAbiword();
|
||||
stdoutCallback(`Abiword died with exit code ${code}`);
|
||||
});
|
||||
|
||||
//delegate the processing of stdout to a other function
|
||||
abiword.stdout.on('data',function (data)
|
||||
{
|
||||
abiword.stdout.on('data',function (data) {
|
||||
//add data to buffer
|
||||
stdoutBuffer+=data.toString();
|
||||
|
||||
|
@ -123,12 +115,10 @@ else
|
|||
};
|
||||
spawnAbiword();
|
||||
|
||||
doConvertTask = function(task, callback)
|
||||
{
|
||||
doConvertTask = function(task, callback) {
|
||||
abiword.stdin.write("convert " + task.srcFile + " " + task.destFile + " " + task.type + "\n");
|
||||
//create a callback that calls the task callback and the caller callback
|
||||
stdoutCallback = function (err)
|
||||
{
|
||||
stdoutCallback = function (err) {
|
||||
callback();
|
||||
console.log("queue continue");
|
||||
try{
|
||||
|
@ -141,8 +131,7 @@ else
|
|||
|
||||
//Queue with the converts we have to do
|
||||
var queue = async.queue(doConvertTask, 1);
|
||||
exports.convertFile = function(srcFile, destFile, type, callback)
|
||||
{
|
||||
exports.convertFile = function(srcFile, destFile, type, callback) {
|
||||
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ var eejs = require('ep_etherpad-lite/node/eejs');
|
|||
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
||||
var _encodeWhitespace = require('./ExportHelper')._encodeWhitespace;
|
||||
|
||||
async function getPadHTML(pad, revNum)
|
||||
{
|
||||
async function getPadHTML(pad, revNum) {
|
||||
let atext = pad.atext;
|
||||
|
||||
// fetch revision atext
|
||||
|
@ -39,8 +38,7 @@ async function getPadHTML(pad, revNum)
|
|||
exports.getPadHTML = getPadHTML;
|
||||
exports.getHTMLFromAtext = getHTMLFromAtext;
|
||||
|
||||
async function getHTMLFromAtext(pad, atext, authorColors)
|
||||
{
|
||||
async function getHTMLFromAtext(pad, atext, authorColors) {
|
||||
var apool = pad.apool();
|
||||
var textLines = atext.text.slice(0, -1).split('\n');
|
||||
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
||||
|
@ -110,8 +108,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
|
||||
// iterates over all props(h1,h2,strong,...), checks if it is used in
|
||||
// this pad, and if yes puts its attrib id->props value into anumMap
|
||||
props.forEach(function (propName, i)
|
||||
{
|
||||
props.forEach(function (propName, i) {
|
||||
var attrib = [propName, true];
|
||||
if (_.isArray(propName)) {
|
||||
// propName can be in the form of ['color', 'red'],
|
||||
|
@ -125,8 +122,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
}
|
||||
});
|
||||
|
||||
function getLineHTML(text, attribs)
|
||||
{
|
||||
function getLineHTML(text, attribs) {
|
||||
// Use order of tags (b/i/u) as order of nesting, for simplicity
|
||||
// and decent nesting. For example,
|
||||
// <b>Just bold<b> <b><i>Bold and italics</i></b> <i>Just italics</i>
|
||||
|
@ -166,8 +162,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
return _.isArray(property);
|
||||
}
|
||||
|
||||
function emitOpenTag(i)
|
||||
{
|
||||
function emitOpenTag(i) {
|
||||
openTags.unshift(i);
|
||||
var spanClass = getSpanClassFor(i);
|
||||
|
||||
|
@ -183,8 +178,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
}
|
||||
|
||||
// this closes an open tag and removes its reference from openTags
|
||||
function emitCloseTag(i)
|
||||
{
|
||||
function emitCloseTag(i) {
|
||||
openTags.shift();
|
||||
var spanClass = getSpanClassFor(i);
|
||||
var spanWithData = isSpanWithData(i);
|
||||
|
@ -202,8 +196,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
|
||||
var idx = 0;
|
||||
|
||||
function processNextChars(numChars)
|
||||
{
|
||||
function processNextChars(numChars) {
|
||||
if (numChars <= 0)
|
||||
{
|
||||
return;
|
||||
|
@ -220,8 +213,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
var usedAttribs = [];
|
||||
|
||||
// mark all attribs as used
|
||||
Changeset.eachAttribNumber(o.attribs, function (a)
|
||||
{
|
||||
Changeset.eachAttribNumber(o.attribs, function (a) {
|
||||
if (a in anumMap)
|
||||
{
|
||||
usedAttribs.push(anumMap[a]); // i = 0 => bold, etc.
|
||||
|
@ -280,8 +272,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
} // end processNextChars
|
||||
if (urls)
|
||||
{
|
||||
urls.forEach(function (urlData)
|
||||
{
|
||||
urls.forEach(function (urlData) {
|
||||
var startIndex = urlData[0];
|
||||
var url = urlData[1];
|
||||
var urlLength = url.length;
|
||||
|
@ -341,8 +332,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
//To create list parent elements
|
||||
if ((!prevLine || prevLine.listLevel !== line.listLevel) || (prevLine && line.listTypeName !== prevLine.listTypeName))
|
||||
{
|
||||
var exists = _.find(openLists, function (item)
|
||||
{
|
||||
var exists = _.find(openLists, function (item) {
|
||||
return (item.level === line.listLevel && item.type === line.listTypeName);
|
||||
});
|
||||
if (!exists) {
|
||||
|
@ -445,8 +435,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
|
||||
for (var diff = nextLevel; diff < line.listLevel; diff++)
|
||||
{
|
||||
openLists = openLists.filter(function(el)
|
||||
{
|
||||
openLists = openLists.filter(function(el) {
|
||||
return el.level !== diff && el.type !== line.listTypeName;
|
||||
});
|
||||
|
||||
|
@ -485,8 +474,7 @@ async function getHTMLFromAtext(pad, atext, authorColors)
|
|||
return pieces.join('');
|
||||
}
|
||||
|
||||
exports.getPadHTMLDocument = async function (padId, revNum)
|
||||
{
|
||||
exports.getPadHTMLDocument = async function (padId, revNum) {
|
||||
let pad = await padManager.getPad(padId);
|
||||
|
||||
// Include some Styles into the Head for Export
|
||||
|
@ -518,8 +506,7 @@ var _REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|g
|
|||
// returns null if no URLs, or [[startIndex1, url1], [startIndex2, url2], ...]
|
||||
|
||||
|
||||
function _findURLs(text)
|
||||
{
|
||||
function _findURLs(text) {
|
||||
_REGEX_URL.lastIndex = 0;
|
||||
var urls = null;
|
||||
var execResult;
|
||||
|
|
|
@ -23,8 +23,7 @@ var padManager = require("../db/PadManager");
|
|||
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
||||
|
||||
// This is slightly different than the HTML method as it passes the output to getTXTFromAText
|
||||
var getPadTXT = async function(pad, revNum)
|
||||
{
|
||||
var getPadTXT = async function(pad, revNum) {
|
||||
let atext = pad.atext;
|
||||
|
||||
if (revNum != undefined) {
|
||||
|
@ -38,8 +37,7 @@ var getPadTXT = async function(pad, revNum)
|
|||
|
||||
// This is different than the functionality provided in ExportHtml as it provides formatting
|
||||
// functionality that is designed specifically for TXT exports
|
||||
function getTXTFromAtext(pad, atext, authorColors)
|
||||
{
|
||||
function getTXTFromAtext(pad, atext, authorColors) {
|
||||
var apool = pad.apool();
|
||||
var textLines = atext.text.slice(0, -1).split('\n');
|
||||
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
||||
|
@ -259,8 +257,7 @@ function getTXTFromAtext(pad, atext, authorColors)
|
|||
|
||||
exports.getTXTFromAtext = getTXTFromAtext;
|
||||
|
||||
exports.getPadTXTDocument = async function(padId, revNum)
|
||||
{
|
||||
exports.getPadTXTDocument = async function(padId, revNum) {
|
||||
let pad = await padManager.getPad(padId);
|
||||
return getPadTXT(pad, revNum);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@ var log4js = require('log4js');
|
|||
const db = require("../db/DB");
|
||||
const hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||
|
||||
exports.setPadRaw = function(padId, records)
|
||||
{
|
||||
exports.setPadRaw = function(padId, records) {
|
||||
records = JSON.parse(records);
|
||||
|
||||
Object.keys(records).forEach(async function(key) {
|
||||
|
|
|
@ -145,8 +145,7 @@ function requestURIs(locations, method, headers, callback) {
|
|||
* @param req the Express request
|
||||
* @param res the Express response
|
||||
*/
|
||||
function minify(req, res)
|
||||
{
|
||||
function minify(req, res) {
|
||||
var filename = req.params['filename'];
|
||||
|
||||
// No relative paths, especially if they may go up the file hierarchy.
|
||||
|
@ -318,22 +317,18 @@ function lastModifiedDateOfEverything(callback) {
|
|||
var folders2check = [ROOT_DIR + 'js/', ROOT_DIR + 'css/'];
|
||||
var latestModification = 0;
|
||||
//go trough this two folders
|
||||
async.forEach(folders2check, function(path, callback)
|
||||
{
|
||||
async.forEach(folders2check, function(path, callback) {
|
||||
//read the files in the folder
|
||||
fs.readdir(path, function(err, files)
|
||||
{
|
||||
fs.readdir(path, function(err, files) {
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//we wanna check the directory itself for changes too
|
||||
files.push(".");
|
||||
|
||||
//go trough all files in this folder
|
||||
async.forEach(files, function(filename, callback)
|
||||
{
|
||||
async.forEach(files, function(filename, callback) {
|
||||
//get the stat data of this file
|
||||
fs.stat(path + "/" + filename, function(err, stats)
|
||||
{
|
||||
fs.stat(path + "/" + filename, function(err, stats) {
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
//get the modification time
|
||||
|
|
|
@ -7,13 +7,11 @@ var Terser = require("terser");
|
|||
var path = require('path');
|
||||
var Threads = require('threads')
|
||||
|
||||
function compressJS(content)
|
||||
{
|
||||
function compressJS(content) {
|
||||
return Terser.minify(content);
|
||||
}
|
||||
|
||||
function compressCSS(filename, ROOT_DIR)
|
||||
{
|
||||
function compressCSS(filename, ROOT_DIR) {
|
||||
return new Promise((res, rej) => {
|
||||
try {
|
||||
const absPath = path.join(ROOT_DIR, filename);
|
||||
|
|
|
@ -381,8 +381,7 @@ exports.commitRateLimiting = {
|
|||
exports.importMaxFileSize = 50 * 1024 * 1024;
|
||||
|
||||
// checks if abiword is avaiable
|
||||
exports.abiwordAvailable = function()
|
||||
{
|
||||
exports.abiwordAvailable = function() {
|
||||
if (exports.abiword != null) {
|
||||
return os.type().indexOf("Windows") != -1 ? "withoutPDF" : "yes";
|
||||
} else {
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
*/
|
||||
var crypto = require('crypto');
|
||||
|
||||
var randomString = function(len)
|
||||
{
|
||||
var randomString = function(len) {
|
||||
return crypto.randomBytes(len).toString('hex')
|
||||
};
|
||||
|
||||
|
|
|
@ -29,8 +29,7 @@ var lineAttributes = [lineMarkerAttribute,'list'];
|
|||
- a SkipList `lines` containing the text lines of the document.
|
||||
*/
|
||||
|
||||
var AttributeManager = function(rep, applyChangesetCallback)
|
||||
{
|
||||
var AttributeManager = function(rep, applyChangesetCallback) {
|
||||
this.rep = rep;
|
||||
this.applyChangesetCallback = applyChangesetCallback;
|
||||
this.author = '';
|
||||
|
@ -62,8 +61,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
@param end [row, col] tuple pointing to the end of the range
|
||||
@param attribs: an array of attributes
|
||||
*/
|
||||
setAttributesOnRange: function(start, end, attribs)
|
||||
{
|
||||
setAttributesOnRange: function(start, end, attribs) {
|
||||
// instead of applying the attributes to the whole range at once, we need to apply them
|
||||
// line by line, to be able to disregard the "*" used as line marker. For more details,
|
||||
// see https://github.com/ether/etherpad-lite/issues/2772
|
||||
|
@ -87,8 +85,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
return this.applyChangeset(allChangesets);
|
||||
},
|
||||
|
||||
_findRowRange: function(row, start, end)
|
||||
{
|
||||
_findRowRange: function(row, start, end) {
|
||||
var startCol, endCol;
|
||||
|
||||
var startLineOffset = this.rep.lines.offsetOfIndex(row);
|
||||
|
@ -119,8 +116,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
@param endCol column where range ends
|
||||
@param attribs: an array of attributes
|
||||
*/
|
||||
_setAttributesOnRangeByLine: function(row, startCol, endCol, attribs)
|
||||
{
|
||||
_setAttributesOnRangeByLine: function(row, startCol, endCol, attribs) {
|
||||
var builder = Changeset.builder(this.rep.lines.totalWidth());
|
||||
ChangesetUtils.buildKeepToStartOfRange(this.rep, builder, [row, startCol]);
|
||||
ChangesetUtils.buildKeepRange(this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
|
||||
|
@ -209,8 +205,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
[attributeName, 'true']
|
||||
], rep.apool);
|
||||
var withItRegex = new RegExp(withIt.replace(/\*/g, '\\*') + "(\\*|$)");
|
||||
function hasIt(attribs)
|
||||
{
|
||||
function hasIt(attribs) {
|
||||
return withItRegex.test(attribs);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
exports.buildRemoveRange = function(rep, builder, start, end)
|
||||
{
|
||||
exports.buildRemoveRange = function(rep, builder, start, end) {
|
||||
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
|
||||
var endLineOffset = rep.lines.offsetOfIndex(end[0]);
|
||||
|
||||
|
@ -34,8 +33,7 @@ exports.buildRemoveRange = function(rep, builder, start, end)
|
|||
}
|
||||
}
|
||||
|
||||
exports.buildKeepRange = function(rep, builder, start, end, attribs, pool)
|
||||
{
|
||||
exports.buildKeepRange = function(rep, builder, start, end, attribs, pool) {
|
||||
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
|
||||
var endLineOffset = rep.lines.offsetOfIndex(end[0]);
|
||||
|
||||
|
@ -50,8 +48,7 @@ exports.buildKeepRange = function(rep, builder, start, end, attribs, pool)
|
|||
}
|
||||
}
|
||||
|
||||
exports.buildKeepToStartOfRange = function(rep, builder, start)
|
||||
{
|
||||
exports.buildKeepToStartOfRange = function(rep, builder, start) {
|
||||
var startLineOffset = rep.lines.offsetOfIndex(start[0]);
|
||||
|
||||
builder.keep(startLineOffset, start[0]);
|
||||
|
|
|
@ -41,8 +41,7 @@ function scriptTag(source) {
|
|||
)
|
||||
}
|
||||
|
||||
function Ace2Editor()
|
||||
{
|
||||
function Ace2Editor() {
|
||||
var ace2 = Ace2Editor;
|
||||
|
||||
var editor = {};
|
||||
|
@ -54,14 +53,11 @@ function Ace2Editor()
|
|||
|
||||
var actionsPendingInit = [];
|
||||
|
||||
function pendingInit(func, optDoNow)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
function pendingInit(func, optDoNow) {
|
||||
return function() {
|
||||
var that = this;
|
||||
var args = arguments;
|
||||
var action = function()
|
||||
{
|
||||
var action = function() {
|
||||
func.apply(that, args);
|
||||
}
|
||||
if (optDoNow)
|
||||
|
@ -79,8 +75,7 @@ function Ace2Editor()
|
|||
};
|
||||
}
|
||||
|
||||
function doActionsPendingInit()
|
||||
{
|
||||
function doActionsPendingInit() {
|
||||
_.each(actionsPendingInit, function(fn,i){
|
||||
fn()
|
||||
});
|
||||
|
@ -114,24 +109,20 @@ function Ace2Editor()
|
|||
});
|
||||
});
|
||||
|
||||
editor.exportText = function()
|
||||
{
|
||||
editor.exportText = function() {
|
||||
if (!loaded) return "(awaiting init)\n";
|
||||
return info.ace_exportText();
|
||||
};
|
||||
|
||||
editor.getFrame = function()
|
||||
{
|
||||
editor.getFrame = function() {
|
||||
return info.frame || null;
|
||||
};
|
||||
|
||||
editor.getDebugProperty = function(prop)
|
||||
{
|
||||
editor.getDebugProperty = function(prop) {
|
||||
return info.ace_getDebugProperty(prop);
|
||||
};
|
||||
|
||||
editor.getInInternationalComposition = function()
|
||||
{
|
||||
editor.getInInternationalComposition = function() {
|
||||
if (!loaded) return false;
|
||||
return info.ace_getInInternationalComposition();
|
||||
};
|
||||
|
@ -145,14 +136,12 @@ function Ace2Editor()
|
|||
// to prepareUserChangeset will return an updated changeset that takes into account the
|
||||
// latest user changes, and modify the changeset to be applied by applyPreparedChangesetToBase
|
||||
// accordingly.
|
||||
editor.prepareUserChangeset = function()
|
||||
{
|
||||
editor.prepareUserChangeset = function() {
|
||||
if (!loaded) return null;
|
||||
return info.ace_prepareUserChangeset();
|
||||
};
|
||||
|
||||
editor.getUnhandledErrors = function()
|
||||
{
|
||||
editor.getUnhandledErrors = function() {
|
||||
if (!loaded) return [];
|
||||
// returns array of {error: <browser Error object>, time: +new Date()}
|
||||
return info.ace_getUnhandledErrors();
|
||||
|
@ -198,28 +187,24 @@ function Ace2Editor()
|
|||
}
|
||||
}
|
||||
|
||||
editor.destroy = pendingInit(function()
|
||||
{
|
||||
editor.destroy = pendingInit(function() {
|
||||
info.ace_dispose();
|
||||
info.frame.parentNode.removeChild(info.frame);
|
||||
delete ace2.registry[info.id];
|
||||
info = null; // prevent IE 6 closure memory leaks
|
||||
});
|
||||
|
||||
editor.init = function(containerId, initialCode, doneFunc)
|
||||
{
|
||||
editor.init = function(containerId, initialCode, doneFunc) {
|
||||
|
||||
editor.importText(initialCode);
|
||||
|
||||
info.onEditorReady = function()
|
||||
{
|
||||
info.onEditorReady = function() {
|
||||
loaded = true;
|
||||
doActionsPendingInit();
|
||||
doneFunc();
|
||||
};
|
||||
|
||||
(function()
|
||||
{
|
||||
(function() {
|
||||
var doctype = "<!doctype html>";
|
||||
|
||||
var iframeHTML = [];
|
||||
|
|
|
@ -22,25 +22,21 @@
|
|||
|
||||
var Security = require('./security');
|
||||
|
||||
function isNodeText(node)
|
||||
{
|
||||
function isNodeText(node) {
|
||||
return (node.nodeType == 3);
|
||||
}
|
||||
|
||||
function object(o)
|
||||
{
|
||||
function object(o) {
|
||||
var f = function(){};
|
||||
f.prototype = o;
|
||||
return new f();
|
||||
}
|
||||
|
||||
function getAssoc(obj, name)
|
||||
{
|
||||
function getAssoc(obj, name) {
|
||||
return obj["_magicdom_" + name];
|
||||
}
|
||||
|
||||
function setAssoc(obj, name, value)
|
||||
{
|
||||
function setAssoc(obj, name, value) {
|
||||
// note that in IE designMode, properties of a node can get
|
||||
// copied to new nodes that are spawned during editing; also,
|
||||
// properties representable in HTML text can survive copy-and-paste
|
||||
|
@ -52,8 +48,7 @@ function setAssoc(obj, name, value)
|
|||
// between false and true, a number between 0 and numItems inclusive.
|
||||
|
||||
|
||||
function binarySearch(numItems, func)
|
||||
{
|
||||
function binarySearch(numItems, func) {
|
||||
if (numItems < 1) return 0;
|
||||
if (func(0)) return 0;
|
||||
if (!func(numItems - 1)) return numItems;
|
||||
|
@ -68,15 +63,13 @@ function binarySearch(numItems, func)
|
|||
return high;
|
||||
}
|
||||
|
||||
function binarySearchInfinite(expectedLength, func)
|
||||
{
|
||||
function binarySearchInfinite(expectedLength, func) {
|
||||
var i = 0;
|
||||
while (!func(i)) i += expectedLength;
|
||||
return binarySearch(i, func);
|
||||
}
|
||||
|
||||
function htmlPrettyEscape(str)
|
||||
{
|
||||
function htmlPrettyEscape(str) {
|
||||
return Security.escapeHTML(str).replace(/\r?\n/g, '\\n');
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,15 +31,13 @@ var hooks = require('./pluginfw/hooks');
|
|||
|
||||
// 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)
|
||||
{
|
||||
function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, BroadcastSlider) {
|
||||
var changesetLoader = undefined;
|
||||
|
||||
// Below Array#indexOf code was direct pasted by AppJet/Etherpad, licence unknown. Possible source: http://www.tutorialspoint.com/javascript/array_indexof.htm
|
||||
if (!Array.prototype.indexOf)
|
||||
{
|
||||
Array.prototype.indexOf = function(elt /*, from*/ )
|
||||
{
|
||||
Array.prototype.indexOf = function(elt /*, from*/ ) {
|
||||
var len = this.length >>> 0;
|
||||
|
||||
var from = Number(arguments[1]) || 0;
|
||||
|
@ -54,8 +52,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
};
|
||||
}
|
||||
|
||||
function debugLog()
|
||||
{
|
||||
function debugLog() {
|
||||
try
|
||||
{
|
||||
if (window.console) console.log.apply(console, arguments);
|
||||
|
@ -82,8 +79,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
clientVars.collab_client_vars.initialAttributedText.attribs, clientVars.collab_client_vars.initialAttributedText.text),
|
||||
|
||||
// generates a jquery element containing HTML for a line
|
||||
lineToElement: function(line, aline)
|
||||
{
|
||||
lineToElement: function(line, aline) {
|
||||
var element = document.createElement("div");
|
||||
var emptyLine = (line == '\n');
|
||||
var domInfo = domline.createDomLine(!emptyLine, true);
|
||||
|
@ -95,8 +91,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
return $(element);
|
||||
},
|
||||
|
||||
applySpliceToDivs: function(start, numRemoved, newLines)
|
||||
{
|
||||
applySpliceToDivs: function(start, numRemoved, newLines) {
|
||||
// remove spliced-out lines from DOM
|
||||
for (var i = start; i < start + numRemoved && i < this.currentDivs.length; i++)
|
||||
{
|
||||
|
@ -137,8 +132,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
},
|
||||
|
||||
// splice the lines
|
||||
splice: function(start, numRemoved, newLinesVA)
|
||||
{
|
||||
splice: function(start, numRemoved, newLinesVA) {
|
||||
var newLines = _.map(Array.prototype.slice.call(arguments, 2), function(s) {
|
||||
return s;
|
||||
});
|
||||
|
@ -152,26 +146,22 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
this.currentLines.splice.apply(this.currentLines, arguments);
|
||||
},
|
||||
// returns the contents of the specified line I
|
||||
get: function(i)
|
||||
{
|
||||
get: function(i) {
|
||||
return this.currentLines[i];
|
||||
},
|
||||
// returns the number of lines in the document
|
||||
length: function()
|
||||
{
|
||||
length: function() {
|
||||
return this.currentLines.length;
|
||||
},
|
||||
|
||||
getActiveAuthors: function()
|
||||
{
|
||||
getActiveAuthors: function() {
|
||||
var self = this;
|
||||
var authors = [];
|
||||
var seenNums = {};
|
||||
var alines = self.alines;
|
||||
for (var i = 0; i < alines.length; i++)
|
||||
{
|
||||
Changeset.eachAttribNumber(alines[i], function(n)
|
||||
{
|
||||
Changeset.eachAttribNumber(alines[i], function(n) {
|
||||
if (!seenNums[n])
|
||||
{
|
||||
seenNums[n] = true;
|
||||
|
@ -191,8 +181,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
}
|
||||
};
|
||||
|
||||
function callCatchingErrors(catcher, func)
|
||||
{
|
||||
function callCatchingErrors(catcher, func) {
|
||||
try
|
||||
{
|
||||
wrapRecordingErrors(catcher, func)();
|
||||
|
@ -202,10 +191,8 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
}
|
||||
}
|
||||
|
||||
function wrapRecordingErrors(catcher, func)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
function wrapRecordingErrors(catcher, func) {
|
||||
return function() {
|
||||
try
|
||||
{
|
||||
return func.apply(this, Array.prototype.slice.call(arguments));
|
||||
|
@ -222,8 +209,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
};
|
||||
}
|
||||
|
||||
function loadedNewChangeset(changesetForward, changesetBackward, revision, timeDelta)
|
||||
{
|
||||
function loadedNewChangeset(changesetForward, changesetBackward, revision, timeDelta) {
|
||||
var broadcasting = (BroadcastSlider.getSliderPosition() == revisionInfo.latest);
|
||||
revisionInfo.addChangeset(revision, revision + 1, changesetForward, changesetBackward, timeDelta);
|
||||
BroadcastSlider.setSliderLength(revisionInfo.latest);
|
||||
|
@ -236,8 +222,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
cause the whole slider to get out of sync.
|
||||
*/
|
||||
|
||||
function applyChangeset(changeset, revision, preventSliderMovement, timeDelta)
|
||||
{
|
||||
function applyChangeset(changeset, revision, preventSliderMovement, timeDelta) {
|
||||
// disable the next 'gotorevision' call handled by a timeslider update
|
||||
if (!preventSliderMovement)
|
||||
{
|
||||
|
@ -283,18 +268,15 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
|
||||
updateTimer();
|
||||
|
||||
var authors = _.map(padContents.getActiveAuthors(), function(name)
|
||||
{
|
||||
var authors = _.map(padContents.getActiveAuthors(), function(name) {
|
||||
return authorData[name];
|
||||
});
|
||||
|
||||
BroadcastSlider.setAuthors(authors);
|
||||
}
|
||||
|
||||
function updateTimer()
|
||||
{
|
||||
var zpad = function(str, length)
|
||||
{
|
||||
function updateTimer() {
|
||||
var zpad = function(str, length) {
|
||||
str = str + "";
|
||||
while (str.length < length)
|
||||
str = '0' + str;
|
||||
|
@ -302,8 +284,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
}
|
||||
|
||||
var date = new Date(padContents.currentTime);
|
||||
var dateFormat = function()
|
||||
{
|
||||
var dateFormat = function() {
|
||||
var month = zpad(date.getMonth() + 1, 2);
|
||||
var day = zpad(date.getDate(), 2);
|
||||
var year = (date.getFullYear());
|
||||
|
@ -349,8 +330,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
|
||||
updateTimer();
|
||||
|
||||
function goToRevision(newRevision)
|
||||
{
|
||||
function goToRevision(newRevision) {
|
||||
padContents.targetRevision = newRevision;
|
||||
var self = this;
|
||||
var path = revisionInfo.getPath(padContents.currentRevision, newRevision);
|
||||
|
@ -376,8 +356,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
var sliderLocation = padContents.currentRevision;
|
||||
// callback is called after changeset information is pulled from server
|
||||
// this may never get called, if the changeset has already been loaded
|
||||
var update = function(start, end)
|
||||
{
|
||||
var update = function(start, end) {
|
||||
// if we've called goToRevision in the time since, don't goToRevision
|
||||
goToRevision(padContents.targetRevision);
|
||||
};
|
||||
|
@ -431,8 +410,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
requestQueue2: [],
|
||||
requestQueue3: [],
|
||||
reqCallbacks: [],
|
||||
queueUp: function(revision, width, callback)
|
||||
{
|
||||
queueUp: function(revision, width, callback) {
|
||||
if (revision < 0) revision = 0;
|
||||
// if(changesetLoader.requestQueue.indexOf(revision) != -1)
|
||||
// return; // already in the queue.
|
||||
|
@ -452,8 +430,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
setTimeout(changesetLoader.loadFromQueue, 10);
|
||||
}
|
||||
},
|
||||
loadFromQueue: function()
|
||||
{
|
||||
loadFromQueue: function() {
|
||||
var self = changesetLoader;
|
||||
var requestQueue = self.requestQueue1.length > 0 ? self.requestQueue1 : self.requestQueue2.length > 0 ? self.requestQueue2 : self.requestQueue3.length > 0 ? self.requestQueue3 : null;
|
||||
|
||||
|
@ -477,8 +454,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
|
||||
self.reqCallbacks[requestID] = callback;
|
||||
},
|
||||
handleSocketResponse: function(message)
|
||||
{
|
||||
handleSocketResponse: function(message) {
|
||||
var self = changesetLoader;
|
||||
|
||||
var start = message.data.start;
|
||||
|
@ -489,8 +465,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
self.handleResponse(message.data, start, granularity, callback);
|
||||
setTimeout(self.loadFromQueue, 10);
|
||||
},
|
||||
handleResponse: function(data, start, granularity, callback)
|
||||
{
|
||||
handleResponse: function(data, start, granularity, callback) {
|
||||
var pool = (new AttribPool()).fromJsonable(data.apool);
|
||||
for (var i = 0; i < data.forwardsChangesets.length; i++)
|
||||
{
|
||||
|
@ -504,8 +479,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
}
|
||||
if (callback) callback(start - 1, start + data.forwardsChangesets.length * granularity - 1);
|
||||
},
|
||||
handleMessageFromServer: function (obj)
|
||||
{
|
||||
handleMessageFromServer: function (obj) {
|
||||
if (obj.type == "COLLABROOM")
|
||||
{
|
||||
obj = obj.data;
|
||||
|
@ -556,8 +530,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
// to start upon window load, just push a function onto this array
|
||||
//window['onloadFuncts'].push(setUpSocket);
|
||||
//window['onloadFuncts'].push(function ()
|
||||
fireWhenAllScriptsAreLoaded.push(function()
|
||||
{
|
||||
fireWhenAllScriptsAreLoaded.push(function() {
|
||||
// set up the currentDivs and DOM
|
||||
padContents.currentDivs = [];
|
||||
$("#innerdocbody").html("");
|
||||
|
@ -588,8 +561,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
var dynamicCSS = makeCSSManager('dynamicsyntax');
|
||||
var authorData = {};
|
||||
|
||||
function receiveAuthorData(newAuthorData)
|
||||
{
|
||||
function receiveAuthorData(newAuthorData) {
|
||||
for (var author in newAuthorData)
|
||||
{
|
||||
var data = newAuthorData[author];
|
||||
|
|
|
@ -23,34 +23,28 @@
|
|||
// of the document. These revisions are connected together by various
|
||||
// changesets, or deltas, between any two revisions.
|
||||
|
||||
function loadBroadcastRevisionsJS()
|
||||
{
|
||||
function Revision(revNum)
|
||||
{
|
||||
function loadBroadcastRevisionsJS() {
|
||||
function Revision(revNum) {
|
||||
this.rev = revNum;
|
||||
this.changesets = [];
|
||||
}
|
||||
|
||||
Revision.prototype.addChangeset = function(destIndex, changeset, timeDelta)
|
||||
{
|
||||
Revision.prototype.addChangeset = function(destIndex, changeset, timeDelta) {
|
||||
var changesetWrapper = {
|
||||
deltaRev: destIndex - this.rev,
|
||||
deltaTime: timeDelta,
|
||||
getValue: function()
|
||||
{
|
||||
getValue: function() {
|
||||
return changeset;
|
||||
}
|
||||
};
|
||||
this.changesets.push(changesetWrapper);
|
||||
this.changesets.sort(function(a, b)
|
||||
{
|
||||
this.changesets.sort(function(a, b) {
|
||||
return (b.deltaRev - a.deltaRev)
|
||||
});
|
||||
}
|
||||
|
||||
revisionInfo = {};
|
||||
revisionInfo.addChangeset = function(fromIndex, toIndex, changeset, backChangeset, timeDelta)
|
||||
{
|
||||
revisionInfo.addChangeset = function(fromIndex, toIndex, changeset, backChangeset, timeDelta) {
|
||||
var startRevision = revisionInfo[fromIndex] || revisionInfo.createNew(fromIndex);
|
||||
var endRevision = revisionInfo[toIndex] || revisionInfo.createNew(toIndex);
|
||||
startRevision.addChangeset(toIndex, changeset, timeDelta);
|
||||
|
@ -59,8 +53,7 @@ function loadBroadcastRevisionsJS()
|
|||
|
||||
revisionInfo.latest = clientVars.collab_client_vars.rev || -1;
|
||||
|
||||
revisionInfo.createNew = function(index)
|
||||
{
|
||||
revisionInfo.createNew = function(index) {
|
||||
revisionInfo[index] = new Revision(index);
|
||||
if (index > revisionInfo.latest)
|
||||
{
|
||||
|
@ -72,8 +65,7 @@ function loadBroadcastRevisionsJS()
|
|||
|
||||
// assuming that there is a path from fromIndex to toIndex, and that the links
|
||||
// are laid out in a skip-list format
|
||||
revisionInfo.getPath = function(fromIndex, toIndex)
|
||||
{
|
||||
revisionInfo.getPath = function(fromIndex, toIndex) {
|
||||
var changesets = [];
|
||||
var spans = [];
|
||||
var times = [];
|
||||
|
|
|
@ -26,15 +26,13 @@ var _ = require('./underscore');
|
|||
var padmodals = require('./pad_modals').padmodals;
|
||||
var colorutils = require('./colorutils').colorutils;
|
||||
|
||||
function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||
{
|
||||
function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
||||
var BroadcastSlider;
|
||||
|
||||
// Hack to ensure timeslider i18n values are in
|
||||
$("[data-key='timeslider_returnToPad'] > a > span").html(html10n.get("timeslider.toolbar.returnbutton"));
|
||||
|
||||
(function()
|
||||
{ // wrap this code in its own namespace
|
||||
(function() { // wrap this code in its own namespace
|
||||
var sliderLength = 1000;
|
||||
var sliderPos = 0;
|
||||
var sliderActive = false;
|
||||
|
@ -42,8 +40,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
var savedRevisions = [];
|
||||
var sliderPlaying = false;
|
||||
|
||||
var _callSliderCallbacks = function(newval)
|
||||
{
|
||||
var _callSliderCallbacks = function(newval) {
|
||||
sliderPos = newval;
|
||||
for (var i = 0; i < slidercallbacks.length; i++)
|
||||
{
|
||||
|
@ -51,8 +48,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
}
|
||||
}
|
||||
|
||||
var updateSliderElements = function()
|
||||
{
|
||||
var updateSliderElements = function() {
|
||||
for (var i = 0; i < savedRevisions.length; i++)
|
||||
{
|
||||
var position = parseInt(savedRevisions[i].attr('pos'));
|
||||
|
@ -61,23 +57,20 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
$("#ui-slider-handle").css('left', sliderPos * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0));
|
||||
}
|
||||
|
||||
var addSavedRevision = function(position, info)
|
||||
{
|
||||
var addSavedRevision = function(position, info) {
|
||||
var newSavedRevision = $('<div></div>');
|
||||
newSavedRevision.addClass("star");
|
||||
|
||||
newSavedRevision.attr('pos', position);
|
||||
newSavedRevision.css('left', (position * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0)) - 1);
|
||||
$("#ui-slider-bar").append(newSavedRevision);
|
||||
newSavedRevision.mouseup(function(evt)
|
||||
{
|
||||
newSavedRevision.mouseup(function(evt) {
|
||||
BroadcastSlider.setSliderPosition(position);
|
||||
});
|
||||
savedRevisions.push(newSavedRevision);
|
||||
};
|
||||
|
||||
var removeSavedRevision = function(position)
|
||||
{
|
||||
var removeSavedRevision = function(position) {
|
||||
var element = $("div.star [pos=" + position + "]");
|
||||
savedRevisions.remove(element);
|
||||
element.remove();
|
||||
|
@ -86,18 +79,15 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
|
||||
/* Begin small 'API' */
|
||||
|
||||
function onSlider(callback)
|
||||
{
|
||||
function onSlider(callback) {
|
||||
slidercallbacks.push(callback);
|
||||
}
|
||||
|
||||
function getSliderPosition()
|
||||
{
|
||||
function getSliderPosition() {
|
||||
return sliderPos;
|
||||
}
|
||||
|
||||
function setSliderPosition(newpos)
|
||||
{
|
||||
function setSliderPosition(newpos) {
|
||||
newpos = Number(newpos);
|
||||
if (newpos < 0 || newpos > sliderLength) return;
|
||||
if(!newpos){
|
||||
|
@ -105,8 +95,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
}
|
||||
window.location.hash = "#" + newpos;
|
||||
$("#ui-slider-handle").css('left', newpos * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0));
|
||||
$("a.tlink").map(function()
|
||||
{
|
||||
$("a.tlink").map(function() {
|
||||
$(this).attr('href', $(this).attr('thref').replace("%revision%", newpos));
|
||||
});
|
||||
|
||||
|
@ -119,33 +108,28 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
_callSliderCallbacks(newpos);
|
||||
}
|
||||
|
||||
function getSliderLength()
|
||||
{
|
||||
function getSliderLength() {
|
||||
return sliderLength;
|
||||
}
|
||||
|
||||
function setSliderLength(newlength)
|
||||
{
|
||||
function setSliderLength(newlength) {
|
||||
sliderLength = newlength;
|
||||
updateSliderElements();
|
||||
}
|
||||
|
||||
// just take over the whole slider screen with a reconnect message
|
||||
|
||||
function showReconnectUI()
|
||||
{
|
||||
function showReconnectUI() {
|
||||
padmodals.showModal("disconnected");
|
||||
}
|
||||
|
||||
function setAuthors(authors)
|
||||
{
|
||||
function setAuthors(authors) {
|
||||
var authorsList = $("#authorsList");
|
||||
authorsList.empty();
|
||||
var numAnonymous = 0;
|
||||
var numNamed = 0;
|
||||
var colorsAnonymous = [];
|
||||
_.each(authors, function(author)
|
||||
{
|
||||
_.each(authors, function(author) {
|
||||
if(author)
|
||||
{
|
||||
var authorColor = clientVars.colorPalette[author.colorId] || author.colorId;
|
||||
|
@ -204,8 +188,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
setSliderPosition: setSliderPosition,
|
||||
getSliderLength: getSliderLength,
|
||||
setSliderLength: setSliderLength,
|
||||
isSliderActive: function()
|
||||
{
|
||||
isSliderActive: function() {
|
||||
return sliderActive;
|
||||
},
|
||||
playpause: playpause,
|
||||
|
@ -214,8 +197,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
setAuthors: setAuthors
|
||||
}
|
||||
|
||||
function playButtonUpdater()
|
||||
{
|
||||
function playButtonUpdater() {
|
||||
if (sliderPlaying)
|
||||
{
|
||||
if (getSliderPosition() + 1 > sliderLength)
|
||||
|
@ -230,8 +212,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
}
|
||||
}
|
||||
|
||||
function playpause()
|
||||
{
|
||||
function playpause() {
|
||||
$("#playpause_button_icon").toggleClass('pause');
|
||||
|
||||
if (!sliderPlaying)
|
||||
|
@ -247,10 +228,8 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
}
|
||||
|
||||
// assign event handlers to html UI elements after page load
|
||||
fireWhenAllScriptsAreLoaded.push(function()
|
||||
{
|
||||
$(document).keyup(function(e)
|
||||
{
|
||||
fireWhenAllScriptsAreLoaded.push(function() {
|
||||
$(document).keyup(function(e) {
|
||||
if (!e) var e = window.event;
|
||||
var code = e.keyCode || e.which;
|
||||
|
||||
|
@ -277,27 +256,23 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
});
|
||||
|
||||
// Resize
|
||||
$(window).resize(function()
|
||||
{
|
||||
$(window).resize(function() {
|
||||
updateSliderElements();
|
||||
});
|
||||
|
||||
// Slider click
|
||||
$("#ui-slider-bar").mousedown(function(evt)
|
||||
{
|
||||
$("#ui-slider-bar").mousedown(function(evt) {
|
||||
$("#ui-slider-handle").css('left', (evt.clientX - $("#ui-slider-bar").offset().left));
|
||||
$("#ui-slider-handle").trigger(evt);
|
||||
});
|
||||
|
||||
// Slider dragging
|
||||
$("#ui-slider-handle").mousedown(function(evt)
|
||||
{
|
||||
$("#ui-slider-handle").mousedown(function(evt) {
|
||||
this.startLoc = evt.clientX;
|
||||
this.currentLoc = parseInt($(this).css('left'));
|
||||
var self = this;
|
||||
sliderActive = true;
|
||||
$(document).mousemove(function(evt2)
|
||||
{
|
||||
$(document).mousemove(function(evt2) {
|
||||
$(self).css('pointer', 'move')
|
||||
var newloc = self.currentLoc + (evt2.clientX - self.startLoc);
|
||||
if (newloc < 0) newloc = 0;
|
||||
|
@ -306,8 +281,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
$(self).css('left', newloc);
|
||||
if (getSliderPosition() != Math.floor(newloc * sliderLength / ($("#ui-slider-bar").width() - 2))) _callSliderCallbacks(Math.floor(newloc * sliderLength / ($("#ui-slider-bar").width() - 2)))
|
||||
});
|
||||
$(document).mouseup(function(evt2)
|
||||
{
|
||||
$(document).mouseup(function(evt2) {
|
||||
$(document).unbind('mousemove');
|
||||
$(document).unbind('mouseup');
|
||||
sliderActive = false;
|
||||
|
@ -326,14 +300,12 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
})
|
||||
|
||||
// play/pause toggling
|
||||
$("#playpause_button_icon").click(function(evt)
|
||||
{
|
||||
$("#playpause_button_icon").click(function(evt) {
|
||||
BroadcastSlider.playpause();
|
||||
});
|
||||
|
||||
// next/prev saved revision and changeset
|
||||
$('.stepper').click(function(evt)
|
||||
{
|
||||
$('.stepper').click(function(evt) {
|
||||
switch ($(this).attr("id")) {
|
||||
case "leftstep":
|
||||
setSliderPosition(getSliderPosition() - 1);
|
||||
|
@ -380,8 +352,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
setSliderLength(clientVars.collab_client_vars.rev);
|
||||
setSliderPosition(clientVars.collab_client_vars.rev);
|
||||
|
||||
_.each(clientVars.savedRevisions, function(revision)
|
||||
{
|
||||
_.each(clientVars.savedRevisions, function(revision) {
|
||||
addSavedRevision(revision.revNum, revision);
|
||||
})
|
||||
|
||||
|
@ -389,8 +360,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
|||
});
|
||||
})();
|
||||
|
||||
BroadcastSlider.onSlider(function(loc)
|
||||
{
|
||||
BroadcastSlider.onSlider(function(loc) {
|
||||
$("#viewlatest").html(loc == BroadcastSlider.getSliderLength() ? "Viewing latest content" : "View latest content");
|
||||
})
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
// One rep.line(div) can be broken in more than one line in the browser.
|
||||
// This function is useful to get the caret position of the line as
|
||||
// is represented by the browser
|
||||
exports.getPosition = function ()
|
||||
{
|
||||
exports.getPosition = function () {
|
||||
var rect, line;
|
||||
var editor = $('#innerdocbody')[0];
|
||||
var range = getSelectionRange();
|
||||
|
@ -98,8 +97,7 @@ exports.getPositionTopOfPreviousBrowserLine = function(caretLinePosition, rep) {
|
|||
return previousLineTop;
|
||||
}
|
||||
|
||||
function caretLineIsFirstBrowserLine(caretLineTop, rep)
|
||||
{
|
||||
function caretLineIsFirstBrowserLine(caretLineTop, rep) {
|
||||
var caretRepLine = rep.selStart[0];
|
||||
var lineNode = rep.lines.atIndex(caretRepLine).lineNode;
|
||||
var firstRootNode = getFirstRootChildNode(lineNode);
|
||||
|
@ -110,8 +108,7 @@ function caretLineIsFirstBrowserLine(caretLineTop, rep)
|
|||
}
|
||||
|
||||
// find the first root node, usually it is a text node
|
||||
function getFirstRootChildNode(node)
|
||||
{
|
||||
function getFirstRootChildNode(node) {
|
||||
if(!node.firstChild){
|
||||
return node;
|
||||
}else{
|
||||
|
@ -120,8 +117,7 @@ function getFirstRootChildNode(node)
|
|||
|
||||
}
|
||||
|
||||
function getPreviousVisibleLine(line, rep)
|
||||
{
|
||||
function getPreviousVisibleLine(line, rep) {
|
||||
if (line < 0) {
|
||||
return 0;
|
||||
}else if (isLineVisible(line, rep)) {
|
||||
|
@ -131,8 +127,7 @@ function getPreviousVisibleLine(line, rep)
|
|||
}
|
||||
}
|
||||
|
||||
function getDimensionOfLastBrowserLineOfRepLine(line, rep)
|
||||
{
|
||||
function getDimensionOfLastBrowserLineOfRepLine(line, rep) {
|
||||
var lineNode = rep.lines.atIndex(line).lineNode;
|
||||
var lastRootChildNode = getLastRootChildNode(lineNode);
|
||||
|
||||
|
@ -141,8 +136,7 @@ function getDimensionOfLastBrowserLineOfRepLine(line, rep)
|
|||
return lastRootChildNodePosition;
|
||||
}
|
||||
|
||||
function getLastRootChildNode(node)
|
||||
{
|
||||
function getLastRootChildNode(node) {
|
||||
if(!node.lastChild){
|
||||
return {
|
||||
node: node,
|
||||
|
@ -158,8 +152,7 @@ function getLastRootChildNode(node)
|
|||
// So, we can use the caret line to calculate the bottom of the line.
|
||||
// [2] the next line is part of another rep line. It's possible this line has different dimensions, so we
|
||||
// have to get the exactly dimension of it
|
||||
exports.getBottomOfNextBrowserLine = function(caretLinePosition, rep)
|
||||
{
|
||||
exports.getBottomOfNextBrowserLine = function(caretLinePosition, rep) {
|
||||
var nextLineBottom = caretLinePosition.bottom + caretLinePosition.height; //[1]
|
||||
var isCaretLineLastBrowserLine = caretLineIsLastBrowserLineOfRepLine(caretLinePosition.top, rep);
|
||||
|
||||
|
@ -174,8 +167,7 @@ exports.getBottomOfNextBrowserLine = function(caretLinePosition, rep)
|
|||
return nextLineBottom;
|
||||
}
|
||||
|
||||
function caretLineIsLastBrowserLineOfRepLine(caretLineTop, rep)
|
||||
{
|
||||
function caretLineIsLastBrowserLineOfRepLine(caretLineTop, rep) {
|
||||
var caretRepLine = rep.selStart[0];
|
||||
var lineNode = rep.lines.atIndex(caretRepLine).lineNode;
|
||||
var lastRootChildNode = getLastRootChildNode(lineNode);
|
||||
|
@ -185,8 +177,7 @@ function caretLineIsLastBrowserLineOfRepLine(caretLineTop, rep)
|
|||
return lastRootChildNodePosition.top === caretLineTop;
|
||||
}
|
||||
|
||||
function getPreviousVisibleLine(line, rep)
|
||||
{
|
||||
function getPreviousVisibleLine(line, rep) {
|
||||
var firstLineOfPad = 0;
|
||||
if (line <= firstLineOfPad) {
|
||||
return firstLineOfPad;
|
||||
|
@ -198,8 +189,7 @@ function getPreviousVisibleLine(line, rep)
|
|||
}
|
||||
exports.getPreviousVisibleLine = getPreviousVisibleLine;
|
||||
|
||||
function getNextVisibleLine(line, rep)
|
||||
{
|
||||
function getNextVisibleLine(line, rep) {
|
||||
var lastLineOfThePad = rep.lines.length() - 1;
|
||||
if (line >= lastLineOfThePad) {
|
||||
return lastLineOfThePad;
|
||||
|
@ -211,13 +201,11 @@ function getNextVisibleLine(line, rep)
|
|||
}
|
||||
exports.getNextVisibleLine = getNextVisibleLine;
|
||||
|
||||
function isLineVisible(line, rep)
|
||||
{
|
||||
function isLineVisible(line, rep) {
|
||||
return rep.lines.atIndex(line).lineNode.offsetHeight > 0;
|
||||
}
|
||||
|
||||
function getDimensionOfFirstBrowserLineOfRepLine(line, rep)
|
||||
{
|
||||
function getDimensionOfFirstBrowserLineOfRepLine(line, rep) {
|
||||
var lineNode = rep.lines.atIndex(line).lineNode;
|
||||
var firstRootChildNode = getFirstRootChildNode(lineNode);
|
||||
|
||||
|
@ -226,8 +214,7 @@ function getDimensionOfFirstBrowserLineOfRepLine(line, rep)
|
|||
return firstRootChildNodePosition;
|
||||
}
|
||||
|
||||
function getSelectionRange()
|
||||
{
|
||||
function getSelectionRange() {
|
||||
var selection;
|
||||
if (!window.getSelection) {
|
||||
return;
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
var AttributePool = require('./AttributePool');
|
||||
var Changeset = require('./Changeset');
|
||||
|
||||
function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
||||
{
|
||||
function makeChangesetTracker(scheduler, apool, aceCallbacksProvider) {
|
||||
|
||||
// latest official text from server
|
||||
var baseAText = Changeset.makeAText("\n");
|
||||
|
@ -44,15 +43,13 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
|||
|
||||
var changeCallbackTimeout = null;
|
||||
|
||||
function setChangeCallbackTimeout()
|
||||
{
|
||||
function setChangeCallbackTimeout() {
|
||||
// can call this multiple times per call-stack, because
|
||||
// we only schedule a call to changeCallback if it exists
|
||||
// and if there isn't a timeout already scheduled.
|
||||
if (changeCallback && changeCallbackTimeout === null)
|
||||
{
|
||||
changeCallbackTimeout = scheduler.setTimeout(function()
|
||||
{
|
||||
changeCallbackTimeout = scheduler.setTimeout(function() {
|
||||
try
|
||||
{
|
||||
changeCallback();
|
||||
|
@ -68,18 +65,14 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
|||
|
||||
var self;
|
||||
return self = {
|
||||
isTracking: function()
|
||||
{
|
||||
isTracking: function() {
|
||||
return tracking;
|
||||
},
|
||||
setBaseText: function(text)
|
||||
{
|
||||
setBaseText: function(text) {
|
||||
self.setBaseAttributedText(Changeset.makeAText(text), null);
|
||||
},
|
||||
setBaseAttributedText: function(atext, apoolJsonObj)
|
||||
{
|
||||
aceCallbacksProvider.withCallbacks("setBaseText", function(callbacks)
|
||||
{
|
||||
setBaseAttributedText: function(atext, apoolJsonObj) {
|
||||
aceCallbacksProvider.withCallbacks("setBaseText", function(callbacks) {
|
||||
tracking = true;
|
||||
baseAText = Changeset.cloneAText(atext);
|
||||
if (apoolJsonObj)
|
||||
|
@ -100,8 +93,7 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
|||
}
|
||||
});
|
||||
},
|
||||
composeUserChangeset: function(c)
|
||||
{
|
||||
composeUserChangeset: function(c) {
|
||||
if (!tracking) return;
|
||||
if (applyingNonUserChanges) return;
|
||||
if (Changeset.isIdentity(c)) return;
|
||||
|
@ -109,12 +101,10 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
|||
|
||||
setChangeCallbackTimeout();
|
||||
},
|
||||
applyChangesToBase: function(c, optAuthor, apoolJsonObj)
|
||||
{
|
||||
applyChangesToBase: function(c, optAuthor, apoolJsonObj) {
|
||||
if (!tracking) return;
|
||||
|
||||
aceCallbacksProvider.withCallbacks("applyChangesToBase", function(callbacks)
|
||||
{
|
||||
aceCallbacksProvider.withCallbacks("applyChangesToBase", function(callbacks) {
|
||||
|
||||
if (apoolJsonObj)
|
||||
{
|
||||
|
@ -149,8 +139,7 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
|||
}
|
||||
});
|
||||
},
|
||||
prepareUserChangeset: function()
|
||||
{
|
||||
prepareUserChangeset: function() {
|
||||
// If there are user changes to submit, 'changeset' will be the
|
||||
// changeset, else it will be null.
|
||||
var toSubmit;
|
||||
|
@ -237,8 +226,7 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
|||
};
|
||||
return data;
|
||||
},
|
||||
applyPreparedChangesetToBase: function()
|
||||
{
|
||||
applyPreparedChangesetToBase: function() {
|
||||
if (!submittedChangeset)
|
||||
{
|
||||
// violation of protocol; use prepareUserChangeset first
|
||||
|
@ -248,12 +236,10 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider)
|
|||
baseAText = Changeset.applyToAText(submittedChangeset, baseAText, apool);
|
||||
submittedChangeset = null;
|
||||
},
|
||||
setUserChangeNotificationCallback: function(callback)
|
||||
{
|
||||
setUserChangeNotificationCallback: function(callback) {
|
||||
changeCallback = callback;
|
||||
},
|
||||
hasUncommittedChanges: function()
|
||||
{
|
||||
hasUncommittedChanges: function() {
|
||||
return !!(submittedChangeset || (!Changeset.isIdentity(userChangeset)));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,16 +20,14 @@ var Tinycon = require('tinycon/tinycon');
|
|||
var hooks = require('./pluginfw/hooks');
|
||||
var padeditor = require('./pad_editor').padeditor;
|
||||
|
||||
var chat = (function()
|
||||
{
|
||||
var chat = (function() {
|
||||
var isStuck = false;
|
||||
var userAndChat = false;
|
||||
var gotInitialMessages = false;
|
||||
var historyPointer = 0;
|
||||
var chatMentions = 0;
|
||||
var self = {
|
||||
show: function ()
|
||||
{
|
||||
show: function () {
|
||||
$("#chaticon").removeClass('visible');
|
||||
$("#chatbox").addClass('visible');
|
||||
self.scrollDown(true);
|
||||
|
@ -39,14 +37,12 @@ var chat = (function()
|
|||
$.gritter.remove(this.id);
|
||||
});
|
||||
},
|
||||
focus: function ()
|
||||
{
|
||||
focus: function () {
|
||||
setTimeout(function(){
|
||||
$("#chatinput").focus();
|
||||
},100);
|
||||
},
|
||||
stickToScreen: function(fromInitialCall) // Make chat stick to right hand side of screen
|
||||
{
|
||||
stickToScreen: function(fromInitialCall) { // Make chat stick to right hand side of screen
|
||||
if(pad.settings.hideChat){
|
||||
return;
|
||||
}
|
||||
|
@ -62,8 +58,7 @@ var chat = (function()
|
|||
padcookie.setPref("chatAlwaysVisible", isStuck);
|
||||
$('#options-stickychat').prop('checked', isStuck);
|
||||
},
|
||||
chatAndUsers: function(fromInitialCall)
|
||||
{
|
||||
chatAndUsers: function(fromInitialCall) {
|
||||
var toEnable = $('#options-chatandusers').is(":checked");
|
||||
if(toEnable || !userAndChat || fromInitialCall){
|
||||
chat.stickToScreen(true);
|
||||
|
@ -79,8 +74,7 @@ var chat = (function()
|
|||
$('#users, .sticky-container').toggleClass("chatAndUsers popup-show stickyUsers", userAndChat);
|
||||
$("#chatbox").toggleClass("chatAndUsersChat", userAndChat);
|
||||
},
|
||||
hide: function ()
|
||||
{
|
||||
hide: function () {
|
||||
// decide on hide logic based on chat window being maximized or not
|
||||
if ($('#options-stickychat').prop('checked')) {
|
||||
chat.stickToScreen();
|
||||
|
@ -92,8 +86,7 @@ var chat = (function()
|
|||
$("#chatbox").removeClass('visible');
|
||||
}
|
||||
},
|
||||
scrollDown: function(force)
|
||||
{
|
||||
scrollDown: function(force) {
|
||||
if ($('#chatbox').hasClass('visible')) {
|
||||
if (force || !self.lastMessage || !self.lastMessage.position() || self.lastMessage.position().top < ($('#chattext').outerHeight() + 20)) {
|
||||
// if we use a slow animate here we can have a race condition when a users focus can not be moved away
|
||||
|
@ -103,16 +96,14 @@ var chat = (function()
|
|||
}
|
||||
}
|
||||
},
|
||||
send: function()
|
||||
{
|
||||
send: function() {
|
||||
var text = $("#chatinput").val();
|
||||
if(text.replace(/\s+/,'').length == 0)
|
||||
return;
|
||||
this._pad.collabClient.sendMessage({"type": "CHAT_MESSAGE", "text": text});
|
||||
$("#chatinput").val("");
|
||||
},
|
||||
addMessage: function(msg, increment, isHistoryAdd)
|
||||
{
|
||||
addMessage: function(msg, increment, isHistoryAdd) {
|
||||
//correct the time
|
||||
msg.time += this._pad.clientTimeOffset;
|
||||
|
||||
|
@ -136,8 +127,7 @@ var chat = (function()
|
|||
console.warn('The "userId" field of a chat message coming from the server was not present. Replacing with "unknown". This may be a bug or a database corruption.');
|
||||
}
|
||||
|
||||
var authorClass = "author-" + msg.userId.replace(/[^a-y0-9]/g, function(c)
|
||||
{
|
||||
var authorClass = "author-" + msg.userId.replace(/[^a-y0-9]/g, function(c) {
|
||||
if (c == ".") return "-";
|
||||
return 'z' + c.charCodeAt(0) + 'z';
|
||||
});
|
||||
|
@ -214,8 +204,7 @@ var chat = (function()
|
|||
if(!isHistoryAdd)
|
||||
self.scrollDown();
|
||||
},
|
||||
init: function(pad)
|
||||
{
|
||||
init: function(pad) {
|
||||
this._pad = pad;
|
||||
$("#chatinput").on("keydown", function(evt){
|
||||
// If the event is Alt C or Escape & we're already in the chat menu
|
||||
|
@ -251,8 +240,7 @@ var chat = (function()
|
|||
// initial messages are loaded in pad.js' _afterHandshake
|
||||
|
||||
$("#chatcounter").text(0);
|
||||
$("#chatloadmessagesbutton").click(function()
|
||||
{
|
||||
$("#chatloadmessagesbutton").click(function() {
|
||||
var start = Math.max(self.historyPointer - 20, 0);
|
||||
var end = self.historyPointer;
|
||||
|
||||
|
|
|
@ -33,8 +33,7 @@ function getSocket() {
|
|||
/** Call this when the document is ready, and a new Ace2Editor() has been created and inited.
|
||||
ACE's ready callback does not need to have fired yet.
|
||||
"serverVars" are from calling doc.getCollabClientVars() on the server. */
|
||||
function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||
{
|
||||
function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) {
|
||||
var editor = ace2editor;
|
||||
pad = _pad; // Inject pad to avoid a circular dependency.
|
||||
|
||||
|
@ -66,29 +65,20 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
tellAceActiveAuthorInfo(initialUserInfo);
|
||||
|
||||
var callbacks = {
|
||||
onUserJoin: function()
|
||||
{},
|
||||
onUserLeave: function()
|
||||
{},
|
||||
onUpdateUserInfo: function()
|
||||
{},
|
||||
onChannelStateChange: function()
|
||||
{},
|
||||
onClientMessage: function()
|
||||
{},
|
||||
onInternalAction: function()
|
||||
{},
|
||||
onConnectionTrouble: function()
|
||||
{},
|
||||
onServerMessage: function()
|
||||
{}
|
||||
onUserJoin: function() {},
|
||||
onUserLeave: function() {},
|
||||
onUpdateUserInfo: function() {},
|
||||
onChannelStateChange: function() {},
|
||||
onClientMessage: function() {},
|
||||
onInternalAction: function() {},
|
||||
onConnectionTrouble: function() {},
|
||||
onServerMessage: function() {}
|
||||
};
|
||||
if (browser.firefox)
|
||||
{
|
||||
// Prevent "escape" from taking effect and canceling a comet connection;
|
||||
// doesn't work if focus is on an iframe.
|
||||
$(window).bind("keydown", function(evt)
|
||||
{
|
||||
$(window).bind("keydown", function(evt) {
|
||||
if (evt.which == 27)
|
||||
{
|
||||
evt.preventDefault()
|
||||
|
@ -100,14 +90,12 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
editor.setBaseAttributedText(serverVars.initialAttributedText, serverVars.apool);
|
||||
editor.setUserChangeNotificationCallback(wrapRecordingErrors("handleUserChanges", handleUserChanges));
|
||||
|
||||
function dmesg(str)
|
||||
{
|
||||
function dmesg(str) {
|
||||
if (typeof window.ajlog == "string") window.ajlog += str + '\n';
|
||||
debugMessages.push(str);
|
||||
}
|
||||
|
||||
function handleUserChanges()
|
||||
{
|
||||
function handleUserChanges() {
|
||||
if (editor.getInInternationalComposition()) return;
|
||||
if ((!getSocket()) || channelState == "CONNECTING")
|
||||
{
|
||||
|
@ -161,12 +149,10 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
{
|
||||
editor.applyPreparedChangesetToBase();
|
||||
setStateIdle();
|
||||
callCatchingErrors("onInternalAction", function()
|
||||
{
|
||||
callCatchingErrors("onInternalAction", function() {
|
||||
callbacks.onInternalAction("commitAcceptedByServer");
|
||||
});
|
||||
callCatchingErrors("onConnectionTrouble", function()
|
||||
{
|
||||
callCatchingErrors("onConnectionTrouble", function() {
|
||||
callbacks.onConnectionTrouble("OK");
|
||||
});
|
||||
handleUserChanges();
|
||||
|
@ -219,8 +205,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
}
|
||||
}
|
||||
|
||||
function setUpSocket()
|
||||
{
|
||||
function setUpSocket() {
|
||||
hiccupCount = 0;
|
||||
setChannelState("CONNECTED");
|
||||
doDeferredActions();
|
||||
|
@ -230,8 +215,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
|
||||
var hiccupCount = 0;
|
||||
|
||||
function sendMessage(msg)
|
||||
{
|
||||
function sendMessage(msg) {
|
||||
getSocket().json.send(
|
||||
{
|
||||
type: "COLLABROOM",
|
||||
|
@ -240,10 +224,8 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
});
|
||||
}
|
||||
|
||||
function wrapRecordingErrors(catcher, func)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
function wrapRecordingErrors(catcher, func) {
|
||||
return function() {
|
||||
try
|
||||
{
|
||||
return func.apply(this, Array.prototype.slice.call(arguments));
|
||||
|
@ -259,8 +241,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
};
|
||||
}
|
||||
|
||||
function callCatchingErrors(catcher, func)
|
||||
{
|
||||
function callCatchingErrors(catcher, func) {
|
||||
try
|
||||
{
|
||||
wrapRecordingErrors(catcher, func)();
|
||||
|
@ -270,8 +251,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
}
|
||||
}
|
||||
|
||||
function handleMessageFromServer(evt)
|
||||
{
|
||||
function handleMessageFromServer(evt) {
|
||||
if (!getSocket()) return;
|
||||
if (!evt.data) return;
|
||||
var wrapper = evt;
|
||||
|
@ -334,12 +314,10 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
rev = newRev;
|
||||
editor.applyPreparedChangesetToBase();
|
||||
setStateIdle();
|
||||
callCatchingErrors("onInternalAction", function()
|
||||
{
|
||||
callCatchingErrors("onInternalAction", function() {
|
||||
callbacks.onInternalAction("commitAcceptedByServer");
|
||||
});
|
||||
callCatchingErrors("onConnectionTrouble", function()
|
||||
{
|
||||
callCatchingErrors("onConnectionTrouble", function() {
|
||||
callbacks.onConnectionTrouble("OK");
|
||||
});
|
||||
handleUserChanges();
|
||||
|
@ -386,12 +364,10 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
{
|
||||
editor.applyPreparedChangesetToBase();
|
||||
setStateIdle();
|
||||
callCatchingErrors("onInternalAction", function()
|
||||
{
|
||||
callCatchingErrors("onInternalAction", function() {
|
||||
callbacks.onInternalAction("commitAcceptedByServer");
|
||||
});
|
||||
callCatchingErrors("onConnectionTrouble", function()
|
||||
{
|
||||
callCatchingErrors("onConnectionTrouble", function() {
|
||||
callbacks.onConnectionTrouble("OK");
|
||||
});
|
||||
handleUserChanges();
|
||||
|
@ -503,8 +479,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
hooks.callAll('handleClientMessage_' + msg.type, {payload: msg.payload});
|
||||
}
|
||||
|
||||
function updateUserInfo(userInfo)
|
||||
{
|
||||
function updateUserInfo(userInfo) {
|
||||
userInfo.userId = userId;
|
||||
userSet[userId] = userInfo;
|
||||
tellAceActiveAuthorInfo(userInfo);
|
||||
|
@ -516,13 +491,11 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
});
|
||||
}
|
||||
|
||||
function tellAceActiveAuthorInfo(userInfo)
|
||||
{
|
||||
function tellAceActiveAuthorInfo(userInfo) {
|
||||
tellAceAuthorInfo(userInfo.userId, userInfo.colorId);
|
||||
}
|
||||
|
||||
function tellAceAuthorInfo(userId, colorId, inactive)
|
||||
{
|
||||
function tellAceAuthorInfo(userId, colorId, inactive) {
|
||||
if(typeof colorId == "number")
|
||||
{
|
||||
colorId = clientVars.colorPalette[colorId];
|
||||
|
@ -544,18 +517,15 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
}
|
||||
}
|
||||
|
||||
function fadeAceAuthorInfo(userInfo)
|
||||
{
|
||||
function fadeAceAuthorInfo(userInfo) {
|
||||
tellAceAuthorInfo(userInfo.userId, userInfo.colorId, true);
|
||||
}
|
||||
|
||||
function getConnectedUsers()
|
||||
{
|
||||
function getConnectedUsers() {
|
||||
return valuesArray(userSet);
|
||||
}
|
||||
|
||||
function tellAceAboutHistoricalAuthors(hadata)
|
||||
{
|
||||
function tellAceAboutHistoricalAuthors(hadata) {
|
||||
for (var author in hadata)
|
||||
{
|
||||
var data = hadata[author];
|
||||
|
@ -566,8 +536,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
}
|
||||
}
|
||||
|
||||
function setChannelState(newChannelState, moreInfo)
|
||||
{
|
||||
function setChannelState(newChannelState, moreInfo) {
|
||||
if (newChannelState != channelState)
|
||||
{
|
||||
channelState = newChannelState;
|
||||
|
@ -575,11 +544,9 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
}
|
||||
}
|
||||
|
||||
function valuesArray(obj)
|
||||
{
|
||||
function valuesArray(obj) {
|
||||
var array = [];
|
||||
$.each(obj, function(k, v)
|
||||
{
|
||||
$.each(obj, function(k, v) {
|
||||
array.push(v);
|
||||
});
|
||||
return array;
|
||||
|
@ -589,15 +556,12 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
// is connected for the first time.
|
||||
var deferredActions = [];
|
||||
|
||||
function defer(func, tag)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
function defer(func, tag) {
|
||||
return function() {
|
||||
var that = this;
|
||||
var args = arguments;
|
||||
|
||||
function action()
|
||||
{
|
||||
function action() {
|
||||
func.apply(that, args);
|
||||
}
|
||||
action.tag = tag;
|
||||
|
@ -612,8 +576,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
}
|
||||
}
|
||||
|
||||
function doDeferredActions(tag)
|
||||
{
|
||||
function doDeferredActions(tag) {
|
||||
var newArray = [];
|
||||
for (var i = 0; i < deferredActions.length; i++)
|
||||
{
|
||||
|
@ -630,8 +593,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
deferredActions = newArray;
|
||||
}
|
||||
|
||||
function sendClientMessage(msg)
|
||||
{
|
||||
function sendClientMessage(msg) {
|
||||
sendMessage(
|
||||
{
|
||||
type: "CLIENT_MESSAGE",
|
||||
|
@ -639,13 +601,11 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
});
|
||||
}
|
||||
|
||||
function getCurrentRevisionNumber()
|
||||
{
|
||||
function getCurrentRevisionNumber() {
|
||||
return rev;
|
||||
}
|
||||
|
||||
function getMissedChanges()
|
||||
{
|
||||
function getMissedChanges() {
|
||||
var obj = {};
|
||||
obj.userInfo = userSet[userId];
|
||||
obj.baseRev = rev;
|
||||
|
@ -664,30 +624,25 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
return obj;
|
||||
}
|
||||
|
||||
function setStateIdle()
|
||||
{
|
||||
function setStateIdle() {
|
||||
state = "IDLE";
|
||||
callbacks.onInternalAction("newlyIdle");
|
||||
schedulePerhapsCallIdleFuncs();
|
||||
}
|
||||
|
||||
function setIsPendingRevision(value)
|
||||
{
|
||||
function setIsPendingRevision(value) {
|
||||
isPendingRevision = value;
|
||||
}
|
||||
|
||||
function callWhenNotCommitting(func)
|
||||
{
|
||||
function callWhenNotCommitting(func) {
|
||||
idleFuncs.push(func);
|
||||
schedulePerhapsCallIdleFuncs();
|
||||
}
|
||||
|
||||
var idleFuncs = [];
|
||||
|
||||
function schedulePerhapsCallIdleFuncs()
|
||||
{
|
||||
setTimeout(function()
|
||||
{
|
||||
function schedulePerhapsCallIdleFuncs() {
|
||||
setTimeout(function() {
|
||||
if (state == "IDLE")
|
||||
{
|
||||
while (idleFuncs.length > 0)
|
||||
|
@ -700,36 +655,28 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
}
|
||||
|
||||
var self = {
|
||||
setOnUserJoin: function(cb)
|
||||
{
|
||||
setOnUserJoin: function(cb) {
|
||||
callbacks.onUserJoin = cb;
|
||||
},
|
||||
setOnUserLeave: function(cb)
|
||||
{
|
||||
setOnUserLeave: function(cb) {
|
||||
callbacks.onUserLeave = cb;
|
||||
},
|
||||
setOnUpdateUserInfo: function(cb)
|
||||
{
|
||||
setOnUpdateUserInfo: function(cb) {
|
||||
callbacks.onUpdateUserInfo = cb;
|
||||
},
|
||||
setOnChannelStateChange: function(cb)
|
||||
{
|
||||
setOnChannelStateChange: function(cb) {
|
||||
callbacks.onChannelStateChange = cb;
|
||||
},
|
||||
setOnClientMessage: function(cb)
|
||||
{
|
||||
setOnClientMessage: function(cb) {
|
||||
callbacks.onClientMessage = cb;
|
||||
},
|
||||
setOnInternalAction: function(cb)
|
||||
{
|
||||
setOnInternalAction: function(cb) {
|
||||
callbacks.onInternalAction = cb;
|
||||
},
|
||||
setOnConnectionTrouble: function(cb)
|
||||
{
|
||||
setOnConnectionTrouble: function(cb) {
|
||||
callbacks.onConnectionTrouble = cb;
|
||||
},
|
||||
setOnServerMessage: function(cb)
|
||||
{
|
||||
setOnServerMessage: function(cb) {
|
||||
callbacks.onServerMessage = cb;
|
||||
},
|
||||
updateUserInfo: defer(updateUserInfo),
|
||||
|
|
|
@ -26,26 +26,22 @@ var colorutils = {};
|
|||
|
||||
// Check that a given value is a css hex color value, e.g.
|
||||
// "#ffffff" or "#fff"
|
||||
colorutils.isCssHex = function(cssColor)
|
||||
{
|
||||
colorutils.isCssHex = function(cssColor) {
|
||||
return /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(cssColor);
|
||||
}
|
||||
|
||||
// "#ffffff" or "#fff" or "ffffff" or "fff" to [1.0, 1.0, 1.0]
|
||||
colorutils.css2triple = function(cssColor)
|
||||
{
|
||||
colorutils.css2triple = function(cssColor) {
|
||||
var sixHex = colorutils.css2sixhex(cssColor);
|
||||
|
||||
function hexToFloat(hh)
|
||||
{
|
||||
function hexToFloat(hh) {
|
||||
return Number("0x" + hh) / 255;
|
||||
}
|
||||
return [hexToFloat(sixHex.substr(0, 2)), hexToFloat(sixHex.substr(2, 2)), hexToFloat(sixHex.substr(4, 2))];
|
||||
}
|
||||
|
||||
// "#ffffff" or "#fff" or "ffffff" or "fff" to "ffffff"
|
||||
colorutils.css2sixhex = function(cssColor)
|
||||
{
|
||||
colorutils.css2sixhex = function(cssColor) {
|
||||
var h = /[0-9a-fA-F]+/.exec(cssColor)[0];
|
||||
if (h.length != 6)
|
||||
{
|
||||
|
@ -58,10 +54,8 @@ colorutils.css2sixhex = function(cssColor)
|
|||
}
|
||||
|
||||
// [1.0, 1.0, 1.0] -> "#ffffff"
|
||||
colorutils.triple2css = function(triple)
|
||||
{
|
||||
function floatToHex(n)
|
||||
{
|
||||
colorutils.triple2css = function(triple) {
|
||||
function floatToHex(n) {
|
||||
var n2 = colorutils.clamp(Math.round(n * 255), 0, 255);
|
||||
return ("0" + n2.toString(16)).slice(-2);
|
||||
}
|
||||
|
@ -69,71 +63,57 @@ colorutils.triple2css = function(triple)
|
|||
}
|
||||
|
||||
|
||||
colorutils.clamp = function(v, bot, top)
|
||||
{
|
||||
colorutils.clamp = function(v, bot, top) {
|
||||
return v < bot ? bot : (v > top ? top : v);
|
||||
};
|
||||
colorutils.min3 = function(a, b, c)
|
||||
{
|
||||
colorutils.min3 = function(a, b, c) {
|
||||
return (a < b) ? (a < c ? a : c) : (b < c ? b : c);
|
||||
};
|
||||
colorutils.max3 = function(a, b, c)
|
||||
{
|
||||
colorutils.max3 = function(a, b, c) {
|
||||
return (a > b) ? (a > c ? a : c) : (b > c ? b : c);
|
||||
};
|
||||
colorutils.colorMin = function(c)
|
||||
{
|
||||
colorutils.colorMin = function(c) {
|
||||
return colorutils.min3(c[0], c[1], c[2]);
|
||||
};
|
||||
colorutils.colorMax = function(c)
|
||||
{
|
||||
colorutils.colorMax = function(c) {
|
||||
return colorutils.max3(c[0], c[1], c[2]);
|
||||
};
|
||||
colorutils.scale = function(v, bot, top)
|
||||
{
|
||||
colorutils.scale = function(v, bot, top) {
|
||||
return colorutils.clamp(bot + v * (top - bot), 0, 1);
|
||||
};
|
||||
colorutils.unscale = function(v, bot, top)
|
||||
{
|
||||
colorutils.unscale = function(v, bot, top) {
|
||||
return colorutils.clamp((v - bot) / (top - bot), 0, 1);
|
||||
};
|
||||
|
||||
colorutils.scaleColor = function(c, bot, top)
|
||||
{
|
||||
colorutils.scaleColor = function(c, bot, top) {
|
||||
return [colorutils.scale(c[0], bot, top), colorutils.scale(c[1], bot, top), colorutils.scale(c[2], bot, top)];
|
||||
}
|
||||
|
||||
colorutils.unscaleColor = function(c, bot, top)
|
||||
{
|
||||
colorutils.unscaleColor = function(c, bot, top) {
|
||||
return [colorutils.unscale(c[0], bot, top), colorutils.unscale(c[1], bot, top), colorutils.unscale(c[2], bot, top)];
|
||||
}
|
||||
|
||||
colorutils.luminosity = function(c)
|
||||
{
|
||||
colorutils.luminosity = function(c) {
|
||||
// rule of thumb for RGB brightness; 1.0 is white
|
||||
return c[0] * 0.30 + c[1] * 0.59 + c[2] * 0.11;
|
||||
}
|
||||
|
||||
colorutils.saturate = function(c)
|
||||
{
|
||||
colorutils.saturate = function(c) {
|
||||
var min = colorutils.colorMin(c);
|
||||
var max = colorutils.colorMax(c);
|
||||
if (max - min <= 0) return [1.0, 1.0, 1.0];
|
||||
return colorutils.unscaleColor(c, min, max);
|
||||
}
|
||||
|
||||
colorutils.blend = function(c1, c2, t)
|
||||
{
|
||||
colorutils.blend = function(c1, c2, t) {
|
||||
return [colorutils.scale(t, c1[0], c2[0]), colorutils.scale(t, c1[1], c2[1]), colorutils.scale(t, c1[2], c2[2])];
|
||||
}
|
||||
|
||||
colorutils.invert = function(c)
|
||||
{
|
||||
colorutils.invert = function(c) {
|
||||
return [1 - c[0], 1 - c[1], 1- c[2]];
|
||||
}
|
||||
|
||||
colorutils.complementary = function(c)
|
||||
{
|
||||
colorutils.complementary = function(c) {
|
||||
var inv = colorutils.invert(c);
|
||||
return [
|
||||
(inv[0] >= c[0]) ? Math.min(inv[0] * 1.30, 1) : (c[0] * 0.30),
|
||||
|
@ -142,8 +122,7 @@ colorutils.complementary = function(c)
|
|||
];
|
||||
}
|
||||
|
||||
colorutils.textColorFromBackgroundColor = function(bgcolor, skinName)
|
||||
{
|
||||
colorutils.textColorFromBackgroundColor = function(bgcolor, skinName) {
|
||||
var white = skinName == 'colibris' ? 'var(--super-light-color)' : '#fff';
|
||||
var black = skinName == 'colibris' ? 'var(--super-dark-color)' : '#222';
|
||||
|
||||
|
|
|
@ -30,53 +30,43 @@ var Changeset = require('./Changeset');
|
|||
var hooks = require('./pluginfw/hooks');
|
||||
var _ = require('./underscore');
|
||||
|
||||
function sanitizeUnicode(s)
|
||||
{
|
||||
function sanitizeUnicode(s) {
|
||||
return UNorm.nfc(s);
|
||||
}
|
||||
|
||||
function makeContentCollector(collectStyles, abrowser, apool, domInterface, className2Author)
|
||||
{
|
||||
function makeContentCollector(collectStyles, abrowser, apool, domInterface, className2Author) {
|
||||
abrowser = abrowser || {};
|
||||
// I don't like the above.
|
||||
|
||||
var dom = domInterface || {
|
||||
isNodeText: function(n)
|
||||
{
|
||||
isNodeText: function(n) {
|
||||
return (n.nodeType == 3);
|
||||
},
|
||||
nodeTagName: function(n)
|
||||
{
|
||||
nodeTagName: function(n) {
|
||||
return n.tagName;
|
||||
},
|
||||
nodeValue: function(n)
|
||||
{
|
||||
nodeValue: function(n) {
|
||||
return n.nodeValue;
|
||||
},
|
||||
nodeNumChildren: function(n)
|
||||
{
|
||||
nodeNumChildren: function(n) {
|
||||
if(n.childNodes == null) return 0;
|
||||
return n.childNodes.length;
|
||||
},
|
||||
nodeChild: function(n, i)
|
||||
{
|
||||
nodeChild: function(n, i) {
|
||||
if(n.childNodes.item == null){
|
||||
return n.childNodes[i];
|
||||
}
|
||||
return n.childNodes.item(i);
|
||||
},
|
||||
nodeProp: function(n, p)
|
||||
{
|
||||
nodeProp: function(n, p) {
|
||||
return n[p];
|
||||
},
|
||||
nodeAttr: function(n, a)
|
||||
{
|
||||
nodeAttr: function(n, a) {
|
||||
if(n.getAttribute != null) return n.getAttribute(a);
|
||||
if(n.attribs != null) return n.attribs[a];
|
||||
return null;
|
||||
},
|
||||
optNodeInnerHTML: function(n)
|
||||
{
|
||||
optNodeInnerHTML: function(n) {
|
||||
return n.innerHTML;
|
||||
}
|
||||
};
|
||||
|
@ -92,66 +82,54 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
_blockElems[element] = 1;
|
||||
});
|
||||
|
||||
function isBlockElement(n)
|
||||
{
|
||||
function isBlockElement(n) {
|
||||
return !!_blockElems[(dom.nodeTagName(n) || "").toLowerCase()];
|
||||
}
|
||||
|
||||
function textify(str)
|
||||
{
|
||||
function textify(str) {
|
||||
return sanitizeUnicode(
|
||||
str.replace(/(\n | \n)/g, ' ').replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' '));
|
||||
}
|
||||
|
||||
function getAssoc(node, name)
|
||||
{
|
||||
function getAssoc(node, name) {
|
||||
return dom.nodeProp(node, "_magicdom_" + name);
|
||||
}
|
||||
|
||||
var lines = (function()
|
||||
{
|
||||
var lines = (function() {
|
||||
var textArray = [];
|
||||
var attribsArray = [];
|
||||
var attribsBuilder = null;
|
||||
var op = Changeset.newOp('+');
|
||||
var self = {
|
||||
length: function()
|
||||
{
|
||||
length: function() {
|
||||
return textArray.length;
|
||||
},
|
||||
atColumnZero: function()
|
||||
{
|
||||
atColumnZero: function() {
|
||||
return textArray[textArray.length - 1] === "";
|
||||
},
|
||||
startNew: function()
|
||||
{
|
||||
startNew: function() {
|
||||
textArray.push("");
|
||||
self.flush(true);
|
||||
attribsBuilder = Changeset.smartOpAssembler();
|
||||
},
|
||||
textOfLine: function(i)
|
||||
{
|
||||
textOfLine: function(i) {
|
||||
return textArray[i];
|
||||
},
|
||||
appendText: function(txt, attrString)
|
||||
{
|
||||
appendText: function(txt, attrString) {
|
||||
textArray[textArray.length - 1] += txt;
|
||||
//dmesg(txt+" / "+attrString);
|
||||
op.attribs = attrString;
|
||||
op.chars = txt.length;
|
||||
attribsBuilder.append(op);
|
||||
},
|
||||
textLines: function()
|
||||
{
|
||||
textLines: function() {
|
||||
return textArray.slice();
|
||||
},
|
||||
attribLines: function()
|
||||
{
|
||||
attribLines: function() {
|
||||
return attribsArray;
|
||||
},
|
||||
// call flush only when you're done
|
||||
flush: function(withNewline)
|
||||
{
|
||||
flush: function(withNewline) {
|
||||
if (attribsBuilder)
|
||||
{
|
||||
attribsArray.push(attribsBuilder.toString());
|
||||
|
@ -164,8 +142,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
}());
|
||||
var cc = {};
|
||||
|
||||
function _ensureColumnZero(state)
|
||||
{
|
||||
function _ensureColumnZero(state) {
|
||||
if (!lines.atColumnZero())
|
||||
{
|
||||
cc.startNewLine(state);
|
||||
|
@ -174,8 +151,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
var selection, startPoint, endPoint;
|
||||
var selStart = [-1, -1],
|
||||
selEnd = [-1, -1];
|
||||
function _isEmpty(node, state)
|
||||
{
|
||||
function _isEmpty(node, state) {
|
||||
// consider clean blank lines pasted in IE to be empty
|
||||
if (dom.nodeNumChildren(node) == 0) return true;
|
||||
if (dom.nodeNumChildren(node) == 1 && getAssoc(node, "shouldBeEmpty") && dom.optNodeInnerHTML(node) == " " && !getAssoc(node, "unpasted"))
|
||||
|
@ -191,8 +167,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
return false;
|
||||
}
|
||||
|
||||
function _pointHere(charsAfter, state)
|
||||
{
|
||||
function _pointHere(charsAfter, state) {
|
||||
var ln = lines.length() - 1;
|
||||
var chr = lines.textOfLine(ln).length;
|
||||
if (chr == 0 && !_.isEmpty(state.lineAttributes))
|
||||
|
@ -203,13 +178,11 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
return [ln, chr];
|
||||
}
|
||||
|
||||
function _reachBlockPoint(nd, idx, state)
|
||||
{
|
||||
function _reachBlockPoint(nd, idx, state) {
|
||||
if (!dom.isNodeText(nd)) _reachPoint(nd, idx, state);
|
||||
}
|
||||
|
||||
function _reachPoint(nd, idx, state)
|
||||
{
|
||||
function _reachPoint(nd, idx, state) {
|
||||
if (startPoint && nd == startPoint.node && startPoint.index == idx)
|
||||
{
|
||||
selStart = _pointHere(0, state);
|
||||
|
@ -219,16 +192,13 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
selEnd = _pointHere(0, state);
|
||||
}
|
||||
}
|
||||
cc.incrementFlag = function(state, flagName)
|
||||
{
|
||||
cc.incrementFlag = function(state, flagName) {
|
||||
state.flags[flagName] = (state.flags[flagName] || 0) + 1;
|
||||
}
|
||||
cc.decrementFlag = function(state, flagName)
|
||||
{
|
||||
cc.decrementFlag = function(state, flagName) {
|
||||
state.flags[flagName]--;
|
||||
}
|
||||
cc.incrementAttrib = function(state, attribName)
|
||||
{
|
||||
cc.incrementAttrib = function(state, attribName) {
|
||||
if (!state.attribs[attribName])
|
||||
{
|
||||
state.attribs[attribName] = 1;
|
||||
|
@ -239,14 +209,12 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
}
|
||||
_recalcAttribString(state);
|
||||
}
|
||||
cc.decrementAttrib = function(state, attribName)
|
||||
{
|
||||
cc.decrementAttrib = function(state, attribName) {
|
||||
state.attribs[attribName]--;
|
||||
_recalcAttribString(state);
|
||||
}
|
||||
|
||||
function _enterList(state, listType)
|
||||
{
|
||||
function _enterList(state, listType) {
|
||||
if(!listType) return;
|
||||
var oldListType = state.lineAttributes['list'];
|
||||
if (listType != 'none')
|
||||
|
@ -268,8 +236,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
return oldListType;
|
||||
}
|
||||
|
||||
function _exitList(state, oldListType)
|
||||
{
|
||||
function _exitList(state, oldListType) {
|
||||
if (state.lineAttributes['list']) {
|
||||
state.listNesting--;
|
||||
}
|
||||
|
@ -283,8 +250,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
_recalcAttribString(state);
|
||||
}
|
||||
|
||||
function _enterAuthor(state, author)
|
||||
{
|
||||
function _enterAuthor(state, author) {
|
||||
var oldAuthor = state.author;
|
||||
state.authorLevel = (state.authorLevel || 0) + 1;
|
||||
state.author = author;
|
||||
|
@ -292,15 +258,13 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
return oldAuthor;
|
||||
}
|
||||
|
||||
function _exitAuthor(state, oldAuthor)
|
||||
{
|
||||
function _exitAuthor(state, oldAuthor) {
|
||||
state.authorLevel--;
|
||||
state.author = oldAuthor;
|
||||
_recalcAttribString(state);
|
||||
}
|
||||
|
||||
function _recalcAttribString(state)
|
||||
{
|
||||
function _recalcAttribString(state) {
|
||||
var lst = [];
|
||||
for (var a in state.attribs)
|
||||
{
|
||||
|
@ -338,8 +302,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
state.attribString = Changeset.makeAttribsString('+', lst, apool);
|
||||
}
|
||||
|
||||
function _produceLineAttributesMarker(state)
|
||||
{
|
||||
function _produceLineAttributesMarker(state) {
|
||||
// TODO: This has to go to AttributeManager.
|
||||
var attributes = [
|
||||
['lmkr', '1'],
|
||||
|
@ -351,8 +314,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
);
|
||||
lines.appendText('*', Changeset.makeAttribsString('+', attributes , apool));
|
||||
}
|
||||
cc.startNewLine = function(state)
|
||||
{
|
||||
cc.startNewLine = function(state) {
|
||||
if (state)
|
||||
{
|
||||
var atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0;
|
||||
|
@ -363,8 +325,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
}
|
||||
lines.startNew();
|
||||
}
|
||||
cc.notifySelection = function(sel)
|
||||
{
|
||||
cc.notifySelection = function(sel) {
|
||||
if (sel)
|
||||
{
|
||||
selection = sel;
|
||||
|
@ -372,14 +333,12 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
endPoint = selection.endPoint;
|
||||
}
|
||||
};
|
||||
cc.doAttrib = function(state, na)
|
||||
{
|
||||
cc.doAttrib = function(state, na) {
|
||||
state.localAttribs = (state.localAttribs || []);
|
||||
state.localAttribs.push(na);
|
||||
cc.incrementAttrib(state, na);
|
||||
};
|
||||
cc.collectContent = function(node, state)
|
||||
{
|
||||
cc.collectContent = function(node, state) {
|
||||
if (!state)
|
||||
{
|
||||
state = {
|
||||
|
@ -746,8 +705,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
state.localAttribs = localAttribs;
|
||||
};
|
||||
// can pass a falsy value for end of doc
|
||||
cc.notifyNextNode = function(node)
|
||||
{
|
||||
cc.notifyNextNode = function(node) {
|
||||
// an "empty block" won't end a line; this addresses an issue in IE with
|
||||
// typing into a blank line at the end of the document. typed text
|
||||
// goes into the body, and the empty line div still looks clean.
|
||||
|
@ -759,25 +717,21 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
}
|
||||
};
|
||||
// each returns [line, char] or [-1,-1]
|
||||
var getSelectionStart = function()
|
||||
{
|
||||
var getSelectionStart = function() {
|
||||
return selStart;
|
||||
};
|
||||
var getSelectionEnd = function()
|
||||
{
|
||||
var getSelectionEnd = function() {
|
||||
return selEnd;
|
||||
};
|
||||
|
||||
// returns array of strings for lines found, last entry will be "" if
|
||||
// last line is complete (i.e. if a following span should be on a new line).
|
||||
// can be called at any point
|
||||
cc.getLines = function()
|
||||
{
|
||||
cc.getLines = function() {
|
||||
return lines.textLines();
|
||||
};
|
||||
|
||||
cc.finish = function()
|
||||
{
|
||||
cc.finish = function() {
|
||||
lines.flush();
|
||||
var lineAttribs = lines.attribLines();
|
||||
var lineStrings = cc.getLines();
|
||||
|
@ -788,8 +742,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
var ss = getSelectionStart();
|
||||
var se = getSelectionEnd();
|
||||
|
||||
function fixLongLines()
|
||||
{
|
||||
function fixLongLines() {
|
||||
// design mode does not deal with with really long lines!
|
||||
var lineLimit = 2000; // chars
|
||||
var buffer = 10; // chars allowed over before wrapping
|
||||
|
@ -819,8 +772,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
|||
newAttribStrings.push(oldAttribString);
|
||||
}
|
||||
|
||||
function fixLineNumber(lineChar)
|
||||
{
|
||||
function fixLineNumber(lineChar) {
|
||||
if (lineChar[0] < 0) return;
|
||||
var n = lineChar[0];
|
||||
var c = lineChar[1];
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function makeCSSManager(emptyStylesheetTitle, doc)
|
||||
{
|
||||
function makeCSSManager(emptyStylesheetTitle, doc) {
|
||||
if (doc === true)
|
||||
{
|
||||
doc = 'parent';
|
||||
|
@ -29,8 +28,7 @@ function makeCSSManager(emptyStylesheetTitle, doc)
|
|||
doc = 'inner';
|
||||
}
|
||||
|
||||
function getSheetByTitle(title)
|
||||
{
|
||||
function getSheetByTitle(title) {
|
||||
if (doc === 'parent')
|
||||
{
|
||||
win = window.parent.parent;
|
||||
|
@ -59,26 +57,22 @@ function makeCSSManager(emptyStylesheetTitle, doc)
|
|||
|
||||
var browserSheet = getSheetByTitle(emptyStylesheetTitle);
|
||||
|
||||
function browserRules()
|
||||
{
|
||||
function browserRules() {
|
||||
return (browserSheet.cssRules || browserSheet.rules);
|
||||
}
|
||||
|
||||
function browserDeleteRule(i)
|
||||
{
|
||||
function browserDeleteRule(i) {
|
||||
if (browserSheet.deleteRule) browserSheet.deleteRule(i);
|
||||
else browserSheet.removeRule(i);
|
||||
}
|
||||
|
||||
function browserInsertRule(i, selector)
|
||||
{
|
||||
function browserInsertRule(i, selector) {
|
||||
if (browserSheet.insertRule) browserSheet.insertRule(selector + ' {}', i);
|
||||
else browserSheet.addRule(selector, null, i);
|
||||
}
|
||||
var selectorList = [];
|
||||
|
||||
function indexOfSelector(selector)
|
||||
{
|
||||
function indexOfSelector(selector) {
|
||||
for (var i = 0; i < selectorList.length; i++)
|
||||
{
|
||||
if (selectorList[i] == selector)
|
||||
|
@ -89,8 +83,7 @@ function makeCSSManager(emptyStylesheetTitle, doc)
|
|||
return -1;
|
||||
}
|
||||
|
||||
function selectorStyle(selector)
|
||||
{
|
||||
function selectorStyle(selector) {
|
||||
var i = indexOfSelector(selector);
|
||||
if (i < 0)
|
||||
{
|
||||
|
@ -102,8 +95,7 @@ function makeCSSManager(emptyStylesheetTitle, doc)
|
|||
return browserRules().item(i).style;
|
||||
}
|
||||
|
||||
function removeSelectorStyle(selector)
|
||||
{
|
||||
function removeSelectorStyle(selector) {
|
||||
var i = indexOfSelector(selector);
|
||||
if (i >= 0)
|
||||
{
|
||||
|
@ -115,8 +107,7 @@ function makeCSSManager(emptyStylesheetTitle, doc)
|
|||
return {
|
||||
selectorStyle: selectorStyle,
|
||||
removeSelectorStyle: removeSelectorStyle,
|
||||
info: function()
|
||||
{
|
||||
info: function() {
|
||||
return selectorList.length + ":" + browserRules().length;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -35,13 +35,11 @@ var noop = function(){};
|
|||
|
||||
var domline = {};
|
||||
|
||||
domline.addToLineClass = function(lineClass, cls)
|
||||
{
|
||||
domline.addToLineClass = function(lineClass, cls) {
|
||||
// an "empty span" at any point can be used to add classes to
|
||||
// the line, using line:className. otherwise, we ignore
|
||||
// the span.
|
||||
cls.replace(/\S+/g, function(c)
|
||||
{
|
||||
cls.replace(/\S+/g, function(c) {
|
||||
if (c.indexOf("line:") == 0)
|
||||
{
|
||||
// add class to line
|
||||
|
@ -53,8 +51,7 @@ domline.addToLineClass = function(lineClass, cls)
|
|||
|
||||
// if "document" is falsy we don't create a DOM node, just
|
||||
// an object with innerHTML and className
|
||||
domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||
{
|
||||
domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument) {
|
||||
var result = {
|
||||
node: null,
|
||||
appendSpan: noop,
|
||||
|
@ -84,8 +81,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
postHtml = '';
|
||||
var curHTML = null;
|
||||
|
||||
function processSpaces(s)
|
||||
{
|
||||
function processSpaces(s) {
|
||||
return domline.processSpaces(s, doesWrap);
|
||||
}
|
||||
|
||||
|
@ -93,8 +89,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
var perHtmlLineProcess = (doesWrap ? processSpaces : _.identity);
|
||||
var lineClass = 'ace-line';
|
||||
|
||||
result.appendSpan = function(txt, cls)
|
||||
{
|
||||
result.appendSpan = function(txt, cls) {
|
||||
|
||||
var processedMarker = false;
|
||||
// Handle lineAttributeMarker, if present
|
||||
|
@ -106,8 +101,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
_.map(hooks.callAll("aceDomLinePreProcessLineAttributes", {
|
||||
domline: domline,
|
||||
cls: cls
|
||||
}), function(modifier)
|
||||
{
|
||||
}), function(modifier) {
|
||||
preHtml += modifier.preHtml;
|
||||
postHtml += modifier.postHtml;
|
||||
processedMarker |= modifier.processedMarker;
|
||||
|
@ -141,8 +135,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
_.map(hooks.callAll("aceDomLineProcessLineAttributes", {
|
||||
domline: domline,
|
||||
cls: cls
|
||||
}), function(modifier)
|
||||
{
|
||||
}), function(modifier) {
|
||||
preHtml += modifier.preHtml;
|
||||
postHtml += modifier.postHtml;
|
||||
processedMarker |= modifier.processedMarker;
|
||||
|
@ -156,16 +149,14 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
var simpleTags = null;
|
||||
if (cls.indexOf('url') >= 0)
|
||||
{
|
||||
cls = cls.replace(/(^| )url:(\S+)/g, function(x0, space, url)
|
||||
{
|
||||
cls = cls.replace(/(^| )url:(\S+)/g, function(x0, space, url) {
|
||||
href = url;
|
||||
return space + "url";
|
||||
});
|
||||
}
|
||||
if (cls.indexOf('tag') >= 0)
|
||||
{
|
||||
cls = cls.replace(/(^| )tag:(\S+)/g, function(x0, space, tag)
|
||||
{
|
||||
cls = cls.replace(/(^| )tag:(\S+)/g, function(x0, space, tag) {
|
||||
if (!simpleTags) simpleTags = [];
|
||||
simpleTags.push(tag.toLowerCase());
|
||||
return space + tag;
|
||||
|
@ -178,8 +169,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
_.map(hooks.callAll("aceCreateDomLine", {
|
||||
domline: domline,
|
||||
cls: cls
|
||||
}), function(modifier)
|
||||
{
|
||||
}), function(modifier) {
|
||||
cls = modifier.cls;
|
||||
extraOpenTags = extraOpenTags + modifier.extraOpenTags;
|
||||
extraCloseTags = modifier.extraCloseTags + extraCloseTags;
|
||||
|
@ -218,15 +208,13 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
html.push('<span class="', Security.escapeHTMLAttribute(cls || ''), '">', extraOpenTags, perTextNodeProcess(Security.escapeHTML(txt)), extraCloseTags, '</span>');
|
||||
}
|
||||
};
|
||||
result.clearSpans = function()
|
||||
{
|
||||
result.clearSpans = function() {
|
||||
html = [];
|
||||
lineClass = 'ace-line';
|
||||
result.lineMarker = 0;
|
||||
};
|
||||
|
||||
function writeHTML()
|
||||
{
|
||||
function writeHTML() {
|
||||
var newHTML = perHtmlLineProcess(html.join(''));
|
||||
if (!newHTML)
|
||||
{
|
||||
|
@ -257,23 +245,20 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
|||
}
|
||||
result.prepareForAdd = writeHTML;
|
||||
result.finishUpdate = writeHTML;
|
||||
result.getInnerHTML = function()
|
||||
{
|
||||
result.getInnerHTML = function() {
|
||||
return curHTML || '';
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
domline.processSpaces = function(s, doesWrap)
|
||||
{
|
||||
domline.processSpaces = function(s, doesWrap) {
|
||||
if (s.indexOf("<") < 0 && !doesWrap)
|
||||
{
|
||||
// short-cut
|
||||
return s.replace(/ /g, ' ');
|
||||
}
|
||||
var parts = [];
|
||||
s.replace(/<[^>]*>?| |[^ <]+/g, function(m)
|
||||
{
|
||||
s.replace(/<[^>]*>?| |[^ <]+/g, function(m) {
|
||||
parts.push(m);
|
||||
});
|
||||
if (doesWrap)
|
||||
|
|
|
@ -44,10 +44,8 @@ linestylefilter.ATTRIB_CLASSES = {
|
|||
var lineAttributeMarker = 'lineAttribMarker';
|
||||
exports.lineAttributeMarker = lineAttributeMarker;
|
||||
|
||||
linestylefilter.getAuthorClassName = function(author)
|
||||
{
|
||||
return "author-" + author.replace(/[^a-y0-9]/g, function(c)
|
||||
{
|
||||
linestylefilter.getAuthorClassName = function(author) {
|
||||
return "author-" + author.replace(/[^a-y0-9]/g, function(c) {
|
||||
if (c == ".") return "-";
|
||||
return 'z' + c.charCodeAt(0) + 'z';
|
||||
});
|
||||
|
@ -55,8 +53,7 @@ linestylefilter.getAuthorClassName = function(author)
|
|||
|
||||
// lineLength is without newline; aline includes newline,
|
||||
// but may be falsy if lineLength == 0
|
||||
linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFunc, apool)
|
||||
{
|
||||
linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFunc, apool) {
|
||||
|
||||
// Plugin Hook to add more Attrib Classes
|
||||
for (const attribClasses of hooks.callAll('aceAttribClasses', linestylefilter.ATTRIB_CLASSES)) {
|
||||
|
@ -67,21 +64,18 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
|||
|
||||
var nextAfterAuthorColors = textAndClassFunc;
|
||||
|
||||
var authorColorFunc = (function()
|
||||
{
|
||||
var authorColorFunc = (function() {
|
||||
var lineEnd = lineLength;
|
||||
var curIndex = 0;
|
||||
var extraClasses;
|
||||
var leftInAuthor;
|
||||
|
||||
function attribsToClasses(attribs)
|
||||
{
|
||||
function attribsToClasses(attribs) {
|
||||
var classes = '';
|
||||
var isLineAttribMarker = false;
|
||||
|
||||
// For each attribute number
|
||||
Changeset.eachAttribNumber(attribs, function(n)
|
||||
{
|
||||
Changeset.eachAttribNumber(attribs, function(n) {
|
||||
// Give us this attributes key
|
||||
var key = apool.getAttribKey(n);
|
||||
if (key)
|
||||
|
@ -127,15 +121,13 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
|||
var attributionIter = Changeset.opIterator(aline);
|
||||
var nextOp, nextOpClasses;
|
||||
|
||||
function goNextOp()
|
||||
{
|
||||
function goNextOp() {
|
||||
nextOp = attributionIter.next();
|
||||
nextOpClasses = (nextOp.opcode && attribsToClasses(nextOp.attribs));
|
||||
}
|
||||
goNextOp();
|
||||
|
||||
function nextClasses()
|
||||
{
|
||||
function nextClasses() {
|
||||
if (curIndex < lineEnd)
|
||||
{
|
||||
extraClasses = nextOpClasses;
|
||||
|
@ -150,8 +142,7 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
|||
}
|
||||
nextClasses();
|
||||
|
||||
return function(txt, cls)
|
||||
{
|
||||
return function(txt, cls) {
|
||||
|
||||
var disableAuthColorForThisLine = hooks.callAll("disableAuthorColorsForThisLine", {
|
||||
linestylefilter: linestylefilter,
|
||||
|
@ -186,8 +177,7 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
|||
return authorColorFunc;
|
||||
};
|
||||
|
||||
linestylefilter.getAtSignSplitterFilter = function(lineText, textAndClassFunc)
|
||||
{
|
||||
linestylefilter.getAtSignSplitterFilter = function(lineText, textAndClassFunc) {
|
||||
var at = /@/g;
|
||||
at.lastIndex = 0;
|
||||
var splitPoints = null;
|
||||
|
@ -206,10 +196,8 @@ linestylefilter.getAtSignSplitterFilter = function(lineText, textAndClassFunc)
|
|||
return linestylefilter.textAndClassFuncSplitter(textAndClassFunc, splitPoints);
|
||||
};
|
||||
|
||||
linestylefilter.getRegexpFilter = function(regExp, tag)
|
||||
{
|
||||
return function(lineText, textAndClassFunc)
|
||||
{
|
||||
linestylefilter.getRegexpFilter = function(regExp, tag) {
|
||||
return function(lineText, textAndClassFunc) {
|
||||
regExp.lastIndex = 0;
|
||||
var regExpMatchs = null;
|
||||
var splitPoints = null;
|
||||
|
@ -229,8 +217,7 @@ linestylefilter.getRegexpFilter = function(regExp, tag)
|
|||
|
||||
if (!regExpMatchs) return textAndClassFunc;
|
||||
|
||||
function regExpMatchForIndex(idx)
|
||||
{
|
||||
function regExpMatchForIndex(idx) {
|
||||
for (var k = 0; k < regExpMatchs.length; k++)
|
||||
{
|
||||
var u = regExpMatchs[k];
|
||||
|
@ -242,11 +229,9 @@ linestylefilter.getRegexpFilter = function(regExp, tag)
|
|||
return false;
|
||||
}
|
||||
|
||||
var handleRegExpMatchsAfterSplit = (function()
|
||||
{
|
||||
var handleRegExpMatchsAfterSplit = (function() {
|
||||
var curIndex = 0;
|
||||
return function(txt, cls)
|
||||
{
|
||||
return function(txt, cls) {
|
||||
var txtlen = txt.length;
|
||||
var newCls = cls;
|
||||
var regExpMatch = regExpMatchForIndex(curIndex);
|
||||
|
@ -270,8 +255,7 @@ linestylefilter.REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|nfs):\/\/|(
|
|||
linestylefilter.getURLFilter = linestylefilter.getRegexpFilter(
|
||||
linestylefilter.REGEX_URL, 'url');
|
||||
|
||||
linestylefilter.textAndClassFuncSplitter = function(func, splitPointsOpt)
|
||||
{
|
||||
linestylefilter.textAndClassFuncSplitter = function(func, splitPointsOpt) {
|
||||
var nextPointIndex = 0;
|
||||
var idx = 0;
|
||||
|
||||
|
@ -281,8 +265,7 @@ linestylefilter.textAndClassFuncSplitter = function(func, splitPointsOpt)
|
|||
nextPointIndex++;
|
||||
}
|
||||
|
||||
function spanHandler(txt, cls)
|
||||
{
|
||||
function spanHandler(txt, cls) {
|
||||
if ((!splitPointsOpt) || nextPointIndex >= splitPointsOpt.length)
|
||||
{
|
||||
func(txt, cls);
|
||||
|
@ -318,16 +301,14 @@ linestylefilter.textAndClassFuncSplitter = function(func, splitPointsOpt)
|
|||
return spanHandler;
|
||||
};
|
||||
|
||||
linestylefilter.getFilterStack = function(lineText, textAndClassFunc, abrowser)
|
||||
{
|
||||
linestylefilter.getFilterStack = function(lineText, textAndClassFunc, abrowser) {
|
||||
var func = linestylefilter.getURLFilter(lineText, textAndClassFunc);
|
||||
|
||||
var hookFilters = hooks.callAll("aceGetFilterStack", {
|
||||
linestylefilter: linestylefilter,
|
||||
browser: abrowser
|
||||
});
|
||||
_.map(hookFilters ,function(hookFilter)
|
||||
{
|
||||
_.map(hookFilters ,function(hookFilter) {
|
||||
func = hookFilter(lineText, func);
|
||||
});
|
||||
|
||||
|
@ -343,8 +324,7 @@ linestylefilter.getFilterStack = function(lineText, textAndClassFunc, abrowser)
|
|||
};
|
||||
|
||||
// domLineObj is like that returned by domline.createDomLine
|
||||
linestylefilter.populateDomLine = function(textLine, aline, apool, domLineObj)
|
||||
{
|
||||
linestylefilter.populateDomLine = function(textLine, aline, apool, domLineObj) {
|
||||
// remove final newline from text if any
|
||||
var text = textLine;
|
||||
if (text.slice(-1) == '\n')
|
||||
|
@ -352,8 +332,7 @@ linestylefilter.populateDomLine = function(textLine, aline, apool, domLineObj)
|
|||
text = text.substring(0, text.length - 1);
|
||||
}
|
||||
|
||||
function textAndClassFunc(tokenText, tokenClass)
|
||||
{
|
||||
function textAndClassFunc(tokenText, tokenClass) {
|
||||
domLineObj.appendSpan(tokenText, tokenClass);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ var hooks = require('./pluginfw/hooks');
|
|||
|
||||
var receivedClientVars = false;
|
||||
|
||||
function randomString()
|
||||
{
|
||||
function randomString() {
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var string_length = 20;
|
||||
var randomstring = '';
|
||||
|
@ -85,8 +84,7 @@ var getParameters = [
|
|||
{ name: "lang", checkVal: null, callback: function(val) { window.html10n.localize([val, 'en']); Cookies.set('language', val); } },
|
||||
];
|
||||
|
||||
function getParams()
|
||||
{
|
||||
function getParams() {
|
||||
// Tries server enforced options first..
|
||||
for(var i = 0; i < getParameters.length; i++)
|
||||
{
|
||||
|
@ -113,8 +111,7 @@ function getParams()
|
|||
}
|
||||
}
|
||||
|
||||
function getUrlVars()
|
||||
{
|
||||
function getUrlVars() {
|
||||
var vars = [], hash;
|
||||
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
|
||||
for(var i = 0; i < hashes.length; i++)
|
||||
|
@ -126,8 +123,7 @@ function getUrlVars()
|
|||
return vars;
|
||||
}
|
||||
|
||||
function sendClientReady(isReconnect, messageType)
|
||||
{
|
||||
function sendClientReady(isReconnect, messageType) {
|
||||
messageType = typeof messageType !== 'undefined' ? messageType : 'CLIENT_READY';
|
||||
var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1);
|
||||
padId = decodeURIComponent(padId); // unescape neccesary due to Safari and Opera interpretation of spaces
|
||||
|
@ -164,8 +160,7 @@ function sendClientReady(isReconnect, messageType)
|
|||
socket.json.send(msg);
|
||||
}
|
||||
|
||||
function handshake()
|
||||
{
|
||||
function handshake() {
|
||||
var loc = document.location;
|
||||
//get the correct port
|
||||
var port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port;
|
||||
|
@ -225,8 +220,7 @@ function handshake()
|
|||
|
||||
var initalized = false;
|
||||
|
||||
socket.on('message', function(obj)
|
||||
{
|
||||
socket.on('message', function(obj) {
|
||||
//the access was not granted, give the user a message
|
||||
if(obj.accessStatus)
|
||||
{
|
||||
|
@ -354,48 +348,37 @@ var pad = {
|
|||
padOptions: {},
|
||||
|
||||
// these don't require init; clientVars should all go through here
|
||||
getPadId: function()
|
||||
{
|
||||
getPadId: function() {
|
||||
return clientVars.padId;
|
||||
},
|
||||
getClientIp: function()
|
||||
{
|
||||
getClientIp: function() {
|
||||
return clientVars.clientIp;
|
||||
},
|
||||
getColorPalette: function()
|
||||
{
|
||||
getColorPalette: function() {
|
||||
return clientVars.colorPalette;
|
||||
},
|
||||
getDisplayUserAgent: function()
|
||||
{
|
||||
getDisplayUserAgent: function() {
|
||||
return padutils.uaDisplay(clientVars.userAgent);
|
||||
},
|
||||
getIsDebugEnabled: function()
|
||||
{
|
||||
getIsDebugEnabled: function() {
|
||||
return clientVars.debugEnabled;
|
||||
},
|
||||
getPrivilege: function(name)
|
||||
{
|
||||
getPrivilege: function(name) {
|
||||
return clientVars.accountPrivs[name];
|
||||
},
|
||||
getUserIsGuest: function()
|
||||
{
|
||||
getUserIsGuest: function() {
|
||||
return clientVars.userIsGuest;
|
||||
},
|
||||
getUserId: function()
|
||||
{
|
||||
getUserId: function() {
|
||||
return pad.myUserInfo.userId;
|
||||
},
|
||||
getUserName: function()
|
||||
{
|
||||
getUserName: function() {
|
||||
return pad.myUserInfo.name;
|
||||
},
|
||||
userList: function()
|
||||
{
|
||||
userList: function() {
|
||||
return paduserlist.users();
|
||||
},
|
||||
switchToPad: function(padId)
|
||||
{
|
||||
switchToPad: function(padId) {
|
||||
var newHref = new RegExp(/.*\/p\/[^\/]+/).exec(document.location.pathname) || clientVars.padId;
|
||||
newHref = newHref[0];
|
||||
|
||||
|
@ -430,17 +413,14 @@ var pad = {
|
|||
window.location.href = newHref;
|
||||
}
|
||||
},
|
||||
sendClientMessage: function(msg)
|
||||
{
|
||||
sendClientMessage: function(msg) {
|
||||
pad.collabClient.sendClientMessage(msg);
|
||||
},
|
||||
|
||||
init: function()
|
||||
{
|
||||
init: function() {
|
||||
padutils.setupGlobalExceptionHandler();
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
$(document).ready(function() {
|
||||
// start the custom js
|
||||
if (typeof customStart == "function") customStart();
|
||||
handshake();
|
||||
|
@ -451,8 +431,7 @@ var pad = {
|
|||
padcookie.init();
|
||||
});
|
||||
},
|
||||
_afterHandshake: function()
|
||||
{
|
||||
_afterHandshake: function() {
|
||||
pad.clientTimeOffset = Date.now() - clientVars.serverTimestamp;
|
||||
//initialize the chat
|
||||
chat.init(this);
|
||||
|
@ -514,11 +493,9 @@ var pad = {
|
|||
$("#chatloadmessagesbutton").css("display", "none");
|
||||
}
|
||||
|
||||
function postAceInit()
|
||||
{
|
||||
function postAceInit() {
|
||||
padeditbar.init();
|
||||
setTimeout(function()
|
||||
{
|
||||
setTimeout(function() {
|
||||
padeditor.ace.focus();
|
||||
}, 0);
|
||||
if(padcookie.getPref("chatAlwaysVisible")){ // if we have a cookie for always showing chat then show it
|
||||
|
@ -557,22 +534,18 @@ var pad = {
|
|||
hooks.aCallAll("postAceInit", {ace: padeditor.ace, pad: pad});
|
||||
}
|
||||
},
|
||||
dispose: function()
|
||||
{
|
||||
dispose: function() {
|
||||
padeditor.dispose();
|
||||
},
|
||||
notifyChangeName: function(newName)
|
||||
{
|
||||
notifyChangeName: function(newName) {
|
||||
pad.myUserInfo.name = newName;
|
||||
pad.collabClient.updateUserInfo(pad.myUserInfo);
|
||||
},
|
||||
notifyChangeColor: function(newColorId)
|
||||
{
|
||||
notifyChangeColor: function(newColorId) {
|
||||
pad.myUserInfo.colorId = newColorId;
|
||||
pad.collabClient.updateUserInfo(pad.myUserInfo);
|
||||
},
|
||||
changePadOption: function(key, value)
|
||||
{
|
||||
changePadOption: function(key, value) {
|
||||
var options = {};
|
||||
options[key] = value;
|
||||
pad.handleOptionsChange(options);
|
||||
|
@ -583,16 +556,14 @@ var pad = {
|
|||
changedBy: pad.myUserInfo.name || "unnamed"
|
||||
});
|
||||
},
|
||||
changeViewOption: function(key, value)
|
||||
{
|
||||
changeViewOption: function(key, value) {
|
||||
var options = {
|
||||
view: {}
|
||||
};
|
||||
options.view[key] = value;
|
||||
pad.handleOptionsChange(options);
|
||||
},
|
||||
handleOptionsChange: function(opts)
|
||||
{
|
||||
handleOptionsChange: function(opts) {
|
||||
// opts object is a full set of options or just
|
||||
// some options to change
|
||||
if (opts.view)
|
||||
|
@ -614,17 +585,14 @@ var pad = {
|
|||
pad.padOptions.guestPolicy = opts.guestPolicy;
|
||||
}
|
||||
},
|
||||
getPadOptions: function()
|
||||
{
|
||||
getPadOptions: function() {
|
||||
// caller shouldn't mutate the object
|
||||
return pad.padOptions;
|
||||
},
|
||||
isPadPublic: function()
|
||||
{
|
||||
isPadPublic: function() {
|
||||
return pad.getPadOptions().guestPolicy == 'allow';
|
||||
},
|
||||
suggestUserName: function(userId, name)
|
||||
{
|
||||
suggestUserName: function(userId, name) {
|
||||
pad.collabClient.sendClientMessage(
|
||||
{
|
||||
type: 'suggestUserName',
|
||||
|
@ -632,20 +600,16 @@ var pad = {
|
|||
newName: name
|
||||
});
|
||||
},
|
||||
handleUserJoin: function(userInfo)
|
||||
{
|
||||
handleUserJoin: function(userInfo) {
|
||||
paduserlist.userJoinOrUpdate(userInfo);
|
||||
},
|
||||
handleUserUpdate: function(userInfo)
|
||||
{
|
||||
handleUserUpdate: function(userInfo) {
|
||||
paduserlist.userJoinOrUpdate(userInfo);
|
||||
},
|
||||
handleUserLeave: function(userInfo)
|
||||
{
|
||||
handleUserLeave: function(userInfo) {
|
||||
paduserlist.userLeave(userInfo);
|
||||
},
|
||||
handleClientMessage: function(msg)
|
||||
{
|
||||
handleClientMessage: function(msg) {
|
||||
if (msg.type == 'suggestUserName')
|
||||
{
|
||||
if (msg.unnamedId == pad.myUserInfo.userId && msg.newName && !pad.myUserInfo.name)
|
||||
|
@ -673,8 +637,7 @@ var pad = {
|
|||
paduserlist.removeGuestPrompt(msg.guestId);
|
||||
}
|
||||
},
|
||||
dmesg: function(m)
|
||||
{
|
||||
dmesg: function(m) {
|
||||
if (pad.getIsDebugEnabled())
|
||||
{
|
||||
var djs = $('#djs').get(0);
|
||||
|
@ -686,14 +649,12 @@ var pad = {
|
|||
}
|
||||
}
|
||||
},
|
||||
handleServerMessage: function(m)
|
||||
{
|
||||
handleServerMessage: function(m) {
|
||||
if (m.type == 'NOTICE')
|
||||
{
|
||||
if (m.text)
|
||||
{
|
||||
alertBar.displayMessage(function(abar)
|
||||
{
|
||||
alertBar.displayMessage(function(abar) {
|
||||
abar.find("#servermsgdate").text(" (" + padutils.simpleDateTime(new Date) + ")");
|
||||
abar.find("#servermsgtext").text(m.text);
|
||||
});
|
||||
|
@ -708,8 +669,7 @@ var pad = {
|
|||
paduserlist.showGuestPrompt(m.userId, m.displayName);
|
||||
}
|
||||
},
|
||||
handleChannelStateChange: function(newState, message)
|
||||
{
|
||||
handleChannelStateChange: function(newState, message) {
|
||||
var oldFullyConnected = !! padconnectionstatus.isFullyConnected();
|
||||
var wasConnecting = (padconnectionstatus.getStatus().what == 'connecting');
|
||||
if (newState == "CONNECTED")
|
||||
|
@ -762,8 +722,7 @@ var pad = {
|
|||
pad.handleIsFullyConnected(newFullyConnected, wasConnecting);
|
||||
}
|
||||
},
|
||||
handleIsFullyConnected: function(isConnected, isInitialConnect)
|
||||
{
|
||||
handleIsFullyConnected: function(isConnected, isInitialConnect) {
|
||||
pad.determineChatVisibility(isConnected && !isInitialConnect);
|
||||
pad.determineChatAndUsersVisibility(isConnected && !isInitialConnect);
|
||||
pad.determineAuthorshipColorsVisibility();
|
||||
|
@ -801,8 +760,7 @@ var pad = {
|
|||
$('#options-colorscheck').prop("checked", false);
|
||||
}
|
||||
},
|
||||
handleCollabAction: function(action)
|
||||
{
|
||||
handleCollabAction: function(action) {
|
||||
if (action == "commitPerformed")
|
||||
{
|
||||
padeditbar.setSyncStatus("syncing");
|
||||
|
@ -812,14 +770,11 @@ var pad = {
|
|||
padeditbar.setSyncStatus("done");
|
||||
}
|
||||
},
|
||||
hideServerMessage: function()
|
||||
{
|
||||
hideServerMessage: function() {
|
||||
alertBar.hideMessage();
|
||||
},
|
||||
asyncSendDiagnosticInfo: function()
|
||||
{
|
||||
window.setTimeout(function()
|
||||
{
|
||||
asyncSendDiagnosticInfo: function() {
|
||||
window.setTimeout(function() {
|
||||
$.ajax(
|
||||
{
|
||||
type: 'post',
|
||||
|
@ -827,15 +782,12 @@ var pad = {
|
|||
data: {
|
||||
diagnosticInfo: JSON.stringify(pad.diagnosticInfo)
|
||||
},
|
||||
success: function()
|
||||
{},
|
||||
error: function()
|
||||
{}
|
||||
success: function() {},
|
||||
error: function() {}
|
||||
});
|
||||
}, 0);
|
||||
},
|
||||
forceReconnect: function()
|
||||
{
|
||||
forceReconnect: function() {
|
||||
$('form#reconnectform input.padId').val(pad.getPadId());
|
||||
pad.diagnosticInfo.collabDiagnosticInfo = pad.collabClient.getDiagnosticInfo();
|
||||
$('form#reconnectform input.diagnosticInfo').val(JSON.stringify(pad.diagnosticInfo));
|
||||
|
@ -843,28 +795,22 @@ var pad = {
|
|||
$('form#reconnectform').submit();
|
||||
},
|
||||
// this is called from code put into a frame from the server:
|
||||
handleImportExportFrameCall: function(callName, varargs)
|
||||
{
|
||||
handleImportExportFrameCall: function(callName, varargs) {
|
||||
padimpexp.handleFrameCall.call(padimpexp, callName, Array.prototype.slice.call(arguments, 1));
|
||||
},
|
||||
callWhenNotCommitting: function(f)
|
||||
{
|
||||
callWhenNotCommitting: function(f) {
|
||||
pad.collabClient.callWhenNotCommitting(f);
|
||||
},
|
||||
getCollabRevisionNumber: function()
|
||||
{
|
||||
getCollabRevisionNumber: function() {
|
||||
return pad.collabClient.getCurrentRevisionNumber();
|
||||
},
|
||||
isFullyConnected: function()
|
||||
{
|
||||
isFullyConnected: function() {
|
||||
return padconnectionstatus.isFullyConnected();
|
||||
},
|
||||
addHistoricalAuthors: function(data)
|
||||
{
|
||||
addHistoricalAuthors: function(data) {
|
||||
if (!pad.collabClient)
|
||||
{
|
||||
window.setTimeout(function()
|
||||
{
|
||||
window.setTimeout(function() {
|
||||
pad.addHistoricalAuthors(data);
|
||||
}, 1000);
|
||||
}
|
||||
|
@ -875,13 +821,11 @@ var pad = {
|
|||
}
|
||||
};
|
||||
|
||||
var alertBar = (function()
|
||||
{
|
||||
var alertBar = (function() {
|
||||
|
||||
var animator = padutils.makeShowHideAnimator(arriveAtAnimationState, false, 25, 400);
|
||||
|
||||
function arriveAtAnimationState(state)
|
||||
{
|
||||
function arriveAtAnimationState(state) {
|
||||
if (state == -1)
|
||||
{
|
||||
$("#alertbar").css('opacity', 0).css('display', 'block');
|
||||
|
@ -905,13 +849,11 @@ var alertBar = (function()
|
|||
}
|
||||
|
||||
var self = {
|
||||
displayMessage: function(setupFunc)
|
||||
{
|
||||
displayMessage: function(setupFunc) {
|
||||
animator.show();
|
||||
setupFunc($("#alertbar"));
|
||||
},
|
||||
hideMessage: function()
|
||||
{
|
||||
hideMessage: function() {
|
||||
animator.hide();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,31 +22,26 @@
|
|||
|
||||
var padmodals = require('./pad_modals').padmodals;
|
||||
|
||||
var padconnectionstatus = (function()
|
||||
{
|
||||
var padconnectionstatus = (function() {
|
||||
|
||||
var status = {
|
||||
what: 'connecting'
|
||||
};
|
||||
|
||||
var self = {
|
||||
init: function()
|
||||
{
|
||||
$('button#forcereconnect').click(function()
|
||||
{
|
||||
init: function() {
|
||||
$('button#forcereconnect').click(function() {
|
||||
window.location.reload();
|
||||
});
|
||||
},
|
||||
connected: function()
|
||||
{
|
||||
connected: function() {
|
||||
status = {
|
||||
what: 'connected'
|
||||
};
|
||||
padmodals.showModal('connected');
|
||||
padmodals.hideOverlay();
|
||||
},
|
||||
reconnecting: function()
|
||||
{
|
||||
reconnecting: function() {
|
||||
status = {
|
||||
what: 'reconnecting'
|
||||
};
|
||||
|
@ -54,8 +49,7 @@ var padconnectionstatus = (function()
|
|||
padmodals.showModal('reconnecting');
|
||||
padmodals.showOverlay();
|
||||
},
|
||||
disconnected: function(msg)
|
||||
{
|
||||
disconnected: function(msg) {
|
||||
if(status.what == "disconnected")
|
||||
return;
|
||||
|
||||
|
@ -89,12 +83,10 @@ var padconnectionstatus = (function()
|
|||
padmodals.showModal(k);
|
||||
padmodals.showOverlay();
|
||||
},
|
||||
isFullyConnected: function()
|
||||
{
|
||||
isFullyConnected: function() {
|
||||
return status.what == 'connected';
|
||||
},
|
||||
getStatus: function()
|
||||
{
|
||||
getStatus: function() {
|
||||
return status;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -79,11 +79,9 @@ ToolbarItem.prototype.bind = function (callback) {
|
|||
};
|
||||
|
||||
|
||||
var padeditbar = (function()
|
||||
{
|
||||
var padeditbar = (function() {
|
||||
|
||||
var syncAnimation = (function()
|
||||
{
|
||||
var syncAnimation = (function() {
|
||||
var SYNCING = -100;
|
||||
var DONE = 100;
|
||||
var state = DONE;
|
||||
|
@ -92,8 +90,7 @@ var padeditbar = (function()
|
|||
var T_START = -0.5;
|
||||
var T_FADE = 1.0;
|
||||
var T_GONE = 1.5;
|
||||
var animator = padutils.makeAnimationScheduler(function()
|
||||
{
|
||||
var animator = padutils.makeAnimationScheduler(function() {
|
||||
if (state == SYNCING || state == DONE)
|
||||
{
|
||||
return false;
|
||||
|
@ -126,14 +123,12 @@ var padeditbar = (function()
|
|||
}
|
||||
}, step * 1000);
|
||||
return {
|
||||
syncing: function()
|
||||
{
|
||||
syncing: function() {
|
||||
state = SYNCING;
|
||||
$("#syncstatussyncing").css('display', 'block');
|
||||
$("#syncstatusdone").css('display', 'none');
|
||||
},
|
||||
done: function()
|
||||
{
|
||||
done: function() {
|
||||
state = T_START;
|
||||
animator.scheduleAnimation();
|
||||
}
|
||||
|
@ -186,16 +181,13 @@ var padeditbar = (function()
|
|||
$('#editbar').toggleClass('editor-scrolled', $(this).scrollTop() > 2);
|
||||
})
|
||||
},
|
||||
isEnabled: function()
|
||||
{
|
||||
isEnabled: function() {
|
||||
return true;
|
||||
},
|
||||
disable: function()
|
||||
{
|
||||
disable: function() {
|
||||
$("#editbar").addClass('disabledtoolbar').removeClass("enabledtoolbar");
|
||||
},
|
||||
enable: function()
|
||||
{
|
||||
enable: function() {
|
||||
$('#editbar').addClass('enabledtoolbar').removeClass('disabledtoolbar');
|
||||
},
|
||||
commands: {},
|
||||
|
@ -223,8 +215,7 @@ var padeditbar = (function()
|
|||
}
|
||||
if(padeditor.ace) padeditor.ace.focus();
|
||||
},
|
||||
toggleDropDown: function(moduleName, cb)
|
||||
{
|
||||
toggleDropDown: function(moduleName, cb) {
|
||||
// do nothing if users are sticked
|
||||
if (moduleName === "users" && $('#users').hasClass('stickyUsers')) {
|
||||
return;
|
||||
|
@ -284,8 +275,7 @@ var padeditbar = (function()
|
|||
}
|
||||
}
|
||||
},
|
||||
setSyncStatus: function(status)
|
||||
{
|
||||
setSyncStatus: function(status) {
|
||||
if (status == "syncing")
|
||||
{
|
||||
syncAnimation.syncing();
|
||||
|
@ -295,8 +285,7 @@ var padeditbar = (function()
|
|||
syncAnimation.done();
|
||||
}
|
||||
},
|
||||
setEmbedLinks: function()
|
||||
{
|
||||
setEmbedLinks: function() {
|
||||
var padUrl = window.location.href.split("?")[0];
|
||||
|
||||
if ($('#readonlyinput').is(':checked'))
|
||||
|
@ -313,8 +302,7 @@ var padeditbar = (function()
|
|||
$('#linkinput').val(padUrl);
|
||||
}
|
||||
},
|
||||
checkAllIconsAreDisplayedInToolbar: function()
|
||||
{
|
||||
checkAllIconsAreDisplayedInToolbar: function() {
|
||||
// reset style
|
||||
$('.toolbar').removeClass('cropped')
|
||||
$('body').removeClass('mobile-layout');
|
||||
|
|
|
@ -24,8 +24,7 @@ const Cookies = require('./pad_utils').Cookies;
|
|||
var padcookie = require('./pad_cookie').padcookie;
|
||||
var padutils = require('./pad_utils').padutils;
|
||||
|
||||
var padeditor = (function()
|
||||
{
|
||||
var padeditor = (function() {
|
||||
var Ace2Editor = undefined;
|
||||
var pad = undefined;
|
||||
var settings = undefined;
|
||||
|
@ -34,14 +33,12 @@ var padeditor = (function()
|
|||
ace: null,
|
||||
// this is accessed directly from other files
|
||||
viewZoom: 100,
|
||||
init: function(readyFunc, initialViewOptions, _pad)
|
||||
{
|
||||
init: function(readyFunc, initialViewOptions, _pad) {
|
||||
Ace2Editor = require('./ace').Ace2Editor;
|
||||
pad = _pad;
|
||||
settings = pad.settings;
|
||||
|
||||
function aceReady()
|
||||
{
|
||||
function aceReady() {
|
||||
$("#editorloadingbox").hide();
|
||||
if (readyFunc)
|
||||
{
|
||||
|
@ -62,24 +59,20 @@ var padeditor = (function()
|
|||
// view bar
|
||||
$("#viewbarcontents").show();
|
||||
},
|
||||
initViewOptions: function()
|
||||
{
|
||||
initViewOptions: function() {
|
||||
// Line numbers
|
||||
padutils.bindCheckboxChange($("#options-linenoscheck"), function()
|
||||
{
|
||||
padutils.bindCheckboxChange($("#options-linenoscheck"), function() {
|
||||
pad.changeViewOption('showLineNumbers', padutils.getCheckbox($("#options-linenoscheck")));
|
||||
});
|
||||
|
||||
// Author colors
|
||||
padutils.bindCheckboxChange($("#options-colorscheck"), function()
|
||||
{
|
||||
padutils.bindCheckboxChange($("#options-colorscheck"), function() {
|
||||
padcookie.setPref('showAuthorshipColors', padutils.getCheckbox("#options-colorscheck"));
|
||||
pad.changeViewOption('showAuthorColors', padutils.getCheckbox("#options-colorscheck"));
|
||||
});
|
||||
|
||||
// Right to left
|
||||
padutils.bindCheckboxChange($("#options-rtlcheck"), function()
|
||||
{
|
||||
padutils.bindCheckboxChange($("#options-rtlcheck"), function() {
|
||||
pad.changeViewOption('rtlIsTrue', padutils.getCheckbox($("#options-rtlcheck")))
|
||||
});
|
||||
html10n.bind('localized', function() {
|
||||
|
@ -88,8 +81,7 @@ var padeditor = (function()
|
|||
})
|
||||
|
||||
// font family change
|
||||
$("#viewfontmenu").change(function()
|
||||
{
|
||||
$("#viewfontmenu").change(function() {
|
||||
pad.changeViewOption('padFontFamily', $("#viewfontmenu").val());
|
||||
});
|
||||
|
||||
|
@ -113,10 +105,8 @@ var padeditor = (function()
|
|||
window.html10n.localize([$("#languagemenu").val(), 'en']);
|
||||
});
|
||||
},
|
||||
setViewOptions: function(newOptions)
|
||||
{
|
||||
function getOption(key, defaultValue)
|
||||
{
|
||||
setViewOptions: function(newOptions) {
|
||||
function getOption(key, defaultValue) {
|
||||
var value = String(newOptions[key]);
|
||||
if (value == "true") return true;
|
||||
if (value == "false") return false;
|
||||
|
@ -146,31 +136,27 @@ var padeditor = (function()
|
|||
|
||||
self.ace.setProperty("textface", newOptions['padFontFamily'] || "");
|
||||
},
|
||||
dispose: function()
|
||||
{
|
||||
dispose: function() {
|
||||
if (self.ace)
|
||||
{
|
||||
self.ace.destroy();
|
||||
self.ace = null;
|
||||
}
|
||||
},
|
||||
enable: function()
|
||||
{
|
||||
enable: function() {
|
||||
if (self.ace)
|
||||
{
|
||||
self.ace.setEditable(true);
|
||||
}
|
||||
},
|
||||
disable: function()
|
||||
{
|
||||
disable: function() {
|
||||
if (self.ace)
|
||||
{
|
||||
self.ace.setProperty("grayedOut", true);
|
||||
self.ace.setEditable(false);
|
||||
}
|
||||
},
|
||||
restoreRevisionText: function(dataFromServer)
|
||||
{
|
||||
restoreRevisionText: function(dataFromServer) {
|
||||
pad.addHistoricalAuthors(dataFromServer.historicalAuthorData);
|
||||
self.ace.importAText(dataFromServer.atext, dataFromServer.apool, true);
|
||||
}
|
||||
|
|
|
@ -20,35 +20,30 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var padimpexp = (function()
|
||||
{
|
||||
var padimpexp = (function() {
|
||||
|
||||
///// import
|
||||
var currentImportTimer = null;
|
||||
|
||||
function addImportFrames()
|
||||
{
|
||||
function addImportFrames() {
|
||||
$("#import .importframe").remove();
|
||||
var iframe = $('<iframe style="display: none;" name="importiframe" class="importframe"></iframe>');
|
||||
$('#import').append(iframe);
|
||||
}
|
||||
|
||||
function fileInputUpdated()
|
||||
{
|
||||
function fileInputUpdated() {
|
||||
$('#importsubmitinput').addClass('throbbold');
|
||||
$('#importformfilediv').addClass('importformenabled');
|
||||
$('#importsubmitinput').removeAttr('disabled');
|
||||
$('#importmessagefail').fadeOut('fast');
|
||||
}
|
||||
|
||||
function fileInputSubmit()
|
||||
{
|
||||
function fileInputSubmit() {
|
||||
$('#importmessagefail').fadeOut("fast");
|
||||
var ret = window.confirm(html10n.get("pad.impexp.confirmimport"));
|
||||
if (ret)
|
||||
{
|
||||
currentImportTimer = window.setTimeout(function()
|
||||
{
|
||||
currentImportTimer = window.setTimeout(function() {
|
||||
if (!currentImportTimer)
|
||||
{
|
||||
return;
|
||||
|
@ -62,8 +57,7 @@ var padimpexp = (function()
|
|||
disabled: true
|
||||
}).val(html10n.get("pad.impexp.importing"));
|
||||
|
||||
window.setTimeout(function()
|
||||
{
|
||||
window.setTimeout(function() {
|
||||
$('#importfileinput').attr(
|
||||
{
|
||||
disabled: true
|
||||
|
@ -75,16 +69,13 @@ var padimpexp = (function()
|
|||
return ret;
|
||||
}
|
||||
|
||||
function importFailed(msg)
|
||||
{
|
||||
function importFailed(msg) {
|
||||
importErrorMessage(msg);
|
||||
}
|
||||
|
||||
function importDone()
|
||||
{
|
||||
function importDone() {
|
||||
$('#importsubmitinput').removeAttr('disabled').val(html10n.get("pad.impexp.importbutton"));
|
||||
window.setTimeout(function()
|
||||
{
|
||||
window.setTimeout(function() {
|
||||
$('#importfileinput').removeAttr('disabled');
|
||||
}, 0);
|
||||
$('#importstatusball').hide();
|
||||
|
@ -92,8 +83,7 @@ var padimpexp = (function()
|
|||
addImportFrames();
|
||||
}
|
||||
|
||||
function importClearTimeout()
|
||||
{
|
||||
function importClearTimeout() {
|
||||
if (currentImportTimer)
|
||||
{
|
||||
window.clearTimeout(currentImportTimer);
|
||||
|
@ -101,8 +91,7 @@ var padimpexp = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function importErrorMessage(status)
|
||||
{
|
||||
function importErrorMessage(status) {
|
||||
var msg="";
|
||||
|
||||
if(status === "convertFailed"){
|
||||
|
@ -117,16 +106,14 @@ var padimpexp = (function()
|
|||
msg = html10n.get("pad.impexp.permission");
|
||||
}
|
||||
|
||||
function showError(fade)
|
||||
{
|
||||
function showError(fade) {
|
||||
$('#importmessagefail').html('<strong style="color: red">'+html10n.get('pad.impexp.importfailed')+':</strong> ' + (msg || html10n.get('pad.impexp.copypaste','')))[(fade ? "fadeIn" : "show")]();
|
||||
}
|
||||
|
||||
if ($('#importexport .importmessage').is(':visible'))
|
||||
{
|
||||
$('#importmessagesuccess').fadeOut("fast");
|
||||
$('#importmessagefail').fadeOut("fast", function()
|
||||
{
|
||||
$('#importmessagefail').fadeOut("fast", function() {
|
||||
showError(true);
|
||||
});
|
||||
}
|
||||
|
@ -136,8 +123,7 @@ var padimpexp = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function importSuccessful(token)
|
||||
{
|
||||
function importSuccessful(token) {
|
||||
$.ajax(
|
||||
{
|
||||
type: 'post',
|
||||
|
@ -153,16 +139,14 @@ var padimpexp = (function()
|
|||
addImportFrames();
|
||||
}
|
||||
|
||||
function importApplicationFailed(xhr, textStatus, errorThrown)
|
||||
{
|
||||
function importApplicationFailed(xhr, textStatus, errorThrown) {
|
||||
importErrorMessage("Error during conversion.");
|
||||
importDone();
|
||||
}
|
||||
|
||||
///// export
|
||||
|
||||
function cantExport()
|
||||
{
|
||||
function cantExport() {
|
||||
var type = $(this);
|
||||
if (type.hasClass("exporthrefpdf"))
|
||||
{
|
||||
|
@ -187,8 +171,7 @@ var padimpexp = (function()
|
|||
/////
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function(_pad)
|
||||
{
|
||||
init: function(_pad) {
|
||||
pad = _pad;
|
||||
|
||||
//get /p/padname
|
||||
|
@ -242,8 +225,7 @@ var padimpexp = (function()
|
|||
$('#importform').unbind("submit").submit(fileInputSubmit);
|
||||
$('.disabledexport').click(cantExport);
|
||||
},
|
||||
handleFrameCall: function(directDatabaseAccess, status)
|
||||
{
|
||||
handleFrameCall: function(directDatabaseAccess, status) {
|
||||
if(directDatabaseAccess === "undefined") directDatabaseAccess = false;
|
||||
if (status !== "ok")
|
||||
{
|
||||
|
@ -262,14 +244,12 @@ var padimpexp = (function()
|
|||
|
||||
importDone();
|
||||
},
|
||||
disable: function()
|
||||
{
|
||||
disable: function() {
|
||||
$("#impexp-disabled-clickcatcher").show();
|
||||
$("#import").css('opacity', 0.5);
|
||||
$("#impexp-export").css('opacity', 0.5);
|
||||
},
|
||||
enable: function()
|
||||
{
|
||||
enable: function() {
|
||||
$("#impexp-disabled-clickcatcher").hide();
|
||||
$("#import").css('opacity', 1);
|
||||
$("#impexp-export").css('opacity', 1);
|
||||
|
|
|
@ -23,16 +23,13 @@
|
|||
var padeditbar = require('./pad_editbar').padeditbar;
|
||||
var automaticReconnect = require('./pad_automatic_reconnect');
|
||||
|
||||
var padmodals = (function()
|
||||
{
|
||||
var padmodals = (function() {
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function(_pad)
|
||||
{
|
||||
init: function(_pad) {
|
||||
pad = _pad;
|
||||
},
|
||||
showModal: function(messageId)
|
||||
{
|
||||
showModal: function(messageId) {
|
||||
padeditbar.toggleDropDown("none", function() {
|
||||
$("#connectivity .visible").removeClass('visible');
|
||||
$("#connectivity ."+messageId).addClass('visible');
|
||||
|
|
|
@ -30,17 +30,14 @@ var colorPickerSetup = false;
|
|||
var previousColorId = 0;
|
||||
|
||||
|
||||
var paduserlist = (function()
|
||||
{
|
||||
var paduserlist = (function() {
|
||||
|
||||
var rowManager = (function()
|
||||
{
|
||||
var rowManager = (function() {
|
||||
// The row manager handles rendering rows of the user list and animating
|
||||
// their insertion, removal, and reordering. It manipulates TD height
|
||||
// and TD opacity.
|
||||
|
||||
function nextRowId()
|
||||
{
|
||||
function nextRowId() {
|
||||
return "usertr" + (nextRowId.counter++);
|
||||
}
|
||||
nextRowId.counter = 1;
|
||||
|
@ -52,8 +49,7 @@ var paduserlist = (function()
|
|||
var ANIMATION_END = 12; // just finishing fading out
|
||||
|
||||
|
||||
function getAnimationHeight(step, power)
|
||||
{
|
||||
function getAnimationHeight(step, power) {
|
||||
var a = Math.abs(step / 12);
|
||||
if (power == 2) a = a * a;
|
||||
else if (power == 3) a = a * a * a;
|
||||
|
@ -72,18 +68,15 @@ var paduserlist = (function()
|
|||
// we do lots of manipulation of table rows and stuff that JQuery makes ok, despite
|
||||
// IE's poor handling when manipulating the DOM directly.
|
||||
|
||||
function getEmptyRowHtml(height)
|
||||
{
|
||||
function getEmptyRowHtml(height) {
|
||||
return '<td colspan="' + NUMCOLS + '" style="border:0;height:' + height + 'px"><!-- --></td>';
|
||||
}
|
||||
|
||||
function isNameEditable(data)
|
||||
{
|
||||
function isNameEditable(data) {
|
||||
return (!data.name) && (data.status != 'Disconnected');
|
||||
}
|
||||
|
||||
function replaceUserRowContents(tr, height, data)
|
||||
{
|
||||
function replaceUserRowContents(tr, height, data) {
|
||||
var tds = getUserRowHtml(height, data).match(/<td.*?<\/td>/gi);
|
||||
if (isNameEditable(data) && tr.find("td.usertdname input:enabled").length > 0)
|
||||
{
|
||||
|
@ -104,8 +97,7 @@ var paduserlist = (function()
|
|||
return tr;
|
||||
}
|
||||
|
||||
function getUserRowHtml(height, data)
|
||||
{
|
||||
function getUserRowHtml(height, data) {
|
||||
var nameHtml;
|
||||
if (data.name)
|
||||
{
|
||||
|
@ -119,18 +111,15 @@ var paduserlist = (function()
|
|||
return ['<td style="height:', height, 'px" class="usertdswatch"><div class="swatch" style="background:' + padutils.escapeHtml(data.color) + '"> </div></td>', '<td style="height:', height, 'px" class="usertdname">', nameHtml, '</td>', '<td style="height:', height, 'px" class="activity">', padutils.escapeHtml(data.activity), '</td>'].join('');
|
||||
}
|
||||
|
||||
function getRowHtml(id, innerHtml, authorId)
|
||||
{
|
||||
function getRowHtml(id, innerHtml, authorId) {
|
||||
return '<tr data-authorId="'+authorId+'" id="' + id + '">' + innerHtml + '</tr>';
|
||||
}
|
||||
|
||||
function rowNode(row)
|
||||
{
|
||||
function rowNode(row) {
|
||||
return $("#" + row.domId);
|
||||
}
|
||||
|
||||
function handleRowData(row)
|
||||
{
|
||||
function handleRowData(row) {
|
||||
if (row.data && row.data.status == 'Disconnected')
|
||||
{
|
||||
row.opacity = 0.5;
|
||||
|
@ -141,13 +130,11 @@ var paduserlist = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function handleRowNode(tr, data)
|
||||
{
|
||||
function handleRowNode(tr, data) {
|
||||
if (data.titleText)
|
||||
{
|
||||
var titleText = data.titleText;
|
||||
window.setTimeout(function()
|
||||
{
|
||||
window.setTimeout(function() {
|
||||
/* tr.attr('title', titleText)*/
|
||||
}, 0);
|
||||
}
|
||||
|
@ -157,11 +144,9 @@ var paduserlist = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function handleOtherUserInputs()
|
||||
{
|
||||
function handleOtherUserInputs() {
|
||||
// handle 'INPUT' elements for naming other unnamed users
|
||||
$("#otheruserstable input.newinput").each(function()
|
||||
{
|
||||
$("#otheruserstable input.newinput").each(function() {
|
||||
var input = $(this);
|
||||
var tr = input.closest("tr");
|
||||
if (tr.length > 0)
|
||||
|
@ -179,8 +164,7 @@ var paduserlist = (function()
|
|||
// animationPower is 0 to skip animation, 1 for linear, 2 for quadratic, etc.
|
||||
|
||||
|
||||
function insertRow(position, data, animationPower)
|
||||
{
|
||||
function insertRow(position, data, animationPower) {
|
||||
position = Math.max(0, Math.min(rowsPresent.length, position));
|
||||
animationPower = (animationPower === undefined ? 4 : animationPower);
|
||||
|
||||
|
@ -227,8 +211,7 @@ var paduserlist = (function()
|
|||
return row;
|
||||
}
|
||||
|
||||
function updateRow(position, data)
|
||||
{
|
||||
function updateRow(position, data) {
|
||||
var row = rowsPresent[position];
|
||||
if (row)
|
||||
{
|
||||
|
@ -245,8 +228,7 @@ var paduserlist = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function removeRow(position, animationPower)
|
||||
{
|
||||
function removeRow(position, animationPower) {
|
||||
animationPower = (animationPower === undefined ? 4 : animationPower);
|
||||
var row = rowsPresent[position];
|
||||
if (row)
|
||||
|
@ -272,8 +254,7 @@ var paduserlist = (function()
|
|||
// newPosition is position after the row has been removed
|
||||
|
||||
|
||||
function moveRow(oldPosition, newPosition, animationPower)
|
||||
{
|
||||
function moveRow(oldPosition, newPosition, animationPower) {
|
||||
animationPower = (animationPower === undefined ? 1 : animationPower); // linear is best
|
||||
var row = rowsPresent[oldPosition];
|
||||
if (row && oldPosition != newPosition)
|
||||
|
@ -284,8 +265,7 @@ var paduserlist = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function animateStep()
|
||||
{
|
||||
function animateStep() {
|
||||
// animation must be symmetrical
|
||||
for (var i = rowsFadingIn.length - 1; i >= 0; i--)
|
||||
{ // backwards to allow removal
|
||||
|
@ -357,10 +337,8 @@ var paduserlist = (function()
|
|||
var otherUsersInfo = [];
|
||||
var otherUsersData = [];
|
||||
|
||||
function rowManagerMakeNameEditor(jnode, userId)
|
||||
{
|
||||
setUpEditable(jnode, function()
|
||||
{
|
||||
function rowManagerMakeNameEditor(jnode, userId) {
|
||||
setUpEditable(jnode, function() {
|
||||
var existingIndex = findExistingIndex(userId);
|
||||
if (existingIndex >= 0)
|
||||
{
|
||||
|
@ -370,8 +348,7 @@ var paduserlist = (function()
|
|||
{
|
||||
return '';
|
||||
}
|
||||
}, function(newName)
|
||||
{
|
||||
}, function(newName) {
|
||||
if (!newName)
|
||||
{
|
||||
jnode.addClass("editempty");
|
||||
|
@ -385,8 +362,7 @@ var paduserlist = (function()
|
|||
});
|
||||
}
|
||||
|
||||
function findExistingIndex(userId)
|
||||
{
|
||||
function findExistingIndex(userId) {
|
||||
var existingIndex = -1;
|
||||
for (var i = 0; i < otherUsersInfo.length; i++)
|
||||
{
|
||||
|
@ -399,10 +375,8 @@ var paduserlist = (function()
|
|||
return existingIndex;
|
||||
}
|
||||
|
||||
function setUpEditable(jqueryNode, valueGetter, valueSetter)
|
||||
{
|
||||
jqueryNode.bind('focus', function(evt)
|
||||
{
|
||||
function setUpEditable(jqueryNode, valueGetter, valueSetter) {
|
||||
jqueryNode.bind('focus', function(evt) {
|
||||
var oldValue = valueGetter();
|
||||
if (jqueryNode.val() !== oldValue)
|
||||
{
|
||||
|
@ -410,16 +384,13 @@ var paduserlist = (function()
|
|||
}
|
||||
jqueryNode.addClass("editactive").removeClass("editempty");
|
||||
});
|
||||
jqueryNode.bind('blur', function(evt)
|
||||
{
|
||||
jqueryNode.bind('blur', function(evt) {
|
||||
var newValue = jqueryNode.removeClass("editactive").val();
|
||||
valueSetter(newValue);
|
||||
});
|
||||
padutils.bindEnterAndEscape(jqueryNode, function onEnter()
|
||||
{
|
||||
padutils.bindEnterAndEscape(jqueryNode, function onEnter() {
|
||||
jqueryNode.blur();
|
||||
}, function onEscape()
|
||||
{
|
||||
}, function onEscape() {
|
||||
jqueryNode.val(valueGetter()).blur();
|
||||
});
|
||||
jqueryNode.removeAttr('disabled').addClass('editable');
|
||||
|
@ -429,8 +400,7 @@ var paduserlist = (function()
|
|||
var guestPromptFlashState = 0;
|
||||
var guestPromptFlash = padutils.makeAnimationScheduler(
|
||||
|
||||
function()
|
||||
{
|
||||
function() {
|
||||
var prompts = $("#guestprompts .guestprompt");
|
||||
if (prompts.length == 0)
|
||||
{
|
||||
|
@ -452,8 +422,7 @@ var paduserlist = (function()
|
|||
|
||||
var pad = undefined;
|
||||
var self = {
|
||||
init: function(myInitialUserInfo, _pad)
|
||||
{
|
||||
init: function(myInitialUserInfo, _pad) {
|
||||
pad = _pad;
|
||||
|
||||
self.setMyUserInfo(myInitialUserInfo);
|
||||
|
@ -465,17 +434,14 @@ var paduserlist = (function()
|
|||
if (pad.getUserIsGuest())
|
||||
{
|
||||
$("#myusernameedit").addClass('myusernameedithoverable');
|
||||
setUpEditable($("#myusernameedit"), function()
|
||||
{
|
||||
setUpEditable($("#myusernameedit"), function() {
|
||||
return myUserInfo.name || '';
|
||||
}, function(newValue)
|
||||
{
|
||||
}, function(newValue) {
|
||||
myUserInfo.name = newValue;
|
||||
pad.notifyChangeName(newValue);
|
||||
// wrap with setTimeout to do later because we get
|
||||
// a double "blur" fire in IE...
|
||||
window.setTimeout(function()
|
||||
{
|
||||
window.setTimeout(function() {
|
||||
self.renderMyUserInfo();
|
||||
}, 0);
|
||||
});
|
||||
|
@ -483,23 +449,19 @@ var paduserlist = (function()
|
|||
|
||||
// color picker
|
||||
$("#myswatchbox").click(showColorPicker);
|
||||
$("#mycolorpicker .pickerswatchouter").click(function()
|
||||
{
|
||||
$("#mycolorpicker .pickerswatchouter").click(function() {
|
||||
$("#mycolorpicker .pickerswatchouter").removeClass('picked');
|
||||
$(this).addClass('picked');
|
||||
});
|
||||
$("#mycolorpickersave").click(function()
|
||||
{
|
||||
$("#mycolorpickersave").click(function() {
|
||||
closeColorPicker(true);
|
||||
});
|
||||
$("#mycolorpickercancel").click(function()
|
||||
{
|
||||
$("#mycolorpickercancel").click(function() {
|
||||
closeColorPicker(false);
|
||||
});
|
||||
//
|
||||
},
|
||||
usersOnline: function()
|
||||
{
|
||||
usersOnline: function() {
|
||||
// Returns an object of users who are currently online on this pad
|
||||
var userList = [].concat(otherUsersInfo); // Make a copy of the otherUsersInfo, otherwise every call to users modifies the referenced array
|
||||
// Now we need to add ourselves..
|
||||
|
@ -527,8 +489,7 @@ var paduserlist = (function()
|
|||
}
|
||||
return userList;
|
||||
},
|
||||
setMyUserInfo: function(info)
|
||||
{
|
||||
setMyUserInfo: function(info) {
|
||||
//translate the colorId
|
||||
if(typeof info.colorId == "number")
|
||||
{
|
||||
|
@ -540,8 +501,7 @@ var paduserlist = (function()
|
|||
|
||||
self.renderMyUserInfo();
|
||||
},
|
||||
userJoinOrUpdate: function(info)
|
||||
{
|
||||
userJoinOrUpdate: function(info) {
|
||||
if ((!info.userId) || (info.userId == myUserInfo.userId))
|
||||
{
|
||||
// not sure how this would happen
|
||||
|
@ -568,8 +528,7 @@ var paduserlist = (function()
|
|||
{
|
||||
numUsersBesides--;
|
||||
}
|
||||
var newIndex = padutils.binarySearch(numUsersBesides, function(n)
|
||||
{
|
||||
var newIndex = padutils.binarySearch(numUsersBesides, function(n) {
|
||||
if (existingIndex >= 0 && n >= existingIndex)
|
||||
{
|
||||
// pretend existingIndex isn't there
|
||||
|
@ -611,8 +570,7 @@ var paduserlist = (function()
|
|||
|
||||
self.updateNumberOfOnlineUsers();
|
||||
},
|
||||
updateNumberOfOnlineUsers: function()
|
||||
{
|
||||
updateNumberOfOnlineUsers: function() {
|
||||
var online = 1; // you are always online!
|
||||
for (var i = 0; i < otherUsersData.length; i++)
|
||||
{
|
||||
|
@ -626,8 +584,7 @@ var paduserlist = (function()
|
|||
|
||||
return online;
|
||||
},
|
||||
userLeave: function(info)
|
||||
{
|
||||
userLeave: function(info) {
|
||||
var existingIndex = findExistingIndex(info.userId);
|
||||
if (existingIndex >= 0)
|
||||
{
|
||||
|
@ -642,8 +599,7 @@ var paduserlist = (function()
|
|||
// joins, or updates happen for this user in the
|
||||
// next N seconds, to remove the user from the list.
|
||||
var thisUserId = info.userId;
|
||||
var thisLeaveTimer = window.setTimeout(function()
|
||||
{
|
||||
var thisLeaveTimer = window.setTimeout(function() {
|
||||
var newExistingIndex = findExistingIndex(thisUserId);
|
||||
if (newExistingIndex >= 0)
|
||||
{
|
||||
|
@ -664,8 +620,7 @@ var paduserlist = (function()
|
|||
|
||||
self.updateNumberOfOnlineUsers();
|
||||
},
|
||||
showGuestPrompt: function(userId, displayName)
|
||||
{
|
||||
showGuestPrompt: function(userId, displayName) {
|
||||
if (knocksToIgnore[userId])
|
||||
{
|
||||
return;
|
||||
|
@ -688,30 +643,25 @@ var paduserlist = (function()
|
|||
// update display name
|
||||
box.find(".guestname").html('<strong>'+_('pad.userlist.guest')+':</strong> ' + padutils.escapeHtml(displayName));
|
||||
}
|
||||
var hideLater = padutils.getCancellableAction(actionName, function()
|
||||
{
|
||||
var hideLater = padutils.getCancellableAction(actionName, function() {
|
||||
self.removeGuestPrompt(userId);
|
||||
});
|
||||
window.setTimeout(hideLater, 15000); // time-out with no knock
|
||||
guestPromptFlash.scheduleAnimation();
|
||||
},
|
||||
removeGuestPrompt: function(userId)
|
||||
{
|
||||
removeGuestPrompt: function(userId) {
|
||||
var box = $("#guestprompt-" + padutils.encodeUserId(userId));
|
||||
// remove ID now so a new knock by same user gets new, unfaded box
|
||||
box.removeAttr('id').fadeOut("fast", function()
|
||||
{
|
||||
box.removeAttr('id').fadeOut("fast", function() {
|
||||
box.remove();
|
||||
});
|
||||
|
||||
knocksToIgnore[userId] = true;
|
||||
window.setTimeout(function()
|
||||
{
|
||||
window.setTimeout(function() {
|
||||
delete knocksToIgnore[userId];
|
||||
}, 5000);
|
||||
},
|
||||
answerGuestPrompt: function(encodedUserId, approve)
|
||||
{
|
||||
answerGuestPrompt: function(encodedUserId, approve) {
|
||||
var guestId = padutils.decodeUserId(encodedUserId);
|
||||
|
||||
var msg = {
|
||||
|
@ -724,8 +674,7 @@ var paduserlist = (function()
|
|||
|
||||
self.removeGuestPrompt(guestId);
|
||||
},
|
||||
renderMyUserInfo: function()
|
||||
{
|
||||
renderMyUserInfo: function() {
|
||||
if (myUserInfo.name)
|
||||
{
|
||||
$("#myusernameedit").removeClass("editempty").val(myUserInfo.name);
|
||||
|
@ -757,14 +706,12 @@ var paduserlist = (function()
|
|||
return self;
|
||||
}());
|
||||
|
||||
function getColorPickerSwatchIndex(jnode)
|
||||
{
|
||||
function getColorPickerSwatchIndex(jnode) {
|
||||
// return Number(jnode.get(0).className.match(/\bn([0-9]+)\b/)[1])-1;
|
||||
return $("#colorpickerswatches li").index(jnode);
|
||||
}
|
||||
|
||||
function closeColorPicker(accept)
|
||||
{
|
||||
function closeColorPicker(accept) {
|
||||
if (accept)
|
||||
{
|
||||
var newColor = $("#mycolorpickerpreview").css("background-color");
|
||||
|
@ -792,8 +739,7 @@ function closeColorPicker(accept)
|
|||
$("#mycolorpicker").removeClass('popup-show');
|
||||
}
|
||||
|
||||
function showColorPicker()
|
||||
{
|
||||
function showColorPicker() {
|
||||
previousColorId = myUserInfo.colorId;
|
||||
$.farbtastic('#colorpicker').setColor(myUserInfo.colorId)
|
||||
|
||||
|
@ -813,8 +759,7 @@ function showColorPicker()
|
|||
|
||||
li.appendTo(colorsList);
|
||||
|
||||
li.bind('click', function(event)
|
||||
{
|
||||
li.bind('click', function(event) {
|
||||
$("#colorpickerswatches li").removeClass('picked');
|
||||
$(event.target).addClass("picked");
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ var Security = require('./security');
|
|||
* Generates a random String with the given length. Is needed to generate the Author, Group, readonly, session Ids
|
||||
*/
|
||||
|
||||
function randomString(len)
|
||||
{
|
||||
function randomString(len) {
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
len = len || 20
|
||||
|
@ -40,27 +39,22 @@ function randomString(len)
|
|||
}
|
||||
|
||||
var padutils = {
|
||||
escapeHtml: function(x)
|
||||
{
|
||||
escapeHtml: function(x) {
|
||||
return Security.escapeHTML(String(x));
|
||||
},
|
||||
uniqueId: function()
|
||||
{
|
||||
uniqueId: function() {
|
||||
var pad = require('./pad').pad; // Sidestep circular dependency
|
||||
function encodeNum(n, width)
|
||||
{
|
||||
function encodeNum(n, width) {
|
||||
// returns string that is exactly 'width' chars, padding with zeros
|
||||
// and taking rightmost digits
|
||||
return (Array(width + 1).join('0') + Number(n).toString(35)).slice(-width);
|
||||
}
|
||||
return [pad.getClientIp(), encodeNum(+new Date, 7), encodeNum(Math.floor(Math.random() * 1e9), 4)].join('.');
|
||||
},
|
||||
uaDisplay: function(ua)
|
||||
{
|
||||
uaDisplay: function(ua) {
|
||||
var m;
|
||||
|
||||
function clean(a)
|
||||
{
|
||||
function clean(a) {
|
||||
var maxlen = 16;
|
||||
a = a.replace(/[^a-zA-Z0-9\.]/g, '');
|
||||
if (a.length > maxlen)
|
||||
|
@ -70,8 +64,7 @@ var padutils = {
|
|||
return a;
|
||||
}
|
||||
|
||||
function checkver(name)
|
||||
{
|
||||
function checkver(name) {
|
||||
var m = ua.match(RegExp(name + '\\/([\\d\\.]+)'));
|
||||
if (m && m.length > 1)
|
||||
{
|
||||
|
@ -123,8 +116,7 @@ var padutils = {
|
|||
return clean(x);
|
||||
},
|
||||
// e.g. "Thu Jun 18 2009 13:09"
|
||||
simpleDateTime: function(date)
|
||||
{
|
||||
simpleDateTime: function(date) {
|
||||
var d = new Date(+date); // accept either number or date
|
||||
var dayOfWeek = (['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'])[d.getDay()];
|
||||
var month = (['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])[d.getMonth()];
|
||||
|
@ -133,8 +125,7 @@ var padutils = {
|
|||
var hourmin = d.getHours() + ":" + ("0" + d.getMinutes()).slice(-2);
|
||||
return dayOfWeek + ' ' + month + ' ' + dayOfMonth + ' ' + year + ' ' + hourmin;
|
||||
},
|
||||
findURLs: function(text)
|
||||
{
|
||||
findURLs: function(text) {
|
||||
// copied from ACE
|
||||
var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
|
||||
var _REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/?=&#;()$]/.source + '|' + _REGEX_WORDCHAR.source + ')');
|
||||
|
@ -143,8 +134,7 @@ var padutils = {
|
|||
// returns null if no URLs, or [[startIndex1, url1], [startIndex2, url2], ...]
|
||||
|
||||
|
||||
function _findURLs(text)
|
||||
{
|
||||
function _findURLs(text) {
|
||||
_REGEX_URL.lastIndex = 0;
|
||||
var urls = null;
|
||||
var execResult;
|
||||
|
@ -161,14 +151,12 @@ var padutils = {
|
|||
|
||||
return _findURLs(text);
|
||||
},
|
||||
escapeHtmlWithClickableLinks: function(text, target)
|
||||
{
|
||||
escapeHtmlWithClickableLinks: function(text, target) {
|
||||
var idx = 0;
|
||||
var pieces = [];
|
||||
var urls = padutils.findURLs(text);
|
||||
|
||||
function advanceTo(i)
|
||||
{
|
||||
function advanceTo(i) {
|
||||
if (i > idx)
|
||||
{
|
||||
pieces.push(Security.escapeHTML(text.substring(idx, i)));
|
||||
|
@ -197,8 +185,7 @@ var padutils = {
|
|||
advanceTo(text.length);
|
||||
return pieces.join('');
|
||||
},
|
||||
bindEnterAndEscape: function(node, onEnter, onEscape)
|
||||
{
|
||||
bindEnterAndEscape: function(node, onEnter, onEscape) {
|
||||
|
||||
// Use keypress instead of keyup in bindEnterAndEscape
|
||||
// Keyup event is fired on enter in IME (Input Method Editor), But
|
||||
|
@ -206,8 +193,7 @@ var padutils = {
|
|||
// It is work on Windows (IE8, Chrome 6.0.472), CentOs (Firefox 3.0) and Mac OSX (Firefox 3.6.10, Chrome 6.0.472, Safari 5.0).
|
||||
if (onEnter)
|
||||
{
|
||||
node.keypress(function(evt)
|
||||
{
|
||||
node.keypress(function(evt) {
|
||||
if (evt.which == 13)
|
||||
{
|
||||
onEnter(evt);
|
||||
|
@ -217,8 +203,7 @@ var padutils = {
|
|||
|
||||
if (onEscape)
|
||||
{
|
||||
node.keydown(function(evt)
|
||||
{
|
||||
node.keydown(function(evt) {
|
||||
if (evt.which == 27)
|
||||
{
|
||||
onEscape(evt);
|
||||
|
@ -226,11 +211,9 @@ var padutils = {
|
|||
});
|
||||
}
|
||||
},
|
||||
timediff: function(d)
|
||||
{
|
||||
timediff: function(d) {
|
||||
var pad = require('./pad').pad; // Sidestep circular dependency
|
||||
function format(n, word)
|
||||
{
|
||||
function format(n, word) {
|
||||
n = Math.round(n);
|
||||
return ('' + n + ' ' + word + (n != 1 ? 's' : '') + ' ago');
|
||||
}
|
||||
|
@ -252,8 +235,7 @@ var padutils = {
|
|||
d /= 24;
|
||||
return format(d, 'day');
|
||||
},
|
||||
makeAnimationScheduler: function(funcToAnimateOneStep, stepTime, stepsAtOnce)
|
||||
{
|
||||
makeAnimationScheduler: function(funcToAnimateOneStep, stepTime, stepsAtOnce) {
|
||||
if (stepsAtOnce === undefined)
|
||||
{
|
||||
stepsAtOnce = 1;
|
||||
|
@ -261,12 +243,10 @@ var padutils = {
|
|||
|
||||
var animationTimer = null;
|
||||
|
||||
function scheduleAnimation()
|
||||
{
|
||||
function scheduleAnimation() {
|
||||
if (!animationTimer)
|
||||
{
|
||||
animationTimer = window.setTimeout(function()
|
||||
{
|
||||
animationTimer = window.setTimeout(function() {
|
||||
animationTimer = null;
|
||||
var n = stepsAtOnce;
|
||||
var moreToDo = true;
|
||||
|
@ -287,23 +267,20 @@ var padutils = {
|
|||
scheduleAnimation: scheduleAnimation
|
||||
};
|
||||
},
|
||||
makeShowHideAnimator: function(funcToArriveAtState, initiallyShown, fps, totalMs)
|
||||
{
|
||||
makeShowHideAnimator: function(funcToArriveAtState, initiallyShown, fps, totalMs) {
|
||||
var animationState = (initiallyShown ? 0 : -2); // -2 hidden, -1 to 0 fade in, 0 to 1 fade out
|
||||
var animationFrameDelay = 1000 / fps;
|
||||
var animationStep = animationFrameDelay / totalMs;
|
||||
|
||||
var scheduleAnimation = padutils.makeAnimationScheduler(animateOneStep, animationFrameDelay).scheduleAnimation;
|
||||
|
||||
function doShow()
|
||||
{
|
||||
function doShow() {
|
||||
animationState = -1;
|
||||
funcToArriveAtState(animationState);
|
||||
scheduleAnimation();
|
||||
}
|
||||
|
||||
function doQuickShow()
|
||||
{ // start showing without losing any fade-in progress
|
||||
function doQuickShow() { // start showing without losing any fade-in progress
|
||||
if (animationState < -1)
|
||||
{
|
||||
animationState = -1;
|
||||
|
@ -316,8 +293,7 @@ var padutils = {
|
|||
scheduleAnimation();
|
||||
}
|
||||
|
||||
function doHide()
|
||||
{
|
||||
function doHide() {
|
||||
if (animationState >= -1 && animationState <= 0)
|
||||
{
|
||||
animationState = 1e-6;
|
||||
|
@ -325,8 +301,7 @@ var padutils = {
|
|||
}
|
||||
}
|
||||
|
||||
function animateOneStep()
|
||||
{
|
||||
function animateOneStep() {
|
||||
if (animationState < -1 || animationState == 0)
|
||||
{
|
||||
return false;
|
||||
|
@ -374,8 +349,7 @@ var padutils = {
|
|||
},
|
||||
_nextActionId: 1,
|
||||
uncanceledActions: {},
|
||||
getCancellableAction: function(actionType, actionFunc)
|
||||
{
|
||||
getCancellableAction: function(actionType, actionFunc) {
|
||||
var o = padutils.uncanceledActions[actionType];
|
||||
if (!o)
|
||||
{
|
||||
|
@ -384,8 +358,7 @@ var padutils = {
|
|||
}
|
||||
var actionId = (padutils._nextActionId++);
|
||||
o[actionId] = true;
|
||||
return function()
|
||||
{
|
||||
return function() {
|
||||
var p = padutils.uncanceledActions[actionType];
|
||||
if (p && p[actionId])
|
||||
{
|
||||
|
@ -393,8 +366,7 @@ var padutils = {
|
|||
}
|
||||
};
|
||||
},
|
||||
cancelActions: function(actionType)
|
||||
{
|
||||
cancelActions: function(actionType) {
|
||||
var o = padutils.uncanceledActions[actionType];
|
||||
if (o)
|
||||
{
|
||||
|
@ -402,25 +374,21 @@ var padutils = {
|
|||
delete padutils.uncanceledActions[actionType];
|
||||
}
|
||||
},
|
||||
makeFieldLabeledWhenEmpty: function(field, labelText)
|
||||
{
|
||||
makeFieldLabeledWhenEmpty: function(field, labelText) {
|
||||
field = $(field);
|
||||
|
||||
function clear()
|
||||
{
|
||||
function clear() {
|
||||
field.addClass('editempty');
|
||||
field.val(labelText);
|
||||
}
|
||||
field.focus(function()
|
||||
{
|
||||
field.focus(function() {
|
||||
if (field.hasClass('editempty'))
|
||||
{
|
||||
field.val('');
|
||||
}
|
||||
field.removeClass('editempty');
|
||||
});
|
||||
field.blur(function()
|
||||
{
|
||||
field.blur(function() {
|
||||
if (!field.val())
|
||||
{
|
||||
clear();
|
||||
|
@ -430,12 +398,10 @@ var padutils = {
|
|||
clear: clear
|
||||
};
|
||||
},
|
||||
getCheckbox: function(node)
|
||||
{
|
||||
getCheckbox: function(node) {
|
||||
return $(node).is(':checked');
|
||||
},
|
||||
setCheckbox: function(node, value)
|
||||
{
|
||||
setCheckbox: function(node, value) {
|
||||
if (value)
|
||||
{
|
||||
$(node).attr('checked', 'checked');
|
||||
|
@ -445,22 +411,17 @@ var padutils = {
|
|||
$(node).removeAttr('checked');
|
||||
}
|
||||
},
|
||||
bindCheckboxChange: function(node, func)
|
||||
{
|
||||
bindCheckboxChange: function(node, func) {
|
||||
$(node).change(func);
|
||||
},
|
||||
encodeUserId: function(userId)
|
||||
{
|
||||
return userId.replace(/[^a-y0-9]/g, function(c)
|
||||
{
|
||||
encodeUserId: function(userId) {
|
||||
return userId.replace(/[^a-y0-9]/g, function(c) {
|
||||
if (c == ".") return "-";
|
||||
return 'z' + c.charCodeAt(0) + 'z';
|
||||
});
|
||||
},
|
||||
decodeUserId: function(encodedUserId)
|
||||
{
|
||||
return encodedUserId.replace(/[a-y0-9]+|-|z.+?z/g, function(cc)
|
||||
{
|
||||
decodeUserId: function(encodedUserId) {
|
||||
return encodedUserId.replace(/[a-y0-9]+|-|z.+?z/g, function(cc) {
|
||||
if (cc == '-') return '.';
|
||||
else if (cc.charAt(0) == 'z')
|
||||
{
|
||||
|
|
|
@ -17,8 +17,7 @@ function Scroll(outerWin) {
|
|||
this.rootDocument = parent.parent.document;
|
||||
}
|
||||
|
||||
Scroll.prototype.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary = function (rep, isScrollableEvent, innerHeight)
|
||||
{
|
||||
Scroll.prototype.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary = function (rep, isScrollableEvent, innerHeight) {
|
||||
// are we placing the caret on the line at the bottom of viewport?
|
||||
// And if so, do we need to scroll the editor, as defined on the settings.json?
|
||||
var shouldScrollWhenCaretIsAtBottomOfViewport = this.scrollSettings.scrollWhenCaretIsInTheLastLineOfViewport;
|
||||
|
@ -36,8 +35,7 @@ Scroll.prototype.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary = functio
|
|||
}
|
||||
}
|
||||
|
||||
Scroll.prototype.scrollWhenPressArrowKeys = function(arrowUp, rep, innerHeight)
|
||||
{
|
||||
Scroll.prototype.scrollWhenPressArrowKeys = function(arrowUp, rep, innerHeight) {
|
||||
// if percentageScrollArrowUp is 0, let the scroll to be handled as default, put the previous
|
||||
// rep line on the top of the viewport
|
||||
if(this._arrowUpWasPressedInTheFirstLineOfTheViewport(arrowUp, rep)){
|
||||
|
@ -54,8 +52,7 @@ Scroll.prototype.scrollWhenPressArrowKeys = function(arrowUp, rep, innerHeight)
|
|||
// Some plugins might set a minimum height to the editor (ex: ep_page_view), so checking
|
||||
// if (caretLine() === rep.lines.length() - 1) is not enough. We need to check if there are
|
||||
// other lines after caretLine(), and all of them are out of viewport.
|
||||
Scroll.prototype._isCaretAtTheBottomOfViewport = function(rep)
|
||||
{
|
||||
Scroll.prototype._isCaretAtTheBottomOfViewport = function(rep) {
|
||||
// computing a line position using getBoundingClientRect() is expensive.
|
||||
// (obs: getBoundingClientRect() is called on caretPosition.getPosition())
|
||||
// To avoid that, we only call this function when it is possible that the
|
||||
|
@ -76,8 +73,7 @@ Scroll.prototype._isCaretAtTheBottomOfViewport = function(rep)
|
|||
return false;
|
||||
}
|
||||
|
||||
Scroll.prototype._isLinePartiallyVisibleOnViewport = function(lineNumber, rep)
|
||||
{
|
||||
Scroll.prototype._isLinePartiallyVisibleOnViewport = function(lineNumber, rep) {
|
||||
var lineNode = rep.lines.atIndex(lineNumber);
|
||||
var linePosition = this._getLineEntryTopBottom(lineNode);
|
||||
var lineTop = linePosition.top;
|
||||
|
@ -98,8 +94,7 @@ Scroll.prototype._isLinePartiallyVisibleOnViewport = function(lineNumber, rep)
|
|||
(bottomOfLineIsAboveViewportBottom && bottomOfLineIsBelowViewportTop);
|
||||
}
|
||||
|
||||
Scroll.prototype._getViewPortTopBottom = function()
|
||||
{
|
||||
Scroll.prototype._getViewPortTopBottom = function() {
|
||||
var theTop = this.getScrollY();
|
||||
var doc = this.doc;
|
||||
var height = doc.documentElement.clientHeight; // includes padding
|
||||
|
@ -113,23 +108,20 @@ Scroll.prototype._getViewPortTopBottom = function()
|
|||
};
|
||||
}
|
||||
|
||||
Scroll.prototype._getEditorPositionTop = function()
|
||||
{
|
||||
Scroll.prototype._getEditorPositionTop = function() {
|
||||
var editor = parent.document.getElementsByTagName('iframe');
|
||||
var editorPositionTop = editor[0].offsetTop;
|
||||
return editorPositionTop;
|
||||
}
|
||||
|
||||
// ep_page_view adds padding-top, which makes the viewport smaller
|
||||
Scroll.prototype._getPaddingTopAddedWhenPageViewIsEnable = function()
|
||||
{
|
||||
Scroll.prototype._getPaddingTopAddedWhenPageViewIsEnable = function() {
|
||||
var aceOuter = this.rootDocument.getElementsByName("ace_outer");
|
||||
var aceOuterPaddingTop = parseInt($(aceOuter).css("padding-top"));
|
||||
return aceOuterPaddingTop;
|
||||
}
|
||||
|
||||
Scroll.prototype._getScrollXY = function()
|
||||
{
|
||||
Scroll.prototype._getScrollXY = function() {
|
||||
var win = this.outerWin;
|
||||
var odoc = this.doc;
|
||||
if (typeof(win.pageYOffset) == "number")
|
||||
|
@ -149,33 +141,27 @@ Scroll.prototype._getScrollXY = function()
|
|||
}
|
||||
}
|
||||
|
||||
Scroll.prototype.getScrollX = function()
|
||||
{
|
||||
Scroll.prototype.getScrollX = function() {
|
||||
return this._getScrollXY().x;
|
||||
}
|
||||
|
||||
Scroll.prototype.getScrollY = function()
|
||||
{
|
||||
Scroll.prototype.getScrollY = function() {
|
||||
return this._getScrollXY().y;
|
||||
}
|
||||
|
||||
Scroll.prototype.setScrollX = function(x)
|
||||
{
|
||||
Scroll.prototype.setScrollX = function(x) {
|
||||
this.outerWin.scrollTo(x, this.getScrollY());
|
||||
}
|
||||
|
||||
Scroll.prototype.setScrollY = function(y)
|
||||
{
|
||||
Scroll.prototype.setScrollY = function(y) {
|
||||
this.outerWin.scrollTo(this.getScrollX(), y);
|
||||
}
|
||||
|
||||
Scroll.prototype.setScrollXY = function(x, y)
|
||||
{
|
||||
Scroll.prototype.setScrollXY = function(x, y) {
|
||||
this.outerWin.scrollTo(x, y);
|
||||
}
|
||||
|
||||
Scroll.prototype._isCaretAtTheTopOfViewport = function(rep)
|
||||
{
|
||||
Scroll.prototype._isCaretAtTheTopOfViewport = function(rep) {
|
||||
var caretLine = rep.selStart[0];
|
||||
var linePrevCaretLine = caretLine - 1;
|
||||
var firstLineVisibleBeforeCaretLine = caretPosition.getPreviousVisibleLine(linePrevCaretLine, rep);
|
||||
|
@ -201,8 +187,7 @@ Scroll.prototype._isCaretAtTheTopOfViewport = function(rep)
|
|||
// By default, when user makes an edition in a line out of viewport, this line goes
|
||||
// to the edge of viewport. This function gets the extra pixels necessary to get the
|
||||
// caret line in a position X relative to Y% viewport.
|
||||
Scroll.prototype._getPixelsRelativeToPercentageOfViewport = function(innerHeight, aboveOfViewport)
|
||||
{
|
||||
Scroll.prototype._getPixelsRelativeToPercentageOfViewport = function(innerHeight, aboveOfViewport) {
|
||||
var pixels = 0;
|
||||
var scrollPercentageRelativeToViewport = this._getPercentageToScroll(aboveOfViewport);
|
||||
if(scrollPercentageRelativeToViewport > 0 && scrollPercentageRelativeToViewport <= 1){
|
||||
|
@ -213,8 +198,7 @@ Scroll.prototype._getPixelsRelativeToPercentageOfViewport = function(innerHeight
|
|||
|
||||
// we use different percentages when change selection. It depends on if it is
|
||||
// either above the top or below the bottom of the page
|
||||
Scroll.prototype._getPercentageToScroll = function(aboveOfViewport)
|
||||
{
|
||||
Scroll.prototype._getPercentageToScroll = function(aboveOfViewport) {
|
||||
var percentageToScroll = this.scrollSettings.percentage.editionBelowViewport;
|
||||
if(aboveOfViewport){
|
||||
percentageToScroll = this.scrollSettings.percentage.editionAboveViewport;
|
||||
|
@ -222,8 +206,7 @@ Scroll.prototype._getPercentageToScroll = function(aboveOfViewport)
|
|||
return percentageToScroll;
|
||||
}
|
||||
|
||||
Scroll.prototype._getPixelsToScrollWhenUserPressesArrowUp = function(innerHeight)
|
||||
{
|
||||
Scroll.prototype._getPixelsToScrollWhenUserPressesArrowUp = function(innerHeight) {
|
||||
var pixels = 0;
|
||||
var percentageToScrollUp = this.scrollSettings.percentageToScrollWhenUserPressesArrowUp;
|
||||
if(percentageToScrollUp > 0 && percentageToScrollUp <= 1){
|
||||
|
@ -232,8 +215,7 @@ Scroll.prototype._getPixelsToScrollWhenUserPressesArrowUp = function(innerHeight
|
|||
return pixels;
|
||||
}
|
||||
|
||||
Scroll.prototype._scrollYPage = function(pixelsToScroll)
|
||||
{
|
||||
Scroll.prototype._scrollYPage = function(pixelsToScroll) {
|
||||
var durationOfAnimationToShowFocusline = this.scrollSettings.duration;
|
||||
if(durationOfAnimationToShowFocusline){
|
||||
this._scrollYPageWithAnimation(pixelsToScroll, durationOfAnimationToShowFocusline);
|
||||
|
@ -242,13 +224,11 @@ Scroll.prototype._scrollYPage = function(pixelsToScroll)
|
|||
}
|
||||
}
|
||||
|
||||
Scroll.prototype._scrollYPageWithoutAnimation = function(pixelsToScroll)
|
||||
{
|
||||
Scroll.prototype._scrollYPageWithoutAnimation = function(pixelsToScroll) {
|
||||
this.outerWin.scrollBy(0, pixelsToScroll);
|
||||
}
|
||||
|
||||
Scroll.prototype._scrollYPageWithAnimation = function(pixelsToScroll, durationOfAnimationToShowFocusline)
|
||||
{
|
||||
Scroll.prototype._scrollYPageWithAnimation = function(pixelsToScroll, durationOfAnimationToShowFocusline) {
|
||||
var outerDocBody = this.doc.getElementById("outerdocbody");
|
||||
|
||||
// it works on later versions of Chrome
|
||||
|
@ -262,8 +242,7 @@ Scroll.prototype._scrollYPageWithAnimation = function(pixelsToScroll, durationOf
|
|||
|
||||
// using a custom queue and clearing it, we avoid creating a queue of scroll animations. So if this function
|
||||
// is called twice quickly, only the last one runs.
|
||||
Scroll.prototype._triggerScrollWithAnimation = function($elem, pixelsToScroll, durationOfAnimationToShowFocusline)
|
||||
{
|
||||
Scroll.prototype._triggerScrollWithAnimation = function($elem, pixelsToScroll, durationOfAnimationToShowFocusline) {
|
||||
// clear the queue of animation
|
||||
$elem.stop("scrollanimation");
|
||||
$elem.animate({
|
||||
|
@ -278,8 +257,7 @@ Scroll.prototype._triggerScrollWithAnimation = function($elem, pixelsToScroll, d
|
|||
// needed to be completely in view. If the value is greater than 0 and less than or equal to 1,
|
||||
// besides of scrolling the minimum needed to be visible, it scrolls additionally
|
||||
// (viewport height * scrollAmountWhenFocusLineIsOutOfViewport) pixels
|
||||
Scroll.prototype.scrollNodeVerticallyIntoView = function(rep, innerHeight)
|
||||
{
|
||||
Scroll.prototype.scrollNodeVerticallyIntoView = function(rep, innerHeight) {
|
||||
var viewport = this._getViewPortTopBottom();
|
||||
var isPartOfRepLineOutOfViewport = this._partOfRepLineIsOutOfViewport(viewport, rep);
|
||||
|
||||
|
@ -304,8 +282,7 @@ Scroll.prototype.scrollNodeVerticallyIntoView = function(rep, innerHeight)
|
|||
}
|
||||
}
|
||||
|
||||
Scroll.prototype._partOfRepLineIsOutOfViewport = function(viewportPosition, rep)
|
||||
{
|
||||
Scroll.prototype._partOfRepLineIsOutOfViewport = function(viewportPosition, rep) {
|
||||
var focusLine = (rep.selFocusAtStart ? rep.selStart[0] : rep.selEnd[0]);
|
||||
var line = rep.lines.atIndex(focusLine);
|
||||
var linePosition = this._getLineEntryTopBottom(line);
|
||||
|
@ -315,8 +292,7 @@ Scroll.prototype._partOfRepLineIsOutOfViewport = function(viewportPosition, rep)
|
|||
return lineIsBelowOfViewport || lineIsAboveOfViewport;
|
||||
}
|
||||
|
||||
Scroll.prototype._getLineEntryTopBottom = function(entry, destObj)
|
||||
{
|
||||
Scroll.prototype._getLineEntryTopBottom = function(entry, destObj) {
|
||||
var dom = entry.lineNode;
|
||||
var top = dom.offsetTop;
|
||||
var height = dom.offsetHeight;
|
||||
|
@ -326,24 +302,20 @@ Scroll.prototype._getLineEntryTopBottom = function(entry, destObj)
|
|||
return obj;
|
||||
}
|
||||
|
||||
Scroll.prototype._arrowUpWasPressedInTheFirstLineOfTheViewport = function(arrowUp, rep)
|
||||
{
|
||||
Scroll.prototype._arrowUpWasPressedInTheFirstLineOfTheViewport = function(arrowUp, rep) {
|
||||
var percentageScrollArrowUp = this.scrollSettings.percentageToScrollWhenUserPressesArrowUp;
|
||||
return percentageScrollArrowUp && arrowUp && this._isCaretAtTheTopOfViewport(rep);
|
||||
}
|
||||
|
||||
Scroll.prototype.getVisibleLineRange = function(rep)
|
||||
{
|
||||
Scroll.prototype.getVisibleLineRange = function(rep) {
|
||||
var viewport = this._getViewPortTopBottom();
|
||||
//console.log("viewport top/bottom: %o", viewport);
|
||||
var obj = {};
|
||||
var self = this;
|
||||
var start = rep.lines.search(function(e)
|
||||
{
|
||||
var start = rep.lines.search(function(e) {
|
||||
return self._getLineEntryTopBottom(e, obj).bottom > viewport.top;
|
||||
});
|
||||
var end = rep.lines.search(function(e)
|
||||
{
|
||||
var end = rep.lines.search(function(e) {
|
||||
// return the first line that the top position is greater or equal than
|
||||
// the viewport. That is the first line that is below the viewport bottom.
|
||||
// So the line that is in the bottom of the viewport is the very previous one.
|
||||
|
@ -354,13 +326,11 @@ Scroll.prototype.getVisibleLineRange = function(rep)
|
|||
return [start, end - 1];
|
||||
}
|
||||
|
||||
Scroll.prototype.getVisibleCharRange = function(rep)
|
||||
{
|
||||
Scroll.prototype.getVisibleCharRange = function(rep) {
|
||||
var lineRange = this.getVisibleLineRange(rep);
|
||||
return [rep.lines.offsetOfIndex(lineRange[0]), rep.lines.offsetOfIndex(lineRange[1])];
|
||||
}
|
||||
|
||||
exports.init = function(outerWin)
|
||||
{
|
||||
exports.init = function(outerWin) {
|
||||
return new Scroll(outerWin);
|
||||
}
|
||||
|
|
|
@ -25,13 +25,11 @@ var Ace2Common = require('./ace2_common'),
|
|||
|
||||
var noop = Ace2Common.noop;
|
||||
|
||||
function SkipList()
|
||||
{
|
||||
function SkipList() {
|
||||
var PROFILER = window.PROFILER;
|
||||
if (!PROFILER)
|
||||
{
|
||||
PROFILER = function()
|
||||
{
|
||||
PROFILER = function() {
|
||||
return {
|
||||
start: noop,
|
||||
mark: noop,
|
||||
|
@ -71,8 +69,7 @@ function SkipList()
|
|||
// this point.
|
||||
|
||||
|
||||
function _getPoint(targetLoc)
|
||||
{
|
||||
function _getPoint(targetLoc) {
|
||||
var numLevels = start.levels;
|
||||
var lvl = numLevels - 1;
|
||||
var i = -1,
|
||||
|
@ -106,15 +103,13 @@ function SkipList()
|
|||
idxs: idxs,
|
||||
loc: targetLoc,
|
||||
widthSkips: widthSkips,
|
||||
toString: function()
|
||||
{
|
||||
toString: function() {
|
||||
return "getPoint(" + targetLoc + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function _getNodeAtOffset(targetOffset)
|
||||
{
|
||||
function _getNodeAtOffset(targetOffset) {
|
||||
var i = 0;
|
||||
var n = start;
|
||||
var lvl = start.levels - 1;
|
||||
|
@ -132,13 +127,11 @@ function SkipList()
|
|||
return n;
|
||||
}
|
||||
|
||||
function _entryWidth(e)
|
||||
{
|
||||
function _entryWidth(e) {
|
||||
return (e && e.width) || 0;
|
||||
}
|
||||
|
||||
function _insertKeyAtPoint(point, newKey, entry)
|
||||
{
|
||||
function _insertKeyAtPoint(point, newKey, entry) {
|
||||
var p = PROFILER("insertKey", false);
|
||||
var newNode = {
|
||||
key: newKey,
|
||||
|
@ -207,13 +200,11 @@ function SkipList()
|
|||
p.end();
|
||||
}
|
||||
|
||||
function _getNodeAtPoint(point)
|
||||
{
|
||||
function _getNodeAtPoint(point) {
|
||||
return point.nodes[0].downPtrs[0];
|
||||
}
|
||||
|
||||
function _incrementPoint(point)
|
||||
{
|
||||
function _incrementPoint(point) {
|
||||
point.loc++;
|
||||
for (var i = 0; i < point.nodes.length; i++)
|
||||
{
|
||||
|
@ -226,8 +217,7 @@ function SkipList()
|
|||
}
|
||||
}
|
||||
|
||||
function _deleteKeyAtPoint(point)
|
||||
{
|
||||
function _deleteKeyAtPoint(point) {
|
||||
var elem = point.nodes[0].downPtrs[0];
|
||||
var elemWidth = _entryWidth(elem.entry);
|
||||
for (var i = 0; i < point.nodes.length; i++)
|
||||
|
@ -256,8 +246,7 @@ function SkipList()
|
|||
totalWidth -= elemWidth;
|
||||
}
|
||||
|
||||
function _propagateWidthChange(node)
|
||||
{
|
||||
function _propagateWidthChange(node) {
|
||||
var oldWidth = node.downSkipWidths[0];
|
||||
var newWidth = _entryWidth(node.entry);
|
||||
var widthChange = newWidth - oldWidth;
|
||||
|
@ -275,8 +264,7 @@ function SkipList()
|
|||
totalWidth += widthChange;
|
||||
}
|
||||
|
||||
function _getNodeIndex(node, byWidth)
|
||||
{
|
||||
function _getNodeIndex(node, byWidth) {
|
||||
var dist = (byWidth ? 0 : -1);
|
||||
var n = node;
|
||||
while (n !== start)
|
||||
|
@ -289,8 +277,7 @@ function SkipList()
|
|||
return dist;
|
||||
}
|
||||
|
||||
function _getNodeByKey(key)
|
||||
{
|
||||
function _getNodeByKey(key) {
|
||||
return keyToNodeMap['$KEY$' + key];
|
||||
}
|
||||
|
||||
|
@ -299,14 +286,12 @@ function SkipList()
|
|||
// all truthy entries.
|
||||
|
||||
|
||||
function _search(entryFunc)
|
||||
{
|
||||
function _search(entryFunc) {
|
||||
var low = start;
|
||||
var lvl = start.levels - 1;
|
||||
var lowIndex = -1;
|
||||
|
||||
function f(node)
|
||||
{
|
||||
function f(node) {
|
||||
if (node === start) return false;
|
||||
else if (node === end) return true;
|
||||
else return entryFunc(node.entry);
|
||||
|
@ -331,19 +316,16 @@ that is a string.
|
|||
*/
|
||||
var self = this;
|
||||
_.extend(this, {
|
||||
length: function()
|
||||
{
|
||||
length: function() {
|
||||
return numNodes;
|
||||
},
|
||||
atIndex: function(i)
|
||||
{
|
||||
atIndex: function(i) {
|
||||
if (i < 0) console.warn("atIndex(" + i + ")");
|
||||
if (i >= numNodes) console.warn("atIndex(" + i + ">=" + numNodes + ")");
|
||||
return _getNodeAtPoint(_getPoint(i)).entry;
|
||||
},
|
||||
// differs from Array.splice() in that new elements are in an array, not varargs
|
||||
splice: function(start, deleteCount, newEntryArray)
|
||||
{
|
||||
splice: function(start, deleteCount, newEntryArray) {
|
||||
if (start < 0) console.warn("splice(" + start + ", ...)");
|
||||
if (start + deleteCount > numNodes)
|
||||
{
|
||||
|
@ -366,20 +348,16 @@ that is a string.
|
|||
node.entry = entry;
|
||||
}
|
||||
},
|
||||
next: function(entry)
|
||||
{
|
||||
next: function(entry) {
|
||||
return _getNodeByKey(entry.key).downPtrs[0].entry || null;
|
||||
},
|
||||
prev: function(entry)
|
||||
{
|
||||
prev: function(entry) {
|
||||
return _getNodeByKey(entry.key).upPtrs[0].entry || null;
|
||||
},
|
||||
push: function(entry)
|
||||
{
|
||||
push: function(entry) {
|
||||
self.splice(numNodes, 0, [entry]);
|
||||
},
|
||||
slice: function(start, end)
|
||||
{
|
||||
slice: function(start, end) {
|
||||
// act like Array.slice()
|
||||
if (start === undefined) start = 0;
|
||||
else if (start < 0) start += numNodes;
|
||||
|
@ -402,68 +380,54 @@ that is a string.
|
|||
}
|
||||
return array;
|
||||
},
|
||||
atKey: function(key)
|
||||
{
|
||||
atKey: function(key) {
|
||||
return _getNodeByKey(key).entry;
|
||||
},
|
||||
indexOfKey: function(key)
|
||||
{
|
||||
indexOfKey: function(key) {
|
||||
return _getNodeIndex(_getNodeByKey(key));
|
||||
},
|
||||
indexOfEntry: function(entry)
|
||||
{
|
||||
indexOfEntry: function(entry) {
|
||||
return self.indexOfKey(entry.key);
|
||||
},
|
||||
containsKey: function(key)
|
||||
{
|
||||
containsKey: function(key) {
|
||||
return !!(_getNodeByKey(key));
|
||||
},
|
||||
// gets the last entry starting at or before the offset
|
||||
atOffset: function(offset)
|
||||
{
|
||||
atOffset: function(offset) {
|
||||
return _getNodeAtOffset(offset).entry;
|
||||
},
|
||||
keyAtOffset: function(offset)
|
||||
{
|
||||
keyAtOffset: function(offset) {
|
||||
return self.atOffset(offset).key;
|
||||
},
|
||||
offsetOfKey: function(key)
|
||||
{
|
||||
offsetOfKey: function(key) {
|
||||
return _getNodeIndex(_getNodeByKey(key), true);
|
||||
},
|
||||
offsetOfEntry: function(entry)
|
||||
{
|
||||
offsetOfEntry: function(entry) {
|
||||
return self.offsetOfKey(entry.key);
|
||||
},
|
||||
setEntryWidth: function(entry, width)
|
||||
{
|
||||
setEntryWidth: function(entry, width) {
|
||||
entry.width = width;
|
||||
_propagateWidthChange(_getNodeByKey(entry.key));
|
||||
},
|
||||
totalWidth: function()
|
||||
{
|
||||
totalWidth: function() {
|
||||
return totalWidth;
|
||||
},
|
||||
offsetOfIndex: function(i)
|
||||
{
|
||||
offsetOfIndex: function(i) {
|
||||
if (i < 0) return 0;
|
||||
if (i >= numNodes) return totalWidth;
|
||||
return self.offsetOfEntry(self.atIndex(i));
|
||||
},
|
||||
indexOfOffset: function(offset)
|
||||
{
|
||||
indexOfOffset: function(offset) {
|
||||
if (offset <= 0) return 0;
|
||||
if (offset >= totalWidth) return numNodes;
|
||||
return self.indexOfEntry(self.atOffset(offset));
|
||||
},
|
||||
search: function(entryFunc)
|
||||
{
|
||||
search: function(entryFunc) {
|
||||
return _search(entryFunc);
|
||||
},
|
||||
//debugToString: _debugToString,
|
||||
debugGetPoint: _getPoint,
|
||||
debugDepth: function()
|
||||
{
|
||||
debugDepth: function() {
|
||||
return start.levels;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -31,8 +31,7 @@ var hooks = require('./pluginfw/hooks');
|
|||
var token, padId, export_links;
|
||||
|
||||
function init() {
|
||||
$(document).ready(function ()
|
||||
{
|
||||
$(document).ready(function () {
|
||||
// start the custom js
|
||||
if (typeof customStart == "function") customStart();
|
||||
|
||||
|
@ -63,19 +62,16 @@ function init() {
|
|||
socket = io.connect(url, {path: exports.baseURL + 'socket.io', resource: resource});
|
||||
|
||||
//send the ready message once we're connected
|
||||
socket.on('connect', function()
|
||||
{
|
||||
socket.on('connect', function() {
|
||||
sendSocketMsg("CLIENT_READY", {});
|
||||
});
|
||||
|
||||
socket.on('disconnect', function()
|
||||
{
|
||||
socket.on('disconnect', function() {
|
||||
BroadcastSlider.showReconnectUI();
|
||||
});
|
||||
|
||||
//route the incoming messages
|
||||
socket.on('message', function(message)
|
||||
{
|
||||
socket.on('message', function(message) {
|
||||
if(message.type == "CLIENT_VARS")
|
||||
{
|
||||
handleClientVars(message);
|
||||
|
@ -91,8 +87,7 @@ function init() {
|
|||
//get all the export links
|
||||
export_links = $('#export > .exportlink')
|
||||
|
||||
$('button#forcereconnect').click(function()
|
||||
{
|
||||
$('button#forcereconnect').click(function() {
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
|
@ -104,8 +99,7 @@ function init() {
|
|||
}
|
||||
|
||||
//sends a message over the socket
|
||||
function sendSocketMsg(type, data)
|
||||
{
|
||||
function sendSocketMsg(type, data) {
|
||||
socket.json.send({
|
||||
component: 'pad', // FIXME: Remove this stupidity!
|
||||
type,
|
||||
|
@ -120,8 +114,7 @@ function sendSocketMsg(type, data)
|
|||
var fireWhenAllScriptsAreLoaded = [];
|
||||
|
||||
var changesetLoader;
|
||||
function handleClientVars(message)
|
||||
{
|
||||
function handleClientVars(message) {
|
||||
//save the client Vars
|
||||
clientVars = message.data;
|
||||
|
||||
|
@ -137,11 +130,9 @@ function handleClientVars(message)
|
|||
var baseURI = document.location.pathname;
|
||||
|
||||
//change export urls when the slider moves
|
||||
BroadcastSlider.onSlider(function(revno)
|
||||
{
|
||||
BroadcastSlider.onSlider(function(revno) {
|
||||
// export_links is a jQuery Array, so .each is allowed.
|
||||
export_links.each(function()
|
||||
{
|
||||
export_links.each(function() {
|
||||
// Modified from regular expression to fix:
|
||||
// https://github.com/ether/etherpad-lite/issues/4071
|
||||
// Where a padId that was numeric would create the wrong export link
|
||||
|
|
|
@ -23,10 +23,8 @@
|
|||
var Changeset = require('./Changeset');
|
||||
var _ = require('./underscore');
|
||||
|
||||
var undoModule = (function()
|
||||
{
|
||||
var stack = (function()
|
||||
{
|
||||
var undoModule = (function() {
|
||||
var stack = (function() {
|
||||
var stackElements = [];
|
||||
// two types of stackElements:
|
||||
// 1) { elementType: UNDOABLE_EVENT, eventType: "anything", [backset: <changeset>,]
|
||||
|
@ -38,8 +36,7 @@ var undoModule = (function()
|
|||
var UNDOABLE_EVENT = "undoableEvent";
|
||||
var EXTERNAL_CHANGE = "externalChange";
|
||||
|
||||
function clearStack()
|
||||
{
|
||||
function clearStack() {
|
||||
stackElements.length = 0;
|
||||
stackElements.push(
|
||||
{
|
||||
|
@ -50,8 +47,7 @@ var undoModule = (function()
|
|||
}
|
||||
clearStack();
|
||||
|
||||
function pushEvent(event)
|
||||
{
|
||||
function pushEvent(event) {
|
||||
var e = _.extend(
|
||||
{}, event);
|
||||
e.elementType = UNDOABLE_EVENT;
|
||||
|
@ -60,8 +56,7 @@ var undoModule = (function()
|
|||
//dmesg("pushEvent backset: "+event.backset);
|
||||
}
|
||||
|
||||
function pushExternalChange(cs)
|
||||
{
|
||||
function pushExternalChange(cs) {
|
||||
var idx = stackElements.length - 1;
|
||||
if (stackElements[idx].elementType == EXTERNAL_CHANGE)
|
||||
{
|
||||
|
@ -77,8 +72,7 @@ var undoModule = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function _exposeEvent(nthFromTop)
|
||||
{
|
||||
function _exposeEvent(nthFromTop) {
|
||||
// precond: 0 <= nthFromTop < numUndoableEvents
|
||||
var targetIndex = stackElements.length - 1 - nthFromTop;
|
||||
var idx = stackElements.length - 1;
|
||||
|
@ -121,20 +115,17 @@ var undoModule = (function()
|
|||
}
|
||||
}
|
||||
|
||||
function getNthFromTop(n)
|
||||
{
|
||||
function getNthFromTop(n) {
|
||||
// precond: 0 <= n < numEvents()
|
||||
_exposeEvent(n);
|
||||
return stackElements[stackElements.length - 1 - n];
|
||||
}
|
||||
|
||||
function numEvents()
|
||||
{
|
||||
function numEvents() {
|
||||
return numUndoableEvents;
|
||||
}
|
||||
|
||||
function popEvent()
|
||||
{
|
||||
function popEvent() {
|
||||
// precond: numEvents() > 0
|
||||
_exposeEvent(0);
|
||||
numUndoableEvents--;
|
||||
|
@ -154,14 +145,12 @@ var undoModule = (function()
|
|||
// invariant: stack always has at least one undoable event
|
||||
var undoPtr = 0; // zero-index from top of stack, 0 == top
|
||||
|
||||
function clearHistory()
|
||||
{
|
||||
function clearHistory() {
|
||||
stack.clearStack();
|
||||
undoPtr = 0;
|
||||
}
|
||||
|
||||
function _charOccurrences(str, c)
|
||||
{
|
||||
function _charOccurrences(str, c) {
|
||||
var i = 0;
|
||||
var count = 0;
|
||||
while (i >= 0 && i < str.length)
|
||||
|
@ -176,13 +165,11 @@ var undoModule = (function()
|
|||
return count;
|
||||
}
|
||||
|
||||
function _opcodeOccurrences(cs, opcode)
|
||||
{
|
||||
function _opcodeOccurrences(cs, opcode) {
|
||||
return _charOccurrences(Changeset.unpack(cs).ops, opcode);
|
||||
}
|
||||
|
||||
function _mergeChangesets(cs1, cs2)
|
||||
{
|
||||
function _mergeChangesets(cs1, cs2) {
|
||||
if (!cs1) return cs2;
|
||||
if (!cs2) return cs1;
|
||||
|
||||
|
@ -219,12 +206,10 @@ var undoModule = (function()
|
|||
return null;
|
||||
}
|
||||
|
||||
function reportEvent(event)
|
||||
{
|
||||
function reportEvent(event) {
|
||||
var topEvent = stack.getNthFromTop(0);
|
||||
|
||||
function applySelectionToTop()
|
||||
{
|
||||
function applySelectionToTop() {
|
||||
if ((typeof event.selStart) == "number")
|
||||
{
|
||||
topEvent.selStart = event.selStart;
|
||||
|
@ -268,16 +253,14 @@ var undoModule = (function()
|
|||
|
||||
}
|
||||
|
||||
function reportExternalChange(changeset)
|
||||
{
|
||||
function reportExternalChange(changeset) {
|
||||
if (changeset && !Changeset.isIdentity(changeset))
|
||||
{
|
||||
stack.pushExternalChange(changeset);
|
||||
}
|
||||
}
|
||||
|
||||
function _getSelectionInfo(event)
|
||||
{
|
||||
function _getSelectionInfo(event) {
|
||||
if ((typeof event.selStart) != "number")
|
||||
{
|
||||
return null;
|
||||
|
@ -298,8 +281,7 @@ var undoModule = (function()
|
|||
// or can be called with no arguments to mean that no undo is possible.
|
||||
// "eventFunc" will be called exactly once.
|
||||
|
||||
function performUndo(eventFunc)
|
||||
{
|
||||
function performUndo(eventFunc) {
|
||||
if (undoPtr < stack.numEvents() - 1)
|
||||
{
|
||||
var backsetEvent = stack.getNthFromTop(undoPtr);
|
||||
|
@ -311,8 +293,7 @@ var undoModule = (function()
|
|||
else eventFunc();
|
||||
}
|
||||
|
||||
function performRedo(eventFunc)
|
||||
{
|
||||
function performRedo(eventFunc) {
|
||||
if (undoPtr >= 2)
|
||||
{
|
||||
var backsetEvent = stack.getNthFromTop(0);
|
||||
|
@ -324,8 +305,7 @@ var undoModule = (function()
|
|||
else eventFunc();
|
||||
}
|
||||
|
||||
function getAPool()
|
||||
{
|
||||
function getAPool() {
|
||||
return undoModule.apool;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
function customStart()
|
||||
{
|
||||
function customStart() {
|
||||
//define your javascript here
|
||||
//jquery is available - except index.js
|
||||
//you can load extra scripts with $.getScript http://api.jquery.com/jQuery.getScript/
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
function customStart()
|
||||
{
|
||||
function customStart() {
|
||||
$('#pad_title').show();
|
||||
$('.buttonicon').mousedown(function() { $(this).parent().addClass('pressed'); })
|
||||
$('.buttonicon').mouseup(function() { $(this).parent().removeClass('pressed'); })
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
function customStart()
|
||||
{
|
||||
function customStart() {
|
||||
}
|
||||
|
|
|
@ -58,8 +58,7 @@ function runTest(number){
|
|||
});
|
||||
}
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -98,8 +98,7 @@ var endPoint = function(point, version){
|
|||
return '/api/'+version+'/'+point+'?apikey='+apiKey;
|
||||
}
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -101,8 +101,7 @@ var endPoint = function(point){
|
|||
return '/api/'+apiVersion+'/'+point+'?apikey='+apiKey;
|
||||
}
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -58,8 +58,7 @@ console.log("here");
|
|||
});
|
||||
}
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -140,8 +140,7 @@ var endPoint = function(point, version){
|
|||
return '/api/'+version+'/'+point+'?apikey='+apiKey;
|
||||
}
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -361,8 +361,7 @@ var endPoint = function(point, version){
|
|||
return `/api/${version}/${point}?apikey=${apiKey}`;
|
||||
};
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -804,8 +804,7 @@ var endPoint = function(point, version){
|
|||
return '/api/'+version+'/'+point+'?apikey='+apiKey;
|
||||
}
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -289,8 +289,7 @@ const endPoint = function(point) {
|
|||
return `/api/${apiVersion}/${point}?apikey=${apiKey}`;
|
||||
};
|
||||
|
||||
function makeid()
|
||||
{
|
||||
function makeid() {
|
||||
let text = '';
|
||||
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@ var helper = {};
|
|||
});
|
||||
}
|
||||
|
||||
helper.randomString = function randomString(len)
|
||||
{
|
||||
helper.randomString = function randomString(len) {
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
var randomstring = '';
|
||||
for (var i = 0; i < len; i++)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
describe("embed links", function(){
|
||||
var objectify = function (str)
|
||||
{
|
||||
var objectify = function (str) {
|
||||
var hash = {};
|
||||
var parts = str.split('&');
|
||||
for(var i = 0; i < parts.length; i++)
|
||||
|
|
Loading…
Reference in a new issue