(trunk web) #4979 "CSS Issues in Web Client" -- proposed fix. See ticket for more details.

This commit is contained in:
Jordan Lee
2012-07-20 17:37:50 +00:00
parent 6a3c7f34ec
commit 4a344d0656
5 changed files with 53 additions and 39 deletions

View File

@@ -79,9 +79,7 @@ $(document).ready(function() {
});
/**
* "innerHTML = html" is pretty slow in FF. Happily a lot of our innerHTML
* changes are triggered by periodic refreshes on torrents whose state hasn't
* changed since the last update, so even this simple test helps a lot.
* Checks to see if the content actually changed before poking the DOM.
*/
function setInnerHTML(e, html)
{
@@ -98,6 +96,22 @@ function setInnerHTML(e, html)
}
};
function sanitizeText(text)
{
return text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
};
/**
* Many of our text changes are triggered by periodic refreshes
* on torrents whose state hasn't changed since the last update,
* so see if the text actually changed before poking the DOM.
*/
function setTextContent(e, text)
{
if (e && (e.textContent != text))
e.textContent = text;
};
/*
* Given a numerator and denominator, return a ratio string
*/

View File

@@ -76,10 +76,10 @@ Dialog.prototype = {
{
if (!isMobileDevice)
$('.dialog_container').hide();
setInnerHTML(this._heading[0], dialog_heading);
setInnerHTML(this._message[0], dialog_message);
setInnerHTML(this._cancel_button[0], cancel_button_label || 'Cancel');
setInnerHTML(this._confirm_button[0], confirm_button_label);
setTextContent(this._heading[0], dialog_heading);
setTextContent(this._message[0], dialog_message);
setTextContent(this._cancel_button[0], cancel_button_label || 'Cancel');
setTextContent(this._confirm_button[0], confirm_button_label);
this._confirm_button.show();
this._callback_function = callback_function;
this._callback_data = callback_data;
@@ -96,11 +96,11 @@ Dialog.prototype = {
alert: function(dialog_heading, dialog_message, cancel_button_label) {
if (!isMobileDevice)
$('.dialog_container').hide();
setInnerHTML(this._heading[0], dialog_heading);
setInnerHTML(this._message[0], dialog_message);
setTextContent(this._heading[0], dialog_heading);
setTextContent(this._message[0], dialog_message);
// jquery::hide() doesn't work here in Safari for some odd reason
this._confirm_button.css('display', 'none');
setInnerHTML(this._cancel_button[0], cancel_button_label);
setTextContent(this._cancel_button[0], cancel_button_label);
// Just in case
$('#upload_container').hide();
$('body').addClass('dialog_showing');

View File

@@ -73,7 +73,7 @@ function FileRow(torrent, i)
' (',
Transmission.fmt.percentString(pct),
'%)' ].join('');
setInnerHTML(elements.progress, c);
setTextContent(elements.progress, c);
},
refreshHTML = function() {
if (fields.isDirty) {
@@ -140,7 +140,7 @@ function FileRow(torrent, i)
name = name.replace(/([\/_\.])/g, "$1&#8203;");
e = document.createElement('div');
e.className = "inspector_torrent_file_list_entry_name";
e.innerHTML = name;
setTextContent(e, name);
root.appendChild(e);
e = document.createElement('div');

View File

@@ -65,7 +65,7 @@ function Inspector(controller) {
name = torrents[0].getName();
else
name = '' + torrents.length+' Transfers Selected';
setInnerHTML(e.name_lb, name || na);
setTextContent(e.name_lb, name || na);
// update the visible page
if ($(e.info_page).is(':visible'))
@@ -146,7 +146,7 @@ function Inspector(controller) {
else
str = torrents[0].getStateString();
}
setInnerHTML(e.state_lb, str);
setTextContent(e.state_lb, str);
stateString = str;
//
@@ -180,7 +180,7 @@ function Inspector(controller) {
else
str = fmt.size(haveVerified) + ' of ' + fmt.size(sizeWhenDone) + ' (' + str +'%), ' + fmt.size(haveUnverified) + ' Unverified';
}
setInnerHTML(e.have_lb, str);
setTextContent(e.have_lb, str);
//
// availability_lb
@@ -192,7 +192,7 @@ function Inspector(controller) {
str = none;
else
str = '' + fmt.percentString( ( 100.0 * available ) / sizeWhenDone ) + '%';
setInnerHTML(e.availability_lb, str);
setTextContent(e.availability_lb, str);
//
// downloaded_lb
@@ -211,7 +211,7 @@ function Inspector(controller) {
else
str = fmt.size(d);
}
setInnerHTML(e.downloaded_lb, str);
setTextContent(e.downloaded_lb, str);
//
// uploaded_lb
@@ -236,7 +236,7 @@ function Inspector(controller) {
}
str = fmt.size(u) + ' (Ratio: ' + fmt.ratioString( Math.ratio(u,d))+')';
}
setInnerHTML(e.uploaded_lb, str);
setTextContent(e.uploaded_lb, str);
//
// running time
@@ -260,7 +260,7 @@ function Inspector(controller) {
else
str = fmt.timeInterval(now/1000 - baseline);
}
setInnerHTML(e.running_time_lb, str);
setTextContent(e.running_time_lb, str);
//
// remaining time
@@ -284,7 +284,7 @@ function Inspector(controller) {
else
str = fmt.timeInterval(baseline);
}
setInnerHTML(e.remaining_time_lb, str);
setTextContent(e.remaining_time_lb, str);
//
// last activity
@@ -308,7 +308,7 @@ function Inspector(controller) {
else
str = fmt.timeInterval(d) + ' ago';
}
setInnerHTML(e.last_activity_lb, str);
setTextContent(e.last_activity_lb, str);
//
// error
@@ -325,7 +325,7 @@ function Inspector(controller) {
}
}
}
setInnerHTML(e.error_lb, str || none);
setTextContent(e.error_lb, str || none);
//
// size
@@ -350,7 +350,7 @@ function Inspector(controller) {
else
str = fmt.size(size) + ' (' + pieces.toStringWithCommas() + ' pieces)';
}
setInnerHTML(e.size_lb, str);
setTextContent(e.size_lb, str);
//
// hash
@@ -367,7 +367,7 @@ function Inspector(controller) {
}
}
}
setInnerHTML(e.hash_lb, str);
setTextContent(e.hash_lb, str);
//
// privacy
@@ -385,7 +385,7 @@ function Inspector(controller) {
}
}
}
setInnerHTML(e.privacy_lb, str);
setTextContent(e.privacy_lb, str);
//
// comment
@@ -404,7 +404,7 @@ function Inspector(controller) {
}
if(!str)
str = none;
setInnerHTML(e.comment_lb, str.replace(/(https?|ftp):\/\/([\w\-]+(\.[\w\-]+)*(\.[a-z]{2,4})?)(\d{1,5})?(\/([^<>\s]*))?/g, '<a target="_blank" href="$&">$&</a>'));
setTextContent(e.comment_lb, str.replace(/(https?|ftp):\/\/([\w\-]+(\.[\w\-]+)*(\.[a-z]{2,4})?)(\d{1,5})?(\/([^<>\s]*))?/g, '<a target="_blank" href="$&">$&</a>'));
//
// origin
@@ -432,7 +432,7 @@ function Inspector(controller) {
else
str = 'Created by ' + creator + ' on ' + (new Date(date*1000)).toDateString();
}
setInnerHTML(e.origin_lb, str);
setTextContent(e.origin_lb, str);
//
// foldername
@@ -449,7 +449,7 @@ function Inspector(controller) {
}
}
}
setInnerHTML(e.foldername_lb, str);
setTextContent(e.foldername_lb, str);
},
/****
@@ -535,7 +535,7 @@ function Inspector(controller) {
peers = tor.getPeers();
html.push('<div class="inspector_group">');
if (torrents.length > 1) {
html.push('<div class="inspector_torrent_label">', tor.getName(), '</div>');
html.push('<div class="inspector_torrent_label">', sanitizeText(tor.getName()), '</div>');
}
if (!peers || !peers.length) {
html.push('<br></div>'); // firefox won't paint the top border if the div is empty
@@ -560,8 +560,8 @@ function Inspector(controller) {
'<td>', (peer.rateToClient ? fmt.speedBps(peer.rateToClient) : ''), '</td>',
'<td class="percentCol">', Math.floor(peer.progress*100), '%', '</td>',
'<td>', fmt.peerStatus(peer.flagStr), '</td>',
'<td>', peer.address, '</td>',
'<td class="clientCol">', peer.clientName, '</td>',
'<td>', sanitizeText(peer.address), '</td>',
'<td class="clientCol">', sanitizeText(peer.clientName), '</td>',
'</tr>');
}
html.push('</table></div>');
@@ -676,8 +676,8 @@ function Inspector(controller) {
announceState = getAnnounceState(tracker);
lastScrapeStatusHash = lastScrapeStatus(tracker);
parity = (j%2) ? 'odd' : 'even';
html.push('<li class="inspector_tracker_entry ', parity, '"><div class="tracker_host" title="', tracker.announce, '">',
tracker.host, '</div>',
html.push('<li class="inspector_tracker_entry ', parity, '"><div class="tracker_host" title="', sanitizeText(tracker.announce), '">',
sanitizeText(tracker.host), '</div>',
'<div class="tracker_activity">',
'<div>', lastAnnounceStatusHash['label'], ': ', lastAnnounceStatusHash['value'], '</div>',
'<div>', announceState, '</div>',

View File

@@ -230,7 +230,7 @@ TorrentRendererFull.prototype =
render: function(controller, t, root)
{
// name
setInnerHTML(root._name_container, t.getName());
setTextContent(root._name_container, t.getName());
// progressbar
TorrentRendererHelper.renderProgressbar(controller, t, root._progressbar);
@@ -239,11 +239,11 @@ TorrentRendererFull.prototype =
var has_error = t.getError() !== Torrent._ErrNone;
var e = root._peer_details_container;
$(e).toggleClass('error',has_error);
setInnerHTML(e, this.getPeerDetails(t));
setTextContent(e, this.getPeerDetails(t));
// progress details
e = root._progress_details_container;
setInnerHTML(e, this.getProgressDetails(controller, t));
setTextContent(e, this.getProgressDetails(controller, t));
// pause/resume button
var is_stopped = t.isStopped();
@@ -319,13 +319,13 @@ TorrentRendererCompact.prototype =
var is_stopped = t.isStopped();
var e = root._name_container;
$(e).toggleClass('paused', is_stopped);
setInnerHTML(e, t.getName());
setTextContent(e, t.getName());
// peer details
var has_error = t.getError() !== Torrent._ErrNone;
e = root._details_container;
$(e).toggleClass('error', has_error);
setInnerHTML(e, this.getPeerDetails(t));
setTextContent(e, this.getPeerDetails(t));
// progressbar
TorrentRendererHelper.renderProgressbar(controller, t, root._progressbar);