/*
* Copyright © Dave Perrett and Malcolm Jarvis
* This code is licensed under the GPL version 2.
* For details, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Class Transmission
*/
function Transmission(){
this.initialize();
}
Transmission.prototype =
{
/*--------------------------------------------
*
* C O N S T R U C T O R
*
*--------------------------------------------*/
initialize: function()
{
// Initialize the helper classes
this.remote = new TransmissionRemote(this);
// Initialize the implementation fields
this._current_search = '';
this._torrents = { };
this._rows = [ ];
// Initialize the clutch preferences
Prefs.getClutchPrefs( this );
this.preloadImages();
// Set up user events
var tr = this;
$('#pause_all_link').bind('click', function(e){ tr.stopAllClicked(e); });
$('#resume_all_link').bind('click', function(e){ tr.startAllClicked(e); });
$('#pause_selected_link').bind('click', function(e){ tr.stopSelectedClicked(e); } );
$('#resume_selected_link').bind('click', function(e){ tr.startSelectedClicked(e); });
$('#remove_link').bind('click', function(e){ tr.removeClicked(e); });
$('#filter_all_link').parent().bind('click', function(e){ tr.showAllClicked(e); });
$('#filter_downloading_link').parent().bind('click', function(e){ tr.showDownloadingClicked(e); });
$('#filter_seeding_link').parent().bind('click', function(e){ tr.showSeedingClicked(e); });
$('#filter_paused_link').parent().bind('click', function(e){ tr.showPausedClicked(e); });
$('#prefs_save_button').bind('click', function(e) { tr.savePrefsClicked(e); return false;});
$('#prefs_cancel_button').bind('click', function(e){ tr.cancelPrefsClicked(e); return false; });
$('.inspector_tab').bind('click', function(e){ tr.inspectorTabClicked(e, this); });
$('.file_wanted_control').live('click', function(e){ tr.fileWantedClicked(e, this); });
$('.file_priority_control').live('click', function(e){ tr.filePriorityClicked(e, this); });
$('#files_select_all').live('click', function(e){ tr.filesSelectAllClicked(e, this); });
$('#files_deselect_all').live('click', function(e){ tr.filesDeselectAllClicked(e, this); });
$('#open_link').bind('click', function(e){ tr.openTorrentClicked(e); });
$('#upload_confirm_button').bind('click', function(e){ tr.confirmUploadClicked(e); return false;});
$('#upload_cancel_button').bind('click', function(e){ tr.cancelUploadClicked(e); return false; });
$('#turtle_button').bind('click', function(e){ tr.toggleTurtleClicked(e); return false; });
$('#prefs_tab_general_tab').click(function(e){ changeTab(this, 'prefs_tab_general') });
$('#prefs_tab_speed_tab').click(function(e){ changeTab(this, 'prefs_tab_speed') });
if (iPhone) {
$('#inspector_close').bind('click', function(e){ tr.hideInspector(); });
$('#preferences_link').bind('click', function(e){ tr.releaseClutchPreferencesButton(e); });
} else {
$(document).bind('keydown', function(e){ tr.keyDown(e); });
$('#torrent_container').bind('click', function(e){ tr.deselectAll( true ); });
$('#filter_toggle_link').bind('click', function(e){ tr.toggleFilterClicked(e); });
$('#inspector_link').bind('click', function(e){ tr.toggleInspectorClicked(e); });
this.setupSearchBox();
this.createContextMenu();
this.createSettingsMenu();
}
this.initTurtleDropDowns();
this._torrent_list = $('#torrent_list')[0];
this._inspector_file_list = $('#inspector_file_list')[0];
this._inspector_tab_files = $('#inspector_tab_files')[0];
this._toolbar_buttons = $('#torrent_global_menu ul li');
this._toolbar_pause_button = $('li#pause_selected')[0];
this._toolbar_pause_all_button = $('li#pause_all')[0];
this._toolbar_start_button = $('li#resume_selected')[0];
this._toolbar_start_all_button = $('li#resume_all')[0];
this._toolbar_remove_button = $('li#remove')[0];
this._context_pause_button = $('li#context_pause_selected')[0];
this._context_start_button = $('li#context_resume_selected')[0];
var ti = '#torrent_inspector_';
this._inspector = { };
this._inspector._info_tab = { };
this._inspector._info_tab.comment = $(ti+'comment')[0];
this._inspector._info_tab.creator_date = $(ti+'creator_date')[0];
this._inspector._info_tab.creator = $(ti+'creator')[0];
this._inspector._info_tab.download_dir = $(ti+'download_dir')[0];
this._inspector._info_tab.downloaded = $(ti+'downloaded')[0];
this._inspector._info_tab.download_from = $(ti+'download_from')[0];
this._inspector._info_tab.download_speed = $(ti+'download_speed')[0];
this._inspector._info_tab.error = $(ti+'error')[0];
this._inspector._info_tab.hash = $(ti+'hash')[0];
this._inspector._info_tab.have = $(ti+'have')[0];
this._inspector._info_tab.name = $(ti+'name')[0];
this._inspector._info_tab.progress = $(ti+'progress')[0];
this._inspector._info_tab.ratio = $(ti+'ratio')[0];
this._inspector._info_tab.secure = $(ti+'secure')[0];
this._inspector._info_tab.size = $(ti+'size')[0];
this._inspector._info_tab.state = $(ti+'state')[0];
this._inspector._info_tab.pieces = $(ti+'pieces')[0];
this._inspector._info_tab.uploaded = $(ti+'uploaded')[0];
this._inspector._info_tab.upload_speed = $(ti+'upload_speed')[0];
this._inspector._info_tab.upload_to = $(ti+'upload_to')[0];
// Setup the preference box
this.setupPrefConstraints();
// Setup the prefs gui
this.initializeSettings( );
// Get preferences & torrents from the daemon
var tr = this;
var async = false;
this.loadDaemonPrefs( async );
this.initializeAllTorrents();
this.togglePeriodicRefresh( true );
this.togglePeriodicSessionRefresh( true );
},
loadDaemonPrefs: function( async ){
var tr = this;
this.remote.loadDaemonPrefs( function(data){
var o = data.arguments;
Prefs.getClutchPrefs( o );
tr.updatePrefs( o );
}, async );
},
preloadImages: function() {
if (iPhone) {
this.loadImages(
'images/buttons/info_general.png',
'images/buttons/info_activity.png',
'images/buttons/info_files.png',
'images/buttons/toolbar_buttons.png',
'images/graphics/filter_bar.png',
'images/graphics/iphone_chrome.png',
'images/graphics/logo.png'
);
} else {
this.loadImages(
'images/buttons/info_general.png',
'images/buttons/info_activity.png',
'images/buttons/info_files.png',
'images/buttons/tab_backgrounds.png',
'images/buttons/toolbar_buttons.png',
'images/buttons/torrent_buttons.png',
'images/buttons/file_wanted_buttons.png',
'images/buttons/file_priority_buttons.png',
'images/graphics/chrome.png',
'images/graphics/filter_bar.png',
'images/graphics/logo.png',
'images/graphics/transfer_arrows.png',
'images/progress/progress.png'
);
}
},
loadImages: function() {
for( var i=0, row; row=arguments[i]; ++i )
jQuery("").attr("src", row);
},
/*
* Set up the preference validation
*/
setupPrefConstraints: function() {
// only allow integers for speed limit & port options
$('div.preference input[@type=text]:not(#download_location)').blur( function() {
this.value = this.value.replace(/[^0-9]/gi, '');
if (this.value == '') {
if ($(this).is('#refresh_rate')) {
this.value = 5;
} else {
this.value = 0;
}
}
});
},
/*
* Load the clutch prefs and init the GUI according to those prefs
*/
initializeSettings: function( )
{
Prefs.getClutchPrefs( this );
// iPhone conditions in the section allow us to not
// include transmenu js to save some bandwidth; if we
// start using prefs on iPhone we need to weed
// transmenu refs out of that too.
$('#filter_' + this[Prefs._FilterMode] + '_link').parent().addClass('selected');
if (!iPhone) $('#sort_by_' + this[Prefs._SortMethod] ).selectMenuItem();
if (!iPhone && ( this[Prefs._SortDirection] == Prefs._SortDescending ) )
$('#reverse_sort_order').selectMenuItem();
if( this[Prefs._ShowFilter] )
this.showFilter( );
if( !iPhone && this[Prefs._ShowInspector] )
this.showInspector( );
},
/*
* Set up the search box
*/
setupSearchBox: function()
{
var tr = this;
var search_box = $('#torrent_search');
search_box.bind('keyup click', {transmission: this}, function(event) {
tr.setSearch(this.value);
});
if (!$.browser.safari)
{
search_box.addClass('blur');
search_box[0].value = 'Filter';
search_box.bind('blur', {transmission: this}, function(event) {
if (this.value == '') {
$(this).addClass('blur');
this.value = 'Filter';
tr.setSearch(null);
}
}).bind('focus', {}, function(event) {
if ($(this).is('.blur')) {
this.value = '';
$(this).removeClass('blur');
}
});
}
},
contextStopSelected: function( ) {
this.stopSelectedTorrents( );
},
contextStartSelected: function( ) {
this.startSelectedTorrents( );
},
contextRemoveSelected: function( ) {
this.removeSelectedTorrents( );
},
contextRemoveDataSelected: function( ) {
this.removeSelectedTorrentsAndData( );
},
contextVerifySelected: function( ) {
this.verifySelectedTorrents( );
},
contextToggleInspector: function( ) {
this.toggleInspector( );
},
contextSelectAll: function( ) {
this.selectAll( true );
},
contextDeselectAll: function( ) {
this.deselectAll( true );
},
/*
* Create the torrent right-click menu
*/
createContextMenu: function() {
var tr = this;
var bindings = {
context_pause_selected: function(e){ tr.contextStopSelected(e); },
context_resume_selected: function(e){ tr.contextStartSelected(e); },
context_remove: function(e){ tr.contextRemoveSelected(e); },
context_removedata: function(e){ tr.contextRemoveDataSelected(e); },
context_verify: function(e){ tr.contextVerifySelected(e); },
context_toggle_inspector: function(e){ tr.contextToggleInspector(e); },
context_select_all: function(e){ tr.contextSelectAll(e); },
context_deselect_all: function(e){ tr.contextDeselectAll(e); }
};
// Setup the context menu
$('ul#torrent_list').contextMenu('torrent_context_menu', {
bindings: bindings,
menuStyle: Menu.context.menu_style,
itemStyle: Menu.context.item_style,
itemHoverStyle: Menu.context.item_hover_style,
itemDisabledStyle: Menu.context.item_disabled_style,
shadow: false,
boundingElement: $('div#torrent_container'),
boundingRightPad: 20,
boundingBottomPad: 5,
onContextMenu: function(e) {
tr.setSelectedTorrent( $(e.target).closest('.torrent')[0]._torrent, true );
return true;
}
});
},
/*
* Create the footer settings menu
*/
createSettingsMenu: function() {
var tr = this;
$('#settings_menu').transMenu({
selected_char: '✔',
direction: 'up',
onClick: function(e){ return tr.processSettingsMenuEvent(e); }
});
$('#unlimited_download_rate').selectMenuItem();
$('#unlimited_upload_rate').selectMenuItem();
},
initTurtleDropDowns: function() {
var i, out, hour, mins, start, end, value, content;
// Build the list of times
out = "";
start = $('#turtle_start_time')[0];
end = $('#turtle_end_time')[0];
for (i = 0; i < 24 * 4; i++) {
hour = parseInt(i / 4);
mins = ((i % 4) * 15);
value = (i * 15);
content = hour + ":" + (mins == 0 ? "00" : mins);
start.options[i] = new Option(content, value);
end.options[i] = new Option(content, value);
}
},
/*--------------------------------------------
*
* U T I L I T I E S
*
*--------------------------------------------*/
getAllTorrents: function()
{
var torrents = [];
for(var key in this._torrents)
torrents.push(this._torrents[key]);
return torrents;
},
getVisibleTorrents: function()
{
var torrents = [ ];
for( var i=0, row; row=this._rows[i]; ++i )
if( row._torrent && ( row[0].style.display != 'none' ) )
torrents.push( row._torrent );
return torrents;
},
getSelectedTorrents: function()
{
var v = this.getVisibleTorrents( );
var s = [ ];
for( var i=0, row; row=v[i]; ++i )
if( row.isSelected( ) )
s.push( row );
return s;
},
getDeselectedTorrents: function() {
var visible_torrent_ids = jQuery.map(this.getVisibleTorrents(), function(t) { return t.id(); } );
var s = [ ];
jQuery.each( this.getAllTorrents( ), function() {
var visible = (-1 != jQuery.inArray(this.id(), visible_torrent_ids));
if (!this.isSelected() || !visible)
s.push( this );
} );
return s;
},
getVisibleRows: function()
{
var rows = [ ];
for( var i=0, row; row=this._rows[i]; ++i )
if( row[0].style.display != 'none' )
rows.push( row );
return rows;
},
getTorrentIndex: function( rows, torrent )
{
for( var i=0, row; row=rows[i]; ++i )
if( row._torrent == torrent )
return i;
return null;
},
setPref: function( key, val )
{
this[key] = val;
Prefs.setValue( key, val );
},
scrollToElement: function( e )
{
if( iPhone )
return;
var container = $('#torrent_container');
var scrollTop = container.scrollTop( );
var innerHeight = container.innerHeight( );
var offsetTop = e[0].offsetTop;
var offsetHeight = e.outerHeight( );
if( offsetTop < scrollTop )
container.scrollTop( offsetTop );
else if( innerHeight + scrollTop < offsetTop + offsetHeight )
container.scrollTop( offsetTop + offsetHeight - innerHeight );
},
seedRatioLimit: function(){
if(this._prefs && this._prefs['seedRatioLimited'])
return this._prefs['seedRatioLimit'];
else
return -1;
},
/*--------------------------------------------
*
* S E L E C T I O N
*
*--------------------------------------------*/
setSelectedTorrent: function( torrent, doUpdate ) {
this.deselectAll( );
this.selectTorrent( torrent, doUpdate );
},
selectElement: function( e, doUpdate ) {
$.className.add( e[0], 'selected' );
this.scrollToElement( e );
if( doUpdate )
this.selectionChanged( );
$.className.add( e[0], 'selected' );
},
selectRow: function( rowIndex, doUpdate ) {
this.selectElement( this._rows[rowIndex], doUpdate );
},
selectTorrent: function( torrent, doUpdate ) {
if( torrent._element )
this.selectElement( torrent._element, doUpdate );
},
deselectElement: function( e, doUpdate ) {
$.className.remove( e[0], 'selected' );
if( doUpdate )
this.selectionChanged( );
},
deselectTorrent: function( torrent, doUpdate ) {
if( torrent._element )
this.deselectElement( torrent._element, doUpdate );
},
selectAll: function( doUpdate ) {
var tr = this;
for( var i=0, row; row=tr._rows[i]; ++i )
tr.selectElement( row );
if( doUpdate )
tr.selectionChanged();
},
deselectAll: function( doUpdate ) {
var tr = this;
for( var i=0, row; row=tr._rows[i]; ++i )
tr.deselectElement( row );
tr._last_torrent_clicked = null;
if( doUpdate )
tr.selectionChanged( );
},
/*
* Select a range from this torrent to the last clicked torrent
*/
selectRange: function( torrent, doUpdate )
{
if( !this._last_torrent_clicked )
{
this.selectTorrent( torrent );
}
else // select the range between the prevous & current
{
var rows = this.getVisibleRows( );
var i = this.getTorrentIndex( rows, this._last_torrent_clicked );
var end = this.getTorrentIndex( rows, torrent );
var step = i < end ? 1 : -1;
for( ; i!=end; i+=step )
this.selectRow( i );
this.selectRow( i );
}
if( doUpdate )
this.selectionChanged( );
},
selectionChanged: function()
{
this.updateButtonStates();
this.updateInspector();
},
/*--------------------------------------------
*
* E V E N T F U N C T I O N S
*
*--------------------------------------------*/
/*
* Process key event
*/
keyDown: function(event)
{
var tr = this;
var sel = tr.getSelectedTorrents( );
var rows = tr.getVisibleRows( );
var i = -1;
if( event.keyCode == 40 ) // down arrow
{
var t = sel.length ? sel[sel.length-1] : null;
i = t==null ? null : tr.getTorrentIndex(rows,t)+1;
if( i == rows.length || i == null )
i = 0;
}
else if( event.keyCode == 38 ) // up arrow
{
var t = sel.length ? sel[0] : null
i = t==null ? null : tr.getTorrentIndex(rows,t)-1;
if( i == -1 || i == null )
i = rows.length - 1;
}
if( 0<=i && i div:contains('N/A')").css('color', '#666');
return;
}
name = torrents.length == 1
? torrents[0].name()
: torrents.length+' Transfers Selected';
if( torrents.length == 1 )
{
var t = torrents[0];
var err = t.getErrorMessage( );
if( err )
error = err;
if( t._comment)
comment = t._comment ;
if( t._creator )
creator = t._creator ;
if( t._download_dir)
download_dir = t._download_dir;
hash = t.hash();
pieces = t._pieceCount + ', ' + Math.formatBytes(t._pieceSize);
date_created = Math.formatTimestamp( t._creator_date );
}
for( var i=0, t; t=torrents[i]; ++i ) {
sizeWhenDone += t._sizeWhenDone;
sizeDone += t._sizeWhenDone - t._leftUntilDone;
total_completed += t.completed();
total_verified += t._verified;
total_size += t.size();
total_upload += t.uploadTotal();
total_download += t.downloadTotal();
total_upload_speed += t.uploadSpeed();
total_download_speed += t.downloadSpeed();
total_upload_peers += t.peersGettingFromUs();
total_download_peers += t.peersSendingToUs();
if( total_state == null )
total_state = t.stateStr();
else if ( total_state.search ( t.stateStr() ) == -1 )
total_state += '/' + t.stateStr();
if( t._is_private )
have_private = true;
else
have_public = true;
}
var private_string = '';
if( have_private && have_public ) private_string = 'Mixed';
else if( have_private ) private_string = 'Private Torrent';
else if( have_public ) private_string = 'Public Torrent';
setInnerHTML( tab.name, name );
setInnerHTML( tab.size, torrents.length ? Math.formatBytes( total_size ) : na );
setInnerHTML( tab.pieces, pieces );
setInnerHTML( tab.hash, hash );
setInnerHTML( tab.state, total_state );
setInnerHTML( tab.download_speed, torrents.length ? Math.formatBytes( total_download_speed ) + '/s' : na );
setInnerHTML( tab.upload_speed, torrents.length ? Math.formatBytes( total_upload_speed ) + '/s' : na );
setInnerHTML( tab.uploaded, torrents.length ? Math.formatBytes( total_upload ) : na );
setInnerHTML( tab.downloaded, torrents.length ? Math.formatBytes( total_download ) : na );
setInnerHTML( tab.ratio, torrents.length ? Math.ratio( total_upload, total_download ) : na );
setInnerHTML( tab.have, torrents.length ? Math.formatBytes(total_completed) + ' (' + Math.formatBytes(total_verified) + ' verified)' : na );
setInnerHTML( tab.upload_to, torrents.length ? total_upload_peers : na );
setInnerHTML( tab.download_from, torrents.length ? total_download_peers : na );
setInnerHTML( tab.secure, private_string );
setInnerHTML( tab.creator_date, date_created );
setInnerHTML( tab.progress, torrents.length ? Math.ratio( sizeDone*100, sizeWhenDone ) + '%' : na );
setInnerHTML( tab.comment, comment.replace(/\//g, '/') );
setInnerHTML( tab.creator, creator );
setInnerHTML( tab.download_dir, download_dir.replace(/([\/_\.])/g, "$1") );
setInnerHTML( tab.error, error );
$(".inspector_row > div:contains('N/A')").css('color', '#666');
this.updateVisibleFileLists();
},
fileListIsVisible: function() {
return this._inspector_tab_files.className.indexOf('selected') != -1;
},
updateVisibleFileLists: function() {
if( this.fileListIsVisible( ) === true ) {
var selected = this.getSelectedTorrents();
jQuery.each( selected, function() { this.showFileList(); } );
jQuery.each( this.getDeselectedTorrents(), function() { this.hideFileList(); } );
// Check if we need to display the select all buttions
if ( !selected.length ) {
if ( $("#select_all_button_container").is(':visible') )
$("#select_all_button_container").hide();
} else {
if ( !$("#select_all_button_container").is(':visible') )
$("#select_all_button_container").show();
}
}
},
/*
* Toggle the visibility of the inspector (used by the context menu)
*/
toggleInspector: function() {
if( this[Prefs._ShowInspector] )
this.hideInspector( );
else
this.showInspector( );
},
showInspector: function() {
$('#torrent_inspector').show();
if (iPhone) {
$('body').addClass('inspector_showing');
$('#inspector_close').show();
this.hideiPhoneAddressbar();
} else {
var w = $('#torrent_inspector').width() + 1 + 'px';
$('#torrent_filter_bar')[0].style.right = w;
$('#torrent_container')[0].style.right = w;
}
setInnerHTML( $('ul li#context_toggle_inspector')[0], 'Hide Inspector' );
this.setPref( Prefs._ShowInspector, true );
this.updateInspector( );
},
/*
* Hide the inspector
*/
hideInspector: function() {
$('#torrent_inspector').hide();
if (iPhone) {
this.deselectAll( );
$('body.inspector_showing').removeClass('inspector_showing');
$('#inspector_close').hide();
this.hideiPhoneAddressbar();
} else {
$('#torrent_filter_bar')[0].style.right = '0px';
$('#torrent_container')[0].style.right = '0px';
setInnerHTML( $('ul li#context_toggle_inspector')[0], 'Show Inspector' );
}
this.setPref( Prefs._ShowInspector, false );
},
/*
* Toggle the visibility of the filter bar
*/
toggleFilter: function() {
if( this[Prefs._ShowFilter] )
this.hideFilter();
else
this.showFilter();
},
showFilter: function( ) {
var container_top = parseInt($('#torrent_container').position().top) + $('#torrent_filter_bar').height() + 1;
$('#torrent_container').css('top', container_top + 'px');
$('#torrent_filter_bar').show();
this.setPref( Prefs._ShowFilter, true );
},
hideFilter: function()
{
var container_top = parseInt($('#torrent_container').css('top')) - $('#torrent_filter_bar').height() - 1;
$('#torrent_container').css('top', container_top + 'px');
$('#torrent_filter_bar').hide();
this.setPref( Prefs._ShowFilter, false );
this.setFilter( Prefs._FilterAll );
},
refreshTorrents: function(ids) {
var tr = this;
if (!ids)
ids = 'recently-active';
this.remote.getUpdatedDataFor(ids, function(active, removed){ tr.updateTorrentsData(active, removed); });
},
updateTorrentsData: function( updated, removed_ids ) {
var tr = this;
var new_torrent_ids = [];
var refresh_files_for = [];
jQuery.each( updated, function() {
var t = tr._torrents[this.id];
if (t){
t.refresh(this);
if(t.isSelected())
refresh_files_for.push(t.id());
}
else
new_torrent_ids.push(this.id);
} );
if(refresh_files_for.length > 0)
tr.remote.loadTorrentFiles( refresh_files_for );
if(new_torrent_ids.length > 0)
tr.remote.getInitialDataFor(new_torrent_ids, function(torrents){ tr.addTorrents(torrents) } );
var removedAny = tr.deleteTorrents(removed_ids);
if( ( new_torrent_ids.length != 0 ) || removedAny ) {
tr.hideiPhoneAddressbar();
tr.deselectAll( true );
}
this.refilter();
},
updateTorrentsFileData: function( torrents ){
var tr = this;
var listIsVisible = tr.fileListIsVisible( );
jQuery.each( torrents, function() {
var t = tr._torrents[this.id];
if (t) {
t.refreshFileModel(this);
if( listIsVisible && t.isSelected())
t.refreshFileView();
}
} );
},
initializeAllTorrents: function(){
var tr = this;
this.remote.getInitialDataFor( null ,function(torrents) { tr.addTorrents(torrents); } );
},
addTorrents: function( new_torrents )
{
var transferFragment = document.createDocumentFragment( );
var fileFragment = document.createDocumentFragment( );
for( var i=0, row; row=new_torrents[i]; ++i ) {
var new_torrent = new Torrent( transferFragment, fileFragment, this, row );
this._torrents[new_torrent.id()] = new_torrent;
}
this._inspector_file_list.appendChild( fileFragment );
this._torrent_list.appendChild( transferFragment );
this.refilter( );
},
deleteTorrents: function(torrent_ids){
if(typeof torrent_ids == 'undefined')
return false;
var tr = this;
var removedAny = false;
$.each( torrent_ids, function(index, id){
var torrent = tr._torrents[id];
if(torrent) {
removedAny = true;
var e = torrent.element();
if( e ) {
var row_index = tr.getTorrentIndex(tr._rows, torrent);
delete e._torrent; //remove circular refernce to help IE garbage collect
tr._rows.splice(row_index, 1)
e.remove();
}
torrent.hideFileList();
torrent.deleteFiles();
delete tr._torrents[torrent.id()];
}
});
return removedAny;
},
/*
* Set the alternating background colors for torrents
*/
setTorrentBgColors: function( )
{
var rows = this.getVisibleRows( );
for( var i=0, row; row=rows[i]; ++i ) {
var wasEven = row[0].className.indexOf('even') != -1;
var isEven = ((i+1) % 2 == 0);
if( wasEven != isEven )
row.toggleClass('even', isEven);
}
},
updateStatusbar: function()
{
var torrents = this.getAllTorrents();
var torrentCount = torrents.length;
var visibleCount = this.getVisibleTorrents().length;
// calculate the overall speed
var upSpeed = 0;
var downSpeed = 0;
for( var i=0, row; row=torrents[i]; ++i ) {
upSpeed += row.uploadSpeed( );
downSpeed += row.downloadSpeed( );
}
// update torrent count label
var s;
if( torrentCount == visibleCount )
s = torrentCount + ' Transfers';
else
s = visibleCount + ' of ' + torrentCount + ' Transfers';
setInnerHTML( $('#torrent_global_transfer')[0], s );
// update the speeds
s = Math.formatBytes( upSpeed ) + '/s';
if( iPhone ) s = 'UL: ' + s;
setInnerHTML( $('#torrent_global_upload')[0], s );
// download speeds
s = Math.formatBytes( downSpeed ) + '/s';
if( iPhone ) s = 'DL: ' + s;
setInnerHTML( $('#torrent_global_download')[0], s );
},
/*
* Select a torrent file to upload
* FIXME
*/
uploadTorrentFile: function(confirmed)
{
// Display the upload dialog
if (! confirmed) {
$('input#torrent_upload_file').attr('value', '');
$('input#torrent_upload_url').attr('value', '');
$('input#torrent_auto_start').attr('checked', this[Prefs._AutoStart]);
$('#upload_container').show();
if (!iPhone && Safari3) {
setTimeout("$('div#upload_container div.dialog_window').css('top', '0px');",10);
}
// Submit the upload form
} else {
var tr = this;
var args = { };
var paused = !$('#torrent_auto_start').is(':checked');
if ('' != $('#torrent_upload_url').val()) {
tr.remote.addTorrentByUrl($('#torrent_upload_url').val(), { paused: paused });
} else {
args.url = '/transmission/upload?paused=' + paused;
args.type = 'POST';
args.data = { 'X-Transmission-Session-Id' : tr.remote._token };
args.dataType = 'xml';
args.iframe = true;
args.success = function( data ) {
tr.refreshTorrents();
tr.togglePeriodicRefresh( true );
};
tr.togglePeriodicRefresh( false );
$('#torrent_upload_form').ajaxSubmit( args );
}
}
},
removeSelectedTorrents: function() {
var torrents = this.getSelectedTorrents( );
if( torrents.length )
this.promptToRemoveTorrents( torrents );
},
removeSelectedTorrentsAndData: function() {
var torrents = this.getSelectedTorrents( );
if( torrents.length )
this.promptToRemoveTorrentsAndData( torrents );
},
promptToRemoveTorrents:function( torrents )
{
if( torrents.length == 1 )
{
var torrent = torrents[0];
var header = 'Remove ' + torrent.name() + '?';
var message = 'Once removed, continuing the transfer will require the torrent file. Are you sure you want to remove it?';
dialog.confirm( header, message, 'Remove', 'transmission.removeTorrents', torrents );
}
else
{
var header = 'Remove ' + torrents.length + ' transfers?';
var message = 'Once removed, continuing the transfers will require the torrent files. Are you sure you want to remove them?';
dialog.confirm( header, message, 'Remove', 'transmission.removeTorrents', torrents );
}
},
promptToRemoveTorrentsAndData:function( torrents )
{
if( torrents.length == 1 )
{
var torrent = torrents[0],
header = 'Remove ' + torrent.name() + ' and delete data?',
message = 'All data downloaded for this torrent will be deleted. Are you sure you want to remove it?';
dialog.confirm( header, message, 'Remove', 'transmission.removeTorrentsAndData', torrents );
}
else
{
var header = 'Remove ' + torrents.length + ' transfers and delete data?',
message = 'All data downloaded for these torrents will be deleted. Are you sure you want to remove them?';
dialog.confirm( header, message, 'Remove', 'transmission.removeTorrentsAndData', torrents );
}
},
removeTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var tr = this;
this.remote.removeTorrents( torrent_ids, function(){ tr.refreshTorrents() } );
},
removeTorrentsAndData: function( torrents ) {
this.remote.removeTorrentsAndData( torrents );
},
verifySelectedTorrents: function() {
this.verifyTorrents( this.getSelectedTorrents( ) );
},
startSelectedTorrents: function( ) {
this.startTorrents( this.getSelectedTorrents( ) );
},
startAllTorrents: function( ) {
this.startTorrents( this.getAllTorrents( ) );
},
startTorrent: function( torrent ) {
this.startTorrents( [ torrent ] );
},
startTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var tr = this;
this.remote.startTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids) } );
},
verifyTorrent: function( torrent ) {
this.verifyTorrents( [ torrent ] );
},
verifyTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var tr = this;
this.remote.verifyTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids) } );
},
stopSelectedTorrents: function( ) {
this.stopTorrents( this.getSelectedTorrents( ) );
},
stopAllTorrents: function( ) {
this.stopTorrents( this.getAllTorrents( ) );
},
stopTorrent: function( torrent ) {
this.stopTorrents( [ torrent ] );
},
stopTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var tr = this;
this.remote.stopTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids )} );
},
changeFileCommand: function(command, torrent, file) {
this.remote.changeFileCommand(command, torrent, file)
},
hideiPhoneAddressbar: function(timeInSeconds) {
var tr = this;
if( iPhone ) {
var delayLength = timeInSeconds ? timeInSeconds*1000 : 150;
// not currently supported on iPhone
if(/*document.body.scrollTop!=1 && */scroll_timeout==null) {
scroll_timeout = setTimeout(function(){ tr.doToolbarHide(); }, delayLength);
}
}
},
doToolbarHide: function() {
window.scrollTo(0,1);
scroll_timeout=null;
},
/***
****
***/
refilter: function()
{
// decide which torrents to keep showing
var allTorrents = this.getAllTorrents( );
var keep = [ ];
for( var i=0, t; t=allTorrents[i]; ++i )
if( t.test( this[Prefs._FilterMode], this._current_search ) )
keep.push( t );
// sort the keepers
Torrent.sortTorrents( keep, this[Prefs._SortMethod],
this[Prefs._SortDirection] );
// make a backup of the selection
var sel = this.getSelectedTorrents( );
this.deselectAll( );
// hide the ones we're not keeping
for( var i=keep.length, e; e=this._rows[i]; ++i ) {
delete e._torrent;
e[0].style.display = 'none';
}
// show the ones we're keeping
sel.sort( Torrent.compareById );
for( var i=0, len=keep.length; i