kopia lustrzana https://github.com/backface/turtlestitch
directly export and import lists as csv files, under construction
rodzic
8e7a9a4bef
commit
a681880965
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
## in development
|
## in development
|
||||||
|
|
||||||
|
### 2019-01-07
|
||||||
|
* Lists, Objects: directly export and import lists as csv files, under construction
|
||||||
|
|
||||||
### 2019-01-04
|
### 2019-01-04
|
||||||
* Objects, Blocks, Threads: new feature/block: sense colors and sprites anywhere
|
* Objects, Blocks, Threads: new feature/block: sense colors and sprites anywhere
|
||||||
* updated German translation
|
* updated German translation
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
<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-04"></script>
|
<script type="text/javascript" src="src/objects.js?version=2019-01-07"></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=2018-10-02"></script>
|
<script type="text/javascript" src="src/lists.js?version=2019-01-07"></script>
|
||||||
<script type="text/javascript" src="src/byob.js?version=2018-11-12"></script>
|
<script type="text/javascript" src="src/byob.js?version=2018-11-12"></script>
|
||||||
<script type="text/javascript" src="src/tables.js?version=2018-10-02"></script>
|
<script type="text/javascript" src="src/tables.js?version=2018-10-02"></script>
|
||||||
<script type="text/javascript" src="src/symbols.js?version=2018-10-02"></script>
|
<script type="text/javascript" src="src/symbols.js?version=2018-10-02"></script>
|
||||||
|
|
89
src/lists.js
89
src/lists.js
|
@ -7,7 +7,7 @@
|
||||||
written by Jens Mönig and Brian Harvey
|
written by Jens Mönig and Brian Harvey
|
||||||
jens@moenig.org, bh@cs.berkeley.edu
|
jens@moenig.org, bh@cs.berkeley.edu
|
||||||
|
|
||||||
Copyright (C) 2018 by Jens Mönig and Brian Harvey
|
Copyright (C) 2019 by Jens Mönig and Brian Harvey
|
||||||
|
|
||||||
This file is part of Snap!.
|
This file is part of Snap!.
|
||||||
|
|
||||||
|
@ -58,11 +58,11 @@
|
||||||
|
|
||||||
/*global modules, BoxMorph, HandleMorph, PushButtonMorph, SyntaxElementMorph,
|
/*global modules, BoxMorph, HandleMorph, PushButtonMorph, SyntaxElementMorph,
|
||||||
Color, Point, WatcherMorph, StringMorph, SpriteMorph, ScrollFrameMorph,
|
Color, Point, WatcherMorph, StringMorph, SpriteMorph, ScrollFrameMorph,
|
||||||
CellMorph, ArrowMorph, MenuMorph, snapEquals, Morph, isNil, localize,
|
CellMorph, ArrowMorph, MenuMorph, snapEquals, Morph, isNil, localize, isString,
|
||||||
MorphicPreferences, TableDialogMorph, SpriteBubbleMorph, SpeechBubbleMorph,
|
MorphicPreferences, TableDialogMorph, SpriteBubbleMorph, SpeechBubbleMorph,
|
||||||
TableFrameMorph, TableMorph, Variable, isSnapObject*/
|
TableFrameMorph, TableMorph, Variable, isSnapObject*/
|
||||||
|
|
||||||
modules.lists = '2018-March-08';
|
modules.lists = '2019-January-07';
|
||||||
|
|
||||||
var List;
|
var List;
|
||||||
var ListWatcherMorph;
|
var ListWatcherMorph;
|
||||||
|
@ -80,26 +80,28 @@ var ListWatcherMorph;
|
||||||
|
|
||||||
setters (linked):
|
setters (linked):
|
||||||
-----------------
|
-----------------
|
||||||
cons - answer a new list with the given item in front
|
cons - answer a new list with the given item in front
|
||||||
cdr - answer all but the first element
|
cdr - answer all but the first element
|
||||||
|
|
||||||
setters (arrayed):
|
setters (arrayed):
|
||||||
------------------
|
------------------
|
||||||
add(element, index) - insert the element before the given slot,
|
add(element, index) - insert the element before the given slot,
|
||||||
put(element, index) - overwrite the element at the given slot
|
put(element, index) - overwrite the element at the given slot
|
||||||
remove(index) - remove the given slot, shortening the list
|
remove(index) - remove the given slot, shortening the list
|
||||||
clear() - remove all elements
|
clear() - remove all elements
|
||||||
|
|
||||||
getters (all hybrid):
|
getters (all hybrid):
|
||||||
---------------------
|
---------------------
|
||||||
length() - number of slots
|
length() - number of slots
|
||||||
at(index) - element present in specified slot
|
at(index) - element present in specified slot
|
||||||
contains(element) - <bool>
|
contains(element) - <bool>
|
||||||
|
|
||||||
conversion:
|
conversion:
|
||||||
-----------
|
-----------
|
||||||
asArray() - answer me as JavaScript array
|
asArray() - answer me as JavaScript array, convert to arrayed
|
||||||
asText() - answer my elements (recursively) concatenated
|
itemsArray() - answer a JavaScript array shallow copy of myself
|
||||||
|
asText() - answer my elements (recursively) concatenated
|
||||||
|
asCSV() - answer a csv-formatted String of myself
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// List instance creation:
|
// List instance creation:
|
||||||
|
@ -399,6 +401,46 @@ List.prototype.becomeLinked = function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
List.prototype.asCSV = function () {
|
||||||
|
// RFC 4180
|
||||||
|
// Caution, no error catching!
|
||||||
|
// this method assumes that the list.canBeCSV()
|
||||||
|
|
||||||
|
var items = this.itemsArray(),
|
||||||
|
rows = [];
|
||||||
|
|
||||||
|
function encodeCell(atomicValue) {
|
||||||
|
var string = atomicValue.toString(),
|
||||||
|
cell;
|
||||||
|
if (string.indexOf('\"') === -1 && (string.indexOf('\n') === -1)) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
cell = ['\"'];
|
||||||
|
string.split('').forEach(function (letter) {
|
||||||
|
cell.push(letter);
|
||||||
|
if (letter === '\"') {
|
||||||
|
cell.push(letter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cell.push('\"');
|
||||||
|
return cell.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items.some(function (any) {return any instanceof List; })) {
|
||||||
|
// 2-dimensional table
|
||||||
|
items.forEach(function (item) {
|
||||||
|
if (item instanceof List) {
|
||||||
|
rows.push(item.itemsArray().map(encodeCell).join(','));
|
||||||
|
} else {
|
||||||
|
rows.push(encodeCell(item));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return rows.join('\n');
|
||||||
|
}
|
||||||
|
// single row
|
||||||
|
return items.map(encodeCell).join(',');
|
||||||
|
};
|
||||||
|
|
||||||
// List testing
|
// List testing
|
||||||
|
|
||||||
List.prototype.equalTo = function (other) {
|
List.prototype.equalTo = function (other) {
|
||||||
|
@ -447,6 +489,25 @@ List.prototype.equalTo = function (other) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
List.prototype.canBeCSV = function () {
|
||||||
|
return this.itemsArray().every(function (value) {
|
||||||
|
return !isNaN(+value) ||
|
||||||
|
isString(value) ||
|
||||||
|
value === true ||
|
||||||
|
value === false ||
|
||||||
|
(value instanceof List && value.hasOnlyAtomicData);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
List.prototype.hasOnlyAtomicData = function () {
|
||||||
|
return this.itemsArray().every(function (value) {
|
||||||
|
return !isNaN(+value) ||
|
||||||
|
isString(value) ||
|
||||||
|
value === true ||
|
||||||
|
value === false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// ListWatcherMorph ////////////////////////////////////////////////////
|
// ListWatcherMorph ////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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-04';
|
modules.objects = '2019-January-07';
|
||||||
|
|
||||||
var SpriteMorph;
|
var SpriteMorph;
|
||||||
var StageMorph;
|
var StageMorph;
|
||||||
|
@ -9567,16 +9567,30 @@ WatcherMorph.prototype.userMenu = function () {
|
||||||
function readText(aFile) {
|
function readText(aFile) {
|
||||||
var frd = new FileReader();
|
var frd = new FileReader();
|
||||||
frd.onloadend = function (e) {
|
frd.onloadend = function (e) {
|
||||||
myself.target.setVar(
|
// +++ needs to be refactored
|
||||||
myself.getter,
|
if (aFile.type.indexOf("csv") ||
|
||||||
e.target.result
|
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) {
|
if (aFile.type.indexOf("text") === -1) {
|
||||||
// special cases for Windows
|
// special cases for Windows
|
||||||
// check the file extension for text-like-ness
|
// check the file extension for text-like-ness
|
||||||
if (contains(
|
if (contains(
|
||||||
|
// +++ avoid doubling
|
||||||
['txt', 'csv', 'xml', 'json', 'tsv'],
|
['txt', 'csv', 'xml', 'json', 'tsv'],
|
||||||
aFile.name.split('.').pop().toLowerCase()
|
aFile.name.split('.').pop().toLowerCase()
|
||||||
)) {
|
)) {
|
||||||
|
@ -9620,6 +9634,19 @@ WatcherMorph.prototype.userMenu = function () {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else if (this.currentValue instanceof List &&
|
||||||
|
this.currentValue.canBeCSV()) { // +++
|
||||||
|
menu.addItem(
|
||||||
|
'export...',
|
||||||
|
function () {
|
||||||
|
var ide = myself.parentThatIsA(IDE_Morph);
|
||||||
|
ide.saveFileAs(
|
||||||
|
myself.currentValue.asCSV(),
|
||||||
|
'text/csv;charset=utf-8', // RFC 4180
|
||||||
|
myself.getter // variable name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
} else if (this.currentValue instanceof Context) {
|
} else if (this.currentValue instanceof Context) {
|
||||||
vNames = this.currentValue.outerContext.variables.names();
|
vNames = this.currentValue.outerContext.variables.names();
|
||||||
if (vNames.length) {
|
if (vNames.length) {
|
||||||
|
|
Ładowanie…
Reference in New Issue