diff --git a/.gitignore b/.gitignore
index c40cd56..a349cbb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,2 @@
.svn
node_modules
-jquery-turtle.min.js
diff --git a/BUILD.txt b/BUILD.txt
index 6208a91..c22f4af 100644
--- a/BUILD.txt
+++ b/BUILD.txt
@@ -29,5 +29,3 @@ Testing
Unit tests use a headless webkit. When setting it up on a system without
GUI, you may find that you need to install font support. On debian.
"apt-get libfontconfig1" provides enough font support.
-
-
diff --git a/LICENSE.txt b/LICENSE.txt
index fca7187..f997494 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -2,7 +2,7 @@ jQuery-turtle version 2.0
LICENSE (MIT):
-Copyright (c) 2013 Pencil Code Foundation, Google, and other contributors.
+Copyright (c) 2013 Pencil Code Foundation, Google Inc., and other contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 91bace6..fe5db8e 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
jQuery-turtle
=============
-version 2.0.8
+version 2.0.9
jQuery-turtle is a jQuery plugin for turtle graphics.
@@ -254,7 +254,7 @@ the functions:
eval $.turtle() # Create the default turtle and global functions.
-defaultspeed Infinity
+speed Infinity
write "Catch blue before red gets you."
bk 100
r = hatch red
@@ -264,7 +264,7 @@ tick 10, ->
fd 6
r.turnto turtle
r.fd 4
- b.turnto bearing b
+ b.turnto direction b
b.fd 3
if b.touches(turtle)
write "You win!"
@@ -331,7 +331,7 @@ element.
License (MIT)
-------------
-Copyright (c) 2014 Pencil Code, Google, and other contributors
+Copyright (c) 2014 Pencil Code, Google Inc., and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/bower.json b/bower.json
index f2e71d7..4eca85a 100644
--- a/bower.json
+++ b/bower.json
@@ -2,7 +2,7 @@
"name": "jquery-turtle",
"main": "jquery-turtle.js",
"ignore": [],
- "version": "2.0.8",
+ "version": "2.0.9",
"description": "Turtle graphics plugin for jQuery.",
"devDependencies": {
"jquery": "latest",
diff --git a/jquery-turtle.js b/jquery-turtle.js
index 476916b..9008141 100644
--- a/jquery-turtle.js
+++ b/jquery-turtle.js
@@ -4,7 +4,7 @@
jQuery-turtle
=============
-version 2.0.8
+version 2.0.9
jQuery-turtle is a jQuery plugin for turtle graphics.
@@ -261,7 +261,7 @@ the functions:
eval $.turtle() # Create the default turtle and global functions.
-defaultspeed Infinity
+speed Infinity
write "Catch blue before red gets you."
bk 100
r = new Turtle red
@@ -772,7 +772,7 @@ function readTransformMatrix(elem) {
// Reads out the css transformOrigin property, if present.
function readTransformOrigin(elem, wh) {
var hidden = ($.css(elem, 'display') === 'none'),
- swapout, old, name, gcs, origin;
+ swapout, old, name;
if (hidden) {
// IE GetComputedStyle doesn't give pixel values for transformOrigin
// unless the element is unhidden.
@@ -783,13 +783,13 @@ function readTransformOrigin(elem, wh) {
elem.style[name] = swapout[name];
}
}
- var gcs = (global.getComputedStyle ? global.getComputedStyle(elem) : null),
- origin = (gcs && gcs[transformOrigin] || $.css(elem, 'transformOrigin'));
+ var gcs = (global.getComputedStyle ? global.getComputedStyle(elem) : null);
if (hidden) {
for (name in swapout) {
elem.style[name] = old[name];
}
}
+ var origin = (gcs && gcs[transformOrigin] || $.css(elem, 'transformOrigin'));
if (origin && origin.indexOf('%') < 0) {
return $.map(origin.split(' '), parseFloat);
}
@@ -960,7 +960,7 @@ function getTurtleOrigin(elem, inverseParent, extra) {
{ position: "absolute", visibility: "hidden", display: "block" } : {},
substTransform = swapout[transform] = (inverseParent ? 'matrix(' +
$.map(inverseParent, cssNum).join(', ') + ', 0, 0)' : 'none'),
- old = {}, name, gbcr, transformOrigin, result;
+ old = {}, name, gbcr, transformOrigin;
for (name in swapout) {
old[name] = elem.style[name];
elem.style[name] = swapout[name];
@@ -1250,7 +1250,7 @@ function scrollWindowToDocumentPosition(pos, limit) {
if (tx < ww2) { tx = ww2; }
if (ty > dh - wh2) { ty = dh - wh2; }
if (ty < wh2) { ty = wh2; }
- targ = { pageX: tx, pageY: ty };
+ var targ = { pageX: tx, pageY: ty };
if ($.isNumeric(limit)) {
targ = limitMovement(w.origin(), targ, limit);
}
@@ -1504,6 +1504,8 @@ function writeTurtleTransform(ts) {
return result.join(' ');
}
+function modulo(n, m) { return (+n % (m = +m) + m) % m; }
+
function radiansToDegrees(r) {
var d = r * 180 / Math.PI;
if (d > 180) { d -= 360; }
@@ -1511,7 +1513,7 @@ function radiansToDegrees(r) {
}
function convertToRadians(d) {
- return d * Math.PI / 180;
+ return d / 180 * Math.PI;
}
function normalizeRotation(x) {
@@ -2176,8 +2178,7 @@ function touchesPixel(elem, color) {
h = (bb.bottom - bb.top),
osc = getOffscreenCanvas(w, h),
octx = osc.getContext('2d'),
- rgba = rgbaForColor(color),
- j = 1, k, data;
+ j = 1, k;
if (!c || c.length < 3 || !w || !h) { return false; }
octx.drawImage(canvas,
bb.left, bb.top, w, h, 0, 0, w, h);
@@ -2687,7 +2688,7 @@ function imgUrl(url) {
if (/\//.test(url)) { return url; }
url = '/img/' + url;
if (isPencilHost(global.location.hostname)) { return url; }
- return '//pencil.io' + url;
+ return '//pencilcode.net' + url;
}
// Retrieves the pencil code login cookie, if there is one.
function loginCookie() {
@@ -2724,7 +2725,8 @@ var stablyLoadedImages = {};
// @param css is a dictionary of css props to set when the image is loaded.
// @param cb is an optional callback, called after the loading is done.
function setImageWithStableOrigin(elem, url, css, cb) {
- var record, urlobj = absoluteUrlObject(url), url = urlobj.href;
+ var record, urlobj = absoluteUrlObject(url);
+ url = urlobj.href;
// The data-loading attr will always reflect the last URL requested.
elem.setAttribute('data-loading', url);
if (url in stablyLoadedImages) {
@@ -3030,7 +3032,7 @@ var Pencil = (function(_super) {
}
// The pencil is a sprite that just defaults to zero size.
var context = canvas ? canvas.parentElement : null;
- var settings = { width: 0, height: 0, color: transparent };
+ var settings = { width: 0, height: 0, color: 'transparent' };
Pencil.__super__.constructor.call(this, settings, context);
// Set the pencil to hidden, infinite speed,
// and drawing on the specifed canvas.
@@ -3070,7 +3072,7 @@ var Webcam = (function(_super) {
function Webcam(opts, context) {
var attrs = "", hassrc = false, hasautoplay = false, hasdims = false;
if ($.isPlainObject(opts)) {
- for (key in opts) {
+ for (var key in opts) {
attrs += ' ' + key + '="' + escapeHtml(opts[key]) + '"';
}
hassrc = ('src' in opts);
@@ -3315,12 +3317,12 @@ var Piano = (function(_super) {
// Converts a midi number to a white key position (black keys round left).
function wcp(n) {
- return floor((n + 7) / 12 * 7);
+ return Math.floor((n + 7) / 12 * 7);
};
// Converts from a white key position to a midi number.
function mcp(n) {
- return ceil(n / 7 * 12) - 7;
+ return Math.ceil(n / 7 * 12) - 7;
};
// True if midi #n is a black key.
@@ -3726,7 +3728,7 @@ function forwardBodyMouseEventsIfNeeded() {
var warn = $.turtle.nowarn;
$.turtle.nowarn = true;
var sel = $(globalDrawing.surface)
- .find('.turtle').within('touch', e).eq(0);
+ .find('.turtle,.turtlelabel').within('touch', e).eq(0);
$.turtle.nowarn = warn;
if (sel.length === 1) {
// Erase portions of the event that are wrong for the turtle.
@@ -3897,11 +3899,16 @@ function resetAudio() {
atop.out = null;
atop.currentStart = null;
}
- var dcn = atop.ac.createDynamicsCompressor();
- dcn.ratio = 16;
- dcn.attack = 0.0005;
- dcn.connect(atop.ac.destination);
- atop.out = dcn;
+ // If resetting due to interrupt after AudioContext closed, this can fail.
+ try {
+ var dcn = atop.ac.createDynamicsCompressor();
+ dcn.ratio = 16;
+ dcn.attack = 0.0005;
+ dcn.connect(atop.ac.destination);
+ atop.out = dcn;
+ } catch (e) {
+ getAudioTop.audioTop = null;
+ }
}
}
@@ -4238,7 +4245,8 @@ var Instrument = (function() {
} else if (releasetime <= attacktime) {
// Release before attack is done? Interrupt ramp up.
g.gain.linearRampToValueAtTime(
- amp * (releasetime - starttime) / (attacktime - starttime));
+ amp * (releasetime - starttime) / (attacktime - starttime),
+ releasetime);
} else {
// Release during decay? Interrupt decay down.
g.gain.setValueAtTime(amp * (timbre.sustain + (1 - timbre.sustain) *
@@ -4510,7 +4518,7 @@ var Instrument = (function() {
if (key in given) {
timbre[key] = given[key];
} else {
- timbre[key] = defaulTimbre[key];
+ timbre[key] = defaultTimbre[key];
}
}
}
@@ -4702,16 +4710,13 @@ var Instrument = (function() {
return result;
}
- var whiteNoiseBuf = null;
function getWhiteNoiseBuf() {
- if (whiteNoiseBuf == null) {
- var ac = getAudioTop().ac,
- bufferSize = 2 * ac.sampleRate,
- whiteNoiseBuf = ac.createBuffer(1, bufferSize, ac.sampleRate),
- output = whiteNoiseBuf.getChannelData(0);
- for (var i = 0; i < bufferSize; i++) {
- output[i] = Math.random() * 2 - 1;
- }
+ var ac = getAudioTop().ac,
+ bufferSize = 2 * ac.sampleRate,
+ whiteNoiseBuf = ac.createBuffer(1, bufferSize, ac.sampleRate),
+ output = whiteNoiseBuf.getChannelData(0);
+ for (var i = 0; i < bufferSize; i++) {
+ output[i] = Math.random() * 2 - 1;
}
return whiteNoiseBuf;
}
@@ -5199,7 +5204,6 @@ function parseABCFile(str) {
function syncopateStem(stem, t) {
var j, note, stemtime = stem.time, newtime = stemtime + t;
stem.time = newtime;
- syncopateStem
for (j = 0; j < stem.notes.length; ++j) {
note = stem.notes[j];
// Only adjust a note's duration if it matched the stem's duration.
@@ -5759,7 +5763,7 @@ function canElementMoveInstantly(elem) {
// moving at speed Infinity.
var atime;
return (elem && $.queue(elem).length == 0 &&
- !elem.parentElement.style.transform &&
+ (!elem.parentElement || !elem.parentElement.style.transform) &&
((atime = animTime(elem)) === 0 || $.fx.speeds[atime] === 0));
}
@@ -5943,6 +5947,9 @@ function wrapglobalcommand(name, helptext, fn, fnfilter) {
cc.exit();
}
if (early) {
+ if (early.result && early.result.constructor === jQuery && global_turtle) {
+ sync(global_turtle, early.result);
+ }
return early.result;
}
};
@@ -6417,6 +6424,39 @@ function drawArrowLine(c, w, x0, y0, x1, y1) {
drawArrowHead(c, m);
}
+//////////////////////////////////////////////////////////////////////////
+// VOICE SYNTHESIS
+// Method for uttering words.
+//////////////////////////////////////////////////////////////////////////
+function utterSpeech(words, cb) {
+ var pollTimer = null;
+ function complete() {
+ if (pollTimer) { clearInterval(pollTimer); }
+ if (cb) { cb(); }
+ }
+ if (!global.speechSynthesis) {
+ console.log('No speech synthesis: ' + words);
+ complete();
+ return;
+ }
+ try {
+ var msg = new global.SpeechSynthesisUtterance(words);
+ msg.addEventListener('end', complete);
+ msg.addEventListener('error', complete);
+ msg.lang = navigator.language || 'en-GB';
+ global.speechSynthesis.speak(msg);
+ pollTimer = setInterval(function() {
+ // Chrome speech synthesis fails to deliver an 'end' event
+ // sometimes, so we also poll every 250ms.
+ if (global.speechSynthesis.pending || global.speechSynthesis.speaking) return;
+ complete();
+ }, 250);
+ } catch (e) {
+ if (global.console) { global.console.log(e); }
+ complete();
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
// TURTLE FUNCTIONS
// Turtle methods to be registered as jquery instance methods.
@@ -6866,34 +6906,13 @@ var turtlefn = {
this.plan(function(j, elem) {
cc.appear(j);
this.queue(function(next) {
- var finished = false,
- pollTimer = null,
- complete = function() {
- if (finished) return;
- clearInterval(pollTimer);
- finished = true;
+ utterSpeech(words, function() {
cc.resolve(j);
next();
- };
- try {
- var msg = new SpeechSynthesisUtterance(words);
- msg.addEventListener('end', complete);
- msg.addEventListener('error', complete);
- speechSynthesis.speak(msg);
- pollTimer = setInterval(function() {
- // Chrome speech synthesis fails to deliver an 'end' event
- // sometimes, so we also poll every 250ms.
- if (speechSynthesis.pending || speechSynthesis.speaking) return;
- complete();
- }, 250);
- } catch (e) {
- if (global.console) { global.console.log(e); }
- complete();
- }
+ });
});
});
return this;
-
}),
play: wrapcommand('play', 1,
["play(notes) Play notes. Notes are specified in " +
@@ -7089,13 +7108,13 @@ var turtlefn = {
var intick = insidetick;
return this.plan(function(j, elem) {
cc.appear(j);
- var applyStyles = {padding: 8},
+ var applyStyles = {},
currentStyles = this.prop('style');
// For defaults, copy inline styles of the turtle itself except for
// properties in the following list (these are the properties used to
// make the turtle look like a turtle).
- for (var j = 0; j < currentStyles.length; ++j) {
- var styleProperty = currentStyles[j];
+ for (var j2 = 0; j2 < currentStyles.length; ++j2) {
+ var styleProperty = currentStyles[j2];
if (/^(?:width|height|opacity|background-image|background-size)$/.test(
styleProperty) || /transform/.test(styleProperty)) {
continue;
@@ -7114,6 +7133,10 @@ var turtlefn = {
// Place the label on the screen using the figured styles.
var out = prepareOutput(html, 'label').result.css(applyStyles)
.addClass('turtlelabel').appendTo(getTurtleField());
+ // If the output has a turtleinput, then forward mouse events.
+ if (out.hasClass('turtleinput') || out.find('.turtleinput').length) {
+ mouseSetupHook.apply(out.get(0));
+ }
if (styles && 'id' in styles) {
out.attr('id', styles.id);
}
@@ -7298,7 +7321,7 @@ var turtlefn = {
if (typeof val != 'object' ||
!$.isNumeric(val.width) || !$.isNumeric(val.height) ||
!($.isArray(val.data) || val.data instanceof Uint8ClampedArray ||
- val.data instanceof Unit8Array)) {
+ val.data instanceof Uint8Array)) {
return;
}
var imdat = ctx.createImageData(
@@ -7509,7 +7532,6 @@ var turtlefn = {
callback.apply(this, arguments);
}
});
- sync = null;
}),
plan: wrapraw('plan',
["plan(fn) Runs fn in the animation queue. For planning logic: " +
@@ -7565,6 +7587,33 @@ var turtlefn = {
})
};
+//////////////////////////////////////////////////////////////////////////
+// QUEUING SUPPORT
+//////////////////////////////////////////////////////////////////////////
+
+function queueShowHideToggle() {
+ $.each(['toggle', 'show', 'hide'], function(i, name) {
+
+
+ var builtInFn = $.fn[name];
+ // Change show/hide/toggle to queue their behavior by default.
+ // Since animating show/hide will call the zero-argument
+ // form synchronously at the end of animation, we avoid
+ // infinite recursion by examining jQuery's internal fxshow
+ // state and avoiding the recursion if the animation is calling
+ // show/hide.
+ $.fn[name] = function(speed, easing, callback) {
+ var a = arguments;
+ // TODO: file a bug in jQuery to allow solving this without _data.
+ if (!a.length && this.hasClass('turtle') &&
+ (this.length > 1 || !$._data(this[0], 'fxshow'))) {
+ a = [0];
+ }
+ builtInFn.apply(this, a);
+ }
+ });
+}
+
// If the queue for an image is empty, starts by queuing a wait-for-load.
function queueWaitIfLoadingImg(img, qname) {
if (!qname) qname = 'fx';
@@ -7579,6 +7628,10 @@ function queueWaitIfLoadingImg(img, qname) {
}
}
+//////////////////////////////////////////////////////////////////////////
+// HUNG LOOP DETECTION
+//////////////////////////////////////////////////////////////////////////
+
var warning_shown = {},
loopCounter = 0,
hungTimer = null,
@@ -7687,7 +7740,7 @@ $.fn.extend(turtlefn);
// * Sets up a global "hatch" function to make a new turtle.
//////////////////////////////////////////////////////////////////////////
-var turtleGIFUrl = "data:image/gif;base64,R0lGODlhKAAwAPIFAAAAAAFsOACSRTCuSICAgP///wAAAAAAACH5BAlkAAYAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAKAAwAAAD72i6zATEgBCAebHpzUnxhDAMAvhxKOoV3ziuZyo3RO26dTbvgXj/gsCO9ysOhENZz+gKJmcUkmA6PSKfSqrWieVtuU+KGNXbXofLEZgR/VHCgdua4isGz9mbmM6U7/94BmlyfUZ1fhqDhYuGgYqMkCOBgo+RfWsNlZZ3ewIpcZaIYaF6XaCkR6aokqqrk0qrqVinpK+fsbZkuK2ouRy0ob4bwJbCibthh6GYebGcY7/EsWqTbdNG1dd9jnXPyk2d38y0Z9Yub2yA6AvWPYk+zEnkv6xdCoPuw/X2gLqy9vJIGAN4b8pAgpQOIlzI8EkCACH5BAlkAAYALAAAAAAoADAAAAPuaLrMBMSAEIB5senNSfGEMAwC+HEo6hXfOK5nKjdE7bp1Nu+BeP+CwI73Kw6EQ1nP6AomZxSSYDo9Ip9KqtaJ5W25Xej3qqGYsdEfZbMcgZXtYpActzLMeLOP6c7f3nVNfEZ7TXSFg4lyZAYBio+LZYiQfHMbc3iTlG9ilGpdjp4ujESiI6RQpqegqkesqqhKrbEpoaa0KLaiuBy6nrxss6+3w7tomo+cDXmBnsoLza2nsb7SN2tl1nyozVOZTJhxysxnd9XYCrrAtT7KQaPruavBo2HQ8xrvffaN+GV5/JbE45fOG8Ek5Q4qXHgwAQA7"
+var turtleGIFUrl = "data:image/gif;base64,R0lGODlhKAAwAPIFAAAAAAFsOACSRTCuSICAgP///wAAAAAAACH5BAlkAAYAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAKAAwAAAD72i6zATEgBCAebHpzUnxhDAMAvhxKOoV3ziuZyo3RO26dTbvgXj/gsCO9ysOhENZz+gKJmcUkmA6PSKfSqrWieVtuU+KGNXbXofLEZgR/VHCgdua4isGz9mbmM6U7/94BmlyfUZ1fhqDhYuGgYqMkCOBgo+RfWsNlZZ3ewIpcZaIYaF6XaCkR6aokqqrk0qrqVinpK+fsbZkuK2ouRy0ob4bwJbCibthh6GYebGcY7/EsWqTbdNG1dd9jnXPyk2d38y0Z9Yub2yA6AvWPYk+zEnkv6xdCoPuw/X2gLqy9vJIGAN4b8pAgpQOIlzI8EkCACH5BAlkAAYALAAAAAAoADAAAAPuaLrMBMSAEIB5senNSfGEMAwC+HEo6hXfOK5nKjdE7bp1Nu+BeP+CwI73Kw6EQ1nP6AomZxSSYDo9Ip9KqtaJ5W25Xej3qqGYsdEfZbMcgZXtYpActzLMeLOP6c7f3nVNfEZ7TXSFg4lyZAYBio+LZYiQfHMbc3iTlG9ilGpdjp4ujESiI6RQpqegqkesqqhKrbEpoaa0KLaiuBy6nrxss6+3w7tomo+cDXmBnsoLza2nsb7SN2tl1nyozVOZTJhxysxnd9XYCrrAtT7KQaPruavBo2HQ8xrvffaN+GV5/JbE45fOG8Ek5Q4qXHgwAQA7";
var eventfn = { click:1, dblclick:1, mouseup:1, mousedown:1, mousemove:1 };
@@ -7817,6 +7870,20 @@ var dollar_turtle_methods = {
function globalspeed(mps) {
globaldefaultspeed(mps);
}),
+ say: wrapraw('say',
+ ["say(words) Say something. Use English words." +
+ "say \"Let's go!\" "],
+ function say(words) {
+ if (global_turtle) {
+ var sel = $(global_turtle);
+ sel.say.call(sel, words);
+ } else {
+ var cc = setupContinuation(null, 'say', arguments, 0);
+ cc.appear(null);
+ utterSpeech(words, function() { cc.resolve(null); });
+ cc.exit();
+ }
+ }),
play: wrapraw('play',
["play(notes) Play notes. Notes are specified in " +
"" +
@@ -7848,7 +7915,7 @@ var dollar_turtle_methods = {
sel.tone.apply(sel, arguments);
} else {
var instrument = getGlobalInstrument();
- instrument.play.apply(instrument, args);
+ instrument.play.apply(instrument);
}
}),
silence: wrapraw('silence',
@@ -7887,7 +7954,6 @@ var dollar_turtle_methods = {
callback.apply(this, arguments);
}
});
- sync = null;
}),
load: wrapraw('load',
["load(url, cb) Loads data from the url and passes it to cb. " +
@@ -7923,7 +7989,8 @@ var dollar_turtle_methods = {
"save 'intro', 'pen gold, 20\\nfd 100\\n' "],
function(url, data, cb) {
if (!url) throw new Error('Missing url for save');
- var payload = { }, url = apiUrl(url, 'save'), key;
+ var payload = { }, key;
+ url = apiUrl(url, 'save');
if (/\.json(?:$|\?|\#)/.test(url)) {
data = JSON.stringify(data, null, 2);
}
@@ -7997,12 +8064,16 @@ var dollar_turtle_methods = {
readnum: wrapglobalcommand('readnum',
["readnum(html, fn) Reads numeric input. Only numbers allowed: " +
"readnum 'Amount?', (v) -> write 'Tip: ' + (0.15 * v) "],
- doOutput, function readnum(a, b) { return prepareInput(a, b, 1); }),
+ doOutput, function readnum(a, b) { return prepareInput(a, b, 'number'); }),
readstr: wrapglobalcommand('readstr',
["readstr(html, fn) Reads text input. Never " +
"converts input to a number: " +
"readstr 'Enter code', (v) -> write v.length + ' long' "],
- doOutput, function readstr(a, b) { return prepareInput(a, b, -1); }),
+ doOutput, function readstr(a, b) { return prepareInput(a, b, 'text'); }),
+ listen: wrapglobalcommand('listen',
+ ["listen(html, fn) Reads voice input, if the browser supports it:" +
+ "listen 'Say something', (v) -> write v "],
+ doOutput, function readstr(a, b) { return prepareInput(a, b, 'voice'); }),
menu: wrapglobalcommand('menu',
["menu(map) shows a menu of choices and calls a function " +
"based on the user's choice: " +
@@ -8119,41 +8190,129 @@ var dollar_turtle_methods = {
["abs(x) The absolute value of x. " +
"see abs -5 "], Math.abs),
acos: wrapraw('acos',
- ["acos(degreees) Trigonometric arccosine, in degrees. " +
- "see acos 0.5 "],
- function acos(x) { return roundEpsilon(Math.acos(x) * 180 / Math.PI); }
- ),
+ ["acos(x) Trigonometric arccosine, in radians. " +
+ "see acos 0.5 "], Math.acos),
asin: wrapraw('asin',
- ["asin(degreees) Trigonometric arcsine, in degrees. " +
- "see asin 0.5 "],
- function asin(x) { return roundEpsilon(Math.asin(x) * 180 / Math.PI); }
- ),
+ ["asin(y) Trigonometric arcsine, in radians. " +
+ "see asin 0.5 "], Math.asin),
atan: wrapraw('atan',
- ["atan(degreees) Trigonometric arctangent, in degrees. " +
+ ["atan(y, x = 1) Trigonometric arctangent, in radians. " +
"see atan 0.5 "],
- function atan(x) { return roundEpsilon(Math.atan(x) * 180 / Math.PI); }
+ function atan(y, x) { return Math.atan2(y, (x == undefined) ? 1 : x); }
),
- atan2: wrapraw('atan2',
- ["atan2(degreees) Trigonometric two-argument arctangent, " +
- "in degrees. see atan -1, 0 "],
- function atan2(x, y) {
- return roundEpsilon(Math.atan2(x, y) * 180 / Math.PI);
- }),
cos: wrapraw('cos',
- ["cos(degreees) Trigonometric cosine, in degrees. " +
- "see cos 45 "],
- function cos(x) { return roundEpsilon(Math.cos((x % 360) * Math.PI / 180)); }
- ),
+ ["cos(radians) Trigonometric cosine, in radians. " +
+ "see cos 0 "], Math.cos),
sin: wrapraw('sin',
- ["sin(degreees) Trigonometric sine, in degrees. " +
- "see sin 45 "],
- function sin(x) { return roundEpsilon(Math.sin((x % 360) * Math.PI / 180)); }
- ),
+ ["sin(radians) Trigonometric sine, in radians. " +
+ "see sin 0 "], Math.sin),
tan: wrapraw('tan',
- ["tan(degreees) Trigonometric tangent, in degrees. " +
- "see tan 45 "],
- function tan(x) { return roundEpsilon(Math.tan((x % 360) * Math.PI / 180)); }
- ),
+ ["tan(radians) Trigonometric tangent, in radians. " +
+ "see tan 0 "], Math.tan),
+
+ // For degree versions of trig functions, make sure we return exact
+ // results when possible. The set of values we have to consider is
+ // fortunately very limited. See "Rational Values of Trigonometric
+ // Functions." http://www.jstor.org/stable/2304540
+
+ acosd: wrapraw('acosd',
+ ["acosd(x) Trigonometric arccosine, in degrees. " +
+ "see acosd 0.5 "],
+ function acosd(x) {
+ switch (x) {
+ case 1: return 0;
+ case .5: return 60;
+ case 0: return 90;
+ case -.5: return 120;
+ case -1: return 180;
+ }
+ return Math.acos(x) * 180 / Math.PI;
+ }),
+ asind: wrapraw('asind',
+ ["asind(x) Trigonometric arcsine, in degrees. " +
+ "see asind 0.5 "],
+ function asind(x) {
+ switch (x) {
+ case 1: return 90;
+ case .5: return 30;
+ case 0: return 0;
+ case -.5: return -30;
+ case -1: return -90;
+ }
+ return Math.asin(x) * 180 / Math.PI;
+ }),
+ atand: wrapraw('atand',
+ ["atand(y, x = 1) Trigonometric arctangent, " +
+ "in degrees. see atand -1, 0/mark>"],
+ function atand(y, x) {
+ if (x == undefined) { x = 1; }
+ if (y == 0) {
+ return (x == 0) ? NaN : ((x > 0) ? 0 : 180);
+ } else if (x == 0) {
+ return (y > 0) ? Infinity : -Infinity;
+ } else if (Math.abs(y) == Math.abs(x)) {
+ return (y > 0) ? ((x > 0) ? 45 : 135) :
+ ((x > 0) ? -45 : -135);
+ }
+ return Math.atan2(y, x) * 180 / Math.PI;
+ }),
+ cosd: wrapraw('cosd',
+ ["cosd(degrees) Trigonometric cosine, in degrees. " +
+ "see cosd 45 "],
+ function cosd(x) {
+ x = modulo(x, 360);
+ if (x % 30 === 0) {
+ switch ((x < 0) ? x + 360 : x) {
+ case 0: return 1;
+ case 60: return .5;
+ case 90: return 0;
+ case 120: return -.5;
+ case 180: return -1;
+ case 240: return -.5;
+ case 270: return 0;
+ case 300: return .5;
+ }
+ }
+ return Math.cos(x / 180 * Math.PI);
+ }),
+ sind: wrapraw('sind',
+ ["sind(degrees) Trigonometric sine, in degrees. " +
+ "see sind 45 "],
+ function sind(x) {
+ x = modulo(x, 360);
+ if (x % 30 === 0) {
+ switch ((x < 0) ? x + 360 : x) {
+ case 0: return 0;
+ case 30: return .5;
+ case 90: return 1;
+ case 150: return .5;
+ case 180: return 0;
+ case 210: return -.5;
+ case 270: return -1;
+ case 330: return -.5;
+ }
+ }
+ return Math.sin(x / 180 * Math.PI);
+ }),
+ tand: wrapraw('tand',
+ ["tand(degrees) Trigonometric tangent, in degrees. " +
+ "see tand 45 "],
+ function tand(x) {
+ x = modulo(x, 360);
+ if (x % 45 === 0) {
+ switch ((x < 0) ? x + 360 : x) {
+ case 0: return 0;
+ case 45: return 1;
+ case 90: return Infinity;
+ case 135: return -1;
+ case 180: return 0;
+ case 225: return 1;
+ case 270: return -Infinity;
+ case 315: return -1
+ }
+ }
+ return Math.tan(x / 180 * Math.PI);
+ }),
ceil: wrapraw('ceil',
["ceil(x) Round up. " +
"see ceil 1.9 "], Math.ceil),
@@ -8328,14 +8487,12 @@ var colors = [
$.turtle = function turtle(id, options) {
var exportedsee = false;
- if (!arguments.length) {
- id = 'turtle';
- }
if (arguments.length == 1 && typeof(id) == 'object' && id &&
!id.hasOwnProperty('length')) {
options = id;
id = 'turtle';
}
+ id = id || 'turtle';
options = options || {};
if ('turtle' in options) {
id = options.turtle;
@@ -8358,15 +8515,15 @@ $.turtle = function turtle(id, options) {
parseFloat(options.hangtime) : 20000;
// Set up global events.
- if (!('events' in options) || options.events) {
+ if (options.events !== false) {
turtleevents(options.eventprefix);
}
- if (!('pressed' in options) || options.pressed) {
+ if (options.pressed !== false) {
addKeyEventHooks();
pressedKey.enable(true);
}
// Set up global log function.
- if (!('see' in options) || options.see) {
+ if (options.see !== false) {
exportsee();
exportedsee = true;
if (global.addEventListener) {
@@ -8375,10 +8532,16 @@ $.turtle = function turtle(id, options) {
global.onerror = see;
}
// Set up an alias.
- global.log = see;
+ global.debug = see;
+ // 'debug' should be used now instead of log
+ deprecate(global, 'log', 'debug');
}
+ if (options.queuehide !== false) {
+ queueShowHideToggle();
+ }
+
// Copy $.turtle.* functions into global namespace.
- if (!('functions' in options) || options.functions) {
+ if (options.functions !== false) {
global.printpage = global.print;
$.extend(global, dollar_turtle_methods);
}
@@ -8405,11 +8568,11 @@ $.turtle = function turtle(id, options) {
}
if (selector && !selector.length) { selector = null; }
// Globalize selected jQuery methods of a singleton turtle.
- if (selector && selector.length === 1 &&
- (!('global' in options) || options.global)) {
+ if (selector && selector.length === 1 && (options.global !== false)) {
var extraturtlefn = {
css:1, fadeIn:1, fadeOut:1, fadeTo:1, fadeToggle:1,
- animate:1, toggle:1, finish:1, promise:1, direct:1 };
+ animate:1, toggle:1, finish:1, promise:1, direct:1,
+ show:1, hide:1 };
var globalfn = $.extend({}, turtlefn, extraturtlefn);
global_turtle_methods.push.apply(global_turtle_methods,
globalizeMethods(selector, globalfn));
@@ -8418,14 +8581,14 @@ $.turtle = function turtle(id, options) {
selector.css({zIndex: 1});
}
// Set up global objects by id.
- if (!('ids' in options) || options.ids) {
+ if (options.ids !== false) {
turtleids(options.idprefix);
if (selector && id) {
global[id] = selector;
}
}
// Set up test console.
- if (!('panel' in options) || options.panel) {
+ if (options.panel !== false) {
var seeopt = {
title: 'test panel (type help for help)',
abbreviate: [undefined, helpok],
@@ -8439,12 +8602,6 @@ $.turtle = function turtle(id, options) {
seeopt.height = options.panelheight;
}
see.init(seeopt);
- if (wrotebody) {
- /*
- see.html('Turtle script should be inside body ' +
- '- wrote a <body> ');
- */
- }
// Return an eval loop hook string if 'see' is exported.
if (exportedsee) {
if (global.CoffeeScript) {
@@ -8454,9 +8611,11 @@ $.turtle = function turtle(id, options) {
}
}
}
+ return $('#' + id);
};
$.extend($.turtle, dollar_turtle_methods);
+$.turtle.colors = colors;
function seehelphook(text, result) {
// Also, check the command to look for (non-CoffeeScript) help requests.
@@ -8885,7 +9044,7 @@ function nameToImg(name, defaultshape) {
// Deal with unquoted "tan" and "dot".
name = name.helpname || name.name;
}
- if (name.constructor === $) {
+ if (name.constructor === jQuery) {
// Unwrap jquery objects.
if (!name.length) { return null; }
name = name.get(0);
@@ -8916,6 +9075,10 @@ function nameToImg(name, defaultshape) {
if (shape) {
return shape(color);
}
+ // Default to '/img/' URLs if it doesn't match a well-known name.
+ if (!/\//.test(name)) {
+ name = imgUrl(name);
+ }
// Parse URLs.
if (/\//.test(name)) {
var hostname = absoluteUrlObject(name).hostname;
@@ -8959,11 +9122,11 @@ function hatchone(name, container, defaultshape) {
// Create an image element with the requested name.
var result;
- if (img) {
+ if (isTag) {
+ result = $(name);
+ } else if (img) {
result = $('');
applyImg(result, img);
- } else if (isTag) {
- result = $(name);
} else {
result = $('' + escapeHtml(name) + '
');
}
@@ -9181,13 +9344,12 @@ function turtleevents(prefix) {
if (prefix || prefix === '') {
eventsaver = (function(e) {
// Keep the old instance if possible.
- var names = [prefix + e.type], j, old, name, prop;
+ var names = [prefix + e.type], j;
if ((e.originalEvent || e) instanceof MouseEvent) {
names.push(prefix + 'mouse');
}
for (j = 0; j < names.length; ++j) {
- var name = names[j];
- old = global[name], prop;
+ var name = names[j], old = global[name], prop;
if (old && old.__proto__ === e.__proto__) {
for (prop in old) { if (old.hasOwnProperty(prop)) delete old[prop]; }
for (prop in e) { if (e.hasOwnProperty(prop)) old[prop] = e[prop]; }
@@ -9289,8 +9451,8 @@ function plainBoxPrint(clr, text) {
maxWidth: '1.2em',
overflow: 'hidden'
}).appendTo(getTrailingPre()), finish = function() {
- if (clr) { elem.css({background: clr}); }
- if (text) { elem.text(text); }
+ if (clr != null) { elem.css({background: clr}); }
+ if (text != null) { elem.text(text); }
};
if (!global_turtle) {
finish();
@@ -9320,6 +9482,8 @@ function prepareOutput(html, tag) {
if (html === undefined || html === null) {
// Make empty line when no arguments.
return {result: $(prefix + ' ' + suffix)};
+ } else if (html.jquery || (html instanceof Element && (html = $(html)))) {
+ return {result: html};
} else {
var wrapped = false, result = null;
html = '' + html;
@@ -9497,18 +9661,25 @@ function prepareButton(name, callback) {
// for creating an input box with a label, for one-shot input
//////////////////////////////////////////////////////////////////////////
+var microphoneSvg = "data:image/svg+xml, "
+
// Simplify $('body').append(' ' + label) and onchange hookup.
-function prepareInput(name, callback, numeric) {
+// Type can be 'auto', 'number', 'text', or 'voice' for slightly
+// different interfaces.
+function prepareInput(name, callback, type) {
if ($.isFunction(name) && !callback) {
callback = name;
name = null;
}
+ if (!type) { type = 'auto'; }
name = $.isNumeric(name) || name ? name : '⇒';
var textbox = $(' ').css({margin:0, padding:0}),
+ button = $('Submit ').css({marginLeft:4}),
label = $('' + name + ' ' +
- ' ').append(textbox),
+ '').append(textbox).append(button),
debounce = null,
- lastseen = textbox.val();
+ lastseen = textbox.val(),
+ recognition = null;
function dodebounce() {
if (!debounce) {
debounce = setTimeout(function() { debounce = null; }, 1000);
@@ -9521,16 +9692,17 @@ function prepareInput(name, callback, numeric) {
dodebounce();
lastseen = val;
textbox.remove();
+ button.remove();
label.append(val).css({display: 'table'});
- if (numeric > 0 || (
- numeric >= 0 && $.isNumeric(val) && ('' + parseFloat(val) == val))) {
+ if (type == 'number' || (type == 'auto' &&
+ $.isNumeric(val) && ('' + parseFloat(val) == val))) {
val = parseFloat(val);
}
label.prop('value', val);
if (callback) { setTimeout(function() {callback.call(label, val); }, 0); }
}
function validate() {
- if (numeric <= 0) return true;
+ if (type != 'numeric') return true;
var val = textbox.val(),
nval = val.replace(/[^0-9\.]/g, '');
if (val != nval || !$.isNumeric(nval)) {
@@ -9544,19 +9716,23 @@ function prepareInput(name, callback, numeric) {
if (!validate()) { return false; }
newval();
}
- if (numeric > 0 && (e.which >= 32 && e.which <= 127) &&
+ if (type == 'voice' && recognition) {
+ recognition.abort();
+ recognition = null;
+ }
+ if (type == 'numeric' && (e.which >= 32 && e.which <= 127) &&
(e.which < '0'.charCodeAt(0) || e.which > '9'.charCodeAt(0)) &&
(e.which != '.'.charCodeAt(0) || ~textbox.val().indexOf('.'))) {
return false;
}
}
textbox.on('keypress keydown', key);
- textbox.on('change', newval);
+ button.on('click', newval);
return {
result: label,
setup: function() {
dodebounce();
- if (numeric < 0) {
+ if (type == 'text' || type == 'voice') {
// Widen a "readstr" textbox to make it fill the line.
var availwidth = label.parent().width(),
freewidth = availwidth + label.offset().left - textbox.offset().left,
@@ -9565,6 +9741,48 @@ function prepareInput(name, callback, numeric) {
marginwidth = textbox.outerWidth(true) - textbox.width();
textbox.width(desiredwidth - marginwidth);
}
+ if (type == 'number') {
+ textbox.attr('type', 'number');
+ }
+ if (type == 'voice') {
+ button.css({display: 'none'});
+ var SR = global.SpeechRecognition || global.webkitSpeechRecognition;
+ if ('function' == typeof(SR)) {
+ try {
+ recognition = new SR();
+ recognition.continuous = false;
+ recognition.interimResults = true;
+ textbox.css({backgroundColor: 'lightyellow',
+ color: 'gray',
+ backgroundImage: "url(" + microphoneSvg + ")",
+ backgroundRepeat: 'no-repeat',
+ backgroundPosition: 'center'});
+ recognition.onspeechstart = function() {
+ textbox.css({background: 'lightgreen'});
+ };
+ recognition.onend = function() {
+ textbox.css({color: '', backgroundColor: '', backgroundImage: '',
+ backgroundRepeat: '', backgroundPosition: ''});
+ textbox.val(lastseen);
+ newval();
+ };
+ recognition.onresult = function(event) {
+ var text = event.results[0][0].transcript;
+ var confidence = event.results[0][0].confidence;
+ var shade = 128 - 128 * confidence;
+ if (event.results[0].isFinal) {
+ shade = 0;
+ lastseen = text;
+ }
+ textbox.css({color: componentColor('rgb', shade, shade, shade)});
+ textbox.val(text);
+ };
+ recognition.start();
+ } catch (e) {
+ console.log(e);
+ }
+ }
+ }
// Focus, but don't cause autoscroll to occur due to focus.
undoScrollAfter(function() { textbox.focus(); });
}
@@ -9662,57 +9880,54 @@ function componentColor(t, args) {
return t + '(' + Array.prototype.join.call(args, ',') + ')';
}
-function autoArgs(arguments, start, map) {
+function autoArgs(args, start, map) {
var j = 0;
var taken = [];
var result = {};
for (var key in map) {
var pattern = map[key];
- for (j = start; j < arguments.length; ++j) {
+ for (j = start; j < args.length; ++j) {
if (~taken.indexOf(j)) continue;
if (pattern == '*') {
break;
- } else if (pattern instanceof RegExp && pattern.test(arguments[j])) {
+ } else if (pattern instanceof RegExp && pattern.test(args[j])) {
break;
- } else if (pattern instanceof Function && pattern(arguments[j])) {
+ } else if (pattern instanceof Function && pattern(args[j])) {
break;
- } else if (pattern == typeof arguments[j]) {
+ } else if (pattern == typeof args[j]) {
break;
}
}
- if (j < arguments.length) {
+ if (j < args.length) {
taken.push(j);
- result[key] = arguments[j];
+ result[key] = args[j];
}
}
- if (taken.length + start < arguments.length) {
+ if (taken.length + start < args.length) {
var extra = [];
- for (j = start; j < arguments.length; ++j) {
+ for (j = start; j < args.length; ++j) {
if (~taken.indexOf(j)) continue;
- extra.push(arguments[j]);
+ extra.push(args[j]);
}
result.extra = extra;
}
return result;
}
+
//////////////////////////////////////////////////////////////////////////
// DEBUGGING SUPPORT
//////////////////////////////////////////////////////////////////////////
var debug = {
init: function initdebug() {
+ if (this.ide) return; // Don't re-initialize debug.
try {
- if (parent && parent.ide) {
- if (this.ide !== parent.ide) {
- this.ide = parent.ide;
- this.ide.bindframe(global);
- }
+ if (parent && parent.ide && parent.ide.bindframe &&
+ parent.ide.bindframe(global, parent)) {
+ this.ide = parent.ide;
this.attached = true;
}
- } catch(e) {
- this.ide = null;
- this.attached = false;
- }
+ } catch(e) { }
if (this.attached) {
if (global.addEventListener) {
global.addEventListener('error', function(event) {
@@ -9810,7 +10025,7 @@ debug.init();
c = cnv.getContext('2d'),
relative = false,
p = lineend || e,
- s, html, dx, dy, dd, dir, ang;
+ html, dx, dy, dd, dir, ang;
if (linestart && 'function' == typeof(linestart.pagexy)) {
var xy = linestart.getxy(), s = linestart.pagexy();
s.x = xy[0];
@@ -10198,7 +10413,8 @@ function isprimitive(vt) {
}
function isdom(obj) {
- return (obj.nodeType && obj.nodeName && typeof(obj.cloneNode) == 'function');
+ return (obj && obj.nodeType && obj.nodeName &&
+ typeof(obj.cloneNode) == 'function');
}
function midtruncate(s, maxlen) {
@@ -10536,7 +10752,6 @@ function aselement(s, def) {
default:
return s;
}
- return null;
}
function stickscroll() {
var stick = false, a = aselement(autoscroll, null);
@@ -10669,6 +10884,11 @@ function initconsolelog() {
_log.apply(this, arguments);
see.apply(this, arguments);
}
+ var _debug = global.console._debug = global.console.debug;
+ global.console.debug = function debug() {
+ _debug.apply(this, arguments);
+ see.apply(this, arguments);
+ }
}
} catch(e) { }
}
diff --git a/jquery-turtle.min.js b/jquery-turtle.min.js
new file mode 100644
index 0000000..387546f
--- /dev/null
+++ b/jquery-turtle.min.js
@@ -0,0 +1,5 @@
+(function(a){function b(b,c){if(Ne>5)Oe.push({elem:b,qname:c});else{for(Ne+=1,a.dequeue(b,c);Oe.length>0;){var d=Oe.shift();a.dequeue(d.elem,d.qname),Vc()}Ne-=1}}function c(a,b){function c(){this.constructor=a}for(var d in b)Je.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a}function d(b){var c,d,e=b.charAt(0).toUpperCase()+b.slice(1),f=["Moz","Webkit","O","ms"],g=document.createElement("div");if(b in g.style)d=b;else for(var h=0;h<0?'"'+a+'"':"'"+a+"'":a}var c=[];for(var d in a)a.hasOwnProperty(d)&&c.push(d+":"+b(a[d])+";");return c.join(" ")}function h(a){return a}function i(a,b){var c=[a[0]*b[0]+a[2]*b[1],a[1]*b[0]+a[3]*b[1]];return 6==a.length&&(c[0]+=a[4],c[1]+=a[5]),c}function j(a,b){var c=[a[0]*b[0]+a[2]*b[1],a[1]*b[0]+a[3]*b[1],a[0]*b[2]+a[2]*b[3],a[1]*b[2]+a[3]*b[3]],d=6==a.length;return 6==b.length?(c.push(a[0]*b[4]+a[2]*b[5]+(d?a[4]:0)),c.push(a[1]*b[4]+a[3]*b[5]+(d?a[5]:0))):d&&(c.push(a[4]),c.push(a[5])),c}function k(a){return Math.abs(a)>1e-12}function l(a){return!(k(a[1])||k(a[2])||k(1-a[0])||k(1-a[3]))}function m(a){if(l(a))return[1,0,0,1];var b=u(a);return k(b[2])?j(o(-b[3]),j(p(1/b[1],1/b[2]),o(-b[0]))):null}function n(a){var b=m(a);if(4==a.length)return b;var c=i(b,[-a[4],-a[5]]);return b.push(c[0]),b.push(c[1]),b}function o(a){var b=Math.cos(a),c=Math.sin(a);return[b,c,-c,b]}function p(a,b){return 1==arguments.length&&(a=b),[a,0,0,b]}function q(a,b){return[a[0]+b[0],a[1]+b[1]]}function r(a,b){return[a[0]-b[0],a[1]-b[1]]}function s(a,b){return[a[0]*b,a[1]*b]}function t(a,b,c){return q(i(a,r(b,c)),c)}function u(a){var b,c,d=a[0]*a[0]+a[1]*a[1],e=a[0]*a[2]+a[1]*a[3],f=a[2]*a[2]+a[3]*a[3],g=-.5*Math.atan2(2*e,d-f),h=Math.cos(g),i=Math.sin(g),j=a[0]*h-a[2]*i,k=a[1]*h-a[3]*i,l=Math.atan2(k,j),m=Math.cos(l),n=Math.sin(l),o=(a[1]*i+a[3]*h)*m-(a[0]*i+a[2]*h)*n,p=(a[0]*h-a[2]*i)*m+(a[1]*h-a[3]*i)*n;return g<-Math.PI/4?(g+=Math.PI/2,c=p,b=o,l-=Math.PI/2):(b=p,c=o),l>Math.PI&&(l-=2*Math.PI),[l,b,c,g]}function v(a,b){var c=(b-a)/2,d=Math.cos(c),e=Math.sin(c),f=d,g=-e,h=1+f*d+g*e,i=f*e-g*d,j=i&&4/3*(Math.sqrt(2*h)-h)/i,k=f-j*g,l=g+j*f,m=k,n=-l,o=c+a,p=Math.cos(o),q=Math.sin(o);return[[k*p-l*q,k*q+l*p],[m*p-n*q,m*q+n*p],[Math.cos(b),Math.sin(b)]]}function w(a){var b=ra(a,!1);if(b)return[b.tx,b.ty];var c=x(a);return c?[c[4],c[5]]:[0,0]}function x(b){var c=Ie.getComputedStyle?Ie.getComputedStyle(b)[Pe]:a.css(b,"transform");if(!c||"none"===c)return null;var d=/^matrix\(([\-+.\de]+),\s*([\-+.\de]+),\s*([\-+.\de]+),\s*([\-+.\de]+),\s*([\-+.\de]+)(?:px)?,\s*([\-+.\de]+)(?:px)?\)$/.exec(c);return d?[parseFloat(d[1]),parseFloat(d[2]),parseFloat(d[3]),parseFloat(d[4]),parseFloat(d[5]),parseFloat(d[6])]:A(c)}function y(b,c){var d,e,f,g="none"===a.css(b,"display");if(g){d={position:"absolute",visibility:"hidden",display:"block"},e={};for(f in d)e[f]=b.style[f],b.style[f]=d[f]}var h=Ie.getComputedStyle?Ie.getComputedStyle(b):null;if(g)for(f in d)b.style[f]=e[f];var i=h&&h[Qe]||a.css(b,"transformOrigin");if(i&&i.indexOf("%")<0)return a.map(i.split(" "),parseFloat);if(c)return[c[0]/2,c[1]/2];var j=a(b);return[j.width()/2,j.height()/2]}function z(a){for(var b,c=[1,0,0,1];null!==a;)b=x(a),b&&!l(b)&&(c=j(b,c)),a=a.parentElement;return c.slice(0,4)}function A(b){var c=[1,0,0,1],d=[],e=[],f=/(?:^\s*|)(\w*)\s*\(([^)]*)\)\s*/g,g=b.replace(f,function(b){return d.push(b[1].toLowerCase()),e.push(a.map(b[2].split(","),function(a){var b=a.trim().toLowerCase();return{num:parseFloat(b),unit:b.replace(/^[+-.\de]*/,"")}})),""});if(g)return null;for(var h=d.length-1;h>=0;--h){var i,k,l,m=null,n=d[h],o=e[h];if("matrix"==n)o.length>=6&&(m=[o[0].num,o[1].num,o[2].num,o[3].num,o[4].num,o[5].num]);else if("rotate"==n)1==o.length&&(i=wa(o[0]),k=Math.cos(i),l=Math.sin(i),m=[k,-l,k,l]);else if("translate"==n||"translatex"==n||"translatey"==n){var p=0,q=0;if(o.length>=1){if(o[0].unit&&"px"!=o[0].unit)return null;if("translate"==n||"translatex"==n?p=o[0].num:"translatey"==n&&(q=o[0].num),"translate"==n&&o.length>=2){if(o[1].unit&&"px"!=o[1].unit)return null;q=o[1].num}m=[0,0,0,0,p,q]}}else if("scale"==n||"scalex"==n||"scaley"==n){var r=1,s=1;o.length>=1&&("scale"==n||"scalex"==n?r=o[0].num:"scaley"==n&&(s=o[0].num),"scale"==n&&o.length>=2&&(s=o[1].num),m=[r,0,0,s,0,0])}else{if("skew"!=n&&"skewx"!=n&&"skewy"!=n)return null;var t=0,u=0;o.length>=1&&("skew"==n||"skewx"==n?t=Math.tan(wa(o[0])):"skewy"==n&&(u=Math.tan(wa(o[0]))),"skew"==n&&o.length>=2&&(u=Math.tan(wa(o[0]))),m=[1,u,t,1,0,0])}c=j(c,m)}return c}function B(a,b,c){if(0>=c)return a;var d=b.pageX-a.pageX,e=b.pageY-a.pageY,f=d*d+e*e;if(c*c>=f)return b;var g=c/Math.sqrt(f);return{pageX:a.pageX+g*d,pageY:a.pageY+g*e}}function C(a,b,c){if(0>=c)b=a;else if(180>c){var d=xa(b-a);d>c?b=a+c:-c>d&&(b=a-c)}return xa(b)}function D(a,b,c,d){return{pageX:Math.floor(a+c/2),pageY:Math.floor(b+d/2)}}function E(a,b,c,d){var e=a+c,f=b+d;return[{pageX:a,pageY:b},{pageX:a,pageY:f},{pageX:e,pageY:f},{pageX:e,pageY:b}]}function F(a){if(!/e[\-+]/.exec(a))return a;var b=a.replace(/(?:\d+(?:\.\d*)?|\.\d+)e[\-+]\d+/g,function(a){return sa(parseFloat(a))});return b}function G(b,c,d){var e=a.data(b,"turtleData");if(e&&e.quickhomeorigin&&e.down&&e.style&&!d&&b.classList&&b.classList.contains("turtle"))return e.quickhomeorigin;var f,g,h,i="none"===a.css(b,"display"),j=i?{position:"absolute",visibility:"hidden",display:"block"}:{},k=(j[Pe]=c?"matrix("+a.map(c,sa).join(", ")+", 0, 0)":"none",{});for(f in j)k[f]=b.style[f],b.style[f]=j[f];g=N(b),h=y(b,[g.width,g.height]);for(f in j)b.style[f]=F(k[f]);d&&(d.gbcr=g,d.localorigin=h);var l=q([g.left,g.top],h);return e&&e.down&&e.style&&(e.quickhomeorigin=l),l}function H(){return Ie.innerHeight||a(Ie).height()}function I(){return Ie.innerWidth||a(Ie).width()}function J(){return document.body?a(document).height():document.height}function K(){return document.body?a(document).width():document.width}function L(a){return a.offsetHeight<=0&&a.offsetWidth<=0}function M(a,b,c,d){return{left:a,top:b,right:a+c,bottom:b+d,width:c,height:d}}function N(b){return mb(b)?M(b.pageX,b.pageY,0,0):a.isWindow(b)?M(a(Ie).scrollLeft(),a(Ie).scrollTop(),I(),H()):9===b.nodeType?M(0,0,K(),J()):"getBoundingClientRect"in b?T.apply(b):M(0,0,0,0)}function O(a,b,c){var d=Math.max(0,Math.max(c.top-a.pageY,a.pageY-c.bottom)),e=Math.max(0,Math.max(c.left-a.pageX,a.pageX-c.right));return e*e+d*d>b}function P(a,b,c){var d=Math.max(c.bottom-a.pageY,a.pageY-c.top),e=Math.max(c.right-a.pageX,a.pageX-c.left);return b>e*e+d*d}function Q(a,b){return b.right=a.top&&b.bottom<=a.bottom&&b.left>=a.left&&b.right<=a.right}function S(a,b){return 4===a.length&&a[0].pageX===b.left&&a[0].pageY===b.top&&a[1].pageX===b.left&&a[1].pageY===b.bottom&&a[2].pageX===b.right&&a[2].pageY===b.bottom&&a[3].pageX===b.right&&a[3].pageY===b.top}function T(){var a=this.getBoundingClientRect();return{top:a.top+Ie.pageYOffset,bottom:a.bottom+Ie.pageYOffset,left:a.left+Ie.pageXOffset,right:a.right+Ie.pageXOffset,width:a.width,height:a.height}}function U(b,c,d,e,f){var g,h,j,k,l=z(b.parentElement),n=m(l),o=G(b,n);if(n){if(a.isNumeric(d)&&(j=w(b),g=q(i(l,j),o),h={pageX:g[0],pageY:g[1]},c=B(h,c,d)),k=i(n,r([c.pageX,c.pageY],o)),e||f){var p=Gc(b);k[0]+=e*p,k[1]-=f*p}return sa(k[0])+" "+sa(k[1])}}function V(a){var b=a.offsetParent;return b?b:document}function W(b,c){c||(c=a(V(b)).pagexy());var d=z(b.parentElement),e=m(d),f=G(b,e),g=ra(b,!0),h=e&&i(e,r([c.pageX,c.pageY],f)),j=1/Gc(b);if(e)return[(g.tx-h[0])*j,(h[1]-g.ty)*j]}function X(b,c){var d,e,f=z(b.parentElement),g=(ra(b,!0),a(V(b)).pagexy()),h=Gc(b),j=[];for(e=0;ei-f&&(d=i-f),f>d&&(d=f),e>j-g&&(e=j-g),g>e&&(e=g);var l={pageX:d,pageY:e};a.isNumeric(c)&&(l=B(k.origin(),l,c)),k.scrollLeft(l.pageX-f),k.scrollTop(l.pageY-g)}function ca(a,b,c){var d=b.pageX-a.pageX,e=b.pageY-a.pageY,f=c.pageX-a.pageX,g=c.pageY-a.pageY;return f*e-d*g}function da(a,b,c){var d=c.pageX-a.pageX,e=c.pageY-a.pageY;return d*b.pageY-b.pageX*e}function ea(a,b){if(b.length<=0)return!1;if(1==b.length)return b[0].pageX==a.pageX&&b[0].pageY==a.pageY;var c=ca(a,b[b.length-1],b[0]);if(0===c)return!0;var d=c>0;if(2==b.length)return!1;for(var e=1;e0!=d)return!1}return!0}function fa(a,b){return{pageX:a.pageX-b.pageX,pageY:a.pageY-b.pageY}}function ga(a,b,c,d){var e,f,g=fa(c,b);for(e=0;e0?1:0>a?-1:0}function ia(a){if(a.length<=2)return 0;var b=ca(a[a.length-1],a[0],a[1]);if(0!==b)return ha(b);for(var c=1;c1&&1!=ha(ca(a[a.length-2],a[a.length-1],b));)a.pop();return a.length&&d(a[a.length-1],b)||a.push(b),a}function c(a,b,c){for(var d=0;db.pageX?1:a.pageYb.pageY?1:0}a.sort(e);var f=c(a,[],b),g=c(a.reverse(),[],b);return f.concat(g.slice(1,-1))}function ma(b){if(!b)return null;if(a.isArray(b))return b;for(var c=a.map(b.trim().split(/\s+/),parseFloat),d=[],e=0;e+1180&&(b-=360),b}function wa(a){return a/180*Math.PI}function xa(a){return Math.abs(a)>180&&(a%=360,a>180?a-=360:-180>=a&&(a+=360)),a}function ya(a){return Math.abs(a)>=720&&(a=a%360+(a>0?360:-360)),a}function za(){return Re.field||Ba(),Re.field}function Aa(){return Re.surface||Ba(),Re.surface}function Ba(){var b=document.createElement("samp"),c=document.createElement("samp"),d=Math.floor(I()/2),e=Math.floor(H()/2);a(b).css({position:"absolute",display:"inline-block",top:0,left:0,width:"100%",height:"100%",font:"inherit",zIndex:-1,transformOrigin:d+"px "+e+"px",pointerEvents:"none",overflow:"hidden"}).addClass("turtlefield"),a(c).attr("id","origin").css({position:"absolute",display:"inline-block",top:e,left:d,width:"100%",height:"0",font:"inherit",transformOrigin:"0px 0px",pointerEvents:"all",turtleSpeed:1/0}).appendTo(b),Re.surface=b,Re.field=c,Ca(),Sb()}function Ca(){document.body?(null==a("html").attr("style")&&a("html").css("min-height","100%"),a(Re.surface).prependTo("body"),Rb()):a(document).ready(Ca)}function Da(a){return a.drawOnCanvas||(a.drawOnCanvas=Fa()),a.drawOnCanvas}function Ea(b){var c=a.data(b,"turtleData");return c?c.drawOnCanvas?c.drawOnCanvas:Re.canvas:null}function Fa(){if(Re.canvas)return Re.canvas;var b=Aa();return Re.canvas=document.createElement("canvas"),a(Re.canvas).css({"z-index":-1}),b.insertBefore(Re.canvas,b.firstChild),Ja(),Ha(Ja),a(Ie).resize(Ja),Re.canvas}function Ga(a,b){return Re.offscreen&&Re.offscreen.width===a&&Re.offscreen.height===b?(Re.offscreen.getContext("2d").clearRect(0,0,a,b),Re.offscreen):(Re.offscreen||(Re.offscreen=document.createElement("canvas")),Re.offscreen.width=a,Re.offscreen.height=b,Re.offscreen)}function Ha(b){var c=a("body"),d=c.width(),e=c.height(),f=function(){(c.width()!=d||c.height()!=e)&&(b(),d=c.width(),e=c.height())};Re.timer&&clearInterval(Re.timer),Re.timer=setInterval(f,250)}function Ia(){var b=a("body");return[Math.max(b.outerWidth(!0),Ie.innerWidth||a(Ie).width()),Math.max(b.outerHeight(!0),Ie.innerHeight||a(Ie).height())]}function Ja(){if(Re.canvas){var b,c=Ia(),d=c[0],e=c[1],f=Re.canvas.width,g=Re.canvas.height,h=Math.max(Math.min(2e3,Math.max(200,f)),100*Math.ceil(d/100))*Re.subpixel,i=Math.max(Math.min(2e3,Math.max(200,f)),100*Math.ceil(e/100))*Re.subpixel;a(Re.surface).css({width:d+"px",height:e+"px"}),(f!=h||g!=i)&&(b=document.createElement("canvas"),b.width=Math.min(f,h),b.height=Math.min(g,i),b.getContext("2d").drawImage(Re.canvas,0,0),Re.canvas.width=h,Re.canvas.height=i,Re.canvas.getContext("2d").drawImage(b,0,0),a(Re.canvas).css({width:h/Re.subpixel,height:i/Re.subpixel}))}}function Ka(a,b){if(!a)return null;if(a&&"function"==typeof a&&(a.helpname||a.name)&&(a=a.helpname||a.name),a=String(a),a.trim&&(a=a.trim()),!a||"none"===a)return null;if("path"===a||"fill"===a)return{savePath:!0};var c=!1;/^erase\b/.test(a)&&(a=a.replace(/^erase\b/,"white; globalCompositeOperation:destination-out"),c=!0);var d=f(a,b);return c&&(d.eraseMode=!0),d}function La(a){return a?g(a):"none"}function Ma(a){return"down"==a||a===!0?!0:"up"==a||a===!1?!1:He}function Na(a){return a?"down":"up"}function Oa(b){var c=a.data(b,"turtleData");return c||(c=a.data(b,"turtleData",{style:null,corners:[[]],path:[[]],down:!1,speed:"turtle",easing:"swing",turningRadius:0,drawOnCanvas:null,quickpagexy:null,quickhomeorigin:null,oldscale:1,instrument:null,stream:null})),c}function Pa(b){var c=a.data(b,"turtleData");return c?c.turningRadius:0}function Qa(){return{get:function(a,b,c){return sa(Pa(a))+"px"},set:function(a,b){var c=parseFloat(b);if(!isNaN(c)&&(Oa(a).turningRadius=c,a.style.turtleTurningRadius=""+sa(c)+"px",0===c)){var d=ra(a,!1);d&&(d.rot>180||d.rot<=-180)&&(d.rot=xa(d.rot),a.style[Pe]=ta(d))}}}}function Ra(){return{get:function(a,b,c){return La(Oa(a).style)},set:function(a,b){var c=Ka(b,"strokeStyle"),d=Oa(a);d.style&&(d.style=null,bb(a,d,!0)),d.style=c,a.style.turtlePenStyle=La(c),bb(a,d,!0)}}}function Sa(){return{get:function(a,b,c){return Na(Oa(a).down)},set:function(a,b){var c=Ma(b);if(c!==He){var d=Oa(a);c!=d.down&&(d.down=c,d.quickpagexy=null,d.quickhomeorigin=null,a.style.turtlePenDown=Na(c),bb(a,d,!0))}}}}function Ta(a,b){return 0===Math.round(a.pageX-b.pageX)&&0===Math.round(a.pageY-b.pageY)}function Ua(a,b){return 0===Math.round(1e3*(a.pageX-b.pageX))&&0===Math.round(1e3*(a.pageY-b.pageY))}function Va(a,b){return Ta(a,b)&&0===Math.round(a.pageX-b.pageX1)&&0===Math.round(a.pageY-b.pageY1)&&0===Math.round(b.pageX2-b.pageX)&&0===Math.round(b.pageY2-b.pageY)}function Wa(a){var b=1e3*a,c=Math.round(b);return Math.abs(c-b) 1){h=b[j],f=h.length>2&&Ta(h[0],h[h.length-1])&&!Ta(h[0],h[Math.floor(h.length/2)]),g=f&&!("pageX2"in h[h.length-1]);var k=h[0].pageX,l=h[0].pageY;i.moveTo(k,l);for(var m=1;m1&&(d.length=1),d[0].length&&(d[0].length=0),void(c&&(e?f.length&&f[0].length&&(1==f[0].length?f[0].length=0:f.unshift([])):(f.length>1&&(f.length=1),f[0].length&&(f[0].length=0))));if(c||!e.savePath){var g=Y(a);if(c&&(g.corner=!0,ab(f[0],g)),!e.savePath){ab(d[0],g);var h=Kc(a);$a(Da(b),b.path,e,h,2)}}}}function cb(b,c){var d=Oa(b);d.style&&(c=a.extend({},d.style,c));var e=Kc(b);$a(Da(d),d.corners,c,e,1)}function db(b){if((!b||/\bcanvas\b/.test(b))&&Re.canvas){var c=Re.canvas.getContext("2d");c.save(),c.setTransform(1,0,0,1,0,0),c.clearRect(0,0,Re.canvas.width,Re.canvas.height),c.restore()}if((!b||/\bturtles\b/.test(b))&&Re.surface){var d=a(Re.surface).find(".turtle").not(".turtlefield");pf&&(d=d.not(pf)),d.remove()}if((!b||/\blabels\b/.test(b))&&Re.surface){var d=a(Re.surface).find(".turtlelabel").not(".turtlefield");d.remove()}(!b||/\btext\b/.test(b))&&a("body").contents().not(".turtlefield").remove()}function eb(a,b){if(!a||a.length<1)return null;for(var c=1,d={left:Math.floor(a[0].pageX),top:Math.floor(a[0].pageY),right:Math.ceil(a[0].pageX),bottom:Math.ceil(a[0].pageY)};c=c[3]/2)return!0}else{var o=!c;for(m=0;m0==o)return!0}return!1}function hb(a,b,c){if(b.img)("CANVAS"==a[0].tagName||a[0].tagName==b.img.tagName)&&Kb(b.img,a[0],b.css);else if("IMG"==a[0].tagName||"CANVAS"==a[0].tagName)Hb(a[0],b.url,b.css,c),c=null;else{var d={backgroundImage:"url("+b.url+")",backgroundRepeat:"no-repeat",backgroundPosition:"center"};b.css.width&&b.css.height&&(d.backgroundSize=b.css.width+"px "+b.css.height+"px"),a.css(d)}c&&c()}function ib(b,c,d){var e,f=ra(b,!0),g=f&&wa(f.rot),h=Gc(b),i=f&&c*h,j=f&&(d||0)*h,k=-Math.cos(g)*i,l=Math.sin(g)*i,m=a.data(b,"turtleData");f&&(d&&(k+=Math.sin(g)*j,l+=Math.cos(g)*j),m&&(e=m.quickpagexy)&&(m.quickpagexy={pageX:e.pageX+l,pageY:e.pageY+k}),f.tx+=l,f.ty+=k,b.style[Pe]=ta(f),bb(b,m,!0))}function jb(b,c,d){var e,f=ra(b,!0),g=a.data(b,"turtleData");f&&(g&&(e=g.quickpagexy)&&(g.quickpagexy={pageX:e.pageX+c,pageY:e.pageY-d}),f.tx+=c,f.ty-=d,b.style[Pe]=ta(f),bb(b,g,!0))}function kb(a,b){var c=ra(a,!0);c&&(c.rot+=b,a.style[Pe]=ta(c))}function lb(a,b,c){var d=ra(a,!0);if(d){var e=Gc(a),f=wa(d.rot),g=b*e,h=(c||0)*e,i=-Math.cos(f)*g,j=Math.sin(f)*g;return h&&(i+=Math.sin(f)*h,j+=Math.cos(f)*h),sa(d.tx+j)+" "+sa(d.ty+i)}}function mb(b){return b&&a.isNumeric(b.pageX)&&a.isNumeric(b.pageY)}function nb(){return{get:function(a,b,c){return Oa(a).speed},set:function(b,c){(a.isNumeric(c)&&!(0>=c)||c in a.fx.speeds||""+c=="Infinity")&&(Oa(b).speed=""+c)}}}function ob(){return{get:function(a,b,c){return Oa(a).easing},set:function(b,c){c in a.easing&&(Oa(b).easing=c)}}}function pb(b,c){var d=a.data(b,"turtleData");return c=c||Df,d?a.isNumeric(d.speed)||"Infinity"==d.speed?1e3/d.speed:"turtle"==d.speed&&c?0:d.speed:c?0:"turtle"}function qb(b){var c=a.data(b,"turtleData");return c?c.easing:null}function rb(){return{get:function(a,b,c){var d=ra(a,b),e=y(a);if(d){var f=wa(d.rot),g=Math.cos(f),h=Math.sin(f),i=Gc(a);return sa(((d.tx+e[0])*h-(d.ty+e[1])*g)/i)+"px"}},set:function(b,c){var d,e=ra(b,!0)||{tx:0,ty:0,rot:0,sx:1,sy:1,twi:0},f=y(b),g=Gc(b),h=parseFloat(c)*g,i=wa(e.rot),j=Math.cos(i),k=Math.sin(i),l=(e.tx+f[0])*j+(e.ty+f[1])*k,m=l*j+h*k-f[0],n=l*k-h*j-f[1],o=a.data(b,"turtleData");o&&(d=o.quickpagexy)&&(o.quickpagexy={pageX:d.pageX+(m-e.tx),pageY:d.pageY+(n-e.ty)}),e.tx=m,e.ty=n,b.style[Pe]=ta(e),bb(b,o)}}}function sb(b,c,d,e){return{get:function(a,c,e){var f=ra(a,c);return f?f[b]+d:void 0},set:function(d,f){var g,h=ra(d,!0)||{tx:0,ty:0,rot:0,sx:1,sy:1,twi:0},i={displace:e},j=a.data(d,"turtleData"),k=h.tx,l=h.ty;h[b]=c(f,d,h,i),d.style[Pe]=ta(h),i.displace?(j&&(g=j.quickpagexy)&&(j.quickpagexy={pageX:g.pageX+(h.tx-k),pageY:g.pageY+(h.ty-l)}),bb(d,j)):Z(d)}}}function tb(a,b,c){var d=ya(b-a),e=d>0?c:-c,f=wa(a),g=[Math.cos(f)*e,Math.sin(f)*e],h=wa(b);return{delta:d,sradius:e,dc:g,dx:g[0]-Math.cos(h)*e,dy:g[1]-Math.sin(h)*e}}function ub(a,b,c,d,e,f){var g,h,j,k,l,m,n,o,p,r,t,u=tb(c,d,e),w=u.sradius,x=u.dc;for(n=1,o=u.delta,p=Math.abs(u.delta),p>45&&(n=Math.ceil(p/45),o=u.delta/n),r=[];--n>=0;)g=0===n?d:c+o,h=wa(c+180),j=wa(g+180),r.push.apply(r,v(h,j)),c=g;for(t=[],k=0;k2||(j.length>=1&&(i[c]=parseFloat(j[0])),j.length>=2?i[d]=parseFloat(j[1]):e?i[d]=0:i[d]=i[c],b.style[Pe]=ta(i),e?(k&&(h=k.quickpagexy)&&(k.quickpagexy={pageX:h.pageX+(i.tx-l),pageY:h.pageY+(i.ty-m)}),bb(b,k)):Z(b))}}}function Ab(a){return Se.href=a,Se}function Bb(a){return Ab(a).href}function Cb(a){return/(?:^|\.)pencil(?:code)?\./i.test(a)}function Db(a){var b=Ab(null==a?"":a).hostname,c=/^(\w+)\.pencil(?:code)?\./i.exec(b);return c?c[1]:null}function Eb(a,b){var c=Ab(null==a?"":a),d=c.href;return Cb(c.hostname)?/^\/(?:edit|home|code|load|save)(?:\/|$)/.test(c.pathname)&&(d=c.protocol+"//"+c.host+"/"+b+"/"+c.pathname.replace(/\/[^\/]*(?:\/|$)/,"")+c.search+c.hash):Cb(Ie.location.hostname)&&(d="/proxy/"+d),d}function Fb(a){return/\//.test(a)?a:(a="/img/"+a,Cb(Ie.location.hostname)?a:"//pencilcode.net"+a)}function Gb(){if(!document.cookie)return null;for(var a=document.cookie.split(/;\s*/),b=0;b0&&b.height>0)try{e=c.getContext("2d"),e.clearRect(0,0,b.width,b.height),e.drawImage(b,0,0)}catch(i){}}else c.src=b.src;d&&g.css(d);var j=y(c);if(b&&!d.turtleHull)try{var k=De(b);Ge(k,parseFloat(g.css("width"))/b.width,parseFloat(g.css("height"))/b.height,-j[0],-j[1]),g.css("turtleHull",k)}catch(i){}Lb(c,f,j)}function Lb(b,c,d){var e=a(b);if(e.hasClass("turtle")&&(d[0]!=c[0]||d[1]!=c[1]))if("absolute"==e.css("position")&&/px$/.test(e.css("left"))&&/px$/.test(e.css("top")))e.css("left",parseFloat(e.css("left"))+c[0]-d[0]),e.css("top",parseFloat(e.css("top"))+c[1]-d[1]);else{var f=ra(b,!0);f.tx+=c[0]-d[0],f.ty+=c[1]-d[1],b.style[Pe]=ta(f)}}function Mb(b,c,d,e,f){var g,h,i,j,k;return e===He&&f===He?(g=a(d),g.length?(h=g[0],i=N(h),S(_(h),i)?b.filter(function(){var b=N(this);return c===(R(i,b)||!Q(i,b)&&a(this).inside(h))}):b.filter(function(){return c===a(this).inside(h)})):[]):(j=a.isNumeric(e)&&a.isNumeric(f)?[e,f]:e,a.isArray(j)&&(j=X(b[0]||document.body,[j])[0]),"touch"===d?mb(j)?b.filter(function(){return c===a(this).touches(j)}):(g=a(j),i=N(g[0]),S(_(g[0]),i)?b.filter(function(){var a=N(this);return c===(!Q(i,a)&&(R(i,a)||g.touches(this)))}):b.filter(function(){return c===g.touches(this)})):(k=d*d,b.filter(function(){var a=N(this);if(O(j,k,a))return!c;if(P(j,k,a))return c;var b=Y(this),d=j.pageX-b.pageX,e=j.pageY-b.pageY;return c===k>=d*d+e*e})))}function Nb(){if(!Ze){Ze=!0;try{Ie.parent.document.activeElement.blur()}catch(a){}Ie.focus()}}function Ob(b,c,d,e,f){for(var g=e.split(/\s+/),h=0;h<0?void 0:c.apply(this,arguments)};c.guid&&(d.guid=c.guid),a.handler=d}}function Wb(){Ob(a.event.fixHooks,"filter",a.event.keyHooks,"keydown keyup",Tb),Ob(a.event.fixHooks,"filter",a.event.keyHooks,"keypress",Ub),Ob(a.event.special,"add",{},"keydown keyup keypress",Vb)}function Xb(){return{get:function(a,b,c){return g(Zb(a).getTimbre())},set:function(a,b){Zb(a).setTimbre(f(b,"wave"))}}}function Yb(){return{get:function(a,b,c){return Zb(a).getVolume()},set:function(a,b){Zb(a).setVolume(parseFloat(b))}}}function Zb(b){var c=Oa(b);if(c.instrument)return c.instrument;c.instrument=new ef("piano");var d=a(b);return c.instrument.on("noteon",function(b){var c=a.Event("noteon");c.midi=b.midi,d.trigger(c)}),c.instrument.on("noteoff",function(b){var c=a.Event("noteoff");c.midi=b.midi,d.trigger(c)}),c.instrument}function $b(){return af||(af=new ef),af}function _b(){return!(!Ie.AudioContext&&!Ie.webkitAudioContext)}function ac(){if(ac.audioTop)return ac.audioTop;if(!_b())return null;var a=new(Ie.AudioContext||Ie.webkitAudioContext);return ac.audioTop={ac:a,wavetable:jc(a),out:null,currentStart:null},bc(),ac.audioTop}function bc(){if(ac.audioTop){var a=ac.audioTop;a.out&&(a.out.disconnect(),a.out=null,a.currentStart=null);try{var b=a.ac.createDynamicsCompressor();b.ratio=16,b.attack=5e-4,b.connect(a.ac.destination),a.out=b}catch(c){ac.audioTop=null}}}function cc(){var a=ac();return null!=a.currentStart?a.currentStart:(a.currentStart=Math.max(.25,a.ac.currentTime),setTimeout(function(){a.currentStart=null},0),a.currentStart)}function dc(a){return 440*Math.pow(2,(a-69)/12)}function ec(a){return Math.round(69+12*Math.log(a/440)/Math.LN2)}function fc(a){var b=/^(\^+|_+|=|)([A-Ga-g])([,']*)$/.exec(a);if(!b)return null;var c=b[3].replace(/,/g,"").length-b[3].replace(/'/g,"").length,d=bf[b[2]]+cf[b[1].charAt(0)]*b[1].length+12*c;return d+60}function gc(a){var b=(a-72)%12;(a>60||0!=b)&&(b+=12);for(var c=Math.round((a-b-60)/12),d=df[b];0!=c;)d+=c>0?"'":",",c+=c>0?-1:1;return d}function hc(a){return dc(fc(a))}function ic(a){function b(a,b){switch(a){case"V":A!==z&&c(b.split(" ")[0]);break;case"M":f(b,A);break;case"L":g(b,A);break;case"Q":h(b,A)}A.hasOwnProperty(a)?A[a]+="\n"+b:A[a]=b,"K"==a&&(B=k(b),A===z&&c(d()))}function c(a){a=a||"",(a||A===z)&&(z.voice||(z.voice={}),z.voice.hasOwnProperty(a)?(A=z.voice[a],C=A.accent):(A={id:a,accent:{slurred:0}},z.voice[a]=A,C=A.accent))}function d(){return z.V?z.V.split(/\s+/)[0]:""}function e(a){var e,f=a.match(gf),g=null,h=0,i=0,j=null;if(!f)return null;for(;h /.test(f[h]))i=f[h++].length;else if(/^\(\d+(?::\d+)*/.test(f[h]))j=o(f[h++]);else if(/^[!+].*[!+]$/.test(f[h]))p(f[h++],C);else if(/^.?".*"$/.test(f[h]))h++;else if(/^[()]$/.test(f[h]))"("==f[h++]?C.slurred+=1:(C.slurred-=1,C.slurred<=0&&(C.slurred=0,A.stems&&A.stems.length>=1&&m(A.stems[A.stems.length-1],!1)));else if(/\|/.test(f[h])){for(e in C)1==e.length&&delete C[e];h++}else g=q(f,h,B,C),null!==g?(j&&(n(g.stem,j.time),j.count-=1,j.count||(j=null)),i&&A.stems&&A.stems.length&&(e=i>0?(1-Math.pow(.5,i))*g.stem.time:(Math.pow(.5,-i)-1)*A.stems[A.stems.length-1].time,l(A.stems[A.stems.length-1],e),l(g.stem,-e)),i=0,C.slurred&&m(g.stem,!0),A===z&&c(d()),"stems"in A||(A.stems=[]),A.stems.push(g.stem),h=g.index):h++}function f(a,b){var c=/^C/.test(a)?1:t(a);c&&(b.unitnote||(.75>c?b.unitnote=1/16:b.unitnote=1/8))}function g(a,b){var c=t(a);c&&(b.unitnote=c)}function h(a,b){var c,d=a.split(/\s+|=/),e=null,f=null;for(c=0;c =0||/^[1-4]$/.test(d[c])?e=e||t(d[c]):f=f||Number(d[c]);e&&(b.unitbeat=e),f&&(b.tempo=f)}function i(a){var b,c,d,e,f,g={};for(c=0;c0)for(b=0;a>b&&7>b;++b)d[c.charAt(b)]="^";else for(b=0;b>a&&b>-7;--b)d[c.charAt(6+b)]="_";return d}function k(a){if(!a)return{};var b,c={"c#":7,"f#":6,b:5,e:4,a:3,d:2,g:1,c:0,f:-1,bb:-2,eb:-3,ab:-4,db:-5,gb:-6,cb:-7,"a#m":7,"d#m":6,"g#m":5,"c#m":4,"f#m":3,bm:2,em:1,am:0,dm:-1,gm:-2,cm:-3,fm:-4,bbm:-5,ebm:-6,abm:-7,"g#mix":7,"c#mix":6,"f#mix":5,bmix:4,emix:3,amix:2,dmix:1,gmix:0,cmix:-1,fmix:-2,bbmix:-3,ebmix:-4,abmix:-5,dbmix:-6,gbmix:-7,"d#dor":7,"g#dor":6,"c#dor":5,"f#dor":4,bdor:3,edor:2,ador:1,ddor:0,gdor:-1,cdor:-2,fdor:-3,bbdor:-4,ebdor:-5,abdor:-6,dbdor:-7,"e#phr":7,"a#phr":6,"d#phr":5,"g#phr":4,"c#phr":3,"f#phr":2,bphr:1,ephr:0,aphr:-1,dphr:-2,gphr:-3,cphr:-4,fphr:-5,bbphr:-6,ebphr:-7,"f#lyd":7,blyd:6,elyd:5,alyd:4,dlyd:3,glyd:2,clyd:1,flyd:0,bblyd:-1,eblyd:-2,ablyd:-3,dblyd:-4,gblyd:-5,cblyd:-6,fblyd:-7,"b#loc":7,"e#loc":6,"a#loc":5,"d#loc":4,"g#loc":3,"c#loc":2,"f#loc":1,bloc:0,eloc:-1,aloc:-2,dloc:-3,gloc:-4,cloc:-5,floc:-6,bbloc:-7},d=a.replace(/\s+/g,"").toLowerCase().substr(0,5),e=d.match(/maj|min|mix|dor|phr|lyd|loc|m/);b=e?"maj"==e?d.substr(0,e.index):"min"==e?d.substr(0,e.index+1):d.substr(0,e.index+e[0].length):/^[a-g][#b]?/.exec(d)||"";var f=j(c[b]),g=a.substr(b.length).match(/(_+|=|\^+)[a-g]/gi);if(g)for(var h=0;h<2))switch(a=a.substring(1,a.length-1)){case"pppp":case"ppp":b.dynamics=.2;break;case"pp":b.dynamics=.4;break;case"p":b.dynamics=.6;break;case"mp":b.dynamics=.8;break;case"mf":b.dynamics=1;break;case"f":b.dynamics=1.2;break;case"ff":b.dynamics=1.4;break;case"fff":case"ffff":b.dynamics=1.5}}function q(a,b,c,d){var e,f,g,h,i=[],j="",k=!1,l=null,m=1/0;if(bf&&(j=e,m=f),b0&&"="==a.charAt(0)?a.substr(1):a}function s(a,b,c){var d,e=/^(\^+|_+|=|)([A-Ga-g])(.*)$/.exec(a);return e?(d=e[2].toUpperCase(),e[1].length>0?(c[d]=e[1],r(a)):r(c.hasOwnProperty(d)?c[d]+e[2]+e[3]:b.hasOwnProperty(d)?b[d]+e[2]+e[3]:a)):a}function t(a){var b,c,d,e=/^(\d*)(?:\/(\d*))?$|^(\/+)$/.exec(a),f=0;if(e){if(e[3])return Math.pow(.5,e[3].length);if(c=e[2]?parseFloat(e[2]):/\//.test(a)?2:1,d=0,b=e[1]?parseFloat(e[1]):1,e[2])for(;d+1c;)d+=1,f=parseFloat(e[1].substring(0,d)),b=parseFloat(e[1].substring(d));return f+b/c}}var u,v,w,x,y=a.split("\n"),z={},A=z,B={},C={slurred:0};for(u=0;u c;++c)e[c]=b.real[c],f[c]=b.imag[c];try{return a.createPeriodicWave(e,f)}catch(g){}try{return a.createWaveTable(e,f)}catch(g){}return null}function d(a,b,c){var d,e,f={real:[],imag:[]},g=a.real.length;for(d=0;g>d;++d)e=Math.log(b[Math.min(d,b.length-1)]),f.real.push(a.real[d]*Math.exp(c*e)),f.imag.push(a.imag[d]*Math.exp(c*e));return f}var e,f,g,h,i,j,k={};for(e in b)if(f=b[e],j=c(f)){if(i={wave:j},f.mult)for(h=b[e].freq,i.freq={},g=0;gc;++c)b[c]&&(b[c].constructor===a?e.push.apply(e,b[c].toArray()):a.isArray(b[c])?e.push.apply(e,b[c]):e.push(b[c]));return{elts:a.unique(e),completion:d}}function lc(){function b(){var a,b=g;for(g=null,f&&f(),a=0;a1)for(c=0;c")}function oc(b){var c,d,e=a.extend({},sf,hf,tf);if(b&&!a.isArray(b.helptext)&&b in e&&(b=e[b]),b&&a.isArray(b.helptext)&&b.helptext.length){for(d=0;d/g,'<$1 style="border:1px solid black;text-decoration:none;word-break:keep-all;white-space:nowrap">').replace(/<(mark)>/g,'<$1 style="border:1px solid blue;color:blue;text-decoration:none;word-break:keep-all;white-space:nowrap;cursor:pointer;" onclick="see.enter($(this).text())">'))}return vf}if("number"==typeof b)return nc("Equal to the number "+b+"."),vf;if("boolean"==typeof b)return nc("Equal to the boolean value "+b+"."),vf;if(null===b)return nc("The special null value represents the absence of a value."),vf;if(b===He)return nc("This is an unassigned value."),vf;if(b===Ie)return nc("The global window object represents the browser window."),vf;if(b===document)return nc("The HTML document running the program."),vf;if(b===jQuery)return nc('The jQuery function. Read about it at jquery.com .'),vf;if(b&&b!=oc)return nc("No help available for "+b),vf;c=[];for(var g in e)!e[g].helptext||!e[g].helptext.length||g in Ie&&"function"!=typeof Ie[g]||c.push(g);return c.sort(function(a,b){return a.length!=b.length?a.length-b.length:b>a?-1:a>b?1:0}),nc("help available for: "+c.map(function(a){return''+a+" "}).join(" ")),vf}function pc(a){return 1==a.length&&qc(a[0])&&a[0]}function qc(b){var c;return!(!b||0!=a.queue(b).length||b.parentElement&&b.parentElement.style.transform||0!==(c=pb(b))&&0!==a.fx.speeds[c])}function rc(b,c){var d;if(null==c){if(qc(b))return;d=pb(b)}else d=1e3*c;var e=a(b);d>0&&e.delay(d)}function sc(a,b){if(b=b||0,a.length<=b)return null;var c=a[a.length-1];return"function"!=typeof c||c.helpname?null:c}function tc(b,c,d,e){function f(d,e){if(null!=d){var f=b&&b[d];e&&f&&bb(f,a.data(f,"turtleData"),!0),Hf.reportEvent("resolve",[c,m,j,d,f])}0==--k&&h&&(l?(Me+=1,setTimeout(function(){Me-=1,h()},0)):h())}function g(a){null!=a&&Hf.reportEvent("appear",[c,m,j,a,b&&b[a],i])}var h=sc(d,e),i=h?Array.prototype.slice.call(d,0,d.length-1):d,j=b?b.length||0:0,k=j+1,l=!0,m=Hf.nextId();return Hf.reportEvent("enter",[c,m,j,i]),{name:c,args:i,appear:g,resolve:f,resolver:function(a,b){return function(){f(a,b)}},exit:function(){Hf.reportEvent("exit",[c,m,j,i]),f(null),l=!1}}}function uc(b,c,d,e){var f=function(){if(Vc(b),Le)throw new Error(b+" interrupted");var d,f=tc(this,b,arguments,c),g=[f].concat(a.makeArray(f.args));try{d=e.apply(this,g)}finally{f.exit()}return d};return zc(b,d,f)}function vc(a,b,c){var d=function(){if(Vc(a),Le)throw new Error(a+" interrupted");return Wc(a,this),c.apply(this,arguments)};return zc(a,b,d)}function wc(b,c,d,e){var f=function(){if(Vc(b),Le)throw new Error(b+" interrupted");var c=null,f=0,g=pf;if(e&&(c=e.apply(null,arguments),f=arguments.length,g=Yc()),g){var h=a(pf).eq(0),i=arguments,j=tc(h,b,arguments,f);h.plan(function(a,b){j.appear(a),d.apply(c,i),this.plan(j.resolver(a))}),j.exit()}else j=tc(null,b,arguments,f),d.apply(c,arguments),j.exit();return c?(c.result&&c.result.constructor===jQuery&&pf&&lc(pf,c.result),c.result):void 0};return zc(b,c,f)}function xc(b,c){return zc(b,c,function(c,d){var e=/^key/.test(b),f=/^mouse|click$/.test(b),g=f?"input,button":e?"textarea,input:not([type]),input[type=text],input[type=password]":null;e&&Nb(),null==d&&"function"==typeof c&&(d=c,c=null),a(Ie).on(b+".turtleevent",null,c,g?function(b){return Le||a(b.target).closest(g).length?void 0:d.apply(this,arguments)}:d)})}function yc(){var b=a._data(Ie,"events");if(!b)return!1;for(var c in b)for(var d=b[c],e=0;eb?-c:c,l=null;i.style&&i.down&&(l=function(){var a=Y(h),c=ra(h,!0),d=z(h.parentElement);return function(){ub(i.corners[0],a,c.rot,c.rot+(e?-b:b),k*(i.oldscale?c.sy:1),d)}}()),i.turningRadius=k,this.animate({turtleRotation:g+sa(b)+"deg"},pb(h,f),qb(h)),this.plan(function(){l&&l(),i.turningRadius=j,a.resolve(d,!0)})}),this)}function Bc(a,b){null==b&&(b=100),"bk"===a.name&&(b=-b);var c,d=Df;return(c=pc(this))?(a.appear(0),ib(c,b,0),a.resolve(0,!0),this):(this.plan(function(c,e){a.appear(c),this.animate({turtleForward:"+="+sa(b||0)+"px"},pb(e,d),qb(e),a.resolver(c,!0))}),this)}function Cc(b,c,d){a.isArray(c)&&(d=c[1],c=c[0]),d||(d=0),c||(c=0);var e=Df;return this.plan(function(a,f){b&&b.appear(a),this.animate({turtlePosition:lb(f,d,c)},pb(f,e),qb(f),b&&b.resolver(a,!0))}),this}function Dc(b,c,d){a.isArray(c)&&(d=c[1],c=c[0]),d||(d=0),c||(c=0);var e,f=Df;return(e=pc(this))?(b&&b.appear(0),jb(e,c,d),b&&b.resolve(0),this):(this.plan(function(a,e){b&&b.appear(a);var g=w(e);this.animate({turtlePosition:sa(g[0]+c)+" "+sa(g[1]-d)},pb(e,f),qb(e),b&&b.resolver(a,!0))}),this)}function Ec(b,c,d){var e=c,f=0,g=0,h=null,i=Df;return a.isNumeric(e)&&a.isNumeric(d)?(f=parseFloat(e),g=parseFloat(d),e=null,h=null):a.isArray(e)?(f=e[0],g=e[1],e=null,h=d):a.isNumeric(d)&&(h=d),this.plan(function(c,d){var j=e;if(null===j&&(j=a(V(d)).pagexy()),j&&!mb(j))try{j=a(j).pagexy()}catch(k){return}return j&&mb(j)?a.isWindow(d)?(b&&b.appear(c),ba(j,h),void(b&&b.resolve(c))):void(9!==d.nodeType&&(b&&b.appear(c),this.animate({turtlePosition:U(d,j,h,f,g)},pb(d,i),qb(d),b&&b.resolver(c,!0)))):void 0}),this}function Fc(a){return function(b,c,d){return this.plan(function(e,f){b.appear(e);var g=this.css("turtlePenDown");this.css({turtlePenDown:"up"}),a.call(this,null,c,d),this.plan(function(){this.css({turtlePenDown:g}),b.resolve(e,!0)})}),this}}function Gc(b){var c=a.data(b,"turtleData");return c&&null!=c.oldscale?c.oldscale:1}function Hc(a,b,c){Jc.call(this,!0,a,b,c)}function Ic(a,b,c){Jc.call(this,!1,a,b,c)}function Jc(b,c,d,e){e===He&&(e=d),d&&e||(d=e=1);var f=Df;return this.plan(function(g,h){if(b&&(Oa(h).oldscale*=e),c.appear(g),a.isWindow(h)||9===h.nodeType)return void c.resolve(g);var i=a.map(a.css(h,"turtleScale").split(" "),parseFloat);1===i.length&&i.push(i[0]),i[0]*=d,i[1]*=e,this.animate({turtleScale:a.map(i,sa).join(" ")},pb(h,f),qb(h),c.resolver(g))}),this}function Kc(a,b){var c=z(a.parentElement),d=l(c),e=d?1:u(c)[1];return e*Gc(a)}function Lc(b){var c=Df;return function(d,e,f){if(a.isNumeric(e)){var g=e;e=f,f=g}return null==f&&(f=8.8),this.plan(function(g,h){var i=Oa(h),j=i.style;e||(e=j&&(j.fillStyle||j.strokeStyle)||"black"),d.appear(g);var k=this.pagexy(),l=ra(h,!0),m=Ka(e,"fillStyle"),n=Da(i),o=Kc(h),p=f*o,q=Math.max(0,p-2),r=p+(m.eraseMode?2:0),s=/rgba|hsla/.test(m.fillStyle);null==m.lineWidth&&j&&j.lineWidth&&(m.lineWidth=j.lineWidth),pc(this)?(b(n,k,r,l.rot,m,!0),d.resolve(g)):this.queue(function(e){a({radius:0}).animate({radius:q},{duration:pb(h,c),step:function(){s||b(n,k,this.radius,l.rot,m,!1)},complete:function(){b(n,k,r,l.rot,m,!0),d.resolve(g),e()}})})}),this}}function Mc(a,b,c,d,e){var f=a.getContext("2d");f.save(),Xa(f,e),c===1/0?(f.setTransform(1,0,0,1,0,0),f.fillRect(0,0,a.width,a.height)):(Za(f,a),f.beginPath(),f.arc(b.pageX,b.pageY,c/2,0,2*Math.PI,!1),f.closePath(),f.fill(),e.strokeStyle&&f.stroke()),f.restore()}function Nc(a,b,c,d,e){var f=a.getContext("2d");if(f.save(),Xa(f,e),c===1/0)f.setTransform(1,0,0,1,0,0),f.fillRect(0,0,a.width,a.height);else{var g=Math.sin((d+45)/180*Math.PI),h=Math.cos((d+45)/180*Math.PI),i=c*h/Math.SQRT2,j=c*g/Math.SQRT2;Za(f,a),f.beginPath(),f.moveTo(b.pageX-i,b.pageY-j),f.lineTo(b.pageX-j,b.pageY+i),f.lineTo(b.pageX+i,b.pageY+j),f.lineTo(b.pageX+j,b.pageY-i),f.closePath(),f.fill(),e.strokeStyle&&f.stroke()}f.restore()}function Oc(a,b,c,d,e,f){var g=a.getContext("2d");if(g.save(),Xa(g,e),!e.strokeStyle&&e.fillStyle&&(g.strokeStyle=e.fillStyle),c!==1/0){var h=Math.sin(d/180*Math.PI),i=-Math.cos(d/180*Math.PI),j=e.lineWidth||1.62,k=b.pageX+c*h,l=b.pageY+c*i,m=Pc(j,k,l,h,i),n=c-m.hs,o=n*h,p=n*i;Za(g,a),n>0&&(g.beginPath(),g.moveTo(b.pageX,b.pageY),g.lineTo(b.pageX+o,b.pageY+p),g.stroke()),f&&Qc(g,m)}g.restore()}function Pc(a,b,c,d,e){var f=Math.max(1.25*a,a+2),g=2*f,h=g-f/2;return{hs:h,x1:b,y1:c,xm:b-d*h,ym:c-e*h,x2:b-e*f-d*g,y2:c+d*f-e*g,x3:b+e*f-d*g,y3:c-d*f-e*g}}function Qc(a,b){a.beginPath(),a.moveTo(b.x2,b.y2),a.lineTo(b.x1,b.y1),a.lineTo(b.x3,b.y3),a.quadraticCurveTo(b.xm,b.ym,b.x2,b.y2),a.closePath(),a.fill()}function Rc(a,b,c,d,e,f){var g=e-c,h=f-d,i=Math.sqrt(g*g+h*h),j=g/i,k=h/i,l=Pc(b,e,f,j,k);i>l.hs&&(a.beginPath(),a.moveTo(c,d),a.lineTo(l.xm,l.ym),a.lineWidth=b,a.stroke()),Qc(a,l)}function Sc(a,b){function c(){d&&clearInterval(d),b&&b()}var d=null;if(!Ie.speechSynthesis)return console.log("No speech synthesis: "+a),void c();try{var e=new Ie.SpeechSynthesisUtterance(a);e.addEventListener("end",c),e.addEventListener("error",c),e.lang=navigator.language||"en-GB",Ie.speechSynthesis.speak(e),d=setInterval(function(){Ie.speechSynthesis.pending||Ie.speechSynthesis.speaking||c()},250)}catch(f){Ie.console&&Ie.console.log(f),c()}}function Tc(){a.each(["toggle","show","hide"],function(b,c){var d=a.fn[c];a.fn[c]=function(b,c,e){var f=arguments;!f.length&&this.hasClass("turtle")&&(this.length>1||!a._data(this[0],"fxshow"))&&(f=[0]),d.apply(this,f)}})}function Uc(c,d){if(d||(d="fx"),"IMG"==c.tagName&&c.src&&!c.complete){var e=a.queue(c,d);0==e.length&&(a.queue(c,d,function(a){Ib(c,null,a)}),b(c,d))}}function Vc(b){if(!(a.turtle.hangtime==1/0||kf++<100)){kf=0;var c=(new Date).getTime();return mf?void(c-mf>a.turtle.hangtime&&(Sf.visible()&&Sf.html('Oops: program interrupted because it was hanging the browser. Try reducing the number of repetitions. Or try using await done defer() or tick to make an animation. '),a.turtle.interrupt("hung"))):(mf=c,clearTimeout(lf),void(lf=setTimeout(function(){clearTimeout(lf),lf=null,mf=null},0)))}}function Wc(b,c){if(!a.turtle.nowarn){var d,e=!0;for(d=0;e&&d=100&&(e=!1);e||(jf[b]||(jf[b]=1,Sf.visible()?Sf.html('Oops: '+b+' may not return useful results when motion is queued. Try speed Infinity or await done defer() first.'):console.warn(b+' may not return useful results when motion is queued. Try "speed Infinity" or "await done defer()".')),c.finish())}}function Xc(a,b,d){a[b]=function(){return b in jf||(Sf.html(''+b+" deprecated. Use "+d+". "),jf[b]=1),a[d].apply(this,arguments)},a[d].__super__&&c(a[b],a[d])}function Yc(){return pf&&a.queue(pf).length>0}function Zc(a){if(null===uf.pollTimer){var b=uf.sent[a],c=uf.waiting[a];c&&c.length&&b&&b.length&&(uf.pollTimer=setTimeout(function(){uf.pollTimer=null,c&&c.length&&b&&b.length&&(c.shift().apply(null,b.shift()),Zc(a))},0))}}function $c(a,b){if("function"!=typeof b&&"undefined"!=typeof b||!/^\w+\s*$/.test(a)){if("undefined"==typeof b&&/^help\s+\S+$/.test(a))return oc(/^help\s+(\S+)$/.exec(a)[1]),!0}else{if(b&&b.helptext)return oc(b),!0;if(a in tf)return oc(a),!0}return!1}function _c(a,b,c,d){return a.helptext?d.helptext=a.helptext:b in c&&(d.helptext=c[b].helptext),d.method=a,d.helpname=b,d}function ad(a,b){var c=[];for(var d in b)!b.hasOwnProperty(d)||d in Ie||(c.push(d),Ie[d]=function(b){var c=a[b],d=a;return _c(c,b,tf,function(){return c.apply(d,arguments)})}(d));return c}function bd(){pf=null;for(var a=0;a=0;i--)null===h[i]?(i--,c.moveTo(d-h[i][0],e+h[i][1])):c.lineTo(d-h[i][0],e+h[i][1])}return c.lineWidth=1.1,c.strokeStyle="rgba(255,255,255,0.75)",c.stroke(),c.beginPath(),c.arc(d,e,15.5,0,2*Math.PI,!1),c.closePath(),c.strokeStyle="rgba(0,0,0,0.4)",c.stroke(),b.toDataURL()}function gd(a){var b=Ga(40,48),c=b.getContext("2d");return c.beginPath(),c.moveTo(0,48),c.lineTo(20,0),c.lineTo(40,48),c.lineTo(20,36),c.closePath(),c.fillStyle=a,c.fill(),b.toDataURL()}function hd(a){var b=Ga(40,40),c=b.getContext("2d");return c.beginPath(),c.arc(20,20,18,-5*Math.PI/2,-Math.PI/2),c.closePath(),c.lineTo(20,20),c.stroke(),c.strokeStyle=a,c.lineWidth=4,c.stroke(),b.toDataURL()}function id(a,b){b=b||12;var c=Ga(b,b),d=c.getContext("2d"),e=b/2;return d.beginPath(),d.arc(e,e,e,0,2*Math.PI),d.closePath(),d.fillStyle=a,d.fill(),c.toDataURL()}function jd(a){function b(){e.moveTo(19.5,43),e.lineTo(20.5,43),e.lineTo(21.5,43.5),e.lineTo(25.5,36.2),e.lineTo(24,35.5),e.lineTo(23,35.5),e.lineTo(20.5,36.5),e.lineTo(19.5,36.5),e.lineTo(17,35.5),e.lineTo(16,35.5),e.lineTo(14.5,36.2),e.lineTo(18.5,43.5),e.closePath()}function c(){e.moveTo(25.5,12),e.lineTo(25.5,8),e.lineTo(14.5,8),e.lineTo(14.5,12),e.closePath()}var d=Ga(40,48),e=d.getContext("2d");return e.beginPath(),b(),e.fillStyle="#ffcb6b",e.fill(),e.beginPath(),c(),e.fillStyle="#d1ebff",e.fill(),e.beginPath(),e.moveTo(19.5,48),e.lineTo(13,36),e.lineTo(13,1),e.lineTo(14,0),e.lineTo(26,0),e.lineTo(27,1),e.lineTo(27,36),e.lineTo(20.5,48),e.closePath(),b(),e.moveTo(25.5,12),e.lineTo(25.5,8),e.lineTo(14.5,8),e.lineTo(14.5,12),e.closePath(),e.fillStyle=a,e.fill(),d.toDataURL()}function kd(a,b,c){return c||(c=1),function(d){var e=document.createElement("canvas");e.width=a,e.height=b;var f=e.getContext("2d");d||(d="rgba(128,128,128,0.125)"),"transparent"!=d&&(f.fillStyle=d,f.fillRect(0,0,a,b));var g=a/c,h=b/c,i={width:g,height:h,transformOrigin:g/2+"px + "+h/2+"px",opacity:1};return 1>c&&(i.imageRendering="pixelated"),{img:e,css:i}}}function ld(a){if(!a)return null;if(a in yf)return yf[a];var b=a.match(/^(\d+)x(\d+)(?:\/(\d+))?$/);return b?kd(parseFloat(b[1]),parseFloat(b[2]),b[3]&&parseFloat(b[3])):null}function md(a,b){var c=a.width||a.height||256,d=a.height||a.width||256,e=a.subpixel||1/(a.scale||1),f=a.color||"transparent",g=kd(c,d,e);return g(f)}function nd(b,c){if(!b)return null;if(a.isPlainObject(b))return md(b,c);if(a.isFunction(b)&&(b.helpname||b.name)&&(b=b.helpname||b.name),b.constructor===jQuery){if(!b.length)return null;b=b.get(0)}if(b.tagName)return"CANVAS"!=b.tagName&&"IMG"!=b.tagName&&"VIDEO"!=b.tagName?null:{img:b,css:{opacity:1}};var d=b.toString().trim().split(/\s+/),e=null,f=null;if(d.length&&(f=ld(d[d.length-1]),f&&d.pop()),d.length&&cd(d.join(" "))&&(e=d.join(" "),d.length=0),!f&&e&&(f=ld(c)),f)return f(e);if(/\//.test(b)||(b=Fb(b)),/\//.test(b)){var g=Ab(b).hostname;return!Cb(g)&&Cb(Ie.location.hostname)&&(b=Ie.location.protocol+"//"+Ie.location.host+"/proxy/"+Bb(b)),{url:b,css:{transformOrigin:"50% 50%",opacity:1}}}return null}function od(a){return null==a?"":String(a).replace(/[&<>"]/g,function(a){return zf[a]})}function pd(b,c,d){var e=b&&/^[a-zA-Z]\w*$/.exec(b),f=b&&/^<.*>$/.exec(b),g=nd(b,d)||null==b&&nd(d);e&&a("#"+b).length&&(e=!1);var h;f?h=a(b):g?(h=a(""),hb(h,g)):h=a(""+od(b)+"
"),b&&"object"==typeof b&&("id"in b&&h.attr("id",b.id),"class"in b&&h.addClass(b["class"])),h.css({position:"absolute",display:"table",top:0,left:0}),(!c||9==c.nodeType||a.isWindow(c))&&(c=za()),h.appendTo(c);var i=y(h[0]);return h.css({top:-i[1],left:-i[0]}),h.css({turtlePosition:U(h[0],a(c).pagexy(),null,0,0),turtleRotation:0,turtleScale:1}),h.addClass("turtle"),e&&(h.attr("id",b),rf&&!Ie.hasOwnProperty(b)&&(Ie[b]=h)),h}function qd(a,b){if("number"==typeof a)return a=Math.ceil(a),"number"==typeof b?(b=Math.ceil(b),Math.floor(Math.random()*(b-a)+a)):Math.floor(Math.random()*a);if("object"==typeof a&&a&&a.length&&a.slice)return a[Math.floor(Math.random()*a.length)];if("normal"==a){var c,d,e,f,g;do c=Math.random(),d=1.7156*(Math.random()-.5),e=c-.449871,f=Math.abs(d)+.386595,g=e*e+f*(.196*f-.25472*e);while(g>.27597&&(g>.27846||d*d>-4*Math.log(c)*c*c));return d/c}return"position"==a?{pageX:qd(K()+1),pageY:qd(J()+1)}:"color"==a?"hsl("+Math.floor(360*Math.random())+",100%,50%)":"gray"==a?"hsl(0,0,"+Math.floor(100*Math.random())+"%)":a===!0?Math.random()>=.5:Math.random()}function rd(b,c){c||"function"!=typeof b||(c=b,b=30);var d=null,e=Math.max(Math.floor(1e3/Math.max(1/86400,b)),0);if(Yc()){var f=a(pf);f.plan(function(){d=c})}else d=c;var g={fn:c,timer:setInterval(function(){if(d)try{Df++,Bf.push(g),d()}finally{Df--,Bf.pop(g)}},e)};return Af.push(g),g.timer}function sd(a){for(var b=[],c=0;c0?1e3/b:0)}function wd(b){b===He&&(b=""),a("[id]").each(function(c,d){Ie[b+d.id]=a("#"+d.id)}),rf=!0}function xd(b){if(b===He&&(b="last"),Ef&&a(Ie).off(a.map(of,function(a,b){return b}).join(" "),Ef),b||""===b){Ef=function(a){var c,d=[b+a.type];for((a.originalEvent||a)instanceof MouseEvent&&d.push(b+"mouse"),c=0;c=a("html").outerHeight(!0);if(b(),e){var f=a(Ie).scrollTop(),g=Math.min(d,a("html").outerHeight(!0)-a(Ie).height());g>f&&a(Ie).scrollTop(g)}}function zd(){if(!Ff.timer){Ff.timer=setTimeout(function(){Ff.timer=null},0);var b=a("body").offset(),c=b?b.top:8;Ff.bottomSeen=Math.min(a(Ie).height()+a(Ie).scrollTop(),a("body").height()+c)}return Ff.bottomSeen}function Ad(b){var c=a(Ie).scrollTop();b(),a(Ie).scrollTop(c)}function Bd(){var a=document.body.lastChild;return a&&"PRE"==a.tagName||(a=document.createElement("pre"),document.body.appendChild(a)),a}function Cd(){var a=arguments;yd(function(){for(var b=Bd(),c=0;c").css({display:"inline-block",verticalAlign:"top",textAlign:"center",height:"1.2em",width:"1.2em",maxWidth:"1.2em",overflow:"hidden"}).appendTo(Bd()),e=function(){null!=b&&d.css({background:b}),null!=c&&d.text(c)};if(pf){var f=a(pf);Ec.call(f,null,d),f.eq(0).plan(e)}else e()}function Ed(){var a=this;yd(function(){a.result.appendTo("body"),a.setup&&a.setup()})}function Fd(b,c){var d="<"+c+' style="display:table">',e=""+c+">";if(b===He||null===b)return{result:a(d+" "+e)};if(b.jquery||b instanceof Element&&(b=a(b)))return{result:b};var f=null;return b=""+b,/^\s*<.*>\s*$/.test(b)&&(f=a(b)),(null==f||1!=f.length||1!=f[0].nodeType)&&(f=a(d+b+e)),{result:f}}function Gd(b,c){function d(b){return function(d){j||m&&"change"==d.type||(j=!0,a(this).prop("checked",!0),i.find("input[type=radio]").prop("disabled",!0),c(b))}}function e(a){return function(){j||(l=a,f())}}function f(a){a||(m+=1,setTimeout(function(){m-=1},0),i.find("input").eq(l).prop("checked",!0)),i.find("input").eq(l).focus()}function g(b,c){a.isFunction(b)&&(b=(k+1).toString());var f=a.isFunction(c)||null==c?b:c,g=a(' ').attr("value",f).on("change click",d(c)),h=a('').append(g).append(b).on("click",d(c)).on("mousedown",e(k)),j=b&&b.toString().substr(0,1).toUpperCase();!j||j in n||(n[j]=k),k+=1,i.append(h)}var h,i=a(" ")}}function ke(){if(!dg&&!Ie.document.getElementById("_logcss")){var a=Ie.document.createElement("style");a.id="_logcss",a.innerHTML=(Mf?"samp._log{"+Mf+"}":"")+cg,Ie.document.head.appendChild(a),dg=!0}}function le(a,b,c){b=b||3;var d=c||[],e=Xd(a);return"Error"==e||"ErrorEvent"==e?(d.push(''),je("",a,b,d),d.push(" ")):Yd(e)?d.push(ae(a)):de(a,!0,100)||0>=b?d.push(fe(a,100)):je("",a,b,d),c?void 0:d.join("")}function me(b,c){switch(typeof b){case"string":return"body"==b?document.body:document.querySelector?document.querySelector(b):a?a(b)[0]:null;case"undefined":return c;case"boolean":return b?c:null;default:return b}}function ne(){var a=!1,b=me(Of,null);return b&&(a=b.scrollHeight-b.scrollTop-10<=b.clientHeight),a?function(){b.scrollTop=b.scrollHeight-b.clientHeight}:function(){}}function oe(){var a,b=me(Pf,null);if(b&&b.appendChild&&gg.length){ke();var c=Ie.document.createElement("samp");c.innerHTML=gg.join(""),gg.length=0;for(var d=ne();a=c.firstChild;)b.appendChild(a);d()}!fg&&gg.length?("auto"==Qf&&Be(),fg=setTimeout(function(){fg=null,oe()},100)):fg&&!gg.length&&(clearTimeout(fg),fg=null)}function pe(){a("#_testpanel").hide()}function qe(){a("#_testpanel").show()}function re(){return a("#_testpanel").is(":visible")}function se(b){a("#_testinput").val(b)}function te(){hg&&a("#_testlog").find("._log").not("#_testpaneltitle").remove()}function ue(a){return' '}function ve(){return Ie.getSelection?Ie.getSelection().toString():document.getSelection?document.getSelection():document.selection?document.selection.createRange().text:void 0}function we(a){return''+a+" "}function xe(){if(Wf){var b,c={height:Xf,history:[]};try{b=Ie.JSON.parse(Ie.localStorage[Wf])}catch(d){b=mg||{}}return b&&b.slice&&b.length?(c.history=b,c):(a.extend(c,b),c)}}function ye(a){if(Wf){var b=xe(),c=!1;if("history"in a&&a.history.length&&(!b.history.length||b.history[b.history.length-1]!==a.history[a.history.length-1])&&(b.history.push(a.history[a.history.length-1]),c=!0),"height"in a&&a.height!==b.height&&(b.height=a.height,c=!0),c)try{Ie.localStorage[Wf]=Ie.JSON.stringify(b)}catch(d){mg=b}}}function ze(){return Ie.innerHeight||a(Ie).height()}function Ae(){try{if(Tf&&Ie.console&&!Ie.console._log&&"function"==typeof Ie.console.log){var a=Ie.console._log=Ie.console.log;Ie.console.log=function(){a.apply(this,arguments),Sf.apply(this,arguments)};var b=Ie.console._debug=Ie.console.debug;Ie.console.debug=function(){b.apply(this,arguments),Sf.apply(this,arguments)}}}catch(c){}}function Be(){ig||(ig=!0,Vd(Ce))}function Ce(){if(hg)Uf&&(a("#_testpaneltitle").length?a("#_testpaneltitle").html(Uf):a("#_testlog").prepend(we(Uf))),a("#_testpanel").show();else if(!Ie.document.getElementById("_testlog")&&Ie.document.body){Ae(),ke();var b=xe(),c=Uf?we(Uf):"";b.height>ze()-50&&(b.height=Math.min(ze(),Math.max(10,ze()-50))),a("body").prepend(''+c+' '+ue("blue")+' '),hg=!0,oe();var d=0,e={};a("#_testinput").on("keydown",function(c){if(13==c.which){var f=a(this).val();if(a(this).val(""),!f.trim().length||b.history.length&&b.history[b.history.length-1]===f||(b.history.push(f),ye({history:[f]})),e={},d=0,Wd(''+ue("lightgray")+he(f)+" "),a(this).select(),f.trim().length&&":"==f.trim()[0]){var g=f.trim().substring(1).trim();if(!g||Zf.hasOwnProperty(g)){Yf=g;var h=g?"scope "+g:"default scope";Wd('switched to '+h+" ")}else Wd('no scope '+g+" ");return}a.turtle.interrupt("reset");var i=!1;try{var j;try{j=Pd(Yf,f)}finally{if(lg&&lg(f,j))i=!0;else{for(var k=kg.length-1;k>=0&&j!==kg[k];--k);0>k&&Wd(le(j))}}}catch(c){i||Sf(c)}}else if(38==c.which||40==c.which){e[d]=a(this).val(),d+=38==c.which?1:-1,d=Math.max(0,Math.min(b.history.length,d));var l=e[d]||b.history[b.history.length-d];"undefined"==typeof l&&(l=""),a(this).val(l),this.selectionStart=this.selectionEnd=l.length,c.preventDefault()}}),a("#_testdrag").on("mousedown",function(c){var d,e=this,f=a("#_testpanel").height()+c.pageY,g=a("#_testdrag").height(),h=c.which;return e.setCapture&&e.setCapture(!0),d=function(c){if("blur"!=c.type&&c.which==h){var e=ze(),i=Math.max(g,Math.min(e,f-c.pageY)),j=ne();a("#_testpanel").height(i),a("#_testscroll").height(i-g),j()}("mouseup"==c.type||"blur"==c.type||"mousemove"==c.type&&c.which!=h)&&(a(Ie).off("mousemove mouseup blur",d),document.releaseCapture&&document.releaseCapture(),a("#_testpanel").height()!=b.height&&(b.height=a("#_testpanel").height(),ye({height:b.height})))},a(Ie).on("mousemove mouseup blur",d),!1}),a("#_testpanel").on("mouseup",function(b){if(!ve()){var c=a("#_testscroll").scrollTop();a("#_testinput").focus(),a("#_testscroll").scrollTop(c)}})}jg&&hg?clearTimeout(jg):hg||jg||(jg=setTimeout(Ce,100))}function De(a,b){var c=document.createElement("canvas");b||(b=0),c.width=a.width,c.height=a.height;var d=c.getContext("2d");return d.drawImage(a,0,0),Ee(c,b)}function Ee(a,b){for(var c,d,e=a.getContext("2d"),f=e.getImageData(0,0,a.width,a.height).data,g=[],h=256*b,i=1/0,j=-1,k=0;kh&&(0>d&&(c=l),d=l);(d>=0||j>=0)&&(g.push({pageX:Math.min(c,i),pageY:k}),g.push({pageX:Math.max(d,j)+1,pageY:k})),i=c,j=d}return j>=0&&(g.push({pageX:i,pageY:a.height}),g.push({pageX:j+1,pageY:a.height})),la(g)}function Fe(a,b){var c=a.getContext("2d"),d=a.width,e=a.height,f=0;if(c.save(),c.beginPath(),c.moveTo(0,0),c.lineTo(d,0),c.lineTo(d,e),c.lineTo(0,e),c.closePath(),b.length)for(c.moveTo(b[0].pageX,b[0].pageY);f"),f||this.capture()}return c(d,b),d.prototype.capture=function(){return this.queue(function(b){var c=this,d=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia;return d?void d.call(navigator,{video:!0},function(d){if(d){var e=Oa(c),f=(""+Math.random()).substr(2);e.stream&&e.stream.stop(),e.stream=d,a(c).on("play.capture"+f,function(){a(c).off("play.capture"+f),b()}),c.src=Ie.URL.createObjectURL(d)}},function(){b()}):void b()})},d.prototype.cut=function(){return this.plan(function(){var a=this.data("turtleData");a.stream&&(a.stream.stop(),a.stream=null),this.attr("src","")})},d}(Ue),Ye=function(a){function b(a){var c,i,j,k,l,m,n,o,p,q,r,s=null,t=this;a=f(a,"keys"),q=ef.pitchToMidi(a.lowest),r=ef.pitchToMidi(a.highest);var u=this._geom={};if(u.lineWidth="lineWidth"in a?a.lineWidth:1.5,u.color="color"in a?a.color:"white",u.blackColor="blackColor"in a?a.blackColor:"black",u.lineColor="lineColor"in a?a.lineColor:"black",j=Math.ceil(u.lineWidth),i=422,c=4.2,null!=q&&null!=r?s=e(r)-e(q)+1:"keys"in a&&(s=Math.ceil(a.keys/12*7)),s&&(c=s/5,i=Math.sqrt(42e3*c)+j),m="width"in a?a.width:"height"in a?Math.round((a.height-j)*c+j):i,l="height"in a?a.height:Math.round((m-j)/c+j),s||(s=Math.max(1,Math.round((m-j)/(l-j)*5))),n=Math.min(e(108),Math.ceil(42+(s-1)/2)),u.highest=null!=r?r:null!=q&&"keys"in a?q+a.keys-1:g(null!=q?e(q)+s-1:n),u.lowest=null!=q?q:"keys"in a?u.highest-a.keys+1:Math.min(u.highest,g(e(u.highest)-s+1)),k=e(u.lowest),n=e(u.highest),h(u.highest)&&(n+=1),s=n-k+1,u.kw=(m-j)/s,u.kh=("height"in a?a.height-j:5*u.kw)+(j-u.lineWidth),u.bkw=4*u.kw/7,u.bkh=3*u.kh/5,u.halfex=j/2,u.leftpx=k*u.kw,u.rightpx=(n+1)*u.kw,u.ckw=(3*u.kw-2*u.bkw)/3,u.fkw=(4*u.kw-3*u.bkw)/4,b.__super__.constructor.call(this,{width:Math.ceil(u.rightpx-u.leftpx+j),height:Math.ceil(u.kh+j)}),"timbre"in a)p=a.timbre;else for(o in ef.defaultTimbre)o in a&&(p||(p={}),p[o]=a[o]);return p||(p="piano"),this.css({turtleTimbre:p}),this.on("noteon",function(a){t.drawkey(a.midi,d(a.midi))}),this.on("noteoff",function(a){t.drawkey(a.midi)}),this.draw(),this}function d(a){return k[(a%12+12)%12]}function e(a){return Math.floor((a+7)/12*7)}function g(a){return Math.ceil(a/7*12)-7}function h(a){return i(a)>=8}function i(a){return[1,8,2,9,3,4,10,5,11,6,12,7][(a%12+12)%12]}function j(a,b,c){var d,f,g,j,k,l,m;switch(l=b.halfex+b.kw*e(c)-b.leftpx,m=b.halfex,d=i(c),g=c===b.lowest,k=c===b.highest,f=0,j=0,d){case 1:j=b.kw-b.ckw;break;case 2:j=f=(b.kw-b.ckw)/2;break;case 3:f=b.kw-b.ckw;break;case 4:j=b.kw-b.fkw;break;case 5:f=b.fkw+b.bkw-b.kw,j=2*b.kw-2*b.fkw-b.bkw;break;case 6:f=2*b.kw-2*b.fkw-b.bkw,j=b.fkw+b.bkw-b.kw;break;case 7:f=b.kw-b.fkw;break;case 8:l+=b.ckw;break;case 9:l+=2*b.ckw+b.bkw-b.kw;break;case 10:l+=b.fkw;break;case 11:l+=2*b.fkw+b.bkw-b.kw;break;case 12:l+=3*b.fkw+2*b.bkw-2*b.kw}return g&&(f=0),k&&(j=0),h(c)?(a.moveTo(l,m+b.bkh),a.lineTo(l+b.bkw,m+b.bkh),a.lineTo(l+b.bkw,m),a.lineTo(l,m),a.closePath()):(a.moveTo(l,m+b.kh),a.lineTo(l+b.kw,m+b.kh),a.lineTo(l+b.kw,m+b.bkh),a.lineTo(l+b.kw-j,m+b.bkh),a.lineTo(l+b.kw-j,m),a.lineTo(l+f,m),a.lineTo(l+f,m+b.bkh),a.lineTo(l,m+b.bkh),a.closePath())}c(b,a),b.prototype.drawkey=function(a,b){var c,d=this._geom;if(d.lowest<=a&&a<=d.highest)return null==b&&(b=h(a)?d.blackColor:d.color),c=this.canvas().getContext("2d"),c.save(),c.beginPath(),j(c,d,a),c.fillStyle=b,c.strokeStyle=d.lineColor,c.lineWidth=d.lineWidth,c.fill(),c.stroke(),c.restore()},b.prototype.draw=function(){for(var a=this._geom.lowest;a<=this._geom.highest;++a)this.drawkey(a)};var k=["#db4437","#ff5722","#f4b400","#ffeb3b","#cddc39","#0f9d58","#00bcd4","#03a9f4","#4285f4","#673ab7","#9c27b0","#e91e63"];return b}(Ue),Ze=!1,$e=function(){for(var a="undefined"!=typeof Ie?Ie.navigator.userAgent:"",b=/OS X/.test(a),c=/Opera/.test(a),d=!/like Gecko/.test(a)&&!c,e={0:"null",1:"mouse1",2:"mouse2",3:"break",4:"mouse3",5:"mouse4",6:"mouse5",8:"backspace",9:"tab",12:"clear",13:"enter",16:"shift",17:"control",18:"alt",19:"pause",20:"capslock",21:"hangulmode",23:"junjamode",24:"finalmode",25:"kanjimode",27:"escape",28:"convert",29:"nonconvert",30:"accept",31:"modechange",27:"escape",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",41:"select",42:"print",43:"execute",44:"snapshot",45:"insert",46:"delete",47:"help",91:"meta",92:"meta",93:b?"meta":"menu",95:"sleep",106:"numpad*",107:"numpad+",108:"numpadenter",109:"numpad-",110:"numpad.",111:"numpad/",144:"numlock",145:"scrolllock",160:"shiftleft",161:"shiftright",162:"controlleft",163:"controlright",164:"altleft",165:"altright",166:"browserback",167:"browserforward",168:"browserrefresh",169:"browserstop",170:"browsersearch",171:"browserfavorites",172:"browserhome",173:b&&d?"-":"volumemute",174:"volumedown",175:"volumeup",176:"mediatracknext",177:"mediatrackprev",178:"mediastop",179:"mediaplaypause",180:"launchmail",181:"launchmediaplayer",182:"launchapp1",183:"launchapp2",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",223:"meta",224:"meta",226:"altgraph",229:"process",231:c?"`":"unicode",246:"attention",247:"crsel",248:"exsel",249:"eraseeof",250:"play",251:"zoom",252:"noname",253:"pa1",254:"clear"},f=48;91>f;++f)e[f]=String.fromCharCode(f).toLowerCase();for(f=96;106>f;++f)e[f]="numpad"+(f-96);for(f=112;136>f;++f)e[f]="f"+(f-111);return e}(),_e=function(){function a(a,c){return function(d){var e,f=d.which;a?e="mouse"+f:(!f&&d.whichSynth&&(f=d.whichSynth),e=$e[f],f>=160&&165>=f&&b(e.replace(/(?:left|right)$/,""),c)),b(e,c)}}function b(a,b){null!=a&&(b?h[a]=!0:delete h[a])}function c(){for(var a in h)delete h[a]}function d(a){c();for(var b in g)a?Ie.addEventListener(b,g[b],!0):Ie.removeEventListener(b,g[b])}function e(){var a,b=[];for(a in h)h[a]&&b.push(a);return b}function f(a){return Nb(),a?(a=a.replace(/\s/g,"").toLowerCase(),h[a]?!0:!1):e()}var g={mousedown:a(1,1),mouseup:a(1,0),keydown:a(0,1),keyup:a(0,0),blur:c},h={};return f.enable=d,f.list=e,f}(),af=null,bf={C:0,D:2,E:4,F:5,G:7,A:9,B:11,c:12,d:14,e:16,f:17,g:19,a:21,b:23},cf={"^":1,"":0,"=":0,_:-1},df=["C","^C","D","_E","E","F","^F","G","_A","A","_B","B","c","^c","d","_e","e","f","^f","g","_a","a","_b","b"],ef=function(){function a(a){this._atop=ac(),this._timbre=b(a,this._atop),this._queue=[],this._minQueueTime=1/0,this._maxScheduledTime=0,this._unsortedQueue=!1,this._startSet=[],this._finishSet={},this._cleanupSet=[],this._callbackSet=[],this._handlers={},this._now=null,_b()&&this.silence()}function b(a,b){a||(a={}),"string"==typeof a&&(a={wave:a});var c,d={},f=b&&b.wavetable&&b.wavetable[a.wave];for(c in e)a.hasOwnProperty(c)?d[c]=a[c]:f&&f.defs&&f.defs.hasOwnProperty(c)?d[c]=f.defs[c]:d[c]=e[c];return d}function c(){for(var a=ac().ac,b=2*a.sampleRate,c=a.createBuffer(1,b,a.sampleRate),d=c.getChannelData(0),e=0;b>e;e++)d[e]=2*Math.random()-1;return c}function d(a,b,d){if("noise"==b){var e=a.ac.createBufferSource();return e.buffer=c(),e.loop=!0,e}var f,g,h,i,j=a.wavetable,k=a.ac.createOscillator();try{if(j.hasOwnProperty(b)){if(g=j[b].wave,j[b].freq){h=0;for(f in j[b].freq)i=Number(f),d>i&&i>h&&(h=i,g=j[b].freq[h])}!k.setPeriodicWave&&k.setWaveTable?k.setWaveTable(g):k.setPeriodicWave(g)}else k.type=b}catch(l){window.console&&window.console.log(l),k.type="square"}return k.frequency.value=d,k}a.timeOffset=.0625,a.dequeueTime=.5,a.bufferSecs=2,a.toneLength=1,a.cleanupDelay=.1,a.prototype.setTimbre=function(a){this._timbre=b(a,this._atop)},a.prototype.getTimbre=function(a){return b(this._timbre,this._atop)},a.prototype.setVolume=function(a){this._out&&(isNaN(a)||(this._out.gain.value=a))},a.prototype.getVolume=function(a){return this._out?this._out.gain.value:0},a.prototype.silence=function(){var a,b,c,d=1;this._queue.length=0,this._minQueueTime=1/0,this._maxScheduledTime=0,this._startSet.length=0,b=this._finishSet,this._finishSet={},c=this._callbackSet,this._callbackSet=[],this._out&&(this._out.disconnect(),d=this._out.gain.value),this._atop=ac(),this._out=this._atop.ac.createGain(),this._out.gain.value=d,this._out.connect(this._atop.out);for(a in b)this._trigger("noteoff",b[a]);for(a=0;a0&&b.velocity>0){for(c=q.createGain(),c.gain.setValueAtTime(0,i),c.gain.linearRampToValueAtTime(p,k);k+1/32>m&&j>m+1/256;)m+=1/256,c.gain.linearRampToValueAtTime(p*(h.sustain+(1-h.sustain)*Math.exp((k-m)/l)),m);c.gain.setTargetAtTime(p*h.sustain,m,l),c.gain.setValueAtTime(p*(h.sustain+(1-h.sustain)*Math.exp((k-j)/l)),j),c.gain.linearRampToValueAtTime(0,n),c.connect(this._out),!h.cutoff&&!h.cutfollow||h.cutoff==1/0?e=c:(e=q.createBiquadFilter(),e.frequency.value=h.cutoff+b.frequency*h.cutfollow,e.Q.value=h.resonance,e.connect(c)),f=d(this._atop,h.wave,b.frequency),f.connect(e),f.start(i),f.stop(n),o&&(g=d(this._atop,h.wave,b.frequency*h.detune),g.connect(e),g.start(i),g.stop(n)),b.gainNode=c,b.oscillators=[f],o&&b.oscillators.push(g),b.cleanuptime=n}else b.duration=0;this._startSet.push(b)},a.prototype._truncateSound=function(b,c){if(c=g?n.gain.setValueAtTime(0,g):h>=g?n.gain.linearRampToValueAtTime(m*(g-f)/(h-f),g):n.gain.setValueAtTime(m*(e.sustain+(1-e.sustain)*Math.exp((h-g)/i)),g),n.gain.linearRampToValueAtTime(0,j),b.oscillators)for(d=0;da.bufferSecs);++b);if(b>0){for(c=this._queue.splice(0,b),b=0;b0?this._queue[0].time:1/0}}for(b=0;b=d&&(k.push({order:[d,0],f:this._trigger,t:this,a:["noteoff",f]}),f.cleanuptime!=1/0&&this._cleanupSet.push(f),delete this._finishSet[e]);for(b=0;b=d&&(k.push({order:[d,1],f:i.callback,t:null,a:[]}),this._callbackSet.splice(b,1),b-=1);for(b=0;b<=j&&(h=f=this._startSet[b],e=f.frequency,g=null,this._finishSet.hasOwnProperty(e)&&(g=this._finishSet[e],g.time0&&f.velocity>0&&g!==f&&(this._finishSet[e]=f,k.push({order:[f.time,2],f:this._trigger,t:this,a:["noteon",f]})));for(this._startPollTimer(),k.sort(function(a,b){return a.order[0]!=b.order[0]?a.order[0]-b.order[0]:a.order[1]-b.order[1]}),b=0;b0&&(g=Math.min(g,this._cleanupSet[0].cleanuptime+1)),g=Math.min(g,this._minQueueTime-a.dequeueTime),d=Math.max(.001,g-this._atop.ac.currentTime),isNaN(d)||d==1/0||(this._pollTimer=setTimeout(f,Math.round(1e3*d)))}},a.prototype.tone=function(b,c,d,f,g,h){if(this._atop){"object"==typeof b&&(null==d&&(d=b.velocity),null==c&&(c=b.duration),null==f&&(f=b.delay),null==g&&(g=b.timbre),null==h&&(h=b.origin),b=b.pitch);var i,j;if(b||(b="C"),isNaN(b)?(i=fc(b),j=dc(i)):(j=Number(b),0>j?(i=-j,j=dc(i)):i=ec(j)),g||(g=this._timbre),g!==this._timbre){var k,l=g;g={};for(k in e)k in l?g[k]=l[k]:g[k]=e[k]}var m=(this._atop.ac,this.now()),n=m+(f||0),o={time:n,on:!1,frequency:j,midi:i,velocity:null==d?1:d,duration:null==c?a.toneLength:c,timbre:g,instrument:this,gainNode:null,oscillators:null,cleanuptime:1/0,origin:h};n=1/8&&(q-=1/32),r=(o.velocity||1)*i*u.volume,this.tone(o.pitch,q,r,h,f,o));h+=n.time*p}v=Math.max(h,v)}}this._maxScheduledTime=Math.max(this._maxScheduledTime,this.now()+v),t&&this.schedule(v,t)};var e=a.defaultTimbre={wave:"square",gain:.1,attack:.002,decay:.4,decayfollow:0,sustain:0,release:.1,cutoff:0,cutfollow:0,resonance:0,detune:0};return a.pitchToMidi=function(a){return"string"==typeof a?fc(a):a},a.midiToPitch=function(a){return"number"==typeof a?gc(a):a},a}(),ff=/^([A-Za-z]):\s*(.*)$/,gf=/(?:\[[A-Za-z]:[^\]]*\])|\s+|%[^\n]*|![^\s!:|\[\]]*!|\+[^+|!]*\+|[_<>@^]?"[^"]*"|\[|\]|>+|<+|(?:(?:\^+|_+|=|)[A-Ga-g](?:,+|'+|))|\(\d+(?::\d+){0,2}|\d*\/\d+|\d+\/?|\/+|[xzXZ]|\[?\|\]?|:?\|:?|::|./g;a.extend(!0,a,{cssHooks:{turtlePenStyle:Ra(),turtlePenDown:Sa(),turtleSpeed:nb(),turtleEasing:ob(),turtleForward:rb(),turtleTurningRadius:Qa(),turtlePosition:zb("turtlePosition","tx","ty",!0),turtlePositionX:sb("tx",parseFloat,"px",!0),turtlePositionY:sb("ty",parseFloat,"px",!0),turtleRotation:sb("rot",vb,"deg",!0),turtleScale:zb("turtleScale","sx","sy",!1),turtleScaleX:sb("sx",h,"",!1),turtleScaleY:sb("sy",h,"",!1),turtleTwist:sb("twi",xa,"deg",!1),turtleHull:oa(),turtleTimbre:Xb(),turtleVolume:Yb()},cssNumber:{turtleRotation:!0,turtleSpeed:!0,turtleScale:!0,turtleScaleX:!0,turtleScaleY:!0,turtleTwist:!0},support:{turtle:!0}}),a.extend(!0,a.fx,{step:{turtlePosition:yb("turtlePosition",!0),turtleRotation:wb("turtleRotation"),turtleScale:yb("turtleScale",!1),turtleTwist:wb("turtleTwist")},speeds:{turtle:0}}),oc.helptext=[];var hf={rt:uc("rt",1,["rt(degrees) Right turn. Pivots clockwise by some degrees: rt 90 ","rt(degrees, radius) Right arc. Pivots with a turning radius: rt 90, 50 "],Ac),lt:uc("lt",1,["lt(degrees) Left turn. Pivots counterclockwise by some degrees: lt 90 ","lt(degrees, radius) Left arc. Pivots with a turning radius: lt 90, 50 "],Ac),fd:uc("fd",1,["fd(pixels) Forward. Moves ahead by some pixels: fd 100 "],Bc),bk:uc("bk",1,["bk(pixels) Back. Moves in reverse by some pixels: bk 100 "],Bc),slide:uc("slide",1,["move(x, y) Slides right x and forward y pixels without turning: slide 50, 100 "],Cc),movexy:uc("movexy",1,["movexy(x, y) Changes graphing coordinates by x and y: movexy 50, 100 "],Dc),moveto:uc("moveto",1,["moveto(x, y) Move to graphing coordinates (see getxy ): moveto 50, 100 ","moveto(obj) Move to page coordinates or an object on the page (see pagexy ): moveto lastmousemove "],Ec),jump:uc("jump",1,["jump(x, y) Move without drawing (compare to slide ): jump 0, 50 "],Fc(Cc)),jumpxy:uc("jumpxy",1,["jumpxy(x, y) Move without drawing (compare to movexy ): jump 0, 50 "],Fc(Dc)),jumpto:uc("jumpto",1,["jumpto(x, y) Move without drawing (compare to moveto ): jumpto 50, 100 "],Fc(Ec)),turnto:uc("turnto",1,["turnto(degrees) Turn to a direction. North is 0, East is 90: turnto 270","turnto(x, y) Turn to graphing coordinates: turnto 50, 100 ","turnto(obj) Turn to page coordinates or an object on the page: turnto lastmousemove "],function(b,c,d){a.isNumeric(d)&&a.isNumeric(c)&&(c=[c,d],d=null);var e=Df;return this.plan(function(f,g){if(b.appear(f),a.isWindow(g)||9===g.nodeType)return void b.resolve(f);var h,i,j,k=null,l=null,m=null;if(a.isNumeric(c))i=wa(c),j=Y(g),l={pageX:j.pageX+1024*Math.sin(i),pageY:j.pageY-1024*Math.cos(i)},k=d;else if(a.isArray(c))m=W(g),m[0]-=c[0],m[1]-=c[1];else if(mb(c))l=c;else try{l=a(c).pagexy()}catch(n){return void b.resolve(f)}m||(m=W(g,l));var o=va(Math.atan2(-m[0],-m[1]));h=ra(g,!0),null!==k&&(i=wa(h.rot),o=C(h.rot,o,null===k?360:k)),o=h.rot+xa(o-h.rot);var p=this.css("turtleTurningRadius");this.css({turtleTurningRadius:0}),this.animate({turtleRotation:o},pb(g,e),qb(g)),this.plan(function(){this.css({turtleTurningRadius:p}),b.resolve(f)})}),this}),home:uc("home",0,["home() Goes home. Jumps to the center without drawing: do home "],function(b,c){return this.plan(function(d,e){b.appear(d);var f=this.css("turtlePenDown"),g=this.css("turtleTurningRadius"),h=c||V(e);this.css({turtlePenDown:"up",turtleTurningRadius:0}),this.css({turtlePosition:U(e,a(h).pagexy(),null,0,0),turtleRotation:0,turtleScale:1}),this.css({turtlePenDown:f,turtleTurningRadius:g}),b.resolve(d)}),this}),copy:uc("copy",0,["copy() makes a new turtle that is a copy of this turtle."],function(b){var c=this.clone().insertAfter(this);return c.hide(),this.plan(function(d,e){b.appear(d);var f=Oa(this),g=Oa(c);for(var h in f)g[h]=f[h];c.attr("style",this.attr("style"));for(var i in a.cssHooks){var j=this.css(i);c.css(i,j)}var k=this.prop("attributes");for(var l in k)c.attr(k[l].name,k[l].value);var m=c.canvas(),n=this.canvas();if(m&&n){m.width=n.width,m.height=n.height;var o=m.getContext("2d");o.drawImage(n,0,0)}c.show(),b.resolve(d)}),lc(c,this),c}),pen:uc("pen",1,["pen(color, size) Selects a pen. Chooses a color and/or size for the pen: pen red ; pen 0 ; pen erase ; pen blue, 5 .","pen(on-or-off) Turns the pen on or off: pen off ; pen on ."],function(b,c,d){var e=Md(arguments,1,{lineCap:/^(?:butt|square|round)$/,lineJoin:/^(?:bevel|round|miter)$/,lineWidth:a.isNumeric,penStyle:"*"});c=e.penStyle,c&&"function"==typeof c&&(c.helpname||c.name)&&(c=c.helpname||c.name),0===e.lineWidth||null===c?c="none":c===He?c="black":a.isPlainObject(c)&&(c=La(c));var f=Df;return this.plan(function(a,d){b.appear(a);var g=!L(d)&&!pc(this),h=g&&Ka(this.css("turtlePenStyle")),i=h&&"down"==this.css("turtlePenDown"),j=!1;if(c===!1||c===!0||"down"==c||"up"==c?(this.css("turtlePenDown",c),j=!0):(e.lineWidth&&(c+=";lineWidth:"+e.lineWidth),e.lineCap&&(c+=";lineCap:"+e.lineCap),e.lineJoin&&(c+=";lineJoin:"+e.lineJoin),this.css("turtlePenStyle",c),this.css("turtlePenDown","none"==c?"up":"down")),g){var k=Ka(this.css("turtlePenStyle")),l=k&&(k.strokeStyle||k.savePath&&"gray")||h&&h.strokeStyle||"gray",m={},n=k&&"down"==this.css("turtlePenDown"),o=new We(l+" pencil",this.parent()),p=this.height();o.css({zIndex:1,turtlePosition:U(o.get(0),this.pagexy(),null,0,0),turtleRotation:this.css("turtleRotation"),turtleSpeed:1/0}),i?n||(m.turtleForward="+="+p,m.opacity=0):(o.css({turtleForward:"+="+p,opacity:0}),n&&(m.turtleForward="-="+p,m.opacity=1)),h&&!k&&"down"==i?(m.turtleForward="+="+p,m.opacity=0):h==k||h&&k&&h.strokeStyle==k.strokeStyle||(o.css({opacity:0}),m.opacity=1),o.animate(m,pb(d,f)),this.queue(function(a){o.done(function(){o.remove(),a()})})}this.plan(function(){b.resolve(a)})}),this}),fill:uc("fill",0,["fill(color) Fills a path traced using pen path : pen path; rt 100, 90; fill blue "],function(b,c){c?a.isPlainObject(c)&&(c=La(c)):c="none";var d=Ka(c,"fillStyle");return this.plan(function(a,c){b.appear(a),cb(c,d),b.resolve(a)}),this}),dot:uc("dot",0,["dot(color, diameter) Draws a dot. Color and diameter are optional: dot blue "],Lc(Mc)),box:uc("box",0,["box(color, size) Draws a box. Color and size are optional: dot blue "],Lc(Nc)),arrow:uc("arrow",0,["arrow(color, size) Draws an arrow. arrow red, 100 "],Lc(Oc)),mirror:uc("mirror",1,["mirror(flipped) Mirrors the turtle across its main axis, or unmirrors if flipped if false. mirror(true) "],function(b,c){return this.plan(function(d,e){b.appear(d);var f=a.map(a.css(e,"turtleScale").split(" "),parseFloat);1===f.length&&f.push(f[0]),f[0]*f[1]<0==!c&&(f[0]=-f[0],this.css("turtleScale",f.join(" "))),b.resolve(d)}),this}),twist:uc("twist",1,["twist(degrees) Set the primary direction of the turtle. Allows use of images that face a different direction than 'up': twist(-90) "],function(b,c){return this.plan(function(d,e){b.appear(d),a.isWindow(e)||9===e.nodeType||(this.css("turtleTwist",c),b.resolve(d))}),this}),scale:uc("scale",1,["scale(factor) Scales all motion up or down by a factor. To double all drawing: scale(2) "],Hc),grow:uc("grow",1,["grow(factor) Changes the size of the element by a factor. To double the size: grow(2) "],Ic),pause:uc("pause",1,["pause(seconds) Pauses some seconds before proceeding. fd 100; pause 2.5; bk 100 ","pause(turtle) Waits for other turtles to be done before proceeding. t = new Turtle().fd 100; pause t; bk 100 "],function(b,c){var d=null,e=null;return c&&a.isFunction(c.done)?(d=c,e=c.done):a.isFunction(c)&&(e=c),e?this.queue(function(){var b=this;e.call(d,function(){var c=b;b=null,c&&a.dequeue(c)})}):this.plan(function(a,d){b.appear(a),rc(d,c),this.plan(b.resolver(a))}),this}),st:uc("st",0,["st() Show turtle. The reverse of ht() . do st "],function(a){return this.plan(function(b){a.appear(b),this.show(),a.resolve(b)}),this}),ht:uc("ht",0,["ht() Hide turtle. The turtle can be shown again with st() . do ht "],function(a){return this.plan(function(b){a.appear(b),this.hide(),a.resolve(b)}),this}),pu:function(){return this.pen(!1,sc(arguments,0))},pd:function(){return this.pen(!0,sc(arguments,0))},pe:function(){return this.pen("erase",sc(arguments,0))},pf:function(){return this.pen("path",sc(arguments,0))},clip:uc("clip",1,["Clips tranparent bits out of the image of the sprite, and sets the hit region."],function(b,c){return null==c&&(c=.125),this.plan(function(d,e){if(b.appear(d),"CANVAS"==e.tagName){var f=De(e,c),g=a(e),h=y(e);Fe(e,f),Ge(f,parseFloat(g.css("width"))/e.width,parseFloat(g.css("height"))/e.height,-h[0],-h[1]),g.css("turtleHull",f)}b.resolve(d)})}),say:uc("say",1,['say(words) Say something. Use English words.say "Let\'s go!" '],function(a,b){return this.plan(function(c,d){a.appear(c),this.queue(function(d){Sc(b,function(){a.resolve(c),d()})})}),this}),play:uc("play",1,['play(notes) Play notes. Notes are specified in ABC notation . play "de[dBFA]2[cGEC]4" '],function(b,c){return this.plan(function(c,d){b.appear(c),this.queue(function(e){var f=Zb(d),g=a.makeArray(b.args),h=!0,i=function(){b.resolve(c),e()};g.length>0&&a.isPlainObject(g[0])&&g[0].hasOwnProperty("wait")&&(h=g[0].wait),h&&g.push(i),f.play.apply(f,g),h||i()})}),this}),tone:zc("tone",["tone(freq) Immediately sound a tone. tone(freq, 0) Stop sounding the tone. tone(freq, v, secs) Play a tone with a volume and duration. Frequency may be a number in Hz or a letter pitch. tone 440, 5 "],function(a,b){var c=arguments;return this.each(function(a,b){var d=Zb(b);d.tone.apply(d,c)})}),silence:zc("silence",["silence() immediately silences sound from play() or tone()."],function(){return this.each(function(a,b){var c=Zb(b);c.silence()})}),speed:uc("speed",1,["speed(persec) Set one turtle's speed in moves per second: turtle.speed 60 "],function(a,b){return this.plan(function(c,d){a.appear(c),this.css("turtleSpeed",b),this.plan(function(){a.resolve(c)})}),this}),wear:uc("wear",1,["wear(color) Sets the turtle shell color: wear turquoise ","wear(url) Sets the turtle image url: wear 'http://bit.ly/1bgrQ0p' "],function(b,c,d){if(("object"==typeof c||"number"==typeof c)&&"string"==typeof d){var e=d;d=c,c=e}"number"==typeof d&&(d={height:d});var f=nd(c,"turtle"),g=Df;return f?(d&&a.extend(f.css,d),this.plan(function(a,c){b.appear(a),this.css({backgroundImage:"none"});var d=!1,e=null;hb(this,f,function(){d=!0;var a=e;a&&(e=null,a())}),pc(this)||this.delay(pb(c,g)),d||this.pause({done:function(a){d?a():e=a}}),this.plan(function(){b.resolve(a)})}),this):this}),saveimg:uc("saveimg",1,["saveimg(filename) Saves the turtle's image as a file. t.saveimg 'mypicture.png' "],function(a,b){return this.plan(function(c,d){a.appear(c);var e=!1;b||(b="img");var f=this.canvas();if(f){var g=f.toDataURL(),h=/^data:image\/(\w+);base64,(.*)$/i.exec(g);h?(h[1]&&b.toLowerCase().lastIndexOf("."+h[1].toLowerCase())!=Math.max(0,b.length-h[1].length-1)&&(b+="."+h[1]),e=!0,sf.save(b,atob(h[2]),function(){a.resolve(c)})):Sf.html('Cannot saveimg: canvas toDataURL did not work as expected. ')}else Sf.html('Cannot saveimg: not a canvas ');e||a.resolve(c)})}),drawon:uc("drawon",1,["drawon(canvas) Switches to drawing on the specified canvas. A = new Sprite('100x100'); drawon A; pen red; fd 50; done -> A.rt 360 "],function(b,c){return this.each(function(){var a=Oa(this);a.drawOnCanvasSync&&lc(this,a.drawOnCanvasSync),a.drawOnCanvasSync=c}),lc(c,this),this.plan(function(d,e){b.appear(d);var f=Oa(e);c&&c!==Ie?c.jquery&&a.isFunction(c.canvas)?f.drawOnCanvas=c.canvas():c.tagName&&"CANVAS"==c.tagName?f.drawOnCanvas=c:(1==c.nodeType||9==c.nodeType)&&(f.drawOnCanvas=a(c).canvas()):f.drawOnCanvas=null,b.resolve(d)})}),label:uc("label",1,["label(text) Labels the current position with HTML: label 'remember' ","label(text, styles, labelsite) Optional position specifies 'top', 'bottom', 'left', 'right', and optional styles is a size or CSS object: label 'big', { color: red, fontSize: 100 }, 'bottom' "],function(b,c,d,e){if((!e||"string"==typeof e)&&(a.isNumeric(d)||a.isPlainObject(d))){var f=e;e=d,d=f}a.isNumeric(e)&&(e={fontSize:e}),null==d&&(d=e&&"labelSide"in e?e.labelSide:e&&"label-side"in e?e["label-side"]:d="rotated scaled");var g=Df;return this.plan(function(f,h){b.appear(f);for(var i={},j=this.prop("style"),k=0;kreload() Does a reload, recycling content (cycling animated gifs)."],function(b){return this.plan(function(c,d){if(b.appear(c),a.isWindow(d)||9===d.nodeType)return Ie.location.reload(),void b.resolve(c);if(d.src){var e=d.src;d.src="",d.src=e}b.resolve(c)}),this}),hatch:function(b,c){if(this.length){c!==He||a.isNumeric(b)||(c=b,b=1);var d=this[0];if(a.isWindow(d)||9===d.nodeType?d=za():/^(?:br|img|input|hr|canvas)$/i.test(d.tagName)&&(d=d.parentElement),1===b)return pd("function"==typeof c?c(0):c,d,"turtle");for(var e=0,f=[];b>e;++e)f.push(pd("function"==typeof c?c(e):c,d,"turtle")[0]);return a(f)}},pagexy:vc("pagexy",["pagexy() Page coordinates {pageX:, pageY}, top-left based: c = pagexy(); fd 500; moveto c "],function(){if(this.length){var a=Y(this[0]);return{pageX:a.pageX,pageY:a.pageY}}}),getxy:vc("getxy",["getxy() Graphing coordinates [x, y], center-based: v = getxy(); move -v[0], -v[1] "],function(){return this.length?W(this[0]):void 0}),direction:vc("direction",["direction() Current turtle direction. North is 0; East is 90: direction() ","direction(obj) direction(x, y) Returns the direction from the turtle towards an object or coordinate. Also see turnto : direction lastclick "],function(b,c){if(this.length){var d,e=this[0],f=b;if(f!==He){if(d=a(e).pagexy(),a.isNumeric(c)&&a.isNumeric(b)&&(f=[b,c]),a.isArray(f)&&(f=X(e,[f])[0]),!mb(f))try{f=a(f).pagexy()}catch(g){}return f?va(Math.atan2(f.pageX-d.pageX,d.pageY-f.pageY)):NaN}return a.isWindow(e)||9===e.nodeType?0:aa(e)}}),distance:vc("distance",["distance(obj) Returns the distance from the turtle to another object: distance lastclick ","distance(x, y) Returns the distance from the turtle to graphing coorindates: distance(100, 0) "],function(b,c){if(this.length){var d,e,f=this[0],g=a(f).pagexy();if(a.isNumeric(c)&&a.isNumeric(b)&&(b=[b,c]),a.isArray(b)&&(b=X(f,[b])[0]),!mb(b))try{b=a(b).pagexy()}catch(h){}return b?(d=b.pageX-g.pageX,e=b.pageY-g.pageY,Math.sqrt(d*d+e*e)):NaN}}),canvas:zc("canvas",["turtle.canvas() The canvas for the turtle image. Draw on the turtle: c = turtle.canvas().getContext('2d'); c.fillStyle = red; c.fillRect(10, 10, 30, 30) "],function(){return this.filter("canvas").get(0)||this.find("canvas").get(0)}),imagedata:zc("imagedata",["imagedata() Returns the image data for the turtle. imdat = imagedata(); write imdat.data.length, 'bytes' ","imagedata(imdat) Sets the image data for the turtle. imagedata({width: 1, height:1, data:[255,0,0,255]}); "],function(b){var c=this.canvas();if(!c){if(b)throw new Error("can only set imagedata on a canvas like a Sprite");var d=this.filter("img").get(0);if(!d)return;c=Ga(d.naturalWidth,d.naturalHeight),c.getContext("2d").drawImage(d,0,0)}var e=c.getContext("2d");if(!b)return e.getImageData(0,0,c.width,c.height);if(!(b instanceof ImageData)){if("object"!=typeof b||!a.isNumeric(b.width)||!a.isNumeric(b.height)||!(a.isArray(b.data)||b.data instanceof Uint8ClampedArray||b.data instanceof Uint8Array))return;for(var f=e.createImageData(Math.round(b.width),Math.round(b.height)),g=Math.min(b.data.length,f.data.length),h=0;g>h;++h)f.data[h]=b.data[h];b=f}if(b.width!=c.width||b.height!=c.height){var i=y(c);c.width=b.width,c.height=b.height;var j=y(c);Lb(c,i,j),a(c).css("turtleHull","auto"),e=c.getContext("2d")}e.putImageData(b,0,0)}),cell:zc("cell",["cell(r, c) Row r and column c in a table. Use together with the table function: g = table 8, 8; g.cell(0,2).text 'hello' "],function(b,c){var d=this.find(a.isNumeric(b)?"tr:nth-of-type("+(b+1)+")":"tr");return d.find(a.isNumeric(c)?"td:nth-of-type("+(c+1)+")":"td")}),shown:vc("shown",["shown() True if turtle is shown, false if hidden: do ht; write shown() "],function(){var a=this.get(0);return a&&!L(a)}),hidden:vc("hidden",["hidden() True if turtle is hidden: do ht; write hidden() "],function(){var a=this.get(0);return!a||L(a)}),inside:vc("inside",["inside(obj) True if the turtle is encircled by obj: inside(window) "],function(b){if(!b)return!1;if("string"==typeof b&&(b=a(b)),b.jquery){if(!b.length||L(b[0]))return!1;b=b[0]}for(var c,d=N(b),e=null,f=!1,g=!0,h=0;g&&htouches(obj) True if the turtle touches obj: touches(lastclick) ","touches(color) True if the turtle touches a drawn color: touches red "],function(b,c){if(!this.length||L(this[0]))return!1;if("function"==typeof b&&cd(b.helpname)&&(b=b.helpname),"color"==b||cd(b))return gb(this[0],"color"==b?null:b);if(a.isNumeric(b)&&a.isNumeric(c)&&(b=[b,c]),a.isArray(b)&&2==b.length&&a.isNumeric(b[0])&&a.isNumeric(b[1])&&(b=X(this[0]||document.body,[b])[0]),!b)return!1;"string"==typeof b&&(b=a(b)),b.jquery||a.isArray(b)||(b=[b]);for(var d,e,f,g,h,i,j=!1,k=0;!j&&kwithin(distance, obj) Filters elements to those within distance of obj: $('.turtle').within(100, lastclick) "],function(a,b,c){return Mb(this,!0,a,b,c)}),notwithin:vc("notwithin",["within(distance, obj) Filters elements to those further than distance of obj: $('.turtle').notwithin(100, lastclick) "],function(a,b,c){return Mb(this,!1,a,b,c)}),nearest:vc("nearest",["nearest(obj) Filters elements to those nearest obj$('.turtle').neareest(lastclick) "],function(b,c){var d,e,f,g=[],h=1/0;if(d=a.isNumeric(d)&&a.isNumeric(c)?[b,c]:b,a.isArray(d)&&(d=X(this[0]||document.body,[d])[0]),!mb(d))try{d=a(d).pagexy()}catch(i){d=null}for(f=0;f=m&&(h>m&&(h=m,g.length=0),g.push(this[f]))}return a(g)}),done:zc("done",["done(fn) Calls fn when animation is complete. Use with await: await done defer() "],function(a){var b=this;return this.promise().done(function(){if(b){var c=b;Me+=1,setTimeout(function(){Me-=1,c.promise().done(a)},0)}else a.apply(this,arguments)})}),plan:zc("plan",["plan(fn) Runs fn in the animation queue. For planning logic: write getxy(); fd 50; plan -> write getxy(); bk 50"],function(c,d,e){function f(f,g,h){var i=e?function(){d.apply(a(f),e)}:function(){d.call(a(f),g,f)},j=(h.length&&h[h.length-1],function(){var d=a.queue(this,c),e=[];"inprogress"===d[0]&&e.unshift(d.shift()),a.queue(f,c,e),i(),Array.prototype.push.apply(a.queue(f,c),d),b(f,c)});j.finish=i,a.queue(f,c,j)}a.isFunction(c)&&(e=d,d=c,c="fx");for(var g,h=this.length,i=0;h>i;++i){g=this[i],Uc(g,c);var j=a.queue(g,c);j.length?f(g,i,j):e?d.apply(a(g),e):d.call(a(g),i,g)}return this})},jf={},kf=0,lf=null,mf=null;Xc(hf,"move","slide"),Xc(hf,"direct","plan"),Xc(hf,"enclosedby","inside"),Xc(hf,"bearing","direction"),a.fn.extend(hf);var nf="data:image/gif;base64,R0lGODlhKAAwAPIFAAAAAAFsOACSRTCuSICAgP///wAAAAAAACH5BAlkAAYAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAKAAwAAAD72i6zATEgBCAebHpzUnxhDAMAvhxKOoV3ziuZyo3RO26dTbvgXj/gsCO9ysOhENZz+gKJmcUkmA6PSKfSqrWieVtuU+KGNXbXofLEZgR/VHCgdua4isGz9mbmM6U7/94BmlyfUZ1fhqDhYuGgYqMkCOBgo+RfWsNlZZ3ewIpcZaIYaF6XaCkR6aokqqrk0qrqVinpK+fsbZkuK2ouRy0ob4bwJbCibthh6GYebGcY7/EsWqTbdNG1dd9jnXPyk2d38y0Z9Yub2yA6AvWPYk+zEnkv6xdCoPuw/X2gLqy9vJIGAN4b8pAgpQOIlzI8EkCACH5BAlkAAYALAAAAAAoADAAAAPuaLrMBMSAEIB5senNSfGEMAwC+HEo6hXfOK5nKjdE7bp1Nu+BeP+CwI73Kw6EQ1nP6AomZxSSYDo9Ip9KqtaJ5W25Xej3qqGYsdEfZbMcgZXtYpActzLMeLOP6c7f3nVNfEZ7TXSFg4lyZAYBio+LZYiQfHMbc3iTlG9ilGpdjp4ujESiI6RQpqegqkesqqhKrbEpoaa0KLaiuBy6nrxss6+3w7tomo+cDXmBnsoLza2nsb7SN2tl1nyozVOZTJhxysxnd9XYCrrAtT7KQaPruavBo2HQ8xrvffaN+GV5/JbE45fOG8Ek5Q4qXHgwAQA7",of={click:1,dblclick:1,mouseup:1,mousedown:1,mousemove:1},pf=null,qf=[],rf=!1,sf={interrupt:zc("interrupt",["interrupt() Interrupts and aborts all turtle commands."],function(b){if("reset"==b)return void(Le=!1);if("test"==b)return Le?!1:Cf?!0:a.timers.length?!0:Af.length?!0:Me?!0:Yc()?!0:a(":animated").length?!0:a(".turtle").filter(function(){return a.queue(this).length>0}).length>0?!0:a(".turtleinput").filter(function(){return!a(this).prop("disabled")}).length>0?!0:yc()?!0:!1;a(":animated,.turtle").clearQueue().stop(),bc(),a(".turtleinput").prop("disabled",!0),a(Ie).off(".turtleevent"),a("*").not("#_testpanel *").map(function(b,c){a._data(c,"events",null)}),Le=!0,ud(null,null),sd();for(var c=a.timers.length-1;c>=0;--c)a.timers[c].anim&&a.timers[c].anim.elem&&a(a.timers[c].anim.elem).stop(!0,!0);var d=b?"'"+b+"'":"";throw new Error("interrupt("+d+") called")}),cs:wc("cs",["cs() Clear screen. Erases both graphics canvas and body text: do cs "],function(){db()}),cg:wc("cg",["cg() Clear graphics. Does not alter body text: do cg "],function(){db("canvas labels")}),ct:wc("ct",["ct() Clear text. Does not alter graphics canvas: do ct "],function(){db("text")}),canvas:zc("canvas",["canvas() Returns the raw turtle canvas. c = canvas().getContext('2d'); c.fillStyle = red; c.fillRect(100,100,200,200) "],function(){return Fa()}),sizexy:zc("sizexy",["sizexy() Get the document pixel [width, height]. [w, h] = sizexy(); canvas('2d').fillRect(0, 0, w, h) "],Ia),forever:zc("forever",["forever(fn) Calls fn repeatedly, forever. forever -> fd 2; rt 2 ","forever(fps, fn) Calls fn repeating fps per second. forever 2, -> fd 25; dot blue "],rd),stop:zc("stop",["stop() stops the current forever loop. forever -> fd 10; if not inside window then stop() ","stop(fn) stops the forever loop corresponding to fn.","Use break to stop a for or while loop."],td),tick:zc("tick",["tick(fps, fn) Calls fn fps times per second until tick is called again: c = 10; tick 1, -> c and write(c--) or tick() "],function(b,c){if(Yc()){var d=a(pf);d.plan(function(){ud(b,c)})}else ud(b,c)}),speed:wc("speed",["speed(mps) Sets default turtle speed in moves per second: speed Infinity "],function(a){vd(a)}),say:zc("say",['say(words) Say something. Use English words.say "Let\'s go!" '],function(b){if(pf){var c=a(pf);c.say.call(c,b)}else{var d=tc(null,"say",arguments,0);d.appear(null),Sc(b,function(){d.resolve(null)}),d.exit()}}),play:zc("play",['play(notes) Play notes. Notes are specified in ABC notation . play "de[dBFA]2[cGEC]4" '],function(){if(pf){var b=a(pf);b.play.apply(b,arguments)}else{var c=tc(null,"play",arguments,0);c.appear(null);var d=$b(),e=a.makeArray(c.args);e.push(function(){c.resolve(null)}),d.play.apply(d,e),c.exit()}}),tone:zc("tone",["tone(freq) Immediately sound a tone. tone(freq, 0) Stop sounding the tone. tone(freq, v, secs) Play a tone with a volume and duration. Frequency may be a number in Hz or a letter pitch. tone 440, 5 "],function(){if(pf){var b=a(pf);b.tone.apply(b,arguments)}else{var c=$b();c.play.apply(c)}}),silence:zc("silence",["silence() Immediately silences sound from play() or tone()."],function(){if(pf){var b=a(pf);b.silence()}else{var c=$b();c.silence()}}),sync:zc("sync",["sync(t1, t2, t3,...) Selected turtles wait for each other to stop."],lc),remove:zc("remove",["remove(t) Remove selected turtles."],mc),done:zc("done",["done(fn) Calls fn when animation is complete. Use with await: await done defer() "],function(b){var c=a(".turtle");return c.promise().done(function(){if(c){var a=c;Me+=1,setTimeout(function(){Me-=1,a.promise().done(b)},0)}else b.apply(this,arguments)})}),load:zc("load",["load(url, cb) Loads data from the url and passes it to cb. load 'intro', (t) -> write 'intro contains', t "],function(b,c){var d;return a.ajax(Eb(b,"load"),{async:!!c,complete:function(e){try{if(d=e.responseObject=JSON.parse(e.responseText),"string"==typeof d.data&&"string"==typeof d.file){if(d=d.data,/\.json(?:$|\?|\#)/.test(b))try{d=JSON.parse(d)}catch(f){}}else a.isArray(d.list)&&"string"==typeof d.directory?d=d.list:d.error&&(d=null)}catch(f){null==d&&e&&e.responseText&&(d=e.responseText)}c&&c(d,e)}}),d}),save:zc("save",["save(url, data, cb) Posts data to the url and calls when done. save 'intro', 'pen gold, 20\\nfd 100\\n' "],function(b,c,d){if(!b)throw new Error("Missing url for save");var e,f={};if(b=Eb(b,"save"),/\.json(?:$|\?|\#)/.test(b)&&(c=JSON.stringify(c,null,2)),"string"==typeof c||"number"==typeof c)f.data=c;else for(e in c)c.hasOwnProperty(e)&&("string"==typeof c[e]?f[e]=c[e]:f[e]=JSON.stringify(c[e]));if(f&&!f.key){var g=Gb();g&&g.key&&g.user==Db(b)&&(f.key=g.key)}a.ajax(Eb(b,"save"),{type:"POST",data:f,complete:function(a){var b;try{b=JSON.parse(a.responseText)}catch(c){null==b&&a&&a.responseText&&(b=a.responseText)}d&&d(b,a)}})}),append:wc("append",["append(html) Appends text to the document without a new line. append 'try this twice...' "],function(b){a.fn.append.apply(a("body"),arguments)}),type:wc("type",["type(text) Types preformatted text like a typewriter. type 'Hello!\n' "],Cd),typebox:wc("typebox",["typebox(clr) Draws a colored box as typewriter output. typebox red "],function(a,b){null!=b||null==a||cd(a)||(b=a,a=null),Dd(a,b)}),typeline:wc("typebox",["typeline() Same as type '\\n'. typeline() "],function(a){Cd((a||"")+"\n")}),write:wc("write",["write(html) Writes a line of text. Arbitrary HTML may be written: write 'Hello, world!' "],Ed,function(){return Fd(Array.prototype.join.call(arguments," "),"div")}),read:wc("read",["read(fn) Reads text or numeric input. Calls fn once: read (x) -> write x ","read(html, fn) Prompts for input: read 'Your name?', (v) -> write 'Hello ' + v "],Ed,function(a,b){return Id(a,b,0)}),readnum:wc("readnum",["readnum(html, fn) Reads numeric input. Only numbers allowed: readnum 'Amount?', (v) -> write 'Tip: ' + (0.15 * v) "],Ed,function(a,b){return Id(a,b,"number")}),readstr:wc("readstr",["readstr(html, fn) Reads text input. Never converts input to a number: readstr 'Enter code', (v) -> write v.length + ' long' "],Ed,function(a,b){return Id(a,b,"text")}),listen:wc("listen",["listen(html, fn) Reads voice input, if the browser supports it:listen 'Say something', (v) -> write v "],Ed,function(a,b){
+return Id(a,b,"voice")}),menu:wc("menu",["menu(map) shows a menu of choices and calls a function based on the user's choice: menu {A: (-> write 'chose A'), B: (-> write 'chose B')} "],Ed,Gd),button:wc("button",["button(text, fn) Writes a button. Calls fn whenever the button is clicked: button 'GO', -> fd 100 "],Ed,Hd),table:wc("table",["table(m, n) Writes m rows and c columns. Access cells using cell : g = table 8, 8; g.cell(2,3).text 'hello' ","table(array) Writes tabular data. Each nested array is a row: table [[1,2,3],[4,5,6]] "],Ed,Kd),img:wc("img",["img(url) Writes an image with the given address. Any URL can be provided. A name without slashes will be treated as '/img/name'.t = img 'tree' "],Ed,Jd),random:zc("random",["random(n) Random non-negative integer less than n: write random 10 ","random(list) Random member of the list: write random ['a', 'b', 'c'] ","random('position') Random page position: moveto random 'position' ","random('color') Random color: pen random 'color' "],qd),rgb:zc("rgb",["rgb(r,g,b) Makes a color out of red, green, and blue parts. pen rgb(150,88,255) "],function(a,b,c){return Ld("rgb",[Math.max(0,Math.min(255,Math.floor(a))),Math.max(0,Math.min(255,Math.floor(b))),Math.max(0,Math.min(255,Math.floor(c)))])}),hatch:function(b,c){return a(document).hatch(b,c)},rgba:zc("rgba",["rgba(r,g,b,a) Makes a color out of red, green, blue, and alpha. pen rgba(150,88,255,0.5) "],function(a,b,c,d){return Ld("rgba",[Math.max(0,Math.min(255,Math.floor(a))),Math.max(0,Math.min(255,Math.floor(b))),Math.max(0,Math.min(255,Math.floor(c))),d])}),hsl:zc("hsl",["hsl(h,s,l) Makes a color out of hue, saturation, and lightness. pen hsl(120,0.65,0.75) "],function(a,b,c){return Ld("hsl",[a,(100*b).toFixed(0)+"%",(100*c).toFixed()+"%"])}),hsla:zc("hsla",["hsla(h,s,l,a) Makes a color out of hue, saturation, lightness, alpha. pen hsla(120,0.65,0.75,0.5) "],function(a,b,c,d){return Ld("hsla",[a,(100*b).toFixed(0)+"%",(100*c).toFixed(0)+"%",d])}),click:xc("click",["click(fn) Calls fn(event) whenever the mouse is clicked. click (e) -> moveto e; label 'clicked' "]),dblclick:xc("dblclick",["dblclick(fn) Calls fn(event) whenever the mouse is double-clicked. dblclick (e) -> moveto e; label 'double' "]),mouseup:xc("mouseup",["mouseup(fn) Calls fn(event) whenever the mouse is released. mouseup (e) -> moveto e; label 'up' "]),mousedown:xc("mousedown",["mousedown(fn) Calls fn(event) whenever the mouse is pressed. mousedown (e) -> moveto e; label 'down' "]),mousemove:xc("mousemove",["mousemove(fn) Calls fn(event) whenever the mouse is moved. mousemove (e) -> write 'at ', e.x, ',', e.y "]),keydown:xc("keydown",["keydown(fn) Calls fn(event) whenever a key is pushed down. keydown (e) -> write 'down ' + e.key "]),keyup:xc("keyup",["keyup(fn) Calls fn(event) whenever a key is released. keyup (e) -> write 'up ' + e.key "]),keypress:xc("keypress",["keypress(fn) Calls fn(event) whenever a character key is pressed. keypress (e) -> write 'press ' + e.key "]),send:zc("send",["send(name) Sends a message to be received by recv. send 'go'; recv 'go', -> fd 100 "],function(a){var b=arguments,c=Array.prototype.slice.call(b,1),d=uf.sent[a];d||(d=uf.sent[a]=[]),d.push(c),Zc(a)}),recv:zc("recv",["recv(name, fn) Calls fn once when a sent message is received. recv 'go', (-> fd 100); send 'go' "],function(a,b){var c=uf.waiting[a];c||(c=uf.waiting[a]=[]),c.push(b),Zc(a)}),abs:zc("abs",["abs(x) The absolute value of x. see abs -5 "],Math.abs),acos:zc("acos",["acos(x) Trigonometric arccosine, in radians. see acos 0.5 "],Math.acos),asin:zc("asin",["asin(y) Trigonometric arcsine, in radians. see asin 0.5 "],Math.asin),atan:zc("atan",["atan(y, x = 1) Trigonometric arctangent, in radians. see atan 0.5 "],function(a,b){return Math.atan2(a,b==He?1:b)}),cos:zc("cos",["cos(radians) Trigonometric cosine, in radians. see cos 0 "],Math.cos),sin:zc("sin",["sin(radians) Trigonometric sine, in radians. see sin 0 "],Math.sin),tan:zc("tan",["tan(radians) Trigonometric tangent, in radians. see tan 0 "],Math.tan),acosd:zc("acosd",["acosd(x) Trigonometric arccosine, in degrees. see acosd 0.5 "],function(a){switch(a){case 1:return 0;case.5:return 60;case 0:return 90;case-.5:return 120;case-1:return 180}return 180*Math.acos(a)/Math.PI}),asind:zc("asind",["asind(x) Trigonometric arcsine, in degrees. see asind 0.5 "],function(a){switch(a){case 1:return 90;case.5:return 30;case 0:return 0;case-.5:return-30;case-1:return-90}return 180*Math.asin(a)/Math.PI}),atand:zc("atand",["atand(y, x = 1) Trigonometric arctangent, in degrees. see atand -1, 0/mark>"],function(a,b){return b==He&&(b=1),0==a?0==b?NaN:b>0?0:180:0==b?a>0?1/0:-(1/0):Math.abs(a)==Math.abs(b)?a>0?b>0?45:135:b>0?-45:-135:180*Math.atan2(a,b)/Math.PI}),cosd:zc("cosd",["cosd(degrees) Trigonometric cosine, in degrees. see cosd 45 "],function(a){if(a=ua(a,360),a%30===0)switch(0>a?a+360:a){case 0:return 1;case 60:return.5;case 90:return 0;case 120:return-.5;case 180:return-1;case 240:return-.5;case 270:return 0;case 300:return.5}return Math.cos(a/180*Math.PI)}),sind:zc("sind",["sind(degrees) Trigonometric sine, in degrees. see sind 45 "],function(a){if(a=ua(a,360),a%30===0)switch(0>a?a+360:a){case 0:return 0;case 30:return.5;case 90:return 1;case 150:return.5;case 180:return 0;case 210:return-.5;case 270:return-1;case 330:return-.5}return Math.sin(a/180*Math.PI)}),tand:zc("tand",["tand(degrees) Trigonometric tangent, in degrees. see tand 45 "],function(a){if(a=ua(a,360),a%45===0)switch(0>a?a+360:a){case 0:return 0;case 45:return 1;case 90:return 1/0;case 135:return-1;case 180:return 0;case 225:return 1;case 270:return-(1/0);case 315:return-1}return Math.tan(a/180*Math.PI)}),ceil:zc("ceil",["ceil(x) Round up. see ceil 1.9 "],Math.ceil),floor:zc("floor",["floor(x) Round down. see floor 1.9 "],Math.floor),round:zc("round",["round(x) Round to the nearest integer. see round 1.9 "],Math.round),exp:zc("exp",["exp(x) Raise e to the power x. see exp 2 "],Math.exp),ln:zc("ln",["ln(x) The natural logarithm of x. see ln 2 "],Math.log),log10:zc("log10",["log10(x) The base 10 logarithm of x. see log10 0.01 "],function(a){return Wa(Math.log(a)*Math.LOG10E)}),pow:zc("pow",["pow(x, y) Raise x to the power y. see pow 4, 1.5 "],function(a,b){return Wa(Math.pow(a,b))}),sqrt:zc("sqrt",["sqrt(x) The square root of x. see sqrt 25 "],Math.sqrt),max:zc("max",["max(x, y, ...) The maximum of a set of values. see max -5, 2, 1 "],Math.max),min:zc("min",["min(x, y, ...) The minimum of a set of values. see min 2, -5, 1 "],Math.min),Pencil:zc("Pencil",["new Pencil(canvas) Make an invisble pencil for drawing on a canvas. s = new Sprite; p = new Pencil(s); p.pen red; p.fd 100; remove p "],Ve),Turtle:zc("Turtle",["new Turtle(color) Make a new turtle. t = new Turtle; t.fd 100 "],We),Piano:zc("Piano",["new Piano(keys) Make a new piano. t = new Piano 88; t.play 'edcdeee' "],Ye),Webcam:zc("Webcam",["new Webcam(options) Make a new webcam. v = new Webcam; v.plan -> pic = new Sprite v "],Xe),Sprite:zc("Sprite",["new Sprite({width:w,height:h,color:c}) Make a new sprite to drawon . s = new Sprite({width:50,height:50,color:blue}); s.fd 100 "],Ue),loadscript:zc("loadscript",["loadscript(url, callback) Loads Javascript or Coffeescript from the given URL, calling callback when done."],function(b,c){Ie.CoffeeScript&&/\.(?:coffee|cs)$/.test(b)?CoffeeScript.load(b,c):a.getScript(b,c)}),pressed:zc("pressed",["pressed('control') Tests if a specific key is pressed. if pressed 'a' then write 'a was pressed' ","pressed.list() Returns a list of pressed keys, by name. write 'Pressed keys: ' + pressed.list().join(',') "],_e),help:oc},tf={finish:{helptext:["finish() Finishes turtle animation. Does not pause for effect: do finish "]}},uf={sent:{},waiting:{},pollTimer:null};Xc(sf,"defaultspeed","speed"),sf.save.loginCookie=Gb;var vf={},wf=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgrey","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgrey","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","transparent"];!function(){for(var a=["none","erase","path","up","down","color","position","normal","touch"],b=a.concat(wf),c=0;csee(v) Shows the value of v in the test panel: see document "]},tf["if"]=tf["else"]=tf.then={helptext:["if then else Tests a condition: if 1 <= (new Date).getDay() <= 5 then write 'Working hard!' else write 'Happy weekend!' "]},tf.await=tf.defer={helptext:['await defer Waits for results from an asynchronous event; from Iced CoffeeScript : await readnum defer n ']}}(),a.turtle=function(b,c){var d=!1;if(1==arguments.length&&"object"==typeof b&&b&&!b.hasOwnProperty("length")&&(c=b,b="turtle"),b=b||"turtle",c=c||{},"turtle"in c&&(b=c.turtle),bd(),"htmlscript"in c&&!c.htmlscript||a('script[type="text/html"]').each(function(){a(this).replaceWith(a(this).html().replace(/^\x3c!\[CDATA\[\n?|\]\]\x3e$/g,""))}),!Re.ctx&&"subpixel"in c&&(Re.subpixel=parseInt(c.subpixel)),a.turtle.hangtime="hangtime"in c?parseFloat(c.hangtime):2e4,c.events!==!1&&xd(c.eventprefix),c.pressed!==!1&&(Wb(),_e.enable(!0)),c.see!==!1&&(Rd(),d=!0,Ie.addEventListener?Ie.addEventListener("error",Sf):Ie.onerror=Sf,Ie.debug=Sf,Xc(Ie,"log","debug")),c.queuehide!==!1&&Tc(),c.functions!==!1&&(Ie.printpage=Ie.print,a.extend(Ie,sf)),vd("defaultspeed"in c?c.defaultspeed:1),_b())try{ac()}catch(e){}var f=null,g=!1;if(b&&(f=a("#"+b),f.length||(a("body").length||(document.write(""),g=!0),f=new We(b))),f&&!f.length&&(f=null),f&&1===f.length&&c.global!==!1){var h={css:1,fadeIn:1,fadeOut:1,fadeTo:1,fadeToggle:1,animate:1,toggle:1,finish:1,promise:1,direct:1,show:1,hide:1},i=a.extend({},hf,h);qf.push.apply(qf,ad(f,i)),pf=f[0],f.css({zIndex:1})}if(c.ids!==!1&&(wd(c.idprefix),f&&b&&(Ie[b]=f)),c.panel!==!1){var j={title:"test panel (type help for help)",abbreviate:[He,vf],consolehook:$c};if(f&&j.abbreviate.push(f),c.title&&(j.title=c.title),c.panelheight&&(j.height=c.panelheight),Sf.init(j),d)return Ie.CoffeeScript?"see.init(eval(see.cs))":Sf.here}return a("#"+b)},a.extend(a.turtle,sf),a.turtle.colors=wf;a.cleanData;a.cleanData=function(b){for(var c,d=0;(c=b[d])!==He;d++){var e=a.data(c,"turtleData");e&&e.stream&&e.stream.stop(),c.id&&Ie[c.id]&&Ie[c.id].jquery&&1===Ie[c.id].length&&Ie[c.id][0]===c&&delete Ie[c.id],c===pf&&bd()}};var xf={},yf={turtle:function(a){return a||(a="mediumseagreen"),{url:fd(a),css:{width:20,height:24,transformOrigin:"10px 13px",turtleHull:"-8 -5 -8 6 -2 -13 2 -13 8 6 8 -5 0 9",opacity:.67,backgroundImage:"url("+nf+")",backgroundSize:"cover"}}},pointer:function(a){return a||(a="gray"),{url:gd(a),css:{width:20,height:24,transformOrigin:"10px 18px",turtleHull:"-10 6 0 -18 10 6",opacity:.67}}},radius:function(a){return a||(a="gray"),{url:hd(a),css:{width:20,height:20,transformOrigin:"10px 10px",turtleHull:"-10 0 -7 7 0 10 7 7 10 0 7 -7 0 -10 -7 -7",opacity:1}}},dot:function(a){return a||(a="black"),{url:id(a,24),css:{width:12,height:12,transformOrigin:"6px 6px",turtleHull:"-6 0 -4 4 0 6 4 4 6 0 4 -4 0 -6 -4 -4",opacity:1}}},point:function(a){return a||(a="black"),{url:id(a,6),css:{width:3,height:3,transformOrigin:"1.5px 1.5px",turtleHull:"-1.5 0 -1 1 0 1.5 1 1 1.5 0 1 -1 0 -1.5 -1 -1",opacity:1}}},pencil:function(a){return a||(a="dodgerblue"),{url:jd(a),css:{width:20,height:24,transformOrigin:"10px 24px",turtleHull:"0 0 -3 -6 -3 -24 3 -6 3 -24",opacity:1}}}},zf={"&":"&","<":"<",">":">",'"':"""},Af=[],Bf=[],Cf=null,Df=0,Ef=null,Ff={autoScrollTimer:null,bottomSeen:0},Gf="data:image/svg+xml, ",Hf={init:function(){if(!this.ide){try{parent&&parent.ide&&parent.ide.bindframe&&parent.ide.bindframe(Ie,parent)&&(this.ide=parent.ide,this.attached=!0)}catch(a){}this.attached&&Ie.addEventListener&&Ie.addEventListener("error",function(a){Hf.reportEvent("error",[a])})}},attached:!1,ide:null,reportEvent:function(a,b){this.ide&&this.ide.reportEvent(a,b)},nextId:function(){return this.ide?this.ide.nextId():0}};Hf.init(),function(){function b(a){return a.toFixed(1).replace(/\.0$/,"")}function c(a){return''+a+""}function d(b,c){return b&&(b=b.get(0))&&c&&c.target&&(b==c.target||a.contains(b,c.target))}if(Hf.ide){var e,f,g,h,i=a("").css({position:"fixed",zIndex:1e6-1,fontFamily:"sans-serif",display:"none",background:"#ff8",border:"1px solid dimgray",padding:"1px",cursor:"move",fontSize:12}).appendTo("body"),j=null,k=null,l=null,m=0,n=0,o=0,p=0;a(Ie).on("mousedown mouseup mousemove keydown",function(q){if("keydown"==q.type){if(q.which<27)return;k&&k.remove(),k=j=l=null}if("mousedown"==q.type)if(k)if(l)k&&k.remove(),k=j=l=null;else if(j)k.css({cursor:"default"}),l=q;else{a.turtle.interrupt("reset");var r=a(".turtle").within("touch",q);j=r.length?r.eq(0):q}else if(d(i,q)){var s=Ia();l=j=null,k=a('').css({position:"absolute",top:0,left:0,cursor:"crosshair",zIndex:1e6}).appendTo("body")}if(k){var t,u,v,w,x,y,z=k.canvas(),A=z.getContext("2d"),B=!1,C=l||q;if(j&&"function"==typeof j.pagexy){var D=j.getxy(),E=j.pagexy();E.x=D[0],E.y=D[1],B=!0,x=j.direction(),t=["getxy is "+b(E.x)+", "+b(E.y),"direction is "+b(x)]}else E=j||C,t=[c("moveto "+b(E.x)+", "+b(E.y))];if(t.unshift(l?'click to close ':j?'click to measure ':'click on point '),u=C.x-E.x,v=C.y-E.y,w=Math.sqrt(u*u+v*v),y=Math.atan2(u,v)/Math.PI*180,j){if(A.save(),A.clearRect(m-10,n-10,o-m+20,p-n+20),m=o=E.pageX,n=p=E.pageY,A.fillStyle="red",A.beginPath(),A.arc(E.pageX,E.pageY,4,0,2*Math.PI,!1),A.closePath(),A.fill(),w>0){if(B){A.strokeStyle="black",A.fillStyle="black",g=(x-90)/180*Math.PI,h=(y-90)/180*Math.PI,e=E.pageX+100*Math.cos(g),f=E.pageY+100*Math.sin(g),Rc(A,2,E.pageX,E.pageY,e,f),m=Math.min(e,m),n=Math.min(f,n),o=Math.max(e,o),p=Math.max(f,p);var F=(360+y-x)%360;A.beginPath(),180>=F?(t.push(c("rt "+b(F))),w>=20&&A.arc(E.pageX,E.pageY,20,g,h)):(t.push(c("lt "+b(360-F))),w>=20&&A.arc(E.pageX,E.pageY,20,h,g)),A.stroke(),m=Math.min(E.pageX-20,m),n=Math.min(E.pageY-20,n),o=Math.max(E.pageX+20,o),p=Math.max(E.pageY+20,p)}else t.push(c("turnto "+b(y)));t.push(c("fd "+b(w))),t.push("end at "+b(C.x)+", "+b(C.y)),A.strokeStyle="red",A.fillStyle="red",Rc(A,2,E.pageX,E.pageY,C.pageX,C.pageY),m=Math.min(C.pageX,m),n=Math.min(C.pageY,n),o=Math.max(C.pageX,o),p=Math.max(C.pageY,p)}A.restore()}i.css({left:0,top:0}).html(t.join(" ")).show();var G={left:"",top:"",right:"",bottom:""};C.pageX+5click to use'),null!=q.x&&t.push(q.x+", "+q.y),i.html(t.join(" ")).css({left:"",top:"",right:0,bottom:0}).show()})}}();var If=null,Jf="see",Kf="0.2",Lf=Sd(Jf),Mf="position:relative;display:block;font-family:monospace;font-size:16px;word-break:break-all;margin-bottom:3px;padding-left:1em;",Nf=5,Of=!1,Pf="body",Qf="auto";try{Ie.self!==Ie.top&&screen.width>=800&&screen.height>=600&&parent&&parent.ide&&(Qf=parent.ide.getOptions().panel)}catch(Rf){}var Sf,Tf=Qf,Uf="",Vf=null,Wf="_loghistory",Xf=50,Yf="",Zf={"":{e:Ie.eval,t:Ie},top:{e:Ie.eval,t:Ie}},$f=Ie.CoffeeScript,_f="(function(){return eval(arguments[0]);})",ag="[_$a-zA-ZÂ -ï¿¿][_$a-zA-Z0-9Â -ï¿¿]*",bg=new RegExp("^\\s*var\\s+(?:"+ag+"\\s*,\\s*)*"+ag+"\\s*;\\s*"),cg="input._log:focus{outline:none;}samp._logcaret{position:absolute;left:0;font-size:120%;}samp._logcaret:before{content: '>'}label._log > span:first-of-type:hover{text-decoration:underline;}samp._log > label._log,samp_.log > span > label._log{display:inline-block;vertical-align:top;}label._log > span:first-of-type{margin-left:2em;text-indent:-1em;}label._log > ul{display:none;padding-left:14px;margin:0;}label._log > span:before{content:'';font-size:70%;font-style:normal;display:inline-block;width:0;text-align:center;}label._log > span:first-of-type:before{content:'\\0025B6';}label._log > ul > li{display:block;white-space:pre-line;margin-left:2em;text-indent:-1em}label._log > ul > li > samp{margin-left:-1em;text-indent:0;white-space:pre;}label._log > input[type=checkbox]:checked ~ span{margin-left:2em;text-indent:-1em;}label._log > input[type=checkbox]:checked ~ span:first-of-type:before{content:'\\0025BC';}label._log > input[type=checkbox]:checked ~ span:before{content:'';}label._log,label._log > input[type=checkbox]:checked ~ ul{display:block;}label._log > span:first-of-type,label._log > input[type=checkbox]:checked ~ span{display:inline-block;}label._log > input[type=checkbox],label._log > input[type=checkbox]:checked ~ span > span{display:none;}",dg=!1,eg={"\x00":"\\0","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t","":"\\v","'":"\\'",'"':'\\"',"\\":"\\\\"},fg=null,gg=[];Sf=function(){Vf&&"function"==typeof Vf.log&&Vf.log.apply(Ie.console,arguments);var a=Array.prototype.slice.call(arguments);for(gg.push('');a.length;){var b=a.shift();"String"==Xd(b)?gg.push(he(b)):gg.push(le(b,Nf,gg)),a.length&&gg.push(" ")}gg.push(" "),oe()};var hg=!1,ig=!1,jg=null,kg=[{}.undefined],lg=null,mg=null}}).call(this,this.jQuery);
\ No newline at end of file
diff --git a/package.json b/package.json
index 208270b..339f358 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jquery-turtle",
- "version": "2.0.8",
+ "version": "2.0.9",
"description": "Turtle graphics plugin for jQuery.",
"main": "jquery-turtle.js",
"scripts": {
diff --git a/test/debugevents.html b/test/debugevents.html
index 64d3a57..b63142f 100644
--- a/test/debugevents.html
+++ b/test/debugevents.html
@@ -64,6 +64,7 @@
window.ide = {
bindframe: function() {
verify('bindframe');
+ return true;
},
reportEvent: function(eventname, args) {
verify([eventname, args[0]]);
diff --git a/test/globals.html b/test/globals.html
index 64400bd..a19cb14 100644
--- a/test/globals.html
+++ b/test/globals.html
@@ -31,6 +31,7 @@
"lastmousedown",
"lastmousemove",
"see",
+ "debug",
"log",
"printpage",
"interrupt",
@@ -59,6 +60,7 @@
"typeline",
"read",
"readnum",
+ "listen",
"readstr",
"menu",
"random",
@@ -84,10 +86,15 @@
"acos",
"asin",
"atan",
- "atan2",
"cos",
"sin",
"tan",
+ "acosd",
+ "asind",
+ "atand",
+ "cosd",
+ "sind",
+ "tand",
"ceil",
"floor",
"round",
@@ -325,6 +332,8 @@
"fadeTo",
"fadeToggle",
"animate",
+ "show",
+ "hide",
"toggle",
"finish",
"promise"
diff --git a/test/hide.html b/test/hide.html
new file mode 100644
index 0000000..7af0f92
--- /dev/null
+++ b/test/hide.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/test/inputoutput.html b/test/inputoutput.html
index a29c622..b3b33b4 100644
--- a/test/inputoutput.html
+++ b/test/inputoutput.html
@@ -20,14 +20,22 @@
equal(td.eq(2).text(), "3");
var clicked = 0;
setTimeout(function() {
- $('input').val('Amy').change();
+ $('input').val('Amy');
+ $('button').click();
}, 1);
- var b;
+ var b, r2;
var r = read('name?', function(t) {
equal(t, 'Amy');
setTimeout(function() {
+ $('input').val('34');
+ var e = jQuery.Event("keydown");
+ e.which = 13; // Enter.
+ $('input').trigger(e);
$('button').click();
}, 1);
+ r2 = readnum('count?', function(c) {
+ equal(c, 34);
+ });
b = button('click me!', function() {
equal(equal($('button').last().text(), 'click me!'));
equal(clicked++, 0);
diff --git a/test/label.html b/test/label.html
index 08983f4..927b318 100644
--- a/test/label.html
+++ b/test/label.html
@@ -62,6 +62,10 @@
equal(rounded($('label:contains(bottomleft)').direction()), 0);
equal(direction(), 90);
equal(rounded($('label:contains(upside down)').direction()), 180);
+ var b;
+ label(b = button('hello'));
+ ok(touches(b));
+ equal(b.direction(), 90);
start();
});
});
diff --git a/test/numeric_functions.html b/test/numeric_functions.html
new file mode 100644
index 0000000..49ee2df
--- /dev/null
+++ b/test/numeric_functions.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
diff --git a/test/random.html b/test/random.html
index 0d03405..4e6e289 100644
--- a/test/random.html
+++ b/test/random.html
@@ -20,6 +20,7 @@
equal(random([1,2,3]), 3);
equal(random(), 0.9520654011140274);
equal(random(null), 0.006122341186296597);
+ equal($.turtle.colors.indexOf('red'), 120);
start();
});
diff --git a/test/say.html b/test/say.html
new file mode 100644
index 0000000..a8aed1c
--- /dev/null
+++ b/test/say.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/test/sync.html b/test/sync.html
index 87e4d1a..4808c51 100644
--- a/test/sync.html
+++ b/test/sync.html
@@ -46,4 +46,22 @@
start();
});
});
+
+asyncTest("Moves a written object and verifies that sync works.", function() {
+ speed(10);
+ var w = write('hello');
+ w.bk(100);
+ sync(w, turtle);
+ w.plan(function() {
+ // When w is done moving, w2 should not have moved yet.
+ var xy2 = w2.getxy();
+ var xy = w.getxy();
+ ok(xy2[1] > xy[1]);
+ });
+ var w2 = write('hello2');
+ w2.bk(100);
+ done(function() {
+ start();
+ });
+});
diff --git a/test/wear.html b/test/wear.html
index 9b91ca6..12a9d3f 100644
--- a/test/wear.html
+++ b/test/wear.html
@@ -24,6 +24,20 @@
});
});
+asyncTest("Wears an creative commons image.", function() {
+ var r = new Turtle(red);
+ r.speed(100);
+ tick(60, function() {
+ ok(r.width() != 20 || r.getxy()[1] == 0);
+ });
+ r.wear('t-watermelon'); // no /img/ needed.
+ r.done(function() {
+ ok(r.width() != 20);
+ tick(null);
+ setTimeout(start, 0);
+ });
+});
+
asyncTest("Wears and hittests different shapes.", function() {
speed(Infinity);
dot(red, 30);
@@ -64,6 +78,8 @@
wear(blue);
pause(0.1, function() {
ok(b.touches(blue));
+ // Verify we don't crash when using wear on a disconnected canvas.
+ $('').css({ position: 'absolute' }).wear('pencil');
setTimeout(start, 0);
});
});
diff --git a/turtle.jquery.json b/turtle.jquery.json
index be5c732..cd8b8a3 100644
--- a/turtle.jquery.json
+++ b/turtle.jquery.json
@@ -14,7 +14,7 @@
"audio",
"collision"
],
- "version": "2.0.8",
+ "version": "2.0.9",
"author": {
"name": "David Bau",
"url": "http://davidbau.com/"