/usr/share/transmission/web/javascript/common.js is in transmission-common 2.92-3ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | /**
* Copyright © Dave Perrett and Malcolm Jarvis
*
* This file is licensed under the GPLv2.
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
var transmission,
dialog,
isMobileDevice = RegExp("(iPhone|iPod|Android)").test(navigator.userAgent),
scroll_timeout;
if (!Array.indexOf){
Array.prototype.indexOf = function(obj){
var i, len;
for (i=0, len=this.length; i<len; i++)
if (this[i]==obj)
return i;
return -1;
}
}
// http://forum.jquery.com/topic/combining-ui-dialog-and-tabs
$.fn.tabbedDialog = function (dialog_opts) {
this.tabs({selected: 0});
this.dialog(dialog_opts);
this.find('.ui-tab-dialog-close').append(this.parent().find('.ui-dialog-titlebar-close'));
this.find('.ui-tab-dialog-close').css({'position':'absolute','right':'0', 'top':'16px'});
this.find('.ui-tab-dialog-close > a').css({'float':'none','padding':'0'});
var tabul = this.find('ul:first');
this.parent().addClass('ui-tabs').prepend(tabul).draggable('option','handle',tabul);
this.siblings('.ui-dialog-titlebar').remove();
tabul.addClass('ui-dialog-titlebar');
}
$(document).ready(function() {
// IE8 and below don’t support ES5 Date.now()
if (!Date.now) {
Date.now = function() {
return +new Date();
};
}
// IE specific fixes here
if ($.browser.msie) {
try {
document.execCommand("BackgroundImageCache", false, true);
} catch(err) {}
$('.dialog_container').css('height',$(window).height()+'px');
}
if ($.browser.safari) {
// Move search field's margin down for the styled input
$('#torrent_search').css('margin-top', 3);
}
if (isMobileDevice){
window.onload = function(){ setTimeout(function() { window.scrollTo(0,1); },500); };
window.onorientationchange = function(){ setTimeout(function() { window.scrollTo(0,1); },100); };
if (window.navigator.standalone)
// Fix min height for isMobileDevice when run in full screen mode from home screen
// so the footer appears in the right place
$('body div#torrent_container').css('min-height', '338px');
$("label[for=torrent_upload_url]").text("URL: ");
} else {
// Fix for non-Safari-3 browsers: dark borders to replace shadows.
$('div.dialog_container div.dialog_window').css('border', '1px solid #777');
}
// Initialise the dialog controller
dialog = new Dialog();
// Initialise the main Transmission controller
transmission = new Transmission();
});
/**
* Checks to see if the content actually changed before poking the DOM.
*/
function setInnerHTML(e, html)
{
if (!e)
return;
/* innerHTML is listed as a string, but the browser seems to change it.
* For example, "∞" gets changed to "∞" somewhere down the line.
* So, let's use an arbitrary different field to test our state... */
if (e.currentHTML != html)
{
e.currentHTML = html;
e.innerHTML = html;
}
};
function sanitizeText(text)
{
return text.replace(/</g, "<").replace(/>/g, ">");
};
/**
* 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
*/
Math.ratio = function(numerator, denominator) {
var result = Math.floor(100 * numerator / denominator) / 100;
// check for special cases
if (result==Number.POSITIVE_INFINITY || result==Number.NEGATIVE_INFINITY) result = -2;
else if (isNaN(result)) result = -1;
return result;
};
/**
* Round a string of a number to a specified number of decimal places
*/
Number.prototype.toTruncFixed = function(place) {
var ret = Math.floor(this * Math.pow (10, place)) / Math.pow(10, place);
return ret.toFixed(place);
}
Number.prototype.toStringWithCommas = function() {
return this.toString().replace(/\B(?=(?:\d{3})+(?!\d))/g, ",");
}
/*
* Trim whitespace from a string
*/
String.prototype.trim = function () {
return this.replace(/^\s*/, "").replace(/\s*$/, "");
}
/***
**** Preferences
***/
function Prefs() { }
Prefs.prototype = { };
Prefs._RefreshRate = 'refresh_rate';
Prefs._FilterMode = 'filter';
Prefs._FilterAll = 'all';
Prefs._FilterActive = 'active';
Prefs._FilterSeeding = 'seeding';
Prefs._FilterDownloading = 'downloading';
Prefs._FilterPaused = 'paused';
Prefs._FilterFinished = 'finished';
Prefs._SortDirection = 'sort_direction';
Prefs._SortAscending = 'ascending';
Prefs._SortDescending = 'descending';
Prefs._SortMethod = 'sort_method';
Prefs._SortByAge = 'age';
Prefs._SortByActivity = 'activity';
Prefs._SortByName = 'name';
Prefs._SortByQueue = 'queue_order';
Prefs._SortBySize = 'size';
Prefs._SortByProgress = 'percent_completed';
Prefs._SortByRatio = 'ratio';
Prefs._SortByState = 'state';
Prefs._CompactDisplayState= 'compact_display_state';
Prefs._Defaults =
{
'filter': 'all',
'refresh_rate' : 5,
'sort_direction': 'ascending',
'sort_method': 'name',
'turtle-state' : false,
'compact_display_state' : false
};
/*
* Set a preference option
*/
Prefs.setValue = function(key, val)
{
if (!(key in Prefs._Defaults))
console.warn("unrecognized preference key '%s'", key);
var date = new Date();
date.setFullYear (date.getFullYear() + 1);
document.cookie = key+"="+val+"; expires="+date.toGMTString()+"; path=/";
};
/**
* Get a preference option
*
* @param key the preference's key
* @param fallback if the option isn't set, return this instead
*/
Prefs.getValue = function(key, fallback)
{
var val;
if (!(key in Prefs._Defaults))
console.warn("unrecognized preference key '%s'", key);
var lines = document.cookie.split(';');
for (var i=0, len=lines.length; !val && i<len; ++i) {
var line = lines[i].trim();
var delim = line.indexOf('=');
if ((delim === key.length) && line.indexOf(key) === 0)
val = line.substring(delim + 1);
}
// FIXME: we support strings and booleans... add number support too?
if (!val) val = fallback;
else if (val === 'true') val = true;
else if (val === 'false') val = false;
return val;
};
/**
* Get an object with all the Clutch preferences set
*
* @pararm o object to be populated (optional)
*/
Prefs.getClutchPrefs = function(o)
{
if (!o)
o = { };
for (var key in Prefs._Defaults)
o[key] = Prefs.getValue(key, Prefs._Defaults[key]);
return o;
};
// forceNumeric() plug-in implementation
jQuery.fn.forceNumeric = function () {
return this.each(function () {
$(this).keydown(function (e) {
var key = e.which || e.keyCode;
return !e.shiftKey && !e.altKey && !e.ctrlKey &&
// numbers
key >= 48 && key <= 57 ||
// Numeric keypad
key >= 96 && key <= 105 ||
// comma, period and minus, . on keypad
key === 190 || key === 188 || key === 109 || key === 110 ||
// Backspace and Tab and Enter
key === 8 || key === 9 || key === 13 ||
// Home and End
key === 35 || key === 36 ||
// left and right arrows
key === 37 || key === 39 ||
// Del and Ins
key === 46 || key === 45;
});
});
}
/**
* http://blog.stevenlevithan.com/archives/parseuri
*
* parseUri 1.2.2
* (c) Steven Levithan <stevenlevithan.com>
* MIT License
*/
function parseUri (str) {
var o = parseUri.options,
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
uri = {},
i = 14;
while (i--) uri[o.key[i]] = m[i] || "";
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) uri[o.q.name][$1] = $2;
});
return uri;
};
parseUri.options = {
strictMode: false,
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
q: {
name: "queryKey",
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
};
|