merge scenes updates

snap7
Michael Ball 2021-06-28 22:13:07 -07:00
commit 74659ed752
36 zmienionych plików z 4447 dodań i 454 usunięć

Wyświetl plik

@ -92,6 +92,128 @@
## in development:
* **New Features:**
* new extension primitives
* **Notable Changes:**
* libraries no longer rely on the JSF primitive, project may need to re-import their libraries to run without having to enable JS extensions
* retired Leap Motion library, took out Hummingbird library (get the current one from Birdbrain)
* **Notable Fixes:**
* fixed occasional invisible error messages
### 2021-06-24
* extensions: tweaked loading unlisted script-extensions
* byob, threads, store: removed unused code
* extensions: added documentation for adding external JS modules
* updated bignumbers library
### 2021-06-23
* updated bignums library
* pushed dev version to 6.10
* took out device libraries (Hummingbird blocks and Leap Motion)
### 2021-06-22
* extensions: added script-loading extension primitive
### 2021-06-20
* updated extensions documentation
### 2021-06-19
* extensions: added color extension primitives
* byob: fixed search for dynamic extension menus
* tweaked make-vars library to reduce internal dependencies
* updated the abominable colors library ;-)
### 2021-06-18
* extensions: added text extension primitives
* updated strings library
* extensions: tweaked variable declaration extension primitive, commented out palette refresh prim
* tweaked make-variables library
* tweaked strings library
* extensions: added color library dropdown menu
* blocks, threads, extensions: separated extension primitives from extension dropdown menus
* blocks, byob: dynamic extension dropdown menu support
* updated strings library (changed variable name to '_case independent')
### 2021-06-17
* extensions: added APL extension primitives
* updated apl library
* threads, extensions: added variable extension primitives
* updated make-variables library
### 2021-06-16
* threads: added exception handling primitives for try/catch
* extensions: added try-catch extension primitives
* updated try-catch library
* extensions: added object-naming extension primitive
* updated text-costume library
### 2021-06-15
* extensions: tweaked world-map primitives
* updated maps library
* extensions: new naming convention
* updated list-utilities library
* extensions: documented function semantics
* updated frequency-distribution-analysis library
* updated animation library
* updated words-sentences library
' extensions: added tts
* updated text-to-speech library
* updated bar-charts library
* fixed #2850 (occasional invisible error message), thanks, Ken, for the bug report!
* extensions: added long-form xhr primitive
* extensions: added geolocation extension primitive
* maps: changed default style to OpenStreetMap
* updated http-blocks library
* updated pixels library
* updated audio library
* updated localstorage library
### 2021-06-14
* new dev version
* threads, blocks, objects, extensions: new safe extensions mechanism
* objects: added new "primitive" blocks to dev palette
* updated list-utilities library
* updated animation library
* updated frequency-distribution-analysis library
* extensions: added some world-map extension primitives
* threads: associate setting with JSF-block rather than the evaluator
* extensions: added more world-map extension primitives
## 6.9.0
* **Notable Changes:**
* JS-functions are now disabled by default until switched on in the settings menu per session
* error messages in presentation mode are now shown as pop-up messages onstage
* **Notable Fixes:**
* register unsaved changes when the user edits a comment
* fixed bignums library and and made colors library faster, thanks, Brian!
* fixed setting the IDE language via a url parameter, thanks, Joan!
* **Translation Updates:**
* Polish, thanks, Witek!
* new Hindi translation, thanks, Barthdry!
* German
### 2021-06-14
* prepared release
### 2021-06-11
* byob, blocks: catch JS functions inside custom dropdown definitions
* German translation update
### 2021-06-10
* threads: error messages in presentation mode are now shown as pop-up messages onstage
* store: commented out modal prompt to enable JS when loading a project that uses it
* gui: renamed setting to "JavaScript extensions"
### 2021-06-09
* new dev version
* Polish translation update, thanks, Witek!
* blocks: register unsaved changes when the user edits a comment
* new Hindi translation, thanks, Barthdry!
* fixed bignums library and and made colors library faster, thanks, Brian!
* gui: fixed setting the IDE language via a url parameter, thanks, Joan!
* threads, gui, objects, byob, store: reinstated JS-function control, disabled JS-functions by default
* gui, store: automatically logout when the user enablesJavaScript, commented out for now
## 6.8.1
* **Notable Fixes:**
* fixed peeling off niladic custom block instances from prototype templates

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -28,9 +28,3 @@ stream-tools.xml Streams (lazy lists) A variation on the list data type in which
bar-charts.xml Bar charts Takes a table (typically from a CSV data set) as input and reports a summary of the table grouped by the field in the specified column number. The remaining three inputs are used only if the field values are numbers, in which case they can be grouped into buckets (e.g., decades, centuries, etc.). Those three inputs specify the smallest and largest values of interest and, most importantly, the width of a bucket (10 for decades, 100 for centuries). If the field isn't numeric, leave these three inputs empty or set them to zero. In that case, each string value of the field is its own bucket, and they appear sorted alphabetically. The block reports a new table with three columns. The first column contains the bucket name or smallest number. The second column contains a nonnegative integer that says how many records in the input table fall into this bucket. The third column is a subtable containing the actual records from the original table that fall into the bucket. If your buckets aren't of constant width, or you want to group by some function of more than one field, load the "Frequency Distribution Analysis" library instead.
httpBlocks.xml Web services access (https) An extended version of the URL block that allows POST, PUT, and DELETE as well as GET requests, allows using the secure HTTPS protocol, and gives control over headers, etc. Also parses JSON data.
make-variables.xml Create variables Create and manage global/sprite/script variables in a script
~ ~
~ ~
~ ~
HummingbirdBlocks.xml Hummingbird robotics Control the Hummingbird robotics kit processor
leap-library.xml LEAP Motion controller Report hand positions from LEAP Motion controller (leapmotion.com).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -0,0 +1,375 @@
makeGlobalObject();
SnapExtensions.primitives.set(
'big_switch(bool)',
loadBlocks
);
SnapExtensions.primitives.set(
'big_scheme(fn, num)',
function (which, num) {
function parseNumber (n) {
var fn = SchemeNumber.fn;
if (!fn['number?'](n)) {
n = '' + n;
try {
return parseENotation(n) || SchemeNumber(n);
} catch (err) {
return NaN;
}
}
return n;
}
function parseENotation (n) {
var fn = SchemeNumber.fn;
var numbers = n.match(/^(-?\d+\.?\d*|-?\.\d+)e(-?\d+)$/i);
if (!numbers) return null;
var coefficient = numbers[1];
var exponent = numbers[2];
return fn['*'](
coefficient,
fn.expt('10', exponent)
);
}
var fn=SchemeNumber.fn,
number=parseNumber(num);
switch (which) {
case 'number?':
case 'complex?':
return (fn['number?'](number));
case 'real?':
return (fn['real?'](number) || fn['real-valued?'](number));
case 'rational?':
return (fn['rational?'](number) || (fn['='](number, fn.rationalize(number, parseNumber('1.0e-5')))));
case 'integer?':
return (fn['integer?'](number) || fn['integer-valued?'](number));
case 'exact?':
case 'inexact?':
case 'finite?':
case 'infinite?':
case 'nan?':
case 'real-part':
case 'imag-part':
return (fn[which](number));
case 'magnitude':
return (fn.magnitude(number));
case 'angle':
return (fn.angle(number));
case 'numerator':
return (fn.numerator(number));
case 'denominator':
return (fn.denominator(number));
case 'exact':
return (fn.exact(number));
case 'inexact':
return (fn.inexact(number));
}
}
);
function makeGlobalObject () {
window.bigNumbers = {
originalEvaluate: InputSlotMorph.prototype.evaluate,
originalChangeVar: VariableFrame.prototype.changeVar,
originalPrims: {
reportBasicSum: Process.prototype.reportBasicSum,
reportBasicDifference: Process.prototype.reportBasicDifference,
reportBasicProduct: Process.prototype.reportBasicProduct,
reportBasicQuotient: Process.prototype.reportBasicQuotient,
reportBasicPower: Process.prototype.reportBasicPower,
reportBasicModulus: Process.prototype.reportBasicModulus,
reportBasicAtan2: Process.prototype.reportBasicAtan2,
reportRound: Process.prototype.reportRound,
reportBasicMin: Process.prototype.reportBasicMin,
reportBasicMax: Process.prototype.reportBasicMax,
reportBasicRandom: Process.prototype.reportBasicRandom,
reportBasicLessThan: Process.prototype.reportBasicLessThan,
reportBasicGreaterThan: Process.prototype.reportBasicGreaterThan,
reportEquals: Process.prototype.reportEquals,
reportIsIdentical: Process.prototype.reportIsIdentical,
reportMonadic: Process.prototype.reportMonadic
}
};
}
function loadBlocks (useBigNums) {
var fn = SchemeNumber.fn;
var originalPrims = window.bigNumbers.originalPrims;
if (useBigNums) {
InputSlotMorph.prototype.evaluate = function () {
var contents = this.contents();
if (this.selectedBlock) {
return this.selectedBlock;
}
if (this.constant) {
return this.constant;
}
if (this.isNumeric) {
return parseNumber(contents.text || '0');
}
return contents.text;
};
VariableFrame.prototype.changeVar = function (name, delta, sender) {
var frame = this.find(name),
value,
newValue;
if (frame) {
value = parseNumber(frame.vars[name].value);
newValue = Number.isNaN(value) ? delta : fn['+'](value, parseNumber(delta));
if (sender instanceof SpriteMorph &&
(frame.owner instanceof SpriteMorph) &&
(sender !== frame.owner)) {
sender.shadowVar(name, newValue);
} else {
frame.vars[name].value = newValue;
}
}
};
Object.assign(Process.prototype, {
reportBasicSum: function (a, b) {
a = parseNumber(a);
b = parseNumber(b);
if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
return fn['+'](a, b);
},
reportBasicDifference: function (a, b) {
a = parseNumber(a);
b = parseNumber(b);
if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
return fn['-'](a, b);
},
reportBasicProduct: function (a, b) {
a = parseNumber(a);
b = parseNumber(b);
if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
return fn['*'](a, b);
},
reportBasicQuotient: function (a, b) {
a = parseNumber(a);
b = parseNumber(b);
if (fn['='](b, '0') && !fn['='](a, '0')) {
return (fn['<'](a, '0') ? SchemeNumber('-inf.0') : SchemeNumber('+inf.0'))
};
if (Number.isNaN(a) || Number.isNaN(b) || fn['='](b, '0')) return NaN;
return fn['/'](a, b);
},
reportBasicPower: function (a, b) {
a = parseNumber(a);
b = parseNumber(b);
if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
return fn['expt'](a, b);
},
reportBasicModulus: function (a, b) {
a = parseNumber(a);
b = parseNumber(b);
if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
var result = fn.mod(a, b);
if (fn['<'](b, '0') && fn['>'](result, '0')) {
result = fn['+'](result, b);
}
return result;
},
reportBasicAtan2: function (a, b) {
a = parseNumber(a);
b = parseNumber(b);
if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
return degrees(fn.atan2(a, b));
},
reportRound: function (n) {
if (this.enableHyperOps) {
if (n instanceof List) {
return n.map(each => this.reportRound(each));
}
}
n = parseNumber(n);
if (Number.isNaN(n)) return NaN;
x = fn.round(n);
if (fn["integer?"](x)) return fn["exact"](x);
return x;
},
reportBasicMin: function (a, b) {
x = parseNumber(a);
y = parseNumber(b);
if (Number.isNaN(x) || Number.isNaN(y)) {
return a<b ? a : b;
}
return fn['<'](x, y) ? x : y;
},
reportBasicMax: function (a, b) {
x = parseNumber(a);
y = parseNumber(b);
if (Number.isNaN(x) || Number.isNaN(y)) {
return a>b ? a : b;
}
return fn['>'](x, y) ? x : y;
},
reportBasicRandom: function (min, max) {
var floor = parseNumber(min),
ceil = parseNumber(max);
if (Number.isNaN(floor) || Number.isNaN(ceil)) return NaN;
if (!fn['='](fn.mod(floor, '1'), '0') || !fn['='](fn.mod(ceil, '1'), '0')) {
// One of the numbers isn't whole. Include the decimal.
return fn['+'](
fn['*'](
Math.random(),
fn['-'](ceil, floor)
),
floor
);
}
var size = Math.ceil(max.toString(10).length/14);
const array = new Uint32Array(size);
window.crypto.getRandomValues(array);
var digits="";
for (i=0;i<size;i++) {
digits = digits + array[i].toString();
}
return fn.floor(
fn['+'](
// fn['*'](
// Math.random(),
fn.mod(parseNumber(digits),
fn['+'](
fn['-'](ceil, floor),
'1'
)
),
floor
)
);
},
reportBasicLessThan: function (a, b) {
x = parseNumber(a);
y = parseNumber(b);
if (Number.isNaN(x) || Number.isNaN(y)) return a<b;
return fn['<'](x, y);
},
reportBasicGreaterThan: function (a, b) {
x = parseNumber(a);
y = parseNumber(b);
if (Number.isNaN(x) || Number.isNaN(y)) return a>b;
return fn['>'](x, y);
},
reportEquals: function (a, b) {
x = parseNumber(a);
y = parseNumber(b);
if (Number.isNaN(x) || Number.isNaN(y)) return snapEquals(a, b);
return fn['='](x, y);
},
reportIsIdentical: function (a, b) {
x = parseNumber(a);
y = parseNumber(b);
if (Number.isNaN(x) || Number.isNaN(y)) return originalPrims.reportIsIdentical(a, b);
return fn['='](x, y);
},
reportMonadic: function (fname, n) {
if (this.enableHyperOps) {
if (n instanceof List) {
return n.map(each => this.reportMonadic(fname, each));
}
}
n = parseNumber(n);
if (Number.isNaN(n)) return NaN;
switch (Process.prototype.inputOption(fname)) {
case 'abs':
return fn.abs(n);
case 'neg':
return fn['-'](n);
case 'sign':
if (fn['='](n,SchemeNumber('0'))) return SchemeNumber('0');
return fn['/'](n, fn.abs(n));
case 'ceiling':
return fn.ceiling(n);
case 'floor':
return fn.floor(n);
case 'sqrt':
return sqrt(n);
case 'sin':
return fn.sin(radians(n));
case 'cos':
return fn.cos(radians(n));
case 'tan':
return fn.tan(radians(n));
case 'asin':
return degrees(fn.asin(n));
case 'acos':
return degrees(fn.acos(n));
case 'atan':
return degrees(fn.atan(n));
case 'ln':
return fn.log(n);
case 'log':
return fn.log(n, '10');
case 'lg':
return fn.log(n, '2');
case 'e^':
return fn.exp(n);
case '10^':
return fn.expt('10', n);
case '2^':
return fn.expt('2', n);
case 'id':
return n;
default:
return SchemeNumber('0');
}
}
});
} else {
InputSlotMorph.prototype.evaluate = window.bigNumbers.originalEvaluate;
VariableFrame.prototype.changeVar = window.bigNumbers.originalChangeVar;
Object.assign(Process.prototype, originalPrims);
}
// +++ done = true;
}
function parseNumber (n) {
var fn = SchemeNumber.fn;
if (!fn['number?'](n)) {
n = '' + n;
try {
return parseENotation(n) || SchemeNumber(n);
} catch (err) {
return NaN;
}
}
return n;
}
function parseENotation (n) {
var fn = SchemeNumber.fn;
var numbers = n.match(/^(-?\d+\.?\d*|-?\.\d+)e(-?\d+)$/i);
if (!numbers) return null;
var coefficient = numbers[1];
var exponent = numbers[2];
return fn['*'](
coefficient,
fn.expt('10', exponent)
);
}
function sqrt (n) {
var fn = SchemeNumber.fn;
if (!fn['exact?'](n) || !fn['rational?'](n) || fn['<'](n,'0')) return fn.sqrt(n);
var rootNumerator = fn['exact-integer-sqrt'](fn.numerator(n));
if (!fn['='](rootNumerator[1], '0')) return fn.sqrt(n);
var rootDenominator = fn['exact-integer-sqrt'](fn.denominator(n));
if (!fn['='](rootDenominator[1], '0')) return fn.sqrt(n);
return fn['/'](rootNumerator[0], rootDenominator[0]);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -1 +1 @@
<blocks app="Snap! 6, https://snap.berkeley.edu" version="1"><block-definition s="store key: %&apos;key&apos; value: %&apos;value&apos; in browser" type="command" category="other"><header></header><code></code><translations></translations><inputs><input type="%s"></input><input type="%s"></input></inputs><script><block s="doRun"><block s="reportJSFunction"><list><l>key</l><l>value</l><l>proc</l></list><l>proc.assertType(key, [&apos;text&apos;, &apos;number&apos;]);&#xD;proc.assertType(value, [&apos;text&apos;, &apos;number&apos;]);&#xD;window.localStorage.setItem(&apos;-snap-project-&apos; + key, &apos;&apos; + value);</l></block><list><block var="key"/><block var="value"/></list></block></script></block-definition><block-definition s="stored data in browser" type="reporter" category="other"><header></header><code></code><translations></translations><inputs></inputs><script><block s="doReport"><block s="evaluate"><block s="reportJSFunction"><list></list><l>var str = window.localStorage,&#xD; len = str.length,&#xD; result = [],&#xD; key,&#xD; i;&#xD;for (i = 0; i &lt; len; i += 1) {&#xD; key = str.key(i);&#xD; if (key.startsWith(&apos;-snap-project-&apos;)) {&#xD; result.push(new List([key.slice(14), str.getItem(key)]));&#xD; }&#xD;}&#xD;return new List(result);</l></block><list></list></block></block></script></block-definition><block-definition s="remove key: %&apos;key&apos; in browser" type="command" category="other"><header></header><code></code><translations></translations><inputs><input type="%s"></input></inputs><script><block s="doRun"><block s="reportJSFunction"><list><l>key</l><l>proc</l></list><l>proc.assertType(key, [&apos;text&apos;, &apos;number&apos;]);&#xD;window.localStorage.removeItem(&apos;-snap-project-&apos; + key);</l></block><list><block var="key"/></list></block></script></block-definition><block-definition s="clear data in browser" type="command" category="other"><header></header><code></code><translations></translations><inputs></inputs><script><block s="doWarp"><script><block s="doForEach"><l>item</l><custom-block s="stored data in browser"></custom-block><script><custom-block s="remove key: %s in browser"><block s="reportListItem"><l>1</l><block var="item"/></block></custom-block></script></block></script></block></script></block-definition><block-definition s="get value from key: %&apos;key&apos; in browser" type="reporter" category="other"><comment w="199.33333333333334" collapsed="false">Reports the value previously stored under&#xD;the input key in the browser&apos;s local storage.&#xD;Reports False if the key is not found.</comment><header></header><code></code><translations></translations><inputs><input type="%s"></input></inputs><script><block s="doReport"><block s="evaluate"><block s="reportJSFunction"><list><l>key</l></list><l>var str = window.localStorage,&#xD; result = str.getItem(&apos;-snap-project-&apos;+key);&#xD;if (!result) {&#xD; return false;&#xD;}&#xD;return result;</l></block><list><block var="key"/></list></block></block></script></block-definition></blocks>
<blocks app="Snap! 6, https://snap.berkeley.edu" version="1"><block-definition s="store key: %&apos;key&apos; value: %&apos;value&apos; in browser" type="command" category="other"><header></header><code></code><translations></translations><inputs><input type="%s"></input><input type="%s"></input></inputs><script><block s="doApplyExtension"><l>db_store(key, val)</l><list><block var="key"/><block var="value"/></list></block></script></block-definition><block-definition s="stored data in browser" type="reporter" category="other"><header></header><code></code><translations></translations><inputs></inputs><script><block s="doReport"><block s="reportApplyExtension"><l>db_getall</l><list></list></block></block></script></block-definition><block-definition s="remove key: %&apos;key&apos; in browser" type="command" category="other"><header></header><code></code><translations></translations><inputs><input type="%s"></input></inputs><script><block s="doApplyExtension"><l>db_remove(key)</l><list><block var="key"/></list></block></script></block-definition><block-definition s="clear data in browser" type="command" category="other"><header></header><code></code><translations></translations><inputs></inputs><script><block s="doWarp"><script><block s="doForEach"><l>item</l><custom-block s="stored data in browser"></custom-block><script><custom-block s="remove key: %s in browser"><block s="reportListItem"><l>1</l><block var="item"/></block></custom-block></script></block></script></block></script></block-definition><block-definition s="get value from key: %&apos;key&apos; in browser" type="reporter" category="other"><comment w="199.33333333333334" collapsed="false">Reports the value previously stored under&#xD;the input key in the browser&apos;s local storage.&#xD;Reports False if the key is not found.</comment><header></header><code></code><translations></translations><inputs><input type="%s"></input></inputs><script><block s="doReport"><block s="reportApplyExtension"><l>db_get(key)</l><list><block var="key"/></list></block></block></script></block-definition></blocks>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -1 +1 @@
<blocks app="Snap! 6.0 beta, https://snap.berkeley.edu" version="1"><block-definition s="$camera snap" type="reporter" category="sensing"><comment x="0" y="0" w="216" collapsed="false">takes a snapshot with the webcam and reports it as a new costume, or zero if the user cancels</comment><header></header><code></code><translations>pt:$camera a imagem actual do vídeo&#xD;</translations><inputs></inputs><script><block s="doDeclareVariables"><list><l>test</l><l>pic</l></list></block><block s="doSetVar"><l>test</l><block s="evaluate"><block s="reportJSFunction"><list></list><l>var camDialog,&#xD; result = false;&#xD;&#xD;camDialog = new CamSnapshotDialogMorph(&#xD; this.parentThatIsA(IDE_Morph),&#xD; this,&#xD; function () {result = null; },&#xD; function (costume) {&#xD; result = costume;&#xD; this.close();&#xD; }&#xD;);&#xD;&#xD;camDialog.key = &apos;camera&apos;;&#xD;camDialog.popUp(this.world());&#xD;return function () {return result; };</l></block><list></list></block></block><block s="doWaitUntil"><block s="evaluate"><block s="reifyScript"><script><block s="doSetVar"><l>pic</l><block s="evaluate"><block var="test"/><list></list></block></block><block s="doReport"><block s="reportNot"><block s="reportEquals"><block var="pic"/><block s="reportBoolean"><l><bool>false</bool></l></block></block></block></block></script><list></list></block><list></list></block></block><block s="doReport"><block var="pic"/></block></script></block-definition></blocks>
<blocks app="Snap! 6, https://snap.berkeley.edu" version="1"><block-definition s="$camera snap" type="reporter" category="sensing"><comment w="216" collapsed="false">takes a snapshot with the webcam and reports it as a new costume, or zero if the user cancels</comment><header></header><code></code><translations>pt:$camera a imagem actual do vídeo&#xD;</translations><inputs></inputs><script><block s="doDeclareVariables"><list><l>callback</l><l>pic</l></list></block><block s="doSetVar"><l>callback</l><block s="reportApplyExtension"><l>mda_snap</l><list></list></block></block><block s="doWaitUntil"><block s="evaluate"><block s="reifyScript"><script><block s="doSetVar"><l>pic</l><block s="evaluate"><block var="callback"/><list></list></block></block><block s="doReport"><block s="reportNot"><block s="reportEquals"><block var="pic"/><block s="reportBoolean"><l><bool>false</bool></l></block></block></block></block></script><list></list></block><list></list></block></block><block s="doReport"><block var="pic"/></block></script></block-definition></blocks>

Wyświetl plik

@ -1 +1 @@
<blocks app="Snap! 5.0, http://snap.berkeley.edu" version="1"><block-definition s="speak %&apos;text&apos; with %&apos;lang&apos; accent $nl and pitch %&apos;pitch&apos; rate %&apos;rate&apos;" type="command" category="sound"><header></header><code></code><translations>de:sprich _ mit _ Aussprache _ und Höhe _ Geschwindigkeit _&#xD;pt:fala _ na língua _ _ com tom _ e velocidade _&#xD;</translations><inputs><input type="%s">Hello, World!</input><input type="%txt">en-US<options>العربية=ar&#xD;Български=bg&#xD;বাংলা=bn&#xD;Català=ca&#xD;Català - Valencià=ca-VA&#xD;Česky=cs&#xD;Deutsch=de&#xD;Dansk=dk&#xD;Ελληνικά=el&#xD;English-American=en-US&#xD;English-British=en-GB&#xD;Esperanto=eo&#xD;Español=es&#xD;Eesti=et&#xD;Euskara=eu&#xD;suomi=fi&#xD;Français=fr&#xD;Galego=gl&#xD;Hrvatski=hr&#xD;Magyar=hu&#xD;Interlingua=ia&#xD;Bahasa Indonesia=id&#xD;Italiano=it&#xD;日本語=ja&#xD;にほんご=ja-HIRA&#xD;ಕನ್ನಡ=kn&#xD;한국어=ko&#xD;Malayalam=ml&#xD;Nederlands=nl&#xD;Norsk=no&#xD;Polski=pl&#xD;Português=pt&#xD;Português do Brasil=pt-BR&#xD;Român=ro&#xD;Русский=ru&#xD;Slovenščina=si&#xD;svenska=sv&#xD;Tamil=ta&#xD;Telagu=te&#xD;Türkçe=tr&#xD;Українська=ua&#xD;简体中文=zh-CN&#xD;繁體中文=zh-TW</options></input><input type="%n">1</input><input type="%n">1</input></inputs><script><block s="doRun"><block s="reportJSFunction"><list><l>msg</l><l>accent</l><l>pitch</l><l>rate</l></list><l>var utter = new SpeechSynthesisUtterance(msg);&#xD;utter.lang = accent;&#xD;utter.pitch = pitch;&#xD;utter.rate = rate;&#xD;window.speechSynthesis.speak(utter);</l></block><list><block var="text"/><block var="lang"/><block var="pitch"/><block var="rate"/></list></block></script></block-definition><block-definition s="speak %&apos;text&apos; with %&apos;lang&apos; accent $nl and pitch %&apos;pitch&apos; rate %&apos;rate&apos; and wait" type="command" category="sound"><header></header><code></code><translations>de:sprich _ mit _ Aussprache _ und Höhe _ Geschwindigkeit _ und warte&#xD;pt:fala _ na língua _ _ com tom _ e velocidade _ , e espera&#xD;</translations><inputs><input type="%s">Hello, World!</input><input type="%txt">en-US<options>العربية=ar&#xD;Български=bg&#xD;বাংলা=bn&#xD;Català=ca&#xD;Català - Valencià=ca-VA&#xD;Česky=cs&#xD;Deutsch=de&#xD;Dansk=dk&#xD;Ελληνικά=el&#xD;English-American=en-US&#xD;English-British=en-GB&#xD;Esperanto=eo&#xD;Español=es&#xD;Eesti=et&#xD;Euskara=eu&#xD;suomi=fi&#xD;Français=fr&#xD;Galego=gl&#xD;Hrvatski=hr&#xD;Magyar=hu&#xD;Interlingua=ia&#xD;Bahasa Indonesia=id&#xD;Italiano=it&#xD;日本語=ja&#xD;にほんご=ja-HIRA&#xD;ಕನ್ನಡ=kn&#xD;한국어=ko&#xD;Malayalam=ml&#xD;Nederlands=nl&#xD;Norsk=no&#xD;Polski=pl&#xD;Português=pt&#xD;Português do Brasil=pt-BR&#xD;Român=ro&#xD;Русский=ru&#xD;Slovenščina=si&#xD;svenska=sv&#xD;Tamil=ta&#xD;Telagu=te&#xD;Türkçe=tr&#xD;Українська=ua&#xD;简体中文=zh-CN&#xD;繁體中文=zh-TW</options></input><input type="%n">1</input><input type="%n">1</input></inputs><script><block s="doDeclareVariables"><list><l>test</l></list></block><block s="doSetVar"><l>test</l><block s="evaluate"><block s="reportJSFunction"><list><l>msg</l><l>accent</l><l>pitch</l><l>rate</l></list><l>var utter = new SpeechSynthesisUtterance(msg),&#xD; isDone = false;&#xD;utter.lang = accent;&#xD;utter.pitch = pitch;&#xD;utter.rate = rate;&#xD;utter.onend = function () {isDone = true; };&#xD;window.speechSynthesis.speak(utter);&#xD;return function () {return isDone; };</l></block><list><block var="text"/><block var="lang"/><block var="pitch"/><block var="rate"/></list></block></block><block s="doWaitUntil"><block s="evaluate"><block var="test"/><list></list></block></block></script></block-definition></blocks>
<blocks app="Snap! 6, https://snap.berkeley.edu" version="1"><block-definition s="speak %&apos;text&apos; with %&apos;lang&apos; accent $nl and pitch %&apos;pitch&apos; rate %&apos;rate&apos;" type="command" category="sound"><header></header><code></code><translations>de:sprich _ mit _ Aussprache _ und Höhe _ Geschwindigkeit _&#xD;pt:fala _ na língua _ _ com tom _ e velocidade _&#xD;</translations><inputs><input type="%s">Hello, World!</input><input type="%txt">en-US<options>العربية=ar&#xD;Български=bg&#xD;বাংলা=bn&#xD;Català=ca&#xD;Català - Valencià=ca-VA&#xD;Česky=cs&#xD;Deutsch=de&#xD;Dansk=dk&#xD;Ελληνικά=el&#xD;English-American=en-US&#xD;English-British=en-GB&#xD;Esperanto=eo&#xD;Español=es&#xD;Eesti=et&#xD;Euskara=eu&#xD;suomi=fi&#xD;Français=fr&#xD;Galego=gl&#xD;Hrvatski=hr&#xD;Magyar=hu&#xD;Interlingua=ia&#xD;Bahasa Indonesia=id&#xD;Italiano=it&#xD;日本語=ja&#xD;にほんご=ja-HIRA&#xD;ಕನ್ನಡ=kn&#xD;한국어=ko&#xD;Malayalam=ml&#xD;Nederlands=nl&#xD;Norsk=no&#xD;Polski=pl&#xD;Português=pt&#xD;Português do Brasil=pt-BR&#xD;Român=ro&#xD;Русский=ru&#xD;Slovenščina=si&#xD;svenska=sv&#xD;Tamil=ta&#xD;Telagu=te&#xD;Türkçe=tr&#xD;Українська=ua&#xD;简体中文=zh-CN&#xD;繁體中文=zh-TW</options></input><input type="%n">1</input><input type="%n">1</input></inputs><script><block s="doApplyExtension"><l>tts_speak(txt, lang, pitch, rate)</l><list><block var="text"/><block var="lang"/><block var="pitch"/><block var="rate"/></list></block></script></block-definition><block-definition s="speak %&apos;text&apos; with %&apos;lang&apos; accent $nl and pitch %&apos;pitch&apos; rate %&apos;rate&apos; and wait" type="command" category="sound"><header></header><code></code><translations>de:sprich _ mit _ Aussprache _ und Höhe _ Geschwindigkeit _ und warte&#xD;pt:fala _ na língua _ _ com tom _ e velocidade _ , e espera&#xD;</translations><inputs><input type="%s">Hello, World!</input><input type="%txt">en-US<options>العربية=ar&#xD;Български=bg&#xD;বাংলা=bn&#xD;Català=ca&#xD;Català - Valencià=ca-VA&#xD;Česky=cs&#xD;Deutsch=de&#xD;Dansk=dk&#xD;Ελληνικά=el&#xD;English-American=en-US&#xD;English-British=en-GB&#xD;Esperanto=eo&#xD;Español=es&#xD;Eesti=et&#xD;Euskara=eu&#xD;suomi=fi&#xD;Français=fr&#xD;Galego=gl&#xD;Hrvatski=hr&#xD;Magyar=hu&#xD;Interlingua=ia&#xD;Bahasa Indonesia=id&#xD;Italiano=it&#xD;日本語=ja&#xD;にほんご=ja-HIRA&#xD;ಕನ್ನಡ=kn&#xD;한국어=ko&#xD;Malayalam=ml&#xD;Nederlands=nl&#xD;Norsk=no&#xD;Polski=pl&#xD;Português=pt&#xD;Português do Brasil=pt-BR&#xD;Român=ro&#xD;Русский=ru&#xD;Slovenščina=si&#xD;svenska=sv&#xD;Tamil=ta&#xD;Telagu=te&#xD;Türkçe=tr&#xD;Українська=ua&#xD;简体中文=zh-CN&#xD;繁體中文=zh-TW</options></input><input type="%n">1</input><input type="%n">1</input></inputs><script><block s="doDeclareVariables"><list><l>callback</l></list></block><block s="doSetVar"><l>callback</l><block s="reportApplyExtension"><l>tts_speak(txt, lang, pitch, rate)</l><list><block var="text"/><block var="lang"/><block var="pitch"/><block var="rate"/></list></block></block><block s="doWaitUntil"><block s="evaluate"><block var="callback"/><list></list></block></block></script></block-definition></blocks>

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -1 +1 @@
<blocks app="Snap! 6.0 beta, https://snap.berkeley.edu" version="1"><block-definition s="costume from text %&apos;text&apos; size %&apos;size&apos;" type="reporter" category="looks"><header></header><code></code><translations>de:Kostüm aus Text _ Größe _&#xD;pt:um traje com o texto _ de tamanho _&#xD;</translations><inputs><input type="%s">A</input><input type="%n">72</input></inputs><script><block s="doDeclareVariables"><list><l>costume</l><l>x</l><l>y</l><l>dir</l><l>cst</l><l>trails</l></list></block><block s="doSetVar"><l>x</l><block s="xPosition"></block></block><block s="doSetVar"><l>y</l><block s="yPosition"></block></block><block s="doSetVar"><l>dir</l><block s="direction"></block></block><block s="doSetVar"><l>cst</l><block s="getCostumeIdx"></block></block><block s="up"></block><block s="gotoXY"><l>0</l><l>0</l></block><block s="setHeading"><l>90</l></block><block s="doSwitchToCostume"><l><option>Turtle</option></l></block><block s="doSetVar"><l>trails</l><block s="reportPenTrailsAsCostume"></block></block><block s="clear"></block><block s="gotoXY"><block s="reportAttributeOf"><l><option>left</option></l><l>Stage</l></block><l>0</l></block><block s="write"><block var="text"/><block var="size"/></block><block s="gotoXY"><block s="reportAttributeOf"><l><option>left</option></l><l>Stage</l></block><l>0</l></block><block s="doSetVar"><l>costume</l><block s="reportPenTrailsAsCostume"></block></block><block s="clear"></block><block s="doRun"><block s="reportJSFunction"><list><l>costume</l><l>name</l></list><l>costume.name = name;</l></block><list><block var="costume"/><block var="text"/></list></block><block s="gotoXY"><l>0</l><l>0</l></block><block s="doSwitchToCostume"><block var="trails"/></block><block s="doStamp"></block><block s="doSwitchToCostume"><block var="cst"/></block><block s="gotoXY"><block var="x"/><block var="y"/></block><block s="setHeading"><block var="dir"/></block><block s="doReport"><block var="costume"/></block></script></block-definition></blocks>
<blocks app="Snap! 6, https://snap.berkeley.edu" version="1"><block-definition s="costume from text %&apos;text&apos; size %&apos;size&apos;" type="reporter" category="looks"><header></header><code></code><translations>de:Kostüm aus Text _ Größe _&#xD;pt:um traje com o texto _ de tamanho _&#xD;</translations><inputs><input type="%s">A</input><input type="%n">72</input></inputs><script><block s="doDeclareVariables"><list><l>costume</l><l>x</l><l>y</l><l>dir</l><l>cst</l><l>trails</l></list></block><block s="doSetVar"><l>x</l><block s="xPosition"></block></block><block s="doSetVar"><l>y</l><block s="yPosition"></block></block><block s="doSetVar"><l>dir</l><block s="direction"></block></block><block s="doSetVar"><l>cst</l><block s="getCostumeIdx"></block></block><block s="up"></block><block s="gotoXY"><l>0</l><l>0</l></block><block s="setHeading"><l>90</l></block><block s="doSwitchToCostume"><l><option>Turtle</option></l></block><block s="doSetVar"><l>trails</l><block s="reportPenTrailsAsCostume"></block></block><block s="clear"></block><block s="gotoXY"><block s="reportAttributeOf"><l><option>left</option></l><l>Stage</l></block><l>0</l></block><block s="write"><block var="text"/><block var="size"/></block><block s="gotoXY"><block s="reportAttributeOf"><l><option>left</option></l><l>Stage</l></block><l>0</l></block><block s="doSetVar"><l>costume</l><block s="reportPenTrailsAsCostume"></block></block><block s="clear"></block><block s="doApplyExtension"><l>obj_name(obj, name)</l><list><block var="costume"/><block var="text"/></list></block><block s="gotoXY"><l>0</l><l>0</l></block><block s="doSwitchToCostume"><block var="trails"/></block><block s="doStamp"></block><block s="doSwitchToCostume"><block var="cst"/></block><block s="gotoXY"><block var="x"/><block var="y"/></block><block s="setHeading"><block var="dir"/></block><block s="doReport"><block var="costume"/></block></script></block-definition></blocks>

Wyświetl plik

@ -1 +1 @@
<blocks app="Snap! 6, https://snap.berkeley.edu" version="1"><block-definition s="safely try %&apos;action&apos; then if %&apos;error&apos; %&apos;handler&apos;" type="command" category="control"><comment w="276" collapsed="false">Catch errors.&#xD;&#xD;Runs the first script. If it succeeds, nothing else happens.&#xD;But if it has an error (something that would otherwise result&#xD;in a red halo around the block), then the second script is run,&#xD;with the text of the error message that would have been shown in the variable ERROR.</comment><header></header><code></code><translations>pt:tenta executar _ e, em caso de erro _ , executa _&#xD;</translations><inputs><input type="%cs"></input><input type="%upvar"></input><input type="%cs"></input></inputs><script><custom-block s="let %upvar be %s"><l>reset</l><block s="evaluate"><block s="reportJSFunction"><list><l>proc</l></list><l>var oldHandleError = proc.handleError,&#xD; oldCatchingErrors = proc.isCatchingErrors;&#xD;&#xD;return function(){&#xD; proc.handleError = oldHandleError;&#xD; proc.isCatchingErrors = oldCatchingErrors;&#xD;}</l></block><list></list></block></custom-block><block s="doCallCC"><block s="reifyScript"><script><block s="doRun"><block s="reportJSFunction"><list><l>reset</l><l>action</l><l>handler</l><l>proc</l></list><l>proc.isCatchingErrors = true;&#xD;proc.handleError = function(error, element){&#xD; reset();&#xD; proc.context = handler;&#xD; proc.context.variables.setVar("error", error);&#xD;}&#xD;&#xD;try{&#xD; proc.evaluate(action, new List(), true);&#xD;}&#xD;catch(e){&#xD; proc.handleError(e, null);&#xD;} </l></block><list><block var="reset"/><block var="action"/><block s="reifyScript"><script><block s="doRun"><block s="reifyScript"><script><block s="doRun"><block var="handler"/><list></list></block><block s="doRun"><block var="return"/><list></list></block></script><list></list></block><list></list></block></script><list></list></block></list></block></script><list><l>return</l></list></block></block><block s="doRun"><block var="reset"/><list></list></block></script></block-definition><block-definition s="error %&apos;msg&apos;" type="command" category="control"><comment w="268.6666666666667" collapsed="false">Throw an error.&#xD;&#xD;Makes a red halo appear around the script that runs it,&#xD;with the input text shown in a speech balloon next to&#xD;the script, just like any Snap! error.&#xD;&#xD;This is useful to put in the second script of SAFELY TRY&#xD;after some other instructions to undo the partial work of&#xD;the first script.</comment><header></header><code></code><translations>pt:lança o erro _&#xD;</translations><inputs><input type="%txt"></input></inputs><script><block s="doRun"><block s="reportJSFunction"><list><l>msg</l></list><l>throw new Error(msg);</l></block><list><block var="msg"/></list></block></script></block-definition><block-definition s="let %&apos;var&apos; be %&apos;val&apos;" type="command" category="other"><comment w="183.33333333333334" collapsed="false">LET (FOO) BE (5)&#xD;is equivalent to&#xD;SCRIPT VARIABLES (FOO)&#xD;SET (FOO) TO (5)</comment><header></header><code></code><translations>pt:cria a variável de guião _ com valor _&#xD;</translations><inputs><input type="%upvar"></input><input type="%s"></input></inputs><script><block s="doSetVar"><l>var</l><block var="val"/></block></script></block-definition><block-definition s="safely try reporting %&apos;this&apos; then if %&apos;error&apos; report %&apos;that&apos;" type="reporter" category="control"><comment w="316.6666666666667" collapsed="false">Catch errors in a reporter.&#xD;&#xD;Evaluates its first input. If that expression successfully reports a value, this block reports that value. If the expression causes a Snap! error,&#xD;then the final input slot is evaluated with the text of what would have&#xD;been the error message in variable ERROR. SAFELY TRY then reports the value of that final expression.&#xD;&#xD;Sometimes you&apos;ll want to throw an error in the final expression. You&#xD;can put an ERROR block inside a CALL block to do that.</comment><header></header><code></code><translations></translations><inputs><input type="%anyUE"></input><input type="%upvar"></input><input type="%anyUE"></input></inputs><script><block s="doDeclareVariables"><list><l>value</l></list></block><custom-block s="safely try %cs then if %upvar %cs"><script><block s="doSetVar"><l>value</l><block s="evaluate"><block var="this"/><list></list></block></block></script><l>err</l><script><block s="doSetVar"><l>error</l><block var="err"/></block><block s="doSetVar"><l>value</l><block s="evaluate"><block var="that"/><list></list></block></block></script></custom-block><block s="doReport"><block var="value"/></block></script></block-definition></blocks>
<blocks app="Snap! 6, https://snap.berkeley.edu" version="1"><block-definition s="safely try %&apos;action&apos; then if %&apos;error&apos; %&apos;handler&apos;" type="command" category="control"><comment w="276" collapsed="false">Catch errors.&#xD;&#xD;Runs the first script. If it succeeds, nothing else happens.&#xD;But if it has an error (something that would otherwise result&#xD;in a red halo around the block), then the second script is run,&#xD;with the text of the error message that would have been shown in the variable ERROR.</comment><header></header><code></code><translations>pt:tenta executar _ e, em caso de erro _ , executa _&#xD;</translations><inputs><input type="%cs"></input><input type="%upvar"></input><input type="%cs"></input></inputs><script><block s="doApplyExtension"><l>err_try(cmd, catch, err)</l><list><block var="action"/><block var="handler"/><block var="error"/></list></block><block s="doApplyExtension"><l>err_reset</l><list></list></block></script></block-definition><block-definition s="error %&apos;msg&apos;" type="command" category="control"><comment x="0" y="0" w="268.6666666666667" collapsed="false">Throw an error.&#xD;&#xD;Makes a red halo appear around the script that runs it,&#xD;with the input text shown in a speech balloon next to&#xD;the script, just like any Snap! error.&#xD;&#xD;This is useful to put in the second script of SAFELY TRY&#xD;after some other instructions to undo the partial work of&#xD;the first script.</comment><header></header><code></code><translations>pt:lança o erro _&#xD;</translations><inputs><input type="%txt"></input></inputs><script><block s="doApplyExtension"><l>err_error(msg)</l><list><block var="msg"/></list></block></script></block-definition><block-definition s="safely try reporting %&apos;this&apos; then if %&apos;error&apos; report %&apos;that&apos;" type="reporter" category="control"><comment x="0" y="0" w="316.6666666666667" collapsed="false">Catch errors in a reporter.&#xD;&#xD;Evaluates its first input. If that expression successfully reports a value, this block reports that value. If the expression causes a Snap! error,&#xD;then the final input slot is evaluated with the text of what would have&#xD;been the error message in variable ERROR. SAFELY TRY then reports the value of that final expression.&#xD;&#xD;Sometimes you&apos;ll want to throw an error in the final expression. You&#xD;can put an ERROR block inside a CALL block to do that.</comment><header></header><code></code><translations></translations><inputs><input type="%anyUE"></input><input type="%upvar"></input><input type="%anyUE"></input></inputs><script><block s="doDeclareVariables"><list><l>value</l></list></block><custom-block s="safely try %cs then if %upvar %cs"><script><block s="doSetVar"><l>value</l><block s="evaluate"><block var="this"/><list></list></block></block></script><l>err</l><script><block s="doSetVar"><l>error</l><block var="err"/></block><block s="doSetVar"><l>value</l><block s="evaluate"><block var="that"/><list></list></block></block></script></custom-block><block s="doReport"><block var="value"/></block></script></block-definition></blocks>

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -185,7 +185,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org, jadga.huegle@sap.com', // optional
'last_changed':
'2021-03-05', // this, too, will appear in the Translators tab
'2021-06-11', // this, too, will appear in the Translators tab
// GUI
// control bar:
@ -1075,6 +1075,14 @@ SnapTranslator.dict.de = {
'check to enable\nvirtual keyboard support\nfor mobile devices':
'einschalten um die virtuelle\nTastatur auf mobilen Ger\u00e4ten\n'
+ 'zu erm\u00f6glichen',
'JavaScript extensions':
'JavaScript Erweiterungen',
'check to support\nnative JavaScript functions':
'einschalten um JavaScript-Funktionen\ndirekt in Snap! zu ermöglichen',
'uncheck to disable support for\nnative JavaScript functions':
'ausschalten, um potentiell gefährliche\nJavaScript-Funktionen zu verhindern',
'JavaScript extensions for Snap!\nare turned off':
'JavaScript Erweiterungen für Snap!\nsind ausgeschaltet',
'Input sliders':
'Eingabeschieber',
'uncheck to disable\ninput sliders for\nentry fields':

2007
locale/lang-hi.js 100644

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -8,21 +8,22 @@
<script src="src/morphic.js?version=2021-04-12"></script>
<script src="src/symbols.js?version=2021-03-03"></script>
<script src="src/widgets.js?version=2021-01-05"></script>
<script src="src/blocks.js?version=2021-04-12"></script>
<script src="src/threads.js?version=2021-04-17"></script>
<script src="src/objects.js?version=2021-04-23"></script>
<script src="src/scenes.js?version=2021-04-23"></script>
<script src="src/gui.js?version=2021-05-11"></script>
<script src="src/paint.js?version=2021-03-17"></script>
<script src="src/blocks.js?version=2021-06-18"></script>
<script src="src/threads.js?version=2021-06-24"></script>
<script src="src/objects.js?version=2021-06-14"></script>
<script src="src/scenes.js?version=2021-05-21"></script>
<script src="src/gui.js?version=2021-06-23"></script>
<script src="src/paint.js?version=2020-05-17"></script>
<script src="src/lists.js?version=2021-03-15"></script>
<script src="src/byob.js?version=2021-05-04"></script>
<script src="src/byob.js?version=2021-06-24"></script>
<script src="src/tables.js?version=2021-03-05"></script>
<script src="src/sketch.js?version=2021-03-17"></script>
<script src="src/video.js?version=2019-06-27"></script>
<script src="src/maps.js?version=2020-03-25"></script>
<script src="src/maps.js?version=2021-06-15"></script>
<script src="src/extensions.js?version=2021-06-24"></script>
<script src="src/xml.js?version=2020-04-27"></script>
<script src="src/store.js?version=2021-04-23"></script>
<script src="src/locale.js?version=2021-03-15"></script>
<script src="src/store.js?version=2021-06-24"></script>
<script src="src/locale.js?version=2021-06-11"></script>
<script src="src/cloud.js?version=2021-02-04"></script>
<script src="src/api.js?version=2021-01-25"></script>
<script src="src/sha512.js?version=2019-06-27"></script>

Wyświetl plik

@ -146,19 +146,19 @@
/*global Array, BoxMorph,
Color, ColorPaletteMorph, FrameMorph, Function, HandleMorph, Math, MenuMorph,
Morph, MorphicPreferences, Object, Point, ScrollFrameMorph, ShadowMorph, ZERO,
String, StringMorph, TextMorph, contains, degrees, detect, PianoMenuMorph,
document, getDocumentPositionOf, isNaN, isString, newCanvas, nop, parseFloat,
radians, useBlurredShadows, SpeechBubbleMorph, modules, StageMorph, Sound,
Morph, MorphicPreferences, Object, ScrollFrameMorph, ShadowMorph, ZERO, Sound,
String, StringMorph, TextMorph, contains, degrees, detect, PianoMenuMorph, nop,
document, getDocumentPositionOf, isNaN, isString, newCanvas, parseFloat, isNil,
radians, useBlurredShadows, SpeechBubbleMorph, modules, StageMorph, SymbolMorph,
fontHeight, TableFrameMorph, SpriteMorph, Context, ListWatcherMorph, Rectangle,
DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, WHITE, BLACK,
Costume, IDE_Morph, BlockDialogMorph, BlockEditorMorph, localize, isNil, CLEAR,
Costume, IDE_Morph, BlockDialogMorph, BlockEditorMorph, localize, CLEAR, Point,
isSnapObject, PushButtonMorph, SpriteIconMorph, Process, AlignmentMorph,
CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/
CustomCommandBlockMorph, ToggleButtonMorph, DialMorph, SnapExtensions*/
// Global stuff ////////////////////////////////////////////////////////
modules.blocks = '2021-April-12';
modules.blocks = '2021-June-18';
var SyntaxElementMorph;
var BlockMorph;
@ -352,6 +352,11 @@ SyntaxElementMorph.prototype.labelParts = {
'(4) triangle' : 4
}
},
'%prim': {
type: 'input',
tags: 'read-only static',
menu: 'primitivesMenu'
},
'%audio': {
type: 'input',
tags: 'read-only static',
@ -2095,11 +2100,11 @@ SyntaxElementMorph.prototype.showBubble = function (value, exportPic, target) {
img,
morphToShow,
isClickable = false,
ide = this.parentThatIsA(IDE_Morph),
ide = this.parentThatIsA(IDE_Morph) || target.parentThatIsA(IDE_Morph),
anchor = this,
pos = this.rightCenter().add(new Point(2, 0)),
sf = this.parentThatIsA(ScrollFrameMorph),
wrrld = this.world();
wrrld = this.world() || target.world();
if ((value === undefined) || !wrrld) {
return null;
@ -9072,6 +9077,7 @@ InputSlotMorph.prototype.menuFromDict = function (
{
var key, dial, flag,
myself = this,
selector,
block = this.parentThatIsA(BlockMorph),
ide = this.parentThatIsA(IDE_Morph),
menu = new MenuMorph(
@ -9094,9 +9100,24 @@ InputSlotMorph.prototype.menuFromDict = function (
}
if (choices instanceof Function) {
if (!Process.prototype.enableJS) {
menu.addItem('JavaScript extensions for Snap!\nare turned off');
return menu;
}
choices = choices.call(this);
} else if (isString(choices)) {
choices = this[choices]();
if (choices.indexOf('ext_') === 0) {
selector = choices.slice(4);
choices = SnapExtensions.menus.get(selector);
if (choices) {
choices = choices.call(this);
} else {
menu.addItem('cannot find extension menu "' + selector + '"');
return menu;
}
} else {
choices = this[choices]();
}
if (!choices) { // menu has already happened
return;
}
@ -9313,6 +9334,16 @@ InputSlotMorph.prototype.messagesReceivedMenu = function (searching) {
return dict;
};
InputSlotMorph.prototype.primitivesMenu = function () {
var dict = {},
allNames = Array.from(SnapExtensions.primitives.keys());
allNames.sort().forEach(name =>
dict[name] = name
);
return dict;
};
InputSlotMorph.prototype.collidablesMenu = function (searching) {
var dict = {
'mouse-pointer' : ['mouse-pointer'],
@ -13167,9 +13198,13 @@ CommentMorph.prototype.mouseClickLeft = function () {
CommentMorph.prototype.layoutChanged = function () {
// react to a change of the contents area
var ide = this.parentThatIsA(IDE_Morph);
this.fixLayout();
this.align();
this.comeToFront();
if (ide) {
ide.recordUnsavedChanges();
}
};
CommentMorph.prototype.fixLayout = function () {

Wyświetl plik

@ -102,11 +102,11 @@ nop, radians, BoxMorph, ArrowMorph, PushButtonMorph, contains, InputSlotMorph,
ToggleButtonMorph, IDE_Morph, MenuMorph, ToggleElementMorph, fontHeight, isNil,
StageMorph, SyntaxElementMorph, CommentMorph, localize, CSlotMorph, Variable,
MorphicPreferences, SymbolMorph, CursorMorph, VariableFrame, BooleanSlotMorph,
WatcherMorph, XML_Serializer, SnapTranslator*/
WatcherMorph, XML_Serializer, SnapTranslator, SnapExtensions*/
// Global stuff ////////////////////////////////////////////////////////
modules.byob = '2021-May-04';
modules.byob = '2021-June-24';
// Declarations
@ -331,7 +331,7 @@ CustomBlockDefinition.prototype.dropDownMenuOf = function (inputName) {
'directionDialMenu'
],
fname
)) {
) || fname.indexOf('ext_') === 0) {
return fname;
}
}
@ -347,9 +347,6 @@ CustomBlockDefinition.prototype.parseChoices = function (string) {
if (string.match(/^function\s*\(.*\)\s*{.*\n/)) {
// It's a JS function definition.
// Let's extract its params and body, and return a Function out of them.
// if (!this.enableJS) {
// throw new Error('JavaScript is not enabled');
// }
params = string.match(/^function\s*\((.*)\)/)[1].split(',');
body = string.split('\n').slice(1,-1).join('\n');
return Function.apply(null, params.concat([body]));
@ -378,16 +375,19 @@ CustomBlockDefinition.prototype.menuSearchWords = function () {
var menu = this.dropDownMenuOf(slot);
if (menu) {
if (isString(menu)) { // special menu, translates its values
menu = InputSlotMorph.prototype[menu](true);
terms.push(
Object.values(menu).map(entry => {
if (isNil(entry)) {return ''; }
if (entry instanceof Array) {
return localize(entry[0]);
}
return entry.toString();
}).join(' ')
);
if (typeof InputSlotMorph.prototype[menu] === 'function') {
// catch typos in extension menus
menu = InputSlotMorph.prototype[menu](true);
terms.push(
Object.values(menu).map(entry => {
if (isNil(entry)) {return ''; }
if (entry instanceof Array) {
return localize(entry[0]);
}
return entry.toString();
}).join(' ')
);
}
} else { // assume a dictionary, take its keys
terms.push(Object.keys(menu).join(' '));
}
@ -2747,6 +2747,13 @@ BlockLabelFragment.prototype.hasSpecialMenu = function () {
);
};
BlockLabelFragment.prototype.hasExtensionMenu = function () {
return contains(
Array.from(SnapExtensions.menus.keys()).map(str => '§_ext_' + str),
this.options
);
};
// arity
BlockLabelFragment.prototype.isSingleInput = function () {
@ -3739,6 +3746,13 @@ InputSlotDialogMorph.prototype.addSlotsMenu = function () {
localize('special'),
this.specialSlotsMenu()
);
if (this.world().currentKey === 16) { // shift-key down
menu.addMenu(
(this.fragment.hasExtensionMenu() ? on : off) +
localize('extension'),
this.extensionOptionsMenu()
);
}
return menu;
}
return this.specialSlotsMenu();
@ -3806,6 +3820,27 @@ InputSlotDialogMorph.prototype.specialOptionsMenu = function () {
return menu;
};
InputSlotDialogMorph.prototype.extensionOptionsMenu = function () {
var menu = new MenuMorph(this.setSlotOptions, null, this),
myself = this,
selectors = Array.from(SnapExtensions.menus.keys()),
on = '\u26AB ',
off = '\u26AA ';
function addSpecialOptions(label, selector) {
menu.addItem(
(myself.fragment.options === selector ?
on : off) + localize(label),
selector
);
}
selectors.forEach(sel => {
addSpecialOptions(sel.slice(4), '§_ext_' + sel);
});
return menu;
};
// InputSlotDialogMorph hiding and showing:
/*

981
src/extensions.js 100644
Wyświetl plik

@ -0,0 +1,981 @@
/*
extensions.js
additional primitives for SNAP!
written by Jens Mönig
Copyright (C) 2021 by Jens Mönig
This file is part of Snap!.
Snap! is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Global settings /////////////////////////////////////////////////////
/*global modules, List, StageMorph, Costume, SpeechSynthesisUtterance, Sound,
IDE_Morph, CamSnapshotDialogMorph, SoundRecorderDialogMorph, isSnapObject, nop,
Color, Process, contains*/
modules.extensions = '2021-June-24';
// Global stuff
var SnapExtensions = {
primitives: new Map(),
menus: new Map(),
scripts: [],
urls: [
'libraries/'
]
};
/*
SnapExtensions is a set of two global dictionaries of named functions to be
used as extension primitives for blocks or dynamic dropdown menus. Block
extensions are stored in the "primitives" dictionary of SnapExtensions,
dynamic dropdown menus in the "menus" section.
You can also extend Snap! with your own externally hosted JavaScript file(s)
and have them add your own extension primitives and menus to the global
SnapExtensions dictionaries. This lets you provide libraries to support
special APIs and custom hardware.
1. Primitives (additional blocks)
=================================
The names under which primitives are stored will apear in the dropdown
menus of the hidden extension "primitive" blocks sorted alphabetically.
(You can find those extension primitives in Snap's search bar or in dev
mode. There are two version of the primitive block, a command version and
a reporter one, both show the same list of available extensions.
naming conventions
------------------
domain-prefix_function-name(parameter-list)
example: 'lst_sort(list, fn)'
- domain-prefix: max 3-letter lowercase identifier
followed by an underscore
e.g.: err_, lst_, txt_, dta_, map_, tts_, xhr_, geo_, mda_
- function-name: short, single word if possible, lowercase
- parameter-list: comma separated names or type indicators
function semantics
------------------
- functions are called by the "primitive" blocks with any arguments provided
- "this" refers to the current snap object (sprite or stage) at call-time
- a reference to the current process is always passed as last argument
2. Menus (for input slots)
==========================
The names of the available dynamic drowdown menus can be written into the
"options" dialog when defining an input slot. Additionally you can choose
from a list of available menus when holding down the shift-key while
clicking on the partial-gear button in Snap's input-slot dialog.
naming conventions
------------------
domain-prefix_function-name
example: 'clr_number'
- domain-prefix: max 3-letter lowercase identifier
followed by an underscore
e.g.: clr_, txt_, lst_
- function-name: short, single word if possible, lowercase
- NOTE: dynamic menu functions cannot have any inputs
function semantics
------------------
- "this" refers to the current input-slot at call-time
- to get a handle on the current block use "this.parentThatIsA(BlockMorph")
- likewise to get a handle on the current sprite use
"this.parentThatIsA(IDE_Morph).currentSprite"
- if you want the menu of one input slot to depend on the contents of
another input slot of the same block, you can get a handle to the block
using the above method, and then access all inputs by calling
"block.inputs()". This will give you an array of all input slots.
You can access the contents of an input slot by calling "slot.evaluate()"
3. External JavaScript files
============================
You can provide extensions for your custom hardware or for arbitrary APIs
or extend Snap! with JavaScript libraries from other parties. You can
load additional JavaScript files using the "src_load(url)" extension
primitive inside Snap, which you can find using Snap's search bar in the
IDE. The loading primitive will wait until the source file has fully loaded
and its defined functions are ready to be called.
adding primitives to SnapExtensions
-----------------------------------
It is the suggested best practice to expose your own extension primitives
by adding them to the global SnapExtensions libraries (for primitives and
menus) using the very same conventions described herein, and then to offer
a library of custom blocks that make calls to your additional operations.
publishing an extension
-----------------------
Running the "src_load(url)" primitive will throw an error unless you first
check the "Enable JavaScript extensions" setting in Snap's preferences menu,
or if your JavaScript extension comes from a list of trusted hosts.
While you develop your JavaScript extension it's recommended to turn the
"Enable JavaScript extensions" setting on to load the extension once, and
then to turn it off again, so you can make sure your custom blocks are not
using any "JS Function" blocks (because those will be caught if the
preference is turned off).
When you're ready to publish your extension you can contact us to allow-list
the url hosting your JS file, or you can send me a Github pull-request to
include it in the main Snap branch.
Whatever you do, please use these extension capabilities sensibly.
*/
// Primitives
// errors & exceptions (err_):
SnapExtensions.primitives.set(
'err_error(msg)',
function (msg) {
throw new Error(msg);
}
);
SnapExtensions.primitives.set(
'err_try(cmd, catch, err)',
function (action, exception, errVarName, proc) {
proc.tryCatch(action, exception, errVarName);
}
);
SnapExtensions.primitives.set(
'err_reset',
function (proc) {
proc.resetErrorHandling();
}
);
SnapExtensions.primitives.set(
'err_ignore',
nop
);
// list utils (lst_):
SnapExtensions.primitives.set(
'lst_sort(list, fn)',
function (data, fn, proc) {
return proc.reportAtomicSort(data, fn);
}
);
SnapExtensions.primitives.set(
'lst_linked(list)',
function (data) {
return data.isLinked;
}
);
// text utils (txt_):
SnapExtensions.primitives.set(
'txt_lowercase(txt)',
function (txt) {
return txt.toLowerCase();
}
);
SnapExtensions.primitives.set(
'txt_indexof(sub, txt)',
function (sub, txt) {
return txt.indexOf(sub) + 1;
}
);
// data sciene & frequency distribution analysis (dta_):
SnapExtensions.primitives.set(
'dta_analyze(list)',
function (list) {
var dict = new Map(),
result = [],
data = list.itemsArray(),
len = data.length,
i;
for (i = 0; i < len; i += 1) {
if (dict.has(data[i])) {
dict.set(data[i], dict.get(data[i]) + 1);
} else {
dict.set(data[i], 1);
}
}
dict.forEach(function (value, key) {
result.push(new List([key, value]));
});
return new List(result);
}
);
SnapExtensions.primitives.set(
'dta_group(list, fn)',
function (data, fn, proc) {
return proc.reportAtomicGroup(data, fn);
}
);
SnapExtensions.primitives.set(
'dta_transpose(list)',
function (data, proc) {
proc.assertType(data, 'list');
return data.transpose();
}
);
SnapExtensions.primitives.set(
'dta_crossproduct(list)',
function (data, proc) {
proc.assertType(data, 'list');
return data.crossproduct();
}
);
// World map (map_):
SnapExtensions.primitives.set(
'map_zoom',
function () {
return this.parentThatIsA(StageMorph).worldMap.zoom;
}
);
SnapExtensions.primitives.set(
'map_zoom(n)',
function (num) {
this.parentThatIsA(StageMorph).worldMap.setZoom(num);
}
);
SnapExtensions.primitives.set(
'map_lon(x)',
function (x) {
return this.parentThatIsA(StageMorph).worldMap.lonFromSnapX(x);
}
);
SnapExtensions.primitives.set(
'map_lat(y)',
function (y) {
return this.parentThatIsA(StageMorph).worldMap.latFromSnapY(y);
}
);
SnapExtensions.primitives.set(
'map_view(lon, lat)',
function (lon, lat) {
this.parentThatIsA(StageMorph).worldMap.setView(lon, lat);
}
);
SnapExtensions.primitives.set(
'map_y(lat)',
function (lat) {
return this.parentThatIsA(StageMorph).worldMap.snapYfromLat(lat);
}
);
SnapExtensions.primitives.set(
'map_x(lon)',
function (lon) {
return this.parentThatIsA(StageMorph).worldMap.snapXfromLon(lon);
}
);
SnapExtensions.primitives.set(
'map_pan(x, y)',
function (x, y) {
this.parentThatIsA(StageMorph).worldMap.panBy(x, y);
}
);
SnapExtensions.primitives.set(
'map_dist(lat1, lon1, lat2, lon2)',
function (lat1, lon1, lat2, lon2) {
return this.parentThatIsA(StageMorph).worldMap.distanceInKm(
lat1,
lon1,
lat2,
lon2
);
}
);
SnapExtensions.primitives.set(
'map_update',
function () {
var stage = this.parentThatIsA(StageMorph);
stage.worldMap.extent = stage.dimensions;
stage.worldMap.render();
}
);
SnapExtensions.primitives.set(
'map_loaded',
function () {
return !this.parentThatIsA(StageMorph).worldMap.loading;
}
);
SnapExtensions.primitives.set(
'map_costume',
function () {
return new Costume(
this.parentThatIsA(StageMorph).worldMap.canvas,
'map'
);
}
);
SnapExtensions.primitives.set(
'map_style(name)',
function (name) {
this.parentThatIsA(StageMorph).worldMap.setHost(name);
}
);
// text-to-speech (tts_):
SnapExtensions.primitives.set(
'tts_speak(txt, lang, pitch, rate)',
function (msg, accent, pitch, rate) {
var utter = new SpeechSynthesisUtterance(msg),
isDone = false;
utter.lang = accent;
utter.pitch = pitch;
utter.rate = rate;
utter.onend = () => isDone = true;
window.speechSynthesis.speak(utter);
return () => isDone;
}
);
// XHR:
SnapExtensions.primitives.set(
'xhr_request(mth, url, dta, hdrs)',
function (method, url, data, headers, proc) {
var response, i, header;
if (!proc.httpRequest) {
proc.httpRequest = new XMLHttpRequest();
proc.httpRequest.open(method, url, true);
proc.assertType(headers, 'list');
for (i = 1; i <= headers.length(); i += 1) {
header = headers.at(i);
proc.assertType(header, 'list');
proc.httpRequest.setRequestHeader(
header.at(1),
header.at(2)
);
}
proc.httpRequest.send(data || null);
} else if (proc.httpRequest.readyState === 4) {
response = proc.httpRequest.responseText;
proc.httpRequest = null;
return response;
}
proc.pushContext('doYield');
proc.pushContext();
}
);
// Geo-location (geo_):
SnapExtensions.primitives.set(
'geo_location(acc?)',
function (includeAccuracy) {
var crd = new List(),
myself = this,
options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
function success(pos) {
crd = new List([
pos.coords.latitude,
pos.coords.longitude
]);
if (includeAccuracy) {
crd.add(pos.coords.accuracy);
}
}
function error(err) {
crd = new List([37.872099, -122.257852]);
myself.inform('Warning:\nGeolocation failed.');
}
navigator.geolocation.getCurrentPosition(
success,
error,
options
);
return () => crd;
}
);
// MediaComp (mda_)
SnapExtensions.primitives.set(
'mda_snap',
function () {
var camDialog,
result = false;
camDialog = new CamSnapshotDialogMorph(
this.parentThatIsA(IDE_Morph),
this,
() => result = null,
function (costume) {
result = costume;
this.close();
}
);
camDialog.key = 'camera';
camDialog.popUp(this.world());
return () => result;
}
);
SnapExtensions.primitives.set(
'mda_record',
function () {
var soundRecorder,
result = false;
soundRecorder = new SoundRecorderDialogMorph(
function (audio) {
if (audio) {
result = new Sound(audio, 'recording');
} else {
result = null;
this.destroy();
}
}
);
soundRecorder.cancel = function () {
result = null;
this.destroy();
};
soundRecorder.key = 'microphone';
soundRecorder.popUp(this.world());
return () => result;
}
);
// Database (db_):
SnapExtensions.primitives.set(
'db_store(key, val)',
function (key, value, proc) {
proc.assertType(key, ['text', 'number']);
proc.assertType(value, ['text', 'number']);
window.localStorage.setItem('-snap-project-' + key, '' + value);
}
);
SnapExtensions.primitives.set(
'db_getall',
function () {
var str = window.localStorage,
len = str.length,
result = [],
key,
i;
for (i = 0; i < len; i += 1) {
key = str.key(i);
if (key.startsWith('-snap-project-')) {
result.push(new List([key.slice(14), str.getItem(key)]));
}
}
return new List(result);
}
);
SnapExtensions.primitives.set(
'db_remove(key)',
function (key, proc) {
proc.assertType(key, ['text', 'number']);
window.localStorage.removeItem('-snap-project-' + key);
}
);
SnapExtensions.primitives.set(
'db_get(key)',
function (key) {
var str = window.localStorage,
result = str.getItem('-snap-project-'+key);
if (!result) {
return false;
}
return result;
}
);
// Object properties (obj_):
SnapExtensions.primitives.set(
'obj_name(obj, name)',
function (obj, name, proc) {
var ide = this.parentThatIsA(IDE_Morph);
proc.assertType(obj, ['sprite', 'stage', 'costume', 'sound']);
if (isSnapObject(obj)) {
obj.setName(ide.newSpriteName(name, obj));
ide.recordUnsavedChanges();
} else if (obj instanceof Costume) {
obj.name = this.newCostumeName(name, obj);
obj.version = Date.now();
ide.hasChangedMedia = true;
ide.recordUnsavedChanges();
} else if (obj instanceof Sound) {
obj.name = ide.newSoundName(name);
ide.hasChangedMedia = true;
ide.recordUnsavedChanges();
}
}
);
// Variables (var_):
SnapExtensions.primitives.set(
'var_declare(scope, name)',
function (scope, name, proc) {
var ide, frame;
proc.assertType(name, 'text');
if (name === '') {return; }
if (scope === 'script') {
frame = proc.context.isInCustomBlock() ?
proc.homeContext.variables
: proc.context.outerContext.variables;
} else if (scope === 'sprite') {
frame = this.variables;
} else {
frame = this.globalVariables();
}
if (frame.vars[name] === undefined) {
frame.addVar(name);
ide = this.parentThatIsA(IDE_Morph);
ide.flushBlocksCache('variables'); // b/c of inheritance
ide.refreshPalette();
}
}
);
SnapExtensions.primitives.set(
'var_delete(name)',
function (name, proc) {
var local;
proc.assertType(name, 'text');
if (name === '') {return; }
local = proc.context.isInCustomBlock() ?
proc.homeContext.variables
: proc.context.outerContext.variables;
if (local.vars[name] !== undefined) {
delete local.vars[name];
} else if (this.deletableVariableNames().indexOf(name) > -1) {
this.deleteVariable(name);
}
}
);
SnapExtensions.primitives.set(
'var_get(name)',
function (name, proc) {
proc.assertType(name, 'text');
return proc.homeContext.variables.getVar(name);
}
);
SnapExtensions.primitives.set(
'var_set(name, val)',
function (name, val, proc) {
var local;
proc.assertType(name, 'text');
if (name === '') {return; }
local = proc.context.isInCustomBlock() ?
proc.homeContext.variables
: proc.context.outerContext.variables;
local.setVar(name, val);
}
);
SnapExtensions.primitives.set(
'var_show(name)',
function (name, proc) {
proc.doShowVar(
name,
proc.context.isInCustomBlock() ?
proc.homeContext
: proc.context.outerContext
);
}
);
SnapExtensions.primitives.set(
'var_hide(name)',
function (name, proc) {
proc.doHideVar(
name,
proc.context.isInCustomBlock() ?
proc.homeContext
: proc.context.outerContext
);
}
);
// IDE (ide_):
// not needed right now, commented out for possibly later
/*
SnapExtensions.primitives.set(
'ide_refreshpalette(name)',
function (name) {
var ide = this.parentThatIsA(IDE_Morph);
if (name !== 'variables') {
ide.flushBlocksCache(name);
}
ide.flushBlocksCache('variables'); // b/c of inheritance
ide.refreshPalette();
}
);
*/
// Colors (clr_):
SnapExtensions.primitives.set(
'clr_rgba(r, g, b, a)',
function (r, g, b, a) {
return new Color(r, g, b, a);
}
);
SnapExtensions.primitives.set(
'clr_channel(clr, rgba)',
function (clr, rgba) {
if (contains(['r', 'g', 'b', 'a'], rgba)) {
return clr[rgba];
}
throw new Error('unknown rgba color channel "' + rgba + '"');
}
);
SnapExtensions.primitives.set(
'clr_hsv(clr)',
function (clr) {
return new List(clr.hsv());
}
);
SnapExtensions.primitives.set(
'clr_hsv(h, s, v)',
function (h, s, v) {
var c = new Color();
c.set_hsv(h, s, v);
return c;
}
);
SnapExtensions.primitives.set(
'clr_setpen(clr)',
function (clr) {
this.setColor(clr);
}
);
SnapExtensions.primitives.set(
'clr_pen',
function () {
return this.color;
}
);
// loading external scripts (src_)
SnapExtensions.primitives.set(
'src_load(url)',
function (url, proc) {
var scriptElement;
if (!proc.context.accumulator) {
proc.context.accumulator = {done: false};
if (contains(SnapExtensions.scripts, url)) {
return;
}
if (Process.prototype.enableJS || SnapExtensions.urls.some(
any => url.indexOf(any) === 0)
) {
scriptElement = document.createElement('script');
scriptElement.onload = () => {
SnapExtensions.scripts.push(url);
proc.context.accumulator.done = true;
};
document.head.appendChild(scriptElement);
scriptElement.src = url;
} else {
throw new Error(
'unlisted extension url:\n"' + url + '"\n' +
'JavaScript extensions for Snap!\nare turned off'
);
}
} else if (proc.context.accumulator.done) {
return;
}
proc.pushContext('doYield');
proc.pushContext();
}
);
// Menus
SnapExtensions.menus.set(
'clr_numbers', // Brian's browns and oranges, sigh...
function () {
var menuName = this.parent.inputs()[0].evaluate(), // first slot
output,
menus = {
'color number': [
"0 black=0",
"14 white=14",
"20 spectral red=20",
"25 darkest red=25",
"30 saddle brown=30",
"35 darkest brown=35",
"40 spectral orange=40",
"45 darkest orange=45",
"50 spectral yellow=50",
"55 darkest yellow=55",
"60 spectral green=60",
"65 darkest green=65",
"70 spectral cyan=70",
"75 darkest cyan=75",
"80 spectral blue=80",
"85 darkest blue=85",
"90 spectral violet=90",
"95 magenta=95"
],
'fair hue': [
"0 red=0",
"12.5 brown=12.5",
"25 orange=25",
"37.5 yellow=37.5",
"50 green=50",
"62.5 cyan=62.5",
"75 blue=75",
"87.5 violet=87.5"
],
'crayon': [
"grays",
[
"0 black #000000=0",
"1 gray7 #121212=1",
"2 gray14 #242424=2",
"3 gray21 #363636=3",
"4 gray28 #484848=4",
"5 gray36 #5c5c5c=5",
"6 gray43 #6d6d6d=6",
"7 gray50 #7f7f7f=7",
"8 gray57 #919191=8",
"9 gray64 #a3a3a3=9",
"10 gray71 #b5b5b5=10",
"11 gray78 #c8c8c8=11",
"12 gray85 #dadada=12",
"13 gray92 #ececec=13",
"14 white #ffffff=14"
],
"pinks",
[
"15 deep pink #ff1493=15",
"16 hot pink #ff69b4=16",
"17 bright pink #ff007f=17",
"18 raspberry #e30b5d=18",
"19 amaranth #e52b50=19"
],
"reds",
[
"20 red #ff0000=20",
"21 burgundy #900020=21",
"22 cherry #990000=22",
"23 dark candy apple red #a40000=23",
"24 sanguine #c00000=24",
"25 maroon #800000=25",
"26 crimson #c90016=26",
"27 Lists #d94d11=27",
"28 candy apple red #ff0800=28",
"29 coquelicot #ff3800=29"
],
"browns",
[
"30 saddle brown #8b4513=30",
"31 chocolate #7b3f00=31",
"32 kobicha #6b4423=32",
"33 sepia #704214=33",
"34 chestnut #954535=34",
"35 dark brown #654321=35",
"36 brown #964b00=36",
"37 golden brown #996515=37",
"38 cinnamon #b87333=38",
"39 copper #d2691e=39"
],
"oranges",
[
"40 orange #ff7f00=40",
"41 Pantone orange #ff5800=41",
"42 pumpkin #ff7518=42",
"43 Variables #f3761d=43",
"44 Spanish orange #e86100=44",
"45 burnt orange #cc5500=45",
"46 sinopia #cb410b=46",
"47 ochre #cc7722=47",
"48 carrot #ed9121=48",
"49 tangerine #f28500=49"
],
"yellows",
[
"50 yellow #ffff00=50",
"51 Control #e6a822=51",
"52 dark goldenrod #b8860b=52",
"53 goldenrod #daa520=53",
"54 saffron #f4c430=54",
"55 sandstorm #ecd540=55",
"56 mustard #ffdb58=56",
"57 gold #ffd700=57",
"58 egg yolk #fee33e=58",
"59 rubber duck #fbe108=59"
],
"greens",
[
"60 lime #00ff00=60",
"61 apple green #8db600=61",
"62 Operators #62c213=62",
"63 forest green #228b22=63",
"64 green #008000=64",
"65 dark green #006400=65",
"66 dark pastel green #03c03c=66",
"67 emerald #50c878=67",
"68 mint #3eb489=68",
"69 Pen #00a178=69"
],
"cyans",
[
"70 aqua (cyan) #00ffff=70",
"71 dark cyan #008b8b=71",
"72 cerulean #007ba7=72",
"73 iceberg #71a6d2=73",
"74 Sensing #0494dc=74",
"75 teal #008080=75",
"76 light sky blue #87cefa=76",
"77 deep sky blue #00bfff=77",
"78 dodger blue #1e90ff=78",
"79 azure #007fff=79"
],
"blues",
[
"80 blue #0000ff=80",
"81 midnight blue #191970=81",
"82 dark powder blue #003399=82",
"83 cobalt #0047ab=83",
"84 denim #1560bd=84",
"85 navy blue #000080=85",
"86 steel blue #4682b4=86",
"87 Motion #4a6cd4=87",
"88 cornflower #6495ed=88",
"89 slate blue #6a5acd=89"
],
"purples",
[
"90 violet #8000ff=90",
"91 Looks #8f56e3=91",
"92 grape #6f2da8=92",
"93 indigo #4b0082=93",
"94 x11 purple #a020f0=94",
"95 magenta (fuchia) #ff00ff=95",
"96 dark orchid #9932cc=96",
"97 Sound #cf4ad9=97",
"98 purple #7f007f=98",
"99 dark magenta #8b008b=99"
]
]
};
function makeMenuHelper(items, output) {
// in an array, walk through the items in pairs
var i = 0,
label, possiblyNested, hasEquals, nestingOutput;
while (i < items.length) {
label = items[i];
possiblyNested = items[i + 1];
// if possiblyNested is array, it is a nest under label
// if possiblyNested is string, it is just a sibling
if (possiblyNested === undefined) {
// label is actually the last element of the list
hasEquals = label.split("=");
if (hasEquals.length === 2) {
output[hasEquals[0]] = hasEquals[1];
i += 1;
} else if (hasEquals.length === 3) {
output[hasEquals[0]+"\u00A0"+"="+"\u00A0"+hasEquals[2]]
= hasEquals[0]+"\u00A0"+"="+"\u00A0"+hasEquals[2];
i += 1;
} else {
output[label] = label;
i += 1;
}
} else if (typeof possiblyNested == "string") {
hasEquals = label.split("=");
if (hasEquals.length == 2) {
output[hasEquals[0]] = hasEquals[1];
i += 1;
} else if (hasEquals.length == 3) {
output[hasEquals[0]+"\u00A0"+"="+"\u00A0"+hasEquals[2]]
= hasEquals[0]+"\u00A0"+"="+"\u00A0"+hasEquals[2];
i += 1;
} else {
output[label] = label;
i += 1;
}
} else if (Array.isArray(possiblyNested)) {
nestingOutput = {};
makeMenuHelper(possiblyNested, nestingOutput);
output[label] = nestingOutput;
i += 2;
} else {
throw new Error("Bad value at index " + i);
}
}
}
try {
output = {};
makeMenuHelper(menus[menuName], output);
return output;
} catch(err) {
nop(err);
}
}
);

Wyświetl plik

@ -83,7 +83,7 @@ Animation, BoxMorph, BlockDialogMorph, Project, ZERO, BLACK*/
// Global stuff ////////////////////////////////////////////////////////
modules.gui = '2021-May-21';
modules.gui = '2021-June-23';
// Declarations
@ -301,7 +301,7 @@ IDE_Morph.prototype.init = function (isAutoFill) {
};
IDE_Morph.prototype.openIn = function (world) {
var hash, myself = this, urlLanguage = null;
var hash, myself = this;
function initUser(username) {
sessionStorage.username = username;
@ -379,9 +379,6 @@ IDE_Morph.prototype.openIn = function (world) {
if (dict.noExitWarning) {
window.onbeforeunload = nop;
}
if (dict.lang) {
myself.setLanguage(dict.lang, null, true); // don't persist
}
// only force my world to get focus if I'm not in embed mode
// to prevent the iFrame from involuntarily scrolling into view
@ -475,26 +472,47 @@ IDE_Morph.prototype.openIn = function (world) {
}
);
}
} else if (location.hash.substr(0, 5) === '#run:') {
} else if (location.hash.substr(0, 5) === '#run:') {
dict = '';
hash = location.hash.substr(5);
idx = hash.indexOf("&");
if (idx > 0) {
hash = hash.slice(0, idx);
}
//decoding if hash is an encoded URI
if (hash.charAt(0) === '%'
|| hash.search(/\%(?:[0-9a-f]{2})/i) > -1) {
hash = decodeURIComponent(hash);
}
if (hash.substr(0, 8) === '<project>') {
this.rawOpenProjectString(hash);
applyFlags(myself.cloud.parseDict(location.hash.substr(5)));
idx = hash.indexOf("&");
// supporting three URL cases
// xml project
if (hash.substr(0, 8) === '<project') {
this.rawOpenProjectString(
hash.slice(0,hash.indexOf('</project>') + 10)
);
applyFlags(
myself.cloud.parseDict(
hash.substr(hash.indexOf('</project>') + 10)
)
);
// no project, only flags
} else if (idx == 0){
applyFlags(myself.cloud.parseDict(hash));
// xml file path
// three path types allowed:
// (1) absolute (http...),
// (2) relative to site ("/path") or
// (3) relative to folder ("path")
} else {
this.shield = new Morph();
this.shield.alpha = 0;
this.shield.setExtent(this.parent.extent());
this.parent.add(this.shield);
this.showMessage('Fetching project...');
if (idx > 0) {
dict = myself.cloud.parseDict(hash.substr(idx));
hash = hash.slice(0,idx);
}
this.getURL(
hash,
projectData => {
@ -516,11 +534,7 @@ IDE_Morph.prototype.openIn = function (world) {
this.shield = null;
msg.destroy();
// this.toggleAppMode(true);
applyFlags(
this.cloud.parseDict(
location.hash.substr(5)
)
);
applyFlags(dict);
}
]);
}
@ -621,16 +635,33 @@ IDE_Morph.prototype.openIn = function (world) {
this.cloudError()
);
} else if (location.hash.substr(0, 6) === '#lang:') {
urlLanguage = location.hash.substr(6);
this.setLanguage(urlLanguage, null, true); // don't persist
this.loadNewProject = true;
dict = myself.cloud.parseDict(location.hash.substr(6));
applyFlags(dict);
} else if (location.hash.substr(0, 7) === '#signup') {
this.createCloudAccount();
}
this.loadNewProject = false;
}
if (this.userLanguage) {
function launcherLangSetting() {
var langSetting = null;
if (location.hash.substr(0, 6) === '#lang:') {
if (location.hash.charAt(8) === '_') {
langSetting = location.hash.slice(6,11);
} else {
langSetting = location.hash.slice(6,8);
}
}
// lang-flag wins lang-anchor setting
langSetting = myself.cloud.parseDict(location.hash).lang || langSetting;
return langSetting;
}
if (launcherLangSetting()) {
// launch with this non-persisten lang setting
this.loadNewProject = true;
this.setLanguage(launcherLangSetting(), interpretUrlAnchors, true);
} else if (this.userLanguage) {
this.loadNewProject = true;
this.setLanguage(this.userLanguage, interpretUrlAnchors);
} else {
@ -3623,10 +3654,14 @@ IDE_Morph.prototype.settingsMenu = function () {
'microphoneMenu'
);
menu.addLine();
/*
addPreference(
'JavaScript',
'JavaScript extensions',
() => {
/*
if (!Process.prototype.enableJS) {
this.logout();
}
*/
Process.prototype.enableJS = !Process.prototype.enableJS;
this.currentSprite.blocksCache.operators = null;
this.currentSprite.paletteCache.operators = null;
@ -3634,9 +3669,11 @@ IDE_Morph.prototype.settingsMenu = function () {
},
Process.prototype.enableJS,
'uncheck to disable support for\nnative JavaScript functions',
'check to support\nnative JavaScript functions'
'check to support\nnative JavaScript functions' /* +
'.\n' +
'NOTE: You will have to manually\n' +
'sign in again to access your account.' */
);
*/
addPreference(
'Add scenes',
() => this.isAddingScenes = !this.isAddingScenes,

Wyświetl plik

@ -46,7 +46,7 @@
/*global modules, contains*/
modules.locale = '2021-March-15';
modules.locale = '2021-June-11';
// Global stuff
@ -168,7 +168,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org, jadga.huegle@sap.com',
'last_changed':
'2021-03-05'
'2021-06-11'
};
SnapTranslator.dict.it = {
@ -318,11 +318,11 @@ SnapTranslator.dict.pl = {
'language_name':
'Polski',
'language_translator':
'Witek Kranas & deKrain',
'Witek Kranas & deKrain & Andrzej Batorski',
'translator_e-mail':
'witek@oeiizk.waw.pl',
'last_changed':
'2017-11-09'
'2021-05-15'
};
SnapTranslator.dict.zh_TW = {
@ -632,3 +632,13 @@ SnapTranslator.dict.he = {
'last_changed':
'2020-04-21'
};
SnapTranslator.dict.hi = {
'language_name':
'हिंदी',
'language_translator':
'Barthdry',
'translator_e-mail':
'barathkumarbasker2007@gmail.com',
'last_changed':
'2021-05-08'
};

Wyświetl plik

@ -7,7 +7,7 @@
written by Jens Mönig
jens@moenig.org
Copyright (C) 2020 by Jens Mönig
Copyright (C) 2021 by Jens Mönig
This file is part of Snap!.
@ -38,7 +38,7 @@
// Global stuff ////////////////////////////////////////////////////////
modules.maps = '2020-March-25';
modules.maps = '2021-June-15';
// WorldMap /////////////////////////////////////////////////////////////
@ -147,7 +147,7 @@ function WorldMap(host) {
'CC-BY-SA, Imagery \u00A9 Mapbox'
}
};
this.api = this.tileServers[host || 'Wikimedia'];
this.api = this.tileServers[host || 'OpenStreetMap'];
this.lon = -122.257852;
this.lat = 37.872099;
this.zoom = 13;

Wyświetl plik

@ -1289,7 +1289,7 @@
/*global window, HTMLCanvasElement, FileReader, Audio, FileList, Map*/
var morphicVersion = '2021-Aril-12';
var morphicVersion = '2021-June-09';
var modules = {}; // keep track of additional loaded modules
var useBlurredShadows = true;
@ -8414,7 +8414,7 @@ MenuMorph.prototype.destroy = function () {
if (this.hasFocus) {
this.world.keyboardFocus = null;
}
if (!this.isListContents) {
if (!this.isListContents && (this.world.activeMenu === this)) {
this.world.activeMenu = null;
}
MenuMorph.uber.destroy.call(this);

Wyświetl plik

@ -84,7 +84,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, BooleanSlotMorph,
localize, TableMorph, TableFrameMorph, normalizeCanvas, VectorPaintEditorMorph,
AlignmentMorph, Process, WorldMap, copyCanvas, useBlurredShadows*/
modules.objects = '2021-April-23';
modules.objects = '2021-June-14';
var SpriteMorph;
var StageMorph;
@ -1508,6 +1508,18 @@ SpriteMorph.prototype.initBlocks = function () {
spec: 'code of %cmdRing'
},
// Extensions
doApplyExtension: {
type: 'command',
category: 'other',
spec: 'primitive %prim %mult%s'
},
reportApplyExtension: {
type: 'reporter',
category: 'other',
spec: 'primitive %prim %mult%s'
},
// Video motion
doSetVideoTransparency: {
type: 'command',
@ -1520,7 +1532,7 @@ SpriteMorph.prototype.initBlocks = function () {
category: 'sensing',
spec: 'video %vid on %self',
defaults: [['motion'], ['myself']]
},
}
};
};
@ -2555,6 +2567,7 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push(block('doPauseAll'));
},
<<<<<<< HEAD
sensing: () => {
blocks.push(block('reportTouchingObject'));
blocks.push(block('reportTouchingColor'));
@ -2571,6 +2584,9 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push(block('reportMouseDown'));
blocks.push('-');
blocks.push(block('reportKeyPressed'));
=======
if (Process.prototype.enableJS) {
>>>>>>> upstream/scenes
blocks.push('-');
blocks.push(block('reportRelationTo'));
blocks.push(block('reportAspect'));
@ -2761,6 +2777,7 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push(block('reportListItem'));
blocks.push(block('reportCDR'));
blocks.push('-');
<<<<<<< HEAD
blocks.push(block('reportListAttribute'));
blocks.push(block('reportListIndex'));
blocks.push(block('reportListContainsItem'));
@ -2798,6 +2815,12 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push('-');
blocks.push(block('reportMappedCode'));
}
=======
blocks.push(block('doShowTable'));
blocks.push('-');
blocks.push(block('doApplyExtension'));
blocks.push(block('reportApplyExtension'));
>>>>>>> upstream/scenes
}
}
@ -8790,7 +8813,7 @@ StageMorph.prototype.blockTemplates = function (category) {
blocks.push(block('reportIsA'));
blocks.push(block('reportIsIdentical'));
if (true) { // (Process.prototype.enableJS) {
if (Process.prototype.enableJS) {
blocks.push('-');
blocks.push(block('reportJSFunction'));
if (Process.prototype.enableCompiling) {
@ -8928,6 +8951,9 @@ StageMorph.prototype.blockTemplates = function (category) {
blocks.push(txt);
blocks.push('-');
blocks.push(block('doShowTable'));
blocks.push('-');
blocks.push(block('doApplyExtension'));
blocks.push(block('reportApplyExtension'));
}
//////// /////////////////////////

Wyświetl plik

@ -61,8 +61,7 @@ Project*/
// Global stuff ////////////////////////////////////////////////////////
modules.store = '2021-May-21';
modules.store = '2021-June-24';
// XML_Serializer ///////////////////////////////////////////////////////
/*
@ -1177,17 +1176,6 @@ SnapSerializer.prototype.loadBlock = function (model, isReporter, object) {
model.attributes['var']
);
} else {
/*
// disable JavaScript functions, commented out for now
if (model.attributes.s === 'reportJSFunction' &&
!Process.prototype.enableJS) {
if (window.confirm('enable JavaScript?')) {
Process.prototype.enableJS = true;
} else {
throw new Error('JavaScript is not enabled');
}
}
*/
block = SpriteMorph.prototype.blockForSelector(model.attributes.s);
migration = SpriteMorph.prototype.blockMigrations[
model.attributes.s
@ -1310,7 +1298,6 @@ SnapSerializer.prototype.loadInput = function (model, input, block, object) {
});
input.fixLayout();
} else if (model.tag === 'block' || model.tag === 'custom-block') {
// block.silentReplaceInput(input, this.loadBlock(model, true, object));
block.replaceInput(input, this.loadBlock(model, true, object));
} else if (model.tag === 'color') {
input.setColor(this.loadColor(model.contents));

Wyświetl plik

@ -59,9 +59,10 @@ degrees, detect, nop, radians, ReporterSlotMorph, CSlotMorph, RingMorph, Sound,
IDE_Morph, ArgLabelMorph, localize, XML_Element, hex_sha512, TableDialogMorph,
StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy, Map,
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, BLACK,
TableFrameMorph, ColorSlotMorph, isSnapObject, newCanvas, Symbol, SVG_Costume*/
TableFrameMorph, ColorSlotMorph, isSnapObject, newCanvas, Symbol, SVG_Costume,
SnapExtensions*/
modules.threads = '2021-April-17';
modules.threads = '2021-June-24';
var ThreadManager;
var Process;
@ -562,7 +563,7 @@ Process.prototype.enableLiveCoding = false; // experimental
Process.prototype.enableSingleStepping = false; // experimental
Process.prototype.enableCompiling = false; // experimental
Process.prototype.flashTime = 0; // experimental
// Process.prototype.enableJS = false;
Process.prototype.enableJS = false;
function Process(topBlock, receiver, onComplete, yieldFirst) {
this.topBlock = topBlock || null;
@ -811,6 +812,23 @@ Process.prototype.evaluateBlock = function (block, argCount) {
}
};
// Process: Primitive Extensions (for libraries etc.)
Process.prototype.doApplyExtension = function (prim, args) {
this.reportApplyExtension(prim, args);
};
Process.prototype.reportApplyExtension = function (prim, args) {
var ext = SnapExtensions.primitives.get(prim);
if (isNil(ext)) {
throw new Error('missing / unspecified extension: ' + prim);
}
return ext.apply(
this.blockReceiver(),
args.itemsArray().concat([this])
);
};
// Process: Special Forms Blocks Primitives
Process.prototype.reportOr = function (block) {
@ -1105,22 +1123,51 @@ Process.prototype.expectReport = function () {
// Process Exception Handling
Process.prototype.handleError = function (error, element) {
var m = element;
Process.prototype.throwError = function (error, element) {
var m = element,
ide = this.homeContext.receiver.parentThatIsA(IDE_Morph);
this.stop();
this.errorFlag = true;
this.topBlock.addErrorHighlight();
if (isNil(m) || isNil(m.world())) {m = this.topBlock; }
m.showBubble(
(m === element ? '' : 'Inside: ')
+ error.name
+ '\n'
+ error.message,
this.exportResult,
this.receiver
);
if (ide.isAppMode) {
ide.showMessage(error.name + '\n' + error.message);
} else {
if (isNil(m) || isNil(m.world())) {m = this.topBlock; }
m.showBubble(
(m === element ? '' : 'Inside: ')
+ error.name
+ '\n'
+ error.message,
this.exportResult,
this.receiver
);
}
};
Process.prototype.tryCatch = function (action, exception, errVarName) {
var next = this.context.continuation();
this.handleError = function(error) {
this.resetErrorHandling();
if (exception.expression instanceof CommandBlockMorph) {
exception.expression = exception.expression.blockSequence();
}
exception.pc = 0;
exception.outerContext.variables.addVar(errVarName);
exception.outerContext.variables.setVar(errVarName, error.message);
this.context = exception;
this.evaluate(next, new List(), true);
};
this.evaluate(action, new List(), true);
};
Process.prototype.resetErrorHandling = function () {
this.handleError = this.throwError;
};
Process.prototype.resetErrorHandling();
Process.prototype.errorObsolete = function () {
throw new Error('a custom block definition is missing');
};
@ -1185,6 +1232,9 @@ Process.prototype.reifyPredicate = function (topBlock, parameterNames) {
};
Process.prototype.reportJSFunction = function (parmNames, body) {
if (!this.enableJS) {
throw new Error('JavaScript extensions for Snap!\nare turned off');
}
return Function.apply(
null,
parmNames.itemsArray().concat([body])
@ -1204,9 +1254,6 @@ Process.prototype.evaluate = function (
return this.returnValueToParentContext(null);
}
if (context instanceof Function) {
// if (!this.enableJS) {
// throw new Error('JavaScript is not enabled');
// }
return context.apply(
this.blockReceiver(),
args.itemsArray().concat([this])
@ -1638,8 +1685,9 @@ Process.prototype.reportGetVar = function () {
);
};
Process.prototype.doShowVar = function (varName) {
var varFrame = (this.context || this.homeContext).variables,
Process.prototype.doShowVar = function (varName, context) {
// context is an optional start-context to be used by extensions
var varFrame = (context || (this.context || this.homeContext)).variables,
stage,
watcher,
target,
@ -1701,9 +1749,10 @@ Process.prototype.doShowVar = function (varName) {
}
};
Process.prototype.doHideVar = function (varName) {
Process.prototype.doHideVar = function (varName, context) {
// if no varName is specified delete all watchers on temporaries
var varFrame = this.context.variables,
// context is an optional start-context to be used by extensions
var varFrame = (context || this.context).variables,
stage,
watcher,
target,
@ -6867,6 +6916,16 @@ Context.prototype.stackSize = function () {
return 1 + this.parentContext.stackSize();
};
Context.prototype.isInCustomBlock = function () {
if (this.isCustomBlock) {
return true;
}
if (this.parentContext) {
return this.parentContext.isInCustomBlock();
}
return false;
};
// Variable /////////////////////////////////////////////////////////////////
function Variable(value, isTransient) {