home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / mozil06.zip / bin / chrome / toolkit.jar / content / global / downloadProgress.js < prev    next >
Text File  |  2001-03-23  |  12KB  |  362 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "License"); you may not use this file except in
  5.  * compliance with the License.  You may obtain a copy of the License at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  10.  * for the specific language governing rights and limitations under the
  11.  * License.
  12.  *
  13.  * The Original Code is Mozilla Communicator client code, 
  14.  * released March 31, 1998. 
  15.  *
  16.  * The Initial Developer of the Original Code is Netscape Communications 
  17.  * Corporation.  Portions created by Netscape are 
  18.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  19.  * Reserved.
  20.  *
  21.  * Contributors:
  22.  *     William A. ("PowerGUI") Law <law@netscape.com>
  23.  */
  24. var data;   // nsIStreamTransferOperation object
  25. var dialog;
  26.  
  27. function loadDialog() {
  28.     dialog.location.setAttribute( "value", data.source.URI.spec );
  29.     var filePicker = Components.classes["@mozilla.org/filepicker;1"].createInstance();
  30.     if (filePicker != null) {
  31.       filePicker = filePicker.QueryInterface( Components.interfaces.nsIFilePicker);
  32.       if (filePicker != null) {
  33.         var outvalue = {};
  34.         filePicker.convertfromfscharset(data.target.nativePath, outvalue);
  35.         dialog.fileName.setAttribute( "value", outvalue.value );
  36.       }
  37.     }
  38.     if (filePicker == null)
  39.       dialog.fileName.setAttribute( "value", data.target.nativePath );
  40. }
  41.  
  42. var contractId = "@mozilla.org/appshell/component/xfer;1";
  43. var observer = {
  44.     Observe: function( subject, topic, data ) {
  45.         switch ( topic ) {
  46.             case contractId+";onProgress":
  47.                 var words = data.split( " " );
  48.                 onProgress( words[0], words[1] );
  49.                 break;
  50.             case contractId+";onStatus":
  51.                 // Ignore useless "Transferring data..." messages
  52.                 // after download has started.
  53.                 if ( !started ) {
  54.                    onStatus( data );
  55.                 }
  56.                 break;
  57.             case contractId+";onCompletion":
  58.                 onCompletion( data );
  59.                 break;
  60.             case contractId+";onError":
  61.                 onError( data );
  62.                 break;
  63.             default:
  64.                 alert( "Unknown topic: " + topic + "\nData: " + data );
  65.                 break;
  66.         }
  67.         return;
  68.     }
  69. }
  70.  
  71. function getString( stringId ) {
  72.    // Check if we've fetched this string already.
  73.    if ( !dialog.strings[ stringId ] ) {
  74.       // Try to get it.
  75.       var elem = document.getElementById( "dialog.strings."+stringId );
  76.       if ( elem
  77.            &&
  78.            elem.childNodes
  79.            &&
  80.            elem.childNodes[0]
  81.            &&
  82.            elem.childNodes[0].nodeValue ) {
  83.          dialog.strings[ stringId ] = elem.childNodes[0].nodeValue;
  84.       } else {
  85.          // If unable to fetch string, use an empty string.
  86.          dialog.strings[ stringId ] = "";
  87.       }
  88.    }
  89.    return dialog.strings[ stringId ];
  90. }
  91.  
  92. function replaceInsert( text, index, value ) {
  93.    var result = text;
  94.    var regExp = eval( "/#"+index+"/" );
  95.    result = result.replace( regExp, value );
  96.    return result;
  97. }
  98.  
  99. function onLoad() {
  100.     // Set global variables.
  101.     data = window.arguments[0];
  102.     if ( !data ) {
  103.         dump( "Invalid argument to downloadProgress.xul\n" );
  104.         window.close()
  105.         return;
  106.     }
  107.  
  108.     dialog = new Object;
  109.     dialog.strings = new Array;
  110.     dialog.location    = document.getElementById("dialog.location");
  111.     dialog.contentType = document.getElementById("dialog.contentType");
  112.     dialog.fileName    = document.getElementById("dialog.fileName");
  113.     dialog.status      = document.getElementById("dialog.status");
  114.     dialog.progress    = document.getElementById("dialog.progress");
  115.     dialog.timeLeft    = document.getElementById("dialog.timeLeft");
  116.     dialog.timeElapsed = document.getElementById("dialog.timeElapsed");
  117.     dialog.cancel      = document.getElementById("dialog.cancel");
  118.  
  119.     // Fill dialog.
  120.     loadDialog();
  121.  
  122.     // Commence transfer.
  123.     data.observer = observer;
  124.     data.Start();
  125. }
  126.  
  127. function onUnload() {
  128.     // Unhook observer.
  129.     data.observer = null;
  130.  
  131.     // See if we completed normally (i.e., are closing ourself).
  132.     if ( !completed ) {
  133.         // Terminate transfer.
  134.         data.Stop();
  135.     }
  136. }
  137.  
  138. var started   = false;
  139. var completed = false;
  140. var startTime;
  141. var elapsed;
  142. var interval = 1000; // Update every 1000 milliseconds.
  143. var lastUpdate = -interval; // Update initially.
  144.  
  145. // These are to throttle down the updating of the download rate figure.
  146. var priorRate = 0;
  147. var rateChanges = 0;
  148. var rateChangeLimit = 2;
  149.  
  150. var warningLimit = 30000; // Warn on Cancel after 30 sec (30000 milleseconds).
  151.  
  152. function stop() {
  153.    // If too much time has elapsed, make sure it's OK to quit.
  154.    if ( started ) {
  155.       // Get current time.
  156.       var now = ( new Date() ).getTime();
  157.    
  158.       // See if sufficient time has elapsed to warrant dialog.
  159.       if ( now - startTime > warningLimit ) {
  160.          // XXX - Disabled for now since confirm call doesn't work.
  161.          if ( 0 && !window.confirm( getString( "confirmCancel" ) ) ) {
  162.             return;
  163.          }
  164.       }
  165.    }
  166.  
  167.    // Stop the transfer.
  168.    data.Stop();
  169.  
  170.    // Close the window.
  171.    window.close();
  172. }
  173.  
  174. function onProgress( bytes, max ) {
  175.     // Check for first time.
  176.     if ( !started ) {
  177.         // Initialize download start time.
  178.         started = true;
  179.         startTime = ( new Date() ).getTime();
  180.     }
  181.  
  182.     // Get current time.
  183.     var now = ( new Date() ).getTime();
  184.     // If interval hasn't elapsed, ignore it.
  185.     if ( now - lastUpdate < interval
  186.          &&
  187.          max != "-1"
  188.          &&
  189.          eval(bytes) < eval(max) ) {
  190.         return;
  191.     }
  192.  
  193.     // Update this time.
  194.     lastUpdate = now;
  195.  
  196.     // Update download rate.
  197.     elapsed = now - startTime;
  198.     var rate; // bytes/sec
  199.     if ( elapsed ) {
  200.         rate = ( bytes * 1000 ) / elapsed;
  201.     } else {
  202.         rate = 0;
  203.     }
  204.  
  205.     // Update elapsed time display.
  206.     dialog.timeElapsed.setAttribute("value", formatSeconds( elapsed / 1000 ));
  207.  
  208.     // Calculate percentage.
  209.     var percent;
  210.     if ( max != "-1" ) {
  211.         percent = parseInt( (bytes*100)/max + .5 );
  212.         if ( percent > 100 ) {
  213.            percent = 100;
  214.         }
  215.  
  216.         // Advance progress meter.
  217.         dialog.progress.setAttribute( "value", percent );
  218.     } else {
  219.         percent = "??";
  220.  
  221.         // Progress meter should be barber-pole in this case.
  222.         dialog.progress.setAttribute( "mode", "undetermined" );
  223.     }
  224.  
  225.     // Check if download complete.
  226.     if ( !completed ) {
  227.         // Update status (nnK of mmK bytes at xx.xK bytes/sec)
  228.         var status = getString( "progressMsg" );
  229.  
  230.         // Insert 1 is the number of kilobytes downloaded so far.
  231.         status = replaceInsert( status, 1, parseInt( bytes/1024 + .5 ) );
  232.  
  233.         // Insert 2 is the total number of kilobytes to be downloaded (if known).
  234.         if ( max != "-1" ) {
  235.            status = replaceInsert( status, 2, parseInt( max/1024 + .5 ) );
  236.         } else {
  237.            status = replaceInsert( status, 2, "??" );
  238.         }
  239.  
  240.         if ( rate ) {
  241.            // rate is bytes/sec
  242.            var kRate = rate / 1024; // K bytes/sec;
  243.            kRate = parseInt( kRate * 10 + .5 ); // xxx (3 digits)
  244.            // Don't update too often!
  245.            if ( kRate != priorRate ) {
  246.               if ( rateChanges++ == rateChangeLimit ) {
  247.                  // Time to update download rate.
  248.                  priorRate = kRate;
  249.                  rateChanges = 0;
  250.               } else {
  251.                  // Stick with old rate for a bit longer.
  252.                  kRate = priorRate;
  253.               }
  254.            } else {
  255.               rateChanges = 0;
  256.            }
  257.            var fraction = kRate % 10;
  258.            kRate = parseInt( ( kRate - fraction ) / 10 );
  259.  
  260.            // Insert 3 is the download rate (in kilobytes/sec).
  261.            status = replaceInsert( status, 3, kRate + "." + fraction );
  262.         } else {
  263.            status = replaceInsert( status, 3, "??.?" );
  264.         }
  265.         // Update status msg.
  266.         onStatus( status );
  267.     }
  268.  
  269.     // Update percentage label on progress meter.
  270.     var percentMsg = getString( "percentMsg" );
  271.     percentMsg = replaceInsert( percentMsg, 1, percent );
  272.     dialog.progress.progresstext = percentMsg;
  273.     
  274.     if ( !completed ) {
  275.         // Update time remaining.
  276.         if ( rate && max != "-1" ) {
  277.             var rem = ( max - bytes ) / rate;
  278.             rem = parseInt( rem + .5 );
  279.             dialog.timeLeft.setAttribute("value", formatSeconds( rem ));
  280.         } else {
  281.             dialog.timeLeft.setAttribute("value", getString( "unknownTime" ));
  282.         }
  283.     } else {
  284.         // Clear time remaining field.
  285.         dialog.timeLeft.setAttribute("value", "");
  286.     }
  287. }
  288.  
  289. function formatSeconds( secs ) {
  290.     // Round the number of seconds to remove fractions.
  291.     secs = parseInt( secs + .5 );
  292.     var hours = parseInt( secs/3600 );
  293.     secs -= hours*3600;
  294.     var mins = parseInt( secs/60 );
  295.     secs -= mins*60;
  296.     var result;
  297.     if ( hours ) {
  298.       result = getString( "longTimeFormat" );
  299.     } else {
  300.       result = getString( "shortTimeFormat" );
  301.     }
  302.     if ( hours < 10 ) {
  303.        hours = "0" + hours;
  304.     }
  305.     if ( mins < 10 ) {
  306.        mins = "0" + mins;
  307.     }
  308.     if ( secs < 10 ) {
  309.        secs = "0" + secs;
  310.     }
  311.     // Insert hours, minutes, and seconds into result string.
  312.     result = replaceInsert( result, 1, hours );
  313.     result = replaceInsert( result, 2, mins );
  314.     result = replaceInsert( result, 3, secs );
  315.  
  316.     return result;
  317. }
  318.  
  319. function onCompletion( status ) {
  320.     // Note that we're done (and can ignore subsequent progress notifications).
  321.     completed = true;
  322.     // Indicate completion in status area.
  323.     var msg = getString( "completeMsg" );
  324.     msg = replaceInsert( msg, 1, formatSeconds( elapsed/1000 ) );
  325.     onStatus( msg );
  326.  
  327.     // Put progress meter at 100%.
  328.     dialog.progress.setAttribute( "value", 100 );
  329.     dialog.progress.setAttribute( "mode", "normal" );
  330.     try {
  331.         // Close the window in 2 seconds (to ensure user sees we're done).
  332.         window.setTimeout( "window.close();", 2000 );
  333.     } catch ( exception ) {
  334.         dump( "Error setting close timeout\n" );
  335.         // OK, try to just close the window immediately.
  336.         window.close();
  337.         // If that's not working either, change button text to give user a clue.
  338.         dialog.cancel.childNodes[0].nodeValue = "Close";
  339.     }
  340. }
  341.  
  342. function onStatus( status ) {
  343.    // Update status text in dialog.
  344.    // Ignore if status text is less than 10 characters (we're getting some
  345.    // bogus onStatus notifications.
  346.    if ( status.length > 9 ) {
  347.       dialog.status.setAttribute("value", status);
  348.    }
  349. }
  350.  
  351. function onError( errorCode ) {
  352.     // XXX - l10n
  353.     var msg = "Unknown error";
  354.     switch ( errorCode ) {
  355.         default:
  356.             msg += " [" + errorCode + "]\n";
  357.             break;
  358.     }
  359.     alert( msg );
  360.     window.close();
  361. }
  362.