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