/*
* 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