/* * 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); }); $('#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; }); 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._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.swarm_speed = $(ti+'swarm_speed')[0]; this._inspector._info_tab.total_leechers = $(ti+'total_leechers')[0]; this._inspector._info_tab.total_seeders = $(ti+'total_seeders')[0]; this._inspector._info_tab.tracker = $(ti+'tracker')[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; this.remote.loadDaemonPrefs( ); this.initalizeAllTorrents(); this.togglePeriodicRefresh( true ); }, 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(); }, /*-------------------------------------------- * * 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 ); }, /*-------------------------------------------- * * 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]; if( t._error_message ) error = t._error_message ; if( t._comment) comment = t._comment ; if( t._creator ) creator = t._creator ; if( t._download_dir) download_dir = t._download_dir; hash = t.hash(); 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_seeders += t.totalSeeders(); total_leechers += t.totalLeechers(); total_upload_peers += t.peersGettingFromUs(); total_download_peers += t.peersSendingToUs(); total_swarm_speed += t.swarmSpeed(); if( total_state == null ) total_state = t.stateStr(); else if ( total_state.search ( t.stateStr() ) == -1 ) total_state += '/' + t.stateStr(); var tracker = t._tracker; if( total_tracker == null ) total_tracker = tracker; else if ( total_tracker.search ( tracker ) == -1 ) total_tracker += ', ' + tracker; 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.tracker, total_tracker.replace(/\//g, '/​') ); 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.total_seeders, torrents.length ? total_seeders : na ); setInnerHTML( tab.total_leechers, torrents.length ? total_leechers : na ); setInnerHTML( tab.swarm_speed, torrents.length ? Math.formatBytes(total_swarm_speed) + '/s' : 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 ) { jQuery.each( this.getSelectedTorrents(), function() { this.showFileList(); } ); jQuery.each( this.getDeselectedTorrents(), function() { this.hideFileList(); } ); } }, /* * 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(); } } ); }, initalizeAllTorrents: 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', ''); $('#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 = { }; if ('' != $('#torrent_upload_url').val()) { tr.remote.addTorrentByUrl($('#torrent_upload_url').val(), { paused: !this[Prefs._AutoStart] }); } else { args.url = '/transmission/upload?paused=' + (this[Prefs._AutoStart] ? 'false' : 'true'); 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 ) { this.remote.removeTorrents( torrents ); }, 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 ) { this.remote.startTorrents( torrents ); }, verifyTorrent: function( torrent ) { this.verifyTorrents( [ torrent ] ); }, verifyTorrents: function( torrents ) { this.remote.verifyTorrents( torrents ); }, stopSelectedTorrents: function( ) { this.stopTorrents( this.getSelectedTorrents( ) ); }, stopAllTorrents: function( ) { this.stopTorrents( this.getAllTorrents( ) ); }, stopTorrent: function( torrent ) { this.stopTorrents( [ torrent ] ); }, stopTorrents: function( torrents ) { this.remote.stopTorrents( torrents ); }, 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