| BachusII on Jul 22, 2005 at 3:45:11 AM (# 2) Hmmm, tough one. IE only, or cross browser? BachusII on Jul 22, 2005 at 4:02:20 AM (# 3) This message has been edited.Excerpt from chris's source code challenge. var x = document.body.appendChild( document.createElement( 'div' ) ); x.addBehavior( '#default#download' ); x.startDownload( wtf.src, function(){} );
wtf.src is ofcourse replaced with a string containing the location of your file.
My thinking is that this way the file already is in the cache. Especially if you replace that anonymous function with one unblocking or showing the link to the file. (i.e. Downloading is only allowed/possible after it is completely loaded.) And a xmlhttprequest to inform the server of the proceedings ofcourse. The user may not have time to hit the cancel button. BachusII on Jul 22, 2005 at 4:13:53 AM (# 4) This message has been edited.This may help if Firefox should be supported too. function ScriptDownloader(url) { var dm = Components.classes["@mozilla.org/download-manager;1"].getService(Components.interfaces.nsIDownloadManager) var ioservice = Components.classes["@mozilla.org/network/io-service;1"].getService(); var sourceUri = ioservice.newURI(url, null, null); var targetFile = getTempFile(); var targetUri = ioservice.newFileURI(targetFile) var persist = makeWebBrowserPersist(); var sysListener = null; var download = null; var self = this; var timerId = null;
this.start = function() { try { dm.addDownload(0, sourceUri, targetUri, parseScriptName(sourceUri), null, null, null, persist) dm.open(window._content, targetFile.path)
download = dm.getDownload(targetFile.path); download.persist = persist;
persist.saveURI(sourceUri, null, null, null, null, targetFile);
// this seems like a huge hack, but it was actually the most reliable // way I could find to determine when downloading is complete timerId = window.setInterval(checkLoad, 200); } catch (e) { handleErrors(e); } }
function checkLoad() { // if the download is complete, stop. if (download.percentComplete == 100) { window.clearInterval(timerId); handleLoad(); } // if not complete yet, double-check that somebody hasn't cancelled it else if (dm.getDownload(targetFile.path) == null) { // the download is no longer active window.clearInterval(timerId); return; } // otherwise, do nothing. downloading continues. }
function handleLoad() { closeDownloadManager();
// validate that we downloaded ok if (!targetFile.exists() || targetFile.fileSize == 0) { alert("The file does not exist or was removed."); return; }
// initialize a new script object var script = new Script(); script.filename = targetFile.leafName; script.enabled = true; script.includes = []; script.excludes = [];
// crack open the file so we can look for metadata in the comments var fileStream = getLineStream(targetFile);
// read one line at a time looking for start meta delimiter or EOF var lineStream = fileStream.QueryInterface(Components.interfaces.nsILineInputStream); var result = {}; var foundMeta = false;
while (lineStream.readLine(result)) { if (result.value.indexOf("// ==UserScript==") == 0) { foundMeta = true; break; } }
// gather up meta lines if (foundMeta) { while (lineStream.readLine(result)) { if (result.value.indexOf("// ==/UserScript==") == 0) { break; }
var match = result.value.match(/\/\/ \@(\S+)\s+([^\n]+)/); if (match != null) { switch (match[1]) { case "name": case "namespace": case "description": script[match[1]] = match[2]; break; case "include": case "exclude": script[match[1]+"s"].push(match[2]); break; } } } }
fileStream.close();
// if no meta info, default to reasonable values if (script.name == null) { script.name = parseScriptName(sourceUri); }
if (script.namespace == null) { script.namespace = sourceUri.host; }
if (script.includes.length == 0) { script.includes.push("*"); }
// open install dialog var result = {}; window.openDialog("chrome://greasemonkey/content/install.xul", "manager", "resizable,centerscreen,modal", script, targetFile, result);
closeDownloadManager();
if (result.value) { alert("Success! Refresh page to see changes."); } }
function handleErrors(e) { //todo: need to handle this somehow. perhaps nsIUriChecker? //if (e.name == "NS_ERROR_FILE_NOT_FOUND") { // alert("User script could not be found. Please check the name and try again."); // window.status = defaultStatus; //} //else { alert("Could not download user script\n\n" + e.toString()); //} }
function closeDownloadManager() { var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator); var en = wm.getEnumerator(""); var n = 0; var dlm = null; while (en.hasMoreElements()) { var w = en.getNext();
if (w.location.href == "chrome://mozapps/content/downloads/downloads.xul") { dlm = w; break; } }
if (dlm != null) { dlm.close(); } } }
swjs on Jul 22, 2005 at 4:14:18 AM (# 5)Hi Bachusll,
I'm glad you think so - I thought I was being a real dumb @rs€.
For the moment it is IE only.
I have played a little now with the Modal window approach, but I think this is bad news coz the run-save-cancel dialog does not want to appear. I seem to recall there is a problem modals launching other window objects. swjs on Jul 22, 2005 at 9:21:36 AM (# 6)Hi Bachusll,
Im not completely with you!
Any chance you could put it simpleton terms for me. I'm having a thick day.
Sorry. BachusII on Jul 22, 2005 at 2:11:41 PM (# 7) This message has been edited.I'll try. - Page load, the link/button/whatever to download the file is not available. Be that hidden, disabled, not displayed, etc.
- On page load, in the background start downloading the file. By way of an adaptation of the script in #2 for example.
(AFAIC tell the startDownload function takes two parameters. The url and a callback funtion.) - As the download completes, the callback function sends a message back to the server. (by xmlhttprequest for example)
And makes the link/button to the file available to the user. - User clicks on the link/button to start downloading the file. (Not knowing the file is already cached.)
- Because the file presumably is in the cache (depending on the users cache settings ofcourse) the time needed is virtually nill. Giving the user no, or as little as possible, time to do something stupid like hitting cancel.
Jack Turk on Aug 3, 2005 at 5:59:01 PM (# 8)Take a look at:
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/css/reference/css_ref_entry.asp and click on behaviour.
There's a call back function for when download is complete. Not sure about cross browser support though...
|