p5 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{src → dist}/accessibility/color_namer.js +48 -3
- package/{src → dist}/accessibility/describe.js +12 -2
- package/{src → dist}/accessibility/gridOutput.js +2 -2
- package/dist/accessibility/index.js +60 -0
- package/{src → dist}/accessibility/outputs.js +23 -2
- package/{src → dist}/accessibility/textOutput.js +2 -2
- package/dist/app.js +120 -0
- package/{src → dist}/color/color_conversion.js +48 -10
- package/{src → dist}/color/color_spaces/hsb.js +3 -1
- package/dist/color/creating_reading.js +3 -0
- package/dist/color/index.js +13 -0
- package/dist/color/p5.Color.culori.js +1 -0
- package/dist/color/p5.Color.js +3 -0
- package/{src → dist}/color/setting.js +9 -6
- package/{src/core/constants.js → dist/constants-tYr0tCl8.js} +284 -132
- package/{src → dist}/core/States.js +3 -1
- package/dist/core/constants.js +1 -0
- package/{src → dist}/core/environment.js +12 -10
- package/{src → dist}/core/friendly_errors/browser_errors.js +1 -1
- package/{src → dist}/core/friendly_errors/fes_core.js +14 -44
- package/{src → dist}/core/friendly_errors/file_errors.js +6 -3
- package/dist/core/friendly_errors/index.js +23 -0
- package/dist/core/friendly_errors/param_validator.js +5421 -0
- package/{src → dist}/core/friendly_errors/sketch_reader.js +50 -4
- package/{src → dist}/core/friendly_errors/sketch_verifier.js +6 -6
- package/{src → dist}/core/friendly_errors/stacktrace.js +3 -5
- package/{src → dist}/core/friendly_errors/validate_params.js +50 -41
- package/{src → dist}/core/helpers.js +9 -6
- package/dist/core/init.js +105 -0
- package/dist/core/internationalization.js +302 -0
- package/dist/core/legacy.js +73 -0
- package/dist/core/main.js +44 -0
- package/dist/core/noop.js +3 -0
- package/dist/core/p5.Graphics.js +40 -0
- package/dist/core/p5.Renderer.js +11 -0
- package/dist/core/p5.Renderer2D.js +44 -0
- package/dist/core/reference.js +1 -0
- package/dist/core/rendering.js +40 -0
- package/{src → dist}/core/structure.js +3 -3
- package/{src → dist}/core/transform.js +2 -2
- package/{src/color/creating_reading.js → dist/creating_reading-Cr8L2Jnm.js} +841 -13
- package/{src → dist}/data/index.js +3 -1
- package/{src → dist}/data/local_storage.js +2 -8
- package/{src → dist}/dom/dom.js +19 -13
- package/dist/dom/index.js +18 -0
- package/{src → dist}/dom/p5.Element.js +14 -12
- package/{src → dist}/dom/p5.File.js +4 -4
- package/{src → dist}/dom/p5.MediaElement.js +10 -4
- package/{src → dist}/events/acceleration.js +26 -26
- package/{src → dist}/events/index.js +3 -1
- package/{src → dist}/events/keyboard.js +14 -12
- package/{src → dist}/events/pointer.js +16 -17
- package/dist/image/const.js +9 -0
- package/{src → dist}/image/filterRenderer2D.js +57 -37
- package/{src → dist}/image/filters.js +1 -3
- package/dist/image/image.js +40 -0
- package/dist/image/index.js +51 -0
- package/dist/image/loading_displaying.js +40 -0
- package/dist/image/p5.Image.js +11 -0
- package/{src → dist}/image/pixels.js +5 -3
- package/{src → dist}/io/csv.js +72 -70
- package/dist/io/files.js +40 -0
- package/dist/io/index.js +51 -0
- package/{src → dist}/io/p5.Table.js +6 -6
- package/{src → dist}/io/p5.TableRow.js +5 -6
- package/{src → dist}/io/p5.XML.js +2 -5
- package/{src → dist}/io/utilities.js +1 -1
- package/{src/core/p5.Renderer2D.js → dist/main-CAxvgiOV.js} +738 -57
- package/{src → dist}/math/Matrices/Matrix.js +10 -8
- package/{src → dist}/math/Matrices/MatrixInterface.js +5 -3
- package/{src → dist}/math/Matrices/MatrixNumjs.js +12 -26
- package/{src → dist}/math/calculation.js +2 -2
- package/{src → dist}/math/index.js +6 -3
- package/{src → dist}/math/math.js +3 -3
- package/{src → dist}/math/noise.js +2 -2
- package/{src → dist}/math/p5.Matrix.js +7 -4
- package/{src → dist}/math/p5.Vector.js +6 -6
- package/{src → dist}/math/random.js +2 -2
- package/{src → dist}/math/trigonometry.js +16 -15
- package/{src/image/p5.Image.js → dist/p5.Renderer-Swjl9HQO.js} +393 -22
- package/dist/rendering-B5TRR7aY.js +24960 -0
- package/{src → dist}/shape/2d_primitives.js +18 -17
- package/{src → dist}/shape/attributes.js +18 -17
- package/{src → dist}/shape/curves.js +2 -2
- package/{src → dist}/shape/custom_shapes.js +44 -64
- package/{src → dist}/shape/index.js +10 -2
- package/{src → dist}/shape/vertex.js +2 -3
- package/dist/type/index.js +25 -0
- package/{src → dist}/type/lib/Typr.js +76 -94
- package/{src → dist}/type/p5.Font.js +37 -63
- package/{src → dist}/type/textCore.js +35 -58
- package/{src → dist}/type/unicodeRanges.js +3 -1
- package/{src → dist}/utilities/conversion.js +2 -2
- package/{src → dist}/utilities/index.js +3 -1
- package/{src → dist}/utilities/time_date.js +6 -7
- package/{src → dist}/utilities/utility_functions.js +2 -2
- package/dist/webgl/3d_primitives.js +40 -0
- package/{src → dist}/webgl/GeometryBufferCache.js +3 -1
- package/{src → dist}/webgl/GeometryBuilder.js +12 -8
- package/{src → dist}/webgl/ShaderGenerator.js +79 -82
- package/{src → dist}/webgl/ShapeBuilder.js +26 -23
- package/dist/webgl/index.js +76 -0
- package/{src → dist}/webgl/interaction.js +7 -6
- package/dist/webgl/light.js +40 -0
- package/{src → dist}/webgl/loading.js +45 -12
- package/dist/webgl/material.js +40 -0
- package/dist/webgl/p5.Camera.js +40 -0
- package/{src → dist}/webgl/p5.DataArray.js +3 -5
- package/dist/webgl/p5.Framebuffer.js +40 -0
- package/{src → dist}/webgl/p5.Geometry.js +12 -15
- package/{src → dist}/webgl/p5.Quat.js +5 -4
- package/{src → dist}/webgl/p5.RenderBuffer.js +2 -3
- package/dist/webgl/p5.RendererGL.js +40 -0
- package/dist/webgl/p5.Shader.js +40 -0
- package/dist/webgl/p5.Texture.js +40 -0
- package/{src → dist}/webgl/text.js +78 -38
- package/lib/p5.esm.js +296 -194
- package/lib/p5.js +296 -194
- package/lib/p5.min.js +1 -1
- package/package.json +17 -17
- package/translations/dev.js +6 -6
- package/translations/index.js +1 -1
- package/types/accessibility/color_namer.d.ts +8 -0
- package/types/accessibility/describe.d.ts +184 -0
- package/types/accessibility/gridOutput.d.ts +8 -0
- package/types/accessibility/outputs.d.ts +235 -0
- package/types/accessibility/textOutput.d.ts +8 -0
- package/types/color/color_conversion.d.ts +47 -0
- package/types/color/creating_reading.d.ts +1348 -0
- package/types/color/p5.Color.d.ts +1070 -0
- package/types/color/setting.d.ts +2085 -0
- package/types/core/constants.d.ts +341 -0
- package/types/core/environment.d.ts +668 -0
- package/types/core/friendly_errors/fes_core.d.ts +8 -0
- package/types/core/friendly_errors/file_errors.d.ts +8 -0
- package/types/core/friendly_errors/param_validator.d.ts +30 -0
- package/types/core/friendly_errors/sketch_reader.d.ts +8 -0
- package/types/core/friendly_errors/stacktrace.d.ts +11 -0
- package/types/core/friendly_errors/validate_params.d.ts +8 -0
- package/types/core/helpers.d.ts +8 -0
- package/types/core/legacy.d.ts +8 -0
- package/types/core/main.d.ts +5996 -0
- package/types/core/p5.Graphics.d.ts +484 -0
- package/types/core/p5.Renderer.d.ts +14 -0
- package/types/core/reference.d.ts +8 -0
- package/types/core/rendering.d.ts +481 -0
- package/types/core/structure.d.ts +492 -0
- package/types/core/transform.d.ts +1638 -0
- package/types/data/local_storage.d.ts +323 -0
- package/types/dom/dom.d.ts +1295 -0
- package/types/dom/p5.Element.d.ts +2011 -0
- package/types/dom/p5.File.d.ts +13 -0
- package/types/dom/p5.MediaElement.d.ts +1249 -0
- package/types/events/acceleration.d.ts +193 -0
- package/types/events/keyboard.d.ts +499 -0
- package/types/events/pointer.d.ts +782 -0
- package/types/global.d.ts +5542 -0
- package/types/image/filterRenderer2D.d.ts +54 -0
- package/types/image/image.d.ts +326 -0
- package/types/image/loading_displaying.d.ts +580 -0
- package/types/image/p5.Image.d.ts +5882 -0
- package/types/image/pixels.d.ts +832 -0
- package/types/io/files.d.ts +1447 -0
- package/types/io/p5.Table.d.ts +1247 -0
- package/types/io/p5.TableRow.d.ts +343 -0
- package/types/io/p5.XML.d.ts +1188 -0
- package/types/math/Matrices/Matrix.d.ts +1029 -0
- package/types/math/Matrices/MatrixNumjs.d.ts +8 -0
- package/types/math/calculation.d.ts +923 -0
- package/types/math/math.d.ts +90 -0
- package/types/math/noise.d.ts +311 -0
- package/types/math/p5.Matrix.d.ts +8 -0
- package/types/math/p5.Vector.d.ts +3416 -0
- package/types/math/random.d.ts +267 -0
- package/types/math/trigonometry.d.ts +663 -0
- package/types/p5.d.ts +6663 -0
- package/types/shape/2d_primitives.d.ts +1033 -0
- package/types/shape/attributes.d.ts +466 -0
- package/types/shape/curves.d.ts +740 -0
- package/types/shape/custom_shapes.d.ts +888 -0
- package/types/shape/vertex.d.ts +1141 -0
- package/types/type/p5.Font.d.ts +575 -0
- package/types/type/textCore.d.ts +1198 -0
- package/types/utilities/conversion.d.ts +894 -0
- package/types/utilities/time_date.d.ts +295 -0
- package/types/utilities/utility_functions.d.ts +587 -0
- package/types/webgl/3d_primitives.d.ts +1432 -0
- package/types/webgl/ShaderGenerator.d.ts +8 -0
- package/types/webgl/interaction.d.ts +371 -0
- package/types/webgl/light.d.ts +1184 -0
- package/types/webgl/loading.d.ts +481 -0
- package/types/webgl/material.d.ts +2656 -0
- package/types/webgl/p5.Camera.d.ts +3023 -0
- package/types/webgl/p5.DataArray.d.ts +61 -0
- package/types/webgl/p5.Framebuffer.d.ts +760 -0
- package/types/webgl/p5.Geometry.d.ts +1191 -0
- package/types/webgl/p5.Quat.d.ts +45 -0
- package/types/webgl/p5.RendererGL.d.ts +234 -0
- package/types/webgl/p5.Shader.d.ts +660 -0
- package/types/webgl/p5.Texture.d.ts +61 -0
- package/types/webgl/text.d.ts +74 -0
- package/src/README.md +0 -27
- package/src/accessibility/index.js +0 -13
- package/src/app.js +0 -61
- package/src/color/index.js +0 -9
- package/src/color/p5.Color.culori.js +0 -66
- package/src/color/p5.Color.js +0 -851
- package/src/core/README.md +0 -91
- package/src/core/friendly_errors/index.js +0 -13
- package/src/core/friendly_errors/param_validator.js +0 -561
- package/src/core/init.js +0 -58
- package/src/core/internationalization.js +0 -195
- package/src/core/legacy.js +0 -29
- package/src/core/main.js +0 -689
- package/src/core/noop.js +0 -1
- package/src/core/p5.Graphics.js +0 -696
- package/src/core/p5.Renderer.js +0 -408
- package/src/core/reference.js +0 -2060
- package/src/core/rendering.js +0 -697
- package/src/dom/index.js +0 -11
- package/src/image/const.js +0 -6
- package/src/image/image.js +0 -731
- package/src/image/index.js +0 -15
- package/src/image/loading_displaying.js +0 -1431
- package/src/io/files.js +0 -2210
- package/src/io/index.js +0 -11
- package/src/math/README.md +0 -40
- package/src/type/index.js +0 -9
- package/src/webgl/3d_primitives.js +0 -2741
- package/src/webgl/index.js +0 -37
- package/src/webgl/light.js +0 -1851
- package/src/webgl/material.js +0 -3854
- package/src/webgl/p5.Camera.js +0 -4010
- package/src/webgl/p5.Framebuffer.js +0 -1865
- package/src/webgl/p5.RendererGL.js +0 -2867
- package/src/webgl/p5.Shader.js +0 -1505
- package/src/webgl/p5.Texture.js +0 -541
- package/src/webgl/shaders/basic.frag +0 -6
- package/src/webgl/shaders/filters/base.frag +0 -22
- package/src/webgl/shaders/filters/base.vert +0 -19
- package/src/webgl/shaders/filters/blur.frag +0 -60
- package/src/webgl/shaders/filters/default.vert +0 -18
- package/src/webgl/shaders/filters/dilate.frag +0 -39
- package/src/webgl/shaders/filters/erode.frag +0 -39
- package/src/webgl/shaders/filters/gray.frag +0 -16
- package/src/webgl/shaders/filters/invert.frag +0 -15
- package/src/webgl/shaders/filters/opaque.frag +0 -12
- package/src/webgl/shaders/filters/posterize.frag +0 -29
- package/src/webgl/shaders/filters/threshold.frag +0 -23
- package/src/webgl/shaders/font.frag +0 -216
- package/src/webgl/shaders/font.vert +0 -44
- package/src/webgl/shaders/imageLight.vert +0 -33
- package/src/webgl/shaders/imageLightDiffused.frag +0 -82
- package/src/webgl/shaders/imageLightSpecular.frag +0 -134
- package/src/webgl/shaders/light.vert +0 -37
- package/src/webgl/shaders/light_texture.frag +0 -26
- package/src/webgl/shaders/lighting.glsl +0 -227
- package/src/webgl/shaders/line.frag +0 -74
- package/src/webgl/shaders/line.vert +0 -294
- package/src/webgl/shaders/normal.frag +0 -6
- package/src/webgl/shaders/normal.vert +0 -72
- package/src/webgl/shaders/phong.frag +0 -84
- package/src/webgl/shaders/phong.vert +0 -87
- package/src/webgl/shaders/point.frag +0 -29
- package/src/webgl/shaders/point.vert +0 -19
- package/src/webgl/shaders/sphereMapping.frag +0 -26
- package/src/webgl/shaders/webgl2Compatibility.glsl +0 -34
package/src/io/files.js
DELETED
|
@@ -1,2210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module IO
|
|
3
|
-
* @submodule Input
|
|
4
|
-
* @for p5
|
|
5
|
-
* @requires core
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { Renderer } from '../core/p5.Renderer';
|
|
9
|
-
import { Graphics } from '../core/p5.Graphics';
|
|
10
|
-
import { parse } from './csv';
|
|
11
|
-
import { downloadFile, _checkFileExtension } from './utilities';
|
|
12
|
-
|
|
13
|
-
class HTTPError extends Error {
|
|
14
|
-
status;
|
|
15
|
-
response;
|
|
16
|
-
ok;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function request(path, type){
|
|
20
|
-
try {
|
|
21
|
-
const res = await fetch(path);
|
|
22
|
-
|
|
23
|
-
if (res.ok) {
|
|
24
|
-
let data;
|
|
25
|
-
switch(type) {
|
|
26
|
-
case 'json':
|
|
27
|
-
data = await res.json();
|
|
28
|
-
break;
|
|
29
|
-
case 'text':
|
|
30
|
-
data = await res.text();
|
|
31
|
-
break;
|
|
32
|
-
case 'arrayBuffer':
|
|
33
|
-
data = await res.arrayBuffer();
|
|
34
|
-
break;
|
|
35
|
-
case 'blob':
|
|
36
|
-
data = await res.blob();
|
|
37
|
-
break;
|
|
38
|
-
case 'bytes':
|
|
39
|
-
// TODO: Chrome does not implement res.bytes() yet
|
|
40
|
-
if(res.bytes){
|
|
41
|
-
data = await res.bytes();
|
|
42
|
-
}else{
|
|
43
|
-
const d = await res.arrayBuffer();
|
|
44
|
-
data = new Uint8Array(d);
|
|
45
|
-
}
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
throw new Error('Unsupported response type');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return { data, headers: res.headers };
|
|
52
|
-
|
|
53
|
-
} else {
|
|
54
|
-
const err = new HTTPError(res.statusText);
|
|
55
|
-
err.status = res.status;
|
|
56
|
-
err.response = res;
|
|
57
|
-
err.ok = false;
|
|
58
|
-
|
|
59
|
-
throw err;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
} catch(err) {
|
|
63
|
-
// Handle both fetch error and HTTP error
|
|
64
|
-
if (err instanceof TypeError) {
|
|
65
|
-
console.log('You may have encountered a CORS error');
|
|
66
|
-
} else if (err instanceof HTTPError) {
|
|
67
|
-
console.log('You have encountered a HTTP error');
|
|
68
|
-
} else if (err instanceof SyntaxError) {
|
|
69
|
-
console.log('There is an error parsing the response to requested data structure');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
throw err;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function files(p5, fn){
|
|
77
|
-
/**
|
|
78
|
-
* Loads a JSON file to create an `Object`.
|
|
79
|
-
*
|
|
80
|
-
* JavaScript Object Notation
|
|
81
|
-
* (<a href="https://developer.mozilla.org/en-US/docs/Glossary/JSON" target="_blank">JSON</a>)
|
|
82
|
-
* is a standard format for sending data between applications. The format is
|
|
83
|
-
* based on JavaScript objects which have keys and values. JSON files store
|
|
84
|
-
* data in an object with strings as keys. Values can be strings, numbers,
|
|
85
|
-
* Booleans, arrays, `null`, or other objects.
|
|
86
|
-
*
|
|
87
|
-
* The first parameter, `path`, is a string with the path to the file.
|
|
88
|
-
* Paths to local files should be relative, as in
|
|
89
|
-
* `loadJSON('assets/data.json')`. URLs such as
|
|
90
|
-
* `'https://example.com/data.json'` may be blocked due to browser security.
|
|
91
|
-
* The `path` parameter can also be defined as a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
92
|
-
* object for more advanced usage.
|
|
93
|
-
*
|
|
94
|
-
* The second parameter, `successCallback`, is optional. If a function is
|
|
95
|
-
* passed, as in `loadJSON('assets/data.json', handleData)`, then the
|
|
96
|
-
* `handleData()` function will be called once the data loads. The object
|
|
97
|
-
* created from the JSON data will be passed to `handleData()` as its only argument.
|
|
98
|
-
* The return value of the `handleData()` function will be used as the final return
|
|
99
|
-
* value of `loadJSON('assets/data.json', handleData)`.
|
|
100
|
-
*
|
|
101
|
-
* The third parameter, `failureCallback`, is also optional. If a function is
|
|
102
|
-
* passed, as in `loadJSON('assets/data.json', handleData, handleFailure)`,
|
|
103
|
-
* then the `handleFailure()` function will be called if an error occurs while
|
|
104
|
-
* loading. The `Error` object will be passed to `handleFailure()` as its only
|
|
105
|
-
* argument. The return value of the `handleFailure()` function will be used as the
|
|
106
|
-
* final return value of `loadJSON('assets/data.json', handleData, handleFailure)`.
|
|
107
|
-
*
|
|
108
|
-
* This function returns a `Promise` and should be used in an `async` setup with
|
|
109
|
-
* `await`. See the examples for the usage syntax.
|
|
110
|
-
*
|
|
111
|
-
* @method loadJSON
|
|
112
|
-
* @param {String|Request} path path of the JSON file to be loaded.
|
|
113
|
-
* @param {Function} [successCallback] function to call once the data is loaded. Will be passed the object.
|
|
114
|
-
* @param {Function} [errorCallback] function to call if the data fails to load. Will be passed an `Error` event object.
|
|
115
|
-
* @return {Promise<Object>} object containing the loaded data.
|
|
116
|
-
*
|
|
117
|
-
* @example
|
|
118
|
-
*
|
|
119
|
-
* <div>
|
|
120
|
-
* <code>
|
|
121
|
-
* let myData;
|
|
122
|
-
*
|
|
123
|
-
* async function setup() {
|
|
124
|
-
* myData = await loadJSON('assets/data.json');
|
|
125
|
-
* createCanvas(100, 100);
|
|
126
|
-
*
|
|
127
|
-
* background(200);
|
|
128
|
-
*
|
|
129
|
-
* // Style the circle.
|
|
130
|
-
* fill(myData.color);
|
|
131
|
-
* noStroke();
|
|
132
|
-
*
|
|
133
|
-
* // Draw the circle.
|
|
134
|
-
* circle(myData.x, myData.y, myData.d);
|
|
135
|
-
*
|
|
136
|
-
* describe('A pink circle on a gray background.');
|
|
137
|
-
* }
|
|
138
|
-
* </code>
|
|
139
|
-
* </div>
|
|
140
|
-
*
|
|
141
|
-
* <div>
|
|
142
|
-
* <code>
|
|
143
|
-
* let myData;
|
|
144
|
-
*
|
|
145
|
-
* async function setup() {
|
|
146
|
-
* myData = await loadJSON('assets/data.json');
|
|
147
|
-
* createCanvas(100, 100);
|
|
148
|
-
*
|
|
149
|
-
* background(200);
|
|
150
|
-
*
|
|
151
|
-
* // Create a p5.Color object and make it transparent.
|
|
152
|
-
* let c = color(myData.color);
|
|
153
|
-
* c.setAlpha(80);
|
|
154
|
-
*
|
|
155
|
-
* // Style the circles.
|
|
156
|
-
* fill(c);
|
|
157
|
-
* noStroke();
|
|
158
|
-
*
|
|
159
|
-
* // Iterate over the myData.bubbles array.
|
|
160
|
-
* for (let b of myData.bubbles) {
|
|
161
|
-
* // Draw a circle for each bubble.
|
|
162
|
-
* circle(b.x, b.y, b.d);
|
|
163
|
-
* }
|
|
164
|
-
*
|
|
165
|
-
* describe('Several pink bubbles floating in a blue sky.');
|
|
166
|
-
* }
|
|
167
|
-
* </code>
|
|
168
|
-
* </div>
|
|
169
|
-
*
|
|
170
|
-
* <div>
|
|
171
|
-
* <code>
|
|
172
|
-
* let myData;
|
|
173
|
-
*
|
|
174
|
-
* async function setup() {
|
|
175
|
-
* myData = await loadJSON('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson');
|
|
176
|
-
* createCanvas(100, 100);
|
|
177
|
-
*
|
|
178
|
-
* background(200);
|
|
179
|
-
*
|
|
180
|
-
* // Get data about the most recent earthquake.
|
|
181
|
-
* let quake = myData.features[0].properties;
|
|
182
|
-
*
|
|
183
|
-
* // Draw a circle based on the earthquake's magnitude.
|
|
184
|
-
* circle(50, 50, quake.mag * 10);
|
|
185
|
-
*
|
|
186
|
-
* // Style the text.
|
|
187
|
-
* textAlign(LEFT, CENTER);
|
|
188
|
-
* textFont('Courier New');
|
|
189
|
-
* textSize(11);
|
|
190
|
-
*
|
|
191
|
-
* // Display the earthquake's location.
|
|
192
|
-
* text(quake.place, 5, 80, 100);
|
|
193
|
-
*
|
|
194
|
-
* describe(`A white circle on a gray background. The text "${quake.place}" is written beneath the circle.`);
|
|
195
|
-
* }
|
|
196
|
-
* </code>
|
|
197
|
-
* </div>
|
|
198
|
-
*
|
|
199
|
-
* <div>
|
|
200
|
-
* <code>
|
|
201
|
-
* let bigQuake;
|
|
202
|
-
*
|
|
203
|
-
* // Load the GeoJSON and preprocess it.
|
|
204
|
-
* async function setup() {
|
|
205
|
-
* await loadJSON(
|
|
206
|
-
* 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson',
|
|
207
|
-
* handleData
|
|
208
|
-
* );
|
|
209
|
-
*
|
|
210
|
-
* createCanvas(100, 100);
|
|
211
|
-
*
|
|
212
|
-
* background(200);
|
|
213
|
-
*
|
|
214
|
-
* // Draw a circle based on the earthquake's magnitude.
|
|
215
|
-
* circle(50, 50, bigQuake.mag * 10);
|
|
216
|
-
*
|
|
217
|
-
* // Style the text.
|
|
218
|
-
* textAlign(LEFT, CENTER);
|
|
219
|
-
* textFont('Courier New');
|
|
220
|
-
* textSize(11);
|
|
221
|
-
*
|
|
222
|
-
* // Display the earthquake's location.
|
|
223
|
-
* text(bigQuake.place, 5, 80, 100);
|
|
224
|
-
*
|
|
225
|
-
* describe(`A white circle on a gray background. The text "${bigQuake.place}" is written beneath the circle.`);
|
|
226
|
-
* }
|
|
227
|
-
*
|
|
228
|
-
* // Find the biggest recent earthquake.
|
|
229
|
-
* function handleData(data) {
|
|
230
|
-
* let maxMag = 0;
|
|
231
|
-
* // Iterate over the earthquakes array.
|
|
232
|
-
* for (let quake of data.features) {
|
|
233
|
-
* // Reassign bigQuake if a larger
|
|
234
|
-
* // magnitude quake is found.
|
|
235
|
-
* if (quake.properties.mag > maxMag) {
|
|
236
|
-
* bigQuake = quake.properties;
|
|
237
|
-
* }
|
|
238
|
-
* }
|
|
239
|
-
* }
|
|
240
|
-
* </code>
|
|
241
|
-
* </div>
|
|
242
|
-
*
|
|
243
|
-
* <div>
|
|
244
|
-
* <code>
|
|
245
|
-
* let bigQuake;
|
|
246
|
-
*
|
|
247
|
-
* // Load the GeoJSON and preprocess it.
|
|
248
|
-
* async function setup() {
|
|
249
|
-
* await loadJSON(
|
|
250
|
-
* 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson',
|
|
251
|
-
* handleData,
|
|
252
|
-
* handleError
|
|
253
|
-
* );
|
|
254
|
-
*
|
|
255
|
-
* createCanvas(100, 100);
|
|
256
|
-
*
|
|
257
|
-
* background(200);
|
|
258
|
-
*
|
|
259
|
-
* // Draw a circle based on the earthquake's magnitude.
|
|
260
|
-
* circle(50, 50, bigQuake.mag * 10);
|
|
261
|
-
*
|
|
262
|
-
* // Style the text.
|
|
263
|
-
* textAlign(LEFT, CENTER);
|
|
264
|
-
* textFont('Courier New');
|
|
265
|
-
* textSize(11);
|
|
266
|
-
*
|
|
267
|
-
* // Display the earthquake's location.
|
|
268
|
-
* text(bigQuake.place, 5, 80, 100);
|
|
269
|
-
*
|
|
270
|
-
* describe(`A white circle on a gray background. The text "${bigQuake.place}" is written beneath the circle.`);
|
|
271
|
-
* }
|
|
272
|
-
*
|
|
273
|
-
* // Find the biggest recent earthquake.
|
|
274
|
-
* function handleData(data) {
|
|
275
|
-
* let maxMag = 0;
|
|
276
|
-
* // Iterate over the earthquakes array.
|
|
277
|
-
* for (let quake of data.features) {
|
|
278
|
-
* // Reassign bigQuake if a larger
|
|
279
|
-
* // magnitude quake is found.
|
|
280
|
-
* if (quake.properties.mag > maxMag) {
|
|
281
|
-
* bigQuake = quake.properties;
|
|
282
|
-
* }
|
|
283
|
-
* }
|
|
284
|
-
* }
|
|
285
|
-
*
|
|
286
|
-
* // Log any errors to the console.
|
|
287
|
-
* function handleError(error) {
|
|
288
|
-
* console.log('Oops!', error);
|
|
289
|
-
* }
|
|
290
|
-
* </code>
|
|
291
|
-
* </div>
|
|
292
|
-
*/
|
|
293
|
-
fn.loadJSON = async function (path, successCallback, errorCallback) {
|
|
294
|
-
// p5._validateParameters('loadJSON', arguments);
|
|
295
|
-
|
|
296
|
-
try{
|
|
297
|
-
const { data } = await request(path, 'json');
|
|
298
|
-
if (successCallback) return successCallback(data);
|
|
299
|
-
return data;
|
|
300
|
-
} catch(err) {
|
|
301
|
-
p5._friendlyFileLoadError(5, path);
|
|
302
|
-
if(errorCallback) {
|
|
303
|
-
return errorCallback(err);
|
|
304
|
-
} else {
|
|
305
|
-
throw err;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Loads a text file to create an `Array`.
|
|
312
|
-
*
|
|
313
|
-
* The first parameter, `path`, is always a string with the path to the file.
|
|
314
|
-
* Paths to local files should be relative, as in
|
|
315
|
-
* `loadStrings('assets/data.txt')`. URLs such as
|
|
316
|
-
* `'https://example.com/data.txt'` may be blocked due to browser security.
|
|
317
|
-
* The `path` parameter can also be defined as a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
318
|
-
* object for more advanced usage.
|
|
319
|
-
*
|
|
320
|
-
* The second parameter, `successCallback`, is optional. If a function is
|
|
321
|
-
* passed, as in `loadStrings('assets/data.txt', handleData)`, then the
|
|
322
|
-
* `handleData()` function will be called once the data loads. The array
|
|
323
|
-
* created from the text data will be passed to `handleData()` as its only
|
|
324
|
-
* argument. The return value of the `handleData()` function will be used as
|
|
325
|
-
* the final return value of `loadStrings('assets/data.txt', handleData)`.
|
|
326
|
-
*
|
|
327
|
-
* The third parameter, `failureCallback`, is also optional. If a function is
|
|
328
|
-
* passed, as in `loadStrings('assets/data.txt', handleData, handleFailure)`,
|
|
329
|
-
* then the `handleFailure()` function will be called if an error occurs while
|
|
330
|
-
* loading. The `Error` object will be passed to `handleFailure()` as its only
|
|
331
|
-
* argument. The return value of the `handleFailure()` function will be used as
|
|
332
|
-
* the final return value of `loadStrings('assets/data.txt', handleData, handleFailure)`.
|
|
333
|
-
*
|
|
334
|
-
* This function returns a `Promise` and should be used in an `async` setup with
|
|
335
|
-
* `await`. See the examples for the usage syntax.
|
|
336
|
-
*
|
|
337
|
-
* @method loadStrings
|
|
338
|
-
* @param {String|Request} path path of the text file to be loaded.
|
|
339
|
-
* @param {Function} [successCallback] function to call once the data is
|
|
340
|
-
* loaded. Will be passed the array.
|
|
341
|
-
* @param {Function} [errorCallback] function to call if the data fails to
|
|
342
|
-
* load. Will be passed an `Error` event
|
|
343
|
-
* object.
|
|
344
|
-
* @return {Promise<String[]>} new array containing the loaded text.
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
*
|
|
348
|
-
* <div>
|
|
349
|
-
* <code>
|
|
350
|
-
* let myData;
|
|
351
|
-
*
|
|
352
|
-
* async function setup() {
|
|
353
|
-
* myData = await loadStrings('assets/test.txt');
|
|
354
|
-
*
|
|
355
|
-
* createCanvas(100, 100);
|
|
356
|
-
*
|
|
357
|
-
* background(200);
|
|
358
|
-
*
|
|
359
|
-
* // Select a random line from the text.
|
|
360
|
-
* let phrase = random(myData);
|
|
361
|
-
*
|
|
362
|
-
* // Style the text.
|
|
363
|
-
* textAlign(LEFT, CENTER);
|
|
364
|
-
* textFont('Courier New');
|
|
365
|
-
* textSize(12);
|
|
366
|
-
*
|
|
367
|
-
* // Display the text.
|
|
368
|
-
* text(phrase, 10, 50, 90);
|
|
369
|
-
*
|
|
370
|
-
* describe(`The text "${phrase}" written in black on a gray background.`);
|
|
371
|
-
* }
|
|
372
|
-
* </code>
|
|
373
|
-
* </div>
|
|
374
|
-
*
|
|
375
|
-
* <div>
|
|
376
|
-
* <code>
|
|
377
|
-
* let lastLine;
|
|
378
|
-
*
|
|
379
|
-
* // Load the text and preprocess it.
|
|
380
|
-
* async function setup() {
|
|
381
|
-
* await loadStrings('assets/test.txt', handleData);
|
|
382
|
-
*
|
|
383
|
-
* createCanvas(100, 100);
|
|
384
|
-
*
|
|
385
|
-
* background(200);
|
|
386
|
-
*
|
|
387
|
-
* // Style the text.
|
|
388
|
-
* textAlign(LEFT, CENTER);
|
|
389
|
-
* textFont('Courier New');
|
|
390
|
-
* textSize(12);
|
|
391
|
-
*
|
|
392
|
-
* // Display the text.
|
|
393
|
-
* text(lastLine, 10, 50, 90);
|
|
394
|
-
*
|
|
395
|
-
* describe('The text "I talk like an orange" written in black on a gray background.');
|
|
396
|
-
* }
|
|
397
|
-
*
|
|
398
|
-
* // Select the last line from the text.
|
|
399
|
-
* function handleData(data) {
|
|
400
|
-
* lastLine = data[data.length - 1];
|
|
401
|
-
* }
|
|
402
|
-
* </code>
|
|
403
|
-
* </div>
|
|
404
|
-
*
|
|
405
|
-
* <div>
|
|
406
|
-
* <code>
|
|
407
|
-
* let lastLine;
|
|
408
|
-
*
|
|
409
|
-
* // Load the text and preprocess it.
|
|
410
|
-
* async function setup() {
|
|
411
|
-
* await loadStrings('assets/test.txt', handleData, handleError);
|
|
412
|
-
*
|
|
413
|
-
* createCanvas(100, 100);
|
|
414
|
-
*
|
|
415
|
-
* background(200);
|
|
416
|
-
*
|
|
417
|
-
* // Style the text.
|
|
418
|
-
* textAlign(LEFT, CENTER);
|
|
419
|
-
* textFont('Courier New');
|
|
420
|
-
* textSize(12);
|
|
421
|
-
*
|
|
422
|
-
* // Display the text.
|
|
423
|
-
* text(lastLine, 10, 50, 90);
|
|
424
|
-
*
|
|
425
|
-
* describe('The text "I talk like an orange" written in black on a gray background.');
|
|
426
|
-
* }
|
|
427
|
-
*
|
|
428
|
-
* // Select the last line from the text.
|
|
429
|
-
* function handleData(data) {
|
|
430
|
-
* lastLine = data[data.length - 1];
|
|
431
|
-
* }
|
|
432
|
-
*
|
|
433
|
-
* // Log any errors to the console.
|
|
434
|
-
* function handleError(error) {
|
|
435
|
-
* console.error('Oops!', error);
|
|
436
|
-
* }
|
|
437
|
-
* </code>
|
|
438
|
-
* </div>
|
|
439
|
-
*/
|
|
440
|
-
fn.loadStrings = async function (path, successCallback, errorCallback) {
|
|
441
|
-
// p5._validateParameters('loadStrings', arguments);
|
|
442
|
-
|
|
443
|
-
try{
|
|
444
|
-
let { data } = await request(path, 'text');
|
|
445
|
-
data = data.split(/\r?\n/);
|
|
446
|
-
|
|
447
|
-
if (successCallback) return successCallback(data);
|
|
448
|
-
return data;
|
|
449
|
-
} catch(err) {
|
|
450
|
-
p5._friendlyFileLoadError(3, path);
|
|
451
|
-
if(errorCallback) {
|
|
452
|
-
return errorCallback(err);
|
|
453
|
-
} else {
|
|
454
|
-
throw err;
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Reads the contents of a file or URL and creates a <a href="#/p5.Table">p5.Table</a> object with
|
|
461
|
-
* its values. If a file is specified, it must be located in the sketch's
|
|
462
|
-
* "data" folder. The filename parameter can also be a URL to a file found
|
|
463
|
-
* online. By default, the file is assumed to be comma-separated (in CSV
|
|
464
|
-
* format). Table only looks for a header row if the 'header' option is
|
|
465
|
-
* included.
|
|
466
|
-
*
|
|
467
|
-
* This function returns a `Promise` and should be used in an `async` setup with
|
|
468
|
-
* `await`. See the examples for the usage syntax.
|
|
469
|
-
*
|
|
470
|
-
* All files loaded and saved use UTF-8 encoding. This method is suitable for fetching files up to size of 64MB.
|
|
471
|
-
*
|
|
472
|
-
* @method loadTable
|
|
473
|
-
* @deprecated p5.Table will be removed in a future version of p5.js to make way for a new, friendlier version :)
|
|
474
|
-
* @param {String|Request} filename name of the file or URL to load
|
|
475
|
-
* @param {String} [separator] the separator character used by the file, defaults to `','`
|
|
476
|
-
* @param {String} [header] "header" to indicate table has header row
|
|
477
|
-
* @param {Function} [callback] function to be executed after
|
|
478
|
-
* <a href="#/p5/loadTable">loadTable()</a> completes. On success, the
|
|
479
|
-
* <a href="#/p5.Table">Table</a> object is passed in as the
|
|
480
|
-
* first argument.
|
|
481
|
-
* @param {Function} [errorCallback] function to be executed if
|
|
482
|
-
* there is an error, response is passed
|
|
483
|
-
* in as first argument
|
|
484
|
-
* @return {Promise<Object>} <a href="#/p5.Table">Table</a> object containing data
|
|
485
|
-
*
|
|
486
|
-
* @example
|
|
487
|
-
* <div class='norender'>
|
|
488
|
-
* <code>
|
|
489
|
-
* let table;
|
|
490
|
-
*
|
|
491
|
-
* async function setup() {
|
|
492
|
-
* // Create a 200x200 canvas
|
|
493
|
-
* createCanvas(200, 200);
|
|
494
|
-
*
|
|
495
|
-
* // Load the CSV file with a header row
|
|
496
|
-
* table = await loadTable('assets/mammals.csv', ',', 'header');
|
|
497
|
-
*
|
|
498
|
-
* // Get the second row (index 1)
|
|
499
|
-
* let row = table.getRow(1);
|
|
500
|
-
*
|
|
501
|
-
* // Set text properties
|
|
502
|
-
* fill(0); // Set text color to black
|
|
503
|
-
* textSize(16); // Adjust text size as needed
|
|
504
|
-
*
|
|
505
|
-
* // Display each column value in the row on the canvas.
|
|
506
|
-
* // Using an offset for y-position so each value appears on a new line.
|
|
507
|
-
* for (let c = 0; c < table.getColumnCount(); c++) {
|
|
508
|
-
* text(row.getString(c), 10, 30 + c * 20);
|
|
509
|
-
* }
|
|
510
|
-
* }
|
|
511
|
-
* </code>
|
|
512
|
-
* </div>
|
|
513
|
-
*/
|
|
514
|
-
fn.loadTable = async function (path, separator, header, successCallback, errorCallback) {
|
|
515
|
-
if(typeof arguments[arguments.length-1] === 'function'){
|
|
516
|
-
if(typeof arguments[arguments.length-2] === 'function'){
|
|
517
|
-
successCallback = arguments[arguments.length-2];
|
|
518
|
-
errorCallback = arguments[arguments.length-1];
|
|
519
|
-
}else{
|
|
520
|
-
successCallback = arguments[arguments.length-1];
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
if(typeof separator !== 'string') separator = ',';
|
|
525
|
-
if(typeof header === 'function') header = false;
|
|
526
|
-
|
|
527
|
-
try{
|
|
528
|
-
let { data } = await request(path, 'text');
|
|
529
|
-
|
|
530
|
-
let ret = new p5.Table();
|
|
531
|
-
data = parse(data, {
|
|
532
|
-
separator
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
if(header){
|
|
536
|
-
ret.columns = data.shift();
|
|
537
|
-
}else{
|
|
538
|
-
ret.columns = Array(data[0].length).fill(null);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
data.forEach((line) => {
|
|
542
|
-
const row = new p5.TableRow(line);
|
|
543
|
-
ret.addRow(row);
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
if (successCallback) {
|
|
547
|
-
return successCallback(ret);
|
|
548
|
-
} else {
|
|
549
|
-
return ret;
|
|
550
|
-
}
|
|
551
|
-
} catch(err) {
|
|
552
|
-
p5._friendlyFileLoadError(2, path);
|
|
553
|
-
if(errorCallback) {
|
|
554
|
-
return errorCallback(err);
|
|
555
|
-
} else {
|
|
556
|
-
throw err;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* Loads an XML file to create a <a href="#/p5.XML">p5.XML</a> object.
|
|
563
|
-
*
|
|
564
|
-
* Extensible Markup Language
|
|
565
|
-
* (<a href="https://developer.mozilla.org/en-US/docs/Web/XML/XML_introduction" target="_blank">XML</a>)
|
|
566
|
-
* is a standard format for sending data between applications. Like HTML, the
|
|
567
|
-
* XML format is based on tags and attributes, as in
|
|
568
|
-
* `<time units="s">1234</time>`.
|
|
569
|
-
*
|
|
570
|
-
* The first parameter, `path`, is always a string with the path to the file.
|
|
571
|
-
* Paths to local files should be relative, as in
|
|
572
|
-
* `loadXML('assets/data.xml')`. URLs such as `'https://example.com/data.xml'`
|
|
573
|
-
* may be blocked due to browser security. The `path` parameter can also be defined
|
|
574
|
-
* as a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
575
|
-
* object for more advanced usage.
|
|
576
|
-
*
|
|
577
|
-
* The second parameter, `successCallback`, is optional. If a function is
|
|
578
|
-
* passed, as in `loadXML('assets/data.xml', handleData)`, then the
|
|
579
|
-
* `handleData()` function will be called once the data loads. The
|
|
580
|
-
* <a href="#/p5.XML">p5.XML</a> object created from the data will be passed
|
|
581
|
-
* to `handleData()` as its only argument. The return value of the `handleData()`
|
|
582
|
-
* function will be used as the final return value of `loadXML('assets/data.xml', handleData)`.
|
|
583
|
-
*
|
|
584
|
-
* The third parameter, `failureCallback`, is also optional. If a function is
|
|
585
|
-
* passed, as in `loadXML('assets/data.xml', handleData, handleFailure)`, then
|
|
586
|
-
* the `handleFailure()` function will be called if an error occurs while
|
|
587
|
-
* loading. The `Error` object will be passed to `handleFailure()` as its only
|
|
588
|
-
* argument. The return value of the `handleFailure()` function will be used as the
|
|
589
|
-
* final return value of `loadXML('assets/data.xml', handleData, handleFailure)`.
|
|
590
|
-
*
|
|
591
|
-
* This function returns a `Promise` and should be used in an `async` setup with
|
|
592
|
-
* `await`. See the examples for the usage syntax.
|
|
593
|
-
*
|
|
594
|
-
* @method loadXML
|
|
595
|
-
* @param {String|Request} path path of the XML file to be loaded.
|
|
596
|
-
* @param {Function} [successCallback] function to call once the data is
|
|
597
|
-
* loaded. Will be passed the
|
|
598
|
-
* <a href="#/p5.XML">p5.XML</a> object.
|
|
599
|
-
* @param {Function} [errorCallback] function to call if the data fails to
|
|
600
|
-
* load. Will be passed an `Error` event
|
|
601
|
-
* object.
|
|
602
|
-
* @return {Promise<p5.XML>} XML data loaded into a <a href="#/p5.XML">p5.XML</a>
|
|
603
|
-
* object.
|
|
604
|
-
*
|
|
605
|
-
* @example
|
|
606
|
-
* <div>
|
|
607
|
-
* <code>
|
|
608
|
-
* let myXML;
|
|
609
|
-
*
|
|
610
|
-
* // Load the XML and create a p5.XML object.
|
|
611
|
-
* async function setup() {
|
|
612
|
-
* myXML = await loadXML('assets/animals.xml');
|
|
613
|
-
*
|
|
614
|
-
* createCanvas(100, 100);
|
|
615
|
-
*
|
|
616
|
-
* background(200);
|
|
617
|
-
*
|
|
618
|
-
* // Get an array with all mammal tags.
|
|
619
|
-
* let mammals = myXML.getChildren('mammal');
|
|
620
|
-
*
|
|
621
|
-
* // Style the text.
|
|
622
|
-
* textAlign(LEFT, CENTER);
|
|
623
|
-
* textFont('Courier New');
|
|
624
|
-
* textSize(14);
|
|
625
|
-
*
|
|
626
|
-
* // Iterate over the mammals array.
|
|
627
|
-
* for (let i = 0; i < mammals.length; i += 1) {
|
|
628
|
-
*
|
|
629
|
-
* // Calculate the y-coordinate.
|
|
630
|
-
* let y = (i + 1) * 25;
|
|
631
|
-
*
|
|
632
|
-
* // Get the mammal's common name.
|
|
633
|
-
* let name = mammals[i].getContent();
|
|
634
|
-
*
|
|
635
|
-
* // Display the mammal's name.
|
|
636
|
-
* text(name, 20, y);
|
|
637
|
-
* }
|
|
638
|
-
*
|
|
639
|
-
* describe(
|
|
640
|
-
* 'The words "Goat", "Leopard", and "Zebra" written on three separate lines. The text is black on a gray background.'
|
|
641
|
-
* );
|
|
642
|
-
* }
|
|
643
|
-
* </code>
|
|
644
|
-
* </div>
|
|
645
|
-
*
|
|
646
|
-
* <div>
|
|
647
|
-
* <code>
|
|
648
|
-
* let lastMammal;
|
|
649
|
-
*
|
|
650
|
-
* // Load the XML and create a p5.XML object.
|
|
651
|
-
* async function setup() {
|
|
652
|
-
* await loadXML('assets/animals.xml', handleData);
|
|
653
|
-
*
|
|
654
|
-
* createCanvas(100, 100);
|
|
655
|
-
*
|
|
656
|
-
* background(200);
|
|
657
|
-
*
|
|
658
|
-
* // Style the text.
|
|
659
|
-
* textAlign(CENTER, CENTER);
|
|
660
|
-
* textFont('Courier New');
|
|
661
|
-
* textSize(16);
|
|
662
|
-
*
|
|
663
|
-
* // Display the content of the last mammal element.
|
|
664
|
-
* text(lastMammal, 50, 50);
|
|
665
|
-
*
|
|
666
|
-
* describe('The word "Zebra" written in black on a gray background.');
|
|
667
|
-
* }
|
|
668
|
-
*
|
|
669
|
-
* // Get the content of the last mammal element.
|
|
670
|
-
* function handleData(data) {
|
|
671
|
-
* // Get an array with all mammal elements.
|
|
672
|
-
* let mammals = data.getChildren('mammal');
|
|
673
|
-
*
|
|
674
|
-
* // Get the content of the last mammal.
|
|
675
|
-
* lastMammal = mammals[mammals.length - 1].getContent();
|
|
676
|
-
* }
|
|
677
|
-
* </code>
|
|
678
|
-
* </div>
|
|
679
|
-
*
|
|
680
|
-
* <div>
|
|
681
|
-
* <code>
|
|
682
|
-
* let lastMammal;
|
|
683
|
-
*
|
|
684
|
-
* // Load the XML and preprocess it.
|
|
685
|
-
* async function setup() {
|
|
686
|
-
* await loadXML('assets/animals.xml', handleData, handleError);
|
|
687
|
-
*
|
|
688
|
-
* createCanvas(100, 100);
|
|
689
|
-
*
|
|
690
|
-
* background(200);
|
|
691
|
-
*
|
|
692
|
-
* // Style the text.
|
|
693
|
-
* textAlign(CENTER, CENTER);
|
|
694
|
-
* textFont('Courier New');
|
|
695
|
-
* textSize(16);
|
|
696
|
-
*
|
|
697
|
-
* // Display the content of the last mammal element.
|
|
698
|
-
* text(lastMammal, 50, 50);
|
|
699
|
-
*
|
|
700
|
-
* describe('The word "Zebra" written in black on a gray background.');
|
|
701
|
-
* }
|
|
702
|
-
*
|
|
703
|
-
* // Get the content of the last mammal element.
|
|
704
|
-
* function handleData(data) {
|
|
705
|
-
* // Get an array with all mammal elements.
|
|
706
|
-
* let mammals = data.getChildren('mammal');
|
|
707
|
-
*
|
|
708
|
-
* // Get the content of the last mammal.
|
|
709
|
-
* lastMammal = mammals[mammals.length - 1].getContent();
|
|
710
|
-
* }
|
|
711
|
-
*
|
|
712
|
-
* // Log any errors to the console.
|
|
713
|
-
* function handleError(error) {
|
|
714
|
-
* console.error('Oops!', error);
|
|
715
|
-
* }
|
|
716
|
-
* </code>
|
|
717
|
-
* </div>
|
|
718
|
-
*/
|
|
719
|
-
fn.loadXML = async function (path, successCallback, errorCallback) {
|
|
720
|
-
try{
|
|
721
|
-
const parser = new DOMParser();
|
|
722
|
-
|
|
723
|
-
let { data } = await request(path, 'text');
|
|
724
|
-
const parsedDOM = parser.parseFromString(data, 'application/xml');
|
|
725
|
-
data = new p5.XML(parsedDOM);
|
|
726
|
-
|
|
727
|
-
if (successCallback) return successCallback(data);
|
|
728
|
-
return data;
|
|
729
|
-
} catch(err) {
|
|
730
|
-
p5._friendlyFileLoadError(1, path);
|
|
731
|
-
if(errorCallback) {
|
|
732
|
-
return errorCallback(err);
|
|
733
|
-
} else {
|
|
734
|
-
throw err;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
};
|
|
738
|
-
|
|
739
|
-
/**
|
|
740
|
-
* This method is suitable for fetching files up to size of 64MB.
|
|
741
|
-
*
|
|
742
|
-
* @method loadBytes
|
|
743
|
-
* @param {String|Request} file name of the file or URL to load
|
|
744
|
-
* @param {Function} [callback] function to be executed after <a href="#/p5/loadBytes">loadBytes()</a>
|
|
745
|
-
* completes
|
|
746
|
-
* @param {Function} [errorCallback] function to be executed if there
|
|
747
|
-
* is an error
|
|
748
|
-
* @returns {Promise<Uint8Array>} a Uint8Array containing the loaded buffer
|
|
749
|
-
*
|
|
750
|
-
* @example
|
|
751
|
-
*
|
|
752
|
-
* <div>
|
|
753
|
-
* <code>
|
|
754
|
-
* let data;
|
|
755
|
-
*
|
|
756
|
-
* async function setup() {
|
|
757
|
-
* createCanvas(100, 100); // Create a canvas
|
|
758
|
-
* data = await loadBytes('assets/mammals.xml'); // Load the bytes from the XML file
|
|
759
|
-
*
|
|
760
|
-
* background(255); // Set a white background
|
|
761
|
-
* fill(0); // Set text color to black
|
|
762
|
-
*
|
|
763
|
-
* // Display the first 5 byte values on the canvas in hexadecimal format
|
|
764
|
-
* for (let i = 0; i < 5; i++) {
|
|
765
|
-
* let byteHex = data[i].toString(16);
|
|
766
|
-
* text(byteHex, 10, 18 * (i + 1)); // Adjust spacing as needed
|
|
767
|
-
* }
|
|
768
|
-
*
|
|
769
|
-
* describe('no image displayed, displays first 5 bytes of mammals.xml in hexadecimal format');
|
|
770
|
-
* }
|
|
771
|
-
* </code>
|
|
772
|
-
* </div>
|
|
773
|
-
*/
|
|
774
|
-
|
|
775
|
-
fn.loadBytes = async function (path, successCallback, errorCallback) {
|
|
776
|
-
try{
|
|
777
|
-
let { data } = await request(path, 'arrayBuffer');
|
|
778
|
-
data = new Uint8Array(data);
|
|
779
|
-
if (successCallback) return successCallback(data);
|
|
780
|
-
return data;
|
|
781
|
-
} catch(err) {
|
|
782
|
-
p5._friendlyFileLoadError(6, path);
|
|
783
|
-
if(errorCallback) {
|
|
784
|
-
return errorCallback(err);
|
|
785
|
-
} else {
|
|
786
|
-
throw err;
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
|
|
791
|
-
/**
|
|
792
|
-
* Loads a file at the given path as a Blob, then returns the resulting data or
|
|
793
|
-
* passes it to a success callback function, if provided. On load, this function
|
|
794
|
-
* returns a `Promise` that resolves to a Blob containing the file data.
|
|
795
|
-
*
|
|
796
|
-
* @method loadBlob
|
|
797
|
-
* @param {String|Request} path - The path or Request object pointing to the file
|
|
798
|
-
* you want to load.
|
|
799
|
-
* @param {Function} [successCallback] - Optional. A function to be called if the
|
|
800
|
-
* file successfully loads, receiving the
|
|
801
|
-
* resulting Blob as its only argument.
|
|
802
|
-
* @param {Function} [errorCallback] - Optional. A function to be called if an
|
|
803
|
-
* error occurs during loading; receives the
|
|
804
|
-
* error object as its only argument.
|
|
805
|
-
* @returns {Promise<Blob>} A promise that resolves with the loaded Blob.
|
|
806
|
-
*
|
|
807
|
-
* @example
|
|
808
|
-
* <div>
|
|
809
|
-
* <code>
|
|
810
|
-
* let myBlob;
|
|
811
|
-
*
|
|
812
|
-
* async function setup() {
|
|
813
|
-
* createCanvas(200, 200);
|
|
814
|
-
* background(220);
|
|
815
|
-
* try {
|
|
816
|
-
* // 1. Load an image file as a Blob.
|
|
817
|
-
* myBlob = await loadBlob('assets/flower-1.png');
|
|
818
|
-
*
|
|
819
|
-
* // 2. Convert the Blob into an object URL.
|
|
820
|
-
* const objectUrl = URL.createObjectURL(myBlob);
|
|
821
|
-
*
|
|
822
|
-
* // 3. Load that object URL into a p5.Image.
|
|
823
|
-
* loadImage(objectUrl, (img) => {
|
|
824
|
-
* // 4. Display the loaded image.
|
|
825
|
-
* image(img, 0, 0, width, height);
|
|
826
|
-
* });
|
|
827
|
-
* } catch (err) {
|
|
828
|
-
* console.error('Error loading blob:', err);
|
|
829
|
-
* }
|
|
830
|
-
* }
|
|
831
|
-
* </code>
|
|
832
|
-
* </div>
|
|
833
|
-
*/
|
|
834
|
-
fn.loadBlob = async function(path, successCallback, errorCallback) {
|
|
835
|
-
try{
|
|
836
|
-
const { data } = await request(path, 'blob');
|
|
837
|
-
if (successCallback) return successCallback(data);
|
|
838
|
-
return data;
|
|
839
|
-
} catch(err) {
|
|
840
|
-
if(errorCallback) {
|
|
841
|
-
return errorCallback(err);
|
|
842
|
-
} else {
|
|
843
|
-
throw err;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
};
|
|
847
|
-
|
|
848
|
-
/**
|
|
849
|
-
* Method for executing an HTTP GET request. If data type is not specified,
|
|
850
|
-
* it will default to `'text'`. This is equivalent to
|
|
851
|
-
* calling <code>httpDo(path, 'GET')</code>. The 'binary' datatype will return
|
|
852
|
-
* a Blob object, and the 'arrayBuffer' datatype will return an ArrayBuffer
|
|
853
|
-
* which can be used to initialize typed arrays (such as Uint8Array).
|
|
854
|
-
*
|
|
855
|
-
* @method httpGet
|
|
856
|
-
* @param {String|Request} path name of the file or url to load
|
|
857
|
-
* @param {String} [datatype] "json", "jsonp", "binary", "arrayBuffer",
|
|
858
|
-
* "xml", or "text"
|
|
859
|
-
* @param {Function} [callback] function to be executed after
|
|
860
|
-
* <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in
|
|
861
|
-
* as first argument
|
|
862
|
-
* @param {Function} [errorCallback] function to be executed if
|
|
863
|
-
* there is an error, response is passed
|
|
864
|
-
* in as first argument
|
|
865
|
-
* @return {Promise} A promise that resolves with the data when the operation
|
|
866
|
-
* completes successfully or rejects with the error after
|
|
867
|
-
* one occurs.
|
|
868
|
-
* @example
|
|
869
|
-
* <div class='norender'><code>
|
|
870
|
-
* // Examples use USGS Earthquake API:
|
|
871
|
-
* // https://earthquake.usgs.gov/fdsnws/event/1/#methods
|
|
872
|
-
* let earthquakes;
|
|
873
|
-
* async function setup() {
|
|
874
|
-
* // Get the most recent earthquake in the database
|
|
875
|
-
* let url =
|
|
876
|
-
'https://earthquake.usgs.gov/fdsnws/event/1/query?' +
|
|
877
|
-
* 'format=geojson&limit=1&orderby=time';
|
|
878
|
-
* earthquakes = await httpGet(url, 'json');
|
|
879
|
-
* }
|
|
880
|
-
*
|
|
881
|
-
* function draw() {
|
|
882
|
-
* if (!earthquakes) {
|
|
883
|
-
* // Wait until the earthquake data has loaded before drawing.
|
|
884
|
-
* return;
|
|
885
|
-
* }
|
|
886
|
-
* background(200);
|
|
887
|
-
* // Get the magnitude and name of the earthquake out of the loaded JSON
|
|
888
|
-
* let earthquakeMag = earthquakes.features[0].properties.mag;
|
|
889
|
-
* let earthquakeName = earthquakes.features[0].properties.place;
|
|
890
|
-
* ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
|
|
891
|
-
* textAlign(CENTER);
|
|
892
|
-
* text(earthquakeName, 0, height - 30, width, 30);
|
|
893
|
-
* noLoop();
|
|
894
|
-
* }
|
|
895
|
-
* </code></div>
|
|
896
|
-
*/
|
|
897
|
-
/**
|
|
898
|
-
* @method httpGet
|
|
899
|
-
* @param {String|Request} path
|
|
900
|
-
* @param {Function} callback
|
|
901
|
-
* @param {Function} [errorCallback]
|
|
902
|
-
* @return {Promise}
|
|
903
|
-
*/
|
|
904
|
-
fn.httpGet = async function (path, datatype='text', successCallback, errorCallback) {
|
|
905
|
-
// p5._validateParameters('httpGet', arguments);
|
|
906
|
-
|
|
907
|
-
if (typeof datatype === 'function') {
|
|
908
|
-
errorCallback = successCallback;
|
|
909
|
-
successCallback = datatype;
|
|
910
|
-
datatype = 'text';
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
// This is like a more primitive version of the other load functions.
|
|
914
|
-
// If the user wanted to customize more behavior, pass in Request to path.
|
|
915
|
-
|
|
916
|
-
return this.httpDo(path, 'GET', datatype, successCallback, errorCallback);
|
|
917
|
-
};
|
|
918
|
-
|
|
919
|
-
/**
|
|
920
|
-
* Method for executing an HTTP POST request. If data type is not specified,
|
|
921
|
-
* it will default to `'text'`. This is equivalent to
|
|
922
|
-
* calling <code>httpDo(path, 'POST')</code>.
|
|
923
|
-
*
|
|
924
|
-
* @method httpPost
|
|
925
|
-
* @param {String|Request} path name of the file or url to load
|
|
926
|
-
* @param {Object|Boolean} [data] param data passed sent with request
|
|
927
|
-
* @param {String} [datatype] "json", "jsonp", "xml", or "text".
|
|
928
|
-
* If omitted, <a href="#/p5/httpPost">httpPost()</a> will guess.
|
|
929
|
-
* @param {Function} [callback] function to be executed after
|
|
930
|
-
* <a href="#/p5/httpPost">httpPost()</a> completes, data is passed in
|
|
931
|
-
* as first argument
|
|
932
|
-
* @param {Function} [errorCallback] function to be executed if
|
|
933
|
-
* there is an error, response is passed
|
|
934
|
-
* in as first argument
|
|
935
|
-
* @return {Promise} A promise that resolves with the data when the operation
|
|
936
|
-
* completes successfully or rejects with the error after
|
|
937
|
-
* one occurs.
|
|
938
|
-
*
|
|
939
|
-
* @example
|
|
940
|
-
* <div>
|
|
941
|
-
* <code>
|
|
942
|
-
* // Examples use jsonplaceholder.typicode.com for a Mock Data API
|
|
943
|
-
*
|
|
944
|
-
* let url = 'https://jsonplaceholder.typicode.com/posts';
|
|
945
|
-
* let postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is very cool.' };
|
|
946
|
-
*
|
|
947
|
-
* function setup() {
|
|
948
|
-
* createCanvas(100, 100);
|
|
949
|
-
* background(200);
|
|
950
|
-
* }
|
|
951
|
-
*
|
|
952
|
-
* function mousePressed() {
|
|
953
|
-
* httpPost(url, 'json', postData, function(result) {
|
|
954
|
-
* strokeWeight(2);
|
|
955
|
-
* text(result.body, mouseX, mouseY);
|
|
956
|
-
* });
|
|
957
|
-
* }
|
|
958
|
-
* </code>
|
|
959
|
-
* </div>
|
|
960
|
-
*
|
|
961
|
-
* <div><code>
|
|
962
|
-
* let url = 'ttps://invalidURL'; // A bad URL that will cause errors
|
|
963
|
-
* let postData = { title: 'p5 Clicked!', body: 'p5.js is very cool.' };
|
|
964
|
-
*
|
|
965
|
-
* function setup() {
|
|
966
|
-
* createCanvas(100, 100);
|
|
967
|
-
* background(200);
|
|
968
|
-
* }
|
|
969
|
-
*
|
|
970
|
-
* function mousePressed() {
|
|
971
|
-
* httpPost(
|
|
972
|
-
* url,
|
|
973
|
-
* 'json',
|
|
974
|
-
* postData,
|
|
975
|
-
* function(result) {
|
|
976
|
-
* // ... won't be called
|
|
977
|
-
* },
|
|
978
|
-
* function(error) {
|
|
979
|
-
* strokeWeight(2);
|
|
980
|
-
* text(error.toString(), mouseX, mouseY);
|
|
981
|
-
* }
|
|
982
|
-
* );
|
|
983
|
-
* }
|
|
984
|
-
* </code></div>
|
|
985
|
-
*/
|
|
986
|
-
/**
|
|
987
|
-
* @method httpPost
|
|
988
|
-
* @param {String|Request} path
|
|
989
|
-
* @param {Object|Boolean} data
|
|
990
|
-
* @param {Function} [callback]
|
|
991
|
-
* @param {Function} [errorCallback]
|
|
992
|
-
* @return {Promise}
|
|
993
|
-
*/
|
|
994
|
-
/**
|
|
995
|
-
* @method httpPost
|
|
996
|
-
* @param {String|Request} path
|
|
997
|
-
* @param {Function} [callback]
|
|
998
|
-
* @param {Function} [errorCallback]
|
|
999
|
-
* @return {Promise}
|
|
1000
|
-
*/
|
|
1001
|
-
fn.httpPost = async function (path, data, datatype='text', successCallback, errorCallback) {
|
|
1002
|
-
// p5._validateParameters('httpPost', arguments);
|
|
1003
|
-
|
|
1004
|
-
// This behave similarly to httpGet and additional options should be passed
|
|
1005
|
-
// as a `Request`` to path. Both method and body will be overridden.
|
|
1006
|
-
// Will try to infer correct Content-Type for given data.
|
|
1007
|
-
|
|
1008
|
-
if (typeof data === 'function') {
|
|
1009
|
-
// Assume both data and datatype are functions as data should not be function
|
|
1010
|
-
successCallback = data;
|
|
1011
|
-
errorCallback = datatype;
|
|
1012
|
-
data = undefined;
|
|
1013
|
-
datatype = 'text';
|
|
1014
|
-
|
|
1015
|
-
} else if (typeof datatype === 'function') {
|
|
1016
|
-
// Data is provided but not datatype\
|
|
1017
|
-
errorCallback = successCallback;
|
|
1018
|
-
successCallback = datatype;
|
|
1019
|
-
datatype = 'text';
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
let reqData = data;
|
|
1023
|
-
let contentType = 'text/plain';
|
|
1024
|
-
// Normalize data
|
|
1025
|
-
if(data instanceof p5.XML) {
|
|
1026
|
-
reqData = data.serialize();
|
|
1027
|
-
contentType = 'application/xml';
|
|
1028
|
-
|
|
1029
|
-
} else if(data instanceof p5.Image) {
|
|
1030
|
-
reqData = await data.toBlob();
|
|
1031
|
-
contentType = 'image/png';
|
|
1032
|
-
|
|
1033
|
-
} else if (typeof data === 'object') {
|
|
1034
|
-
reqData = JSON.stringify(data);
|
|
1035
|
-
contentType = 'application/json';
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
const requestOptions = {
|
|
1039
|
-
method: 'POST',
|
|
1040
|
-
body: reqData,
|
|
1041
|
-
headers: {
|
|
1042
|
-
'Content-Type': contentType
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1045
|
-
|
|
1046
|
-
if (reqData) {
|
|
1047
|
-
requestOptions.body = reqData;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
const req = new Request(path, requestOptions);
|
|
1051
|
-
|
|
1052
|
-
return this.httpDo(req, 'POST', datatype, successCallback, errorCallback);
|
|
1053
|
-
};
|
|
1054
|
-
|
|
1055
|
-
/**
|
|
1056
|
-
* Method for executing an HTTP request. If data type is not specified,
|
|
1057
|
-
* it will default to `'text'`.
|
|
1058
|
-
*
|
|
1059
|
-
* This function is meant for more advanced usage of HTTP requests in p5.js. It is
|
|
1060
|
-
* best used when a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
1061
|
-
* object is passed to the `path` parameter.
|
|
1062
|
-
*
|
|
1063
|
-
* This method is suitable for fetching files up to size of 64MB when "GET" is used.
|
|
1064
|
-
*
|
|
1065
|
-
* @method httpDo
|
|
1066
|
-
* @param {String|Request} path name of the file or url to load
|
|
1067
|
-
* @param {String} [method] either "GET", "POST", "PUT", "DELETE",
|
|
1068
|
-
* or other HTTP request methods
|
|
1069
|
-
* @param {String} [datatype] "json", "jsonp", "xml", or "text"
|
|
1070
|
-
* @param {Object} [data] param data passed sent with request
|
|
1071
|
-
* @param {Function} [callback] function to be executed after
|
|
1072
|
-
* <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in
|
|
1073
|
-
* as first argument
|
|
1074
|
-
* @param {Function} [errorCallback] function to be executed if
|
|
1075
|
-
* there is an error, response is passed
|
|
1076
|
-
* in as first argument
|
|
1077
|
-
* @return {Promise} A promise that resolves with the data when the operation
|
|
1078
|
-
* completes successfully or rejects with the error after
|
|
1079
|
-
* one occurs.
|
|
1080
|
-
*
|
|
1081
|
-
* @example
|
|
1082
|
-
* <div>
|
|
1083
|
-
* <code>
|
|
1084
|
-
* // Examples use USGS Earthquake API:
|
|
1085
|
-
* // https://earthquake.usgs.gov/fdsnws/event/1/#methods
|
|
1086
|
-
*
|
|
1087
|
-
* // displays an animation of all USGS earthquakes
|
|
1088
|
-
* let earthquakes;
|
|
1089
|
-
* let eqFeatureIndex = 0;
|
|
1090
|
-
*
|
|
1091
|
-
* function setup() {
|
|
1092
|
-
* let url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson';
|
|
1093
|
-
* httpDo(
|
|
1094
|
-
* url,
|
|
1095
|
-
* {
|
|
1096
|
-
* method: 'GET',
|
|
1097
|
-
* // Other Request options, like special headers for apis
|
|
1098
|
-
* headers: { authorization: 'Bearer secretKey' }
|
|
1099
|
-
* },
|
|
1100
|
-
* function(res) {
|
|
1101
|
-
* earthquakes = res;
|
|
1102
|
-
* }
|
|
1103
|
-
* );
|
|
1104
|
-
* }
|
|
1105
|
-
*
|
|
1106
|
-
* function draw() {
|
|
1107
|
-
* // wait until the data is loaded
|
|
1108
|
-
* if (!earthquakes || !earthquakes.features[eqFeatureIndex]) {
|
|
1109
|
-
* return;
|
|
1110
|
-
* }
|
|
1111
|
-
* clear();
|
|
1112
|
-
*
|
|
1113
|
-
* let feature = earthquakes.features[eqFeatureIndex];
|
|
1114
|
-
* let mag = feature.properties.mag;
|
|
1115
|
-
* let rad = mag / 11 * ((width + height) / 2);
|
|
1116
|
-
* fill(255, 0, 0, 100);
|
|
1117
|
-
* ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad);
|
|
1118
|
-
*
|
|
1119
|
-
* if (eqFeatureIndex >= earthquakes.features.length) {
|
|
1120
|
-
* eqFeatureIndex = 0;
|
|
1121
|
-
* } else {
|
|
1122
|
-
* eqFeatureIndex += 1;
|
|
1123
|
-
* }
|
|
1124
|
-
* }
|
|
1125
|
-
* </code>
|
|
1126
|
-
* </div>
|
|
1127
|
-
*/
|
|
1128
|
-
/**
|
|
1129
|
-
* @method httpDo
|
|
1130
|
-
* @param {String|Request} path
|
|
1131
|
-
* @param {Function} [callback]
|
|
1132
|
-
* @param {Function} [errorCallback]
|
|
1133
|
-
* @return {Promise}
|
|
1134
|
-
*/
|
|
1135
|
-
fn.httpDo = async function (path, method, datatype, successCallback, errorCallback) {
|
|
1136
|
-
// This behave similarly to httpGet but even more primitive. The user
|
|
1137
|
-
// will most likely want to pass in a Request to path, the only convenience
|
|
1138
|
-
// is that datatype will be taken into account to parse the response.
|
|
1139
|
-
|
|
1140
|
-
if(typeof datatype === 'function'){
|
|
1141
|
-
errorCallback = successCallback;
|
|
1142
|
-
successCallback = datatype;
|
|
1143
|
-
datatype = undefined;
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
// Try to infer data type if it is defined
|
|
1147
|
-
if(!datatype){
|
|
1148
|
-
const extension = typeof path === 'string' ?
|
|
1149
|
-
path.split(".").pop() :
|
|
1150
|
-
path.url.split(".").pop();
|
|
1151
|
-
switch(extension) {
|
|
1152
|
-
case 'json':
|
|
1153
|
-
datatype = 'json';
|
|
1154
|
-
break;
|
|
1155
|
-
|
|
1156
|
-
case 'jpg':
|
|
1157
|
-
case 'jpeg':
|
|
1158
|
-
case 'png':
|
|
1159
|
-
case 'webp':
|
|
1160
|
-
case 'gif':
|
|
1161
|
-
datatype = 'blob';
|
|
1162
|
-
break;
|
|
1163
|
-
|
|
1164
|
-
case 'xml':
|
|
1165
|
-
// NOTE: still need to normalize type handling/mapping
|
|
1166
|
-
// datatype = 'xml';
|
|
1167
|
-
case 'txt':
|
|
1168
|
-
default:
|
|
1169
|
-
datatype = 'text';
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
const req = new Request(path, {
|
|
1174
|
-
method
|
|
1175
|
-
});
|
|
1176
|
-
|
|
1177
|
-
try{
|
|
1178
|
-
const { data } = await request(req, datatype);
|
|
1179
|
-
if (successCallback) {
|
|
1180
|
-
return successCallback(data);
|
|
1181
|
-
} else {
|
|
1182
|
-
return data;
|
|
1183
|
-
}
|
|
1184
|
-
} catch(err) {
|
|
1185
|
-
if(errorCallback) {
|
|
1186
|
-
return errorCallback(err);
|
|
1187
|
-
} else {
|
|
1188
|
-
throw err;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
};
|
|
1192
|
-
|
|
1193
|
-
/**
|
|
1194
|
-
* @module IO
|
|
1195
|
-
* @submodule Output
|
|
1196
|
-
* @for p5
|
|
1197
|
-
*/
|
|
1198
|
-
// private array of p5.PrintWriter objects
|
|
1199
|
-
fn._pWriters = [];
|
|
1200
|
-
|
|
1201
|
-
/**
|
|
1202
|
-
* Creates a new <a href="#/p5.PrintWriter">p5.PrintWriter</a> object.
|
|
1203
|
-
*
|
|
1204
|
-
* <a href="#/p5.PrintWriter">p5.PrintWriter</a> objects provide a way to
|
|
1205
|
-
* save a sequence of text data, called the *print stream*, to the user's
|
|
1206
|
-
* computer. They're low-level objects that enable precise control of text
|
|
1207
|
-
* output. Functions such as
|
|
1208
|
-
* <a href="#/p5/saveStrings">saveStrings()</a> and
|
|
1209
|
-
* <a href="#/p5/saveJSON">saveJSON()</a> are easier to use for simple file
|
|
1210
|
-
* saving.
|
|
1211
|
-
*
|
|
1212
|
-
* The first parameter, `filename`, is the name of the file to be written. If
|
|
1213
|
-
* a string is passed, as in `createWriter('words.txt')`, a new
|
|
1214
|
-
* <a href="#/p5.PrintWriter">p5.PrintWriter</a> object will be created that
|
|
1215
|
-
* writes to a file named `words.txt`.
|
|
1216
|
-
*
|
|
1217
|
-
* The second parameter, `extension`, is optional. If a string is passed, as
|
|
1218
|
-
* in `createWriter('words', 'csv')`, the first parameter will be interpreted
|
|
1219
|
-
* as the file name and the second parameter as the extension.
|
|
1220
|
-
*
|
|
1221
|
-
* @method createWriter
|
|
1222
|
-
* @param {String} name name of the file to create.
|
|
1223
|
-
* @param {String} [extension] format to use for the file.
|
|
1224
|
-
* @return {p5.PrintWriter} stream for writing data.
|
|
1225
|
-
*
|
|
1226
|
-
* @example
|
|
1227
|
-
* <div>
|
|
1228
|
-
* <code>
|
|
1229
|
-
* function setup() {
|
|
1230
|
-
* createCanvas(100, 100);
|
|
1231
|
-
*
|
|
1232
|
-
* background(200);
|
|
1233
|
-
*
|
|
1234
|
-
* // Style the text.
|
|
1235
|
-
* textAlign(LEFT, CENTER);
|
|
1236
|
-
* textFont('Courier New');
|
|
1237
|
-
* textSize(12);
|
|
1238
|
-
*
|
|
1239
|
-
* // Display instructions.
|
|
1240
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1241
|
-
*
|
|
1242
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1243
|
-
* }
|
|
1244
|
-
*
|
|
1245
|
-
* // Save the file when the user double-clicks.
|
|
1246
|
-
* function doubleClicked() {
|
|
1247
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1248
|
-
* // Create a p5.PrintWriter object.
|
|
1249
|
-
* let myWriter = createWriter('xo.txt');
|
|
1250
|
-
*
|
|
1251
|
-
* // Add some lines to the print stream.
|
|
1252
|
-
* myWriter.print('XOO');
|
|
1253
|
-
* myWriter.print('OXO');
|
|
1254
|
-
* myWriter.print('OOX');
|
|
1255
|
-
*
|
|
1256
|
-
* // Save the file and close the print stream.
|
|
1257
|
-
* myWriter.close();
|
|
1258
|
-
* }
|
|
1259
|
-
* }
|
|
1260
|
-
* </code>
|
|
1261
|
-
* </div>
|
|
1262
|
-
*
|
|
1263
|
-
* <div>
|
|
1264
|
-
* <code>
|
|
1265
|
-
* function setup() {
|
|
1266
|
-
* createCanvas(100, 100);
|
|
1267
|
-
*
|
|
1268
|
-
* background(200);
|
|
1269
|
-
*
|
|
1270
|
-
* // Style the text.
|
|
1271
|
-
* textAlign(LEFT, CENTER);
|
|
1272
|
-
* textFont('Courier New');
|
|
1273
|
-
* textSize(12);
|
|
1274
|
-
*
|
|
1275
|
-
* // Display instructions.
|
|
1276
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1277
|
-
*
|
|
1278
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1279
|
-
* }
|
|
1280
|
-
*
|
|
1281
|
-
* // Save the file when the user double-clicks.
|
|
1282
|
-
* function doubleClicked() {
|
|
1283
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1284
|
-
* // Create a p5.PrintWriter object.
|
|
1285
|
-
* // Use the file format .csv.
|
|
1286
|
-
* let myWriter = createWriter('mauna_loa_co2', 'csv');
|
|
1287
|
-
*
|
|
1288
|
-
* // Add some lines to the print stream.
|
|
1289
|
-
* myWriter.print('date,ppm_co2');
|
|
1290
|
-
* myWriter.print('1960-01-01,316.43');
|
|
1291
|
-
* myWriter.print('1970-01-01,325.06');
|
|
1292
|
-
* myWriter.print('1980-01-01,337.9');
|
|
1293
|
-
* myWriter.print('1990-01-01,353.86');
|
|
1294
|
-
* myWriter.print('2000-01-01,369.45');
|
|
1295
|
-
* myWriter.print('2020-01-01,413.61');
|
|
1296
|
-
*
|
|
1297
|
-
* // Save the file and close the print stream.
|
|
1298
|
-
* myWriter.close();
|
|
1299
|
-
* }
|
|
1300
|
-
* }
|
|
1301
|
-
* </code>
|
|
1302
|
-
* </div>
|
|
1303
|
-
*/
|
|
1304
|
-
fn.createWriter = function (name, extension) {
|
|
1305
|
-
let newPW;
|
|
1306
|
-
// check that it doesn't already exist
|
|
1307
|
-
for (const i in fn._pWriters) {
|
|
1308
|
-
if (fn._pWriters[i].name === name) {
|
|
1309
|
-
// if a p5.PrintWriter w/ this name already exists...
|
|
1310
|
-
// return fn._pWriters[i]; // return it w/ contents intact.
|
|
1311
|
-
// or, could return a new, empty one with a unique name:
|
|
1312
|
-
newPW = new p5.PrintWriter(name + this.millis(), extension);
|
|
1313
|
-
fn._pWriters.push(newPW);
|
|
1314
|
-
return newPW;
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
newPW = new p5.PrintWriter(name, extension);
|
|
1318
|
-
fn._pWriters.push(newPW);
|
|
1319
|
-
return newPW;
|
|
1320
|
-
};
|
|
1321
|
-
|
|
1322
|
-
/**
|
|
1323
|
-
* A class to describe a print stream.
|
|
1324
|
-
*
|
|
1325
|
-
* Each `p5.PrintWriter` object provides a way to save a sequence of text
|
|
1326
|
-
* data, called the *print stream*, to the user's computer. It's a low-level
|
|
1327
|
-
* object that enables precise control of text output. Functions such as
|
|
1328
|
-
* <a href="#/p5/saveStrings">saveStrings()</a> and
|
|
1329
|
-
* <a href="#/p5/saveJSON">saveJSON()</a> are easier to use for simple file
|
|
1330
|
-
* saving.
|
|
1331
|
-
*
|
|
1332
|
-
* Note: <a href="#/p5/createWriter">createWriter()</a> is the recommended way
|
|
1333
|
-
* to make an instance of this class.
|
|
1334
|
-
*
|
|
1335
|
-
* @class p5.PrintWriter
|
|
1336
|
-
* @param {String} filename name of the file to create.
|
|
1337
|
-
* @param {String} [extension] format to use for the file.
|
|
1338
|
-
*
|
|
1339
|
-
* @example
|
|
1340
|
-
* <div>
|
|
1341
|
-
* <code>
|
|
1342
|
-
* function setup() {
|
|
1343
|
-
* createCanvas(100, 100);
|
|
1344
|
-
*
|
|
1345
|
-
* background(200);
|
|
1346
|
-
*
|
|
1347
|
-
* // Style the text.
|
|
1348
|
-
* textAlign(LEFT, CENTER);
|
|
1349
|
-
* textFont('Courier New');
|
|
1350
|
-
* textSize(12);
|
|
1351
|
-
*
|
|
1352
|
-
* // Display instructions.
|
|
1353
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1354
|
-
*
|
|
1355
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1356
|
-
* }
|
|
1357
|
-
*
|
|
1358
|
-
* // Save the file when the user double-clicks.
|
|
1359
|
-
* function doubleClicked() {
|
|
1360
|
-
* // Create a p5.PrintWriter object.
|
|
1361
|
-
* let myWriter = createWriter('xo.txt');
|
|
1362
|
-
*
|
|
1363
|
-
* // Add some lines to the print stream.
|
|
1364
|
-
* myWriter.print('XOO');
|
|
1365
|
-
* myWriter.print('OXO');
|
|
1366
|
-
* myWriter.print('OOX');
|
|
1367
|
-
*
|
|
1368
|
-
* // Save the file and close the print stream.
|
|
1369
|
-
* myWriter.close();
|
|
1370
|
-
* }
|
|
1371
|
-
* </code>
|
|
1372
|
-
* </div>
|
|
1373
|
-
*/
|
|
1374
|
-
p5.PrintWriter = function (filename, extension) {
|
|
1375
|
-
let self = this;
|
|
1376
|
-
this.name = filename;
|
|
1377
|
-
this.content = '';
|
|
1378
|
-
|
|
1379
|
-
/**
|
|
1380
|
-
* Writes data to the print stream without adding new lines.
|
|
1381
|
-
*
|
|
1382
|
-
* The parameter, `data`, is the data to write. `data` can be a number or
|
|
1383
|
-
* string, as in `myWriter.write('hi')`, or an array of numbers and strings,
|
|
1384
|
-
* as in `myWriter.write([1, 2, 3])`. A comma will be inserted between array
|
|
1385
|
-
* array elements when they're added to the print stream.
|
|
1386
|
-
*
|
|
1387
|
-
* @method write
|
|
1388
|
-
* @param {String|Number|Array} data data to be written as a string, number,
|
|
1389
|
-
* or array of strings and numbers.
|
|
1390
|
-
*
|
|
1391
|
-
* @example
|
|
1392
|
-
* <div>
|
|
1393
|
-
* <code>
|
|
1394
|
-
* function setup() {
|
|
1395
|
-
* createCanvas(100, 100);
|
|
1396
|
-
*
|
|
1397
|
-
* background(200);
|
|
1398
|
-
*
|
|
1399
|
-
* // Style the text.
|
|
1400
|
-
* textAlign(LEFT, CENTER);
|
|
1401
|
-
* textFont('Courier New');
|
|
1402
|
-
* textSize(12);
|
|
1403
|
-
*
|
|
1404
|
-
* // Display instructions.
|
|
1405
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1406
|
-
*
|
|
1407
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1408
|
-
* }
|
|
1409
|
-
*
|
|
1410
|
-
* // Save the file when the user double-clicks.
|
|
1411
|
-
* function doubleClicked() {
|
|
1412
|
-
* // Create a p5.PrintWriter object.
|
|
1413
|
-
* let myWriter = createWriter('numbers.txt');
|
|
1414
|
-
*
|
|
1415
|
-
* // Add some data to the print stream.
|
|
1416
|
-
* myWriter.write('1,2,3,');
|
|
1417
|
-
* myWriter.write(['4', '5', '6']);
|
|
1418
|
-
*
|
|
1419
|
-
* // Save the file and close the print stream.
|
|
1420
|
-
* myWriter.close();
|
|
1421
|
-
* }
|
|
1422
|
-
* </code>
|
|
1423
|
-
* </div>
|
|
1424
|
-
*/
|
|
1425
|
-
this.write = function (data) {
|
|
1426
|
-
this.content += data;
|
|
1427
|
-
};
|
|
1428
|
-
|
|
1429
|
-
/**
|
|
1430
|
-
* Writes data to the print stream with new lines added.
|
|
1431
|
-
*
|
|
1432
|
-
* The parameter, `data`, is the data to write. `data` can be a number or
|
|
1433
|
-
* string, as in `myWriter.print('hi')`, or an array of numbers and strings,
|
|
1434
|
-
* as in `myWriter.print([1, 2, 3])`. A comma will be inserted between array
|
|
1435
|
-
* array elements when they're added to the print stream.
|
|
1436
|
-
*
|
|
1437
|
-
* @method print
|
|
1438
|
-
* @param {String|Number|Array} data data to be written as a string, number,
|
|
1439
|
-
* or array of strings and numbers.
|
|
1440
|
-
*
|
|
1441
|
-
* @example
|
|
1442
|
-
* <div>
|
|
1443
|
-
* <code>
|
|
1444
|
-
* function setup() {
|
|
1445
|
-
* createCanvas(100, 100);
|
|
1446
|
-
*
|
|
1447
|
-
* background(200);
|
|
1448
|
-
*
|
|
1449
|
-
* // Style the text.
|
|
1450
|
-
* textAlign(LEFT, CENTER);
|
|
1451
|
-
* textFont('Courier New');
|
|
1452
|
-
* textSize(12);
|
|
1453
|
-
*
|
|
1454
|
-
* // Display instructions.
|
|
1455
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1456
|
-
*
|
|
1457
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1458
|
-
* }
|
|
1459
|
-
*
|
|
1460
|
-
* // Save the file when the user double-clicks.
|
|
1461
|
-
* function doubleClicked() {
|
|
1462
|
-
* // Create a p5.PrintWriter object.
|
|
1463
|
-
* let myWriter = createWriter('numbers.txt');
|
|
1464
|
-
*
|
|
1465
|
-
* // Add some data to the print stream.
|
|
1466
|
-
* myWriter.print('1,2,3,');
|
|
1467
|
-
* myWriter.print(['4', '5', '6']);
|
|
1468
|
-
*
|
|
1469
|
-
* // Save the file and close the print stream.
|
|
1470
|
-
* myWriter.close();
|
|
1471
|
-
* }
|
|
1472
|
-
* </code>
|
|
1473
|
-
* </div>
|
|
1474
|
-
*/
|
|
1475
|
-
this.print = function (data) {
|
|
1476
|
-
this.content += `${data}\n`;
|
|
1477
|
-
};
|
|
1478
|
-
|
|
1479
|
-
/**
|
|
1480
|
-
* Clears all data from the print stream.
|
|
1481
|
-
*
|
|
1482
|
-
* @method clear
|
|
1483
|
-
*
|
|
1484
|
-
* @example
|
|
1485
|
-
* <div>
|
|
1486
|
-
* <code>
|
|
1487
|
-
* function setup() {
|
|
1488
|
-
* createCanvas(100, 100);
|
|
1489
|
-
*
|
|
1490
|
-
* background(200);
|
|
1491
|
-
*
|
|
1492
|
-
* // Style the text.
|
|
1493
|
-
* textAlign(LEFT, CENTER);
|
|
1494
|
-
* textFont('Courier New');
|
|
1495
|
-
* textSize(12);
|
|
1496
|
-
*
|
|
1497
|
-
* // Display instructions.
|
|
1498
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1499
|
-
*
|
|
1500
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1501
|
-
* }
|
|
1502
|
-
*
|
|
1503
|
-
* // Save the file when the user double-clicks.
|
|
1504
|
-
* function doubleClicked() {
|
|
1505
|
-
* // Create a p5.PrintWriter object.
|
|
1506
|
-
* let myWriter = createWriter('numbers.txt');
|
|
1507
|
-
*
|
|
1508
|
-
* // Add some data to the print stream.
|
|
1509
|
-
* myWriter.print('Hello p5*js!');
|
|
1510
|
-
*
|
|
1511
|
-
* // Clear the print stream.
|
|
1512
|
-
* myWriter.clear();
|
|
1513
|
-
*
|
|
1514
|
-
* // Save the file and close the print stream.
|
|
1515
|
-
* myWriter.close();
|
|
1516
|
-
* }
|
|
1517
|
-
* </code>
|
|
1518
|
-
* </div>
|
|
1519
|
-
*/
|
|
1520
|
-
this.clear = function () {
|
|
1521
|
-
this.content = '';
|
|
1522
|
-
};
|
|
1523
|
-
|
|
1524
|
-
/**
|
|
1525
|
-
* Saves the file and closes the print stream.
|
|
1526
|
-
*
|
|
1527
|
-
* @method close
|
|
1528
|
-
*
|
|
1529
|
-
* @example
|
|
1530
|
-
* <div>
|
|
1531
|
-
* <code>
|
|
1532
|
-
* function setup() {
|
|
1533
|
-
* createCanvas(100, 100);
|
|
1534
|
-
*
|
|
1535
|
-
* background(200);
|
|
1536
|
-
*
|
|
1537
|
-
* // Style the text.
|
|
1538
|
-
* textAlign(LEFT, CENTER);
|
|
1539
|
-
* textFont('Courier New');
|
|
1540
|
-
* textSize(12);
|
|
1541
|
-
*
|
|
1542
|
-
* // Display instructions.
|
|
1543
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1544
|
-
*
|
|
1545
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1546
|
-
* }
|
|
1547
|
-
*
|
|
1548
|
-
* // Save the file when the user double-clicks.
|
|
1549
|
-
* function doubleClicked() {
|
|
1550
|
-
* // Create a p5.PrintWriter object.
|
|
1551
|
-
* let myWriter = createWriter('cat.txt');
|
|
1552
|
-
*
|
|
1553
|
-
* // Add some data to the print stream.
|
|
1554
|
-
* // ASCII art courtesy Wikipedia:
|
|
1555
|
-
* // https://en.wikipedia.org/wiki/ASCII_art
|
|
1556
|
-
* myWriter.print(' (\\_/) ');
|
|
1557
|
-
* myWriter.print("(='.'=)");
|
|
1558
|
-
* myWriter.print('(")_(")');
|
|
1559
|
-
*
|
|
1560
|
-
* // Save the file and close the print stream.
|
|
1561
|
-
* myWriter.close();
|
|
1562
|
-
* }
|
|
1563
|
-
* </code>
|
|
1564
|
-
* </div>
|
|
1565
|
-
*/
|
|
1566
|
-
this.close = function () {
|
|
1567
|
-
// convert String to Array for the writeFile Blob
|
|
1568
|
-
const arr = [];
|
|
1569
|
-
arr.push(this.content);
|
|
1570
|
-
fn.writeFile(arr, filename, extension);
|
|
1571
|
-
// remove from _pWriters array and delete self
|
|
1572
|
-
for (const i in fn._pWriters) {
|
|
1573
|
-
if (fn._pWriters[i].name === this.name) {
|
|
1574
|
-
// remove from _pWriters array
|
|
1575
|
-
fn._pWriters.splice(i, 1);
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
self.clear();
|
|
1579
|
-
self = {};
|
|
1580
|
-
};
|
|
1581
|
-
};
|
|
1582
|
-
|
|
1583
|
-
/**
|
|
1584
|
-
* @module IO
|
|
1585
|
-
* @submodule Output
|
|
1586
|
-
* @for p5
|
|
1587
|
-
*/
|
|
1588
|
-
|
|
1589
|
-
// object, filename, options --> saveJSON, saveStrings,
|
|
1590
|
-
// filename, [extension] [canvas] --> saveImage
|
|
1591
|
-
|
|
1592
|
-
/**
|
|
1593
|
-
* Saves a given element(image, text, json, csv, wav, or html) to the client's
|
|
1594
|
-
* computer. The first parameter can be a pointer to element we want to save.
|
|
1595
|
-
* The element can be one of <a href="#/p5.Element">p5.Element</a>,an Array of
|
|
1596
|
-
* Strings, an Array of JSON, a JSON object, a <a href="#/p5.Table">p5.Table
|
|
1597
|
-
* </a>, a <a href="#/p5.Image">p5.Image</a>, or a p5.SoundFile (requires
|
|
1598
|
-
* p5.sound). The second parameter is a filename (including extension).The
|
|
1599
|
-
* third parameter is for options specific to this type of object. This method
|
|
1600
|
-
* will save a file that fits the given parameters.
|
|
1601
|
-
* If it is called without specifying an element, by default it will save the
|
|
1602
|
-
* whole canvas as an image file. You can optionally specify a filename as
|
|
1603
|
-
* the first parameter in such a case.
|
|
1604
|
-
* **Note that it is not recommended to
|
|
1605
|
-
* call this method within draw, as it will open a new save dialog on every
|
|
1606
|
-
* render.**
|
|
1607
|
-
*
|
|
1608
|
-
* @method save
|
|
1609
|
-
* @param {Object|String} [objectOrFilename] If filename is provided, will
|
|
1610
|
-
* save canvas as an image with
|
|
1611
|
-
* either png or jpg extension
|
|
1612
|
-
* depending on the filename.
|
|
1613
|
-
* If object is provided, will
|
|
1614
|
-
* save depending on the object
|
|
1615
|
-
* and filename (see examples
|
|
1616
|
-
* above).
|
|
1617
|
-
* @param {String} [filename] If an object is provided as the first
|
|
1618
|
-
* parameter, then the second parameter
|
|
1619
|
-
* indicates the filename,
|
|
1620
|
-
* and should include an appropriate
|
|
1621
|
-
* file extension (see examples above).
|
|
1622
|
-
* @param {Boolean|String} [options] Additional options depend on
|
|
1623
|
-
* filetype. For example, when saving JSON,
|
|
1624
|
-
* <code>true</code> indicates that the
|
|
1625
|
-
* output will be optimized for filesize,
|
|
1626
|
-
* rather than readability.
|
|
1627
|
-
*
|
|
1628
|
-
* @example
|
|
1629
|
-
* <div class="norender"><code>
|
|
1630
|
-
* // Saves the canvas as an image
|
|
1631
|
-
* cnv = createCanvas(300, 300);
|
|
1632
|
-
* save(cnv, 'myCanvas.jpg');
|
|
1633
|
-
*
|
|
1634
|
-
* // Saves the canvas as an image by default
|
|
1635
|
-
* save('myCanvas.jpg');
|
|
1636
|
-
* describe('An example for saving a canvas as an image.');
|
|
1637
|
-
* </code></div>
|
|
1638
|
-
*
|
|
1639
|
-
* <div class="norender"><code>
|
|
1640
|
-
* // Saves p5.Image as an image
|
|
1641
|
-
* img = createImage(10, 10);
|
|
1642
|
-
* save(img, 'myImage.png');
|
|
1643
|
-
* describe('An example for saving a p5.Image element as an image.');
|
|
1644
|
-
* </code></div>
|
|
1645
|
-
*
|
|
1646
|
-
* <div class="norender"><code>
|
|
1647
|
-
* // Saves p5.Renderer object as an image
|
|
1648
|
-
* obj = createGraphics(100, 100);
|
|
1649
|
-
* save(obj, 'myObject.png');
|
|
1650
|
-
* describe('An example for saving a p5.Renderer element.');
|
|
1651
|
-
* </code></div>
|
|
1652
|
-
*
|
|
1653
|
-
* <div class="norender"><code>
|
|
1654
|
-
* let myTable = new p5.Table();
|
|
1655
|
-
* // Saves table as html file
|
|
1656
|
-
* save(myTable, 'myTable.html');
|
|
1657
|
-
*
|
|
1658
|
-
* // Comma Separated Values
|
|
1659
|
-
* save(myTable, 'myTable.csv');
|
|
1660
|
-
*
|
|
1661
|
-
* // Tab Separated Values
|
|
1662
|
-
* save(myTable, 'myTable.tsv');
|
|
1663
|
-
*
|
|
1664
|
-
* describe(`An example showing how to save a table in formats of
|
|
1665
|
-
* HTML, CSV and TSV.`);
|
|
1666
|
-
* </code></div>
|
|
1667
|
-
*
|
|
1668
|
-
* <div class="norender"><code>
|
|
1669
|
-
* let myJSON = { a: 1, b: true };
|
|
1670
|
-
*
|
|
1671
|
-
* // Saves pretty JSON
|
|
1672
|
-
* save(myJSON, 'my.json');
|
|
1673
|
-
*
|
|
1674
|
-
* // Optimizes JSON filesize
|
|
1675
|
-
* save(myJSON, 'my.json', true);
|
|
1676
|
-
*
|
|
1677
|
-
* describe('An example for saving JSON to a txt file with some extra arguments.');
|
|
1678
|
-
* </code></div>
|
|
1679
|
-
*
|
|
1680
|
-
* <div class="norender"><code>
|
|
1681
|
-
* // Saves array of strings to text file with line breaks after each item
|
|
1682
|
-
* let arrayOfStrings = ['a', 'b'];
|
|
1683
|
-
* save(arrayOfStrings, 'my.txt');
|
|
1684
|
-
* describe(`An example for saving an array of strings to text file
|
|
1685
|
-
* with line breaks.`);
|
|
1686
|
-
* </code></div>
|
|
1687
|
-
*/
|
|
1688
|
-
fn.save = function (object, _filename, _options) {
|
|
1689
|
-
// TODO: parameters is not used correctly
|
|
1690
|
-
// parse the arguments and figure out which things we are saving
|
|
1691
|
-
const args = arguments;
|
|
1692
|
-
// =================================================
|
|
1693
|
-
// OPTION 1: saveCanvas...
|
|
1694
|
-
|
|
1695
|
-
// if no arguments are provided, save canvas
|
|
1696
|
-
const cnv = this._curElement ? this._curElement.elt : this.elt;
|
|
1697
|
-
if (args.length === 0) {
|
|
1698
|
-
fn.saveCanvas(cnv);
|
|
1699
|
-
return;
|
|
1700
|
-
|
|
1701
|
-
} else if (args[0] instanceof Renderer || args[0] instanceof Graphics) {
|
|
1702
|
-
// otherwise, parse the arguments
|
|
1703
|
-
// if first param is a p5Graphics, then saveCanvas
|
|
1704
|
-
fn.saveCanvas(args[0].canvas, args[1], args[2]);
|
|
1705
|
-
return;
|
|
1706
|
-
|
|
1707
|
-
} else if (args.length === 1 && typeof args[0] === 'string') {
|
|
1708
|
-
// if 1st param is String and only one arg, assume it is canvas filename
|
|
1709
|
-
fn.saveCanvas(cnv, args[0]);
|
|
1710
|
-
|
|
1711
|
-
} else {
|
|
1712
|
-
// =================================================
|
|
1713
|
-
// OPTION 2: extension clarifies saveStrings vs. saveJSON
|
|
1714
|
-
const extension = _checkFileExtension(args[1], args[2])[1];
|
|
1715
|
-
switch (extension) {
|
|
1716
|
-
case 'json':
|
|
1717
|
-
fn.saveJSON(args[0], args[1], args[2]);
|
|
1718
|
-
return;
|
|
1719
|
-
case 'txt':
|
|
1720
|
-
fn.saveStrings(args[0], args[1], args[2]);
|
|
1721
|
-
return;
|
|
1722
|
-
// =================================================
|
|
1723
|
-
// OPTION 3: decide based on object...
|
|
1724
|
-
default:
|
|
1725
|
-
if (args[0] instanceof Array) {
|
|
1726
|
-
fn.saveStrings(args[0], args[1], args[2]);
|
|
1727
|
-
} else if (args[0] instanceof p5.Table) {
|
|
1728
|
-
fn.saveTable(args[0], args[1], args[2]);
|
|
1729
|
-
} else if (args[0] instanceof p5.Image) {
|
|
1730
|
-
fn.saveCanvas(args[0].canvas, args[1]);
|
|
1731
|
-
} else if (args[0] instanceof p5.SoundFile) {
|
|
1732
|
-
fn.saveSound(args[0], args[1], args[2], args[3]);
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
};
|
|
1737
|
-
|
|
1738
|
-
/**
|
|
1739
|
-
* Saves an `Object` or `Array` to a JSON file.
|
|
1740
|
-
*
|
|
1741
|
-
* JavaScript Object Notation
|
|
1742
|
-
* (<a href="https://developer.mozilla.org/en-US/docs/Glossary/JSON" target="_blank">JSON</a>)
|
|
1743
|
-
* is a standard format for sending data between applications. The format is
|
|
1744
|
-
* based on JavaScript objects which have keys and values. JSON files store
|
|
1745
|
-
* data in an object with strings as keys. Values can be strings, numbers,
|
|
1746
|
-
* Booleans, arrays, `null`, or other objects.
|
|
1747
|
-
*
|
|
1748
|
-
* The first parameter, `json`, is the data to save. The data can be an array,
|
|
1749
|
-
* as in `[1, 2, 3]`, or an object, as in
|
|
1750
|
-
* `{ x: 50, y: 50, color: 'deeppink' }`.
|
|
1751
|
-
*
|
|
1752
|
-
* The second parameter, `filename`, is a string that sets the file's name.
|
|
1753
|
-
* For example, calling `saveJSON([1, 2, 3], 'data.json')` saves the array
|
|
1754
|
-
* `[1, 2, 3]` to a file called `data.json` on the user's computer.
|
|
1755
|
-
*
|
|
1756
|
-
* The third parameter, `optimize`, is optional. If `true` is passed, as in
|
|
1757
|
-
* `saveJSON([1, 2, 3], 'data.json', true)`, then all unneeded whitespace will
|
|
1758
|
-
* be removed to reduce the file size.
|
|
1759
|
-
*
|
|
1760
|
-
* Note: The browser will either save the file immediately or prompt the user
|
|
1761
|
-
* with a dialogue window.
|
|
1762
|
-
*
|
|
1763
|
-
* @method saveJSON
|
|
1764
|
-
* @param {Array|Object} json data to save.
|
|
1765
|
-
* @param {String} filename name of the file to be saved.
|
|
1766
|
-
* @param {Boolean} [optimize] whether to trim unneeded whitespace. Defaults
|
|
1767
|
-
* to `true`.
|
|
1768
|
-
*
|
|
1769
|
-
* @example
|
|
1770
|
-
* <div>
|
|
1771
|
-
* <code>
|
|
1772
|
-
* function setup() {
|
|
1773
|
-
* createCanvas(100, 100);
|
|
1774
|
-
*
|
|
1775
|
-
* background(200);
|
|
1776
|
-
*
|
|
1777
|
-
* // Style the text.
|
|
1778
|
-
* textAlign(LEFT, CENTER);
|
|
1779
|
-
* textFont('Courier New');
|
|
1780
|
-
* textSize(12);
|
|
1781
|
-
*
|
|
1782
|
-
* // Display instructions.
|
|
1783
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1784
|
-
*
|
|
1785
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1786
|
-
* }
|
|
1787
|
-
*
|
|
1788
|
-
* // Save the file when the user double-clicks.
|
|
1789
|
-
* function doubleClicked() {
|
|
1790
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1791
|
-
* // Create an array.
|
|
1792
|
-
* let data = [1, 2, 3];
|
|
1793
|
-
*
|
|
1794
|
-
* // Save the JSON file.
|
|
1795
|
-
* saveJSON(data, 'numbers.json');
|
|
1796
|
-
* }
|
|
1797
|
-
* }
|
|
1798
|
-
* </code>
|
|
1799
|
-
* </div>
|
|
1800
|
-
*
|
|
1801
|
-
* <div>
|
|
1802
|
-
* <code>
|
|
1803
|
-
* function setup() {
|
|
1804
|
-
* createCanvas(100, 100);
|
|
1805
|
-
*
|
|
1806
|
-
* background(200);
|
|
1807
|
-
*
|
|
1808
|
-
* // Style the text.
|
|
1809
|
-
* textAlign(LEFT, CENTER);
|
|
1810
|
-
* textFont('Courier New');
|
|
1811
|
-
* textSize(12);
|
|
1812
|
-
*
|
|
1813
|
-
* // Display instructions.
|
|
1814
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1815
|
-
*
|
|
1816
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1817
|
-
* }
|
|
1818
|
-
*
|
|
1819
|
-
* // Save the file when the user double-clicks.
|
|
1820
|
-
* function doubleClicked() {
|
|
1821
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1822
|
-
* // Create an object.
|
|
1823
|
-
* let data = { x: mouseX, y: mouseY };
|
|
1824
|
-
*
|
|
1825
|
-
* // Save the JSON file.
|
|
1826
|
-
* saveJSON(data, 'state.json');
|
|
1827
|
-
* }
|
|
1828
|
-
* }
|
|
1829
|
-
* </code>
|
|
1830
|
-
* </div>
|
|
1831
|
-
*
|
|
1832
|
-
* <div>
|
|
1833
|
-
* <code>
|
|
1834
|
-
* function setup() {
|
|
1835
|
-
* createCanvas(100, 100);
|
|
1836
|
-
*
|
|
1837
|
-
* background(200);
|
|
1838
|
-
*
|
|
1839
|
-
* // Style the text.
|
|
1840
|
-
* textAlign(LEFT, CENTER);
|
|
1841
|
-
* textFont('Courier New');
|
|
1842
|
-
* textSize(12);
|
|
1843
|
-
*
|
|
1844
|
-
* // Display instructions.
|
|
1845
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1846
|
-
*
|
|
1847
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1848
|
-
* }
|
|
1849
|
-
*
|
|
1850
|
-
* // Save the file when the user double-clicks.
|
|
1851
|
-
* function doubleClicked() {
|
|
1852
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1853
|
-
* // Create an object.
|
|
1854
|
-
* let data = { x: mouseX, y: mouseY };
|
|
1855
|
-
*
|
|
1856
|
-
* // Save the JSON file and reduce its size.
|
|
1857
|
-
* saveJSON(data, 'state.json', true);
|
|
1858
|
-
* }
|
|
1859
|
-
* }
|
|
1860
|
-
* </code>
|
|
1861
|
-
* </div>
|
|
1862
|
-
*/
|
|
1863
|
-
fn.saveJSON = function (json, filename, optimize) {
|
|
1864
|
-
// p5._validateParameters('saveJSON', arguments);
|
|
1865
|
-
let stringify;
|
|
1866
|
-
if (optimize) {
|
|
1867
|
-
stringify = JSON.stringify(json);
|
|
1868
|
-
} else {
|
|
1869
|
-
stringify = JSON.stringify(json, undefined, 2);
|
|
1870
|
-
}
|
|
1871
|
-
this.saveStrings(stringify.split('\n'), filename, 'json');
|
|
1872
|
-
};
|
|
1873
|
-
|
|
1874
|
-
/**
|
|
1875
|
-
* Saves an `Array` of `String`s to a file, one per line.
|
|
1876
|
-
*
|
|
1877
|
-
* The first parameter, `list`, is an array with the strings to save.
|
|
1878
|
-
*
|
|
1879
|
-
* The second parameter, `filename`, is a string that sets the file's name.
|
|
1880
|
-
* For example, calling `saveStrings(['0', '01', '011'], 'data.txt')` saves
|
|
1881
|
-
* the array `['0', '01', '011']` to a file called `data.txt` on the user's
|
|
1882
|
-
* computer.
|
|
1883
|
-
*
|
|
1884
|
-
* The third parameter, `extension`, is optional. If a string is passed, as in
|
|
1885
|
-
* `saveStrings(['0', '01', '0`1'], 'data', 'txt')`, the second parameter will
|
|
1886
|
-
* be interpreted as the file name and the third parameter as the extension.
|
|
1887
|
-
*
|
|
1888
|
-
* The fourth parameter, `isCRLF`, is also optional, If `true` is passed, as
|
|
1889
|
-
* in `saveStrings(['0', '01', '011'], 'data', 'txt', true)`, then two
|
|
1890
|
-
* characters, `\r\n` , will be added to the end of each string to create new
|
|
1891
|
-
* lines in the saved file. `\r` is a carriage return (CR) and `\n` is a line
|
|
1892
|
-
* feed (LF). By default, only `\n` (line feed) is added to each string in
|
|
1893
|
-
* order to create new lines.
|
|
1894
|
-
*
|
|
1895
|
-
* Note: The browser will either save the file immediately or prompt the user
|
|
1896
|
-
* with a dialogue window.
|
|
1897
|
-
*
|
|
1898
|
-
* @method saveStrings
|
|
1899
|
-
* @param {String[]} list data to save.
|
|
1900
|
-
* @param {String} filename name of file to be saved.
|
|
1901
|
-
* @param {String} [extension] format to use for the file.
|
|
1902
|
-
* @param {Boolean} [isCRLF] whether to add `\r\n` to the end of each
|
|
1903
|
-
* string. Defaults to `false`.
|
|
1904
|
-
*
|
|
1905
|
-
* @example
|
|
1906
|
-
* <div>
|
|
1907
|
-
* <code>
|
|
1908
|
-
* function setup() {
|
|
1909
|
-
* createCanvas(100, 100);
|
|
1910
|
-
*
|
|
1911
|
-
* background(200);
|
|
1912
|
-
*
|
|
1913
|
-
* // Style the text.
|
|
1914
|
-
* textAlign(LEFT, CENTER);
|
|
1915
|
-
* textFont('Courier New');
|
|
1916
|
-
* textSize(12);
|
|
1917
|
-
*
|
|
1918
|
-
* // Display instructions.
|
|
1919
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1920
|
-
*
|
|
1921
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1922
|
-
* }
|
|
1923
|
-
*
|
|
1924
|
-
* // Save the file when the user double-clicks.
|
|
1925
|
-
* function doubleClicked() {
|
|
1926
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1927
|
-
* // Create an array.
|
|
1928
|
-
* let data = ['0', '01', '011'];
|
|
1929
|
-
*
|
|
1930
|
-
* // Save the text file.
|
|
1931
|
-
* saveStrings(data, 'data.txt');
|
|
1932
|
-
* }
|
|
1933
|
-
* }
|
|
1934
|
-
* </code>
|
|
1935
|
-
* </div>
|
|
1936
|
-
*
|
|
1937
|
-
* <div>
|
|
1938
|
-
* <code>
|
|
1939
|
-
* function setup() {
|
|
1940
|
-
* createCanvas(100, 100);
|
|
1941
|
-
*
|
|
1942
|
-
* background(200);
|
|
1943
|
-
*
|
|
1944
|
-
* // Style the text.
|
|
1945
|
-
* textAlign(LEFT, CENTER);
|
|
1946
|
-
* textFont('Courier New');
|
|
1947
|
-
* textSize(12);
|
|
1948
|
-
*
|
|
1949
|
-
* // Display instructions.
|
|
1950
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1951
|
-
*
|
|
1952
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1953
|
-
* }
|
|
1954
|
-
*
|
|
1955
|
-
* // Save the file when the user double-clicks.
|
|
1956
|
-
* function doubleClicked() {
|
|
1957
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1958
|
-
* // Create an array.
|
|
1959
|
-
* // ASCII art courtesy Wikipedia:
|
|
1960
|
-
* // https://en.wikipedia.org/wiki/ASCII_art
|
|
1961
|
-
* let data = [' (\\_/) ', "(='.'=)", '(")_(")'];
|
|
1962
|
-
*
|
|
1963
|
-
* // Save the text file.
|
|
1964
|
-
* saveStrings(data, 'cat', 'txt');
|
|
1965
|
-
* }
|
|
1966
|
-
* }
|
|
1967
|
-
* </code>
|
|
1968
|
-
* </div>
|
|
1969
|
-
*
|
|
1970
|
-
* <div>
|
|
1971
|
-
* <code>
|
|
1972
|
-
* function setup() {
|
|
1973
|
-
* createCanvas(100, 100);
|
|
1974
|
-
*
|
|
1975
|
-
* background(200);
|
|
1976
|
-
*
|
|
1977
|
-
* // Style the text.
|
|
1978
|
-
* textAlign(LEFT, CENTER);
|
|
1979
|
-
* textFont('Courier New');
|
|
1980
|
-
* textSize(12);
|
|
1981
|
-
*
|
|
1982
|
-
* // Display instructions.
|
|
1983
|
-
* text('Double-click to save', 5, 50, 90);
|
|
1984
|
-
*
|
|
1985
|
-
* describe('The text "Double-click to save" written in black on a gray background.');
|
|
1986
|
-
* }
|
|
1987
|
-
*
|
|
1988
|
-
* // Save the file when the user double-clicks.
|
|
1989
|
-
* function doubleClicked() {
|
|
1990
|
-
* if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
|
|
1991
|
-
* // Create an array.
|
|
1992
|
-
* // +--+
|
|
1993
|
-
* // / /|
|
|
1994
|
-
* // +--+ +
|
|
1995
|
-
* // | |/
|
|
1996
|
-
* // +--+
|
|
1997
|
-
* let data = [' +--+', ' / /|', '+--+ +', '| |/', '+--+'];
|
|
1998
|
-
*
|
|
1999
|
-
* // Save the text file.
|
|
2000
|
-
* // Use CRLF for line endings.
|
|
2001
|
-
* saveStrings(data, 'box', 'txt', true);
|
|
2002
|
-
* }
|
|
2003
|
-
* }
|
|
2004
|
-
* </code>
|
|
2005
|
-
* </div>
|
|
2006
|
-
*/
|
|
2007
|
-
fn.saveStrings = function (list, filename, extension, isCRLF) {
|
|
2008
|
-
// p5._validateParameters('saveStrings', arguments);
|
|
2009
|
-
const ext = extension || 'txt';
|
|
2010
|
-
const pWriter = new p5.PrintWriter(filename, ext);
|
|
2011
|
-
for (let item of list) {
|
|
2012
|
-
isCRLF ? pWriter.write(item + '\r\n') : pWriter.write(item + '\n');
|
|
2013
|
-
}
|
|
2014
|
-
pWriter.close();
|
|
2015
|
-
pWriter.clear();
|
|
2016
|
-
};
|
|
2017
|
-
|
|
2018
|
-
// =======
|
|
2019
|
-
// HELPERS
|
|
2020
|
-
// =======
|
|
2021
|
-
|
|
2022
|
-
function escapeHelper(content) {
|
|
2023
|
-
return content
|
|
2024
|
-
.replace(/&/g, '&')
|
|
2025
|
-
.replace(/</g, '<')
|
|
2026
|
-
.replace(/>/g, '>')
|
|
2027
|
-
.replace(/"/g, '"')
|
|
2028
|
-
.replace(/'/g, ''');
|
|
2029
|
-
}
|
|
2030
|
-
|
|
2031
|
-
/**
|
|
2032
|
-
* Writes the contents of a <a href="#/p5.Table">Table</a> object to a file. Defaults to a
|
|
2033
|
-
* text file with comma-separated-values ('csv') but can also
|
|
2034
|
-
* use tab separation ('tsv'), or generate an HTML table ('html').
|
|
2035
|
-
* The file saving process and location of the saved file will
|
|
2036
|
-
* vary between web browsers.
|
|
2037
|
-
*
|
|
2038
|
-
* @method saveTable
|
|
2039
|
-
* @deprecated p5.Table will be removed in a future version of p5.js to make way for a new, friendlier version :)
|
|
2040
|
-
* @param {p5.Table} Table the <a href="#/p5.Table">Table</a> object to save to a file
|
|
2041
|
-
* @param {String} filename the filename to which the Table should be saved
|
|
2042
|
-
* @param {String} [options] can be one of "tsv", "csv", or "html"
|
|
2043
|
-
* @example
|
|
2044
|
-
* <div><code>
|
|
2045
|
-
* let table;
|
|
2046
|
-
*
|
|
2047
|
-
* function setup() {
|
|
2048
|
-
* table = new p5.Table();
|
|
2049
|
-
*
|
|
2050
|
-
* table.addColumn('id');
|
|
2051
|
-
* table.addColumn('species');
|
|
2052
|
-
* table.addColumn('name');
|
|
2053
|
-
*
|
|
2054
|
-
* let newRow = table.addRow();
|
|
2055
|
-
* newRow.setNum('id', table.getRowCount() - 1);
|
|
2056
|
-
* newRow.setString('species', 'Panthera leo');
|
|
2057
|
-
* newRow.setString('name', 'Lion');
|
|
2058
|
-
*
|
|
2059
|
-
* // To save, un-comment next line then click 'run'
|
|
2060
|
-
* // saveTable(table, 'new.csv');
|
|
2061
|
-
*
|
|
2062
|
-
* describe('no image displayed');
|
|
2063
|
-
* }
|
|
2064
|
-
*
|
|
2065
|
-
* // Saves the following to a file called 'new.csv':
|
|
2066
|
-
* // id,species,name
|
|
2067
|
-
* // 0,Panthera leo,Lion
|
|
2068
|
-
* </code></div>
|
|
2069
|
-
*/
|
|
2070
|
-
fn.saveTable = function (table, filename, options) {
|
|
2071
|
-
// p5._validateParameters('saveTable', arguments);
|
|
2072
|
-
let ext;
|
|
2073
|
-
if (options === undefined) {
|
|
2074
|
-
ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length);
|
|
2075
|
-
if(ext === filename) ext = 'csv';
|
|
2076
|
-
} else {
|
|
2077
|
-
ext = options;
|
|
2078
|
-
}
|
|
2079
|
-
const pWriter = this.createWriter(filename, ext);
|
|
2080
|
-
|
|
2081
|
-
const header = table.columns;
|
|
2082
|
-
|
|
2083
|
-
let sep = ','; // default to CSV
|
|
2084
|
-
if (ext === 'tsv') {
|
|
2085
|
-
sep = '\t';
|
|
2086
|
-
}
|
|
2087
|
-
if (ext !== 'html') {
|
|
2088
|
-
const output = table.toString(sep);
|
|
2089
|
-
pWriter.write(output);
|
|
2090
|
-
} else {
|
|
2091
|
-
// otherwise, make HTML
|
|
2092
|
-
pWriter.print('<html>');
|
|
2093
|
-
pWriter.print('<head>');
|
|
2094
|
-
let str = ' <meta http-equiv="content-type" content';
|
|
2095
|
-
str += '="text/html;charset=utf-8" />';
|
|
2096
|
-
pWriter.print(str);
|
|
2097
|
-
pWriter.print('</head>');
|
|
2098
|
-
|
|
2099
|
-
pWriter.print('<body>');
|
|
2100
|
-
pWriter.print(' <table>');
|
|
2101
|
-
|
|
2102
|
-
// make header if it has values
|
|
2103
|
-
if (header[0] !== '0') {
|
|
2104
|
-
pWriter.print(' <tr>');
|
|
2105
|
-
for (let k = 0; k < header.length; k++) {
|
|
2106
|
-
const e = escapeHelper(header[k]);
|
|
2107
|
-
pWriter.print(` <td>${e}`);
|
|
2108
|
-
pWriter.print(' </td>');
|
|
2109
|
-
}
|
|
2110
|
-
pWriter.print(' </tr>');
|
|
2111
|
-
}
|
|
2112
|
-
|
|
2113
|
-
// make rows
|
|
2114
|
-
for (let row = 0; row < table.rows.length; row++) {
|
|
2115
|
-
pWriter.print(' <tr>');
|
|
2116
|
-
for (let col = 0; col < table.columns.length; col++) {
|
|
2117
|
-
const entry = table.rows[row].getString(col);
|
|
2118
|
-
const htmlEntry = escapeHelper(entry);
|
|
2119
|
-
pWriter.print(` <td>${htmlEntry}`);
|
|
2120
|
-
pWriter.print(' </td>');
|
|
2121
|
-
}
|
|
2122
|
-
pWriter.print(' </tr>');
|
|
2123
|
-
}
|
|
2124
|
-
pWriter.print(' </table>');
|
|
2125
|
-
pWriter.print('</body>');
|
|
2126
|
-
pWriter.print('</html>');
|
|
2127
|
-
}
|
|
2128
|
-
// close and clear the pWriter
|
|
2129
|
-
pWriter.close();
|
|
2130
|
-
pWriter.clear();
|
|
2131
|
-
}; // end saveTable()
|
|
2132
|
-
|
|
2133
|
-
/**
|
|
2134
|
-
* Generate a blob of file data as a url to prepare for download.
|
|
2135
|
-
* Accepts an array of data, a filename, and an extension (optional).
|
|
2136
|
-
* This is a private function because it does not do any formatting,
|
|
2137
|
-
* but it is used by <a href="#/p5/saveStrings">saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc.
|
|
2138
|
-
*
|
|
2139
|
-
* @param {Array} dataToDownload
|
|
2140
|
-
* @param {String} filename
|
|
2141
|
-
* @param {String} [extension]
|
|
2142
|
-
* @private
|
|
2143
|
-
*/
|
|
2144
|
-
fn.writeFile = function (dataToDownload, filename, extension) {
|
|
2145
|
-
let type = 'application/octet-stream';
|
|
2146
|
-
if (fn._isSafari()) {
|
|
2147
|
-
type = 'text/plain';
|
|
2148
|
-
}
|
|
2149
|
-
const blob = new Blob(dataToDownload, {
|
|
2150
|
-
type
|
|
2151
|
-
});
|
|
2152
|
-
fn.downloadFile(blob, filename, extension);
|
|
2153
|
-
};
|
|
2154
|
-
|
|
2155
|
-
/**
|
|
2156
|
-
* Forces download. Accepts a url to filedata/blob, a filename,
|
|
2157
|
-
* and an extension (optional).
|
|
2158
|
-
* This is a private function because it does not do any formatting,
|
|
2159
|
-
* but it is used by <a href="#/p5/saveStrings">saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc.
|
|
2160
|
-
*
|
|
2161
|
-
* @method downloadFile
|
|
2162
|
-
* @private
|
|
2163
|
-
* @param {String|Blob} data either an href generated by createObjectURL,
|
|
2164
|
-
* or a Blob object containing the data
|
|
2165
|
-
* @param {String} [filename]
|
|
2166
|
-
* @param {String} [extension]
|
|
2167
|
-
*/
|
|
2168
|
-
fn.downloadFile = downloadFile;
|
|
2169
|
-
|
|
2170
|
-
/**
|
|
2171
|
-
* Returns a file extension, or another string
|
|
2172
|
-
* if the provided parameter has no extension.
|
|
2173
|
-
*
|
|
2174
|
-
* @param {String} filename
|
|
2175
|
-
* @param {String} [extension]
|
|
2176
|
-
* @return {String[]} [fileName, fileExtension]
|
|
2177
|
-
*
|
|
2178
|
-
* @private
|
|
2179
|
-
*/
|
|
2180
|
-
fn._checkFileExtension = _checkFileExtension;
|
|
2181
|
-
|
|
2182
|
-
/**
|
|
2183
|
-
* Returns true if the browser is Safari, false if not.
|
|
2184
|
-
* Safari makes trouble for downloading files.
|
|
2185
|
-
*
|
|
2186
|
-
* @return {Boolean} [description]
|
|
2187
|
-
* @private
|
|
2188
|
-
*/
|
|
2189
|
-
fn._isSafari = function () {
|
|
2190
|
-
// The following line is CC BY SA 3 by user Fregante https://stackoverflow.com/a/23522755
|
|
2191
|
-
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
2192
|
-
};
|
|
2193
|
-
|
|
2194
|
-
/**
|
|
2195
|
-
* Helper function, a callback for download that deletes
|
|
2196
|
-
* an invisible anchor element from the DOM once the file
|
|
2197
|
-
* has been automatically downloaded.
|
|
2198
|
-
*
|
|
2199
|
-
* @private
|
|
2200
|
-
*/
|
|
2201
|
-
function destroyClickedElement(event) {
|
|
2202
|
-
document.body.removeChild(event.target);
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
|
|
2206
|
-
export default files;
|
|
2207
|
-
|
|
2208
|
-
if(typeof p5 !== 'undefined'){
|
|
2209
|
-
files(p5, p5.prototype);
|
|
2210
|
-
}
|