From: Charles Kerr Date: Sat, 19 Jun 2010 18:40:07 +0000 (+0000) Subject: (trunk web) add a more flexible speed / size formatter to the web client X-Git-Tag: 2.10~401 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1aba1c8d66591ec3cc81bd1c3dcc6c026b1e4f09;p=transmission (trunk web) add a more flexible speed / size formatter to the web client --- diff --git a/web/javascript/common.js b/web/javascript/common.js index dea11f730..c27a2e2f2 100644 --- a/web/javascript/common.js +++ b/web/javascript/common.js @@ -107,150 +107,6 @@ function setInnerHTML( e, html ) } }; -/* - * Converts file & folder byte size values to more - * readable values (bytes, KiB, MiB, GiB or TiB). - * - * @param integer bytes - * @returns string - */ -Math.formatBytes = function(bytes) { - var size; - var unit; - - // Terabytes (TiB). - if ( bytes >= 1099511627776 ) { - size = bytes / 1099511627776; - unit = ' TiB'; - - // Gigabytes (GiB). - } else if ( bytes >= 1073741824 ) { - size = bytes / 1073741824; - unit = ' GiB'; - - // Megabytes (MiB). - } else if ( bytes >= 1048576 ) { - size = bytes / 1048576; - unit = ' MiB'; - - // Kilobytes (KiB). - } else if ( bytes >= 1024 ) { - size = bytes / 1024; - unit = ' KiB'; - - // The file is less than one KiB - } else { - size = bytes; - unit = ' bytes'; - } - - // Single-digit numbers have greater precision - var precision = 1; - if (size < 10) { - precision = 2; - } - size = Math.roundWithPrecision(size, precision); - - // Add the decimal if this is an integer - if ((size % 1) == 0 && unit != ' bytes') { - size = size + '.0'; - } - - return size + unit; -}; - - -/* - * Converts seconds to more readable units (hours, minutes etc). - * - * @param integer seconds - * @returns string - */ -Math.formatSeconds = function(seconds) -{ - var result; - var days = Math.floor(seconds / 86400); - var hours = Math.floor((seconds % 86400) / 3600); - var minutes = Math.floor((seconds % 3600) / 60); - var seconds = Math.floor((seconds % 3600) % 60); - - if (days > 0 && hours == 0) - result = days + ' days'; - else if (days > 0 && hours > 0) - result = days + ' days ' + hours + ' hr'; - else if (hours > 0 && minutes == 0) - result = hours + ' hr'; - else if (hours > 0 && minutes > 0) - result = hours + ' hr ' + minutes + ' min'; - else if (minutes > 0 && seconds == 0) - result = minutes + ' min'; - else if (minutes > 0 && seconds > 0) - result = minutes + ' min ' + seconds + ' seconds'; - else - result = seconds + ' seconds'; - - return result; -}; - - -/* - * Converts a unix timestamp to a human readable value - * - * @param integer seconds - * @returns string - */ -Math.formatTimestamp = function(seconds) { - var myDate = new Date(seconds*1000); - var now = new Date(); - - var date = ""; - var time = ""; - - var sameYear = now.getFullYear() == myDate.getFullYear(); - var sameMonth = now.getMonth() == myDate.getMonth(); - - var dateDiff = now.getDate() - myDate.getDate(); - if(sameYear && sameMonth && Math.abs(dateDiff) <= 1){ - if(dateDiff == 0){ - date = "Today"; - } - else if(dateDiff == 1){ - date = "Yesterday"; - } - else{ - date = "Tomorrow"; - } - } - else{ - date = myDate.toDateString(); - } - - var hours = myDate.getHours(); - var period = "AM"; - if(hours > 12){ - hours = hours - 12; - period = "PM"; - } - if(hours == 0){ - hours = 12; - } - if(hours < 10){ - hours = "0" + hours; - } - var minutes = myDate.getMinutes(); - if(minutes < 10){ - minutes = "0" + minutes; - } - var seconds = myDate.getSeconds(); - if(seconds < 10){ - seconds = "0" + seconds; - } - - time = [hours, minutes, seconds].join(':'); - - return [date, time, period].join(' '); -}; - /* * Round a float to a specified number of decimal * places, stripping trailing zeroes diff --git a/web/javascript/formatter.js b/web/javascript/formatter.js new file mode 100644 index 000000000..8194cb9ca --- /dev/null +++ b/web/javascript/formatter.js @@ -0,0 +1,169 @@ +/** +*** This file Copyright (C) 2010 Mnemosyne LLC +*** +*** This code is licensed under the GPL version 2. +*** For more details, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html +**/ + +Transmission.fmt = (function() +{ + var KB_val = 1024; + var MB_val = 1024 * 1024; + var GB_val = 1024 * 1024 * 1024; + var KB_str = 'KiB'; + var MB_str = 'MiB'; + var GB_str = 'GiB'; + + /** + * Round a number to a specified number of decimal places, stripping trailing zeroes + * @param number floatnum + * @param number precision + * @returns number + */ + var roundWithPrecision = function(floatnum, precision) { + return Math.round ( floatnum * Math.pow ( 10, precision ) ) / Math.pow ( 10, precision ); + }; + + return { + MODE_IEC: 1, + MODE_SI: 2, + + setMode: function( mode ) { + if( mode == MODE_IEC ) { + this.KB_val = 1024; + this.MB_val = this.KB_val * 1024; + this.GB_val = this.MB_val * 1024; + this.KB_str = 'KiB'; + this.MB_str = 'MiB'; + this.GB_str = 'GiB'; + } else { + this.KB_val = 1000; + this.MB_val = this.KB_val * 1000; + this.GB_val = this.MB_val * 1000; + this.KB_str = 'kB'; + this.MB_str = 'MB'; + this.GB_str = 'GB'; + } + }, + + + /** + * Formats the bytes into a string value with B, KiB, MiB, or GiB units. + * + * @param {Number} bytes the filesize in bytes + * @return {String} formatted string with B, KiB, MiB or GiB units. + */ + size: function( bytes ) + { + if( !bytes ) + return 'None'; + + if( bytes < KB_val ) + return bytes.toFixed(0) + ' B'; + + if( bytes < ( KB_val * 100 ) ) + return roundWithPrecision(bytes/KB_val, 2) + ' ' + KB_str; + if( bytes < MB_val ) + return roundWithPrecision(bytes/KB_val, 1) + ' ' + KB_str; + + if( bytes < ( MB_val * 100 ) ) + return roundWithPrecision(bytes/MB_val, 2) + ' ' + MB_str; + if( bytes < GB_val ) + return roundWithPrecision(bytes/MB_val, 1) + ' ' + MB_str; + + + if( bytes < ( GB_val * 100 ) ) + return roundWithPrecision(bytes/GB_val, 2) + ' ' + GB_str; + else + return roundWithPrecision(bytes/GB_val, 1) + ' ' + GB_str; + }, + + speed: function( bytes ) + { + if( !bytes ) + return 'None'; + else + return this.size( bytes ) + '/s'; + }, + + timeInterval: function( seconds ) + { + return 'Hello'; + var result; + var days = Math.floor(seconds / 86400); + var hours = Math.floor((seconds % 86400) / 3600); + var minutes = Math.floor((seconds % 3600) / 60); + var seconds = Math.floor((seconds % 3600) % 60); + + if (days > 0 && hours == 0) + result = days + ' days'; + else if (days > 0 && hours > 0) + result = days + ' days ' + hours + ' hr'; + else if (hours > 0 && minutes == 0) + result = hours + ' hr'; + else if (hours > 0 && minutes > 0) + result = hours + ' hr ' + minutes + ' min'; + else if (minutes > 0 && seconds == 0) + result = minutes + ' min'; + else if (minutes > 0 && seconds > 0) + result = minutes + ' min ' + seconds + ' seconds'; + else + result = seconds + ' seconds'; + + return result; + }, + + timestamp: function( seconds ) + { + var myDate = new Date(seconds*1000); + var now = new Date(); + + var date = ""; + var time = ""; + + var sameYear = now.getFullYear() == myDate.getFullYear(); + var sameMonth = now.getMonth() == myDate.getMonth(); + + var dateDiff = now.getDate() - myDate.getDate(); + if(sameYear && sameMonth && Math.abs(dateDiff) <= 1){ + if(dateDiff == 0){ + date = "Today"; + } + else if(dateDiff == 1){ + date = "Yesterday"; + } + else{ + date = "Tomorrow"; + } + } + else{ + date = myDate.toDateString(); + } + + var hours = myDate.getHours(); + var period = "AM"; + if(hours > 12){ + hours = hours - 12; + period = "PM"; + } + if(hours == 0){ + hours = 12; + } + if(hours < 10){ + hours = "0" + hours; + } + var minutes = myDate.getMinutes(); + if(minutes < 10){ + minutes = "0" + minutes; + } + var seconds = myDate.getSeconds(); + if(seconds < 10){ + seconds = "0" + seconds; + } + + time = [hours, minutes, seconds].join(':'); + + return [date, time, period].join(' '); + } + } +})(); diff --git a/web/javascript/torrent.js b/web/javascript/torrent.js index 6fd6bc88a..3499d3040 100644 --- a/web/javascript/torrent.js +++ b/web/javascript/torrent.js @@ -435,6 +435,13 @@ Torrent.prototype = return null; }, + formatUL: function() { + return 'UL: ' + Transmission.fmt.speed(this._upload_speed); + }, + formatDL: function() { + return 'DL: ' + Transmission.fmt.speed(this._download_speed); + }, + getPeerDetails: function() { var c; @@ -453,39 +460,33 @@ Torrent.prototype = case Torrent._StatusDownloading: if(compact_mode){ - c = 'DL: ' - c += Math.formatBytes(this._download_speed); - c += '/s UL: '; - c += Math.formatBytes(this._upload_speed); - c += '/s'; + c = this.formatDL(); + c += ' '; + c += this.formatUL(); } else { // 'Downloading from 36 of 40 peers - DL: 60.2 KiB/s UL: 4.3 KiB/s' c = 'Downloading from '; c += this.peersSendingToUs(); c += ' of '; c += this._peers_connected; - c += ' peers - DL: '; - c += Math.formatBytes(this._download_speed); - c += '/s UL: '; - c += Math.formatBytes(this._upload_speed); - c += '/s'; + c += ' peers - '; + c = this.formatDL(); + c += ' '; + c += this.formatUL(); } break; case Torrent._StatusSeeding: if(compact_mode){ - c = 'UL: ' - c += Math.formatBytes(this._upload_speed); - c += '/s'; + c += this.formatUL(); } else { // 'Seeding to 13 of 22 peers - UL: 36.2 KiB/s' c = 'Seeding to '; c += this.peersGettingFromUs(); c += ' of '; c += this._peers_connected; - c += ' peers - UL: '; - c += Math.formatBytes(this._upload_speed); - c += '/s'; + c += ' peers - '; + c += this.formatUL(); } break; @@ -555,14 +556,14 @@ Torrent.prototype = if (this._eta < 0 || this._eta >= Torrent._InfiniteTimeRemaining ) eta += 'remaining time unknown'; else - eta += Math.formatSeconds(this._eta) + ' remaining'; + eta += Transmission.fmt.timeInterval(this._eta) + ' remaining'; } // Create the 'progress details' label // Eg: '101 MiB of 631 MiB (16.02%) - 2 hr remaining' - c = Math.formatBytes( this._sizeWhenDone - this._leftUntilDone ); + c = Transmission.fmt.size( this._sizeWhenDone - this._leftUntilDone ); c += ' of '; - c += Math.formatBytes( this._sizeWhenDone ); + c += Transmission.fmt.size( this._sizeWhenDone ); c += ' ('; c += this.getPercentDoneStr(); c += '%)'; @@ -596,14 +597,14 @@ Torrent.prototype = if (this._eta < 0 || this._eta >= Torrent._InfiniteTimeRemaining ) eta += 'remaining time unknown'; else - eta += Math.formatSeconds(this._eta) + ' remaining'; + eta += Transmission.fmt.timeInterval(this._eta) + ' remaining'; } // Create the 'progress details' label // Eg: '698.05 MiB, uploaded 8.59 GiB (Ratio: 12.3)' - c = Math.formatBytes( this._size ); + c = Transmission.fmt.size( this._size ); c += ', uploaded '; - c += Math.formatBytes( this._upload_total ); + c += Transmission.fmt.size( this._upload_total ); c += ' (Ratio '; if(this._upload_ratio > -1) c += Math.round(this._upload_ratio*100)/100; @@ -957,9 +958,9 @@ TorrentFile.prototype = { }, refreshProgressHTML: function() { - var c = Math.formatBytes(this._done); + var c = Transmission.fmt.size(this._done); c += ' of '; - c += Math.formatBytes(this._size); + c += Transmission.fmt.size(this._size); c += ' ('; c += Math.ratio(100 * this._done, this._size); c += '%)'; diff --git a/web/javascript/transmission.js b/web/javascript/transmission.js index 3e3fa46dd..577b3ae81 100644 --- a/web/javascript/transmission.js +++ b/web/javascript/transmission.js @@ -881,8 +881,8 @@ Transmission.prototype = w.addClass('turtleDisabled'); t = "Click to enable Temporary Speed Limits"; } - t += " (" + this._prefs[RPC._TurtleUpSpeedLimit] + " kB/s up, " - + this._prefs[RPC._TurtleDownSpeedLimit] + " kB/s down)"; + t += " (" + Transmission.fmt.speed(this._prefs[RPC._TurtleUpSpeedLimit]) + " up, " + + Transmission.fmt.speed(this._prefs[RPC._TurtleDownSpeedLimit]) + " down)"; w.attr( 'title', t ); }, @@ -950,12 +950,12 @@ Transmission.prototype = if (!iPhone) { - setInnerHTML( $('#limited_download_rate')[0], 'Limit (' + down_limit + ' KiB/s)' ); + setInnerHTML( $('#limited_download_rate')[0], 'Limit (' + Transmission.fmt.speed(down_limit) + ')' ); var key = down_limited ? '#limited_download_rate' : '#unlimited_download_rate'; $(key).deselectMenuSiblings().selectMenuItem(); - setInnerHTML( $('#limited_upload_rate')[0], 'Limit (' + up_limit + ' KiB/s)' ); + setInnerHTML( $('#limited_download_rate')[0], 'Limit (' + Transmission.fmt.speed(up_limit) + ')' ); key = up_limited ? '#limited_upload_rate' : '#unlimited_upload_rate'; $(key).deselectMenuSiblings().selectMenuItem(); @@ -1002,15 +1002,15 @@ Transmission.prototype = var session = stats["current-stats"]; var total = stats["cumulative-stats"]; - setInnerHTML( $('#stats_session_uploaded')[0], Math.formatBytes(session["uploadedBytes"]) ); - setInnerHTML( $('#stats_session_downloaded')[0], Math.formatBytes(session["downloadedBytes"]) ); + setInnerHTML( $('#stats_session_uploaded')[0], Transmission.fmt.size(session["uploadedBytes"]) ); + setInnerHTML( $('#stats_session_downloaded')[0], Transmission.fmt.size(session["downloadedBytes"]) ); setInnerHTML( $('#stats_session_ratio')[0], Math.ratio(session["uploadedBytes"],session["downloadedBytes"])); - setInnerHTML( $('#stats_session_duration')[0], Math.formatSeconds(session["secondsActive"]) ); + setInnerHTML( $('#stats_session_duration')[0], Transmission.fmt.timeInterval(session["secondsActive"]) ); setInnerHTML( $('#stats_total_count')[0], total["sessionCount"] + " times" ); - setInnerHTML( $('#stats_total_uploaded')[0], Math.formatBytes(total["uploadedBytes"]) ); - setInnerHTML( $('#stats_total_downloaded')[0], Math.formatBytes(total["downloadedBytes"]) ); + setInnerHTML( $('#stats_total_uploaded')[0], Transmission.fmt.size(total["uploadedBytes"]) ); + setInnerHTML( $('#stats_total_downloaded')[0], Transmission.fmt.size(total["downloadedBytes"]) ); setInnerHTML( $('#stats_total_ratio')[0], Math.ratio(total["uploadedBytes"],total["downloadedBytes"])); - setInnerHTML( $('#stats_total_duration')[0], Math.formatSeconds(total["secondsActive"]) ); + setInnerHTML( $('#stats_total_duration')[0], Transmission.fmt.timeInterval(total["secondsActive"]) ); }, setSearch: function( search ) { @@ -1069,7 +1069,7 @@ Transmission.prototype = $element.deselectMenuSiblings().selectMenuItem(); args[RPC._DownSpeedLimited] = false; } else { - setInnerHTML( $('#limited_download_rate')[0], 'Limit (' + rate + ' KiB/s)' ); + setInnerHTML( $('#limited_download_rate')[0], 'Limit (' + Transmission.fmt.speed(rate) + ')' ); $('#limited_download_rate').deselectMenuSiblings().selectMenuItem(); $('div.preference input#download_rate')[0].value = rate; args[RPC._DownSpeedLimit] = parseInt( rate ); @@ -1087,7 +1087,7 @@ Transmission.prototype = $element.deselectMenuSiblings().selectMenuItem(); args[RPC._UpSpeedLimited] = false; } else { - setInnerHTML( $('#limited_upload_rate')[0], 'Limit (' + rate + ' KiB/s)' ); + setInnerHTML( $('#limited_upload_rate')[0], 'Limit (' + Transmission.fmt.speed(rate) + ')' ); $('#limited_upload_rate').deselectMenuSiblings().selectMenuItem(); $('div.preference input#upload_rate')[0].value = rate; args[RPC._UpSpeedLimit] = parseInt( rate ); @@ -1153,7 +1153,7 @@ Transmission.prototype = var comment = 'N/A'; var download_dir = 'N/A'; var date_created = 'N/A'; - var error = ''; + var error = 'None'; var hash = 'N/A'; var have_public = false; var have_private = false; @@ -1226,8 +1226,8 @@ Transmission.prototype = download_dir = t._download_dir; hash = t.hash(); - pieces = t._pieceCount + ', ' + Math.formatBytes(t._pieceSize); - date_created = Math.formatTimestamp( t._creator_date ); + pieces = t._pieceCount + ', ' + Transmission.fmt.size(t._pieceSize); + date_created = Transmission.fmt.timestamp( t._creator_date ); } for( var i=0, t; t=torrents[i]; ++i ) { @@ -1259,17 +1259,17 @@ Transmission.prototype = else if( have_public ) private_string = 'Public Torrent'; setInnerHTML( tab.name, name ); - setInnerHTML( tab.size, torrents.length ? Math.formatBytes( total_size ) : na ); + setInnerHTML( tab.size, torrents.length ? Transmission.fmt.size( 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.download_speed, torrents.length ? Transmission.fmt.speed( total_download_speed ) : na ); + setInnerHTML( tab.upload_speed, torrents.length ? Transmission.fmt.speed( total_upload_speed ) : na ); + setInnerHTML( tab.uploaded, torrents.length ? Transmission.fmt.size( total_upload ) : na ); + setInnerHTML( tab.downloaded, torrents.length ? Transmission.fmt.size( total_download ) : na ); setInnerHTML( tab.availability, torrents.length ? Math.ratio( total_availability*100, sizeWhenDone ) + '%' : 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.have, torrents.length ? Transmission.fmt.size(total_completed) + ' (' + Transmission.fmt.size(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 ); @@ -1325,8 +1325,8 @@ Transmission.prototype = var parity = ((i+1) % 2 == 0 ? 'even' : 'odd'); html += ''; html += '' + (peer.isEncrypted ? 'Encrypted' : '') + ''; - html += '' + (peer.rateToPeer ? Math.formatBytes(peer.rateToPeer) + '/s' : '') + ''; - html += '' + (peer.rateToClient ? Math.formatBytes(peer.rateToClient) + '/s' : '') + ''; + html += '' + Transmission.fmt.speed(peer.rateToPeer) + ''; + html += '' + Transmission.fmt.speed(peer.rateToClient) + ''; html += '' + Math.floor(peer.progress*100) + '%' + ''; html += '' + peer.flagStr + ''; html += '' + peer.address + ''; @@ -1378,7 +1378,7 @@ Transmission.prototype = var lastAnnounceLabel = 'Last Announce'; var lastAnnounce = 'N/A'; if (tracker.hasAnnounced) { - var lastAnnounceTime = Math.formatTimestamp(tracker.lastAnnounceTime); + var lastAnnounceTime = Transmission.fmt.timestamp(tracker.lastAnnounceTime); if (tracker.lastAnnounceSucceeded) { lastAnnounce = lastAnnounceTime; lastAnnounce += ' (got ' + tracker.lastAnnouncePeerCount + ' peer'; @@ -1403,7 +1403,7 @@ Transmission.prototype = if(timeUntilAnnounce < 0){ timeUntilAnnounce = 0; } - announceState = 'Next announce in ' + Math.formatSeconds(timeUntilAnnounce); + announceState = 'Next announce in ' + Transmission.fmt.timeInterval(timeUntilAnnounce); break; case Torrent._TrackerQueued: announceState = 'Announce is queued'; @@ -1423,7 +1423,7 @@ Transmission.prototype = var lastScrapeLabel = 'Last Scrape'; var lastScrape = 'N/A'; if (tracker.hasScraped) { - var lastScrapeTime = Math.formatTimestamp(tracker.lastScrapeTime); + var lastScrapeTime = Transmission.fmt.timestamp(tracker.lastScrapeTime); if (tracker.lastScrapeSucceeded) { lastScrape = lastScrapeTime; } else { @@ -1685,12 +1685,12 @@ Transmission.prototype = setInnerHTML( $('#torrent_global_transfer')[0], s ); // update the speeds - s = Math.formatBytes( upSpeed ) + '/s'; + s = Transmission.fmt.speed( upSpeed ); if( iPhone ) s = 'UL: ' + s; setInnerHTML( $('#torrent_global_upload')[0], s ); // download speeds - s = Math.formatBytes( downSpeed ) + '/s'; + s = Transmission.fmt.speed( downSpeed ); if( iPhone ) s = 'DL: ' + s; setInnerHTML( $('#torrent_global_download')[0], s ); },