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