/* * 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() { // IE specific fixes here if ($.browser.msie) { try { document.execCommand("BackgroundImageCache", false, true); } catch(err) {} $('head').append(''); $('head').append(''); $('.dialog_container').css('height',$(window).height()+'px'); } // 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 $('#pause_all_link').bind('click', this.stopAllClicked ); $('#resume_all_link').bind('click', this.startAllClicked); $('#pause_selected_link').bind('click', this.stopSelectedClicked ); $('#resume_selected_link').bind('click', this.startSelectedClicked); $('#remove_link').bind('click', this.removeClicked); $('#removedata_link').bind('click', this.removeDataClicked); $('#filter_all_link').parent().bind('click', this.showAllClicked); $('#filter_downloading_link').parent().bind('click', this.showDownloadingClicked); $('#filter_seeding_link').parent().bind('click', this.showSeedingClicked); $('#filter_paused_link').parent().bind('click', this.showPausedClicked); $('#prefs_save_button').bind('click', this.savePrefsClicked); $('#prefs_cancel_button').bind('click', this.cancelPrefsClicked); $('#inspector_tab_info').bind('click', this.inspectorTabClicked); $('#inspector_tab_activity').bind('click', this.inspectorTabClicked); $('#inspector_tab_files').bind('click', this.inspectorTabClicked); if (iPhone) { $('#torrent_inspector').bind('click', this.hideInspector); $('#preferences_link').bind('click', this.releaseClutchPreferencesButton); } else { $(document).bind('keydown', this.keyDown); $('#torrent_container').bind('click', this.deselectAll); $('#open_link').bind('click', this.openTorrentClicked); $('#filter_toggle_link').bind('click', this.toggleFilterClicked); $('#inspector_link').bind('click', this.toggleInspectorClicked); $('#upload_confirm_button').bind('click', this.confirmUploadClicked); $('#upload_cancel_button').bind('click', this.cancelUploadClicked); this.setupSearchBox(); this.createContextMenu(); this.createSettingsMenu(); } // Setup the preference box this.setupPrefConstraints(); // Setup the prefs gui this.initializeSettings( ); // Get preferences & torrents from the daemon this.remote.loadDaemonPrefs( ); this.remote.loadTorrents( true ); 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; i").attr("src", arguments[i]); } }, /* * 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( 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( ) { transmission.stopSelectedTorrents( ); }, contextStartSelected: function( ) { transmission.startSelectedTorrents( ); }, contextRemoveSelected: function( ) { transmission.removeSelectedTorrents( ); }, contextRemoveDataSelected: function( ) { transmission.removeSelectedTorrentsAndData( ); }, contextVerifySelected: function( ) { transmission.verifySelectedTorrents( ); }, contextToggleInspector: function( ) { transmission.toggleInspector( ); }, contextSelectAll: function( ) { transmission.selectAll( true ); }, contextDeselectAll: function( ) { transmission.deselectAll( true ); }, /* * Create the torrent right-click menu */ createContextMenu: function() { var bindings = { context_pause_selected: this.contextStopSelected, context_resume_selected: this.contextStartSelected, context_remove: this.contextRemoveSelected, context_removedata: this.contextRemoveDataSelected, context_verify: this.contextVerifySelected, context_toggle_inspector: this.contextToggleInspector, context_select_all: this.contextSelectAll, context_deselect_all: this.contextDeselectAll }; // 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 }); }, /* * Create the footer settings menu */ createSettingsMenu: function() { $('#settings_menu').transMenu({ selected_char: '✔', direction: 'up', onClick: this.processSettingsMenuEvent }); $('#unlimited_download_rate').selectMenuItem(); $('#unlimited_upload_rate').selectMenuItem(); }, /*-------------------------------------------- * * U T I L I T I E S * *--------------------------------------------*/ getAllTorrents: function() { return this._torrents; }, getVisibleTorrents: function() { var torrents = [ ]; for( var i=0, len=this._rows.length; 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 ; } hash = t.hash(); date_created = Math.formatTimestamp( t._creator_date ); } for(i = 0; i < torrents.length; ++i ) { var t = torrents[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'; var ti = '#torrent_inspector_'; setInnerHTML( $(ti+'name')[0], name ); setInnerHTML( $(ti+'size')[0], torrents.length ? Math.formatBytes( total_size ) : 'N/A' ); setInnerHTML( $(ti+'tracker')[0], total_tracker.replace(/\//g, '/​') ); setInnerHTML( $(ti+'hash')[0], hash ); setInnerHTML( $(ti+'state')[0], total_state ); setInnerHTML( $(ti+'download_speed')[0], torrents.length ? Math.formatBytes( total_download_speed ) + '/s' : 'N/A' ); setInnerHTML( $(ti+'upload_speed')[0], torrents.length ? Math.formatBytes( total_upload_speed ) + '/s' : 'N/A' ); setInnerHTML( $(ti+'uploaded')[0], torrents.length ? Math.formatBytes( total_upload ) : 'N/A' ); setInnerHTML( $(ti+'downloaded')[0], torrents.length ? Math.formatBytes( total_download ) : 'N/A' ); setInnerHTML( $(ti+'ratio')[0], torrents.length ? Math.ratio( total_upload, total_download ) : 'N/A' ); setInnerHTML( $(ti+'total_seeders')[0], torrents.length ? total_seeders : 'N/A' ); setInnerHTML( $(ti+'total_leechers')[0], torrents.length ? total_leechers : 'N/A' ); setInnerHTML( $(ti+'swarm_speed')[0], torrents.length ? Math.formatBytes(total_swarm_speed) + '/s' : 'N/A' ); setInnerHTML( $(ti+'have')[0], torrents.length ? Math.formatBytes(total_completed) + ' (' + Math.formatBytes(total_verified) + ' verified)' : 'N/A' ); setInnerHTML( $(ti+'upload_to')[0], torrents.length ? total_upload_peers : 'N/A' ); setInnerHTML( $(ti+'download_from')[0], torrents.length ? total_download_peers : 'N/A' ); setInnerHTML( $(ti+'secure')[0], private_string ); setInnerHTML( $(ti+'creator_date')[0], date_created ); setInnerHTML( $(ti+'progress')[0], torrents.length ? Math.ratio( sizeDone*100, sizeWhenDone ) + '%' : 'N/A' ); setInnerHTML( $(ti+'comment')[0], comment.replace(/\//g, '/​') ); setInnerHTML( $(ti+'creator')[0], creator ); setInnerHTML( $(ti+'error')[0], error ); $(".inspector_row > div:contains('N/A')").css('color', '#666'); this.updateVisibleFileLists(); }, updateVisibleFileLists: function() { 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'); 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) { transmsision.deselectAll( ); $('body.inspector_showing').removeClass('inspector_showing'); transmission.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 ); }, updateTorrentsData: function( torrent_list ) { var tr = this; jQuery.each( torrent_list, function() { var t = Torrent.lookup(tr._torrents, this.id); if (t) t.refresh(this); } ); }, /* * Process got some new torrent data from the server */ updateAllTorrents: function( torrent_list ) { var torrent_data; var new_torrents = []; var torrent_ids = []; var handled = []; // refresh existing torrents this.updateTorrentsData( torrent_list ); // partition existing and new torrents for( var i=0, len=torrent_list.length; i