kopia lustrzana https://github.com/backface/turtlestitch
commit
99784ca436
|
|
@ -0,0 +1,2 @@
|
|||
/*! @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})}
|
||||
36
blocks.js
36
blocks.js
|
|
@ -1855,7 +1855,8 @@ SyntaxElementMorph.prototype.showBubble = function (value, exportPic) {
|
|||
};
|
||||
|
||||
SyntaxElementMorph.prototype.exportPictureWithResult = function (aBubble) {
|
||||
var scr = this.fullImage(),
|
||||
var ide = this.parentThatIsA(IDE_Morph),
|
||||
scr = this.fullImage(),
|
||||
bub = aBubble.fullImageClassic(),
|
||||
taller = Math.max(0, bub.height - scr.height),
|
||||
pic = newCanvas(new Point(
|
||||
|
|
@ -1865,7 +1866,12 @@ SyntaxElementMorph.prototype.exportPictureWithResult = function (aBubble) {
|
|||
ctx = pic.getContext('2d');
|
||||
ctx.drawImage(scr, 0, pic.height - scr.height);
|
||||
ctx.drawImage(bub, scr.width + 2, 0);
|
||||
window.open(pic.toDataURL());
|
||||
// request to open pic in new window.
|
||||
ide.saveCanvasAs(
|
||||
pic,
|
||||
ide.projetName || localize('Untitled') + ' ' + localize('script pic'),
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
// SyntaxElementMorph code mapping
|
||||
|
|
@ -2332,7 +2338,13 @@ BlockMorph.prototype.userMenu = function () {
|
|||
menu.addItem(
|
||||
"script pic...",
|
||||
function () {
|
||||
window.open(myself.topBlock().scriptPic().toDataURL());
|
||||
var ide = myself.parentThatIsA(IDE_Morph);
|
||||
ide.saveCanvasAs(
|
||||
myself.topBlock().scriptPic(),
|
||||
ide.projetName || localize('Untitled') + ' ' +
|
||||
localize('script pic'),
|
||||
true // request new window
|
||||
);
|
||||
},
|
||||
'open a new window\nwith a picture of this script'
|
||||
);
|
||||
|
|
@ -5489,9 +5501,15 @@ ScriptsMorph.prototype.cleanUp = function () {
|
|||
};
|
||||
|
||||
ScriptsMorph.prototype.exportScriptsPicture = function () {
|
||||
var pic = this.scriptsPicture();
|
||||
var pic = this.scriptsPicture(),
|
||||
ide = this.world().children[0];
|
||||
if (pic) {
|
||||
window.open(pic.toDataURL());
|
||||
ide.saveCanvasAs(
|
||||
pic,
|
||||
ide.projetName || localize('Untitled') + ' ' +
|
||||
localize('script pic'),
|
||||
true // request new window
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -11166,7 +11184,13 @@ CommentMorph.prototype.userMenu = function () {
|
|||
menu.addItem(
|
||||
"comment pic...",
|
||||
function () {
|
||||
window.open(myself.fullImageClassic().toDataURL());
|
||||
var ide = myself.parentThatIsA(IDE_Morph);
|
||||
ide.saveCanvasAs(
|
||||
myself.fullImageClassic(),
|
||||
ide.projetName || localize('Untitled') + ' ' +
|
||||
localize('comment pic'),
|
||||
true // request new window
|
||||
);
|
||||
},
|
||||
'open a new window\nwith a picture of this comment'
|
||||
);
|
||||
|
|
|
|||
28
byob.js
28
byob.js
|
|
@ -821,7 +821,13 @@ CustomCommandBlockMorph.prototype.userMenu = function () {
|
|||
menu.addItem(
|
||||
"script pic...",
|
||||
function () {
|
||||
window.open(this.topBlock().scriptPic().toDataURL());
|
||||
var ide = this.world().children[0];
|
||||
ide.saveCanvasAs(
|
||||
this.topBlock().scriptPic(),
|
||||
ide.projectName || localize('Untitled') + ' ' +
|
||||
localize('script pic'),
|
||||
true // request opening a new window
|
||||
);
|
||||
},
|
||||
'open a new window\nwith a picture of this script'
|
||||
);
|
||||
|
|
@ -862,8 +868,10 @@ CustomCommandBlockMorph.prototype.userMenu = function () {
|
|||
};
|
||||
|
||||
CustomCommandBlockMorph.prototype.exportBlockDefinition = function () {
|
||||
var xml = new SnapSerializer().serialize(this.definition);
|
||||
window.open('data:text/xml,' + encodeURIComponent(xml));
|
||||
var xml = new SnapSerializer().serialize(this.definition),
|
||||
ide = this.parentThatIsA(IDE_Morph);
|
||||
|
||||
ide.saveXMLAs(xml, this.spec);
|
||||
};
|
||||
|
||||
CustomCommandBlockMorph.prototype.deleteBlockDefinition = function () {
|
||||
|
|
@ -3497,17 +3505,21 @@ BlockExportDialogMorph.prototype.selectNone = function () {
|
|||
// BlockExportDialogMorph ops
|
||||
|
||||
BlockExportDialogMorph.prototype.exportBlocks = function () {
|
||||
var str = encodeURIComponent(
|
||||
this.serializer.serialize(this.blocks)
|
||||
);
|
||||
var str = this.serializer.serialize(this.blocks),
|
||||
ide = this.world().children[0];
|
||||
|
||||
if (this.blocks.length > 0) {
|
||||
window.open('data:text/xml,<blocks app="'
|
||||
str = '<blocks app="'
|
||||
+ this.serializer.app
|
||||
+ '" version="'
|
||||
+ this.serializer.version
|
||||
+ '">'
|
||||
+ str
|
||||
+ '</blocks>');
|
||||
+ '</blocks>';
|
||||
ide.saveXMLAs(
|
||||
str,
|
||||
ide.projectName || localize('Untitled') + ' ' + localize('blocks')
|
||||
);
|
||||
} else {
|
||||
new DialogBoxMorph().inform(
|
||||
'Export blocks',
|
||||
|
|
|
|||
371
gui.js
371
gui.js
|
|
@ -67,7 +67,7 @@ BlockImportDialogMorph, SnapTranslator, localize, List, InputSlotMorph,
|
|||
SnapCloud, Uint8Array, HandleMorph, SVG_Costume, fontHeight, hex_sha512,
|
||||
sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph, Audio,
|
||||
SpeechBubbleMorph, ScriptFocusMorph, XML_Element, WatcherMorph,
|
||||
BlockRemovalDialogMorph*/
|
||||
BlockRemovalDialogMorph, saveAs*/
|
||||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -85,7 +85,6 @@ var SoundIconMorph;
|
|||
var JukeboxMorph;
|
||||
var StageHandleMorph;
|
||||
|
||||
|
||||
// IDE_Morph ///////////////////////////////////////////////////////////
|
||||
|
||||
// I am SNAP's top-level frame, the Editor window
|
||||
|
|
@ -2519,15 +2518,6 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
menu.addItem('New', 'createNewProject');
|
||||
menu.addItem('Open...', 'openProjectsBrowser');
|
||||
menu.addItem('Save', "save");
|
||||
if (shiftClicked) {
|
||||
menu.addItem(
|
||||
'Save to disk',
|
||||
'saveProjectToDisk',
|
||||
'store this project\nin the downloads folder\n'
|
||||
+ '(in supporting browsers)',
|
||||
new Color(100, 0, 0)
|
||||
);
|
||||
}
|
||||
menu.addItem('Save As...', 'saveProjectsBrowser');
|
||||
menu.addLine();
|
||||
menu.addItem(
|
||||
|
|
@ -2564,6 +2554,24 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
'file menu import hint' // looks up the actual text in the translator
|
||||
);
|
||||
|
||||
if (shiftClicked) {
|
||||
menu.addItem(
|
||||
localize('Export project...') + ' ' + localize('(in a new window)'),
|
||||
function () {
|
||||
if (myself.projectName) {
|
||||
myself.exportProject(myself.projectName, shiftClicked);
|
||||
} else {
|
||||
myself.prompt('Export Project As...', function (name) {
|
||||
// false - override the shiftClick setting to use XML
|
||||
// true - open XML in a new tab
|
||||
myself.exportProject(name, false, true);
|
||||
}, null, 'exportProject');
|
||||
}
|
||||
},
|
||||
'show project data as XML\nin a new browser window',
|
||||
new Color(100, 0, 0)
|
||||
);
|
||||
}
|
||||
menu.addItem(
|
||||
shiftClicked ?
|
||||
'Export project as plain text...' : 'Export project...',
|
||||
|
|
@ -2572,11 +2580,11 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
myself.exportProject(myself.projectName, shiftClicked);
|
||||
} else {
|
||||
myself.prompt('Export Project As...', function (name) {
|
||||
myself.exportProject(name);
|
||||
myself.exportProject(name, shiftClicked);
|
||||
}, null, 'exportProject');
|
||||
}
|
||||
},
|
||||
'show project data as XML\nin a new browser window',
|
||||
'save project data as XML\nto your downloads folder',
|
||||
shiftClicked ? new Color(100, 0, 0) : null
|
||||
);
|
||||
|
||||
|
|
@ -2606,7 +2614,7 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
'Export summary with drop-shadows...',
|
||||
function () {myself.exportProjectSummary(true); },
|
||||
'open a new browser browser window' +
|
||||
'\n with a summary of this project' +
|
||||
'\nwith a summary of this project' +
|
||||
'\nwith drop-shadows on all pictures.' +
|
||||
'\nnot supported by all browsers',
|
||||
new Color(100, 0, 0)
|
||||
|
|
@ -2984,7 +2992,6 @@ IDE_Morph.prototype.save = function () {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
IDE_Morph.prototype.saveProject = function (name) {
|
||||
var myself = this;
|
||||
this.nextSteps([
|
||||
|
|
@ -2997,6 +3004,7 @@ IDE_Morph.prototype.saveProject = function (name) {
|
|||
]);
|
||||
};
|
||||
|
||||
// Serialize a project and save to the browser.
|
||||
IDE_Morph.prototype.rawSaveProject = function (name) {
|
||||
var str;
|
||||
if (name) {
|
||||
|
|
@ -3019,104 +3027,28 @@ IDE_Morph.prototype.rawSaveProject = function (name) {
|
|||
}
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.saveProjectToDisk = function () {
|
||||
var data,
|
||||
link = document.createElement('a');
|
||||
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
data = this.serializer.serialize(this.stage);
|
||||
link.setAttribute('href', 'data:text/xml,' + data);
|
||||
link.setAttribute('download', this.projectName + '.xml');
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
} catch (err) {
|
||||
this.showMessage('Saving failed: ' + err);
|
||||
}
|
||||
} else {
|
||||
data = this.serializer.serialize(this.stage);
|
||||
link.setAttribute('href', 'data:text/xml,' + data);
|
||||
link.setAttribute('download', this.projectName + '.xml');
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
};
|
||||
IDE_Morph.prototype.exportProject = function (name, plain, newWindow) {
|
||||
// Export project XML, saving a file to disk
|
||||
// newWindow requests displaying the project in a new tab.
|
||||
var menu, str, dataPrefix;
|
||||
|
||||
/* alternative download mechanism, commented out in favor of blob-uris
|
||||
IDE_Morph.prototype.saveProjectToDisk = function () {
|
||||
var data;
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
data = this.serializer.serialize(this.stage);
|
||||
} catch (err) {
|
||||
this.showMessage('Serialization failed: ' + err);
|
||||
}
|
||||
} else {
|
||||
data = this.serializer.serialize(this.stage);
|
||||
}
|
||||
this.download(data, this.projectName);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.download = function (data, fileName, mime, suffix) {
|
||||
var link = document.createElement('a'),
|
||||
myself = this;
|
||||
|
||||
mime = mime || 'data:text/xml';
|
||||
fileName = fileName || 'download';
|
||||
suffix = suffix || 'xml';
|
||||
|
||||
function saveToDisk() {
|
||||
var msg = myself.showMessage('Downloading to disk...');
|
||||
link.setAttribute('href', mime + ',' + data);
|
||||
link.setAttribute('download', fileName + '.' + suffix);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
msg.destroy();
|
||||
}
|
||||
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
saveToDisk();
|
||||
} catch (err) {
|
||||
this.showMessage('Saving failed: ' + err);
|
||||
}
|
||||
} else {
|
||||
saveToDisk();
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
IDE_Morph.prototype.exportProject = function (name, plain) {
|
||||
var menu, str;
|
||||
if (name) {
|
||||
this.setProjectName(name);
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
menu = this.showMessage('Exporting');
|
||||
str = encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
this.setURL('#open:' + str);
|
||||
window.open('data:text/'
|
||||
+ (plain ? 'plain,' + str : 'xml,' + str));
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
} catch (err) {
|
||||
this.showMessage('Export failed: ' + err);
|
||||
}
|
||||
} else {
|
||||
dataPrefix = 'data:text/' + plain ? 'plain,' : 'xml,';
|
||||
try {
|
||||
menu = this.showMessage('Exporting');
|
||||
str = encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
this.setURL('#open:' + str);
|
||||
window.open('data:text/'
|
||||
+ (plain ? 'plain,' + str : 'xml,' + str));
|
||||
str = this.serializer.serialize(this.stage)
|
||||
this.setURL('#open:' + dataPrefix + encodeURIComponent(str));
|
||||
this.saveXMLAs(str, name, newWindow);
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
} catch (err) {
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
this.showMessage('Export failed: ' + err);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -3175,16 +3107,15 @@ IDE_Morph.prototype.removeUnusedBlocks = function () {
|
|||
};
|
||||
|
||||
IDE_Morph.prototype.exportSprite = function (sprite) {
|
||||
var str = encodeURIComponent(
|
||||
this.serializer.serialize(sprite.allParts())
|
||||
);
|
||||
window.open('data:text/xml,<sprites app="'
|
||||
var str = this.serializer.serialize(sprite.allParts());
|
||||
str = '<sprites app="'
|
||||
+ this.serializer.app
|
||||
+ '" version="'
|
||||
+ this.serializer.version
|
||||
+ '">'
|
||||
+ str
|
||||
+ '</sprites>');
|
||||
+ '</sprites>';
|
||||
this.saveXMLAs(str, sprite.name);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.exportScriptsPicture = function () {
|
||||
|
|
@ -3233,8 +3164,7 @@ IDE_Morph.prototype.exportScriptsPicture = function () {
|
|||
y += padding;
|
||||
y += each.height;
|
||||
});
|
||||
|
||||
window.open(pic.toDataURL());
|
||||
this.saveCanvasAs(pic, this.projectName || localize('Untitled'), true);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
|
||||
|
|
@ -3511,9 +3441,12 @@ IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
|
|||
addBlocks(stage.globalBlocks);
|
||||
}
|
||||
|
||||
window.open('data:text/html;charset=utf-8,' + encodeURIComponent(
|
||||
'<!DOCTYPE html>' + html.toString()
|
||||
));
|
||||
this.saveFileAs(
|
||||
'<!DOCTYPE html>' + html.toString(),
|
||||
'text/html;charset=utf-8,',
|
||||
pname,
|
||||
true // request opening a new window.
|
||||
);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.openProjectString = function (str) {
|
||||
|
|
@ -3713,11 +3646,126 @@ IDE_Morph.prototype.openProject = function (name) {
|
|||
};
|
||||
|
||||
IDE_Morph.prototype.setURL = function (str) {
|
||||
// Set the URL to a project's XML contents
|
||||
if (this.projectsInURLs) {
|
||||
location.hash = str;
|
||||
}
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.saveFileAs = function (
|
||||
contents,
|
||||
fileType,
|
||||
fileName,
|
||||
newWindow // (optional) defaults to false.
|
||||
) {
|
||||
/** Allow for downloading a file to a disk or open in a new tab.
|
||||
This relies the FileSaver.js library which exports saveAs()
|
||||
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,
|
||||
world = this.world(),
|
||||
fileExt,
|
||||
dataURI, dialog;
|
||||
|
||||
// fileType is a <kind>/<ext>;<charset> format.
|
||||
fileExt = fileType.split('/')[1].split(';')[0];
|
||||
// handle text/plain as a .txt file
|
||||
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) {
|
||||
var i,
|
||||
data = text,
|
||||
components = text.split(','),
|
||||
hasTypeStr = text.indexOf('data:') === 0;
|
||||
// Convert to binary data, in format Blob() can use.
|
||||
if (hasTypeStr && components[0].indexOf('base64') > -1) {
|
||||
text = atob(components[1]);
|
||||
data = new Uint8Array(text.length),
|
||||
i = text.length;
|
||||
while (i--) {
|
||||
data[i] = text.charCodeAt(i);
|
||||
}
|
||||
}
|
||||
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 {
|
||||
blobIsSupported = !!new Blob;
|
||||
} catch (e) {}
|
||||
|
||||
if (newWindow) {
|
||||
// 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)) {
|
||||
contents = dataURItoBlob(contents, fileType);
|
||||
}
|
||||
// download a file and delegate to FileSaver
|
||||
// false: Do not preprend a BOM to the file.
|
||||
saveAs(contents, fileName + fileExt, false);
|
||||
} else {
|
||||
dialog = new DialogBoxMorph();
|
||||
dialog.inform(
|
||||
localize('Could not export') + ' ' + fileName,
|
||||
'unable to export text',
|
||||
world
|
||||
);
|
||||
dialog.fixLayout();
|
||||
dialog.drawNew();
|
||||
}
|
||||
}
|
||||
|
||||
IDE_Morph.prototype.saveCanvasAs = function (canvas, fileName, newWindow) {
|
||||
// Export a Canvas object as a PNG image
|
||||
// cavas.toBlob() is currently only supported in Firefox and IE
|
||||
var myself = this;
|
||||
if (canvas.toBlob) {
|
||||
canvas.toBlob(function (blob) {
|
||||
myself.saveFileAs(blob, 'image/png', fileName, newWindow);
|
||||
});
|
||||
} else {
|
||||
this.saveFileAs(canvas.toDataURL(), 'image/png', fileName, newWindow);
|
||||
}
|
||||
}
|
||||
|
||||
IDE_Morph.prototype.saveXMLAs = function(xml, fileName, newWindow) {
|
||||
// wrapper to saving XML files with a proper type tag.
|
||||
this.saveFileAs(xml, 'text/xml;chartset=utf-8', fileName, newWindow);
|
||||
}
|
||||
|
||||
IDE_Morph.prototype.switchToUserMode = function () {
|
||||
var world = this.world();
|
||||
|
||||
|
|
@ -4487,33 +4535,19 @@ IDE_Morph.prototype.exportProjectMedia = function (name) {
|
|||
this.serializer.isCollectingMedia = true;
|
||||
if (name) {
|
||||
this.setProjectName(name);
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
menu = this.showMessage('Exporting');
|
||||
encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
media = encodeURIComponent(
|
||||
this.serializer.mediaXML(name)
|
||||
);
|
||||
window.open('data:text/xml,' + media);
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
} catch (err) {
|
||||
this.serializer.isCollectingMedia = false;
|
||||
this.showMessage('Export failed: ' + err);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
menu = this.showMessage('Exporting');
|
||||
encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
media = encodeURIComponent(
|
||||
this.serializer.mediaXML()
|
||||
);
|
||||
window.open('data:text/xml,' + media);
|
||||
media = this.serializer.mediaXML(name);
|
||||
this.saveXMLAs(media, this.projectName + ' media');
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
} catch (err) {
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
this.serializer.isCollectingMedia = false;
|
||||
this.showMessage('Export failed: ' + err);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.serializer.isCollectingMedia = false;
|
||||
|
|
@ -4529,10 +4563,8 @@ IDE_Morph.prototype.exportProjectNoMedia = function (name) {
|
|||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
menu = this.showMessage('Exporting');
|
||||
str = encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
window.open('data:text/xml,' + str);
|
||||
str = this.serializer.serialize(this.stage);
|
||||
this.saveXMLAs(str, this.projectName);
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
} catch (err) {
|
||||
|
|
@ -4541,10 +4573,8 @@ IDE_Morph.prototype.exportProjectNoMedia = function (name) {
|
|||
}
|
||||
} else {
|
||||
menu = this.showMessage('Exporting');
|
||||
str = encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
window.open('data:text/xml,' + str);
|
||||
str = this.serializer.serialize(this.stage);
|
||||
this.saveXMLAs(str, this.projectName);
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
}
|
||||
|
|
@ -4561,17 +4591,10 @@ IDE_Morph.prototype.exportProjectAsCloudData = function (name) {
|
|||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
menu = this.showMessage('Exporting');
|
||||
str = encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
media = encodeURIComponent(
|
||||
this.serializer.mediaXML(name)
|
||||
);
|
||||
dta = encodeURIComponent('<snapdata>')
|
||||
+ str
|
||||
+ media
|
||||
+ encodeURIComponent('</snapdata>');
|
||||
window.open('data:text/xml,' + dta);
|
||||
str = this.serializer.serialize(this.stage);
|
||||
media = this.serializer.mediaXML(name);
|
||||
dta = '<snapdata>' + str + media + '</snapdata>';
|
||||
this.saveXMLAs(str, this.projectName);
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
} catch (err) {
|
||||
|
|
@ -4580,17 +4603,10 @@ IDE_Morph.prototype.exportProjectAsCloudData = function (name) {
|
|||
}
|
||||
} else {
|
||||
menu = this.showMessage('Exporting');
|
||||
str = encodeURIComponent(
|
||||
this.serializer.serialize(this.stage)
|
||||
);
|
||||
media = encodeURIComponent(
|
||||
this.serializer.mediaXML()
|
||||
);
|
||||
dta = encodeURIComponent('<snapdata>')
|
||||
+ str
|
||||
+ media
|
||||
+ encodeURIComponent('</snapdata>');
|
||||
window.open('data:text/xml,' + dta);
|
||||
str = this.serializer.serialize(this.stage);
|
||||
media = this.serializer.mediaXML(name);
|
||||
dta = '<snapdata>' + str + media + '</snapdata>';
|
||||
this.saveXMLAs(str, this.projectName);
|
||||
menu.destroy();
|
||||
this.showMessage('Exported!', 1);
|
||||
}
|
||||
|
|
@ -5908,7 +5924,12 @@ SpriteIconMorph.prototype.userMenu = function () {
|
|||
menu.addItem(
|
||||
'pic...',
|
||||
function () {
|
||||
window.open(myself.object.fullImageClassic().toDataURL());
|
||||
var ide = myself.parentThatIsA(IDE_Morph);
|
||||
ide.saveCanvasAs(
|
||||
myself.object.fullImageClassic(),
|
||||
this.object.name,
|
||||
true
|
||||
);
|
||||
},
|
||||
'open a new window\nwith a picture of the stage'
|
||||
);
|
||||
|
|
@ -6269,10 +6290,12 @@ CostumeIconMorph.prototype.removeCostume = function () {
|
|||
};
|
||||
|
||||
CostumeIconMorph.prototype.exportCostume = function () {
|
||||
var ide = this.parentThatIsA(IDE_Morph);
|
||||
if (this.object instanceof SVG_Costume) {
|
||||
window.open(this.object.contents.src);
|
||||
} else { // rastered Costume
|
||||
window.open(this.object.contents.toDataURL());
|
||||
// don't show SVG costumes in a new tab (shows text)
|
||||
ide.saveFileAs(this.object.contents.src, 'text/svg', this.object.name);
|
||||
} else { // rasterized Costume
|
||||
ide.saveCanvasAs(this.object.object.contents, this.object.name, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
10
locale.js
10
locale.js
|
|
@ -141,7 +141,15 @@ SnapTranslator.dict.en = {
|
|||
+ 'a file on your computer by dropping it here\n',
|
||||
'block deletion dialog text':
|
||||
'Are you sure you want to delete this\n'
|
||||
+ 'custom block and all its instances?'
|
||||
+ 'custom block and all its instances?',
|
||||
'download to disk text':
|
||||
'This item could not be opened in a new tab.\n' +
|
||||
'It has been saved to your browser\'s downloads folder.',
|
||||
'unable to export text':
|
||||
'This item could not be exported from Snap!.\n' +
|
||||
'It\'s likely that your project may contain a lot of media ' +
|
||||
'(sounds and images) or that you are using an older browser.' +
|
||||
'Please try using a recent version of Chrome, Firefox, or Safari.'
|
||||
};
|
||||
|
||||
SnapTranslator.dict.de = {
|
||||
|
|
|
|||
16
objects.js
16
objects.js
|
|
@ -589,7 +589,7 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
},
|
||||
|
||||
/* migrated to a newer block version:
|
||||
|
||||
|
||||
receiveClick: {
|
||||
type: 'hat',
|
||||
category: 'control',
|
||||
|
|
@ -5839,7 +5839,11 @@ StageMorph.prototype.userMenu = function () {
|
|||
menu.addItem(
|
||||
"pic...",
|
||||
function () {
|
||||
window.open(myself.fullImageClassic().toDataURL());
|
||||
ide.saveCanvasAs(
|
||||
myself.fullImageClassic(),
|
||||
myself.name,
|
||||
true // open as new window
|
||||
);
|
||||
},
|
||||
'open a new window\nwith a picture of the stage'
|
||||
);
|
||||
|
|
@ -7729,9 +7733,11 @@ WatcherMorph.prototype.userMenu = function () {
|
|||
menu.addItem(
|
||||
'export...',
|
||||
function () {
|
||||
window.open(
|
||||
'data:text/plain;charset=utf-8,' +
|
||||
encodeURIComponent(this.currentValue.toString())
|
||||
var ide = myself.parentThatIsA(IDE_Morph);
|
||||
ide.saveFileAs(
|
||||
myself.currentValue.toString(),
|
||||
'text/plain;charset=utf-8',
|
||||
myself.getter // variable name
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
<script type="text/javascript" src="locale.js"></script>
|
||||
<script type="text/javascript" src="cloud.js"></script>
|
||||
<script type="text/javascript" src="sha512.js"></script>
|
||||
<script type="text/javascript" src="FileSaver.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var world;
|
||||
window.onload = function () {
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue