mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
pad userlist: Use jQuery to create rows
This makes the code easier to read and maintain, and it reduces the likelihood of introducing an XSS vulnerability.
This commit is contained in:
parent
53ac25e9eb
commit
53bc80e381
1 changed files with 50 additions and 23 deletions
|
@ -67,44 +67,69 @@ const paduserlist = (function () {
|
||||||
// we do lots of manipulation of table rows and stuff that JQuery makes ok, despite
|
// we do lots of manipulation of table rows and stuff that JQuery makes ok, despite
|
||||||
// IE's poor handling when manipulating the DOM directly.
|
// IE's poor handling when manipulating the DOM directly.
|
||||||
|
|
||||||
function getEmptyRowHtml(height) {
|
const createEmptyRowTds = (height) => $('<td>')
|
||||||
return `<td colspan="${NUMCOLS}" style="border:0;height:${height}px"><!-- --></td>`;
|
.attr('colspan', NUMCOLS)
|
||||||
}
|
.css('border', 0)
|
||||||
|
.css('height', `${height}px`);
|
||||||
|
|
||||||
function isNameEditable(data) {
|
function isNameEditable(data) {
|
||||||
return (!data.name) && (data.status != 'Disconnected');
|
return (!data.name) && (data.status != 'Disconnected');
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceUserRowContents(tr, height, data) {
|
function replaceUserRowContents(tr, height, data) {
|
||||||
const tds = getUserRowHtml(height, data).match(/<td.*?<\/td>/gi);
|
const tds = createUserRowTds(height, data);
|
||||||
if (isNameEditable(data) && tr.find('td.usertdname input:enabled').length > 0) {
|
if (isNameEditable(data) && tr.find('td.usertdname input:enabled').length > 0) {
|
||||||
// preserve input field node
|
// preserve input field node
|
||||||
for (let i = 0; i < tds.length; i++) {
|
tds.each((i, td) => {
|
||||||
const oldTd = $(tr.find('td').get(i));
|
const oldTd = $(tr.find('td').get(i));
|
||||||
if (!oldTd.hasClass('usertdname')) {
|
if (!oldTd.hasClass('usertdname')) {
|
||||||
oldTd.replaceWith(tds[i]);
|
oldTd.replaceWith(td);
|
||||||
|
} else {
|
||||||
|
// Prevent leak. I'm not 100% confident that this is necessary, but it shouldn't hurt.
|
||||||
|
$(td).remove();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
} else {
|
} else {
|
||||||
tr.html(tds.join(''));
|
tr.empty().append(tds);
|
||||||
}
|
}
|
||||||
return tr;
|
return tr;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserRowHtml(height, data) {
|
const createUserRowTds = (height, data) => {
|
||||||
let nameHtml;
|
let name;
|
||||||
if (data.name) {
|
if (data.name) {
|
||||||
nameHtml = padutils.escapeHtml(data.name);
|
name = document.createTextNode(data.name);
|
||||||
} else {
|
} else {
|
||||||
nameHtml = `<input data-l10n-id="pad.userlist.unnamed" type="text" class="editempty newinput" value="${_('pad.userlist.unnamed')}" ${isNameEditable(data) ? '' : 'disabled="disabled" '}/>`;
|
name = $('<input>')
|
||||||
|
.attr('data-l10n-id', 'pad.userlist.unnamed')
|
||||||
|
.attr('type', 'text')
|
||||||
|
.addClass('editempty')
|
||||||
|
.addClass('newinput')
|
||||||
|
.attr('value', _('pad.userlist.unnamed'));
|
||||||
|
if (isNameEditable(data)) name.attr('disabled', 'disabled');
|
||||||
}
|
}
|
||||||
|
return $()
|
||||||
|
.add($('<td>')
|
||||||
|
.css('height', `${height}px`)
|
||||||
|
.addClass('usertdswatch')
|
||||||
|
.append($('<div>')
|
||||||
|
.addClass('swatch')
|
||||||
|
.css('background', padutils.escapeHtml(data.color))
|
||||||
|
.html(' ')))
|
||||||
|
.add($('<td>')
|
||||||
|
.css('height', `${height}px`)
|
||||||
|
.addClass('usertdname')
|
||||||
|
.append(name))
|
||||||
|
.add($('<td>')
|
||||||
|
.css('height', `${height}px`)
|
||||||
|
.addClass('activity')
|
||||||
|
.text(data.activity));
|
||||||
|
};
|
||||||
|
|
||||||
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('');
|
const createRow = (id, contents, authorId) => $('<tr>')
|
||||||
}
|
.attr('data-authorId', authorId)
|
||||||
|
.attr('id', id)
|
||||||
function getRowHtml(id, innerHtml, authorId) {
|
.append(contents);
|
||||||
return `<tr data-authorId="${authorId}" id="${id}">${innerHtml}</tr>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rowNode(row) {
|
function rowNode(row) {
|
||||||
return $(`#${row.domId}`);
|
return $(`#${row.domId}`);
|
||||||
|
@ -164,11 +189,11 @@ const paduserlist = (function () {
|
||||||
rowsPresent.splice(position, 0, row);
|
rowsPresent.splice(position, 0, row);
|
||||||
let tr;
|
let tr;
|
||||||
if (animationPower == 0) {
|
if (animationPower == 0) {
|
||||||
tr = $(getRowHtml(domId, getUserRowHtml(getAnimationHeight(0), data), authorId));
|
tr = createRow(domId, createUserRowTds(getAnimationHeight(0), data), authorId);
|
||||||
row.animationStep = 0;
|
row.animationStep = 0;
|
||||||
} else {
|
} else {
|
||||||
rowsFadingIn.push(row);
|
rowsFadingIn.push(row);
|
||||||
tr = $(getRowHtml(domId, getEmptyRowHtml(getAnimationHeight(ANIMATION_START)), authorId));
|
tr = createRow(domId, createEmptyRowTds(getAnimationHeight(ANIMATION_START)), authorId);
|
||||||
}
|
}
|
||||||
handleRowNode(tr, data);
|
handleRowNode(tr, data);
|
||||||
$('table#otheruserstable').show();
|
$('table#otheruserstable').show();
|
||||||
|
@ -245,13 +270,15 @@ const paduserlist = (function () {
|
||||||
if (step <= -OPACITY_STEPS) {
|
if (step <= -OPACITY_STEPS) {
|
||||||
node.find('td').height(animHeight);
|
node.find('td').height(animHeight);
|
||||||
} else if (step == -OPACITY_STEPS + 1) {
|
} else if (step == -OPACITY_STEPS + 1) {
|
||||||
node.html(getUserRowHtml(animHeight, row.data)).find('td').css('opacity', baseOpacity * 1 / OPACITY_STEPS);
|
node.empty().append(createUserRowTds(animHeight, row.data))
|
||||||
|
.find('td').css('opacity', baseOpacity * 1 / OPACITY_STEPS);
|
||||||
handleRowNode(node, row.data);
|
handleRowNode(node, row.data);
|
||||||
} else if (step < 0) {
|
} else if (step < 0) {
|
||||||
node.find('td').css('opacity', baseOpacity * (OPACITY_STEPS - (-step)) / OPACITY_STEPS).height(animHeight);
|
node.find('td').css('opacity', baseOpacity * (OPACITY_STEPS - (-step)) / OPACITY_STEPS).height(animHeight);
|
||||||
} else if (step == 0) {
|
} else if (step == 0) {
|
||||||
// set HTML in case modified during animation
|
// set HTML in case modified during animation
|
||||||
node.html(getUserRowHtml(animHeight, row.data)).find('td').css('opacity', baseOpacity * 1).height(animHeight);
|
node.empty().append(createUserRowTds(animHeight, row.data))
|
||||||
|
.find('td').css('opacity', baseOpacity * 1).height(animHeight);
|
||||||
handleRowNode(node, row.data);
|
handleRowNode(node, row.data);
|
||||||
rowsFadingIn.splice(i, 1); // remove from set
|
rowsFadingIn.splice(i, 1); // remove from set
|
||||||
}
|
}
|
||||||
|
@ -265,7 +292,7 @@ const paduserlist = (function () {
|
||||||
if (step < OPACITY_STEPS) {
|
if (step < OPACITY_STEPS) {
|
||||||
node.find('td').css('opacity', baseOpacity * (OPACITY_STEPS - step) / OPACITY_STEPS).height(animHeight);
|
node.find('td').css('opacity', baseOpacity * (OPACITY_STEPS - step) / OPACITY_STEPS).height(animHeight);
|
||||||
} else if (step == OPACITY_STEPS) {
|
} else if (step == OPACITY_STEPS) {
|
||||||
node.html(getEmptyRowHtml(animHeight));
|
node.empty().append(createEmptyRowTds(animHeight));
|
||||||
} else if (step <= ANIMATION_END) {
|
} else if (step <= ANIMATION_END) {
|
||||||
node.find('td').height(animHeight);
|
node.find('td').height(animHeight);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue