Merge pull request #1841 from cycomachead/fix-downloads

Fix Issues for Exporting Files
upd4.1
Jens Mönig 2017-09-19 08:57:19 +02:00 zatwierdzone przez GitHub
commit 643cf9072f
5 zmienionych plików z 35 dodań i 82 usunięć

2
FileSaver.min.js vendored
Wyświetl plik

@ -1,2 +1,2 @@
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs=saveAs||function(e){"use strict";if(typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),i="download"in r,o=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},a=/Version\/[\d\.]+.*Safari/.test(navigator.userAgent),f=e.webkitRequestFileSystem,u=e.requestFileSystem||f||e.mozRequestFileSystem,s=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},c="application/octet-stream",d=0,l=500,w=function(t){var r=function(){if(typeof t==="string"){n().revokeObjectURL(t)}else{t.remove()}};if(e.chrome){r()}else{setTimeout(r,l)}},p=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var i=e["on"+t[r]];if(typeof i==="function"){try{i.call(e,n||e)}catch(o){s(o)}}}},v=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob(["\ufeff",e],{type:e.type})}return e},y=function(t,s,l){if(!l){t=v(t)}var y=this,m=t.type,S=false,h,R,O=function(){p(y,"writestart progress write writeend".split(" "))},g=function(){if(R&&a&&typeof FileReader!=="undefined"){var r=new FileReader;r.onloadend=function(){var e=r.result;R.location.href="data:attachment/file"+e.slice(e.search(/[,;]/));y.readyState=y.DONE;O()};r.readAsDataURL(t);y.readyState=y.INIT;return}if(S||!h){h=n().createObjectURL(t)}if(R){R.location.href=h}else{var i=e.open(h,"_blank");if(i==undefined&&a){e.location.href=h}}y.readyState=y.DONE;O();w(h)},b=function(e){return function(){if(y.readyState!==y.DONE){return e.apply(this,arguments)}}},E={create:true,exclusive:false},N;y.readyState=y.INIT;if(!s){s="download"}if(i){h=n().createObjectURL(t);r.href=h;r.download=s;setTimeout(function(){o(r);O();w(h);y.readyState=y.DONE});return}if(e.chrome&&m&&m!==c){N=t.slice||t.webkitSlice;t=N.call(t,0,t.size,c);S=true}if(f&&s!=="download"){s+=".download"}if(m===c||f){R=e}if(!u){g();return}d+=t.size;u(e.TEMPORARY,d,b(function(e){e.root.getDirectory("saved",E,b(function(e){var n=function(){e.getFile(s,E,b(function(e){e.createWriter(b(function(n){n.onwriteend=function(t){R.location.href=e.toURL();y.readyState=y.DONE;p(y,"writeend",t);w(e)};n.onerror=function(){var e=n.error;if(e.code!==e.ABORT_ERR){g()}};"writestart progress write abort".split(" ").forEach(function(e){n["on"+e]=y["on"+e]});n.write(t);y.abort=function(){n.abort();y.readyState=y.DONE};y.readyState=y.WRITING}),g)}),g)};e.getFile(s,{create:false},b(function(e){e.remove();n()}),b(function(e){if(e.code===e.NOT_FOUND_ERR){n()}else{g()}}))}),g)}),g)},m=y.prototype,S=function(e,t,n){return new y(e,t,n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){if(!n){e=v(e)}return navigator.msSaveOrOpenBlob(e,t||"download")}}m.abort=function(){var e=this;e.readyState=e.DONE;p(e,"abort")};m.readyState=m.INIT=0;m.WRITING=1;m.DONE=2;m.error=m.onwritestart=m.onprogress=m.onwrite=m.onabort=m.onerror=m.onwriteend=null;return S}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!=null){define([],function(){return saveAs})} var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",d=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,d)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(a){u(a)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,d){if(!d){t=p(t)}var v=this,w=t.type,m=w===s,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&&i)&&e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var n=e.open(t,"_blank");if(!n)e.location.href=t;t=undefined;v.readyState=v.DONE;h()};r.readAsDataURL(t);v.readyState=v.INIT;return}if(!y){y=n().createObjectURL(t)}if(m){e.location.href=y}else{var o=e.open(y,"_blank");if(!o){e.location.href=y}}v.readyState=v.DONE;h();c(y)};v.readyState=v.INIT;if(o){y=n().createObjectURL(t);setTimeout(function(){r.href=y;r.download=u;a(r);h();c(y);v.readyState=v.DONE});return}S()},w=v.prototype,m=function(e,t,n){return new v(e,t||e.name||"download",n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){t=t||e.name||"download";if(!n){e=p(e)}return navigator.msSaveOrOpenBlob(e,t)}}w.abort=function(){};w.readyState=w.INIT=0;w.WRITING=1;w.DONE=2;w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null;return m}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!==null){define("FileSaver.js",function(){return saveAs})}

Wyświetl plik

@ -1982,7 +1982,7 @@ SyntaxElementMorph.prototype.exportPictureWithResult = function (aBubble) {
// request to open pic in new window. // request to open pic in new window.
ide.saveCanvasAs( ide.saveCanvasAs(
pic, pic,
(ide.projetName || localize('untitled')) + ' ' + localize('script pic') (ide.projectName || localize('untitled')) + ' ' + localize('script pic')
); );
}; };
@ -2583,9 +2583,8 @@ BlockMorph.prototype.userMenu = function () {
); );
ide.saveCanvasAs( ide.saveCanvasAs(
myself.topBlock().scriptPic(), myself.topBlock().scriptPic(),
(ide.projetName || localize('untitled')) + ' ' + (ide.projectName || localize('untitled')) + ' ' +
localize('script pic'), localize('script pic')
false // request new window
); );
}, },
'open a new window\nwith a picture of this script' 'open a new window\nwith a picture of this script'
@ -6382,9 +6381,8 @@ ScriptsMorph.prototype.exportScriptsPicture = function () {
if (pic) { if (pic) {
ide.saveCanvasAs( ide.saveCanvasAs(
pic, pic,
(ide.projetName || localize('untitled')) + ' ' + (ide.projectName || localize('untitled')) + ' ' +
localize('script pic'), localize('script pic')
false // request new window
); );
} }
}; };
@ -11734,9 +11732,8 @@ CommentMorph.prototype.userMenu = function () {
var ide = myself.parentThatIsA(IDE_Morph); var ide = myself.parentThatIsA(IDE_Morph);
ide.saveCanvasAs( ide.saveCanvasAs(
myself.fullImageClassic(), myself.fullImageClassic(),
(ide.projetName || localize('untitled')) + ' ' + (ide.projectName || localize('untitled')) + ' ' +
localize('comment pic'), localize('comment pic')
false // request new window
); );
}, },
'open a new window\nwith a picture of this comment' 'open a new window\nwith a picture of this comment'

Wyświetl plik

@ -941,8 +941,7 @@ CustomCommandBlockMorph.prototype.userMenu = function () {
ide.saveCanvasAs( ide.saveCanvasAs(
this.topBlock().scriptPic(), this.topBlock().scriptPic(),
(ide.projectName || localize('untitled')) + ' ' + (ide.projectName || localize('untitled')) + ' ' +
localize('script pic'), localize('script pic')
false // request opening a new window
); );
}, },
'open a new window\nwith a picture of this script' 'open a new window\nwith a picture of this script'

86
gui.js
Wyświetl plik

@ -889,7 +889,7 @@ IDE_Morph.prototype.createControlBar = function () {
} }
this.refreshResumeSymbol(); this.refreshResumeSymbol();
}; };
this.controlBar.refreshResumeSymbol = function () { this.controlBar.refreshResumeSymbol = function () {
var pauseSymbols; var pauseSymbols;
if (Process.prototype.enableSingleStepping && if (Process.prototype.enableSingleStepping &&
@ -2945,8 +2945,7 @@ IDE_Morph.prototype.projectMenu = function () {
} else { } else {
myself.prompt('Export Project As...', function (name) { myself.prompt('Export Project As...', function (name) {
// false - override the shiftClick setting to use XML // false - override the shiftClick setting to use XML
// true - open XML in a new tab myself.exportProject(name, false);
myself.exportProject(name, false, true);
}, null, 'exportProject'); }, null, 'exportProject');
} }
}, },
@ -3584,7 +3583,7 @@ IDE_Morph.prototype.rawSaveProject = function (name) {
}; };
IDE_Morph.prototype.exportProject = function (name, plain, newWindow) { IDE_Morph.prototype.exportProject = function (name, plain) {
// Export project XML, saving a file to disk // Export project XML, saving a file to disk
// newWindow requests displaying the project in a new tab. // newWindow requests displaying the project in a new tab.
var menu, str, dataPrefix; var menu, str, dataPrefix;
@ -3596,7 +3595,7 @@ IDE_Morph.prototype.exportProject = function (name, plain, newWindow) {
menu = this.showMessage('Exporting'); menu = this.showMessage('Exporting');
str = this.serializer.serialize(this.stage); str = this.serializer.serialize(this.stage);
this.setURL('#open:' + dataPrefix + encodeURIComponent(str)); this.setURL('#open:' + dataPrefix + encodeURIComponent(str));
this.saveXMLAs(str, name, newWindow); this.saveXMLAs(str, name);
menu.destroy(); menu.destroy();
this.showMessage('Exported!', 1); this.showMessage('Exported!', 1);
} catch (err) { } catch (err) {
@ -3720,7 +3719,7 @@ IDE_Morph.prototype.exportScriptsPicture = function () {
y += padding; y += padding;
y += each.height; y += each.height;
}); });
this.saveCanvasAs(pic, this.projectName || localize('untitled'), true); this.saveCanvasAs(pic, this.projectName || localize('Untitled'));
}; };
IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) { IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
@ -4000,8 +3999,7 @@ IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
this.saveFileAs( this.saveFileAs(
'<!DOCTYPE html>' + html.toString(), '<!DOCTYPE html>' + html.toString(),
'text/html;charset=utf-8', 'text/html;charset=utf-8',
pname, pname
false // request opening a new window.
); );
}; };
@ -4215,15 +4213,11 @@ IDE_Morph.prototype.setURL = function (str) {
IDE_Morph.prototype.saveFileAs = function ( IDE_Morph.prototype.saveFileAs = function (
contents, contents,
fileType, fileType,
fileName, fileName
newWindow // (optional) defaults to false.
) { ) {
/** Allow for downloading a file to a disk or open in a new tab. /** Allow for downloading a file to a disk.
This relies the FileSaver.js library which exports saveAs() This relies the FileSaver.js library which exports saveAs()
Two utility methods saveImageAs and saveXMLAs should be used first. Two utility methods saveImageAs and saveXMLAs should be used first.
1. Opening a new window uses standard URI encoding.
2. downloading a file uses Blobs.
- every other combo is unsupposed.
*/ */
var blobIsSupported = false, var blobIsSupported = false,
world = this.world(), world = this.world(),
@ -4235,13 +4229,6 @@ IDE_Morph.prototype.saveFileAs = function (
// handle text/plain as a .txt file // handle text/plain as a .txt file
fileExt = '.' + (fileExt === 'plain' ? 'txt' : fileExt); fileExt = '.' + (fileExt === 'plain' ? 'txt' : fileExt);
// This is a workaround for a known Chrome crash with large URLs
function exhibitsChomeBug(contents) {
var MAX_LENGTH = 2e6,
isChrome = navigator.userAgent.indexOf('Chrome') !== -1;
return isChrome && contents.length > MAX_LENGTH;
}
function dataURItoBlob(text, mimeType) { function dataURItoBlob(text, mimeType) {
var i, var i,
data = text, data = text,
@ -4259,37 +4246,11 @@ IDE_Morph.prototype.saveFileAs = function (
return new Blob([data], {type: mimeType }); return new Blob([data], {type: mimeType });
} }
function dataURLFormat(text) {
var hasTypeStr = text.indexOf('data:') === 0;
if (hasTypeStr) {return text; }
return 'data:' + fileType + ',' + encodeURIComponent(text);
}
try { try {
blobIsSupported = !!new Blob(); blobIsSupported = !!new Blob();
} catch (e) {} } catch (e) {}
if (newWindow) { if (blobIsSupported) {
// Blob URIs need a custom URL to be displayed in a new window
if (contents instanceof Blob) {
dataURI = URL.createObjectURL(contents);
} else {
dataURI = dataURLFormat(contents);
}
// Detect crashing errors - fallback to downloading if necessary
if (!exhibitsChomeBug(dataURI)) {
window.open(dataURI, fileName);
// Blob URIs should be "cleaned up" to reduce memory.
if (contents instanceof Blob) {
URL.revokeObjectURL(dataURI);
}
} else {
// (recursively) call this defauling newWindow to false
this.showMessage('download to disk text');
this.saveFileAs(contents, fileType, fileName);
}
} else if (blobIsSupported) {
if (!(contents instanceof Blob)) { if (!(contents instanceof Blob)) {
contents = dataURItoBlob(contents, fileType); contents = dataURItoBlob(contents, fileType);
} }
@ -4308,26 +4269,26 @@ IDE_Morph.prototype.saveFileAs = function (
} }
}; };
IDE_Morph.prototype.saveCanvasAs = function (canvas, fileName, newWindow) { IDE_Morph.prototype.saveCanvasAs = function (canvas, fileName) {
// Export a Canvas object as a PNG image // Export a Canvas object as a PNG image
// Note: This commented out due to poor browser support. // Note: This commented out due to poor browser support.
// cavas.toBlob() is currently supported in Firefox, IE, Chrome but // cavas.toBlob() is currently supported in Firefox, IE, Chrome but
// browsers prevent easily saving the generated files. // browsers prevent easily saving the generated files.
// Do not re-enable without revisiting issue #1191 // Do not re-enable without revisiting issue #1191
// if (canvas.toBlob) { // if (canvas.toBlob) {
// var myself = this; // var myself = this;
// canvas.toBlob(function (blob) { // canvas.toBlob(function (blob) {
// myself.saveFileAs(blob, 'image/png', fileName, newWindow); // myself.saveFileAs(blob, 'image/png', fileName);
// }); // });
// return; // return;
// } // }
this.saveFileAs(canvas.toDataURL(), 'image/png', fileName, newWindow); this.saveFileAs(canvas.toDataURL(), 'image/png', fileName);
}; };
IDE_Morph.prototype.saveXMLAs = function(xml, fileName, newWindow) { IDE_Morph.prototype.saveXMLAs = function(xml, fileName) {
// wrapper to saving XML files with a proper type tag. // wrapper to saving XML files with a proper type tag.
this.saveFileAs(xml, 'text/xml;chartset=utf-8', fileName, newWindow); this.saveFileAs(xml, 'text/xml;chartset=utf-8', fileName);
}; };
IDE_Morph.prototype.switchToUserMode = function () { IDE_Morph.prototype.switchToUserMode = function () {
@ -5728,7 +5689,7 @@ ProjectDialogMorph.prototype.buildFilterField = function () {
this.filterField.reactToKeystroke = function (evt) { this.filterField.reactToKeystroke = function (evt) {
var text = this.getValue(); var text = this.getValue();
myself.listField.elements = myself.listField.elements =
myself.projectList.filter(function (aProject) { myself.projectList.filter(function (aProject) {
var name, var name,
notes; notes;
@ -6356,7 +6317,7 @@ ProjectDialogMorph.prototype.fixLayout = function () {
// LibraryImportDialogMorph /////////////////////////////////////////// // LibraryImportDialogMorph ///////////////////////////////////////////
// I am preview dialog shown before importing a library. // I am preview dialog shown before importing a library.
// I inherit from a DialogMorph but look similar to // I inherit from a DialogMorph but look similar to
// ProjectDialogMorph, and BlockImportDialogMorph // ProjectDialogMorph, and BlockImportDialogMorph
LibraryImportDialogMorph.prototype = new DialogBoxMorph(); LibraryImportDialogMorph.prototype = new DialogBoxMorph();
@ -6591,7 +6552,7 @@ LibraryImportDialogMorph.prototype.fixLayout = function () {
Morph.prototype.trackChanges = oldFlag; Morph.prototype.trackChanges = oldFlag;
this.changed(); this.changed();
}; };
// Library Cache Utilities. // Library Cache Utilities.
LibraryImportDialogMorph.prototype.hasCached = function (key) { LibraryImportDialogMorph.prototype.hasCached = function (key) {
return this.libraryCache.hasOwnProperty(key); return this.libraryCache.hasOwnProperty(key);
@ -6918,8 +6879,7 @@ SpriteIconMorph.prototype.userMenu = function () {
var ide = myself.parentThatIsA(IDE_Morph); var ide = myself.parentThatIsA(IDE_Morph);
ide.saveCanvasAs( ide.saveCanvasAs(
myself.object.fullImageClassic(), myself.object.fullImageClassic(),
this.object.name, this.object.name
true
); );
}, },
'open a new window\nwith a picture of the stage' 'open a new window\nwith a picture of the stage'
@ -7322,7 +7282,7 @@ CostumeIconMorph.prototype.exportCostume = function () {
// don't show SVG costumes in a new tab (shows text) // don't show SVG costumes in a new tab (shows text)
ide.saveFileAs(this.object.contents.src, 'text/svg', this.object.name); ide.saveFileAs(this.object.contents.src, 'text/svg', this.object.name);
} else { // rasterized Costume } else { // rasterized Costume
ide.saveCanvasAs(this.object.contents, this.object.name, false); ide.saveCanvasAs(this.object.contents, this.object.name);
} }
}; };
@ -8347,7 +8307,7 @@ PaletteHandleMorph.prototype.mouseEnter
PaletteHandleMorph.prototype.mouseLeave PaletteHandleMorph.prototype.mouseLeave
= StageHandleMorph.prototype.mouseLeave; = StageHandleMorph.prototype.mouseLeave;
PaletteHandleMorph.prototype.mouseDoubleClick = function () { PaletteHandleMorph.prototype.mouseDoubleClick = function () {
this.target.parentThatIsA(IDE_Morph).setPaletteWidth(200); this.target.parentThatIsA(IDE_Morph).setPaletteWidth(200);
}; };
@ -8447,7 +8407,7 @@ CamSnapshotDialogMorph.prototype.buildContents = function () {
this.addButton('ok', 'Save'); this.addButton('ok', 'Save');
this.addButton('cancel', 'Cancel'); this.addButton('cancel', 'Cancel');
this.fixLayout(); this.fixLayout();
this.drawNew(); this.drawNew();
}; };

Wyświetl plik

@ -7248,8 +7248,7 @@ StageMorph.prototype.userMenu = function () {
function () { function () {
ide.saveCanvasAs( ide.saveCanvasAs(
myself.fullImageClassic(), myself.fullImageClassic(),
myself.name, myself.name
true // open as new window
); );
}, },
'open a new window\nwith a picture of the stage' 'open a new window\nwith a picture of the stage'
@ -9335,8 +9334,7 @@ WatcherMorph.prototype.userMenu = function () {
inp.click(); inp.click();
} }
); );
if (this.currentValue && if (isString(this.currentValue) || !isNaN(+this.currentValue)) {
(isString(this.currentValue) || !isNaN(+this.currentValue))) {
menu.addItem( menu.addItem(
'export...', 'export...',
function () { function () {
@ -9344,8 +9342,7 @@ WatcherMorph.prototype.userMenu = function () {
ide.saveFileAs( ide.saveFileAs(
myself.currentValue.toString(), myself.currentValue.toString(),
'text/plain;charset=utf-8', 'text/plain;charset=utf-8',
myself.getter, // variable name myself.getter // variable name
false
); );
} }
); );