lint: broadcast_revisions (#4571)
Co-authored-by: Richard Hansen <rhansen@rhansen.org>pull/4613/head
parent
4aef15cb11
commit
8bf463fb00
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
|
@ -32,51 +34,33 @@ const 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) {
|
||||
let goToRevisionIfEnabledCount = 0;
|
||||
let 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*/) {
|
||||
const len = this.length >>> 0;
|
||||
|
||||
let from = Number(arguments[1]) || 0;
|
||||
from = (from < 0) ? Math.ceil(from) : Math.floor(from);
|
||||
if (from < 0) from += len;
|
||||
|
||||
for (; from < len; from++) {
|
||||
if (from in this && this[from] === elt) return from;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
|
||||
function debugLog() {
|
||||
const debugLog = (...args) => {
|
||||
try {
|
||||
if (window.console) console.log.apply(console, arguments);
|
||||
if (window.console) console.log(...args);
|
||||
} catch (e) {
|
||||
if (window.console) console.log('error printing: ', e);
|
||||
}
|
||||
}
|
||||
|
||||
// var socket;
|
||||
const channelState = 'DISCONNECTED';
|
||||
|
||||
const appLevelDisconnectReason = null;
|
||||
};
|
||||
|
||||
const padContents = {
|
||||
currentRevision: clientVars.collab_client_vars.rev,
|
||||
currentTime: clientVars.collab_client_vars.time,
|
||||
currentLines: Changeset.splitTextLines(clientVars.collab_client_vars.initialAttributedText.text),
|
||||
currentLines:
|
||||
Changeset.splitTextLines(clientVars.collab_client_vars.initialAttributedText.text),
|
||||
currentDivs: null,
|
||||
// to be filled in once the dom loads
|
||||
apool: (new AttribPool()).fromJsonable(clientVars.collab_client_vars.apool),
|
||||
alines: Changeset.splitAttributionLines(
|
||||
clientVars.collab_client_vars.initialAttributedText.attribs, clientVars.collab_client_vars.initialAttributedText.text),
|
||||
clientVars.collab_client_vars.initialAttributedText.attribs,
|
||||
clientVars.collab_client_vars.initialAttributedText.text),
|
||||
|
||||
// generates a jquery element containing HTML for a line
|
||||
lineToElement(line, aline) {
|
||||
const element = document.createElement('div');
|
||||
const emptyLine = (line == '\n');
|
||||
const emptyLine = (line === '\n');
|
||||
const domInfo = domline.createDomLine(!emptyLine, true);
|
||||
linestylefilter.populateDomLine(line, aline, this.apool, domInfo);
|
||||
domInfo.prepareForAdd();
|
||||
|
@ -86,9 +70,10 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
return $(element);
|
||||
},
|
||||
|
||||
applySpliceToDivs(start, numRemoved, newLines) {
|
||||
// splice the lines
|
||||
splice(start, numRemoved, ...newLines) {
|
||||
// remove spliced-out lines from DOM
|
||||
for (var i = start; i < start + numRemoved && i < this.currentDivs.length; i++) {
|
||||
for (let i = start; i < start + numRemoved && i < this.currentDivs.length; i++) {
|
||||
this.currentDivs[i].remove();
|
||||
}
|
||||
|
||||
|
@ -96,7 +81,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
this.currentDivs.splice(start, numRemoved);
|
||||
|
||||
const newDivs = [];
|
||||
for (var i = 0; i < newLines.length; i++) {
|
||||
for (let i = 0; i < newLines.length; i++) {
|
||||
newDivs.push(this.lineToElement(newLines[i], this.alines[start + i]));
|
||||
}
|
||||
|
||||
|
@ -104,7 +89,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
let startDiv = this.currentDivs[start - 1] || null;
|
||||
|
||||
// insert the div elements into the correct place, in the correct order
|
||||
for (var i = 0; i < newDivs.length; i++) {
|
||||
for (let i = 0; i < newDivs.length; i++) {
|
||||
if (startDiv) {
|
||||
startDiv.after(newDivs[i]);
|
||||
} else {
|
||||
|
@ -114,23 +99,10 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
}
|
||||
|
||||
// insert new divs into currentDivs array
|
||||
newDivs.unshift(0); // remove 0 elements
|
||||
newDivs.unshift(start);
|
||||
this.currentDivs.splice.apply(this.currentDivs, newDivs);
|
||||
return this;
|
||||
},
|
||||
|
||||
// splice the lines
|
||||
splice(start, numRemoved, newLinesVA) {
|
||||
const newLines = _.map(Array.prototype.slice.call(arguments, 2), (s) => s);
|
||||
|
||||
// apply this splice to the divs
|
||||
this.applySpliceToDivs(start, numRemoved, newLines);
|
||||
this.currentDivs.splice(start, 0, ...newDivs);
|
||||
|
||||
// call currentLines.splice, to keep the currentLines array up to date
|
||||
newLines.unshift(numRemoved);
|
||||
newLines.unshift(start);
|
||||
this.currentLines.splice.apply(this.currentLines, arguments);
|
||||
this.currentLines.splice(start, numRemoved, ...newLines);
|
||||
},
|
||||
// returns the contents of the specified line I
|
||||
get(i) {
|
||||
|
@ -142,16 +114,15 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
},
|
||||
|
||||
getActiveAuthors() {
|
||||
const self = this;
|
||||
const authors = [];
|
||||
const seenNums = {};
|
||||
const alines = self.alines;
|
||||
const alines = this.alines;
|
||||
for (let i = 0; i < alines.length; i++) {
|
||||
Changeset.eachAttribNumber(alines[i], (n) => {
|
||||
if (!seenNums[n]) {
|
||||
seenNums[n] = true;
|
||||
if (self.apool.getAttribKey(n) == 'author') {
|
||||
const a = self.apool.getAttribValue(n);
|
||||
if (this.apool.getAttribKey(n) === 'author') {
|
||||
const a = this.apool.getAttribValue(n);
|
||||
if (a) {
|
||||
authors.push(a);
|
||||
}
|
||||
|
@ -164,42 +135,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
},
|
||||
};
|
||||
|
||||
function callCatchingErrors(catcher, func) {
|
||||
try {
|
||||
wrapRecordingErrors(catcher, func)();
|
||||
} catch (e) { /* absorb*/
|
||||
}
|
||||
}
|
||||
|
||||
function wrapRecordingErrors(catcher, func) {
|
||||
return function () {
|
||||
try {
|
||||
return func.apply(this, Array.prototype.slice.call(arguments));
|
||||
} catch (e) {
|
||||
// caughtErrors.push(e);
|
||||
// caughtErrorCatchers.push(catcher);
|
||||
// caughtErrorTimes.push(+new Date());
|
||||
// console.dir({catcher: catcher, e: e});
|
||||
debugLog(e); // TODO(kroo): added temporary, to catch errors
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function loadedNewChangeset(changesetForward, changesetBackward, revision, timeDelta) {
|
||||
const broadcasting = (BroadcastSlider.getSliderPosition() == revisionInfo.latest);
|
||||
revisionInfo.addChangeset(revision, revision + 1, changesetForward, changesetBackward, timeDelta);
|
||||
BroadcastSlider.setSliderLength(revisionInfo.latest);
|
||||
if (broadcasting) applyChangeset(changesetForward, revision + 1, false, timeDelta);
|
||||
}
|
||||
|
||||
/*
|
||||
At this point, we must be certain that the changeset really does map from
|
||||
the current revision to the specified revision. Any mistakes here will
|
||||
cause the whole slider to get out of sync.
|
||||
*/
|
||||
|
||||
function applyChangeset(changeset, revision, preventSliderMovement, timeDelta) {
|
||||
const applyChangeset = (changeset, revision, preventSliderMovement, timeDelta) => {
|
||||
// disable the next 'gotorevision' call handled by a timeslider update
|
||||
if (!preventSliderMovement) {
|
||||
goToRevisionIfEnabledCount++;
|
||||
|
@ -215,7 +151,8 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
}
|
||||
|
||||
// scroll to the area that is changed before the lines are mutated
|
||||
if ($('#options-followContents').is(':checked') || $('#options-followContents').prop('checked')) {
|
||||
if ($('#options-followContents').is(':checked') ||
|
||||
$('#options-followContents').prop('checked')) {
|
||||
// get the index of the first line that has mutated attributes
|
||||
// the last line in `oldAlines` should always equal to "|1+1", ie newline without attributes
|
||||
// so it should be safe to assume this line has changed attributes when inserting content at
|
||||
|
@ -227,11 +164,25 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
return true; // break
|
||||
}
|
||||
});
|
||||
// deal with someone is the author of a line and changes one character, so the alines won't change
|
||||
// deal with someone is the author of a line and changes one character,
|
||||
// so the alines won't change
|
||||
if (lineChanged === undefined) {
|
||||
lineChanged = Changeset.opIterator(Changeset.unpack(changeset).ops).next().lines;
|
||||
}
|
||||
|
||||
const goToLineNumber = (lineNumber) => {
|
||||
// Sets the Y scrolling of the browser to go to this line
|
||||
const line = $('#innerdocbody').find(`div:nth-child(${lineNumber + 1})`);
|
||||
const newY = $(line)[0].offsetTop;
|
||||
const ecb = document.getElementById('editorcontainerbox');
|
||||
// Chrome 55 - 59 bugfix
|
||||
if (ecb.scrollTo) {
|
||||
ecb.scrollTo({top: newY, behavior: 'smooth'});
|
||||
} else {
|
||||
$('#editorcontainerbox').scrollTop(newY);
|
||||
}
|
||||
};
|
||||
|
||||
goToLineNumber(lineChanged);
|
||||
}
|
||||
|
||||
|
@ -244,17 +195,32 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
const authors = _.map(padContents.getActiveAuthors(), (name) => authorData[name]);
|
||||
|
||||
BroadcastSlider.setAuthors(authors);
|
||||
}
|
||||
};
|
||||
|
||||
function updateTimer() {
|
||||
const zpad = function (str, length) {
|
||||
const loadedNewChangeset = (changesetForward, changesetBackward, revision, timeDelta) => {
|
||||
const revisionInfo = window.revisionInfo;
|
||||
const broadcasting = (BroadcastSlider.getSliderPosition() === revisionInfo.latest);
|
||||
revisionInfo.addChangeset(
|
||||
revision, revision + 1, changesetForward, changesetBackward, timeDelta);
|
||||
BroadcastSlider.setSliderLength(revisionInfo.latest);
|
||||
if (broadcasting) applyChangeset(changesetForward, revision + 1, false, timeDelta);
|
||||
};
|
||||
|
||||
/*
|
||||
At this point, we must be certain that the changeset really does map from
|
||||
the current revision to the specified revision. Any mistakes here will
|
||||
cause the whole slider to get out of sync.
|
||||
*/
|
||||
|
||||
const updateTimer = () => {
|
||||
const zpad = (str, length) => {
|
||||
str = `${str}`;
|
||||
while (str.length < length) str = `0${str}`;
|
||||
return str;
|
||||
};
|
||||
|
||||
const date = new Date(padContents.currentTime);
|
||||
const dateFormat = function () {
|
||||
const dateFormat = () => {
|
||||
const month = zpad(date.getMonth() + 1, 2);
|
||||
const day = zpad(date.getDate(), 2);
|
||||
const year = (date.getFullYear());
|
||||
|
@ -292,43 +258,41 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
year: date.getFullYear(),
|
||||
});
|
||||
$('#revision_date').html(revisionDate);
|
||||
}
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
|
||||
function goToRevision(newRevision) {
|
||||
const goToRevision = (newRevision) => {
|
||||
padContents.targetRevision = newRevision;
|
||||
const self = this;
|
||||
const path = revisionInfo.getPath(padContents.currentRevision, newRevision);
|
||||
const path = window.revisionInfo.getPath(padContents.currentRevision, newRevision);
|
||||
|
||||
hooks.aCallAll('goToRevisionEvent', {
|
||||
rev: newRevision,
|
||||
});
|
||||
|
||||
if (path.status == 'complete') {
|
||||
var cs = path.changesets;
|
||||
var changeset = cs[0];
|
||||
var timeDelta = path.times[0];
|
||||
for (var i = 1; i < cs.length; i++) {
|
||||
if (path.status === 'complete') {
|
||||
const cs = path.changesets;
|
||||
let changeset = cs[0];
|
||||
let timeDelta = path.times[0];
|
||||
for (let i = 1; i < cs.length; i++) {
|
||||
changeset = Changeset.compose(changeset, cs[i], padContents.apool);
|
||||
timeDelta += path.times[i];
|
||||
}
|
||||
if (changeset) applyChangeset(changeset, path.rev, true, timeDelta);
|
||||
} else if (path.status == 'partial') {
|
||||
const sliderLocation = padContents.currentRevision;
|
||||
} else if (path.status === 'partial') {
|
||||
// callback is called after changeset information is pulled from server
|
||||
// this may never get called, if the changeset has already been loaded
|
||||
const update = function (start, end) {
|
||||
const update = (start, end) => {
|
||||
// if we've called goToRevision in the time since, don't goToRevision
|
||||
goToRevision(padContents.targetRevision);
|
||||
};
|
||||
|
||||
// do our best with what we have...
|
||||
var cs = path.changesets;
|
||||
const cs = path.changesets;
|
||||
|
||||
var changeset = cs[0];
|
||||
var timeDelta = path.times[0];
|
||||
for (var i = 1; i < cs.length; i++) {
|
||||
let changeset = cs[0];
|
||||
let timeDelta = path.times[0];
|
||||
for (let i = 1; i < cs.length; i++) {
|
||||
changeset = Changeset.compose(changeset, cs[i], padContents.apool);
|
||||
timeDelta += path.times[i];
|
||||
}
|
||||
|
@ -342,23 +306,23 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
|
||||
const authors = _.map(padContents.getActiveAuthors(), (name) => authorData[name]);
|
||||
BroadcastSlider.setAuthors(authors);
|
||||
}
|
||||
};
|
||||
|
||||
function loadChangesetsForRevision(revision, callback) {
|
||||
const loadChangesetsForRevision = (revision, callback) => {
|
||||
if (BroadcastSlider.getSliderLength() > 10000) {
|
||||
var start = (Math.floor((revision) / 10000) * 10000); // revision 0 to 10
|
||||
const start = (Math.floor((revision) / 10000) * 10000); // revision 0 to 10
|
||||
changesetLoader.queueUp(start, 100);
|
||||
}
|
||||
|
||||
if (BroadcastSlider.getSliderLength() > 1000) {
|
||||
var start = (Math.floor((revision) / 1000) * 1000); // (start from -1, go to 19) + 1
|
||||
const start = (Math.floor((revision) / 1000) * 1000); // (start from -1, go to 19) + 1
|
||||
changesetLoader.queueUp(start, 10);
|
||||
}
|
||||
|
||||
start = (Math.floor((revision) / 100) * 100);
|
||||
const start = (Math.floor((revision) / 100) * 100);
|
||||
|
||||
changesetLoader.queueUp(start, 1, callback);
|
||||
}
|
||||
};
|
||||
|
||||
changesetLoader = {
|
||||
running: false,
|
||||
|
@ -369,29 +333,38 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
reqCallbacks: [],
|
||||
queueUp(revision, width, callback) {
|
||||
if (revision < 0) revision = 0;
|
||||
// if(changesetLoader.requestQueue.indexOf(revision) != -1)
|
||||
// if(this.requestQueue.indexOf(revision) != -1)
|
||||
// return; // already in the queue.
|
||||
if (changesetLoader.resolved.indexOf(`${revision}_${width}`) != -1) return; // already loaded from the server
|
||||
changesetLoader.resolved.push(`${revision}_${width}`);
|
||||
if (this.resolved.indexOf(`${revision}_${width}`) !== -1) {
|
||||
// already loaded from the server
|
||||
return;
|
||||
}
|
||||
this.resolved.push(`${revision}_${width}`);
|
||||
|
||||
const requestQueue = width == 1 ? changesetLoader.requestQueue3 : width == 10 ? changesetLoader.requestQueue2 : changesetLoader.requestQueue1;
|
||||
const requestQueue =
|
||||
width === 1 ? this.requestQueue3
|
||||
: width === 10 ? this.requestQueue2
|
||||
: this.requestQueue1;
|
||||
requestQueue.push(
|
||||
{
|
||||
rev: revision,
|
||||
res: width,
|
||||
callback,
|
||||
});
|
||||
if (!changesetLoader.running) {
|
||||
changesetLoader.running = true;
|
||||
setTimeout(changesetLoader.loadFromQueue, 10);
|
||||
if (!this.running) {
|
||||
this.running = true;
|
||||
setTimeout(() => this.loadFromQueue(), 10);
|
||||
}
|
||||
},
|
||||
loadFromQueue() {
|
||||
const self = changesetLoader;
|
||||
const requestQueue = self.requestQueue1.length > 0 ? self.requestQueue1 : self.requestQueue2.length > 0 ? self.requestQueue2 : self.requestQueue3.length > 0 ? self.requestQueue3 : null;
|
||||
const requestQueue =
|
||||
this.requestQueue1.length > 0 ? this.requestQueue1
|
||||
: this.requestQueue2.length > 0 ? this.requestQueue2
|
||||
: this.requestQueue3.length > 0 ? this.requestQueue3
|
||||
: null;
|
||||
|
||||
if (!requestQueue) {
|
||||
self.running = false;
|
||||
this.running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -407,48 +380,48 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
requestID,
|
||||
});
|
||||
|
||||
self.reqCallbacks[requestID] = callback;
|
||||
this.reqCallbacks[requestID] = callback;
|
||||
},
|
||||
handleSocketResponse(message) {
|
||||
const self = changesetLoader;
|
||||
|
||||
const start = message.data.start;
|
||||
const granularity = message.data.granularity;
|
||||
const callback = self.reqCallbacks[message.data.requestID];
|
||||
delete self.reqCallbacks[message.data.requestID];
|
||||
const callback = this.reqCallbacks[message.data.requestID];
|
||||
delete this.reqCallbacks[message.data.requestID];
|
||||
|
||||
self.handleResponse(message.data, start, granularity, callback);
|
||||
setTimeout(self.loadFromQueue, 10);
|
||||
this.handleResponse(message.data, start, granularity, callback);
|
||||
setTimeout(() => this.loadFromQueue(), 10);
|
||||
},
|
||||
handleResponse(data, start, granularity, callback) {
|
||||
handleResponse: (data, start, granularity, callback) => {
|
||||
const pool = (new AttribPool()).fromJsonable(data.apool);
|
||||
for (let i = 0; i < data.forwardsChangesets.length; i++) {
|
||||
const astart = start + i * granularity - 1; // rev -1 is a blank single line
|
||||
let aend = start + (i + 1) * granularity - 1; // totalRevs is the most recent revision
|
||||
if (aend > data.actualEndNum - 1) aend = data.actualEndNum - 1;
|
||||
// debugLog("adding changeset:", astart, aend);
|
||||
const forwardcs = Changeset.moveOpsToNewPool(data.forwardsChangesets[i], pool, padContents.apool);
|
||||
const backwardcs = Changeset.moveOpsToNewPool(data.backwardsChangesets[i], pool, padContents.apool);
|
||||
revisionInfo.addChangeset(astart, aend, forwardcs, backwardcs, data.timeDeltas[i]);
|
||||
const forwardcs =
|
||||
Changeset.moveOpsToNewPool(data.forwardsChangesets[i], pool, padContents.apool);
|
||||
const backwardcs =
|
||||
Changeset.moveOpsToNewPool(data.backwardsChangesets[i], pool, padContents.apool);
|
||||
window.revisionInfo.addChangeset(astart, aend, forwardcs, backwardcs, data.timeDeltas[i]);
|
||||
}
|
||||
if (callback) callback(start - 1, start + data.forwardsChangesets.length * granularity - 1);
|
||||
},
|
||||
handleMessageFromServer(obj) {
|
||||
if (obj.type == 'COLLABROOM') {
|
||||
if (obj.type === 'COLLABROOM') {
|
||||
obj = obj.data;
|
||||
|
||||
if (obj.type == 'NEW_CHANGES') {
|
||||
if (obj.type === 'NEW_CHANGES') {
|
||||
const changeset = Changeset.moveOpsToNewPool(
|
||||
obj.changeset, (new AttribPool()).fromJsonable(obj.apool), padContents.apool);
|
||||
|
||||
var changesetBack = Changeset.inverse(
|
||||
let changesetBack = Changeset.inverse(
|
||||
obj.changeset, padContents.currentLines, padContents.alines, padContents.apool);
|
||||
|
||||
var changesetBack = Changeset.moveOpsToNewPool(
|
||||
changesetBack = Changeset.moveOpsToNewPool(
|
||||
changesetBack, (new AttribPool()).fromJsonable(obj.apool), padContents.apool);
|
||||
|
||||
loadedNewChangeset(changeset, changesetBack, obj.newRev - 1, obj.timeDelta);
|
||||
} else if (obj.type == 'NEW_AUTHORDATA') {
|
||||
} else if (obj.type === 'NEW_AUTHORDATA') {
|
||||
const authorMap = {};
|
||||
authorMap[obj.author] = obj.data;
|
||||
receiveAuthorData(authorMap);
|
||||
|
@ -456,13 +429,13 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
const authors = _.map(padContents.getActiveAuthors(), (name) => authorData[name]);
|
||||
|
||||
BroadcastSlider.setAuthors(authors);
|
||||
} else if (obj.type == 'NEW_SAVEDREV') {
|
||||
} else if (obj.type === 'NEW_SAVEDREV') {
|
||||
const savedRev = obj.savedRev;
|
||||
BroadcastSlider.addSavedRevision(savedRev.revNum, savedRev);
|
||||
}
|
||||
hooks.callAll(`handleClientTimesliderMessage_${obj.type}`, {payload: obj});
|
||||
} else if (obj.type == 'CHANGESET_REQ') {
|
||||
changesetLoader.handleSocketResponse(obj);
|
||||
} else if (obj.type === 'CHANGESET_REQ') {
|
||||
this.handleSocketResponse(obj);
|
||||
} else {
|
||||
debugLog(`Unknown message type: ${obj.type}`);
|
||||
}
|
||||
|
@ -485,49 +458,36 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
|||
|
||||
// this is necessary to keep infinite loops of events firing,
|
||||
// since goToRevision changes the slider position
|
||||
var goToRevisionIfEnabledCount = 0;
|
||||
const goToRevisionIfEnabled = function () {
|
||||
const goToRevisionIfEnabled = (...args) => {
|
||||
if (goToRevisionIfEnabledCount > 0) {
|
||||
goToRevisionIfEnabledCount--;
|
||||
} else {
|
||||
goToRevision.apply(goToRevision, arguments);
|
||||
goToRevision(...args);
|
||||
}
|
||||
};
|
||||
|
||||
BroadcastSlider.onSlider(goToRevisionIfEnabled);
|
||||
|
||||
const dynamicCSS = makeCSSManager('dynamicsyntax');
|
||||
var authorData = {};
|
||||
const authorData = {};
|
||||
|
||||
function receiveAuthorData(newAuthorData) {
|
||||
for (const author in newAuthorData) {
|
||||
const data = newAuthorData[author];
|
||||
const bgcolor = typeof data.colorId === 'number' ? clientVars.colorPalette[data.colorId] : data.colorId;
|
||||
const receiveAuthorData = (newAuthorData) => {
|
||||
for (const [author, data] of Object.entries(newAuthorData)) {
|
||||
const bgcolor = typeof data.colorId === 'number'
|
||||
? clientVars.colorPalette[data.colorId] : data.colorId;
|
||||
if (bgcolor && dynamicCSS) {
|
||||
const selector = dynamicCSS.selectorStyle(`.${linestylefilter.getAuthorClassName(author)}`);
|
||||
selector.backgroundColor = bgcolor;
|
||||
selector.color = (colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5) ? '#ffffff' : '#000000'; // see ace2_inner.js for the other part
|
||||
selector.color = (colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5)
|
||||
? '#ffffff' : '#000000'; // see ace2_inner.js for the other part
|
||||
}
|
||||
authorData[author] = data;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
receiveAuthorData(clientVars.collab_client_vars.historicalAuthorData);
|
||||
|
||||
return changesetLoader;
|
||||
|
||||
function goToLineNumber(lineNumber) {
|
||||
// Sets the Y scrolling of the browser to go to this line
|
||||
const line = $('#innerdocbody').find(`div:nth-child(${lineNumber + 1})`);
|
||||
const newY = $(line)[0].offsetTop;
|
||||
const ecb = document.getElementById('editorcontainerbox');
|
||||
// Chrome 55 - 59 bugfix
|
||||
if (ecb.scrollTo) {
|
||||
ecb.scrollTo({top: newY, behavior: 'smooth'});
|
||||
} else {
|
||||
$('#editorcontainerbox').scrollTop(newY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.loadBroadcastJS = loadBroadcastJS;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
|
@ -23,7 +25,7 @@
|
|||
// of the document. These revisions are connected together by various
|
||||
// changesets, or deltas, between any two revisions.
|
||||
|
||||
function loadBroadcastRevisionsJS() {
|
||||
const loadBroadcastRevisionsJS = () => {
|
||||
function Revision(revNum) {
|
||||
this.rev = revNum;
|
||||
this.changesets = [];
|
||||
|
@ -33,18 +35,16 @@ function loadBroadcastRevisionsJS() {
|
|||
const changesetWrapper = {
|
||||
deltaRev: destIndex - this.rev,
|
||||
deltaTime: timeDelta,
|
||||
getValue() {
|
||||
return changeset;
|
||||
},
|
||||
getValue: () => changeset,
|
||||
};
|
||||
this.changesets.push(changesetWrapper);
|
||||
this.changesets.sort((a, b) => (b.deltaRev - a.deltaRev));
|
||||
};
|
||||
|
||||
revisionInfo = {};
|
||||
const revisionInfo = {};
|
||||
revisionInfo.addChangeset = function (fromIndex, toIndex, changeset, backChangeset, timeDelta) {
|
||||
const startRevision = revisionInfo[fromIndex] || revisionInfo.createNew(fromIndex);
|
||||
const endRevision = revisionInfo[toIndex] || revisionInfo.createNew(toIndex);
|
||||
const startRevision = this[fromIndex] || this.createNew(fromIndex);
|
||||
const endRevision = this[toIndex] || this.createNew(toIndex);
|
||||
startRevision.addChangeset(toIndex, changeset, timeDelta);
|
||||
endRevision.addChangeset(fromIndex, backChangeset, -1 * timeDelta);
|
||||
};
|
||||
|
@ -52,12 +52,12 @@ function loadBroadcastRevisionsJS() {
|
|||
revisionInfo.latest = clientVars.collab_client_vars.rev || -1;
|
||||
|
||||
revisionInfo.createNew = function (index) {
|
||||
revisionInfo[index] = new Revision(index);
|
||||
if (index > revisionInfo.latest) {
|
||||
revisionInfo.latest = index;
|
||||
this[index] = new Revision(index);
|
||||
if (index > this.latest) {
|
||||
this.latest = index;
|
||||
}
|
||||
|
||||
return revisionInfo[index];
|
||||
return this[index];
|
||||
};
|
||||
|
||||
// assuming that there is a path from fromIndex to toIndex, and that the links
|
||||
|
@ -66,8 +66,8 @@ function loadBroadcastRevisionsJS() {
|
|||
const changesets = [];
|
||||
const spans = [];
|
||||
const times = [];
|
||||
let elem = revisionInfo[fromIndex] || revisionInfo.createNew(fromIndex);
|
||||
if (elem.changesets.length != 0 && fromIndex != toIndex) {
|
||||
let elem = this[fromIndex] || this.createNew(fromIndex);
|
||||
if (elem.changesets.length !== 0 && fromIndex !== toIndex) {
|
||||
const reverse = !(fromIndex < toIndex);
|
||||
while (((elem.rev < toIndex) && !reverse) || ((elem.rev > toIndex) && reverse)) {
|
||||
let couldNotContinue = false;
|
||||
|
@ -76,27 +76,29 @@ function loadBroadcastRevisionsJS() {
|
|||
for (let i = reverse ? elem.changesets.length - 1 : 0;
|
||||
reverse ? i >= 0 : i < elem.changesets.length;
|
||||
i += reverse ? -1 : 1) {
|
||||
if (((elem.changesets[i].deltaRev < 0) && !reverse) || ((elem.changesets[i].deltaRev > 0) && reverse)) {
|
||||
if (((elem.changesets[i].deltaRev < 0) && !reverse) ||
|
||||
((elem.changesets[i].deltaRev > 0) && reverse)) {
|
||||
couldNotContinue = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (((elem.rev + elem.changesets[i].deltaRev <= toIndex) && !reverse) || ((elem.rev + elem.changesets[i].deltaRev >= toIndex) && reverse)) {
|
||||
if (((elem.rev + elem.changesets[i].deltaRev <= toIndex) && !reverse) ||
|
||||
((elem.rev + elem.changesets[i].deltaRev >= toIndex) && reverse)) {
|
||||
const topush = elem.changesets[i];
|
||||
changesets.push(topush.getValue());
|
||||
spans.push(elem.changesets[i].deltaRev);
|
||||
times.push(topush.deltaTime);
|
||||
elem = revisionInfo[elem.rev + elem.changesets[i].deltaRev];
|
||||
elem = this[elem.rev + elem.changesets[i].deltaRev];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (couldNotContinue || oldRev == elem.rev) break;
|
||||
if (couldNotContinue || oldRev === elem.rev) break;
|
||||
}
|
||||
}
|
||||
|
||||
let status = 'partial';
|
||||
if (elem.rev == toIndex) status = 'complete';
|
||||
if (elem.rev === toIndex) status = 'complete';
|
||||
|
||||
return {
|
||||
fromRev: fromIndex,
|
||||
|
@ -107,6 +109,7 @@ function loadBroadcastRevisionsJS() {
|
|||
times,
|
||||
};
|
||||
};
|
||||
}
|
||||
window.revisionInfo = revisionInfo;
|
||||
};
|
||||
|
||||
exports.loadBroadcastRevisionsJS = loadBroadcastRevisionsJS;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
'use strict';
|
||||
/**
|
||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||
* This helps other people to understand this code better and helps them to improve it.
|
||||
|
@ -26,13 +27,14 @@ const _ = require('./underscore');
|
|||
const padmodals = require('./pad_modals').padmodals;
|
||||
const colorutils = require('./colorutils').colorutils;
|
||||
|
||||
function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
||||
const loadBroadcastSliderJS = (fireWhenAllScriptsAreLoaded) => {
|
||||
let BroadcastSlider;
|
||||
|
||||
// Hack to ensure timeslider i18n values are in
|
||||
$("[data-key='timeslider_returnToPad'] > a > span").html(html10n.get('timeslider.toolbar.returnbutton'));
|
||||
$("[data-key='timeslider_returnToPad'] > a > span").html(
|
||||
html10n.get('timeslider.toolbar.returnbutton'));
|
||||
|
||||
(function () { // wrap this code in its own namespace
|
||||
(() => { // wrap this code in its own namespace
|
||||
let sliderLength = 1000;
|
||||
let sliderPos = 0;
|
||||
let sliderActive = false;
|
||||
|
@ -40,27 +42,30 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
const savedRevisions = [];
|
||||
let sliderPlaying = false;
|
||||
|
||||
const _callSliderCallbacks = function (newval) {
|
||||
const _callSliderCallbacks = (newval) => {
|
||||
sliderPos = newval;
|
||||
for (let i = 0; i < slidercallbacks.length; i++) {
|
||||
slidercallbacks[i](newval);
|
||||
}
|
||||
};
|
||||
|
||||
const updateSliderElements = function () {
|
||||
const updateSliderElements = () => {
|
||||
for (let i = 0; i < savedRevisions.length; i++) {
|
||||
const position = parseInt(savedRevisions[i].attr('pos'));
|
||||
savedRevisions[i].css('left', (position * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0)) - 1);
|
||||
savedRevisions[i].css(
|
||||
'left', (position * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0)) - 1);
|
||||
}
|
||||
$('#ui-slider-handle').css('left', sliderPos * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0));
|
||||
$('#ui-slider-handle').css(
|
||||
'left', sliderPos * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0));
|
||||
};
|
||||
|
||||
const addSavedRevision = function (position, info) {
|
||||
const addSavedRevision = (position, info) => {
|
||||
const newSavedRevision = $('<div></div>');
|
||||
newSavedRevision.addClass('star');
|
||||
|
||||
newSavedRevision.attr('pos', position);
|
||||
newSavedRevision.css('left', (position * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0)) - 1);
|
||||
newSavedRevision.css(
|
||||
'left', (position * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0)) - 1);
|
||||
$('#ui-slider-bar').append(newSavedRevision);
|
||||
newSavedRevision.mouseup((evt) => {
|
||||
BroadcastSlider.setSliderPosition(position);
|
||||
|
@ -68,60 +73,50 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
savedRevisions.push(newSavedRevision);
|
||||
};
|
||||
|
||||
const removeSavedRevision = function (position) {
|
||||
const element = $(`div.star [pos=${position}]`);
|
||||
savedRevisions.remove(element);
|
||||
element.remove();
|
||||
return element;
|
||||
};
|
||||
|
||||
/* Begin small 'API' */
|
||||
|
||||
function onSlider(callback) {
|
||||
const onSlider = (callback) => {
|
||||
slidercallbacks.push(callback);
|
||||
}
|
||||
};
|
||||
|
||||
function getSliderPosition() {
|
||||
return sliderPos;
|
||||
}
|
||||
const getSliderPosition = () => sliderPos;
|
||||
|
||||
function setSliderPosition(newpos) {
|
||||
const setSliderPosition = (newpos) => {
|
||||
newpos = Number(newpos);
|
||||
if (newpos < 0 || newpos > sliderLength) return;
|
||||
if (!newpos) {
|
||||
newpos = 0; // stops it from displaying NaN if newpos isn't set
|
||||
}
|
||||
window.location.hash = `#${newpos}`;
|
||||
$('#ui-slider-handle').css('left', newpos * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0));
|
||||
$('#ui-slider-handle').css(
|
||||
'left', newpos * ($('#ui-slider-bar').width() - 2) / (sliderLength * 1.0));
|
||||
$('a.tlink').map(function () {
|
||||
$(this).attr('href', $(this).attr('thref').replace('%revision%', newpos));
|
||||
});
|
||||
|
||||
$('#revision_label').html(html10n.get('timeslider.version', {version: newpos}));
|
||||
|
||||
$('#leftstar, #leftstep').toggleClass('disabled', newpos == 0);
|
||||
$('#rightstar, #rightstep').toggleClass('disabled', newpos == sliderLength);
|
||||
$('#leftstar, #leftstep').toggleClass('disabled', newpos === 0);
|
||||
$('#rightstar, #rightstep').toggleClass('disabled', newpos === sliderLength);
|
||||
|
||||
sliderPos = newpos;
|
||||
_callSliderCallbacks(newpos);
|
||||
}
|
||||
};
|
||||
|
||||
function getSliderLength() {
|
||||
return sliderLength;
|
||||
}
|
||||
const getSliderLength = () => sliderLength;
|
||||
|
||||
function setSliderLength(newlength) {
|
||||
const setSliderLength = (newlength) => {
|
||||
sliderLength = newlength;
|
||||
updateSliderElements();
|
||||
}
|
||||
};
|
||||
|
||||
// just take over the whole slider screen with a reconnect message
|
||||
|
||||
function showReconnectUI() {
|
||||
const showReconnectUI = () => {
|
||||
padmodals.showModal('disconnected');
|
||||
}
|
||||
};
|
||||
|
||||
function setAuthors(authors) {
|
||||
const setAuthors = (authors) => {
|
||||
const authorsList = $('#authorsList');
|
||||
authorsList.empty();
|
||||
let numAnonymous = 0;
|
||||
|
@ -132,7 +127,8 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
const authorColor = clientVars.colorPalette[author.colorId] || author.colorId;
|
||||
if (author.name) {
|
||||
if (numNamed !== 0) authorsList.append(', ');
|
||||
const textColor = colorutils.textColorFromBackgroundColor(authorColor, clientVars.skinName);
|
||||
const textColor =
|
||||
colorutils.textColorFromBackgroundColor(authorColor, clientVars.skinName);
|
||||
$('<span />')
|
||||
.text(author.name || 'unnamed')
|
||||
.css('background-color', authorColor)
|
||||
|
@ -168,27 +164,12 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
authorsList.append(')');
|
||||
}
|
||||
}
|
||||
if (authors.length == 0) {
|
||||
if (authors.length === 0) {
|
||||
authorsList.append(html10n.get('timeslider.toolbar.authorsList'));
|
||||
}
|
||||
}
|
||||
|
||||
BroadcastSlider = {
|
||||
onSlider,
|
||||
getSliderPosition,
|
||||
setSliderPosition,
|
||||
getSliderLength,
|
||||
setSliderLength,
|
||||
isSliderActive() {
|
||||
return sliderActive;
|
||||
},
|
||||
playpause,
|
||||
addSavedRevision,
|
||||
showReconnectUI,
|
||||
setAuthors,
|
||||
};
|
||||
|
||||
function playButtonUpdater() {
|
||||
const playButtonUpdater = () => {
|
||||
if (sliderPlaying) {
|
||||
if (getSliderPosition() + 1 > sliderLength) {
|
||||
$('#playpause_button_icon').toggleClass('pause');
|
||||
|
@ -199,39 +180,52 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
|
||||
setTimeout(playButtonUpdater, 100);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function playpause() {
|
||||
const playpause = () => {
|
||||
$('#playpause_button_icon').toggleClass('pause');
|
||||
|
||||
if (!sliderPlaying) {
|
||||
if (getSliderPosition() == sliderLength) setSliderPosition(0);
|
||||
if (getSliderPosition() === sliderLength) setSliderPosition(0);
|
||||
sliderPlaying = true;
|
||||
playButtonUpdater();
|
||||
} else {
|
||||
sliderPlaying = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BroadcastSlider = {
|
||||
onSlider,
|
||||
getSliderPosition,
|
||||
setSliderPosition,
|
||||
getSliderLength,
|
||||
setSliderLength,
|
||||
isSliderActive: () => sliderActive,
|
||||
playpause,
|
||||
addSavedRevision,
|
||||
showReconnectUI,
|
||||
setAuthors,
|
||||
};
|
||||
|
||||
// assign event handlers to html UI elements after page load
|
||||
fireWhenAllScriptsAreLoaded.push(() => {
|
||||
$(document).keyup((e) => {
|
||||
if (!e) var e = window.event;
|
||||
if (!e) e = window.event;
|
||||
const code = e.keyCode || e.which;
|
||||
|
||||
if (code == 37) { // left
|
||||
if (code === 37) { // left
|
||||
if (e.shiftKey) {
|
||||
$('#leftstar').click();
|
||||
} else {
|
||||
$('#leftstep').click();
|
||||
}
|
||||
} else if (code == 39) { // right
|
||||
} else if (code === 39) { // right
|
||||
if (e.shiftKey) {
|
||||
$('#rightstar').click();
|
||||
} else {
|
||||
$('#rightstep').click();
|
||||
}
|
||||
} else if (code == 32) { // spacebar
|
||||
} else if (code === 32) { // spacebar
|
||||
$('#playpause_button_icon').trigger('click');
|
||||
}
|
||||
});
|
||||
|
@ -251,31 +245,32 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
$('#ui-slider-handle').mousedown(function (evt) {
|
||||
this.startLoc = evt.clientX;
|
||||
this.currentLoc = parseInt($(this).css('left'));
|
||||
const self = this;
|
||||
sliderActive = true;
|
||||
$(document).mousemove((evt2) => {
|
||||
$(self).css('pointer', 'move');
|
||||
let newloc = self.currentLoc + (evt2.clientX - self.startLoc);
|
||||
$(this).css('pointer', 'move');
|
||||
let newloc = this.currentLoc + (evt2.clientX - this.startLoc);
|
||||
if (newloc < 0) newloc = 0;
|
||||
if (newloc > ($('#ui-slider-bar').width() - 2)) newloc = ($('#ui-slider-bar').width() - 2);
|
||||
$('#revision_label').html(html10n.get('timeslider.version', {version: Math.floor(newloc * sliderLength / ($('#ui-slider-bar').width() - 2))}));
|
||||
$(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)));
|
||||
const maxPos = $('#ui-slider-bar').width() - 2;
|
||||
if (newloc > maxPos) newloc = maxPos;
|
||||
const version = Math.floor(newloc * sliderLength / maxPos);
|
||||
$('#revision_label').html(html10n.get('timeslider.version', {version}));
|
||||
$(this).css('left', newloc);
|
||||
if (getSliderPosition() !== version) _callSliderCallbacks(version);
|
||||
});
|
||||
$(document).mouseup((evt2) => {
|
||||
$(document).unbind('mousemove');
|
||||
$(document).unbind('mouseup');
|
||||
sliderActive = false;
|
||||
let newloc = self.currentLoc + (evt2.clientX - self.startLoc);
|
||||
let newloc = this.currentLoc + (evt2.clientX - this.startLoc);
|
||||
if (newloc < 0) newloc = 0;
|
||||
if (newloc > ($('#ui-slider-bar').width() - 2)) newloc = ($('#ui-slider-bar').width() - 2);
|
||||
$(self).css('left', newloc);
|
||||
// if(getSliderPosition() != Math.floor(newloc * sliderLength / ($("#ui-slider-bar").width()-2)))
|
||||
setSliderPosition(Math.floor(newloc * sliderLength / ($('#ui-slider-bar').width() - 2)));
|
||||
if (parseInt($(self).css('left')) < 2) {
|
||||
$(self).css('left', '2px');
|
||||
const maxPos = $('#ui-slider-bar').width() - 2;
|
||||
if (newloc > maxPos) newloc = maxPos;
|
||||
$(this).css('left', newloc);
|
||||
setSliderPosition(Math.floor(newloc * sliderLength / maxPos));
|
||||
if (parseInt($(this).css('left')) < 2) {
|
||||
$(this).css('left', '2px');
|
||||
} else {
|
||||
self.currentLoc = parseInt($(self).css('left'));
|
||||
this.currentLoc = parseInt($(this).css('left'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -294,29 +289,30 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
case 'rightstep':
|
||||
setSliderPosition(getSliderPosition() + 1);
|
||||
break;
|
||||
case 'leftstar':
|
||||
var nextStar = 0; // default to first revision in document
|
||||
for (var i = 0; i < savedRevisions.length; i++) {
|
||||
var pos = parseInt(savedRevisions[i].attr('pos'));
|
||||
case 'leftstar': {
|
||||
let nextStar = 0; // default to first revision in document
|
||||
for (let i = 0; i < savedRevisions.length; i++) {
|
||||
const pos = parseInt(savedRevisions[i].attr('pos'));
|
||||
if (pos < getSliderPosition() && nextStar < pos) nextStar = pos;
|
||||
}
|
||||
setSliderPosition(nextStar);
|
||||
break;
|
||||
case 'rightstar':
|
||||
var nextStar = sliderLength; // default to last revision in document
|
||||
for (var i = 0; i < savedRevisions.length; i++) {
|
||||
var pos = parseInt(savedRevisions[i].attr('pos'));
|
||||
}
|
||||
case 'rightstar': {
|
||||
let nextStar = sliderLength; // default to last revision in document
|
||||
for (let i = 0; i < savedRevisions.length; i++) {
|
||||
const pos = parseInt(savedRevisions[i].attr('pos'));
|
||||
if (pos > getSliderPosition() && nextStar > pos) nextStar = pos;
|
||||
}
|
||||
setSliderPosition(nextStar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (clientVars) {
|
||||
$('#timeslider-wrapper').show();
|
||||
|
||||
const startPos = clientVars.collab_client_vars.rev;
|
||||
if (window.location.hash.length > 1) {
|
||||
const hashRev = Number(window.location.hash.substr(1));
|
||||
if (!isNaN(hashRev)) {
|
||||
|
@ -336,10 +332,11 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) {
|
|||
})();
|
||||
|
||||
BroadcastSlider.onSlider((loc) => {
|
||||
$('#viewlatest').html(loc == BroadcastSlider.getSliderLength() ? 'Viewing latest content' : 'View latest content');
|
||||
$('#viewlatest').html(
|
||||
`${loc === BroadcastSlider.getSliderLength() ? 'Viewing' : 'View'} latest content`);
|
||||
});
|
||||
|
||||
return BroadcastSlider;
|
||||
}
|
||||
};
|
||||
|
||||
exports.loadBroadcastSliderJS = loadBroadcastSliderJS;
|
||||
|
|
Loading…
Reference in New Issue