kopia lustrzana https://github.com/backface/turtlestitch
automatically parse csv files on import
also: experimental "raw data" and "parse" opspull/89/head
rodzic
3848932955
commit
6c5a0b9c88
|
@ -1,6 +1,8 @@
|
||||||
# Snap<em>!</em> (BYOB) History
|
# Snap<em>!</em> (BYOB) History
|
||||||
|
|
||||||
## in development
|
## in development
|
||||||
|
### 2019-01-08
|
||||||
|
* Objects: automatically parse csv files on import, experimental "raw data" and "parse" ops
|
||||||
|
|
||||||
### 2019-01-07
|
### 2019-01-07
|
||||||
* Lists, Objects: directly export and import lists as csv files, under construction
|
* Lists, Objects: directly export and import lists as csv files, under construction
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<script type="text/javascript" src="src/widgets.js?version=2018-10-02"></script>
|
<script type="text/javascript" src="src/widgets.js?version=2018-10-02"></script>
|
||||||
<script type="text/javascript" src="src/blocks.js?version=2019-01-04"></script>
|
<script type="text/javascript" src="src/blocks.js?version=2019-01-04"></script>
|
||||||
<script type="text/javascript" src="src/threads.js?version=2019-01-04"></script>
|
<script type="text/javascript" src="src/threads.js?version=2019-01-04"></script>
|
||||||
<script type="text/javascript" src="src/objects.js?version=2019-01-07"></script>
|
<script type="text/javascript" src="src/objects.js?version=2019-01-08"></script>
|
||||||
<script type="text/javascript" src="src/gui.js?version=2019-01-02"></script>
|
<script type="text/javascript" src="src/gui.js?version=2019-01-02"></script>
|
||||||
<script type="text/javascript" src="src/paint.js?version=2018-10-02"></script>
|
<script type="text/javascript" src="src/paint.js?version=2018-10-02"></script>
|
||||||
<script type="text/javascript" src="src/lists.js?version=2019-01-07"></script>
|
<script type="text/javascript" src="src/lists.js?version=2019-01-07"></script>
|
||||||
|
|
217
src/objects.js
217
src/objects.js
|
@ -83,7 +83,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
|
||||||
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph,
|
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph,
|
||||||
AlignmentMorph, Process, XML_Element, VectorPaintEditorMorph*/
|
AlignmentMorph, Process, XML_Element, VectorPaintEditorMorph*/
|
||||||
|
|
||||||
modules.objects = '2019-January-07';
|
modules.objects = '2019-January-08';
|
||||||
|
|
||||||
var SpriteMorph;
|
var SpriteMorph;
|
||||||
var StageMorph;
|
var StageMorph;
|
||||||
|
@ -9457,6 +9457,7 @@ WatcherMorph.prototype.mouseClickLeft = function () {
|
||||||
WatcherMorph.prototype.userMenu = function () {
|
WatcherMorph.prototype.userMenu = function () {
|
||||||
var myself = this,
|
var myself = this,
|
||||||
ide = this.parentThatIsA(IDE_Morph),
|
ide = this.parentThatIsA(IDE_Morph),
|
||||||
|
shiftClicked = (this.world().currentKey === 16),
|
||||||
menu = new MenuMorph(this),
|
menu = new MenuMorph(this),
|
||||||
on = '\u25CF',
|
on = '\u25CF',
|
||||||
off = '\u25CB',
|
off = '\u25CB',
|
||||||
|
@ -9528,101 +9529,25 @@ WatcherMorph.prototype.userMenu = function () {
|
||||||
menu.addLine();
|
menu.addLine();
|
||||||
menu.addItem(
|
menu.addItem(
|
||||||
'import...',
|
'import...',
|
||||||
function () {
|
'importData'
|
||||||
var inp = document.createElement('input'),
|
|
||||||
ide = myself.parentThatIsA(IDE_Morph);
|
|
||||||
if (ide.filePicker) {
|
|
||||||
document.body.removeChild(ide.filePicker);
|
|
||||||
ide.filePicker = null;
|
|
||||||
}
|
|
||||||
inp.type = 'file';
|
|
||||||
inp.style.color = "transparent";
|
|
||||||
inp.style.backgroundColor = "transparent";
|
|
||||||
inp.style.border = "none";
|
|
||||||
inp.style.outline = "none";
|
|
||||||
inp.style.position = "absolute";
|
|
||||||
inp.style.top = "0px";
|
|
||||||
inp.style.left = "0px";
|
|
||||||
inp.style.width = "0px";
|
|
||||||
inp.style.height = "0px";
|
|
||||||
inp.style.display = "none";
|
|
||||||
inp.addEventListener(
|
|
||||||
"change",
|
|
||||||
function () {
|
|
||||||
var file;
|
|
||||||
|
|
||||||
function txtOnlyMsg(ftype, anyway) {
|
|
||||||
ide.confirm(
|
|
||||||
localize(
|
|
||||||
'Snap! can only import "text" files.\n' +
|
|
||||||
'You selected a file of type "' +
|
|
||||||
ftype +
|
|
||||||
'".'
|
|
||||||
) + '\n\n' + localize('Open anyway?'),
|
|
||||||
'Unable to import',
|
|
||||||
anyway // callback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function readText(aFile) {
|
|
||||||
var frd = new FileReader();
|
|
||||||
frd.onloadend = function (e) {
|
|
||||||
// +++ needs to be refactored
|
|
||||||
if (aFile.type.indexOf("csv") ||
|
|
||||||
aFile.name.split('.').pop()
|
|
||||||
.toLowerCase() === 'csv') {
|
|
||||||
// catch parsing errors
|
|
||||||
myself.target.setVar(
|
|
||||||
myself.getter,
|
|
||||||
Process.prototype.parseCSV(
|
|
||||||
e.target.result
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
myself.target.setVar(
|
|
||||||
myself.getter,
|
|
||||||
e.target.result
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (aFile.type.indexOf("text") === -1) {
|
|
||||||
// special cases for Windows
|
|
||||||
// check the file extension for text-like-ness
|
|
||||||
if (contains(
|
|
||||||
// +++ avoid doubling
|
|
||||||
['txt', 'csv', 'xml', 'json', 'tsv'],
|
|
||||||
aFile.name.split('.').pop().toLowerCase()
|
|
||||||
)) {
|
|
||||||
frd.readAsText(aFile);
|
|
||||||
} else {
|
|
||||||
// show a warning and an option
|
|
||||||
// letting the user load the file anyway
|
|
||||||
txtOnlyMsg(
|
|
||||||
aFile.type,
|
|
||||||
function () {frd.readAsText(aFile); }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
frd.readAsText(aFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.body.removeChild(inp);
|
|
||||||
ide.filePicker = null;
|
|
||||||
if (inp.files.length > 0) {
|
|
||||||
file = inp.files[inp.files.length - 1];
|
|
||||||
readText(file);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
false
|
|
||||||
);
|
|
||||||
document.body.appendChild(inp);
|
|
||||||
ide.filePicker = inp;
|
|
||||||
inp.click();
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
if (shiftClicked) {
|
||||||
|
menu.addItem(
|
||||||
|
'import raw data...',
|
||||||
|
function () {myself.importData(true); },
|
||||||
|
'do not attempt to\nparse or format data',
|
||||||
|
new Color(100, 0, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
if (isString(this.currentValue) || !isNaN(+this.currentValue)) {
|
if (isString(this.currentValue) || !isNaN(+this.currentValue)) {
|
||||||
|
if (shiftClicked) {
|
||||||
|
menu.addItem(
|
||||||
|
'parse',
|
||||||
|
'parseTxt',
|
||||||
|
'try to convert\nraw data into a list',
|
||||||
|
new Color(100, 0, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
menu.addItem(
|
menu.addItem(
|
||||||
'export...',
|
'export...',
|
||||||
function () {
|
function () {
|
||||||
|
@ -9635,7 +9560,7 @@ WatcherMorph.prototype.userMenu = function () {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else if (this.currentValue instanceof List &&
|
} else if (this.currentValue instanceof List &&
|
||||||
this.currentValue.canBeCSV()) { // +++
|
this.currentValue.canBeCSV()) {
|
||||||
menu.addItem(
|
menu.addItem(
|
||||||
'export...',
|
'export...',
|
||||||
function () {
|
function () {
|
||||||
|
@ -9660,6 +9585,108 @@ WatcherMorph.prototype.userMenu = function () {
|
||||||
return menu;
|
return menu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WatcherMorph.prototype.importData = function (raw) {
|
||||||
|
// raw is a Boolean flag selecting to keep the data unparsed
|
||||||
|
var inp = document.createElement('input'),
|
||||||
|
ide = this.parentThatIsA(IDE_Morph),
|
||||||
|
myself = this;
|
||||||
|
|
||||||
|
function userImport() {
|
||||||
|
|
||||||
|
function txtOnlyMsg(ftype, anyway) {
|
||||||
|
ide.confirm(
|
||||||
|
localize(
|
||||||
|
'Snap! can only import "text" files.\n' +
|
||||||
|
'You selected a file of type "' +
|
||||||
|
ftype +
|
||||||
|
'".'
|
||||||
|
) + '\n\n' + localize('Open anyway?'),
|
||||||
|
'Unable to import',
|
||||||
|
anyway // callback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readText(aFile) {
|
||||||
|
var frd = new FileReader(),
|
||||||
|
ext = aFile.name.split('.').pop().toLowerCase();
|
||||||
|
|
||||||
|
function isTextFile(aFile) {
|
||||||
|
// special cases for Windows
|
||||||
|
// check the file extension for text-like-ness
|
||||||
|
return aFile.type.indexOf("text") !== -1 ||
|
||||||
|
contains(['txt', 'csv', 'xml', 'json', 'tsv'], ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCSVFile(aFile) {
|
||||||
|
return aFile.type.indexOf("csv") !== -1 || (ext === 'csv');
|
||||||
|
}
|
||||||
|
|
||||||
|
frd.onloadend = function (e) {
|
||||||
|
if (!raw && isCSVFile(aFile)) {
|
||||||
|
myself.target.setVar(
|
||||||
|
myself.getter,
|
||||||
|
Process.prototype.parseCSV(e.target.result)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
myself.target.setVar(
|
||||||
|
myself.getter,
|
||||||
|
e.target.result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (raw || isTextFile(aFile)) {
|
||||||
|
frd.readAsText(aFile);
|
||||||
|
} else {
|
||||||
|
// show a warning and an option
|
||||||
|
// letting the user load the file anyway
|
||||||
|
txtOnlyMsg(
|
||||||
|
aFile.type,
|
||||||
|
function () {frd.readAsText(aFile); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.removeChild(inp);
|
||||||
|
ide.filePicker = null;
|
||||||
|
if (inp.files.length > 0) {
|
||||||
|
readText(inp.files[inp.files.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ide.filePicker) {
|
||||||
|
document.body.removeChild(ide.filePicker);
|
||||||
|
ide.filePicker = null;
|
||||||
|
}
|
||||||
|
inp.type = 'file';
|
||||||
|
inp.style.color = "transparent";
|
||||||
|
inp.style.backgroundColor = "transparent";
|
||||||
|
inp.style.border = "none";
|
||||||
|
inp.style.outline = "none";
|
||||||
|
inp.style.position = "absolute";
|
||||||
|
inp.style.top = "0px";
|
||||||
|
inp.style.left = "0px";
|
||||||
|
inp.style.width = "0px";
|
||||||
|
inp.style.height = "0px";
|
||||||
|
inp.style.display = "none";
|
||||||
|
inp.addEventListener(
|
||||||
|
"change",
|
||||||
|
userImport,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
document.body.appendChild(inp);
|
||||||
|
ide.filePicker = inp;
|
||||||
|
inp.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
WatcherMorph.prototype.parseTxt = function () {
|
||||||
|
// experimental!
|
||||||
|
this.target.setVar(
|
||||||
|
this.getter,
|
||||||
|
Process.prototype.parseCSV(this.target.vars[this.getter].value)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
WatcherMorph.prototype.setStyle = function (style) {
|
WatcherMorph.prototype.setStyle = function (style) {
|
||||||
this.style = style;
|
this.style = style;
|
||||||
this.fixLayout();
|
this.fixLayout();
|
||||||
|
|
Ładowanie…
Reference in New Issue