From d42f564e0485f461f1fee29e5f20b9f7f137d2a0 Mon Sep 17 00:00:00 2001 From: David Bau Date: Mon, 27 May 2013 08:43:14 -0400 Subject: [PATCH 01/25] scale is a relative operation now. --- jquery-turtle.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index 15f149a..baabdd5 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -54,7 +54,7 @@ Turtle-oriented methods taking advantage of the css support: $(x).img('blue') // Switch the image to a blue pointer. May use any url. $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion in page coordinates. $(x).turnto(heading || position) // Absolute heading adjustment. - $(x).scale(1.5) // Scales the element up to 150% size. + $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". $(x).mirror(true) // Flips the turtle across its direction axis. $(x).reload() // Reloads the turtle's image (restarting animated gifs) @@ -1795,14 +1795,16 @@ var turtlefn = { }); }, scale: function(valx, valy) { - if (valx === undefined && valy === undefined) { - return parseFloat(this.css('turtleTwist')); - } - var val = '' + cssNum(valx) + - (valy === undefined ? '' : ' ' + cssNum(valy)); + if (valy === undefined) { valy = valx; } + // Disallow scaling to zero using this method. + if (!valx || !valy) { return this; } return this.direct(function(j, elem) { if ($.isWindow(elem) || elem.nodeType === 9) return; - this.css('turtleScale', val); + var c = $.map($.css(elem, 'turtleScale').split(' '), parseFloat); + if (c.length === 1) { c.push(c[0]); } + c[0] *= valx; + c[1] *= valy; + this.css('turtleScale', $.map(c, cssNum).join(' ')); }); }, shown: function() { From 1834ead4bc264f4082be2495afa96b86635e8d2f Mon Sep 17 00:00:00 2001 From: David Bau Date: Mon, 27 May 2013 08:59:42 -0400 Subject: [PATCH 02/25] dot scales diameter. --- jquery-turtle.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index baabdd5..199ff6c 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -1683,7 +1683,9 @@ var turtlefn = { var ps = parsePenStyle(style, 'fillStyle'); return this.direct(function(j, elem) { var c = this.center(); - fillDot(c, diameter, ps); + // Scale by sx. (TODO: consider drawing ellipse for sx != sy.) + var s = $.map($.css(elem, 'turtleScale').split(' '), parseFloat); + fillDot(c, diameter * s[0], ps); // Once drawing begins, origin must be stable. watchImageToFixOriginOnLoad(elem); }); From 4de42392a7007efb05e0a647a2065f2e8ead2f1d Mon Sep 17 00:00:00 2001 From: David Bau Date: Mon, 27 May 2013 09:39:13 -0400 Subject: [PATCH 03/25] Fix pen 'path'. --- jquery-turtle.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index 199ff6c..a08a934 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -1300,9 +1300,9 @@ function flushPenState(elem) { !isPointNearby(center, state.path[state.path.length - 1])) { state.path.push(center); } - if (!state.style.path) { + if (!state.style.savePath) { var ctx = getTurtleDrawingCtx(); - isClosed = isPointNearby( + isClosed = state.path.length > 2 && isPointNearby( state.path[0], state.path[state.path.length - 1]); ctx.save(); applyPenStyle(ctx, state.style); From 14bd120bb5e3881d9c074954de754a06a1467465 Mon Sep 17 00:00:00 2001 From: David Bau Date: Tue, 28 May 2013 09:12:25 -0400 Subject: [PATCH 04/25] Update jquery-turtle.js --- jquery-turtle.js | 131 +++++++++++++++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 44 deletions(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index a08a934..fad8516 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -4,7 +4,7 @@ jQuery-turtle ============= -version 2.0.4 +version 2.0.5 jQuery-turtle is a jQuery plugin for turtle graphics. @@ -48,25 +48,28 @@ Turtle-oriented methods taking advantage of the css support: $(x).bk(50) // Back. $(x).rt(90) // Right turn. $(x).lt(45) // Left turn. + + // Methods below happen in an instant, but queue after animation. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. - $(x).dot(12) // Draws a dot of diameter 12. + $(x).dot(12) // Draws a circular dot of diameter 12. $(x).erase() // Erases under the turtles collision hull. $(x).img('blue') // Switch the image to a blue pointer. May use any url. $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion in page coordinates. $(x).turnto(heading || position) // Absolute heading adjustment. $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". - $(x).mirror(true) // Flips the turtle across its direction axis. + $(x).mirror(true) // Flips the turtle across its main axis. $(x).reload() // Reloads the turtle's image (restarting animated gifs) $(x).direct(fn) // Like each, but this is set to $(elt) instead of elt. + // Methods below this line do not queue for animation. - $(x).center() // Page coordinate position of transform-origin. - $(x).direction() // Absolute bearing taking into account nested transforms. + $(x).origin() // Page coordinate position of transform-origin. + $(x).bearing() // Absolute direction taking into account all transforms. $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") $(x).touches(y) // Collision tests elements (uses turtleHull if present). $(x).encloses(y) // Containment collision test. - $(x).within(d, t) // Filters to items with centers within d of t.center(). + $(x).within(d, t) // Filters to items with origins within d of t.origin(). $(x).notwithin() // The negation of within. @@ -132,36 +135,57 @@ After eval($.turtle()): * An eval debugging panel (see.js) is shown at the bottom of the screen. * Turtle methods on the default turtle are packaged as globals, e.g., fd(10). * Every #id element is turned into a global variable: window.id = $('#id'). - * Globals are set up to save events: "lastclick", "lastmousemove", etc. * Default turtle animation is set to 1 move per sec so steps can be seen. - * speed(movesPerSec) adjusts $.fx.speeds.turtle to 1000 / movesPerSec. - * tick([ticksPerSec,] fn) is similarly an easier-to-call setInterval. - * random(lessThanThisInteger || array) is an easy alternative to Math.random. - * remove() will remove the global turtle and global turtle methods. - * hatch([n,] [spec]) creates and returns any number of new turtles. - * see(a, b, c) logs tree-expandable data into the debugging panel. - * output(html or text) appends html to the document body. - * input(label, callback) appends a labelled input field to the document body. + * And the following are defined: + +
+  lastclick             // Event object of the last click event in the doc.
+  lastmousemove         // The last mousemove event.
+  lastmouseup           // The last mouseup event.
+  lastmousedown         // The last mousedown event.
+  keydown               // The last keydown event.
+  keyup                 // The last keyup event.
+  keypress              // The last keypress event.
+  speed(movesPerSec)    // Sets $.fx.speeds.turtle to 1000 / movesPerSec.
+  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).
+  random(n)             // Returns a random number [0...n-1].
+  random(list)          // Returns a random element of the list.
+  random('normal')      // Returns a gaussian random (mean 0 stdev 1).
+  random('uniform')     // Returns a uniform random [0...1).
+  random('position')    // Returns a random {pageX:x, pageY:y} in the document.
+  remove()              // Removes default turtle and its globals (fd, etc).
+  hatch([n,], [img])    // Creates and returns n turtles with the given img.
+  see(a, b, c...)       // Logs tree-expandable data into debugging panel.
+  output(html || text)  // Appends html into the document body.
+  input([label,] fn)    // Makes a one-time input field, calls fn after entry.
+  button([label,] fn)   // Makes a clickable button, calls fn when clicked.
+
For example, after eval($.turtle()), the following is a valid program in CoffeeScript syntax:
-speed 100
-pen 'red'
-chaser = hatch()
-chaser.moveto 0,0
-chaser.bg 'red'
-player = turtle
+speed Infinity
+output "Try to catch blue."
+r = hatch 'red'
+b = hatch 'blue'
+safe = 20
 tick 10, ->
-  player.turnto lastmousemove
-  player.fd 5
-  chaser.turnto player
-  chaser.rt (random 60) - 30
-  chaser.fd 5
-  if chaser.touches player
-    output "tag! you're it!"
-    tick ->
+  turnto lastmousemove
+  fd 6
+  if safe > 0
+    safe = safe - 1
+  else
+    r.turnto turtle
+    r.fd 4
+    b.turnto r
+    b.fd 3
+    if b.touches(turtle)
+      output "You win!"
+      tick null
+    else if r.touches(turtle)
+      output "Too slow!"
+      tick null
 
The turtle teaching environment is designed to work well with either @@ -501,7 +525,7 @@ function transformStyleAsMatrix(transformStyle) { ////////////////////////////////////////////////////////////////////////// // ABSOLUTE PAGE POSITIONING -// Dealing with the element center, rectangle, and direction on the page, +// Dealing with the element origin, rectangle, and direction on the page, // taking into account nested parent transforms. ////////////////////////////////////////////////////////////////////////// @@ -731,7 +755,7 @@ function getCenterInPageCoordinates(elem) { { position: "absolute", visibility: "hidden", display: "block" } : {}, st = swapout[transform] = (inverseParent ? 'matrix(' + $.map(inverseParent, cssNum).join(', ') + ', 0, 0)' : 'none'), - substTransform = (st == 'matrix(1, 0, 0, 1, 0, 0)') ? 'none' : st; + substTransform = (st == 'matrix(1, 0, 0, 1, 0, 0)') ? 'none' : st, saved = elem.style[transform], gbcr = cleanSwap(elem, swapout, readPageGbcr), middle = readTransformOrigin(elem, [gbcr.width, gbcr.height]), @@ -837,7 +861,7 @@ function scrollWindowToDocumentPosition(pos, limit) { if (ty < wh2) { ty = wh2; } targ = { pageX: tx, pageY: ty }; if ($.isNumeric(limit)) { - targ = limitMovement(w.center(), targ, limit); + targ = limitMovement(w.origin(), targ, limit); } w.scrollLeft(targ.pageX - ww2); w.scrollTop(targ.pageY - wh2); @@ -1573,7 +1597,7 @@ function withinOrNot(obj, within, distance, x, y) { } var ctr = $.isNumeric(x) && $.isNumeric(y) ? { pageX: x, pageY: y } : isPageCoordinate(x) ? x : - $(x).center(), + $(x).origin(), d2 = distance * distance; return obj.filter(function() { var gbcr = getPageGbcr(this); @@ -1682,7 +1706,7 @@ var turtlefn = { if (!style) { style = 'black'; } var ps = parsePenStyle(style, 'fillStyle'); return this.direct(function(j, elem) { - var c = this.center(); + var c = this.origin(); // Scale by sx. (TODO: consider drawing ellipse for sx != sy.) var s = $.map($.css(elem, 'turtleScale').split(' '), parseFloat); fillDot(c, diameter * s[0], ps); @@ -1720,7 +1744,7 @@ var turtlefn = { } }); }, - center: function() { + origin: function() { if (!this.length) return; return getCenterInPageCoordinates(this[0]); }, @@ -1737,7 +1761,7 @@ var turtlefn = { } return this.direct(function(j, elem) { var pos = position; - if (pos && !isPageCoordinate(pos)) { pos = $(pos).center(); } + if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } if (!pos || !isPageCoordinate(pos)) return this; if ($.isWindow(elem)) { scrollWindowToDocumentPosition(pos, limit); @@ -1751,19 +1775,19 @@ var turtlefn = { flushPenState(elem); }); }, - direction: function() { + bearing: function() { if (!this.length) return; var elem = this[0], dir; if ($.isWindow(elem) || elem.nodeType === 9) return 0; return getDirectionOnPage(elem); }, - turnto: function(direction, limit) { + turnto: function(bearing, limit) { return this.direct(function(j, elem) { if ($.isWindow(elem) || elem.nodeType === 9) return; - var dir = direction; - if (!$.isNumeric(direction)) { - var pos = direction, cur = $(elem).center(); - if (pos && !isPageCoordinate(pos)) { pos = $(pos).center(); } + var dir = bearing; + if (!$.isNumeric(bearing)) { + var pos = bearing, cur = $(elem).origin(); + if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } if (!pos || !isPageCoordinate(pos)) return; dir = radiansToDegrees( Math.atan2(pos.pageX - cur.pageX, cur.pageY - pos.pageY)); @@ -1961,7 +1985,8 @@ var dollar_turtle_methods = { random: random, hatch: hatch, input: input, - output: output + output: output, + button: button }; $.turtle = function turtle(id, options) { @@ -2357,12 +2382,30 @@ function output(html) { if (html === undefined || html === null) { return $('').img('turtle').appendTo('body'); } - if (!html || html[0] != '<' || html.indexOf('>') == -1) { + if (!html || html[0] != '<') { html = '
' + escapeHtml(html) + '
'; } return $(html).appendTo('body'); } +// Simplify $('body'>.append('').click(fn). +function button(name, callback) { + if ($.isFunction(name) && callback === undefined) { + callback = name; + name = null; + } + if (name === null || name === undefined) { + name = '\u25CE'; + } + var result = $(''); + result.appendTo('body'); + if (callback) { + result.click(callback); + } + return result; +} + + // Simplify $('body').append('' + label) and onchange hookup. function input(name, callback) { if ($.isFunction(name) && callback === undefined) { From 292c40ba2539ea4acd00b4a845242570e997f283 Mon Sep 17 00:00:00 2001 From: David Bau Date: Wed, 29 May 2013 08:06:39 -0400 Subject: [PATCH 05/25] Update jquery-turtle.js --- jquery-turtle.js | 122 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 33 deletions(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index fad8516..ec6d8ab 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -106,7 +106,7 @@ motion: $(x).css('turtleScaleY', '2'); // y stretch before rotate after twist. $(x).css('turtleTwist', '45'); // turn before stretching. $(x).css('turtleForward', '50'); // position in direction of rotation. - $(x).css('turtlePen', 'red'); // or 'red lineWidth 2px' etc. + $(x).css('turtlePenStyle', 'red'); // or 'red lineWidth 2px' etc. $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions. @@ -1229,7 +1229,7 @@ function resizecanvas() { } } -// turtlePen style syntax +// turtlePenStyle style syntax function parsePenStyle(text, defaultProp) { if (!text) { return null; } text = text.trim(); @@ -1269,15 +1269,29 @@ function writePenStyle(style) { return result.join(' '); } +function parsePenDown(style) { + if (style == 'down') return true; + if (style == 'up') return false; + return undefined; +} + +function writePenDown(bool) { + return bool ? 'down' : 'up'; +} + function getTurtleData(elem) { var state = $.data(elem, 'turtleData'); if (!state) { - state = $.data(elem, 'turtleData', { style: null, path: [] }); + state = $.data(elem, 'turtleData', { + style: {}, + path: [[]], + down: true + }); } return state; } -function makePenHook() { +function makePenStyleHook() { return { get: function(elem, computed, extra) { return writePenStyle(getTurtleData(elem).style); @@ -1285,10 +1299,23 @@ function makePenHook() { set: function(elem, value) { var style = parsePenStyle(value, 'strokeStyle'); getTurtleData(elem).style = style; - elem.style.turtlePen = writePenStyle(style); - if (style) { - flushPenState(elem); - } + elem.style.turtlePenStyle = writePenStyle(style); + flushPenState(elem); + } + }; +} + +function makePenDownHook() { + return { + get: function(elem, computed, extra) { + return writePenDown(getTurtleData(elem).down); + }, + set: function(elem, value) { + var style = parsePenDown(value); + if (style === undefined) return; + getTurtleData(elem).down = style; + elem.style.turtlePenDown = writePenDown(style); + flushPenState(elem); } }; } @@ -1298,48 +1325,72 @@ function isPointNearby(a, b) { Math.round(a.pageY - b.pageY) === 0; } -function applyPenStyle(ctx, ps) { +function applyPenStyle(ctx, ps, scale) { + scale = scale || 1; if (!ps || !('strokeStyle' in ps)) { ctx.strokeStyle = 'black'; } - if (!ps || !('lineWidth' in ps)) { ctx.lineWidth = 1.62; } + if (!ps || !('lineWidth' in ps)) { ctx.lineWidth = 1.62 * scale; } if (!ps || !('lineCap' in ps)) { ctx.lineCap = 'round'; } if (ps) { for (var a in ps) { - if (a === 'path') { continue; } - ctx[a] = ps[a]; + if (a === 'savePath') { continue; } + if (scale && a === 'lineWidth') { + ctx[a] = scale * ps[a]; + } else { + ctx[a] = ps[a]; + } } } } function flushPenState(elem) { var state = getTurtleData(elem); - if (!state.style) { - if (state.path.length) { state.path.length = 0; } + if (!state.style || (!state.down && !state.style.savePath)) { + if (state.path.length > 1) { state.path.length = 1; } + if (state.path[0].length) { state.path[0].length = 0; } + return; + } + if (!state.down) { + // Penup when saving path will start a new segment if one isn't started. + if (state.path.length && state.path[0].length) { + state.path.shift([]); + } return; } var center = getCenterInPageCoordinates(elem); // Once the pen is down, the origin needs to be stable when the image // loads. watchImageToFixOriginOnLoad(elem); - if (!state.path.length || - !isPointNearby(center, state.path[state.path.length - 1])) { - state.path.push(center); + if (!state.path[0].length || + !isPointNearby(center, state.path[0][state.path[0].length - 1])) { + state.path[0].push(center); } if (!state.style.savePath) { - var ctx = getTurtleDrawingCtx(); - isClosed = state.path.length > 2 && isPointNearby( - state.path[0], state.path[state.path.length - 1]); + var ts = readTurtleTransform(elem, true), + ctx = getTurtleDrawingCtx(), + isClosed, + j = state.path.length, + segment; ctx.save(); - applyPenStyle(ctx, state.style); ctx.beginPath(); - ctx.moveTo(state.path[0].pageX, state.path[0].pageY); - for (var j = 1; j < state.path.length - (isClosed ? 1 : 0); ++j) { - ctx.lineTo(state.path[j].pageX, state.path[j].pageY); + // Scale up lineWidth by sx. (TODO: consider parent transforms.) + applyPenStyle(ctx, state.style, ts.sx); + while (j--) { + if (state.path[j].length) { + segment = state.path[j]; + isClosed = segment.length > 2 && isPointNearby( + segment[0], segment[segment.length - 1]); + ctx.moveTo(segment[0].pageX, segment[0].pageY); + for (var k = 1; k < segment.length - (isClosed ? 1 : 0); ++k) { + ctx.lineTo(segment[k].pageX, segment[k].pageY); + } + if (isClosed) { ctx.closePath(); } + } } - if (isClosed) { ctx.closePath(); } if ('fillStyle' in state.style) { ctx.fill(); } if ('strokeStyle' in state.style) { ctx.stroke(); } ctx.restore(); - state.path.splice(0, state.path.length - 1); + state.path.length = 1; + state.path[0].splice(0, state.path[0].length - 1); } } @@ -1617,7 +1668,8 @@ function withinOrNot(obj, within, distance, x, y) { $.extend(true, $, { cssHooks: { - turtlePen: makePenHook(), + turtlePenStyle: makePenStyleHook(), + turtlePenDown: makePenDownHook(), turtleForward: makeTurtleForwardHook(), turtlePosition: makeTurtleXYHook('turtlePosition', 'tx', 'ty', true), turtlePositionX: makeTurtleHook('tx', identity, 'px', true), @@ -1694,7 +1746,11 @@ var turtlefn = { }, pen: function(penstyle) { return this.direct(function(j, elem) { - this.css('turtlePen', penstyle); + if (penstyle == 'down' || penstyle == 'up') { + this.css('turtlePenDown', penstyle); + } else { + this.css('turtlePenStyle', penstyle); + } }); }, dot: function(style, diameter) { @@ -1706,10 +1762,10 @@ var turtlefn = { if (!style) { style = 'black'; } var ps = parsePenStyle(style, 'fillStyle'); return this.direct(function(j, elem) { - var c = this.origin(); - // Scale by sx. (TODO: consider drawing ellipse for sx != sy.) - var s = $.map($.css(elem, 'turtleScale').split(' '), parseFloat); - fillDot(c, diameter * s[0], ps); + var c = this.origin(), + ts = readTurtleTransform(elem, true); + // Scale by sx. (TODO: consider parent transforms.) + fillDot(c, diameter * ts.sx, ps); // Once drawing begins, origin must be stable. watchImageToFixOriginOnLoad(elem); }); @@ -2041,7 +2097,7 @@ $.turtle = function turtle(id, options) { } // Set turtle speed speed(options.hasOwnProperty('speed') ? options.speed : 1); - // Find or create a turtle if one does not exist. + // Find or create a singleton turtle if one does not exist. var selector = null; if (id) { selector = $('#' + id); From 232fe2080d9b02c8dab71b875c68074bbe281982 Mon Sep 17 00:00:00 2001 From: davidbau Date: Wed, 29 May 2013 05:10:35 -0700 Subject: [PATCH 06/25] Create gh-pages branch via GitHub --- index.html | 106 ++++++++++++++++++++++++++++++++-------------------- params.json | 2 +- 2 files changed, 67 insertions(+), 41 deletions(-) diff --git a/index.html b/index.html index abc74a3..99158c8 100644 --- a/index.html +++ b/index.html @@ -30,9 +30,10 @@

jQuery-turtle

-

jQuery-turtle

+

+jQuery-turtle

-

version 2.0.4

+

version 2.0.5

jQuery-turtle is a jQuery plugin for turtle graphics.

@@ -49,9 +50,6 @@

jQuery-turtle

positioning, and absolute direction reading and setting.

Try an interactive demo (CoffeeScript syntax) here.

-

Under the covers, CSS3 2D transforms and jQuery animations are used to execute and store turtle movement, so jQuery-turtle @@ -71,7 +69,8 @@

jQuery-turtle

and creation of new turtles. The jQuery teaching environment has been developed to support a curriculum for young students.

-

JQuery Methods for Turtle Movement

+

+JQuery Methods for Turtle Movement

Turtle-oriented methods taking advantage of the css support:

@@ -80,25 +79,28 @@

JQuery Methods for Turtle Movement

$(x).bk(50) // Back. $(x).rt(90) // Right turn. $(x).lt(45) // Left turn. + + // Methods below happen in an instant, but queue after animation. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. - $(x).dot(12) // Draws a dot of diameter 12. + $(x).dot(12) // Draws a circular dot of diameter 12. $(x).erase() // Erases under the turtles collision hull. $(x).img('blue') // Switch the image to a blue pointer. May use any url. $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion in page coordinates. $(x).turnto(heading || position) // Absolute heading adjustment. - $(x).scale(1.5) // Scales the element up to 150% size. + $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". - $(x).mirror(true) // Flips the turtle across its direction axis. + $(x).mirror(true) // Flips the turtle across its main axis. $(x).reload() // Reloads the turtle's image (restarting animated gifs) $(x).direct(fn) // Like each, but this is set to $(elt) instead of elt. + // Methods below this line do not queue for animation. - $(x).center() // Page coordinate position of transform-origin. - $(x).direction() // Absolute bearing taking into account nested transforms. + $(x).origin() // Page coordinate position of transform-origin. + $(x).bearing() // Absolute direction taking into account all transforms. $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") $(x).touches(y) // Collision tests elements (uses turtleHull if present). $(x).encloses(y) // Containment collision test. - $(x).within(d, t) // Filters to items with centers within d of t.center(). + $(x).within(d, t) // Filters to items with origins within d of t.origin(). $(x).notwithin() // The negation of within. @@ -119,7 +121,8 @@

JQuery Methods for Turtle Movement

the bounding box of the elements (as transformed) but can be overridden by the turtleHull CSS property, if present.

-

JQuery CSS Hooks for Turtle Geometry

+

+JQuery CSS Hooks for Turtle Geometry

Turtle-oriented 2d transform cssHooks, with animation support on all motion:

@@ -152,7 +155,8 @@

JQuery CSS Hooks for Turtle Geometry

If set to 'auto' (the default) the hull is just the bounding box for the element.

-

Turtle Teaching Environment

+

+Turtle Teaching Environment

An optional teaching environment setup is created by eval($.turtle()). It provides easy packaging for the above functionality.

@@ -164,41 +168,63 @@

Turtle Teaching Environment

  • An eval debugging panel (see.js) is shown at the bottom of the screen.
  • Turtle methods on the default turtle are packaged as globals, e.g., fd(10).
  • Every #id element is turned into a global variable: window.id = $('#id').
  • -
  • Globals are set up to save events: "lastclick", "lastmousemove", etc.
  • Default turtle animation is set to 1 move per sec so steps can be seen.
  • -
  • speed(movesPerSec) adjusts $.fx.speeds.turtle to 1000 / movesPerSec.
  • -
  • tick([ticksPerSec,] fn) is similarly an easier-to-call setInterval.
  • -
  • random(lessThanThisInteger || array) is an easy alternative to Math.random.
  • -
  • remove() will remove the global turtle and global turtle methods.
  • -
  • hatch([n,] [spec]) creates and returns any number of new turtles.
  • -
  • see(a, b, c) logs tree-expandable data into the debugging panel.
  • -
  • output(html or text) appends html to the document body.
  • -
  • input(label, callback) appends a labelled input field to the document body.
  • -

    For example, after eval($.turtle()), the following is a valid program +

  • And the following are defined:
  • +
    +  lastclick             // Event object of the last click event in the doc.
    +  lastmousemove         // The last mousemove event.
    +  lastmouseup           // The last mouseup event.
    +  lastmousedown         // The last mousedown event.
    +  keydown               // The last keydown event.
    +  keyup                 // The last keyup event.
    +  keypress              // The last keypress event.
    +  speed(movesPerSec)    // Sets $.fx.speeds.turtle to 1000 / movesPerSec.
    +  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).
    +  random(n)             // Returns a random number [0...n-1].
    +  random(list)          // Returns a random element of the list.
    +  random('normal')      // Returns a gaussian random (mean 0 stdev 1).
    +  random('uniform')     // Returns a uniform random [0...1).
    +  random('position')    // Returns a random {pageX:x, pageY:y} in the document.
    +  remove()              // Removes default turtle and its globals (fd, etc).
    +  hatch([n,], [img])    // Creates and returns n turtles with the given img.
    +  see(a, b, c...)       // Logs tree-expandable data into debugging panel.
    +  output(html || text)  // Appends html into the document body.
    +  input([label,] fn)    // Makes a one-time input field, calls fn after entry.
    +  button([label,] fn)   // Makes a clickable button, calls fn when clicked.
    +
    + +

    For example, after eval($.turtle()), the following is a valid program in CoffeeScript syntax:

    -speed 100
    -pen 'red'
    -chaser = hatch()
    -chaser.moveto 0,0
    -chaser.bg 'red'
    -player = turtle
    +speed Infinity
    +output "Try to catch blue."
    +r = hatch 'red'
    +b = hatch 'blue'
    +safe = 20
     tick 10, ->
    -  player.turnto lastmousemove
    -  player.fd 5
    -  chaser.turnto player
    -  chaser.rt (random 60) - 30
    -  chaser.fd 5
    -  if chaser.touches player
    -    output "tag! you're it!"
    -    tick ->
    +  turnto lastmousemove
    +  fd 6
    +  if safe > 0
    +    safe = safe - 1
    +  else
    +    r.turnto turtle
    +    r.fd 4
    +    b.turnto r
    +    b.fd 3
    +    if b.touches(turtle)
    +      output "You win!"
    +      tick null
    +    else if r.touches(turtle)
    +      output "Too slow!"
    +      tick null
     

    The turtle teaching environment is designed to work well with either Javascript or CoffeeScript.

    -

    License (MIT)

    +

    +License (MIT)

    Copyright (c) 2013 David Bau

    @@ -227,4 +253,4 @@

    License (MIT)

    - + \ No newline at end of file diff --git a/params.json b/params.json index 2d6e6d2..5ee6339 100644 --- a/params.json +++ b/params.json @@ -1 +1 @@ -{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.4\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using LOGO-inspired turtle methods like fd, bk, rt, and lt.\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\nThe plugin also provides functions to help in a rotated,\r\nscaled, and transformed world where nested elements may be\r\ntransformed. There are functions for collision testing, absolute\r\npositioning, and absolute direction reading and setting.\r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\nUnder the covers, CSS3 2D transforms and jQuery animations are\r\nused to execute and store turtle movement, so jQuery-turtle\r\ninteracts well with other jQuery animations or direct uses of\r\n2D CSS3 transforms. The plugin sets up jQuery CSS hooks for\r\nsynthetic CSS properties such as turtleForward that can be\r\nanimated or used to directly manipulate turtle geometry at a basic\r\nmathematical level.\r\n\r\nA high-level educational environment is enabled by $.turtle().\r\nThat call creates a set of global objects and functions\r\ncatering to beginners. These include a default turtle\r\nand global functions to control it; an onpage debugger panel;\r\njQuery instances for every object with an #id; simplified\r\nglobals to access recent mouse and keyboard events, and\r\nsimplified functions for randomness, timers, animation control,\r\nand creation of new turtles. The jQuery teaching environment\r\nhas been developed to support a curriculum for young students.\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nTurtle-oriented methods taking advantage of the css support:\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).dot(12)      // Draws a dot of diameter 12.\r\n  $(x).erase()      // Erases under the turtles collision hull.\r\n  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion in page coordinates.\r\n  $(x).turnto(heading || position)      // Absolute heading adjustment.\r\n  $(x).scale(1.5)   // Scales the element up to 150% size.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its direction axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.\r\n  // Methods below this line do not queue for animation.\r\n  $(x).center()     // Page coordinate position of transform-origin.\r\n  $(x).direction()  // Absolute bearing taking into account nested transforms.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with centers within d of t.center().\r\n  $(x).notwithin()  // The negation of within.\r\n
    \r\n\r\nWhen $.fx.speeds.turtle is nonzero (the default is zero unless\r\n$.turtle() is called), the first four movement functions animate\r\nat that speed, and the remaining mutators also participate in the\r\nanimation queue. Note that property-reading functions such as\r\ntouches() are synchronous and will not queue, and setting\r\n$.fx.speed.turtle to 0 will make movement functions synchronous.\r\n\r\nThe absolute motion methods moveto and turnto accept any argument\r\nwith pageX and pageY, including, usefully, mouse events. They\r\noperate in absolute page coordinates even when the turtle is nested\r\nwithin further transformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test using\r\nthe convex hull for the two objects in question. This defaults to\r\nthe bounding box of the elements (as transformed) but can be overridden\r\nby the turtleHull CSS property, if present.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nTurtle-oriented 2d transform cssHooks, with animation support on all\r\nmotion:\r\n\r\n
    \r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch before rotate after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch before rotate after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePen', 'red');          // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nAn optional teaching environment setup is created by eval($.turtle()).\r\nIt provides easy packaging for the above functionality.\r\n\r\nAfter eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Globals are set up to save events: \"lastclick\", \"lastmousemove\", etc.\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * speed(movesPerSec) adjusts $.fx.speeds.turtle to 1000 / movesPerSec.\r\n * tick([ticksPerSec,] fn) is similarly an easier-to-call setInterval.\r\n * random(lessThanThisInteger || array) is an easy alternative to Math.random.\r\n * remove() will remove the global turtle and global turtle methods.\r\n * hatch([n,] [spec]) creates and returns any number of new turtles.\r\n * see(a, b, c) logs tree-expandable data into the debugging panel.\r\n * output(html or text) appends html to the document body.\r\n * input(label, callback) appends a labelled input field to the document body.\r\n\r\nFor example, after eval($.turtle()), the following is a valid program\r\nin CoffeeScript syntax:\r\n\r\n
    \r\nspeed 100\r\npen 'red'\r\nchaser = hatch()\r\nchaser.moveto 0,0\r\nchaser.bg 'red'\r\nplayer = turtle\r\ntick 10, ->\r\n  player.turnto lastmousemove\r\n  player.fd 5\r\n  chaser.turnto player\r\n  chaser.rt (random 60) - 30\r\n  chaser.fd 5\r\n  if chaser.touches player\r\n    output \"tag! you're it!\"\r\n    tick ->\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file +{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using LOGO-inspired turtle methods like fd, bk, rt, and lt.\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\nThe plugin also provides functions to help in a rotated,\r\nscaled, and transformed world where nested elements may be\r\ntransformed. There are functions for collision testing, absolute\r\npositioning, and absolute direction reading and setting.\r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\nUnder the covers, CSS3 2D transforms and jQuery animations are\r\nused to execute and store turtle movement, so jQuery-turtle\r\ninteracts well with other jQuery animations or direct uses of\r\n2D CSS3 transforms. The plugin sets up jQuery CSS hooks for\r\nsynthetic CSS properties such as turtleForward that can be\r\nanimated or used to directly manipulate turtle geometry at a basic\r\nmathematical level.\r\n\r\nA high-level educational environment is enabled by $.turtle().\r\nThat call creates a set of global objects and functions\r\ncatering to beginners. These include a default turtle\r\nand global functions to control it; an onpage debugger panel;\r\njQuery instances for every object with an #id; simplified\r\nglobals to access recent mouse and keyboard events, and\r\nsimplified functions for randomness, timers, animation control,\r\nand creation of new turtles. The jQuery teaching environment\r\nhas been developed to support a curriculum for young students.\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nTurtle-oriented methods taking advantage of the css support:\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n\r\n  // Methods below happen in an instant, but queue after animation.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).erase()      // Erases under the turtles collision hull.\r\n  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion in page coordinates.\r\n  $(x).turnto(heading || position)      // Absolute heading adjustment.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate position of transform-origin.\r\n  $(x).bearing()    // Absolute direction taking into account all transforms.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n
    \r\n\r\nWhen $.fx.speeds.turtle is nonzero (the default is zero unless\r\n$.turtle() is called), the first four movement functions animate\r\nat that speed, and the remaining mutators also participate in the\r\nanimation queue. Note that property-reading functions such as\r\ntouches() are synchronous and will not queue, and setting\r\n$.fx.speed.turtle to 0 will make movement functions synchronous.\r\n\r\nThe absolute motion methods moveto and turnto accept any argument\r\nwith pageX and pageY, including, usefully, mouse events. They\r\noperate in absolute page coordinates even when the turtle is nested\r\nwithin further transformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test using\r\nthe convex hull for the two objects in question. This defaults to\r\nthe bounding box of the elements (as transformed) but can be overridden\r\nby the turtleHull CSS property, if present.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nTurtle-oriented 2d transform cssHooks, with animation support on all\r\nmotion:\r\n\r\n
    \r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch before rotate after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch before rotate after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePen', 'red');          // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nAn optional teaching environment setup is created by eval($.turtle()).\r\nIt provides easy packaging for the above functionality.\r\n\r\nAfter eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * And the following are defined:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  speed(movesPerSec)    // Sets $.fx.speeds.turtle to 1000 / movesPerSec.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} in the document.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  output(html || text)  // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n
    \r\n\r\nFor example, after eval($.turtle()), the following is a valid program\r\nin CoffeeScript syntax:\r\n\r\n
    \r\nspeed Infinity\r\noutput \"Try to catch blue.\"\r\nr = hatch 'red'\r\nb = hatch 'blue'\r\nsafe = 20\r\ntick 10, ->\r\n  turnto lastmousemove\r\n  fd 6\r\n  if safe > 0\r\n    safe = safe - 1\r\n  else\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto r\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      output \"You win!\"\r\n      tick null\r\n    else if r.touches(turtle)\r\n      output \"Too slow!\"\r\n      tick null\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file From c9d3b7fcef04b70983971ff013dba7583b4491cc Mon Sep 17 00:00:00 2001 From: David Bau Date: Wed, 29 May 2013 08:11:31 -0400 Subject: [PATCH 07/25] Update iframe. --- index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 99158c8..ccd1b4d 100644 --- a/index.html +++ b/index.html @@ -50,6 +50,9 @@

    positioning, and absolute direction reading and setting.

    Try an interactive demo (CoffeeScript syntax) here.

    +

    Under the covers, CSS3 2D transforms and jQuery animations are used to execute and store turtle movement, so jQuery-turtle @@ -253,4 +256,4 @@

    - \ No newline at end of file + From a9be19b0f27381fd1ad63f13901492fb8d8e9c15 Mon Sep 17 00:00:00 2001 From: David Bau Date: Sat, 1 Jun 2013 07:14:22 -0400 Subject: [PATCH 08/25] Update jquery-turtle.js --- jquery-turtle.js | 307 +++++++++++++++++++++++++++++------------------ 1 file changed, 190 insertions(+), 117 deletions(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index ec6d8ab..1d030af 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -48,14 +48,17 @@ Turtle-oriented methods taking advantage of the css support: $(x).bk(50) // Back. $(x).rt(90) // Right turn. $(x).lt(45) // Left turn. + $(x).move(x, y) // Move right by x while moving forward by y. + $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion on page. + $(x).turnto(bearing || position) // Absolute direction adjustment. // Methods below happen in an instant, but queue after animation. + $(x).home() // Moves to the origin of the document, turned up. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. $(x).dot(12) // Draws a circular dot of diameter 12. + $(x).speed(10) // Sets turtle animation speed to 10 moves per sec. $(x).erase() // Erases under the turtles collision hull. $(x).img('blue') // Switch the image to a blue pointer. May use any url. - $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion in page coordinates. - $(x).turnto(heading || position) // Absolute heading adjustment. $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". $(x).mirror(true) // Flips the turtle across its main axis. @@ -64,7 +67,8 @@ Turtle-oriented methods taking advantage of the css support: // Methods below this line do not queue for animation. $(x).origin() // Page coordinate position of transform-origin. - $(x).bearing() // Absolute direction taking into account all transforms. + $(x).bearing([p]) // Absolute direction on page. + $(x).distance(p) // Distance to p in page coordinates. $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") $(x).touches(y) // Collision tests elements (uses turtleHull if present). @@ -74,7 +78,7 @@ Turtle-oriented methods taking advantage of the css support: When $.fx.speeds.turtle is nonzero (the default is zero unless -$.turtle() is called), the first four movement functions animate +$.turtle() is called), the first seven movement functions animate at that speed, and the remaining mutators also participate in the animation queue. Note that property-reading functions such as touches() are synchronous and will not queue, and setting @@ -97,16 +101,18 @@ Turtle-oriented 2d transform cssHooks, with animation support on all motion:
    +  $(x).css('turtleSpeed', '10');         // default speed in moves per second.
       $(x).css('turtlePosition', '30 40');   // position in local coordinates.
       $(x).css('turtlePositionX', '30');     // x component.
       $(x).css('turtlePositionY', '40');     // y component.
       $(x).css('turtleRotation', '90');      // rotation in degrees.
       $(x).css('turtleScale', '2');          // double the size of any element.
    -  $(x).css('turtleScaleX', '2');         // x stretch before rotate after twist.
    -  $(x).css('turtleScaleY', '2');         // y stretch before rotate after twist.
    +  $(x).css('turtleScaleX', '2');         // x stretch after twist.
    +  $(x).css('turtleScaleY', '2');         // y stretch after twist.
       $(x).css('turtleTwist', '45');         // turn before stretching.
       $(x).css('turtleForward', '50');       // position in direction of rotation.
       $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    +  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
       $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
     
    @@ -146,13 +152,13 @@ After eval($.turtle()): keydown // The last keydown event. keyup // The last keyup event. keypress // The last keypress event. - speed(movesPerSec) // Sets $.fx.speeds.turtle to 1000 / movesPerSec. + turtlespeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. tick([perSec,] fn) // Sets fn as the tick callback (null to clear). random(n) // Returns a random number [0...n-1]. random(list) // Returns a random element of the list. random('normal') // Returns a gaussian random (mean 0 stdev 1). random('uniform') // Returns a uniform random [0...1). - random('position') // Returns a random {pageX:x, pageY:y} in the document. + random('position') // Returns a random {pageX:x, pageY:y} coordinate. remove() // Removes default turtle and its globals (fd, etc). hatch([n,], [img]) // Creates and returns n turtles with the given img. see(a, b, c...) // Logs tree-expandable data into debugging panel. @@ -166,26 +172,26 @@ in CoffeeScript syntax:
     speed Infinity
    -output "Try to catch blue."
    +output "Catch blue before red gets you."
    +bk 100
     r = hatch 'red'
     b = hatch 'blue'
    -safe = 20
     tick 10, ->
       turnto lastmousemove
       fd 6
    -  if safe > 0
    -    safe = safe - 1
    -  else
    -    r.turnto turtle
    -    r.fd 4
    -    b.turnto r
    -    b.fd 3
    -    if b.touches(turtle)
    -      output "You win!"
    -      tick null
    -    else if r.touches(turtle)
    -      output "Too slow!"
    -      tick null
    +  r.turnto turtle
    +  r.fd 4
    +  b.turnto bearing b
    +  b.fd 3
    +  if b.touches(turtle)
    +    output "You win!"
    +    tick off
    +  else if r.touches(turtle)
    +    output "Red got you!"
    +    tick off
    +  else if not b.touches(document)
    +    output "Blue got away!"
    +    tick off
     
    The turtle teaching environment is designed to work well with either @@ -703,7 +709,7 @@ function readPageGbcr() { // to get origin position; then calculate displacement needed to move // turtle to target coordinates (again reversing parent distortions // if possible). -function setCenterInPageCoordinates(elem, target, limit, localx, localy) { +function computeTargetAsTurtlePosition(elem, target, limit, localx, localy) { var totalParentTransform = totalTransform2x2(elem.parentElement), inverseParent = inverse2x2(totalParentTransform), hidden = ($.css(elem, 'display') === 'none'), @@ -714,9 +720,10 @@ function setCenterInPageCoordinates(elem, target, limit, localx, localy) { gbcr = cleanSwap(elem, swapout, readPageGbcr), middle = readTransformOrigin(elem, [gbcr.width, gbcr.height]), origin = addVector([gbcr.left, gbcr.top], middle), - pos, current, translation, localTarget; + pos, current, tr, localTarget; if (!inverseParent) { return; } if ($.isNumeric(limit)) { + tr = getElementTranslation(elem); pos = addVector(matrixVectorProduct(totalParentTransform, tr), origin); current = { pageX: pos[0], @@ -732,7 +739,7 @@ function setCenterInPageCoordinates(elem, target, limit, localx, localy) { localTarget[0] += Math.cos(r) * localx + Math.sin(r) * localy; localTarget[1] += Math.sin(r) * localx - Math.cos(r) * localy; } - $.style(elem, 'turtlePosition', localTarget.join(' ')); + return cssNum(localTarget[0]) + ' ' + cssNum(localTarget[1]); } // Uses getBoundingClientRect to figure out current position in page @@ -815,7 +822,7 @@ function getCornersInPageCoordinates(elem, untransformed) { }); } -function setDirectionOnPage(elem, target, limit) { +function computeDirectionAsTurtleRotation(elem, target, limit) { var totalParentTransform = totalTransform2x2(elem.parentElement), inverseParent = inverse2x2(totalParentTransform), ts = readTurtleTransform(elem, true); @@ -832,8 +839,7 @@ function setDirectionOnPage(elem, target, limit) { var rt = convertToRadians(target), lp = matrixVectorProduct(inverseParent, [Math.sin(rt), Math.cos(rt)]), tr = Math.atan2(lp[0], lp[1]); - ts.rot = radiansToDegrees(tr); - elem.style[transform] = writeTurtleTransform(ts); + return radiansToDegrees(tr); } function getDirectionOnPage(elem) { @@ -1270,8 +1276,8 @@ function writePenStyle(style) { } function parsePenDown(style) { - if (style == 'down') return true; - if (style == 'up') return false; + if (style == 'down' || style === true) return true; + if (style == 'up' || style === false) return false; return undefined; } @@ -1285,7 +1291,8 @@ function getTurtleData(elem) { state = $.data(elem, 'turtleData', { style: {}, path: [[]], - down: true + down: true, + speed: 'turtle' }); } return state; @@ -1447,13 +1454,15 @@ function applyImg(sel, img) { function doQuickMove(elem, distance, sideways) { var ts = readTurtleTransform(elem, true), - r = (ts || 0) && convertToRadians(ts.rot), - dy = -Math.cos(r) * distance, - dx = Math.sin(r) * distance; + r = ts && convertToRadians(ts.rot), + scaledDistance = ts && (distance * ts.sy), + scaledSideways = ts && ((sideways || 0) * ts.sx), + dy = -Math.cos(r) * scaledDistance, + dx = Math.sin(r) * scaledDistance; if (!ts) { return; } if (sideways) { - dy += Math.sin(r) * sideways; - dx += Math.cos(r) * sideways; + dy += Math.sin(r) * scaledSideways; + dx += Math.cos(r) * scaledSideways; } ts.tx += dx; ts.ty += dy; @@ -1463,9 +1472,9 @@ function doQuickMove(elem, distance, sideways) { function displacedPosition(elem, distance, sideways) { var ts = readTurtleTransform(elem, true), - r = (ts || 0) && convertToRadians(ts.rot), - scaledDistance = (ts || 0) && (distance * ts.sy), - scaledSideways = (ts || 0) && ((sideways || 0) * ts.sx), + r = ts && convertToRadians(ts.rot), + scaledDistance = ts && (distance * ts.sy), + scaledSideways = ts && ((sideways || 0) * ts.sx), dy = -Math.cos(r) * scaledDistance, dx = Math.sin(r) * scaledDistance; if (!ts) { return; } @@ -1480,6 +1489,30 @@ function isPageCoordinate(obj) { return $.isNumeric(obj.pageX) && $.isNumeric(obj.pageY); } +function makeTurtleSpeedHook() { + return { + get: function(elem, computed, extra) { + return getTurtleData(elem).speed; + }, + set: function(elem, value) { + if ((!$.isNumeric(value) || value <= 0) && + !(value in $.fx.speeds) && ('' + value != 'Infinity')) { + return; + } + getTurtleData(elem).speed = '' + value; + } + } +} + +function animMs(elem) { + var state = $.data(elem, 'turtleData'); + if (!state) return 'turtle'; + if ($.isNumeric(state.speed) || state.speed == 'Infinity') { + return 1000 / state.speed; + } + return state.speed; +} + function makeTurtleForwardHook() { return { get: function(elem, computed, extra) { @@ -1670,6 +1703,7 @@ $.extend(true, $, { cssHooks: { turtlePenStyle: makePenStyleHook(), turtlePenDown: makePenDownHook(), + turtleSpeed: makeTurtleSpeedHook(), turtleForward: makeTurtleForwardHook(), turtlePosition: makeTurtleXYHook('turtlePosition', 'tx', 'ty', true), turtlePositionX: makeTurtleHook('tx', identity, 'px', true), @@ -1682,6 +1716,7 @@ $.extend(true, $, { turtleHull: makeHullHook() }, cssNumber: { + turtleSpeed: true, turtleScale: true, turtleScaleX: true, turtleScaleY: true, @@ -1705,48 +1740,103 @@ $.extend(true, $.fx, { var turtlefn = { rt: function(amount) { - return this.animate({'turtleRotation': '+=' + amount}, 'turtle'); + return this.direct(function(j, elem) { + this.animate({turtleRotation: '+=' + amount}, animMs(elem)); + }); }, lt: function(amount) { - return this.animate({'turtleRotation': '-=' + amount}, 'turtle'); + return this.direct(function(j, elem) { + this.animate({turtleRotation: '-=' + amount}, animMs(elem)); + }); }, - fd: function(amount, y) { + fd: function(amount) { + var elem, q, doqueue; + if (this.length == 1 && !$.fx.speeds.turtle && + animMs(elem = this[0]) == 'turtle') { + q = $.queue(elem); + doqueue = (q.length > 0); + function domove() { + doQuickMove(elem, amount, 0); + if (doqueue) { $.dequeue(elem); } + } + if (doqueue) { + domove.finish = domove; + q.push(domove); + } else { + domove(); + } + } + return this.direct(function(j, elem) { + this.animate({turtleForward: '+=' + amount}, animMs(elem)); + }); + }, + bk: function(amount) { + return this.fd(-amount); + }, + move: function(amount, y) { var sideways = 0; if (y !== undefined) { sideways = amount; amount = y; } - // Fast path: do the move directly when there is no animation. - if (!$.fx.speeds.turtle) { - return this.each(function(j, elem) { - var q = $.queue(elem), doqueue = (q && q.length > 0); - function domove() { - doQuickMove(elem, amount, sideways); - if (doqueue) { $.dequeue(elem); } - } - if (doqueue) { - domove.finish = domove; - q.push(domove); - } else { - domove(); - } - }); + return this.direct(function(j, elem) { + this.animate({turtlePosition: + displacedPosition(elem, amount, sideways)}, animMs(elem)); + }); + }, + moveto: function(position, limit, y) { + if ($.isNumeric(position) && $.isNumeric(limit)) { + position = { pageX: parseFloat(position), pageY: parseFloat(limit) }; + limit = null; } - if (!sideways) { - return this.animate({'turtleForward': '+=' + amount}, 'turtle'); - } else { - return this.direct(function(j, elem) { - this.animate({'turtlePosition': - displacedPosition(elem, amount, sideways)}, 'turtle'); - }); + var localx = 0, localy = 0; + if ($.isNumeric(y) && $.isNumeric(limit)) { + localx = limit; + localy = y; + limit = null; } + return this.direct(function(j, elem) { + var pos = position; + if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } + if (!pos || !isPageCoordinate(pos)) return this; + if ($.isWindow(elem)) { + scrollWindowToDocumentPosition(pos, limit); + return; + } else if (elem.nodeType === 9) { + return; + } + this.animate({turtlePosition: + computeTargetAsTurtlePosition(elem, pos, limit, localx, localy)}, + animMs(elem)); + }); }, - bk: function(amount) { - return this.fd(-amount); + turnto: function(bearing, limit) { + return this.direct(function(j, elem) { + if ($.isWindow(elem) || elem.nodeType === 9) return; + var dir = bearing; + if (!$.isNumeric(bearing)) { + var pos = bearing, cur = $(elem).origin(); + if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } + if (!pos || !isPageCoordinate(pos)) return; + dir = radiansToDegrees( + Math.atan2(pos.pageX - cur.pageX, cur.pageY - pos.pageY)); + } + this.animate({turtleRotation: + computeDirectionAsTurtleRotation(elem, dir, limit)}, animMs(elem)); + }); + }, + home: function() { + return this.direct(function(j, elem) { + this.css({ + turtlePosition: + computeTargetAsTurtlePosition(elem, $(document).origin(), null, 0, 0), + turtleRotation: 0}); + }); }, pen: function(penstyle) { return this.direct(function(j, elem) { - if (penstyle == 'down' || penstyle == 'up') { + if (penstyle === false || penstyle === true || + penstyle == 'down' || penstyle == 'up') { this.css('turtlePenDown', penstyle); } else { this.css('turtlePenStyle', penstyle); @@ -1779,6 +1869,11 @@ var turtlefn = { watchImageToFixOriginOnLoad(elem); }); }, + speed: function(mps) { + return this.direct(function(j, elem) { + this.css('turtleSpeed', mps); + }); + }, img: function (name) { var img = nameToImg(name); if (!img) return this; @@ -1804,52 +1899,27 @@ var turtlefn = { if (!this.length) return; return getCenterInPageCoordinates(this[0]); }, - moveto: function(position, limit, y) { - if ($.isNumeric(position) && $.isNumeric(limit)) { - position = { pageX: parseFloat(position), pageY: parseFloat(limit) }; - limit = null; - } - var localx = 0, localy = 0; - if ($.isNumeric(y) && $.isNumeric(limit)) { - localx = limit; - localy = y; - limit = null; - } - return this.direct(function(j, elem) { - var pos = position; - if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } - if (!pos || !isPageCoordinate(pos)) return this; - if ($.isWindow(elem)) { - scrollWindowToDocumentPosition(pos, limit); - return; - } else if (elem.nodeType === 9) { - return; - } - setCenterInPageCoordinates(elem, pos, limit, localx, localy); - // moveto implies a request for a stable origin. - watchImageToFixOriginOnLoad(elem); - flushPenState(elem); - }); - }, - bearing: function() { + bearing: function(pos, y) { if (!this.length) return; - var elem = this[0], dir; + var elem = this[0], dir, cur; + if (pos !== undefined) { + cur = $(elem).origin(); + if ($.isNumeric(y) && $.isNumeric(x)) { pos = { pageX: pos, pageY: y }; } + else if (!isPageCoordinate(pos)) { pos = $(pos).origin(); } + return radiansToDegrees( + Math.atan2(pos.pageX - cur.pageX, cur.pageY - pos.pageY)); + } if ($.isWindow(elem) || elem.nodeType === 9) return 0; return getDirectionOnPage(elem); }, - turnto: function(bearing, limit) { - return this.direct(function(j, elem) { - if ($.isWindow(elem) || elem.nodeType === 9) return; - var dir = bearing; - if (!$.isNumeric(bearing)) { - var pos = bearing, cur = $(elem).origin(); - if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } - if (!pos || !isPageCoordinate(pos)) return; - dir = radiansToDegrees( - Math.atan2(pos.pageX - cur.pageX, cur.pageY - pos.pageY)); - } - setDirectionOnPage(elem, dir, limit); - }); + distance: function(pos, y) { + if (!this.length) return; + var elem = this[0], dx, dy, cur = $(elem).origin(); + if ($.isNumeric(y) && $.isNumeric(x)) { pos = { pageX: pos, pageY: y }; } + else if (!isPageCoordinate(pos)) { pos = $(pos).origin(); } + dx = pos.pageX - cur.pageX; + dy = pos.pageY - cur.pageY; + return Math.sqrt(dx * dx + dy * dy); }, mirror: function(val) { if (val === undefined) { @@ -2037,7 +2107,8 @@ var attaching_ids = false; var dollar_turtle_methods = { erase: function() { directIfGlobal(function() { $(document).erase() }); }, tick: function(x, y) { directIfGlobal(function() { tick(x, y); }); }, - speed: function(mps) { directIfGlobal(function() { speed(mps); }); }, + turtlespeed: function(mps) { + directIfGlobal(function() { turtlespeed(mps); }); }, random: random, hatch: hatch, input: input, @@ -2095,8 +2166,8 @@ $.turtle = function turtle(id, options) { if (!options.hasOwnProperty('functions') || options.functions) { $.extend(window, dollar_turtle_methods); } - // Set turtle speed - speed(options.hasOwnProperty('speed') ? options.speed : 1); + // Set default turtle speed + turtlespeed(options.hasOwnProperty('turtlespeed') ? options.turtlespeed : 1); // Find or create a singleton turtle if one does not exist. var selector = null; if (id) { @@ -2330,7 +2401,7 @@ function hatchone(name) { 'display': 'inline-block', 'top': 0, 'left': 0 - }).appendTo(getTurtleClipSurface()).moveto(document); + }).appendTo(getTurtleClipSurface()).home(); // Every hatched turtle has class="turtle". result.addClass('turtle'); @@ -2377,8 +2448,10 @@ function random(arg) { // Simplify setInterval(fn, 1000) to just tick(fn). var tickinterval = null; function tick(rps, fn) { - fn = arguments.length >= 2 ? fn : rps; - rps = arguments.length > 1 && $.isNumeric(rps) ? rps : 1; + if (fn === undefined && $.isFunction(rps)) { + fn = rps; + rps = 1; + } if (tickinterval) { window.clearInterval(tickinterval); tickinterval = null; @@ -2389,7 +2462,7 @@ function tick(rps, fn) { } // Allow speed to be set in moves per second. -function speed(mps) { +function turtlespeed(mps) { if (mps === undefined) { return 1000 / $.fx.speeds.turtle; } else { From f00372aea874c366242338d77ed3014274bf464b Mon Sep 17 00:00:00 2001 From: davidbau Date: Sat, 1 Jun 2013 06:17:07 -0700 Subject: [PATCH 09/25] Create gh-pages branch via GitHub --- index.html | 59 ++++++++++++++++++++++++++++------------------------- params.json | 2 +- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/index.html b/index.html index ccd1b4d..9fe75b8 100644 --- a/index.html +++ b/index.html @@ -50,9 +50,6 @@

    positioning, and absolute direction reading and setting.

    Try an interactive demo (CoffeeScript syntax) here.

    -

    Under the covers, CSS3 2D transforms and jQuery animations are used to execute and store turtle movement, so jQuery-turtle @@ -82,14 +79,17 @@

    $(x).bk(50) // Back. $(x).rt(90) // Right turn. $(x).lt(45) // Left turn. + $(x).move(x, y) // Move right by x while moving forward by y. + $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion on page. + $(x).turnto(bearing || position) // Absolute direction adjustment. // Methods below happen in an instant, but queue after animation. + $(x).home() // Moves to the origin of the document, turned up. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. $(x).dot(12) // Draws a circular dot of diameter 12. + $(x).speed(10) // Sets turtle animation speed to 10 moves per sec. $(x).erase() // Erases under the turtles collision hull. $(x).img('blue') // Switch the image to a blue pointer. May use any url. - $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion in page coordinates. - $(x).turnto(heading || position) // Absolute heading adjustment. $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". $(x).mirror(true) // Flips the turtle across its main axis. @@ -98,7 +98,8 @@

    // Methods below this line do not queue for animation. $(x).origin() // Page coordinate position of transform-origin. - $(x).bearing() // Absolute direction taking into account all transforms. + $(x).bearing([p]) // Absolute direction on page. + $(x).distance(p) // Distance to p in page coordinates. $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") $(x).touches(y) // Collision tests elements (uses turtleHull if present). @@ -108,7 +109,7 @@

    When $.fx.speeds.turtle is nonzero (the default is zero unless -$.turtle() is called), the first four movement functions animate +$.turtle() is called), the first seven movement functions animate at that speed, and the remaining mutators also participate in the animation queue. Note that property-reading functions such as touches() are synchronous and will not queue, and setting @@ -131,16 +132,18 @@

    motion:

    +  $(x).css('turtleSpeed', '10');         // default speed in moves per second.
       $(x).css('turtlePosition', '30 40');   // position in local coordinates.
       $(x).css('turtlePositionX', '30');     // x component.
       $(x).css('turtlePositionY', '40');     // y component.
       $(x).css('turtleRotation', '90');      // rotation in degrees.
       $(x).css('turtleScale', '2');          // double the size of any element.
    -  $(x).css('turtleScaleX', '2');         // x stretch before rotate after twist.
    -  $(x).css('turtleScaleY', '2');         // y stretch before rotate after twist.
    +  $(x).css('turtleScaleX', '2');         // x stretch after twist.
    +  $(x).css('turtleScaleY', '2');         // y stretch after twist.
       $(x).css('turtleTwist', '45');         // turn before stretching.
       $(x).css('turtleForward', '50');       // position in direction of rotation.
    -  $(x).css('turtlePen', 'red');          // or 'red lineWidth 2px' etc.
    +  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    +  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
       $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
     
    @@ -181,13 +184,13 @@

    keydown // The last keydown event. keyup // The last keyup event. keypress // The last keypress event. - speed(movesPerSec) // Sets $.fx.speeds.turtle to 1000 / movesPerSec. + turtlespeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. tick([perSec,] fn) // Sets fn as the tick callback (null to clear). random(n) // Returns a random number [0...n-1]. random(list) // Returns a random element of the list. random('normal') // Returns a gaussian random (mean 0 stdev 1). random('uniform') // Returns a uniform random [0...1). - random('position') // Returns a random {pageX:x, pageY:y} in the document. + random('position') // Returns a random {pageX:x, pageY:y} coordinate. remove() // Removes default turtle and its globals (fd, etc). hatch([n,], [img]) // Creates and returns n turtles with the given img. see(a, b, c...) // Logs tree-expandable data into debugging panel. @@ -201,26 +204,26 @@

     speed Infinity
    -output "Try to catch blue."
    +output "Catch blue before red gets you."
    +bk 100
     r = hatch 'red'
     b = hatch 'blue'
    -safe = 20
     tick 10, ->
       turnto lastmousemove
       fd 6
    -  if safe > 0
    -    safe = safe - 1
    -  else
    -    r.turnto turtle
    -    r.fd 4
    -    b.turnto r
    -    b.fd 3
    -    if b.touches(turtle)
    -      output "You win!"
    -      tick null
    -    else if r.touches(turtle)
    -      output "Too slow!"
    -      tick null
    +  r.turnto turtle
    +  r.fd 4
    +  b.turnto bearing b
    +  b.fd 3
    +  if b.touches(turtle)
    +    output "You win!"
    +    tick off
    +  else if r.touches(turtle)
    +    output "Red got you!"
    +    tick off
    +  else if not b.touches(document)
    +    output "Blue got away!"
    +    tick off
     

    The turtle teaching environment is designed to work well with either @@ -256,4 +259,4 @@

    - + \ No newline at end of file diff --git a/params.json b/params.json index 5ee6339..a36b177 100644 --- a/params.json +++ b/params.json @@ -1 +1 @@ -{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using LOGO-inspired turtle methods like fd, bk, rt, and lt.\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\nThe plugin also provides functions to help in a rotated,\r\nscaled, and transformed world where nested elements may be\r\ntransformed. There are functions for collision testing, absolute\r\npositioning, and absolute direction reading and setting.\r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\nUnder the covers, CSS3 2D transforms and jQuery animations are\r\nused to execute and store turtle movement, so jQuery-turtle\r\ninteracts well with other jQuery animations or direct uses of\r\n2D CSS3 transforms. The plugin sets up jQuery CSS hooks for\r\nsynthetic CSS properties such as turtleForward that can be\r\nanimated or used to directly manipulate turtle geometry at a basic\r\nmathematical level.\r\n\r\nA high-level educational environment is enabled by $.turtle().\r\nThat call creates a set of global objects and functions\r\ncatering to beginners. These include a default turtle\r\nand global functions to control it; an onpage debugger panel;\r\njQuery instances for every object with an #id; simplified\r\nglobals to access recent mouse and keyboard events, and\r\nsimplified functions for randomness, timers, animation control,\r\nand creation of new turtles. The jQuery teaching environment\r\nhas been developed to support a curriculum for young students.\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nTurtle-oriented methods taking advantage of the css support:\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n\r\n  // Methods below happen in an instant, but queue after animation.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).erase()      // Erases under the turtles collision hull.\r\n  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion in page coordinates.\r\n  $(x).turnto(heading || position)      // Absolute heading adjustment.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate position of transform-origin.\r\n  $(x).bearing()    // Absolute direction taking into account all transforms.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n
    \r\n\r\nWhen $.fx.speeds.turtle is nonzero (the default is zero unless\r\n$.turtle() is called), the first four movement functions animate\r\nat that speed, and the remaining mutators also participate in the\r\nanimation queue. Note that property-reading functions such as\r\ntouches() are synchronous and will not queue, and setting\r\n$.fx.speed.turtle to 0 will make movement functions synchronous.\r\n\r\nThe absolute motion methods moveto and turnto accept any argument\r\nwith pageX and pageY, including, usefully, mouse events. They\r\noperate in absolute page coordinates even when the turtle is nested\r\nwithin further transformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test using\r\nthe convex hull for the two objects in question. This defaults to\r\nthe bounding box of the elements (as transformed) but can be overridden\r\nby the turtleHull CSS property, if present.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nTurtle-oriented 2d transform cssHooks, with animation support on all\r\nmotion:\r\n\r\n
    \r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch before rotate after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch before rotate after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePen', 'red');          // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nAn optional teaching environment setup is created by eval($.turtle()).\r\nIt provides easy packaging for the above functionality.\r\n\r\nAfter eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * And the following are defined:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  speed(movesPerSec)    // Sets $.fx.speeds.turtle to 1000 / movesPerSec.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} in the document.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  output(html || text)  // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n
    \r\n\r\nFor example, after eval($.turtle()), the following is a valid program\r\nin CoffeeScript syntax:\r\n\r\n
    \r\nspeed Infinity\r\noutput \"Try to catch blue.\"\r\nr = hatch 'red'\r\nb = hatch 'blue'\r\nsafe = 20\r\ntick 10, ->\r\n  turnto lastmousemove\r\n  fd 6\r\n  if safe > 0\r\n    safe = safe - 1\r\n  else\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto r\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      output \"You win!\"\r\n      tick null\r\n    else if r.touches(turtle)\r\n      output \"Too slow!\"\r\n      tick null\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file +{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using LOGO-inspired turtle methods like fd, bk, rt, and lt.\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\nThe plugin also provides functions to help in a rotated,\r\nscaled, and transformed world where nested elements may be\r\ntransformed. There are functions for collision testing, absolute\r\npositioning, and absolute direction reading and setting.\r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\nUnder the covers, CSS3 2D transforms and jQuery animations are\r\nused to execute and store turtle movement, so jQuery-turtle\r\ninteracts well with other jQuery animations or direct uses of\r\n2D CSS3 transforms. The plugin sets up jQuery CSS hooks for\r\nsynthetic CSS properties such as turtleForward that can be\r\nanimated or used to directly manipulate turtle geometry at a basic\r\nmathematical level.\r\n\r\nA high-level educational environment is enabled by $.turtle().\r\nThat call creates a set of global objects and functions\r\ncatering to beginners. These include a default turtle\r\nand global functions to control it; an onpage debugger panel;\r\njQuery instances for every object with an #id; simplified\r\nglobals to access recent mouse and keyboard events, and\r\nsimplified functions for randomness, timers, animation control,\r\nand creation of new turtles. The jQuery teaching environment\r\nhas been developed to support a curriculum for young students.\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nTurtle-oriented methods taking advantage of the css support:\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).move(x, y)   // Move right by x while moving forward by y.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)      // Absolute direction adjustment.\r\n\r\n  // Methods below happen in an instant, but queue after animation.\r\n  $(x).home()       // Moves to the origin of the document, turned up.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).erase()      // Erases under the turtles collision hull.\r\n  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate position of transform-origin.\r\n  $(x).bearing([p]) // Absolute direction on page.\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n
    \r\n\r\nWhen $.fx.speeds.turtle is nonzero (the default is zero unless\r\n$.turtle() is called), the first seven movement functions animate\r\nat that speed, and the remaining mutators also participate in the\r\nanimation queue. Note that property-reading functions such as\r\ntouches() are synchronous and will not queue, and setting\r\n$.fx.speed.turtle to 0 will make movement functions synchronous.\r\n\r\nThe absolute motion methods moveto and turnto accept any argument\r\nwith pageX and pageY, including, usefully, mouse events. They\r\noperate in absolute page coordinates even when the turtle is nested\r\nwithin further transformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test using\r\nthe convex hull for the two objects in question. This defaults to\r\nthe bounding box of the elements (as transformed) but can be overridden\r\nby the turtleHull CSS property, if present.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nTurtle-oriented 2d transform cssHooks, with animation support on all\r\nmotion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nAn optional teaching environment setup is created by eval($.turtle()).\r\nIt provides easy packaging for the above functionality.\r\n\r\nAfter eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * And the following are defined:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  turtlespeed(mps)      // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  output(html || text)  // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n
    \r\n\r\nFor example, after eval($.turtle()), the following is a valid program\r\nin CoffeeScript syntax:\r\n\r\n
    \r\nspeed Infinity\r\noutput \"Catch blue before red gets you.\"\r\nbk 100\r\nr = hatch 'red'\r\nb = hatch 'blue'\r\ntick 10, ->\r\n  turnto lastmousemove\r\n  fd 6\r\n  r.turnto turtle\r\n  r.fd 4\r\n  b.turnto bearing b\r\n  b.fd 3\r\n  if b.touches(turtle)\r\n    output \"You win!\"\r\n    tick off\r\n  else if r.touches(turtle)\r\n    output \"Red got you!\"\r\n    tick off\r\n  else if not b.touches(document)\r\n    output \"Blue got away!\"\r\n    tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file From ea8b9727099b4d1063794353abc7cf439930c90f Mon Sep 17 00:00:00 2001 From: David Bau Date: Sat, 1 Jun 2013 09:18:32 -0400 Subject: [PATCH 10/25] Add iframe. --- index.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 9fe75b8..d1ccb9e 100644 --- a/index.html +++ b/index.html @@ -51,6 +51,10 @@

    Try an interactive demo (CoffeeScript syntax) here.

    + +

    Under the covers, CSS3 2D transforms and jQuery animations are used to execute and store turtle movement, so jQuery-turtle interacts well with other jQuery animations or direct uses of @@ -259,4 +263,4 @@

    - \ No newline at end of file + From 6ba241c4c256ad61239d61c4146f59e00c241e1d Mon Sep 17 00:00:00 2001 From: David Bau Date: Sat, 1 Jun 2013 12:06:05 -0400 Subject: [PATCH 11/25] Fix example. --- index.html | 2 +- jquery-turtle.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index d1ccb9e..09b7115 100644 --- a/index.html +++ b/index.html @@ -207,7 +207,7 @@

    in CoffeeScript syntax:

    -speed Infinity
    +turtlespeed Infinity
     output "Catch blue before red gets you."
     bk 100
     r = hatch 'red'
    diff --git a/jquery-turtle.js b/jquery-turtle.js
    index 1d030af..fa5fb14 100644
    --- a/jquery-turtle.js
    +++ b/jquery-turtle.js
    @@ -171,7 +171,7 @@ For example, after eval($.turtle()), the following is a valid program
     in CoffeeScript syntax:
     
     
    -speed Infinity
    +turtlespeed Infinity
     output "Catch blue before red gets you."
     bk 100
     r = hatch 'red'
    
    From 83e532f0b77502fa1b73c01de9e8975c93047d1c Mon Sep 17 00:00:00 2001
    From: David Bau 
    Date: Wed, 12 Jun 2013 00:45:20 -0400
    Subject: [PATCH 12/25] Update version.
    
    ---
     jquery-turtle.js | 302 +++++++++++++++++++++++++++++++++++++++++------
     1 file changed, 268 insertions(+), 34 deletions(-)
    
    diff --git a/jquery-turtle.js b/jquery-turtle.js
    index fa5fb14..3c64e41 100644
    --- a/jquery-turtle.js
    +++ b/jquery-turtle.js
    @@ -56,6 +56,7 @@ Turtle-oriented methods taking advantage of the css support:
       $(x).home()       // Moves to the origin of the document, turned up.
       $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.
       $(x).dot(12)      // Draws a circular dot of diameter 12.
    +  $(x).mark('A')    // Prints an HTML inline-block at the turtle location.
       $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.
       $(x).erase()      // Erases under the turtles collision hull.
       $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.
    @@ -75,6 +76,7 @@ Turtle-oriented methods taking advantage of the css support:
       $(x).encloses(y)  // Containment collision test.
       $(x).within(d, t) // Filters to items with origins within d of t.origin().
       $(x).notwithin()  // The negation of within.
    +  $(x).cell(x, y)   // Selects the yth row and xth column cell in a table.
     
    When $.fx.speeds.turtle is nonzero (the default is zero unless @@ -152,7 +154,7 @@ After eval($.turtle()): keydown // The last keydown event. keyup // The last keyup event. keypress // The last keypress event. - turtlespeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. + defaultspeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. tick([perSec,] fn) // Sets fn as the tick callback (null to clear). random(n) // Returns a random number [0...n-1]. random(list) // Returns a random element of the list. @@ -162,17 +164,19 @@ After eval($.turtle()): remove() // Removes default turtle and its globals (fd, etc). hatch([n,], [img]) // Creates and returns n turtles with the given img. see(a, b, c...) // Logs tree-expandable data into debugging panel. - output(html || text) // Appends html into the document body. + print(html) // Appends html into the document body. input([label,] fn) // Makes a one-time input field, calls fn after entry. button([label,] fn) // Makes a clickable button, calls fn when clicked. + table(w, h) // Outputs a table with h rows and w columns. + play("ccggaag2") // Plays a couple measures of song using ABC notation.
    For example, after eval($.turtle()), the following is a valid program in CoffeeScript syntax:
    -turtlespeed Infinity
    -output "Catch blue before red gets you."
    +defaultspeed Infinity
    +print "Catch blue before red gets you."
     bk 100
     r = hatch 'red'
     b = hatch 'blue'
    @@ -184,13 +188,13 @@ tick 10, ->
       b.turnto bearing b
       b.fd 3
       if b.touches(turtle)
    -    output "You win!"
    +    print "You win!"
         tick off
       else if r.touches(turtle)
    -    output "Red got you!"
    +    print "Red got you!"
         tick off
       else if not b.touches(document)
    -    output "Blue got away!"
    +    print "Blue got away!"
         tick off
     
    @@ -560,8 +564,8 @@ function limitRotation(start, target, limit) { return normalizeRotation(target); } -function getCenterLTWH(x0, y0, w, h) { - return { pageX: x0 + w / 2, pageY: y0 + h / 2 }; +function getRoundedCenterLTWH(x0, y0, w, h) { + return { pageX: Math.floor(x0 + w / 2), pageY: Math.floor(y0 + h / 2) }; } function getStraightRectLTWH(x0, y0, w, h) { @@ -749,10 +753,10 @@ function computeTargetAsTurtlePosition(elem, target, limit, localx, localy) { // to get the final x and y, returned as {pageX:, pagey:}. function getCenterInPageCoordinates(elem) { if ($.isWindow(elem)) { - return getCenterLTWH( + return getRoundedCenterLTWH( $(window).scrollLeft(), $(window).scrollTop(), ww(), wh()); } else if (elem.nodeType === 9) { - return getCenterLTWH(0, 0, dw(), dh()); + return getRoundedCenterLTWH(0, 0, dw(), dh()); } var tr = getElementTranslation(elem), totalParentTransform = totalTransform2x2(elem.parentElement), @@ -1504,7 +1508,7 @@ function makeTurtleSpeedHook() { } } -function animMs(elem) { +function animTime(elem) { var state = $.data(elem, 'turtleData'); if (!state) return 'turtle'; if ($.isNumeric(state.speed) || state.speed == 'Infinity') { @@ -1741,18 +1745,18 @@ $.extend(true, $.fx, { var turtlefn = { rt: function(amount) { return this.direct(function(j, elem) { - this.animate({turtleRotation: '+=' + amount}, animMs(elem)); + this.animate({turtleRotation: '+=' + amount}, animTime(elem)); }); }, lt: function(amount) { return this.direct(function(j, elem) { - this.animate({turtleRotation: '-=' + amount}, animMs(elem)); + this.animate({turtleRotation: '-=' + amount}, animTime(elem)); }); }, fd: function(amount) { var elem, q, doqueue; if (this.length == 1 && !$.fx.speeds.turtle && - animMs(elem = this[0]) == 'turtle') { + animTime(elem = this[0]) == 'turtle') { q = $.queue(elem); doqueue = (q.length > 0); function domove() { @@ -1765,9 +1769,10 @@ var turtlefn = { } else { domove(); } + return this; } return this.direct(function(j, elem) { - this.animate({turtleForward: '+=' + amount}, animMs(elem)); + this.animate({turtleForward: '+=' + amount}, animTime(elem)); }); }, bk: function(amount) { @@ -1781,7 +1786,7 @@ var turtlefn = { } return this.direct(function(j, elem) { this.animate({turtlePosition: - displacedPosition(elem, amount, sideways)}, animMs(elem)); + displacedPosition(elem, amount, sideways)}, animTime(elem)); }); }, moveto: function(position, limit, y) { @@ -1807,7 +1812,7 @@ var turtlefn = { } this.animate({turtlePosition: computeTargetAsTurtlePosition(elem, pos, limit, localx, localy)}, - animMs(elem)); + animTime(elem)); }); }, turnto: function(bearing, limit) { @@ -1822,15 +1827,18 @@ var turtlefn = { Math.atan2(pos.pageX - cur.pageX, cur.pageY - pos.pageY)); } this.animate({turtleRotation: - computeDirectionAsTurtleRotation(elem, dir, limit)}, animMs(elem)); + computeDirectionAsTurtleRotation(elem, dir, limit)}, animTime(elem)); }); }, home: function() { return this.direct(function(j, elem) { + var down = this.css('turtlePenDown'); + this.css({turtlePenDown: 'up' }); this.css({ turtlePosition: computeTargetAsTurtlePosition(elem, $(document).origin(), null, 0, 0), turtleRotation: 0}); + this.css({turtlePenDown: down }); }); }, pen: function(penstyle) { @@ -1844,9 +1852,11 @@ var turtlefn = { }); }, dot: function(style, diameter) { - if ($.isNumeric(style) && diameter === undefined) { - diameter = style; - style = null; + if ($.isNumeric(style)) { + // Allow for parameters in either order. + var t = style; + style = diameter; + diameter = t; } if (diameter === undefined) { diameter = 8.8; } if (!style) { style = 'black'; } @@ -1881,6 +1891,21 @@ var turtlefn = { applyImg(this, img); }); }, + mark: function(html, fn) { + return this.direct(function() { + var out = output(html, 'mark').css({ + position: 'absolute', + display: 'inline-block' + }).addClass('turtle'); + out.css({ + turtlePosition: computeTargetAsTurtlePosition( + out.get(0), this.origin(), null, 0, 0) + }); + if ($.isFunction(fn)) { + out.direct(fn); + } + }); + }, reload: function() { // Used to reload images to cycle animated gifs. return this.direct(function(j, elem) { @@ -1959,6 +1984,12 @@ var turtlefn = { this.css('turtleScale', $.map(c, cssNum).join(' ')); }); }, + cell: function(x, y) { + var sel = this.find( + $.isNumeric(y) ? 'tr:nth-of-type(' + (y + 1) + ')' : 'tr'); + return sel.find( + $.isNumeric(x) ? 'td:nth-of-type(' + (x + 1) + ')' : 'td'); + }, shown: function() { return this.is(':visible'); }, @@ -2107,13 +2138,15 @@ var attaching_ids = false; var dollar_turtle_methods = { erase: function() { directIfGlobal(function() { $(document).erase() }); }, tick: function(x, y) { directIfGlobal(function() { tick(x, y); }); }, - turtlespeed: function(mps) { - directIfGlobal(function() { turtlespeed(mps); }); }, + defaultspeed: function(mps) { + directIfGlobal(function() { defaultspeed(mps); }); }, + print: function(html) { return output(html, 'div'); }, random: random, hatch: hatch, input: input, - output: output, - button: button + button: button, + table: table, + play: play }; $.turtle = function turtle(id, options) { @@ -2167,7 +2200,7 @@ $.turtle = function turtle(id, options) { $.extend(window, dollar_turtle_methods); } // Set default turtle speed - turtlespeed(options.hasOwnProperty('turtlespeed') ? options.turtlespeed : 1); + defaultspeed(options.hasOwnProperty('defaultspeed') ? options.defaultspeed : 1); // Find or create a singleton turtle if one does not exist. var selector = null; if (id) { @@ -2438,10 +2471,16 @@ function random(arg) { } if (arg == 'position') { return { - pageX: random(dw()), - pageY: random(dh()) + pageX: random(dw() + 1), + pageY: random(dh() + 1) }; } + if (arg == 'color') { + return 'hsl(' + Math.floor(Math.random() * 360) + ',100%,50%)'; + } + if (arg == 'gray') { + return 'hsl(0,0,' + Math.floor(Math.random() * 100) + '%)'; + } return Math.random(); } @@ -2462,7 +2501,7 @@ function tick(rps, fn) { } // Allow speed to be set in moves per second. -function turtlespeed(mps) { +function defaultspeed(mps) { if (mps === undefined) { return 1000 / $.fx.speeds.turtle; } else { @@ -2507,14 +2546,23 @@ function turtleevents(prefix) { } // Simplify $('body').append(html). -function output(html) { +function output(html, defaulttag) { if (html === undefined || html === null) { return $('').img('turtle').appendTo('body'); } - if (!html || html[0] != '<') { - html = '
    ' + escapeHtml(html) + '
    '; + var wrapped = false, result = null; + html = '' + html; + while ((result === null || result.length != 1) && !wrapped) { + // Wrap if obviously not surrounded by a tag already, or if we tried + // to trust a surrounding tag but found multiple bits. + if (html.charAt(0) != '<' || html.charAt(html.length - 1) != '>' || + (result !== null && result.length != 1)) { + html = '<' + defaulttag + '>' + html + ''; + wrapped = true; + } + result = $(html); } - return $(html).appendTo('body'); + return result.appendTo('body'); } // Simplify $('body'>.append('').click(fn). @@ -2578,6 +2626,190 @@ function input(name, callback) { return thisval; } +function table(width, height, cellCss, tableCss) { + var html = ['']; + for (var row = 0; row < height; row++) { + html.push(''); + for (var col = 0; col < width; col++) { + html.push(''); + } + html.push(''); + } + html.push('
    '); + var result = $(html.join('')); + var defaultCss = { + borderCollapse: 'collapse', + width: '35px', + height: '35px', + border: '1px solid black', + tableLayout: 'fixed', + textAlign: 'center', + margin: '0', + padding: '0' + }; + result.css($.extend({}, defaultCss, cellCss, + { width: 'auto', height: 'auto', maxWidth: 'auto'}, + tableCss)); + result.find('td').css($.extend({}, defaultCss, cellCss)); + result.appendTo('body'); + return result; +} + +////////////////////////////////////////////////////////////////////////// +// WEB AUDIO SUPPORT +// Definition of play("ABC") - uses ABC music note syntax. +////////////////////////////////////////////////////////////////////////// + +var ABCtoken = /\s+|\[|\]|>+|<+|(?:(?:\^\^|\^|__|_|=|)[A-Ga-g](?:,+|'+|))|\d*\/\d+|\d+|\/+|[xzXZ]|./g; +var audioTop = null; +function getAudioTop() { + if (!audioTop) { + var ac = new (window.audioContext || window.webkitAudioContext), + dcn = ac.createDynamicsCompressor(); + dcn.connect(ac.destination); + audioTop = { + ac: ac, + out: dcn + } + } + return audioTop; +} +function parseABCNotes(str) { + var tokens = str.match(ABCtoken), result = [], stem = null, + index = 0, dotted = 0, t; + while (index < tokens.length) { + if (/^s+$/.test(tokens[index])) { index++; continue; } + if (//.test(tokens[index])) { dotted = tokens[index++].length; continue; } + stem = parseStem(tokens, index); + if (stem === null) { + // Skip unparsable bits + index++; + continue; + } + if (stem !== null) { + if (dotted && result.length) { + if (dotted > 0) { + t = (1 - Math.pow(0.5, dotted)) * stem.value.time; + } else { + t = (Math.pow(0.5, -dotted) - 1) * result[result.length - 1].time; + } + result[result.length - 1].time += t; + stem.value.time -= t; + dotted = 0; + } + result.push(stem.value); + index = stem.index; + } + } + return result; +} +function parseStem(tokens, index) { + var pitch = []; + if (index < tokens.length && tokens[index] == '[') { + index++; + while (index < tokens.length && /[A-Ga-g]/.test(tokens[index])) { + pitch.push(tokens[index++]); + } + if (tokens[index] != ']') { + return null; + } + index++; + } else if (index < tokens.length && /[A-Ga-g]/.test(tokens[index])) { + pitch.push(tokens[index++]); + } else if (/^[xzXZ]$/.test(tokens[index])) { + // Rest - no pitch. + index++; + } else { + return null; + } + var duration = ''; + if (tokens.length && /\d|\//.test(tokens[index])) { + duration = tokens[index++]; + } + return { + index: index, + value: { + pitch: pitch, + duration: duration, + frequency: pitch.map(pitchToFrequency), + time: durationToTime(duration) + } + } +} +function pitchToFrequency(pitch) { + var m = /^(\^\^|\^|__|_|=|)([A-Ga-g])(,+|'+|)$/.exec(pitch); + if (!m) { return null; } + var n = {C:-9,D:-7,E:-5,F:-4,G:-2,A:0,B:2,c:3,d:5,e:7,f:8,g:10,a:12,b:14}; + var a = { '^^':2, '^':1, '': 0, '=':0, '_':-1, '__':-2 }; + var semitone = n[m[2]] + a[m[1]] + (/,/.test(m[3]) ? -12 : 12) * m[3].length; + return 440 * Math.pow(2, semitone / 12); +} +function durationToTime(duration) { + var m = /^(\d*)(?:\/(\d*))?$|^(\/+)$/.exec(duration), n, d; + if (m[3]) return Math.pow(0.5, m[3].length); + n = (m[1] ? parseFloat(m[1]) : 1); + d = (m[2] ? parseFloat(m[2]) : /\//.test(duration) ? 2 : 1); + return n / d; +} +function play(opts) { + var atop = getAudioTop(), + start_time = atop.ac.currentTime, + firstvoice = 0, voice, freqmult, beatsecs, + volume = 0.5, tempo = 120, transpose = 0, type = ['sine']; + if ($.isPlainObject(opts)) { + if ('volume' in opts) { volume = opts.volume; } + if ('tempo' in opts) { tempo = opts.tempo; } + if ('transpose' in opts) { transpose = opts.transpose; } + if ('type' in opts) { type = opts.type; } + firstvoice = 1; + } + voice = firstvoice; + beatsecs = 60 / tempo; + freqmult = Math.pow(2, transpose / 12); + if (!$.isArray(type)) { type = [type]; } + for (; voice < arguments.length; voice++) { + var notes = parseABCNotes(arguments[voice]), + vtype = type[(voice - firstvoice) % type.length] || 'sine', + time = start_time, fingers = 0, strength, i; + for (i = 0; i < notes.length; i++) { + fingers = Math.max(fingers, notes[i].frequency.length); + } + if (fingers == 0) { continue; } + // Attenuate chorded voice so chorded power matches volume. + strength = volume / Math.sqrt(fingers); + for (i = 0; i < notes.length; i++) { + if (notes[i].frequency.length > 0) { + var g = atop.ac.createGainNode(), + secs = notes[i].time * beatsecs, + envelope, pt; + g.gain.setValueAtTime(0, time); + envelope = [ + {v: 1.0, t: Math.min(0.01 * beatsecs, 0.1 * secs)}, + {v: 0.9, t: Math.min(0.05 * beatsecs, 0.2 * secs)}, + {v: 0.6, t: Math.min(secs - 0.05 * beatsecs, 0.9 * secs)}, + {v: 0.0, t: secs} + ]; + for (var e = 0; e < envelope.length; e++) { + pt = envelope[e]; + g.gain.linearRampToValueAtTime(pt.v * strength, time + pt.t); + } + g.connect(atop.out); + for (var x = 0; x < notes[i].frequency.length; x++) { + var o = atop.ac.createOscillator(); + o.type = vtype; + o.frequency.value = notes[i].frequency[x] * freqmult; + o.connect(g); + o.start(time); + o.stop(time + secs); + } + } + time += notes[i].time * beatsecs; + } + } +} + + ////////////////////////////////////////////////////////////////////////// // SEE LOGGING SUPPORT // A copy of see.js here. @@ -3426,4 +3658,6 @@ function tryinitpanel() { } } +eval("scope('jquery-turtle', " + seejs + ", this)"); + })(jQuery); From a4ffc5a117151fc5b816662469c5471d551ca82c Mon Sep 17 00:00:00 2001 From: davidbau Date: Tue, 11 Jun 2013 22:00:00 -0700 Subject: [PATCH 13/25] Create gh-pages branch via GitHub --- index.html | 26 ++++++++++++++------------ params.json | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/index.html b/index.html index 09b7115..23bc18e 100644 --- a/index.html +++ b/index.html @@ -51,10 +51,6 @@

    Try an interactive demo (CoffeeScript syntax) here.

    - -

    Under the covers, CSS3 2D transforms and jQuery animations are used to execute and store turtle movement, so jQuery-turtle interacts well with other jQuery animations or direct uses of @@ -91,6 +87,7 @@

    $(x).home() // Moves to the origin of the document, turned up. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. $(x).dot(12) // Draws a circular dot of diameter 12. + $(x).mark('A') // Prints an HTML inline-block at the turtle location. $(x).speed(10) // Sets turtle animation speed to 10 moves per sec. $(x).erase() // Erases under the turtles collision hull. $(x).img('blue') // Switch the image to a blue pointer. May use any url. @@ -110,6 +107,7 @@

    $(x).encloses(y) // Containment collision test. $(x).within(d, t) // Filters to items with origins within d of t.origin(). $(x).notwithin() // The negation of within. + $(x).cell(x, y) // Selects the yth row and xth column cell in a table.

    When $.fx.speeds.turtle is nonzero (the default is zero unless @@ -188,27 +186,31 @@

    keydown // The last keydown event. keyup // The last keyup event. keypress // The last keypress event. - turtlespeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. + defaultspeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. tick([perSec,] fn) // Sets fn as the tick callback (null to clear). random(n) // Returns a random number [0...n-1]. random(list) // Returns a random element of the list. random('normal') // Returns a gaussian random (mean 0 stdev 1). random('uniform') // Returns a uniform random [0...1). random('position') // Returns a random {pageX:x, pageY:y} coordinate. + random('color') // Returns a random hsl(*, 100%, 50%) color. + random('gray') // Returns a random hsl(0, 0, *) gray. remove() // Removes default turtle and its globals (fd, etc). hatch([n,], [img]) // Creates and returns n turtles with the given img. see(a, b, c...) // Logs tree-expandable data into debugging panel. - output(html || text) // Appends html into the document body. + print(html) // Appends html into the document body. input([label,] fn) // Makes a one-time input field, calls fn after entry. button([label,] fn) // Makes a clickable button, calls fn when clicked. + table(w, h) // Outputs a table with h rows and w columns. + play("ccggaag2") // Plays a couple measures of song using ABC notation.

    For example, after eval($.turtle()), the following is a valid program in CoffeeScript syntax:

    -turtlespeed Infinity
    -output "Catch blue before red gets you."
    +defaultspeed Infinity
    +print "Catch blue before red gets you."
     bk 100
     r = hatch 'red'
     b = hatch 'blue'
    @@ -220,13 +222,13 @@ 

    b.turnto bearing b b.fd 3 if b.touches(turtle) - output "You win!" + print "You win!" tick off else if r.touches(turtle) - output "Red got you!" + print "Red got you!" tick off else if not b.touches(document) - output "Blue got away!" + print "Blue got away!" tick off

    @@ -263,4 +265,4 @@

    - + \ No newline at end of file diff --git a/params.json b/params.json index a36b177..c005d55 100644 --- a/params.json +++ b/params.json @@ -1 +1 @@ -{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using LOGO-inspired turtle methods like fd, bk, rt, and lt.\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\nThe plugin also provides functions to help in a rotated,\r\nscaled, and transformed world where nested elements may be\r\ntransformed. There are functions for collision testing, absolute\r\npositioning, and absolute direction reading and setting.\r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\nUnder the covers, CSS3 2D transforms and jQuery animations are\r\nused to execute and store turtle movement, so jQuery-turtle\r\ninteracts well with other jQuery animations or direct uses of\r\n2D CSS3 transforms. The plugin sets up jQuery CSS hooks for\r\nsynthetic CSS properties such as turtleForward that can be\r\nanimated or used to directly manipulate turtle geometry at a basic\r\nmathematical level.\r\n\r\nA high-level educational environment is enabled by $.turtle().\r\nThat call creates a set of global objects and functions\r\ncatering to beginners. These include a default turtle\r\nand global functions to control it; an onpage debugger panel;\r\njQuery instances for every object with an #id; simplified\r\nglobals to access recent mouse and keyboard events, and\r\nsimplified functions for randomness, timers, animation control,\r\nand creation of new turtles. The jQuery teaching environment\r\nhas been developed to support a curriculum for young students.\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nTurtle-oriented methods taking advantage of the css support:\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).move(x, y)   // Move right by x while moving forward by y.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)      // Absolute direction adjustment.\r\n\r\n  // Methods below happen in an instant, but queue after animation.\r\n  $(x).home()       // Moves to the origin of the document, turned up.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).erase()      // Erases under the turtles collision hull.\r\n  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate position of transform-origin.\r\n  $(x).bearing([p]) // Absolute direction on page.\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n
    \r\n\r\nWhen $.fx.speeds.turtle is nonzero (the default is zero unless\r\n$.turtle() is called), the first seven movement functions animate\r\nat that speed, and the remaining mutators also participate in the\r\nanimation queue. Note that property-reading functions such as\r\ntouches() are synchronous and will not queue, and setting\r\n$.fx.speed.turtle to 0 will make movement functions synchronous.\r\n\r\nThe absolute motion methods moveto and turnto accept any argument\r\nwith pageX and pageY, including, usefully, mouse events. They\r\noperate in absolute page coordinates even when the turtle is nested\r\nwithin further transformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test using\r\nthe convex hull for the two objects in question. This defaults to\r\nthe bounding box of the elements (as transformed) but can be overridden\r\nby the turtleHull CSS property, if present.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nTurtle-oriented 2d transform cssHooks, with animation support on all\r\nmotion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nAn optional teaching environment setup is created by eval($.turtle()).\r\nIt provides easy packaging for the above functionality.\r\n\r\nAfter eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * And the following are defined:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  turtlespeed(mps)      // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  output(html || text)  // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n
    \r\n\r\nFor example, after eval($.turtle()), the following is a valid program\r\nin CoffeeScript syntax:\r\n\r\n
    \r\nspeed Infinity\r\noutput \"Catch blue before red gets you.\"\r\nbk 100\r\nr = hatch 'red'\r\nb = hatch 'blue'\r\ntick 10, ->\r\n  turnto lastmousemove\r\n  fd 6\r\n  r.turnto turtle\r\n  r.fd 4\r\n  b.turnto bearing b\r\n  b.fd 3\r\n  if b.touches(turtle)\r\n    output \"You win!\"\r\n    tick off\r\n  else if r.touches(turtle)\r\n    output \"Red got you!\"\r\n    tick off\r\n  else if not b.touches(document)\r\n    output \"Blue got away!\"\r\n    tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file +{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using LOGO-inspired turtle methods like fd, bk, rt, and lt.\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\nThe plugin also provides functions to help in a rotated,\r\nscaled, and transformed world where nested elements may be\r\ntransformed. There are functions for collision testing, absolute\r\npositioning, and absolute direction reading and setting.\r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\nUnder the covers, CSS3 2D transforms and jQuery animations are\r\nused to execute and store turtle movement, so jQuery-turtle\r\ninteracts well with other jQuery animations or direct uses of\r\n2D CSS3 transforms. The plugin sets up jQuery CSS hooks for\r\nsynthetic CSS properties such as turtleForward that can be\r\nanimated or used to directly manipulate turtle geometry at a basic\r\nmathematical level.\r\n\r\nA high-level educational environment is enabled by $.turtle().\r\nThat call creates a set of global objects and functions\r\ncatering to beginners. These include a default turtle\r\nand global functions to control it; an onpage debugger panel;\r\njQuery instances for every object with an #id; simplified\r\nglobals to access recent mouse and keyboard events, and\r\nsimplified functions for randomness, timers, animation control,\r\nand creation of new turtles. The jQuery teaching environment\r\nhas been developed to support a curriculum for young students.\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nTurtle-oriented methods taking advantage of the css support:\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).move(x, y)   // Move right by x while moving forward by y.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)      // Absolute direction adjustment.\r\n\r\n  // Methods below happen in an instant, but queue after animation.\r\n  $(x).home()       // Moves to the origin of the document, turned up.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).mark('A')    // Prints an HTML inline-block at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).erase()      // Erases under the turtles collision hull.\r\n  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate position of transform-origin.\r\n  $(x).bearing([p]) // Absolute direction on page.\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(x, y)   // Selects the yth row and xth column cell in a table.\r\n
    \r\n\r\nWhen $.fx.speeds.turtle is nonzero (the default is zero unless\r\n$.turtle() is called), the first seven movement functions animate\r\nat that speed, and the remaining mutators also participate in the\r\nanimation queue. Note that property-reading functions such as\r\ntouches() are synchronous and will not queue, and setting\r\n$.fx.speed.turtle to 0 will make movement functions synchronous.\r\n\r\nThe absolute motion methods moveto and turnto accept any argument\r\nwith pageX and pageY, including, usefully, mouse events. They\r\noperate in absolute page coordinates even when the turtle is nested\r\nwithin further transformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test using\r\nthe convex hull for the two objects in question. This defaults to\r\nthe bounding box of the elements (as transformed) but can be overridden\r\nby the turtleHull CSS property, if present.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nTurtle-oriented 2d transform cssHooks, with animation support on all\r\nmotion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nAn optional teaching environment setup is created by eval($.turtle()).\r\nIt provides easy packaging for the above functionality.\r\n\r\nAfter eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * And the following are defined:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  print(html)           // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(w, h)           // Outputs a table with h rows and w columns.\r\n  play(\"ccggaag2\")      // Plays a couple measures of song using ABC notation.\r\n
    \r\n\r\nFor example, after eval($.turtle()), the following is a valid program\r\nin CoffeeScript syntax:\r\n\r\n
    \r\ndefaultspeed Infinity\r\nprint \"Catch blue before red gets you.\"\r\nbk 100\r\nr = hatch 'red'\r\nb = hatch 'blue'\r\ntick 10, ->\r\n  turnto lastmousemove\r\n  fd 6\r\n  r.turnto turtle\r\n  r.fd 4\r\n  b.turnto bearing b\r\n  b.fd 3\r\n  if b.touches(turtle)\r\n    print \"You win!\"\r\n    tick off\r\n  else if r.touches(turtle)\r\n    print \"Red got you!\"\r\n    tick off\r\n  else if not b.touches(document)\r\n    print \"Blue got away!\"\r\n    tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file From feefe977981293ec7e03c86529ba7afb43e3c75b Mon Sep 17 00:00:00 2001 From: David Bau Date: Wed, 12 Jun 2013 01:03:13 -0400 Subject: [PATCH 14/25] Update docs. --- index.html | 6 +++++- jquery-turtle.js | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 23bc18e..62e373d 100644 --- a/index.html +++ b/index.html @@ -51,6 +51,10 @@

    Try an interactive demo (CoffeeScript syntax) here.

    + +

    Under the covers, CSS3 2D transforms and jQuery animations are used to execute and store turtle movement, so jQuery-turtle interacts well with other jQuery animations or direct uses of @@ -265,4 +269,4 @@

    - \ No newline at end of file + diff --git a/jquery-turtle.js b/jquery-turtle.js index 3c64e41..08bb114 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -161,6 +161,8 @@ After eval($.turtle()): random('normal') // Returns a gaussian random (mean 0 stdev 1). random('uniform') // Returns a uniform random [0...1). random('position') // Returns a random {pageX:x, pageY:y} coordinate. + random('color') // Returns a random hsl(*, 100%, 50%) color. + random('gray') // Returns a random hsl(0, 0, *) gray. remove() // Removes default turtle and its globals (fd, etc). hatch([n,], [img]) // Creates and returns n turtles with the given img. see(a, b, c...) // Logs tree-expandable data into debugging panel. From 46dd409419f8c977cfb113c842de2a0c9f8f78c9 Mon Sep 17 00:00:00 2001 From: David Bau Date: Wed, 12 Jun 2013 01:12:40 -0400 Subject: [PATCH 15/25] Update version. --- jquery-turtle.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index 08bb114..28ddb39 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -2142,13 +2142,18 @@ var dollar_turtle_methods = { tick: function(x, y) { directIfGlobal(function() { tick(x, y); }); }, defaultspeed: function(mps) { directIfGlobal(function() { defaultspeed(mps); }); }, + play: function(ops) { + var x = arguments; + directIfGlobal(function() { + play.apply(null, x); + }); + }, print: function(html) { return output(html, 'div'); }, random: random, hatch: hatch, input: input, button: button, table: table, - play: play }; $.turtle = function turtle(id, options) { From 4fce25c7a3996748c3ab7de5266057dab5d573eb Mon Sep 17 00:00:00 2001 From: davidbau Date: Wed, 19 Jun 2013 19:11:37 -0700 Subject: [PATCH 16/25] Create gh-pages branch via GitHub --- index.html | 259 ++++++++++++++++++++++++++++------------------------ params.json | 2 +- 2 files changed, 143 insertions(+), 118 deletions(-) diff --git a/index.html b/index.html index 62e373d..7c3c268 100644 --- a/index.html +++ b/index.html @@ -38,45 +38,51 @@

    jQuery-turtle is a jQuery plugin for turtle graphics.

    With jQuery-turtle, every DOM element is a turtle that can be -moved using LOGO-inspired turtle methods like fd, bk, rt, and lt.

    +moved using turtle graphics methods like fd (forward), bk (back), +rt (right turn), and lt (left turn). The pen function allows +a turtle to draw on a full-document canvas as it moves.

       $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();
     
    -

    The plugin also provides functions to help in a rotated, -scaled, and transformed world where nested elements may be -transformed. There are functions for collision testing, absolute -positioning, and absolute direction reading and setting.

    +

    jQuery-turtle provides:

    -

    Try an interactive demo (CoffeeScript syntax) here.

    +
      +
    • Relative and absolute motion and drawing.
    • +
    • Functions to ease basic input, output, and game-making for beginners.
    • +
    • Operations on sets of turtles, and turtle motion of arbitrary elements.
    • +
    • Accurate collision-testing of turtles with arbitrary convex hulls.
    • +
    • Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.
    • +
    • An interactive turtle console in either Javascript or CoffeeScript.
    • +

    The plugin can also create a learning environment with a default +turtle that is friendly for beginners. The following is a complete +CoffeeScript program that uses the default turtle to draw a grid of +sixteen colored polygons.

    + +
    +  eval $.turtle()  # Create the default turtle.
    +
    +  speed 100
    +  for color in ['red', 'gold', 'green', 'blue']
    +    for sides in [3..6]
    +      pen color
    +      for x in [1..sides]
    +        fd 100 / sides
    +        lt 360 / sides
    +      pen 'none'
    +      fd 40
    +    move 40, -160
    +
    - - -

    Under the covers, CSS3 2D transforms and jQuery animations are -used to execute and store turtle movement, so jQuery-turtle -interacts well with other jQuery animations or direct uses of -2D CSS3 transforms. The plugin sets up jQuery CSS hooks for -synthetic CSS properties such as turtleForward that can be -animated or used to directly manipulate turtle geometry at a basic -mathematical level.

    - -

    A high-level educational environment is enabled by $.turtle(). -That call creates a set of global objects and functions -catering to beginners. These include a default turtle -and global functions to control it; an onpage debugger panel; -jQuery instances for every object with an #id; simplified -globals to access recent mouse and keyboard events, and -simplified functions for randomness, timers, animation control, -and creation of new turtles. The jQuery teaching environment -has been developed to support a curriculum for young students.

    +

    Try an interactive demo (CoffeeScript syntax) here.

    JQuery Methods for Turtle Movement

    -

    Turtle-oriented methods taking advantage of the css support:

    +

    The turtle API is briefly summarized below. All the following +turtle-oriented methods operate on any jQuery object (including +the default turtle, if used):

       $(x).fd(100)      // Forward relative motion in local coordinates.
    @@ -86,24 +92,27 @@ 

    $(x).move(x, y) // Move right by x while moving forward by y. $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion on page. $(x).turnto(bearing || position) // Absolute direction adjustment. + $(x).play("ccgg") // Plays notes using ABC notation. - // Methods below happen in an instant, but queue after animation. - $(x).home() // Moves to the origin of the document, turned up. + // Methods below happen in an instant, but line up in the animation queue. + $(x).home() // Moves to the origin of the document, with bearing 0. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. + $(x).fill('pink') // Fills a shape previously outlined using pen('path'). $(x).dot(12) // Draws a circular dot of diameter 12. $(x).mark('A') // Prints an HTML inline-block at the turtle location. $(x).speed(10) // Sets turtle animation speed to 10 moves per sec. - $(x).erase() // Erases under the turtles collision hull. - $(x).img('blue') // Switch the image to a blue pointer. May use any url. + $(x).erase() // Erases the canvas under the turtle collision hull. + $(x).img('blue') // Switches the turtle to a blue picture. Use any url. $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". $(x).mirror(true) // Flips the turtle across its main axis. $(x).reload() // Reloads the turtle's image (restarting animated gifs) - $(x).direct(fn) // Like each, but this is set to $(elt) instead of elt. + $(x).direct(fn) // Like each, but this is set to $(elt) instead of elt, + // and the callback fn can insert into the animation queue. // Methods below this line do not queue for animation. - $(x).origin() // Page coordinate position of transform-origin. - $(x).bearing([p]) // Absolute direction on page. + $(x).origin() // Page coordinate of the turtle's transform-origin. + $(x).bearing([p]) // The turtles absolute direction (or direction towards p). $(x).distance(p) // Distance to p in page coordinates. $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") @@ -114,66 +123,40 @@

    $(x).cell(x, y) // Selects the yth row and xth column cell in a table.

    -

    When $.fx.speeds.turtle is nonzero (the default is zero unless -$.turtle() is called), the first seven movement functions animate -at that speed, and the remaining mutators also participate in the -animation queue. Note that property-reading functions such as -touches() are synchronous and will not queue, and setting -$.fx.speed.turtle to 0 will make movement functions synchronous.

    - -

    The absolute motion methods moveto and turnto accept any argument -with pageX and pageY, including, usefully, mouse events. They -operate in absolute page coordinates even when the turtle is nested -within further transformed elements.

    - -

    The hit-testing functions touches() and encloses() will test using -the convex hull for the two objects in question. This defaults to -the bounding box of the elements (as transformed) but can be overridden -by the turtleHull CSS property, if present.

    - -

    -JQuery CSS Hooks for Turtle Geometry

    - -

    Turtle-oriented 2d transform cssHooks, with animation support on all -motion:

    - -
    -  $(x).css('turtleSpeed', '10');         // default speed in moves per second.
    -  $(x).css('turtlePosition', '30 40');   // position in local coordinates.
    -  $(x).css('turtlePositionX', '30');     // x component.
    -  $(x).css('turtlePositionY', '40');     // y component.
    -  $(x).css('turtleRotation', '90');      // rotation in degrees.
    -  $(x).css('turtleScale', '2');          // double the size of any element.
    -  $(x).css('turtleScaleX', '2');         // x stretch after twist.
    -  $(x).css('turtleScaleY', '2');         // y stretch after twist.
    -  $(x).css('turtleTwist', '45');         // turn before stretching.
    -  $(x).css('turtleForward', '50');       // position in direction of rotation.
    -  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    -  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
    -  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
    -
    - -

    Arbitrary 2d transforms are supported, including transforms of elements -nested within other elements that have css transforms. Transforms are -automatically decomposed to turtle components when necessary.

    - -

    A canvas is supported for drawing, but only created when the pen is -used; pen styles include canvas style properties such as lineWidth -and lineCap.

    - -

    A convex hull polygon can be set to be used by the collision detection -and hit-testing functions (encloses, touches). The turtleHull is a list -of (unrotated) x-y coordinates relative to the object's transformOrigin. -If set to 'auto' (the default) the hull is just the bounding box for the -element.

    +

    When the speed of a turtle is nonzero, the first seven movement +functions animate at that speed, and the remaining mutators also +participate in the animation queue. The default turtle speed is +a leisurely one move per second (as appropriate for the creature), +but you may soon discover the desire to set speed higher.

    + +

    Setting the turtle speed to Infinity will make movement synchronous, +which makes the synchronous distance, direction, and hit-testing useful +for realtime game-making. To play music without stalling turtle +movement, use the global function playnow() instead of the turtle +method play().

    + +

    The absolute motion methods moveto and turnto accept any object +that has pageX and pageY properties (or an origin() method that will +return such an object), including, usefully, mouse events. +Moveto and turnto operate in absolute page coordinates and work +properly even when the turtle is nested within further CSS +transformed elements.

    + +

    The hit-testing functions touches() and encloses() will test for +collisions using the convex hulls of the objects in question. +The hull of an element defaults to the bounding box of the element +(as transformed) but can be overridden by the turtleHull CSS property, +if present. The default turtle is given a turtle-shaped hull.

    Turtle Teaching Environment

    -

    An optional teaching environment setup is created by eval($.turtle()). -It provides easy packaging for the above functionality.

    +

    A default turtle together with an interactive console are created by +calling eval($.turtle()). This call will expose a the default turtle +methods as global functions. It will also set up a number of other global +symbols to provide beginners with a simplified programming environment.

    -

    After eval($.turtle()):

    +

    In detail, after eval($.turtle()):

    • An <img id="turtle"> is created if #turtle doesn't already exist.
    • @@ -181,8 +164,12 @@

    • Turtle methods on the default turtle are packaged as globals, e.g., fd(10).
    • Every #id element is turned into a global variable: window.id = $('#id').
    • Default turtle animation is set to 1 move per sec so steps can be seen.
    • -
    • And the following are defined:
    • -

    +
  • Global event listeners are created to update global event variables.
  • +
  • Methods of $.turtle.* (enumerated below) are exposed as global functions.
  • +

    Beyond the functions to control the default turtle, the globals added by +$.turtle() are as follows:

    + +
       lastclick             // Event object of the last click event in the doc.
       lastmousemove         // The last mousemove event.
       lastmouseup           // The last mouseup event.
    @@ -206,39 +193,77 @@ 

    input([label,] fn) // Makes a one-time input field, calls fn after entry. button([label,] fn) // Makes a clickable button, calls fn when clicked. table(w, h) // Outputs a table with h rows and w columns. - play("ccggaag2") // Plays a couple measures of song using ABC notation. + playnow('CEG') // Plays musical notes now, without queueing.

    -

    For example, after eval($.turtle()), the following is a valid program -in CoffeeScript syntax:

    +

    Here is another CoffeeScript example that demonstrates some of +the functions:

    -defaultspeed Infinity
    -print "Catch blue before red gets you."
    -bk 100
    -r = hatch 'red'
    -b = hatch 'blue'
    -tick 10, ->
    -  turnto lastmousemove
    -  fd 6
    -  r.turnto turtle
    -  r.fd 4
    -  b.turnto bearing b
    -  b.fd 3
    -  if b.touches(turtle)
    -    print "You win!"
    -    tick off
    -  else if r.touches(turtle)
    -    print "Red got you!"
    -    tick off
    -  else if not b.touches(document)
    -    print "Blue got away!"
    -    tick off
    +  eval $.turtle()  # Create the default turtle and global functions.
    +
    +  defaultspeed Infinity
    +  print "Catch blue before red gets you."
    +  bk 100
    +  r = hatch 'red'
    +  b = hatch 'blue'
    +  tick 10, ->
    +    turnto lastmousemove
    +    fd 6
    +    r.turnto turtle
    +    r.fd 4
    +    b.turnto bearing b
    +    b.fd 3
    +    if b.touches(turtle)
    +      print "You win!"
    +      tick off
    +    else if r.touches(turtle)
    +      print "Red got you!"
    +      tick off
    +    else if not b.touches(document)
    +      print "Blue got away!"
    +      tick off
     

    The turtle teaching environment is designed to work well with either Javascript or CoffeeScript.

    +

    +JQuery CSS Hooks for Turtle Geometry

    + +

    Underlying turtle motion are turtle-oriented 2d transform jQuery cssHooks, +with animation support on all motion:

    + +
    +  $(x).css('turtleSpeed', '10');         // default speed in moves per second.
    +  $(x).css('turtlePosition', '30 40');   // position in local coordinates.
    +  $(x).css('turtlePositionX', '30');     // x component.
    +  $(x).css('turtlePositionY', '40');     // y component.
    +  $(x).css('turtleRotation', '90');      // rotation in degrees.
    +  $(x).css('turtleScale', '2');          // double the size of any element.
    +  $(x).css('turtleScaleX', '2');         // x stretch after twist.
    +  $(x).css('turtleScaleY', '2');         // y stretch after twist.
    +  $(x).css('turtleTwist', '45');         // turn before stretching.
    +  $(x).css('turtleForward', '50');       // position in direction of rotation.
    +  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    +  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
    +  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
    +
    + +

    Arbitrary 2d transforms are supported, including transforms of elements +nested within other elements that have css transforms. Transforms are +automatically decomposed to turtle components when necessary.

    + +

    A canvas is supported for drawing, but only created when the pen is +used; pen styles include canvas style properties such as lineWidth +and lineCap.

    + +

    A convex hull polygon can be set to be used by the collision detection +and hit-testing functions (encloses, touches). The turtleHull is a list +of (unrotated) x-y coordinates relative to the object's transformOrigin. +If set to 'auto' (the default) the hull is just the bounding box for the +element.

    +

    License (MIT)

    @@ -269,4 +294,4 @@

    - + \ No newline at end of file diff --git a/params.json b/params.json index c005d55..ca4ac7a 100644 --- a/params.json +++ b/params.json @@ -1 +1 @@ -{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using LOGO-inspired turtle methods like fd, bk, rt, and lt.\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\nThe plugin also provides functions to help in a rotated,\r\nscaled, and transformed world where nested elements may be\r\ntransformed. There are functions for collision testing, absolute\r\npositioning, and absolute direction reading and setting.\r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\nUnder the covers, CSS3 2D transforms and jQuery animations are\r\nused to execute and store turtle movement, so jQuery-turtle\r\ninteracts well with other jQuery animations or direct uses of\r\n2D CSS3 transforms. The plugin sets up jQuery CSS hooks for\r\nsynthetic CSS properties such as turtleForward that can be\r\nanimated or used to directly manipulate turtle geometry at a basic\r\nmathematical level.\r\n\r\nA high-level educational environment is enabled by $.turtle().\r\nThat call creates a set of global objects and functions\r\ncatering to beginners. These include a default turtle\r\nand global functions to control it; an onpage debugger panel;\r\njQuery instances for every object with an #id; simplified\r\nglobals to access recent mouse and keyboard events, and\r\nsimplified functions for randomness, timers, animation control,\r\nand creation of new turtles. The jQuery teaching environment\r\nhas been developed to support a curriculum for young students.\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nTurtle-oriented methods taking advantage of the css support:\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).move(x, y)   // Move right by x while moving forward by y.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)      // Absolute direction adjustment.\r\n\r\n  // Methods below happen in an instant, but queue after animation.\r\n  $(x).home()       // Moves to the origin of the document, turned up.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).mark('A')    // Prints an HTML inline-block at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).erase()      // Erases under the turtles collision hull.\r\n  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate position of transform-origin.\r\n  $(x).bearing([p]) // Absolute direction on page.\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(x, y)   // Selects the yth row and xth column cell in a table.\r\n
    \r\n\r\nWhen $.fx.speeds.turtle is nonzero (the default is zero unless\r\n$.turtle() is called), the first seven movement functions animate\r\nat that speed, and the remaining mutators also participate in the\r\nanimation queue. Note that property-reading functions such as\r\ntouches() are synchronous and will not queue, and setting\r\n$.fx.speed.turtle to 0 will make movement functions synchronous.\r\n\r\nThe absolute motion methods moveto and turnto accept any argument\r\nwith pageX and pageY, including, usefully, mouse events. They\r\noperate in absolute page coordinates even when the turtle is nested\r\nwithin further transformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test using\r\nthe convex hull for the two objects in question. This defaults to\r\nthe bounding box of the elements (as transformed) but can be overridden\r\nby the turtleHull CSS property, if present.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nTurtle-oriented 2d transform cssHooks, with animation support on all\r\nmotion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nAn optional teaching environment setup is created by eval($.turtle()).\r\nIt provides easy packaging for the above functionality.\r\n\r\nAfter eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * And the following are defined:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  print(html)           // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(w, h)           // Outputs a table with h rows and w columns.\r\n  play(\"ccggaag2\")      // Plays a couple measures of song using ABC notation.\r\n
    \r\n\r\nFor example, after eval($.turtle()), the following is a valid program\r\nin CoffeeScript syntax:\r\n\r\n
    \r\ndefaultspeed Infinity\r\nprint \"Catch blue before red gets you.\"\r\nbk 100\r\nr = hatch 'red'\r\nb = hatch 'blue'\r\ntick 10, ->\r\n  turnto lastmousemove\r\n  fd 6\r\n  r.turnto turtle\r\n  r.fd 4\r\n  b.turnto bearing b\r\n  b.fd 3\r\n  if b.touches(turtle)\r\n    print \"You win!\"\r\n    tick off\r\n  else if r.touches(turtle)\r\n    print \"Red got you!\"\r\n    tick off\r\n  else if not b.touches(document)\r\n    print \"Blue got away!\"\r\n    tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file +{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using turtle graphics methods like fd (forward), bk (back),\r\nrt (right turn), and lt (left turn). The pen function allows\r\na turtle to draw on a full-document canvas as it moves.\r\n\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\n\r\njQuery-turtle provides:\r\n * Relative and absolute motion and drawing.\r\n * Functions to ease basic input, output, and game-making for beginners.\r\n * Operations on sets of turtles, and turtle motion of arbitrary elements.\r\n * Accurate collision-testing of turtles with arbitrary convex hulls.\r\n * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.\r\n * An interactive turtle console in either Javascript or CoffeeScript.\r\n\r\nThe plugin can also create a learning environment with a default\r\nturtle that is friendly for beginners. The following is a complete\r\nCoffeeScript program that uses the default turtle to draw a grid of\r\nsixteen colored polygons.\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle.\r\n\r\n  speed 100\r\n  for color in ['red', 'gold', 'green', 'blue']\r\n    for sides in [3..6]\r\n      pen color\r\n      for x in [1..sides]\r\n        fd 100 / sides\r\n        lt 360 / sides\r\n      pen 'none'\r\n      fd 40\r\n    move 40, -160\r\n
    \r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nThe turtle API is briefly summarized below. All the following\r\nturtle-oriented methods operate on any jQuery object (including\r\nthe default turtle, if used):\r\n\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).move(x, y)   // Move right by x while moving forward by y.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)      // Absolute direction adjustment.\r\n  $(x).play(\"ccgg\") // Plays notes using ABC notation.\r\n\r\n  // Methods below happen in an instant, but line up in the animation queue.\r\n  $(x).home()       // Moves to the origin of the document, with bearing 0.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).fill('pink') // Fills a shape previously outlined using pen('path').\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).mark('A')    // Prints an HTML inline-block at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).erase()      // Erases the canvas under the turtle collision hull.\r\n  $(x).img('blue')  // Switches the turtle to a blue picture.  Use any url.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,\r\n                    // and the callback fn can insert into the animation queue.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate of the turtle's transform-origin.\r\n  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(x, y)   // Selects the yth row and xth column cell in a table.\r\n
    \r\n\r\nWhen the speed of a turtle is nonzero, the first seven movement\r\nfunctions animate at that speed, and the remaining mutators also\r\nparticipate in the animation queue. The default turtle speed is\r\na leisurely one move per second (as appropriate for the creature),\r\nbut you may soon discover the desire to set speed higher.\r\n\r\nSetting the turtle speed to Infinity will make movement synchronous,\r\nwhich makes the synchronous distance, direction, and hit-testing useful\r\nfor realtime game-making. To play music without stalling turtle\r\nmovement, use the global function playnow() instead of the turtle\r\nmethod play().\r\n\r\nThe absolute motion methods moveto and turnto accept any object\r\nthat has pageX and pageY properties (or an origin() method that will\r\nreturn such an object), including, usefully, mouse events.\r\nMoveto and turnto operate in absolute page coordinates and work\r\nproperly even when the turtle is nested within further CSS\r\ntransformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test for\r\ncollisions using the convex hulls of the objects in question.\r\nThe hull of an element defaults to the bounding box of the element\r\n(as transformed) but can be overridden by the turtleHull CSS property,\r\nif present. The default turtle is given a turtle-shaped hull.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nA default turtle together with an interactive console are created by\r\ncalling eval($.turtle()). This call will expose a the default turtle\r\nmethods as global functions. It will also set up a number of other global\r\nsymbols to provide beginners with a simplified programming environment.\r\n\r\nIn detail, after eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * Global event listeners are created to update global event variables.\r\n * Methods of $.turtle.* (enumerated below) are exposed as global functions.\r\n\r\nBeyond the functions to control the default turtle, the globals added by\r\n$.turtle() are as follows:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  print(html)           // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(w, h)           // Outputs a table with h rows and w columns.\r\n  playnow('CEG')        // Plays musical notes now, without queueing.\r\n
    \r\n\r\nHere is another CoffeeScript example that demonstrates some of\r\nthe functions:\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle and global functions.\r\n\r\n  defaultspeed Infinity\r\n  print \"Catch blue before red gets you.\"\r\n  bk 100\r\n  r = hatch 'red'\r\n  b = hatch 'blue'\r\n  tick 10, ->\r\n    turnto lastmousemove\r\n    fd 6\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto bearing b\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      print \"You win!\"\r\n      tick off\r\n    else if r.touches(turtle)\r\n      print \"Red got you!\"\r\n      tick off\r\n    else if not b.touches(document)\r\n      print \"Blue got away!\"\r\n      tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nUnderlying turtle motion are turtle-oriented 2d transform jQuery cssHooks,\r\nwith animation support on all motion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file From 91f5413c56ed0926ec9f1e7bca8ef38d800bea17 Mon Sep 17 00:00:00 2001 From: David Bau Date: Wed, 19 Jun 2013 22:12:27 -0400 Subject: [PATCH 17/25] Add iframe. --- index.html | 6 +- jquery-turtle.js | 410 ++++++++++++++++++++++++++++------------------- 2 files changed, 248 insertions(+), 168 deletions(-) diff --git a/index.html b/index.html index 7c3c268..a5c48dd 100644 --- a/index.html +++ b/index.html @@ -77,6 +77,10 @@

    Try an interactive demo (CoffeeScript syntax) here.

    + +

    JQuery Methods for Turtle Movement

    @@ -294,4 +298,4 @@

    - \ No newline at end of file + diff --git a/jquery-turtle.js b/jquery-turtle.js index 28ddb39..8ef7e57 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -9,40 +9,53 @@ version 2.0.5 jQuery-turtle is a jQuery plugin for turtle graphics. With jQuery-turtle, every DOM element is a turtle that can be -moved using LOGO-inspired turtle methods like fd, bk, rt, and lt. +moved using turtle graphics methods like fd (forward), bk (back), +rt (right turn), and lt (left turn). The pen function allows +a turtle to draw on a full-document canvas as it moves. +
       $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();
     
    -The plugin also provides functions to help in a rotated, -scaled, and transformed world where nested elements may be -transformed. There are functions for collision testing, absolute -positioning, and absolute direction reading and setting. + +jQuery-turtle provides: + * Relative and absolute motion and drawing. + * Functions to ease basic input, output, and game-making for beginners. + * Operations on sets of turtles, and turtle motion of arbitrary elements. + * Accurate collision-testing of turtles with arbitrary convex hulls. + * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio. + * An interactive turtle console in either Javascript or CoffeeScript. + +The plugin can also create a learning environment with a default +turtle that is friendly for beginners. The following is a complete +CoffeeScript program that uses the default turtle to draw a grid of +sixteen colored polygons. + +
    +  eval $.turtle()  # Create the default turtle.
    +
    +  speed 100
    +  for color in ['red', 'gold', 'green', 'blue']
    +    for sides in [3..6]
    +      pen color
    +      for x in [1..sides]
    +        fd 100 / sides
    +        lt 360 / sides
    +      pen 'none'
    +      fd 40
    +    move 40, -160
    +
    [Try an interactive demo (CoffeeScript syntax) here.]( http://davidbau.github.io/jquery-turtle/demo.html) -Under the covers, CSS3 2D transforms and jQuery animations are -used to execute and store turtle movement, so jQuery-turtle -interacts well with other jQuery animations or direct uses of -2D CSS3 transforms. The plugin sets up jQuery CSS hooks for -synthetic CSS properties such as turtleForward that can be -animated or used to directly manipulate turtle geometry at a basic -mathematical level. - -A high-level educational environment is enabled by $.turtle(). -That call creates a set of global objects and functions -catering to beginners. These include a default turtle -and global functions to control it; an onpage debugger panel; -jQuery instances for every object with an #id; simplified -globals to access recent mouse and keyboard events, and -simplified functions for randomness, timers, animation control, -and creation of new turtles. The jQuery teaching environment -has been developed to support a curriculum for young students. JQuery Methods for Turtle Movement ---------------------------------- -Turtle-oriented methods taking advantage of the css support: +The turtle API is briefly summarized below. All the following +turtle-oriented methods operate on any jQuery object (including +the default turtle, if used): +
       $(x).fd(100)      // Forward relative motion in local coordinates.
       $(x).bk(50)       // Back.
    @@ -51,24 +64,27 @@ Turtle-oriented methods taking advantage of the css support:
       $(x).move(x, y)   // Move right by x while moving forward by y.
       $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion on page.
       $(x).turnto(bearing || position)      // Absolute direction adjustment.
    +  $(x).play("ccgg") // Plays notes using ABC notation.
     
    -  // Methods below happen in an instant, but queue after animation.
    -  $(x).home()       // Moves to the origin of the document, turned up.
    +  // Methods below happen in an instant, but line up in the animation queue.
    +  $(x).home()       // Moves to the origin of the document, with bearing 0.
       $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.
    +  $(x).fill('pink') // Fills a shape previously outlined using pen('path').
       $(x).dot(12)      // Draws a circular dot of diameter 12.
       $(x).mark('A')    // Prints an HTML inline-block at the turtle location.
       $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.
    -  $(x).erase()      // Erases under the turtles collision hull.
    -  $(x).img('blue')  // Switch the image to a blue pointer.  May use any url.
    +  $(x).erase()      // Erases the canvas under the turtle collision hull.
    +  $(x).img('blue')  // Switches the turtle to a blue picture.  Use any url.
       $(x).scale(1.5)   // Scales turtle size and motion by 150%.
       $(x).twist(180)   // Changes which direction is considered "forward".
       $(x).mirror(true) // Flips the turtle across its main axis.
       $(x).reload()     // Reloads the turtle's image (restarting animated gifs)
    -  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt.
    +  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,
    +                    // and the callback fn can insert into the animation queue.
     
       // Methods below this line do not queue for animation.
    -  $(x).origin()     // Page coordinate position of transform-origin.
    -  $(x).bearing([p]) // Absolute direction on page.
    +  $(x).origin()     // Page coordinate of the turtle's transform-origin.
    +  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).
       $(x).distance(p)  // Distance to p in page coordinates.
       $(x).shown()      // Shorthand for is(":visible")
       $(x).hidden()     // Shorthand for !is(":visible")
    @@ -79,72 +95,50 @@ Turtle-oriented methods taking advantage of the css support:
       $(x).cell(x, y)   // Selects the yth row and xth column cell in a table.
     
    -When $.fx.speeds.turtle is nonzero (the default is zero unless -$.turtle() is called), the first seven movement functions animate -at that speed, and the remaining mutators also participate in the -animation queue. Note that property-reading functions such as -touches() are synchronous and will not queue, and setting -$.fx.speed.turtle to 0 will make movement functions synchronous. - -The absolute motion methods moveto and turnto accept any argument -with pageX and pageY, including, usefully, mouse events. They -operate in absolute page coordinates even when the turtle is nested -within further transformed elements. - -The hit-testing functions touches() and encloses() will test using -the convex hull for the two objects in question. This defaults to -the bounding box of the elements (as transformed) but can be overridden -by the turtleHull CSS property, if present. - -JQuery CSS Hooks for Turtle Geometry ------------------------------------- - -Turtle-oriented 2d transform cssHooks, with animation support on all -motion: - -
    -  $(x).css('turtleSpeed', '10');         // default speed in moves per second.
    -  $(x).css('turtlePosition', '30 40');   // position in local coordinates.
    -  $(x).css('turtlePositionX', '30');     // x component.
    -  $(x).css('turtlePositionY', '40');     // y component.
    -  $(x).css('turtleRotation', '90');      // rotation in degrees.
    -  $(x).css('turtleScale', '2');          // double the size of any element.
    -  $(x).css('turtleScaleX', '2');         // x stretch after twist.
    -  $(x).css('turtleScaleY', '2');         // y stretch after twist.
    -  $(x).css('turtleTwist', '45');         // turn before stretching.
    -  $(x).css('turtleForward', '50');       // position in direction of rotation.
    -  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    -  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
    -  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
    -
    - -Arbitrary 2d transforms are supported, including transforms of elements -nested within other elements that have css transforms. Transforms are -automatically decomposed to turtle components when necessary. - -A canvas is supported for drawing, but only created when the pen is -used; pen styles include canvas style properties such as lineWidth -and lineCap. - -A convex hull polygon can be set to be used by the collision detection -and hit-testing functions (encloses, touches). The turtleHull is a list -of (unrotated) x-y coordinates relative to the object's transformOrigin. -If set to 'auto' (the default) the hull is just the bounding box for the -element. +When the speed of a turtle is nonzero, the first seven movement +functions animate at that speed, and the remaining mutators also +participate in the animation queue. The default turtle speed is +a leisurely one move per second (as appropriate for the creature), +but you may soon discover the desire to set speed higher. + +Setting the turtle speed to Infinity will make movement synchronous, +which makes the synchronous distance, direction, and hit-testing useful +for realtime game-making. To play music without stalling turtle +movement, use the global function playnow() instead of the turtle +method play(). + +The absolute motion methods moveto and turnto accept any object +that has pageX and pageY properties (or an origin() method that will +return such an object), including, usefully, mouse events. +Moveto and turnto operate in absolute page coordinates and work +properly even when the turtle is nested within further CSS +transformed elements. + +The hit-testing functions touches() and encloses() will test for +collisions using the convex hulls of the objects in question. +The hull of an element defaults to the bounding box of the element +(as transformed) but can be overridden by the turtleHull CSS property, +if present. The default turtle is given a turtle-shaped hull. Turtle Teaching Environment --------------------------- -An optional teaching environment setup is created by eval($.turtle()). -It provides easy packaging for the above functionality. +A default turtle together with an interactive console are created by +calling eval($.turtle()). This call will expose a the default turtle +methods as global functions. It will also set up a number of other global +symbols to provide beginners with a simplified programming environment. -After eval($.turtle()): +In detail, after eval($.turtle()): * An <img id="turtle"> is created if #turtle doesn't already exist. * An eval debugging panel (see.js) is shown at the bottom of the screen. * Turtle methods on the default turtle are packaged as globals, e.g., fd(10). * Every #id element is turned into a global variable: window.id = $('#id'). * Default turtle animation is set to 1 move per sec so steps can be seen. - * And the following are defined: + * Global event listeners are created to update global event variables. + * Methods of $.turtle.* (enumerated below) are exposed as global functions. + +Beyond the functions to control the default turtle, the globals added by +$.turtle() are as follows:
       lastclick             // Event object of the last click event in the doc.
    @@ -170,39 +164,77 @@ After eval($.turtle()):
       input([label,] fn)    // Makes a one-time input field, calls fn after entry.
       button([label,] fn)   // Makes a clickable button, calls fn when clicked.
       table(w, h)           // Outputs a table with h rows and w columns.
    -  play("ccggaag2")      // Plays a couple measures of song using ABC notation.
    +  playnow('CEG')        // Plays musical notes now, without queueing.
     
    -For example, after eval($.turtle()), the following is a valid program -in CoffeeScript syntax: +Here is another CoffeeScript example that demonstrates some of +the functions:
    -defaultspeed Infinity
    -print "Catch blue before red gets you."
    -bk 100
    -r = hatch 'red'
    -b = hatch 'blue'
    -tick 10, ->
    -  turnto lastmousemove
    -  fd 6
    -  r.turnto turtle
    -  r.fd 4
    -  b.turnto bearing b
    -  b.fd 3
    -  if b.touches(turtle)
    -    print "You win!"
    -    tick off
    -  else if r.touches(turtle)
    -    print "Red got you!"
    -    tick off
    -  else if not b.touches(document)
    -    print "Blue got away!"
    -    tick off
    +  eval $.turtle()  # Create the default turtle and global functions.
    +
    +  defaultspeed Infinity
    +  print "Catch blue before red gets you."
    +  bk 100
    +  r = hatch 'red'
    +  b = hatch 'blue'
    +  tick 10, ->
    +    turnto lastmousemove
    +    fd 6
    +    r.turnto turtle
    +    r.fd 4
    +    b.turnto bearing b
    +    b.fd 3
    +    if b.touches(turtle)
    +      print "You win!"
    +      tick off
    +    else if r.touches(turtle)
    +      print "Red got you!"
    +      tick off
    +    else if not b.touches(document)
    +      print "Blue got away!"
    +      tick off
     
    The turtle teaching environment is designed to work well with either Javascript or CoffeeScript. +JQuery CSS Hooks for Turtle Geometry +------------------------------------ + +Underlying turtle motion are turtle-oriented 2d transform jQuery cssHooks, +with animation support on all motion: + +
    +  $(x).css('turtleSpeed', '10');         // default speed in moves per second.
    +  $(x).css('turtlePosition', '30 40');   // position in local coordinates.
    +  $(x).css('turtlePositionX', '30');     // x component.
    +  $(x).css('turtlePositionY', '40');     // y component.
    +  $(x).css('turtleRotation', '90');      // rotation in degrees.
    +  $(x).css('turtleScale', '2');          // double the size of any element.
    +  $(x).css('turtleScaleX', '2');         // x stretch after twist.
    +  $(x).css('turtleScaleY', '2');         // y stretch after twist.
    +  $(x).css('turtleTwist', '45');         // turn before stretching.
    +  $(x).css('turtleForward', '50');       // position in direction of rotation.
    +  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    +  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
    +  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
    +
    + +Arbitrary 2d transforms are supported, including transforms of elements +nested within other elements that have css transforms. Transforms are +automatically decomposed to turtle components when necessary. + +A canvas is supported for drawing, but only created when the pen is +used; pen styles include canvas style properties such as lineWidth +and lineCap. + +A convex hull polygon can be set to be used by the collision detection +and hit-testing functions (encloses, touches). The turtleHull is a list +of (unrotated) x-y coordinates relative to the object's transformOrigin. +If set to 'auto' (the default) the hull is just the bounding box for the +element. + License (MIT) ------------- @@ -1355,6 +1387,34 @@ function applyPenStyle(ctx, ps, scale) { } } +function drawAndClearPath(path, style, scale) { + var ctx = getTurtleDrawingCtx(), + isClosed, + j = path.length, + segment; + ctx.save(); + ctx.beginPath(); + // Scale up lineWidth by sx. (TODO: consider parent transforms.) + applyPenStyle(ctx, style, scale); + while (j--) { + if (path[j].length) { + segment = path[j]; + isClosed = segment.length > 2 && isPointNearby( + segment[0], segment[segment.length - 1]); + ctx.moveTo(segment[0].pageX, segment[0].pageY); + for (var k = 1; k < segment.length - (isClosed ? 1 : 0); ++k) { + ctx.lineTo(segment[k].pageX, segment[k].pageY); + } + if (isClosed) { ctx.closePath(); } + } + } + if ('fillStyle' in style) { ctx.fill(); } + if ('strokeStyle' in style) { ctx.stroke(); } + ctx.restore(); + path.length = 1; + path[0].splice(0, path[0].length - 1); +} + function flushPenState(elem) { var state = getTurtleData(elem); if (!state.style || (!state.down && !state.style.savePath)) { @@ -1378,32 +1438,17 @@ function flushPenState(elem) { state.path[0].push(center); } if (!state.style.savePath) { - var ts = readTurtleTransform(elem, true), - ctx = getTurtleDrawingCtx(), - isClosed, - j = state.path.length, - segment; - ctx.save(); - ctx.beginPath(); - // Scale up lineWidth by sx. (TODO: consider parent transforms.) - applyPenStyle(ctx, state.style, ts.sx); - while (j--) { - if (state.path[j].length) { - segment = state.path[j]; - isClosed = segment.length > 2 && isPointNearby( - segment[0], segment[segment.length - 1]); - ctx.moveTo(segment[0].pageX, segment[0].pageY); - for (var k = 1; k < segment.length - (isClosed ? 1 : 0); ++k) { - ctx.lineTo(segment[k].pageX, segment[k].pageY); - } - if (isClosed) { ctx.closePath(); } - } - } - if ('fillStyle' in state.style) { ctx.fill(); } - if ('strokeStyle' in state.style) { ctx.stroke(); } - ctx.restore(); - state.path.length = 1; - state.path[0].splice(0, state.path[0].length - 1); + var ts = readTurtleTransform(elem, true); + drawAndClearPath(state.path, state.style, ts.sx); + } +} + +function endAndFillPenPath(elem, style) { + var ts = readTurtleTransform(elem, true), + state = getTurtleData(elem); + drawAndClearPath(state.path, style); + if (state.style.savePath) { + $.style(elem, 'turtlePenStyle', 'none'); } } @@ -1853,6 +1898,13 @@ var turtlefn = { } }); }, + fill: function(style) { + if (!style) { style = 'black'; } + var ps = parsePenStyle(style, 'fillStyle'); + return this.direct(function(j, elem) { + endAndFillPenPath(elem, ps); + }); + }, dot: function(style, diameter) { if ($.isNumeric(style)) { // Allow for parameters in either order. @@ -1881,6 +1933,13 @@ var turtlefn = { watchImageToFixOriginOnLoad(elem); }); }, + play: function(notes) { + var args = arguments; + return this.queue(function() { + // playABC will call $(this).dequeue() when song is done. + playABC(this, args); + }); + }, speed: function(mps) { return this.direct(function(j, elem) { this.css('turtleSpeed', mps); @@ -2094,7 +2153,7 @@ var turtlefn = { }), action = animation.finish = (args ? (function() { callback.apply($(elem), args); }) : - (function() { callback.call($(elem), j, elem); })); + (function() { callback.call($(elem), index, elem); })); $.queue(elem, qname, animation); } var elem, sel, length = this.length, j = 0; @@ -2142,12 +2201,7 @@ var dollar_turtle_methods = { tick: function(x, y) { directIfGlobal(function() { tick(x, y); }); }, defaultspeed: function(mps) { directIfGlobal(function() { defaultspeed(mps); }); }, - play: function(ops) { - var x = arguments; - directIfGlobal(function() { - play.apply(null, x); - }); - }, + playnow: function() { playABC(null, arguments); }, print: function(html) { return output(html, 'div'); }, random: random, hatch: hatch, @@ -2207,7 +2261,12 @@ $.turtle = function turtle(id, options) { $.extend(window, dollar_turtle_methods); } // Set default turtle speed - defaultspeed(options.hasOwnProperty('defaultspeed') ? options.defaultspeed : 1); + defaultspeed(options.hasOwnProperty('defaultspeed') ? + options.defaultspeed : 1); + // Initialize audio context (avoids delay in first notes). + try { + getAudioTop(); + } catch (e) { } // Find or create a singleton turtle if one does not exist. var selector = null; if (id) { @@ -2759,26 +2818,32 @@ function durationToTime(duration) { d = (m[2] ? parseFloat(m[2]) : /\//.test(duration) ? 2 : 1); return n / d; } -function play(opts) { +function playABC(elem, args) { var atop = getAudioTop(), - start_time = atop.ac.currentTime, + start_time = atop.ac.currentTime, end_time = start_time, firstvoice = 0, voice, freqmult, beatsecs, - volume = 0.5, tempo = 120, transpose = 0, type = ['sine']; - if ($.isPlainObject(opts)) { + volume = 0.5, tempo = 120, transpose = 0, type = ['square'], + envelope = {a: 0.01, d: 0.2, s: 0.1, r: 0.1}, + notes, vtype, time, fingers, strength, i, g, t, + atime, slast, rtime, stime, dt, opts; + if ($.isPlainObject(args[0])) { + opts = args[0]; if ('volume' in opts) { volume = opts.volume; } if ('tempo' in opts) { tempo = opts.tempo; } if ('transpose' in opts) { transpose = opts.transpose; } if ('type' in opts) { type = opts.type; } + if ('envelope' in opts) { $.extend(envelope, opts.envelope); } firstvoice = 1; } voice = firstvoice; beatsecs = 60 / tempo; freqmult = Math.pow(2, transpose / 12); if (!$.isArray(type)) { type = [type]; } - for (; voice < arguments.length; voice++) { - var notes = parseABCNotes(arguments[voice]), - vtype = type[(voice - firstvoice) % type.length] || 'sine', - time = start_time, fingers = 0, strength, i; + for (; voice < args.length; voice++) { + notes = parseABCNotes(args[voice]); + vtype = type[(voice - firstvoice) % type.length] || 'square'; + time = start_time; + fingers = 0; for (i = 0; i < notes.length; i++) { fingers = Math.max(fingers, notes[i].frequency.length); } @@ -2786,21 +2851,21 @@ function play(opts) { // Attenuate chorded voice so chorded power matches volume. strength = volume / Math.sqrt(fingers); for (i = 0; i < notes.length; i++) { + t = notes[i].time; if (notes[i].frequency.length > 0) { - var g = atop.ac.createGainNode(), - secs = notes[i].time * beatsecs, - envelope, pt; + g = atop.ac.createGainNode(); + stime = t * beatsecs + time; + atime = Math.min(t, envelope.a) * beatsecs + time; + rtime = Math.max(0, t + envelope.r) * beatsecs + time; + if (atime > rtime) { atime = rtime = (atime + rtime) / 2; } + if (rtime < stime) { stime = rtime; rtime = t * beatsecs + time; } + dt = envelope.d * beatsecs; g.gain.setValueAtTime(0, time); - envelope = [ - {v: 1.0, t: Math.min(0.01 * beatsecs, 0.1 * secs)}, - {v: 0.9, t: Math.min(0.05 * beatsecs, 0.2 * secs)}, - {v: 0.6, t: Math.min(secs - 0.05 * beatsecs, 0.9 * secs)}, - {v: 0.0, t: secs} - ]; - for (var e = 0; e < envelope.length; e++) { - pt = envelope[e]; - g.gain.linearRampToValueAtTime(pt.v * strength, time + pt.t); - } + g.gain.linearRampToValueAtTime(strength, atime); + g.gain.setTargetAtTime(envelope.s * strength, atime, dt); + slast = envelope.s + (1 - envelope.s) * Math.exp((atime - stime) / dt); + g.gain.setValueAtTime(slast * strength, stime); + g.gain.linearRampToValueAtTime(0, rtime); g.connect(atop.out); for (var x = 0; x < notes[i].frequency.length; x++) { var o = atop.ac.createOscillator(); @@ -2808,12 +2873,23 @@ function play(opts) { o.frequency.value = notes[i].frequency[x] * freqmult; o.connect(g); o.start(time); - o.stop(time + secs); + o.stop(rtime); } } - time += notes[i].time * beatsecs; + time += t * beatsecs; + } + end_time = Math.max(end_time, time); + } + function callDequeueWhenDone() { + if (atop.ac.currentTime < end_time) { + setTimeout(callDequeueWhenDone, (end_time - atop.ac.currentTime) * 1000); + } else { + $(elem).dequeue(); } } + if (elem) { + callDequeueWhenDone(); + } } From 54d88d2d10d6761400ae9d1530b149a0c6945963 Mon Sep 17 00:00:00 2001 From: David Bau Date: Mon, 8 Jul 2013 08:15:44 -0400 Subject: [PATCH 18/25] version 2.0.6 --- jquery-turtle.js | 1636 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 1277 insertions(+), 359 deletions(-) diff --git a/jquery-turtle.js b/jquery-turtle.js index 8ef7e57..58cdef8 100644 --- a/jquery-turtle.js +++ b/jquery-turtle.js @@ -4,7 +4,7 @@ jQuery-turtle ============= -version 2.0.5 +version 2.0.6 jQuery-turtle is a jQuery plugin for turtle graphics. @@ -42,7 +42,7 @@ sixteen colored polygons. lt 360 / sides pen 'none' fd 40 - move 40, -160 + slide 40, -160

    [Try an interactive demo (CoffeeScript syntax) here.]( @@ -61,20 +61,26 @@ the default turtle, if used): $(x).bk(50) // Back. $(x).rt(90) // Right turn. $(x).lt(45) // Left turn. - $(x).move(x, y) // Move right by x while moving forward by y. - $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion on page. - $(x).turnto(bearing || position) // Absolute direction adjustment. - $(x).play("ccgg") // Plays notes using ABC notation. + $(x).slide(x, y) // Move right by x while moving forward by y. + $(x).rarc(100,60) // Turn right 60 degrees tracing an arc of radius 100. + $(x).larc(50,360) // Left 360 degrees tracing a full circle of radius 50. + $(x).moveto({pageX:x,pageY:y} | [x,y]) // Absolute motion on page. + $(x).turnto(bearing || position) // Absolute direction adjustment. + $(x).play("ccgg") // Plays notes using ABC notation and waits until done. // Methods below happen in an instant, but line up in the animation queue. - $(x).home() // Moves to the origin of the document, with bearing 0. + $(x).home() // Jumps to the center of the document, with bearing 0. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. - $(x).fill('pink') // Fills a shape previously outlined using pen('path'). + $(x).pu() // Pen up - temporarily disables the pen (also pen(false)). + $(x).pd() // Pen down - starts a new pen path. + $(x).pe() // Uses the pen 'erase' style. + $(x).fill('gold') // Fills a shape previously outlined using pen('path'). $(x).dot(12) // Draws a circular dot of diameter 12. - $(x).mark('A') // Prints an HTML inline-block at the turtle location. + $(x).label('A') // Prints an HTML label at the turtle location. $(x).speed(10) // Sets turtle animation speed to 10 moves per sec. - $(x).erase() // Erases the canvas under the turtle collision hull. - $(x).img('blue') // Switches the turtle to a blue picture. Use any url. + $(x).ht() // Hides the turtle. + $(x).st() // Shows the turtle. + $(x).wear('blue') // Switches to a blue shell. Use any image or color. $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". $(x).mirror(true) // Flips the turtle across its main axis. @@ -83,36 +89,77 @@ the default turtle, if used): // and the callback fn can insert into the animation queue. // Methods below this line do not queue for animation. - $(x).origin() // Page coordinate of the turtle's transform-origin. + $(x).getxy() // Local (center-y-up [x, y]) coordinates of the turtle. + $(x).pagexy() // Page (topleft-y-down {pageX:x, pageY:y}) coordinates. $(x).bearing([p]) // The turtles absolute direction (or direction towards p). $(x).distance(p) // Distance to p in page coordinates. $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") $(x).touches(y) // Collision tests elements (uses turtleHull if present). $(x).encloses(y) // Containment collision test. - $(x).within(d, t) // Filters to items with origins within d of t.origin(). + $(x).within(d, t) // Filters to items with centers within d of t.pagexy(). $(x).notwithin() // The negation of within. - $(x).cell(x, y) // Selects the yth row and xth column cell in a table. + $(x).cell(y, x) // Selects the yth row and xth column cell in a table. + $(x).hatch([n,] [img]) // Creates and returns n turtles with the given img. When the speed of a turtle is nonzero, the first seven movement -functions animate at that speed, and the remaining mutators also -participate in the animation queue. The default turtle speed is -a leisurely one move per second (as appropriate for the creature), -but you may soon discover the desire to set speed higher. +functions animate at that speed (in moves per second), and the +remaining mutators also participate in the animation queue. The +default turtle speed is a leisurely one move per second (as +appropriate for the creature), but you may soon discover the +desire to set speed higher. -Setting the turtle speed to Infinity will make movement synchronous, +Setting the turtle speed to Infinity will make its movement synchronous, which makes the synchronous distance, direction, and hit-testing useful -for realtime game-making. To play music without stalling turtle -movement, use the global function playnow() instead of the turtle -method play(). - -The absolute motion methods moveto and turnto accept any object -that has pageX and pageY properties (or an origin() method that will -return such an object), including, usefully, mouse events. -Moveto and turnto operate in absolute page coordinates and work -properly even when the turtle is nested within further CSS -transformed elements. +for realtime game-making. + +The turtle pen respects canvas styling: any valid strokeStyle is +accepted; and also using a space-separated syntax, lineWidth, lineCap, +lineJoin, miterLimit, and fillStyle can be specified, e.g., +pen('red lineWidth 5 lineCap square'). The same syntax applies for +styling dot and fill (except that the default interpretation for the +first value is fillStyle instead of strokeStyle). + +The fill method is used by tracing an invisible path using the +pen('path') style, and then calling the fill method. Disconnected +paths can be created using pu() and pd(). + +The play method plays a sequence of notes specified using a subset of +standard ABC notation. Capital C denotes middle C, and lowercase c is +an octave higher. Pitches and durations can be altered with commas, +apostrophes, carets, underscores, digits, and slashes as in the +standard. Enclosing letters in square brackets represents a chord, +and z represents a rest. The default tempo is 120, but can be changed +by passing a options object as the first parameter setting tempo, e.g., +{ tempo: 200 }. Other options include volume: 0.5, type: 'sine' or +'square' or 'sawtooth' or 'triangle', and envelope: which defines +an ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }. + +The turtle's motion will pause while it is playing notes. To play +notes without stalling turtle movement, use the global function sound() +instead of the turtle method play(). + +The direct method can be used to queue logic (including synchronous +tests or actions) by running a function in the animation queue. Unlike +jquery queue(), direct arranges things so that if further animations +are queued by the callback function, they are inserted (in natural +recursive functional execution order) instead of being appended. + +The turnto method can turn to an absolute bearing (if called with a +single numeric argument) or towards an absolute position on the +screen. The methods moveto and turnto accept either page or +graphing coordinates. + +Graphing coordinates are measured upwards and rightwards from the +center of the page, and they are specified as bare numeric x, y +arguments or [x, y] pairs as returned from getxy(). + +Page coordinates are specified by an object with pageX and pageY +properties, or with a pagexy() method that will return such an object. +That includes, usefullly, mouse events and turtle objects. Page +coordinates are measured downward from the top-left corner of the +page to the center (or transform-origin) of the given object. The hit-testing functions touches() and encloses() will test for collisions using the convex hulls of the objects in question. @@ -124,9 +171,10 @@ Turtle Teaching Environment --------------------------- A default turtle together with an interactive console are created by -calling eval($.turtle()). This call will expose a the default turtle -methods as global functions. It will also set up a number of other global -symbols to provide beginners with a simplified programming environment. +calling eval($.turtle()). That call exposes all the turtle methods +such as (fd, rt, getxy, etc) as global functions operating on the default +turtle. It will also set up a number of other global symbols to provide +beginners with a simplified programming environment. In detail, after eval($.turtle()): * An <img id="turtle"> is created if #turtle doesn't already exist. @@ -148,9 +196,13 @@ $.turtle() are as follows: keydown // The last keydown event. keyup // The last keyup event. keypress // The last keypress event. + hatch([n,] [img]) // Creates and returns n turtles with the given img. + cs() // Clears the screen, both the canvas and the body text. + cg() // Clears the graphics canvas without clearing the text. + ct() // Clears the text without clearing the canvas. defaultspeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. tick([perSec,] fn) // Sets fn as the tick callback (null to clear). - random(n) // Returns a random number [0...n-1]. + random(n) // Returns a random number [0..n-1]. random(list) // Returns a random element of the list. random('normal') // Returns a gaussian random (mean 0 stdev 1). random('uniform') // Returns a uniform random [0...1). @@ -158,13 +210,14 @@ $.turtle() are as follows: random('color') // Returns a random hsl(*, 100%, 50%) color. random('gray') // Returns a random hsl(0, 0, *) gray. remove() // Removes default turtle and its globals (fd, etc). - hatch([n,], [img]) // Creates and returns n turtles with the given img. see(a, b, c...) // Logs tree-expandable data into debugging panel. - print(html) // Appends html into the document body. - input([label,] fn) // Makes a one-time input field, calls fn after entry. + write(html) // Appends html into the document body. + read([label,] fn) // Makes a one-time input field, calls fn after entry. + readnum([label,] fn) // Like read, but restricted to numeric input. + readstr([label,] fn) // Like read, but never converts input to a number. button([label,] fn) // Makes a clickable button, calls fn when clicked. - table(w, h) // Outputs a table with h rows and w columns. - playnow('CEG') // Plays musical notes now, without queueing. + table(m, n) // Outputs a table with m rows and n columns. + sound('[DFG][EGc]') // Plays musical notes now, without queueing. Here is another CoffeeScript example that demonstrates some of @@ -174,7 +227,7 @@ the functions: eval $.turtle() # Create the default turtle and global functions. defaultspeed Infinity - print "Catch blue before red gets you." + write "Catch blue before red gets you." bk 100 r = hatch 'red' b = hatch 'blue' @@ -186,13 +239,13 @@ the functions: b.turnto bearing b b.fd 3 if b.touches(turtle) - print "You win!" + write "You win!" tick off else if r.touches(turtle) - print "Red got you!" + write "Red got you!" tick off else if not b.touches(document) - print "Blue got away!" + write "Blue got away!" tick off @@ -208,22 +261,33 @@ with animation support on all motion:
       $(x).css('turtleSpeed', '10');         // default speed in moves per second.
       $(x).css('turtlePosition', '30 40');   // position in local coordinates.
    -  $(x).css('turtlePositionX', '30');     // x component.
    -  $(x).css('turtlePositionY', '40');     // y component.
    -  $(x).css('turtleRotation', '90');      // rotation in degrees.
    +  $(x).css('turtlePositionX', '30px');   // x component.
    +  $(x).css('turtlePositionY', '40px');   // y component.
    +  $(x).css('turtleRotation', '90deg');   // rotation in degrees.
       $(x).css('turtleScale', '2');          // double the size of any element.
       $(x).css('turtleScaleX', '2');         // x stretch after twist.
       $(x).css('turtleScaleY', '2');         // y stretch after twist.
    -  $(x).css('turtleTwist', '45');         // turn before stretching.
    -  $(x).css('turtleForward', '50');       // position in direction of rotation.
    +  $(x).css('turtleTwist', '45deg');      // turn before stretching.
    +  $(x).css('turtleForward', '50px');     // position in direction of rotation.
    +  $(x).css('turtleTurningRadius, '50px');// arc turning radius for rotation.
       $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
       $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
       $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
     
    Arbitrary 2d transforms are supported, including transforms of elements -nested within other elements that have css transforms. Transforms are -automatically decomposed to turtle components when necessary. +nested within other elements that have css transforms. For example, arc +paths of a turtle within a skewed div will transform to the proper elliptical +arc. Note that while turtle motion is transformed, lines and dots are not: +for example, dots are always circular. To get transformed circles, trace +out an arc. + +Transforms on the turtle itself are used to infer the turtle position, +direction, and rendering of the sprite. ScaleY stretches the turtle +sprite in the direction of movement also stretches distances for +motion in all directions. ScaleX stretches the turtle sprite perpendicular +to the direction of motion and also stretches line and dot widths for +drawing. A canvas is supported for drawing, but only created when the pen is used; pen styles include canvas style properties such as lineWidth @@ -382,6 +446,10 @@ function subtractVector(v, s) { return [v[0] - s[0], v[1] - s[1]]; } +function scaleVector(v, s) { + return [v[0] * s, v[1] * s]; +} + function translatedMVP(m, v, origin) { return addVector(matrixVectorProduct(m, subtractVector(v, origin)), origin); } @@ -439,6 +507,30 @@ function decomposeSVD(m) { return [theta, sv1, sv2, phi]; } +// Returns approximate three bezier curve control points for a unit circle +// arc from angle a1 to a2 (not including the beginning point). +function approxBezierUnitArc(a1, a2) { + var a = (a2 - a1) / 2, + x4 = Math.cos(a), + y4 = Math.sin(a), + x1 = x4, + y1 = -y4, + q2 = 1 + x1 * x4 + y1 * y4, + k2 = 4/3 * (Math.sqrt(2 * q2) - q2) / (x1 * y4 - y1 * x4), + x2 = x1 - k2 * y1, + y2 = y1 + k2 * x1, + x3 = x2, + y3 = -y2, + ar = a + a1, + car = Math.cos(ar), + sar = Math.sin(ar); + return [ + [x2 * car - y2 * sar, x2 * sar + y2 * car], + [x3 * car - y3 * sar, x3 * sar + y3 * car], + [Math.cos(a2), Math.sin(a2)] + ]; +} + ////////////////////////////////////////////////////////////////////////// // CSS TRANSFORMS // Basic manipulation of 2d CSS transforms. @@ -474,9 +566,14 @@ function readTransformMatrix(elem) { function readTransformOrigin(elem, wh) { var gcs = (window.getComputedStyle ? window.getComputedStyle(elem) : null), origin = (gcs && gcs[transformOrigin] || $.css(elem, 'transformOrigin')); - return origin && origin.indexOf('%') < 0 ? - $.map(origin.split(' '), parseFloat) : - [wh[0] / 2, wh[1] / 2]; + if (origin && origin.indexOf('%') < 0) { + return $.map(origin.split(' '), parseFloat); + } + if (wh) { + return [wh[0] / 2, wh[1] / 2]; + } + var sel = $(elem); + return [sel.width() / 2, sel.height() / 2]; } // Composes all the 2x2 transforms up to the top. @@ -730,7 +827,7 @@ function readPageGbcr() { left: 0, right: this.width || 0, width: this.width || 0, - height: this.height || 0, + height: this.height || 0 } } return { @@ -773,13 +870,61 @@ function computeTargetAsTurtlePosition(elem, target, limit, localx, localy) { subtractVector([target.pageX, target.pageY], origin)); if (localx || localy) { var ts = readTurtleTransform(elem, true), - r = (ts || 0) && convertToRadians(ts.rot); - localTarget[0] += Math.cos(r) * localx + Math.sin(r) * localy; - localTarget[1] += Math.sin(r) * localx - Math.cos(r) * localy; + sy = ts ? ts.sy : 1; + localTarget[0] += localx * sy; + localTarget[1] -= localy * sy; } return cssNum(localTarget[0]) + ' ' + cssNum(localTarget[1]); } +function homeContainer(elem) { + var container = elem.offsetParent; + if (!container || container == drawing.surface) { + return document; + } + return container; +} + +// Compute the home position and the turtle location in local turtle +// coordinates; return the local offset from the home position as +// an array of len 2. +function computePositionAsLocalOffset(elem, home) { + if (!home) { + home = $(homeContainer(elem)).pagexy(); + } + var totalParentTransform = totalTransform2x2(elem.parentElement), + inverseParent = inverse2x2(totalParentTransform), + hidden = ($.css(elem, 'display') === 'none'), + swapout = hidden ? + { position: "absolute", visibility: "hidden", display: "block" } : {}, + substTransform = swapout[transform] = (inverseParent ? 'matrix(' + + $.map(inverseParent, cssNum).join(', ') + ', 0, 0)' : 'none'), + gbcr = cleanSwap(elem, swapout, readPageGbcr), + middle = readTransformOrigin(elem, [gbcr.width, gbcr.height]), + origin = addVector([gbcr.left, gbcr.top], middle), + ts = readTurtleTransform(elem, true), + localHome = inverseParent && matrixVectorProduct(inverseParent, + subtractVector([home.pageX, home.pageY], origin)), + isy = ts && 1 / ts.sy; + if (!inverseParent) { return; } + return [(ts.tx - localHome[0]) * isy, (localHome[1] - ts.ty) * isy]; +} + +function convertLocalXyToPageCoordinates(elem, localxy) { + var totalParentTransform = totalTransform2x2(elem.parentElement), + ts = readTurtleTransform(elem, true), + center = $(homeContainer(elem)).pagexy(), + result = [], + pageOffset, j; + for (j = 0; j < localxy.length; j++) { + pageOffset = matrixVectorProduct( + totalParentTransform, [localxy[j][0] * ts.sy, -localxy[j][1] * ts.sy]); + result.push({ pageX: center.pageX + pageOffset[0], + pageY: center.pageY + pageOffset[1] }); + } + return result; +} + // Uses getBoundingClientRect to figure out current position in page // coordinates. Works by backing out local transformation (and inverting // any parent rotations and distortions) so that the bounding rect is @@ -789,7 +934,7 @@ function getCenterInPageCoordinates(elem) { if ($.isWindow(elem)) { return getRoundedCenterLTWH( $(window).scrollLeft(), $(window).scrollTop(), ww(), wh()); - } else if (elem.nodeType === 9) { + } else if (elem.nodeType === 9 || elem == document.body) { return getRoundedCenterLTWH(0, 0, dw(), dh()); } var tr = getElementTranslation(elem), @@ -860,6 +1005,7 @@ function getCornersInPageCoordinates(elem, untransformed) { }); } +/* function computeDirectionAsTurtleRotation(elem, target, limit) { var totalParentTransform = totalTransform2x2(elem.parentElement), inverseParent = inverse2x2(totalParentTransform), @@ -879,10 +1025,11 @@ function computeDirectionAsTurtleRotation(elem, target, limit) { tr = Math.atan2(lp[0], lp[1]); return radiansToDegrees(tr); } +*/ function getDirectionOnPage(elem) { var ts = readTurtleTransform(elem, true), - r = convertToRadians(ts.rot), + r = convertToRadians(normalizeRotation(ts.rot)), ux = Math.sin(r), uy = Math.cos(r), totalParentTransform = totalTransform2x2(elem.parentElement), up = matrixVectorProduct(totalParentTransform, [ux, uy]); @@ -1174,9 +1321,16 @@ function normalizeRotation(x) { return x; } +function normalizeRotationDelta(x) { + if (Math.abs(x) >= 720) { + x = x % 360 + (x > 0 ? 360 : -360); + } + return x; +} + ////////////////////////////////////////////////////////////////////////// // TURTLE DRAWING SUPPORT -// If pen, erase, or dot are used, then a full-page canvas is created +// If pen, fill, or dot are used, then a full-page canvas is created // and used for drawing. ////////////////////////////////////////////////////////////////////////// @@ -1195,13 +1349,16 @@ function getTurtleClipSurface() { return drawing.surface; } var surface = document.createElement('samp'); - $(surface).css({ - position: 'absolute', - display: 'inline-block', - top: 0, left: 0, width: '100%', height: '100%', - 'z-index': -1, - overflow: 'hidden' - }); + $(surface) + .attr('id', '_turtlefield') + .css({ + position: 'absolute', + display: 'inline-block', + top: 0, left: 0, width: '100%', height: '100%', + zIndex: -1, + fontFamily: 'inherit', + overflow: 'hidden' + }); drawing.surface = surface; attachClipSurface(); return surface; @@ -1210,6 +1367,25 @@ function getTurtleClipSurface() { function attachClipSurface() { if (document.body) { $(drawing.surface).prependTo('body'); + // Attach an event handler to forward mouse events from the body + // to turtles in the turtle field layer. + $('body').on('click.turtle ' + + 'mouseup.turtle mousedown.turtle mousemove.turtle', function(e) { + if (e.target === this && !e.isTrigger) { + // Only forward events directly on the body that (geometrically) + // touch a turtle directly within the turtlefield. + var sel = $('#_turtlefield > .turtle').within('touch', e).eq(0); + if (sel.length === 1) { + // Erase portions of the event that are wrong for the turtle. + e.target = null; + e.relatedTarget = null; + e.fromElement = null; + e.toElement = null; + sel.trigger(e); + return false; + } + } + }); } else { $(document).ready(attachClipSurface); } @@ -1222,7 +1398,7 @@ function getTurtleDrawingCtx() { var surface = getTurtleClipSurface(); drawing.canvas = document.createElement('canvas'); $(drawing.canvas).css({'z-index': -1}); - surface.appendChild(drawing.canvas); + surface.insertBefore(drawing.canvas, surface.firstChild); drawing.ctx = drawing.canvas.getContext('2d'); resizecanvas(); pollbodysize(resizecanvas); @@ -1279,6 +1455,12 @@ function parsePenStyle(text, defaultProp) { text = text.trim(); if (!text || text === 'none') { return null; } if (text === 'path') { return { savePath: true }; } + var eraseMode = false; + if (/^erase\b/.test(text)) { + text = text.replace( + /^erase\b/, 'white globalCompositeOperation destination-out'); + eraseMode = true; + } var words = text.split(/\s+/), mapping = { strokeStyle: identity, @@ -1287,8 +1469,10 @@ function parsePenStyle(text, defaultProp) { lineJoin: identity, miterLimit: parseFloat, fillStyle: identity, + globalCompositeOperation: identity }, result = {}, j, end = words.length; + if (eraseMode) { result.eraseMode = true; } for (j = words.length - 1; j >= 0; --j) { if (mapping.hasOwnProperty(words[j])) { var key = words[j], @@ -1327,15 +1511,48 @@ function getTurtleData(elem) { var state = $.data(elem, 'turtleData'); if (!state) { state = $.data(elem, 'turtleData', { - style: {}, + style: null, path: [[]], down: true, - speed: 'turtle' + speed: 'turtle', + turningRadius: 0, + // Below: support for image loading without messing up origin. + lastSeenOrigin: null, + lastSeenOriginTime: null, + lastSeenOriginTimer: null, + lastSeenOriginEvent: null }); } return state; } +function getTurningRadius(elem) { + var state = $.data(elem, 'turtleData'); + if (!state) { return 0; } + return state.turningRadius; +} + +function makeTurningRadiusHook() { + return { + get: function(elem, computed, extra) { + return cssNum(getTurningRadius(elem)) + 'px'; + }, + set: function(elem, value) { + var radius = parseFloat(value); + if (isNaN(radius)) return; + getTurtleData(elem).turningRadius = radius; + elem.style.turtleTurningRadius = '' + cssNum(radius) + 'px'; + if (radius === 0) { + var ts = readTurtleTransform(elem, false); + if (ts && (ts.rot > 180 || ts.rot <= -180)) { + ts.rot = normalizeRotation(ts.rot); + elem.style[transform] = writeTurtleTransform(ts); + } + } + } + }; +} + function makePenStyleHook() { return { get: function(elem, computed, extra) { @@ -1372,14 +1589,15 @@ function isPointNearby(a, b) { function applyPenStyle(ctx, ps, scale) { scale = scale || 1; + var extraWidth = ps.eraseMode ? 1 : 0; if (!ps || !('strokeStyle' in ps)) { ctx.strokeStyle = 'black'; } - if (!ps || !('lineWidth' in ps)) { ctx.lineWidth = 1.62 * scale; } + if (!ps || !('lineWidth' in ps)) { ctx.lineWidth = 1.62 * scale + extraWidth; } if (!ps || !('lineCap' in ps)) { ctx.lineCap = 'round'; } if (ps) { for (var a in ps) { - if (a === 'savePath') { continue; } + if (a === 'savePath' || a === 'eraseMode') { continue; } if (scale && a === 'lineWidth') { - ctx[a] = scale * ps[a]; + ctx[a] = scale * ps[a] + extraWidth; } else { ctx[a] = ps[a]; } @@ -1389,7 +1607,7 @@ function applyPenStyle(ctx, ps, scale) { function drawAndClearPath(path, style, scale) { var ctx = getTurtleDrawingCtx(), - isClosed, + isClosed, skipLast, j = path.length, segment; ctx.save(); @@ -1401,9 +1619,17 @@ function drawAndClearPath(path, style, scale) { segment = path[j]; isClosed = segment.length > 2 && isPointNearby( segment[0], segment[segment.length - 1]); + skipLast = isClosed && (!('pageX2' in segment[segment.length - 1])); ctx.moveTo(segment[0].pageX, segment[0].pageY); - for (var k = 1; k < segment.length - (isClosed ? 1 : 0); ++k) { - ctx.lineTo(segment[k].pageX, segment[k].pageY); + for (var k = 1; k < segment.length - (skipLast ? 1 : 0); ++k) { + if ('pageX2' in segment[k]) { + ctx.bezierCurveTo( + segment[k].pageX1, segment[k].pageY1, + segment[k].pageX2, segment[k].pageY2, + segment[k].pageX, segment[k].pageY); + } else { + ctx.lineTo(segment[k].pageX, segment[k].pageY); + } } if (isClosed) { ctx.closePath(); } } @@ -1415,6 +1641,18 @@ function drawAndClearPath(path, style, scale) { path[0].splice(0, path[0].length - 1); } +function addBezierToPath(path, start, triples) { + if (!path.length || !isPointNearby(start, path[path.length - 1])) { + path.push(start); + } + for (var j = 0; j < triples.length; ++j) { + path.push({ + pageX1: triples[j][0].pageX, pageY1: triples[j][0].pageY, + pageX2: triples[j][1].pageX, pageY2: triples[j][1].pageY, + pageX: triples[j][2].pageX, pageY: triples[j][2].pageY }); + } +} + function flushPenState(elem) { var state = getTurtleData(elem); if (!state.style || (!state.down && !state.style.savePath)) { @@ -1429,6 +1667,7 @@ function flushPenState(elem) { } return; } + if (state.lastSeenOrigin) { fixOriginIfWatching(elem); } var center = getCenterInPageCoordinates(elem); // Once the pen is down, the origin needs to be stable when the image // loads. @@ -1447,7 +1686,7 @@ function endAndFillPenPath(elem, style) { var ts = readTurtleTransform(elem, true), state = getTurtleData(elem); drawAndClearPath(state.path, style); - if (state.style.savePath) { + if (state.style && state.style.savePath) { $.style(elem, 'turtlePenStyle', 'none'); } } @@ -1460,9 +1699,21 @@ function fillDot(position, diameter, style) { ctx.arc(position.pageX, position.pageY, diameter / 2, 0, 2*Math.PI, false); ctx.closePath(); ctx.fill(); + if (style.strokeStyle) { + ctx.stroke(); + } ctx.restore(); } +function clearField(arg) { + if (!arg || /\bcanvas\b/.test(arg)) { + eraseBox(document, {fillStyle: 'transparent'}); + } + if (!arg || /\btext\b/.test(arg)) { + $('body').contents().not('samp#_testpanel,samp#_turtlefield').remove(); + } +} + function eraseBox(elem, style) { var c = getCornersInPageCoordinates(elem), ctx = getTurtleDrawingCtx(), @@ -1491,15 +1742,24 @@ function eraseBox(elem, style) { function applyImg(sel, img) { if (sel[0].tagName == 'IMG') { + sel[0].src = ''; sel[0].src = img.url; + sel.css({ + backgroundImage: 'none', + height: 'auto', + width: 'auto' + }); sel.css(img.css); } else { - sel.css({ + var props = { backgroundImage: 'url(' + img.url + ')', backgroundRepeat: 'no-repeat', backgroundPosition: 'center', - backgroundSize: img.css.width + 'px ' + img.css.height + 'px' - }); + }; + if (img.css.width && img.css.height) { + props.backgroundSize = img.css.width + 'px ' + img.css.height + 'px'; + } + sel.css(props); } } @@ -1507,7 +1767,7 @@ function doQuickMove(elem, distance, sideways) { var ts = readTurtleTransform(elem, true), r = ts && convertToRadians(ts.rot), scaledDistance = ts && (distance * ts.sy), - scaledSideways = ts && ((sideways || 0) * ts.sx), + scaledSideways = ts && ((sideways || 0) * ts.sy), dy = -Math.cos(r) * scaledDistance, dx = Math.sin(r) * scaledDistance; if (!ts) { return; } @@ -1525,7 +1785,7 @@ function displacedPosition(elem, distance, sideways) { var ts = readTurtleTransform(elem, true), r = ts && convertToRadians(ts.rot), scaledDistance = ts && (distance * ts.sy), - scaledSideways = ts && ((sideways || 0) * ts.sx), + scaledSideways = ts && ((sideways || 0) * ts.sy), dy = -Math.cos(r) * scaledDistance, dx = Math.sin(r) * scaledDistance; if (!ts) { return; } @@ -1567,24 +1827,32 @@ function animTime(elem) { function makeTurtleForwardHook() { return { get: function(elem, computed, extra) { - var ts = readTurtleTransform(elem, computed); + // TODO: after reading turtleForward, we need to also + // adjust it if ts.tx/ty change due to an origin change, + // so that images don't stutter if they resize during an fd. + // OR - offset by origin, so that changes in its value are + // not a factor. + var ts = readTurtleTransform(elem, computed), + middle = readTransformOrigin(elem); if (ts) { var r = convertToRadians(ts.rot), c = Math.cos(r), s = Math.sin(r); - return (ts.tx * s - ts.ty * c) / ts.sy + 'px'; + return cssNum(((ts.tx + middle[0]) * s - (ts.ty + middle[1]) * c) + / ts.sy) + 'px'; } }, set: function(elem, value) { var ts = readTurtleTransform(elem, true) || {tx: 0, ty: 0, rot: 0, sx: 1, sy: 1, twi: 0}, + middle = readTransformOrigin(elem), v = parseFloat(value) * ts.sy, r = convertToRadians(ts.rot), c = Math.cos(r), s = Math.sin(r), - p = ts.tx * c + ts.ty * s; - ts.tx = p * c + v * s; - ts.ty = p * s - v * c; + p = (ts.tx + middle[0]) * c + (ts.ty + middle[1]) * s; + ts.tx = p * c + v * s - middle[0]; + ts.ty = p * s - v * c - middle[1]; elem.style[transform] = writeTurtleTransform(ts); flushPenState(elem); } @@ -1595,25 +1863,87 @@ function makeTurtleForwardHook() { function makeTurtleHook(prop, normalize, unit, displace) { return { get: function(elem, computed, extra) { + if (displace) fixOriginIfWatching(elem); var ts = readTurtleTransform(elem, computed); if (ts) { return ts[prop] + unit; } }, set: function(elem, value) { + if (displace) fixOriginIfWatching(elem); var ts = readTurtleTransform(elem, true) || - {tx: 0, ty: 0, rot: 0, sx: 1, sy: 1, twi: 0}; - ts[prop] = normalize(value); + {tx: 0, ty: 0, rot: 0, sx: 1, sy: 1, twi: 0}, + opt = { displace: displace }; + ts[prop] = normalize(value, elem, ts, opt); elem.style[transform] = writeTurtleTransform(ts); - if (displace) { + if (opt.displace) { flushPenState(elem); } } }; } +function maybeArcRotation(end, elem, ts, opt) { + end = parseFloat(end); + var state = $.data(elem, 'turtleData'), + tradius = state ? state.turningRadius : 0; + if (tradius == 0) { return normalizeRotation(end); } + var r0 = ts.rot, r1, r1r, a1r, a2r, j, r, pts, triples, + delta = normalizeRotationDelta(end - r0), + radius = (delta > 0 ? tradius : -tradius) * ts.sy, + splits = 1, + splita = delta, + absang = Math.abs(delta), + tracing = (state && state.style && state.down), + r0r = convertToRadians(ts.rot), + dc = [Math.cos(r0r) * radius, Math.sin(r0r) * radius], + path, totalParentTransform, start, relative, points; + if (tracing) { + if (!state) { + state = getTurtleData(elem); + } + if (absang > 45) { + splits = Math.ceil(absang / 45); + splita = delta / splits; + } + path = state.path[0]; + totalParentTransform = totalTransform2x2(elem.parentElement); + start = getCenterInPageCoordinates(elem); + relative = []; + while (--splits >= 0) { + r1 = splits === 0 ? end : r0 + splita; + a1r = convertToRadians(r0 + 180); + a2r = convertToRadians(r1 + 180); + relative.push.apply(relative, approxBezierUnitArc(a1r, a2r)); + r0 = r1; + } + points = []; + r = matrixVectorProduct(totalParentTransform, dc); + for (j = 0; j < relative.length; j++) { + // Multiply each coordinate by radius and add to dc; then + // apply parent distortions to get relative offsets to the + // turtle's original position. + r = matrixVectorProduct(totalParentTransform, + addVector(scaleVector(relative[j], radius), dc)); + points.push({ + pageX: r[0] + start.pageX, + pageY: r[1] + start.pageY}); + } + triples = []; + for (j = 0; j < points.length; j += 3) { + triples.push(points.slice(j, j + 3)); + } + addBezierToPath(path, start, triples); + } + r1r = convertToRadians(end) + ts.tx += dc[0] - Math.cos(r1r) * radius; + ts.ty += dc[1] - Math.sin(r1r) * radius; + opt.displace = true; + return end; +} + function makeRotationStep(prop) { return function(fx) { if (!fx.delta) { - fx.delta = normalizeRotation(fx.end - fx.start); + fx.delta = normalizeRotationDelta(fx.end - fx.start); fx.start = fx.end - fx.delta; } $.cssHooks[prop].set(fx.elem, fx.start + fx.delta * fx.pos); @@ -1649,6 +1979,7 @@ var XY = ['X', 'Y']; function makeTurtleXYHook(publicname, propx, propy, displace) { return { get: function(elem, computed, extra) { + fixOriginIfWatching(elem); var ts = readTurtleTransform(elem, computed); if (ts) { if (displace || ts[propx] != ts[propy]) { @@ -1660,6 +1991,7 @@ function makeTurtleXYHook(publicname, propx, propy, displace) { } }, set: function(elem, value, extra) { + fixOriginIfWatching(elem); var ts = readTurtleTransform(elem, true) || {tx: 0, ty: 0, rot: 0, sx: 1, sy: 1, twi: 0}; var parts = (typeof(value) == 'string' ? value.split(/\s+/) : [value]); @@ -1676,29 +2008,69 @@ function makeTurtleXYHook(publicname, propx, propy, displace) { }; } +function fixOriginIfWatching(elem) { + // A function to reposition an image turtle each time its origin + // changes from the last seen origin, to keep the origin in the + // same location on the page. + var state = $.data(elem, 'turtleData'); + if (state && state.lastSeenOrigin) { + var oldOrigin = state.lastSeenOrigin, + newOrigin = readTransformOrigin(elem), + now = (new Date).getTime(); + if (state.lastSeenOriginEvent && elem.complete) { + $.event.remove(elem, 'load.turtle', state.lastSeenOriginEvent); + state.lastSeenOriginEvent = null; + state.lastSeenOriginTime = now; + } + if (newOrigin[0] != oldOrigin[0] || newOrigin[1] != oldOrigin[1]) { + var ts = readTurtleTransform(elem, true); + ts.tx += oldOrigin[0] - newOrigin[0]; + ts.ty += oldOrigin[1] - newOrigin[1]; + state.lastSeenOrigin = newOrigin; + state.lastSeenOriginTime = now; + elem.style[transform] = writeTurtleTransform(ts); + } else if (elem.tagName == 'IMG' && !elem.complete) { + state.lastSeenOriginTime = now; + if (!state.lastSeenOriginEvent) { + state.lastSeenOriginEvent = (function() { fixOriginIfWatching(elem); }); + $.event.add(elem, 'load.turtle', state.lastSeenOriginEvent); + } + } else if (!state.lastSeenOriginTime) { + state.lastSeenOriginTime = now; + } else if (!state.lastSeenOriginEvent && + now - state.lastSeenOriginTime > 1000) { + // Watch for an additional second after anything interesting; + // then clear the watcher. + clearInterval(state.lastSeenOriginTimer); + state.lastSeenOriginTimer = null; + state.lastSeenOriginTime = null; + state.lastSeenOrigin = null; + } + } +} + function watchImageToFixOriginOnLoad(elem) { - if (!elem || elem.tagName !== 'IMG' && elem.complete || - $.data(elem, 'turtleFixingOrigin')) { + if (!elem || elem.tagName !== 'IMG' || + $(elem).css('position') != 'absolute') { return; } - $.data(elem, 'turtleFixingOrigin', true); - var oldOrigin = readTransformOrigin(elem, - [$(elem).width(), $(elem).height()]), - fixOrigin = function() { - var newOrigin = readTransformOrigin(elem, - [$(elem).width(), $(elem).height()]), - ts = readTurtleTransform(elem, true); - $.removeData(elem, 'turtleFixingOrigin'); - ts.tx += oldOrigin[0] - newOrigin[0]; - ts.ty += oldOrigin[1] - newOrigin[1]; - elem.style[transform] = writeTurtleTransform(ts); - jQuery.event.remove(elem, 'load', fixOrigin); - }; - jQuery.event.add(elem, 'load', fixOrigin); + var state = getTurtleData(elem), + now = (new Date).getTime(); + if (state.lastSeenOrigin) { + // Already tracking: let it continue. + fixOriginIfWatching(elem); + return; + } + state.lastSeenOrigin = readTransformOrigin(elem); + state.lastSeenOriginTimer = setInterval(function() { + fixOriginIfWatching(elem); + }, 200); + fixOriginIfWatching(elem); } + function withinOrNot(obj, within, distance, x, y) { - var sel, gbcr; + var sel, gbcr, pos, d2; if (x === undefined && y === undefined) { sel = $(distance); gbcr = getPageGbcr(sel[0]); @@ -1714,33 +2086,46 @@ function withinOrNot(obj, within, distance, x, y) { }); } } + if ($.isNumeric(x) && $.isNumeric(y)) { + pos = [x, y]; + } else { + pos = x; + } + if ($.isArray(pos)) { + // [x, y]: local coordinates. + pos = convertLocalXyToPageCoordinates(obj[0] || document.body, [pos])[0]; + } if (distance === 'touch') { - sel = $(x); - gbcr = getPageGbcr(sel[0]); - if (polyMatchesGbcr(getCornersInPageCoordinates(sel[0]), gbcr)) { + if (isPageCoordinate(pos)) { return obj.filter(function() { - var thisgbcr = getPageGbcr(this); - // !isDisjoint test assumes gbcr is tight. - return within === (!isDisjointGbcr(gbcr, thisgbcr) && - (gbcrEncloses(gbcr, thisgbcr) || sel.touches(this))); + return within === $(this).encloses(pos); }); } else { - return obj.filter(function() { - return within === sel.touches(this); - }); + sel = $(pos); + gbcr = getPageGbcr(sel[0]); + if (polyMatchesGbcr(getCornersInPageCoordinates(sel[0]), gbcr)) { + return obj.filter(function() { + var thisgbcr = getPageGbcr(this); + // !isDisjoint test assumes gbcr is tight. + return within === (!isDisjointGbcr(gbcr, thisgbcr) && + (gbcrEncloses(gbcr, thisgbcr) || sel.touches(this))); + }); + } else { + return obj.filter(function() { + return within === sel.touches(this); + }); + } } } - var ctr = $.isNumeric(x) && $.isNumeric(y) ? { pageX: x, pageY: y } : - isPageCoordinate(x) ? x : - $(x).origin(), - d2 = distance * distance; + d2 = distance * distance; return obj.filter(function() { var gbcr = getPageGbcr(this); - if (isGbcrOutside(ctr, distance, d2, gbcr)) { return !within; } - if (isGbcrInside(ctr, d2, gbcr)) { return within; } - var thisctr = getCenterInPageCoordinates(this), - dx = ctr.pageX - thisctr.pageX, - dy = ctr.pageY - thisctr.pageY; + if (isGbcrOutside(pos, distance, d2, gbcr)) { return !within; } + if (isGbcrInside(pos, d2, gbcr)) { return within; } + fixOriginIfWatching(this); + var thispos = getCenterInPageCoordinates(this), + dx = pos.pageX - thispos.pageX, + dy = pos.pageY - thispos.pageY; return within === (dx * dx + dy * dy <= d2); }); } @@ -1756,10 +2141,11 @@ $.extend(true, $, { turtlePenDown: makePenDownHook(), turtleSpeed: makeTurtleSpeedHook(), turtleForward: makeTurtleForwardHook(), + turtleTurningRadius: makeTurningRadiusHook(), turtlePosition: makeTurtleXYHook('turtlePosition', 'tx', 'ty', true), turtlePositionX: makeTurtleHook('tx', identity, 'px', true), turtlePositionY: makeTurtleHook('ty', identity, 'px', true), - turtleRotation: makeTurtleHook('rot', normalizeRotation, 'deg', false), + turtleRotation: makeTurtleHook('rot', maybeArcRotation, 'deg', true), turtleScale: makeTurtleXYHook('turtleScale', 'sx', 'sy', false), turtleScaleX: makeTurtleHook('sx', identity, '', false), turtleScaleY: makeTurtleHook('sy', identity, '', false), @@ -1767,6 +2153,7 @@ $.extend(true, $, { turtleHull: makeHullHook() }, cssNumber: { + turtleRotation: true, turtleSpeed: true, turtleScale: true, turtleScaleX: true, @@ -1789,24 +2176,73 @@ $.extend(true, $.fx, { } }); +function wraphelp(text, fn) { + fn.helptext = text; + return fn; +} + +function helpwrite(text) { + see.html(''); +} +function globalhelp(obj) { + var helptable = $.extend({}, dollar_turtle_methods, turtlefn), + helplist, j; + if (obj && (!$.isArray(obj.helptext))) { + if (obj in helptable) { + obj = helptable[obj]; + } + } + if (obj && $.isArray(obj.helptext) && obj.helptext.length) { + for (j = 0; j < obj.helptext.length; ++j) { + var text = obj.helptext[j]; + helpwrite(text.replace(/<(u|mark)>/g, + '<$1 style="border:1px solid black;text-decoration:none;' + + 'word-break:keep-all;white-space:nowrap">')); + } + return; + } + helplist = []; + for (var name in helptable) { + if (helptable[name].helptext && helptable[name].helptext.length) { + helplist.push(name); + } + } + helplist.sort(); + helpwrite("help available for: " + helplist.join(" ")); +} +globalhelp.helptext = []; + var turtlefn = { - rt: function(amount) { + rt: wraphelp( + ["rt(degrees) Right turn. Pivots clockwise by some degrees: " + + "rt 90"], + function rt(amount) { return this.direct(function(j, elem) { - this.animate({turtleRotation: '+=' + amount}, animTime(elem)); + this.animate({turtleRotation: '+=' + cssNum(amount || 0) + 'deg'}, + animTime(elem)); }); - }, - lt: function(amount) { + }), + lt: wraphelp( + ["lt(degrees) Left turn. Pivots counterclockwise by some degrees: " + + "lt 90"], + function lt(amount) { return this.direct(function(j, elem) { - this.animate({turtleRotation: '-=' + amount}, animTime(elem)); + this.animate({turtleRotation: '-=' + cssNum(amount || 0) + 'deg'}, + animTime(elem)); }); - }, - fd: function(amount) { + }), + fd: wraphelp( + ["fd(pixels) Forward. Moves ahead by some pixels: " + + "fd 100"], + function fd(amount) { var elem, q, doqueue; if (this.length == 1 && !$.fx.speeds.turtle && animTime(elem = this[0]) == 'turtle') { q = $.queue(elem); doqueue = (q.length > 0); function domove() { + fixOriginIfWatching(elem); doQuickMove(elem, amount, 0); if (doqueue) { $.dequeue(elem); } } @@ -1819,38 +2255,102 @@ var turtlefn = { return this; } return this.direct(function(j, elem) { - this.animate({turtleForward: '+=' + amount}, animTime(elem)); + fixOriginIfWatching(elem); + this.animate({turtleForward: '+=' + cssNum(amount || 0) + 'px'}, + animTime(elem)); }); - }, - bk: function(amount) { + }), + bk: wraphelp( + ["bk(pixels) Back. Moves in reverse by some pixels: " + + "bk 100"], + function bk(amount) { return this.fd(-amount); - }, - move: function(amount, y) { - var sideways = 0; - if (y !== undefined) { - sideways = amount; - amount = y; - } + }), + slide: wraphelp( + ["slide(x, y) Slides right x and forward y pixels without turning: " + + "slide 50, 100"], + function slide(x, y) { + if (!y) { y = 0; } + if (!x) { x = 0; } return this.direct(function(j, elem) { this.animate({turtlePosition: - displacedPosition(elem, amount, sideways)}, animTime(elem)); + displacedPosition(elem, y, x)}, animTime(elem)); }); - }, - moveto: function(position, limit, y) { - if ($.isNumeric(position) && $.isNumeric(limit)) { - position = { pageX: parseFloat(position), pageY: parseFloat(limit) }; - limit = null; + }), + rarc: wraphelp( + ["rarc(radius, degrees) Right arc. " + + "Curves right some degrees, with a radius: " + + "rarc 100, 45"], + function rarc(radius, amount) { + if (!radius || !amount) { + return this.rt(amount); + } + return this.direct(function(j, elem) { + var oldRadius = this.css('turtleTurningRadius'); + this.css({turtleTurningRadius: (amount < 0) ? -radius : radius}); + this.animate({turtleRotation: '+=' + cssNum(amount) + 'deg'}, + animTime(elem)); + this.direct(function() { + this.css({turtleTurningRadius: oldRadius}); + }); + }); + }), + larc: wraphelp( + ["larc(radius, degrees) Left arc. " + + "Curves left some degrees, with a radius: " + + "larc 100, 45"], + function larc(radius, amount) { + if (!radius || !amount) { + return this.lt(amount); } - var localx = 0, localy = 0; - if ($.isNumeric(y) && $.isNumeric(limit)) { - localx = limit; - localy = y; + return this.direct(function(j, elem) { + var oldRadius = this.css('turtleTurningRadius'); + this.css({turtleTurningRadius: (amount < 0) ? -radius : radius}); + this.animate({turtleRotation: '-=' + cssNum(amount) + 'deg'}, + animTime(elem)); + this.direct(function() { + this.css({turtleTurningRadius: oldRadius}); + }); + }); + }), + moveto: wraphelp( + ["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"], + function moveto(x, y) { + var position = x, localx = 0, localy = 0, limit = null; + if ($.isNumeric(position) && $.isNumeric(y)) { + // moveto x, y: use local coordinates. + localx = parseFloat(position); + localy = parseFloat(y); + position = null; limit = null; + } else if ($.isArray(position)) { + // moveto [x, y], limit: use local coordinates (limit optional). + localx = position[0]; + localy = position[1]; + position = null; + limit = y; + } else if ($.isNumeric(y)) { + // moveto obj, limit: limited motion in the direction of obj. + limit = y; } + // Otherwise moveto {pos}, limit: absolute motion with optional limit. return this.direct(function(j, elem) { var pos = position; - if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } - if (!pos || !isPageCoordinate(pos)) return this; + if (pos === null) { + pos = $(homeContainer(elem)).pagexy(); + } + if (pos && !isPageCoordinate(pos)) { + try { + pos = $(pos).pagexy(); + } catch (e) { + return; + } + } + if (!pos || !isPageCoordinate(pos)) return; if ($.isWindow(elem)) { scrollWindowToDocumentPosition(pos, limit); return; @@ -1861,35 +2361,82 @@ var turtlefn = { computeTargetAsTurtlePosition(elem, pos, limit, localx, localy)}, animTime(elem)); }); - }, - turnto: function(bearing, limit) { + }), + turnto: wraphelp( + ["turnto(degrees) Turn to a bearing. " + + "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 turnto(bearing, y) { + if ($.isNumeric(y) && $.isNumeric(bearing)) { + // turnto x, y: convert to turnto [x, y]. + bearing = [bearing, y]; + y = null; + } return this.direct(function(j, elem) { if ($.isWindow(elem) || elem.nodeType === 9) return; - var dir = bearing; - if (!$.isNumeric(bearing)) { - var pos = bearing, cur = $(elem).origin(); - if (pos && !isPageCoordinate(pos)) { pos = $(pos).origin(); } - if (!pos || !isPageCoordinate(pos)) return; - dir = radiansToDegrees( - Math.atan2(pos.pageX - cur.pageX, cur.pageY - pos.pageY)); - } - this.animate({turtleRotation: - computeDirectionAsTurtleRotation(elem, dir, limit)}, animTime(elem)); + // turnto bearing: just use the given absolute. + var limit = null, ts, r, + targetpos = null, nlocalxy = null; + if ($.isNumeric(bearing)) { + r = convertToRadians(bearing); + fixOriginIfWatching(elem); + targetpos = getCenterInPageCoordinates(elem); + targetpos.pageX += Math.sin(r) * 1024; + targetpos.pageY -= Math.cos(r) * 1024; + limit = y; + } else if ($.isArray(bearing)) { + nlocalxy = computePositionAsLocalOffset(elem); + nlocalxy[0] -= bearing[0]; + nlocalxy[1] -= bearing[1]; + } else if (isPageCoordinate(bearing)) { + targetpos = bearing; + } else { + try { + targetpos = $(bearing).pagexy(); + } catch(e) { + return; + } + } + if (!nlocalxy) { + nlocalxy = computePositionAsLocalOffset(elem, targetpos); + } + dir = radiansToDegrees(Math.atan2(-nlocalxy[0], -nlocalxy[1])); + if (!(limit === null)) { + ts = readTurtleTransform(elem, true); + r = convertToRadians(ts.rot); + dir = limitRotation(ts.rot, dir, limit); + } + this.animate({turtleRotation: dir}, animTime(elem)); }); - }, - home: function() { + }), + home: wraphelp( + ["home() Goes home. " + + "Jumps to the center without drawing: home()"], + function home(container) { return this.direct(function(j, elem) { - var down = this.css('turtlePenDown'); - this.css({turtlePenDown: 'up' }); + var down = this.css('turtlePenDown'), + radius = this.css('turtleTurningRadius'), + hc = container || homeContainer(elem); + this.css({turtlePenDown: 'up', turtleTurningRadius: 0 }); this.css({ turtlePosition: - computeTargetAsTurtlePosition(elem, $(document).origin(), null, 0, 0), + computeTargetAsTurtlePosition( + elem, $(hc).pagexy(), null, 0, 0), turtleRotation: 0}); - this.css({turtlePenDown: down }); + this.css({turtlePenDown: down, turtleTurningRadius: radius }); }); - }, - pen: function(penstyle) { + }), + pen: wraphelp( + ["pen(color) Selects a pen. " + + "Chooses a color and style for the pen: pen 'red'."], + function pen(penstyle) { return this.direct(function(j, elem) { + if (penstyle === undefined) { + penstyle = 'black'; + } if (penstyle === false || penstyle === true || penstyle == 'down' || penstyle == 'up') { this.css('turtlePenDown', penstyle); @@ -1897,15 +2444,23 @@ var turtlefn = { this.css('turtlePenStyle', penstyle); } }); - }, - fill: function(style) { + }), + fill: wraphelp( + ["fill(color) Fills a path traced using " + + "pen 'path': " + + "pen 'path'; rarc 100, 90; fill 'blue'"], + function fill(style) { if (!style) { style = 'black'; } var ps = parsePenStyle(style, 'fillStyle'); return this.direct(function(j, elem) { endAndFillPenPath(elem, ps); }); - }, - dot: function(style, diameter) { + }), + dot: wraphelp( + ["dot(color, diameter) Draws a dot. " + + "Color and diameter are optional: " + + "dot 'blue'"], + function dot(style, diameter) { if ($.isNumeric(style)) { // Allow for parameters in either order. var t = style; @@ -1916,58 +2471,112 @@ var turtlefn = { if (!style) { style = 'black'; } var ps = parsePenStyle(style, 'fillStyle'); return this.direct(function(j, elem) { - var c = this.origin(), - ts = readTurtleTransform(elem, true); + var c = this.pagexy(), + ts = readTurtleTransform(elem, true), + extraDiam = (ps.eraseMode ? 2 : 0); // Scale by sx. (TODO: consider parent transforms.) - fillDot(c, diameter * ts.sx, ps); + fillDot(c, diameter * ts.sx + extraDiam, ps); // Once drawing begins, origin must be stable. watchImageToFixOriginOnLoad(elem); }); - }, - erase: function(style) { - if (!style) { style = 'transparent'; } - var ps = parsePenStyle(style, 'fillStyle'); - return this.direct(function(j, elem) { - eraseBox(elem, ps); - // Once drawing begins, origin must be stable. - watchImageToFixOriginOnLoad(elem); - }); - }, - play: function(notes) { + }), + wait: wraphelp( + ["wait(seconds) Waits some seconds before proceeding. " + + "fd 100; wait 2.5; bk 100"], + function wait(seconds) { + return this.delay(seconds * 1000); + }), + st: wraphelp( + ["st() Show turtle. The reverse of " + + "ht(). st()"], + function st() { + return this.direct(function() { this.show(); }); + }), + ht: wraphelp( + ["ht() Hide turtle. The turtle can be shown again with " + + "st(). ht()"], + function ht() { + return this.direct(function() { this.hide(); }); + }), + pu: wraphelp( + ["pu() Pen up. Tracing can be resumed with " + + "pd(). pu()"], + function pu() { + return this.pen(false); + }), + pd: wraphelp( + ["pd() Pen down. Resumes tracing a path that was paused with " + + "pu(). pd()"], + function pd() { + return this.pen(true); + }), + pe: wraphelp( + ["pe() Pen erase. Can overtrace old " + + "lines to erase them. pen 'red'; fd 100; pe(); bk 100"], + function pe() { + return this.pen('erase'); + }), + play: wraphelp( + ["play(notes) Play notes. Notes are specified in " + + "ABC notation. " + + "play \"de[dBFA]2[cGEC]4\""], + function play(notes) { var args = arguments; return this.queue(function() { // playABC will call $(this).dequeue() when song is done. playABC(this, args); }); - }, - speed: function(mps) { + }), + speed: wraphelp( + ["speed(persec) Set turtle speed in moves per second: " + + "speed Infinity"], + function speed(mps) { return this.direct(function(j, elem) { this.css('turtleSpeed', mps); }); - }, - img: function (name) { + }), + wear: wraphelp( + ["wear(color) Sets the turtle shell color: " + + "wear 'turquoise'", + "wear(url) Sets the turtle image url: " + + "wear 'http://bit.ly/1bgrQ0p'"], + function wear(name) { var img = nameToImg(name); if (!img) return this; - return this.direct(function() { + return this.direct(function(j, elem) { + // Bug workaround - if backgroudnImg isn't cleared early enough, + // the turtle image doesn't update. (Even though this is done + // later in applyImg.) + this.css({ + backgroundImage: 'none', + }); + // Keep the position of the origin unchanged even if the image resizes. + watchImageToFixOriginOnLoad(elem); applyImg(this, img); + fixOriginIfWatching(elem); }); - }, - mark: function(html, fn) { + }), + label: wraphelp( + ["label(text) Labels the current position with HTML: " + + "label 'remember'"], + function label(html, fn) { return this.direct(function() { - var out = output(html, 'mark').css({ + var out = output(html, 'label').css({ position: 'absolute', - display: 'inline-block' - }).addClass('turtle'); + display: 'inline-block', + top: 0, + left: 0 + }).addClass('turtle').appendTo(getTurtleClipSurface()); out.css({ turtlePosition: computeTargetAsTurtlePosition( - out.get(0), this.origin(), null, 0, 0) + out.get(0), this.pagexy(), null, 0, 0) }); if ($.isFunction(fn)) { out.direct(fn); } }); - }, - reload: function() { + }), + reload: function reload() { // Used to reload images to cycle animated gifs. return this.direct(function(j, elem) { if ($.isWindow(elem) || elem.nodeType === 9) { @@ -1981,33 +2590,90 @@ var turtlefn = { } }); }, - origin: function() { + hatch: wraphelp( + ["hatch(count, color) Hatches any number of new turtles. Optional " + + "color name. g = hatch 5; g.direct -> @fd random 500"], + function(count, spec) { + if (!this.length) return; + if (spec === undefined && !$.isNumeric(count)) { + spec = count; + count = 1; + } + // Determine the container in which to hatch the turtle. + var container = this[0], clone = null; + if ($.isWindow(container) || container.nodeType === 9) { + container = getTurtleClipSurface(); + } else if (/^(?:br|img|input|hr)$/i.test(container.tagName)) { + container = container.parentElement; + clone = this[0]; + } + // Create the turtle(s) + if (count === 1) { + // Pass through identical jquery instance in the 1 case. + return hatchone( + typeof spec === 'function' ? spec(0) : spec, container, clone); + } else { + var k = 0, result = []; + for (; k < count; ++k) { + result.push(hatchone( + typeof spec === 'function' ? spec(k) : spec, container, clone)[0]); + } + return $(result); + } + }), + pagexy: wraphelp( + ["pagexy() Page coordinates as obj, with " + + "top-left based obj.pageX, obj.pageY: " + + "c = pagexy(); fd 500; moveto c"], + function pagexy() { if (!this.length) return; + fixOriginIfWatching(this[0]); return getCenterInPageCoordinates(this[0]); - }, - bearing: function(pos, y) { + }), + getxy: wraphelp( + ["getxy() Returns graphing coordinates [x, y], center-based: " + + "v = getxy(); slide -v[0], -v[1]"], + function getxy() { + if (!this.length) return; + return computePositionAsLocalOffset(this[0]); + }), + bearing: wraphelp( + ["bearing() Returns turtle bearing. North is 0; East is 90: " + + "write bearing()", + "bearing(obj) bearing(x, y) Returns the direction " + + "from the turtle towards an object or coordinate: " + + "write bearing(lastmouseclick)"], + function bearing(x, y) { if (!this.length) return; - var elem = this[0], dir, cur; + var elem = this[0], pos = x, dir, cur; if (pos !== undefined) { - cur = $(elem).origin(); - if ($.isNumeric(y) && $.isNumeric(x)) { pos = { pageX: pos, pageY: y }; } - else if (!isPageCoordinate(pos)) { pos = $(pos).origin(); } + cur = $(elem).pagexy(); + if ($.isNumeric(y) && $.isNumeric(x)) { pos = [x, y]; } + if ($.isArray(pos)) { + pos = convertLocalXyToPageCoordinates(elem, [pos])[0]; + } + if (!isPageCoordinate(pos)) { pos = $(pos).pagexy(); } return radiansToDegrees( Math.atan2(pos.pageX - cur.pageX, cur.pageY - pos.pageY)); } if ($.isWindow(elem) || elem.nodeType === 9) return 0; return getDirectionOnPage(elem); - }, - distance: function(pos, y) { + }), + distance: wraphelp( + ["distance(obj) Returns the distance from the turtle to " + + "another object: write distance(lastmouseclick)", + "distance(x, y) Returns the distance from the turtle to " + + "graphing coorindates: write distance(100, 0)"], + function distance(pos, y) { if (!this.length) return; - var elem = this[0], dx, dy, cur = $(elem).origin(); + var elem = this[0], dx, dy, cur = $(elem).pagexy(); if ($.isNumeric(y) && $.isNumeric(x)) { pos = { pageX: pos, pageY: y }; } - else if (!isPageCoordinate(pos)) { pos = $(pos).origin(); } + else if (!isPageCoordinate(pos)) { pos = $(pos).pagexy(); } dx = pos.pageX - cur.pageX; dy = pos.pageY - cur.pageY; return Math.sqrt(dx * dx + dy * dy); - }, - mirror: function(val) { + }), + mirror: function mirror(val) { if (val === undefined) { // Zero arguments returns true if mirrored. var c = $.map(this.css('turtleScale').split(' '), parseFloat), @@ -2023,7 +2689,11 @@ var turtlefn = { } }); }, - twist: function(val) { + twist: wraphelp( + ["twist(degrees) Set the primary direction of the turtle. Allows " + + "use of images that face a different direction than 'up': " + + "twist(90)"], + function twist(val) { if (val === undefined) { return parseFloat(this.css('turtleTwist')); } @@ -2031,8 +2701,11 @@ var turtlefn = { if ($.isWindow(elem) || elem.nodeType === 9) return; this.css('turtleTwist', val); }); - }, - scale: function(valx, valy) { + }), + scale: wraphelp( + ["scale(factor) Scales all motion up or down by a factor. " + + "To double all drawing: scale(2)"], + function scale(valx, valy) { if (valy === undefined) { valy = valx; } // Disallow scaling to zero using this method. if (!valx || !valy) { return this; } @@ -2044,20 +2717,33 @@ var turtlefn = { c[1] *= valy; this.css('turtleScale', $.map(c, cssNum).join(' ')); }); - }, - cell: function(x, y) { + }), + cell: wraphelp( + ["cell(r, c) Cell in 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 cell(r, c) { var sel = this.find( - $.isNumeric(y) ? 'tr:nth-of-type(' + (y + 1) + ')' : 'tr'); + $.isNumeric(r) ? 'tr:nth-of-type(' + (r + 1) + ')' : 'tr'); return sel.find( - $.isNumeric(x) ? 'td:nth-of-type(' + (x + 1) + ')' : 'td'); - }, - shown: function() { + $.isNumeric(c) ? 'td:nth-of-type(' + (c + 1) + ')' : 'td'); + }), + shown: wraphelp( + ["shown() True if turtle is shown, false if hidden: " + + "ht(); write shown()"], + function shown() { return this.is(':visible'); - }, - hidden: function() { + }), + hidden: wraphelp( + ["hidden() True if turtle is hidden: " + + "ht(); write hidden()"], + function hidden() { return this.is(':hidden'); - }, - encloses: function(arg, y) { + }), + encloses: wraphelp( + ["encloses(obj) True if the first element fully encloses obj: " + + "write $(window).encloses(turtle)"], + function encloses(arg, y) { if (!this.length || this.hidden()) return false; if ($.isNumeric(arg) && $.isNumeric(y)) { arg = [{ pageX: arg, pageY: y }]; @@ -2091,11 +2777,18 @@ var turtlefn = { } } return !!allok; - }, - touches: function(arg, y) { + }), + touches: wraphelp( + ["touches(obj) True if the first element touches obj: " + + "write turtle1.touches(turtle2)"], + function touches(arg, y) { if (this.hidden() || !this.length) { return false; } if ($.isNumeric(arg) && $.isNumeric(y)) { - arg = [{ pageX: arg, pageY: y }]; + arg = [arg, y]; + } + if ($.isArray(arg) && arg.length == 2 && + $.isNumeric(arg[0]) && $.isNumeric(arg[1])) { + arg = convertLocalXyToPageCoordinates(this[0] || document.body, [arg])[0]; } if (!arg) return false; if (typeof arg === 'string') { arg = $(arg); } @@ -2121,14 +2814,14 @@ var turtlefn = { } } return !!anyok; - }, - within: function(distance, x, y) { + }), + within: function within(distance, x, y) { return withinOrNot(this, true, distance, x, y); }, - notwithin: function(distance, x, y) { + notwithin: function notwithin(distance, x, y) { return withinOrNot(this, false, distance, x, y); }, - direct: function(qname, callback, args) { + direct: function direct(qname, callback, args) { if ($.isFunction(qname)) { args = callback; callback = qname; @@ -2174,7 +2867,6 @@ var turtlefn = { $.fn.extend(turtlefn); - ////////////////////////////////////////////////////////////////////////// // TURTLE GLOBAL ENVIRONMENT // Implements educational support when $.turtle() is called: @@ -2188,7 +2880,7 @@ $.fn.extend(turtlefn); // * Sets up a global "hatch" function to make a new turtle. ////////////////////////////////////////////////////////////////////////// -var turtleGIFUrl = "data:image/gif;base64,R0lGODlhKAAvAPIHAAFsOACSRQ2ZRQySQzCuSBygRQ+DPv///yH5BAlkAAcAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAKAAvAAAD/ni63P4wygVqnVjWQnoBWdgAXdmBYkiaJZpiK0u4ryafNUwYw0AUHFruARgEjkiBcOgAAJ+FwXJSMcwglqwlFcMxskZkIbDNAKwmlOUoQB4JyDK1a7AMxm4k3K3NNlkVRwVteQF4bnVnJR9/J0VihQKHeU4mjCMzhYN5m5EfgE2BeQJ7eoUBkm10RKeGeKQEhGKHfaynpIMCkrF6kxcRRbJuk3o/HcJkGndAsqSnHW/Iv7aoHEDQhaVAeXXA2YvIpYaFUwdnz4S4gxy6b+RYBs+ci0+wUJdNrcSubri6AgMAlhPVT1w0NwbjeBvmoWCehAG6YWFzTBcvNsT2RSxnfM5atlkO3y28BQcWw30cFQBoBYseM5NxtBBZqUkWB4Pbjji5OYVgEmIXHVYqYYBIpmHIOhWqAwoTASlJkKGSSqbLjCUxqjjzRK7PNAqWqrQKYPCrjRYqaWqKKaILPnNrIm40C8OAgQ8cZTIx42Wvjrd+gUkMrIEu4cMLEgAAIfkECWQABwAsAAAAACgALwCCAm04AJJFDZlFDJJDL65IHKBGDIM+////A/54utz+MMoFgKkzy1qIL4AmNoBneuEolqeZqhnbEi+8zagdE8YwEIVOTfewBI5IwZDoAASfBSUzUqlalwcnCgup9pCBQqDKqJy4pAoYTECSzefmtSIQr492N9wld6nDAndhglo5TWcAgXh3dYIXQkuFNHdRa5WMIBiHHwCCbWyKYHUCF10Wf5R2Ah6heHloCqhrqwK1dUBIuHobA61Il2wnvrAAA0+hq4JBRwS1YJpFSR1BHp5JvqUQBncnwMzSd1yyuYG1QHUdzoNr4p3coh0f1KtAUO3KqaLntrXigslrmrERNIZKq3h5AgDMRRCNO3q2BB5pBCbhri7T3rlC9naJ3QaCCtusSpjRYxorBXzMagHFXMcxkajRcGcpVDyFv14V6WYEXkBfIZVAoxCPU82jggY4wWIB0TVGQGEakjMnZFKLUvms6EXwJUwZPFRU8aRIU1OtI6p+HQIW1oQ5RZykdPvWg4EpaYHQxZtlKV8NZP4KZpAAADs="; +var turtleGIFUrl = "data:image/gif;base64,R0lGODlhKAAwAPEDAAFsOACSRTCuSAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJZAADACwAAAAAKAAwAAACzpyPqcvtByJ49EWBRaw8gZxNXfeB4ciVpoZWqim2zhfUNivP9h7EOQPg9VqSDVDocwUyQ8UFlrS8mobIciXoRRtBULGLBWm/EudVHA6fxVFw+v2mQtbwundhteuz2yp9z/cVMAPIhvIC2EdYiKHIxdhIBIkzgrjnCDSJiacpCbnp1HkoWklKYqo0KUfhxjhWBmQ5ibFaJTsbGYob1nb2+kdbVLNS++Lz5JVEBguhEmQW/GOcSUl09sxZffj1qP2zCPo9QBMuXVMubSS+/lAAACH5BAVkAAMALAEAAQAmAC4AAALNnI9pwKAP4wKiCiZzpLY6DR5c54XhSH5mhnbqugnBTF8wS+fBez+AvuvhdDxEA3NqXYqDnyXIcpIqu5fU8zlqr9OntgPlPrtk2TQcKKvXMpWSDYcu0vB6NVE90uskOY6fsvIGxxQDaFEIMciW6HOIKPhYYrK41qhQqXaZkFm2aSRpQxn6KUIaKVnatHfoZ6TF2sokFopY1PmIZFrryRkrk0dLpef1usXDMKXb5CIk5TqwY+s8idncw1EoPYxdjanVLSqk4aTqPGOOvaxRAAA7"; var eventfn = { click:1, mouseup:1, mousedown:1, mousemove:1, keydown:1, keypress:1, keyup:1 }; @@ -2197,17 +2889,80 @@ var global_turtle = null; var global_turtle_methods = []; var attaching_ids = false; var dollar_turtle_methods = { - erase: function() { directIfGlobal(function() { $(document).erase() }); }, - tick: function(x, y) { directIfGlobal(function() { tick(x, y); }); }, - defaultspeed: function(mps) { - directIfGlobal(function() { defaultspeed(mps); }); }, - playnow: function() { playABC(null, arguments); }, - print: function(html) { return output(html, 'div'); }, - random: random, - hatch: hatch, - input: input, - button: button, - table: table, + cs: wraphelp( + ["cs() Clear screen. Erases both graphics canvas and " + + "body text: cs()"], + function cs() { directIfGlobal(function() { clearField() }); }), + cg: wraphelp( + ["cg() Clear graphics. Does not alter body text: " + + "cg()"], + function cg() { directIfGlobal(function() { clearField('canvas') }); }), + ct: wraphelp( + ["ct() Clear text. Does not alter graphics canvas: " + + "ct()"], + function ct() { directIfGlobal(function() { clearField('text') }); }), + tick: wraphelp( + ["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 tick(tps, fn) { + directIfGlobal(function() { globaltick(tps, fn); }); + }), + defaultspeed: wraphelp( + ["defaultspeed(mps) Sets default turtle speed for new turtles: " + + "defaultspeed 60"], + function defaultspeed(mps) { + directIfGlobal(function() { globaldefaultspeed(mps); }); }), + sound: function sound() { playABC(null, arguments); }, + write: wraphelp( + ["write(html) Writes text output. Arbitrary HTML may be written: " + + "write 'Hello, world!'"], + function write(html) { return output(html, 'div'); }), + read: wraphelp( + ["read(html, fn) Reads text or numeric input. " + + "Calls fn once with the entered value: " + + "read 'Your name?', (v) -> write 'Hello ' + v"], + function read(a, b) { return input(a, b, 0); }), + readnum: wraphelp( + ["readnum(html, fn) Reads numeric input. Only numbers allowed: " + + "read 'Amount?', (v) -> write 'Tip: ' + (0.15 * v)"], + function readnum(a, b) { return input(a, b, 1); }), + readstr: wraphelp( + ["readstr(html, fn) Reads text input. Never " + + "converts input to a number: " + + "read 'Enter code', (v) -> write v.length + ' characters'"], + function readstr(a, b) { return input(a, b, -1); }), + random: wraphelp( + ["random(n) Returns a random non-negative integer less than n: " + + "write random 10", + "random(list) Returns a random member of the list: " + + "write random ['a', 'b', 'c']", + "random('position') Returns a random page position: " + + "moveto random 'position'", + "random('color') Returns a random page color: " + + "pen random 'color'"], + random), + hatch: wraphelp( + ["hatch(count, color) Hatches any number of new turtles. Optional " + + "color name. g = hatch 5; g.direct -> @fd random 500"], + function hatch(count, spec) { + if (global_turtle) return $(global_turtle).hatch(count, spec); + else return $(document).hatch(count, spec); + }), + button: wraphelp( + ["button(text, fn) Writes a button. Calls " + + "fn whenever the button is clicked: " + + "button 'GO', -> fd 100"], + button), + table: wraphelp( + ["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]]"], + table), + help: globalhelp }; $.turtle = function turtle(id, options) { @@ -2238,10 +2993,6 @@ $.turtle = function turtle(id, options) { if (!options.hasOwnProperty('events') || options.events) { turtleevents(options.eventprefix); } - // Set up window-scoped event handler methods too. - if (!options.hasOwnProperty('handlers') || options.handlers) { - globalizeMethods($(window), eventfn); - } // Set up global objects by id. if (!options.hasOwnProperty('ids') || options.ids) { turtleids(options.idprefix); @@ -2261,7 +3012,7 @@ $.turtle = function turtle(id, options) { $.extend(window, dollar_turtle_methods); } // Set default turtle speed - defaultspeed(options.hasOwnProperty('defaultspeed') ? + globaldefaultspeed(options.hasOwnProperty('defaultspeed') ? options.defaultspeed : 1); // Initialize audio context (avoids delay in first notes). try { @@ -2272,7 +3023,7 @@ $.turtle = function turtle(id, options) { if (id) { selector = $('#' + id); if (!selector.length) { - selector = hatch(id); + selector = dollar_turtle_methods.hatch(id); } } if (selector && !selector.length) { selector = null; } @@ -2280,9 +3031,9 @@ $.turtle = function turtle(id, options) { if (selector && selector.length === 1 && (!options.hasOwnProperty('global') || options.global)) { var extraturtlefn = { - show:1, hide:1, css:1, fadeIn:1, fadeOut:1, fadeTo:1, fadeToggle:1, - animate:1, delay:1, stop:1, finish:1, toggle:1, remove:1 }; - var globalfn = $.extend({}, turtlefn, extraturtlefn); + css:1, fadeIn:1, fadeOut:1, fadeTo:1, fadeToggle:1, + animate:1, stop:1, toggle:1, finish:1, remove:1 }; + var globalfn = $.extend({}, turtlefn, eventfn, extraturtlefn); global_turtle_methods.push.apply(global_turtle_methods, globalizeMethods(selector, globalfn)); global_turtle = selector[0]; @@ -2292,8 +3043,9 @@ $.turtle = function turtle(id, options) { if (!options.hasOwnProperty('panel') || options.panel) { var retval = null, seeopt = { - title: 'turtle test panel', - abbreviate: [undefined] + title: 'turtle test panel - Enter commands or type help for help', + abbreviate: [undefined], + consolehook: seehelphook }; if (selector) { seeopt.abbreviate.push(selector); } if (options.title) { @@ -2316,15 +3068,43 @@ $.turtle = function turtle(id, options) { $.extend($.turtle, dollar_turtle_methods); +function seehelphook(text, result) { + if (typeof result == 'function' && /^\w+\s*$/.test(text) && result.helptext) { + globalhelp(result); + return true; + } + return false; +} + +function copyhelp(method, fname, extrahelp, globalfn) { + if (method.helptext) { + globalfn.helptext = method.helptext; + } else if (fname in extrahelp) { + globalfn.helptext = extrahelp[fname]; + } + return globalfn; +} + +var extrahelp = { + remove: ["remove() Removes main turtle completely. " + + "Also removes fd, bk, rt, etc: " + + "remove()"], + finish: ["finish() Finishes turtle animation. " + + "Does not pause for effect: " + + "finish()"] +}; + function globalizeMethods(thisobj, fnames) { var replaced = []; for (var fname in fnames) { if (fnames.hasOwnProperty(fname) && !(fname in window)) { replaced.push(fname); - window[fname] = (function() { + window[fname] = (function(fname) { var method = thisobj[fname], target = thisobj; - return (function() { return method.apply(target, arguments); }); - })(); + return copyhelp(method, fname, extrahelp, + (function() { /* Use parentheses to call a function */ + return method.apply(target, arguments); })); + })(fname); } } return replaced; @@ -2359,12 +3139,67 @@ function onDOMNodeRemoved(e) { } function isCSSColor(color) { - if (!/^[a-z]+$/i.exec(color)) { return false; } + if (!/^[a-z]+$|^(?:rgb|hsl)a?\([^)]*\)$|^\#[a-f0-9]{3}(?:[a-f0-9]{3})?$/i + .exec(color)) { + return false; + } var d = document.createElement('div'), unset = d.style.color; d.style.color = color; return (unset != d.style.color); } +function createTurtleShellOfColor(color) { + var c = document.createElement('canvas'); + c.width = 40; + c.height = 48; + var ctx = c.getContext('2d'), + cx = 20, + cy = 26; + ctx.beginPath(); + ctx.arc(cx, cy, 16, 0, 2 * Math.PI, false); + ctx.closePath(); + ctx.fillStyle = color; + ctx.fill(); + ctx.beginPath(); + // Half of a symmetric turtle shell pattern. + var pattern = [ + [[5, -14], [3, -11]], + [[3, -11], [7, -8], [4, -4]], + [[4, -4], [7, 0], [4, 4]], + [[4, 4], [7, 8], [3, 11]], + [[7, -8], [12, -9], null], + [[7, 0], [15, 0], null], + [[7, 8], [12, 9], null], + [[3, 11], [1, 15], null] + ]; + for (var j = 0; j < pattern.length; j++) { + var path = pattern[j], connect = true; + ctx.moveTo(cx + path[0][0], cy + path[0][1]); + for (var k = 1; k < path.length; k++) { + if (path[k] !== null) { + ctx.lineTo(cx + path[k][0], cy + path[k][1]); + } + } + for (var k = path.length - 1; k >= 0; k--) { + if (path[k] === null) { + k--; + ctx.moveTo(cx - path[k][0], cy + path[k][1]); + } else { + ctx.lineTo(cx - path[k][0], cy + path[k][1]); + } + } + } + ctx.lineWidth = 1.1; + ctx.strokeStyle = 'rgba(255,255,255,0.75)'; + ctx.stroke(); + ctx.beginPath(); + ctx.arc(cx, cy, 15.5, 0, 2 * Math.PI, false); + ctx.closePath(); + ctx.strokeStyle = 'rgba(0,0,0,0.4)'; + ctx.stroke(); + return c.toDataURL(); +} + function createPointerOfColor(color) { var c = document.createElement('canvas'); c.width = 40; @@ -2385,50 +3220,25 @@ var entityMap = { "&": "&", "<": "<", ">": ">", - '"': '"', + '"': '"' }; function escapeHtml(string) { return String(string).replace(/[&<>"]/g, function(s) {return entityMap[s];}); } -// Turtle creation function. -function hatch(count, spec) { - if (spec === undefined && !$.isNumeric(count)) { - spec = count; - count = 1; - } - if (count === 1) { - // Pass through identical jquery instance in the 1 case. - return hatchone(typeof spec === 'function' ? spec(0) : spec); - } else { - var j = 0, result = []; - for (; j < count; ++j) { - result.push(hatchone(typeof spec === 'function' ? spec(j) : spec)[0]); - } - return $(result); - } -} - function nameToImg(name) { - if (name == 'turtle') return { - url: turtleGIFUrl, - css: { - width: 20, - height: 24, - turtleHull: "-8 -5 -8 6 0 -13 8 6 8 -5 0 9", - transformOrigin: '10px 13px', - opacity: 0.5 - } - }; + if (name == 'turtle') { name = 'mediumseagreen'; } if (isCSSColor(name)) return { - url: createPointerOfColor(name), + url: createTurtleShellOfColor(name), css: { width: 20, height: 24, - turtleHull: "-10 11 0 -13 10 11", + turtleHull: "-8 -5 -8 6 0 -13 8 6 8 -5 0 9", transformOrigin: '10px 13px', - opacity: 0.8 + opacity: 0.5, + backgroundImage: 'url(' + turtleGIFUrl + ')', + backgroundSize: 'contain' } }; var openicon = @@ -2461,14 +3271,16 @@ function nameToImg(name) { css: { width: targetSize, height: targetSize, + transformOrigin: '50% 50%', opacity: 1 } } } - if (/^(?:https?:\/)?\//i.exec(name)) { + if (/^(?:(?:https?|data):)?\//i.exec(name)) { return { url: name, css: { + transformOrigin: '50% 50%', opacity: 1 } } @@ -2476,7 +3288,7 @@ function nameToImg(name) { return null; } -function hatchone(name) { +function hatchone(name, container, clonepos) { var isID = name && /^[a-zA-Z]\w*$/.exec(name), isTag = name && /^<.*>$/.exec(name), img = nameToImg(name) || @@ -2495,12 +3307,29 @@ function hatchone(name) { } else { result = $('
    ' + escapeHtml(name) + '
    '); } + // Position the turtle inside the container. result.css({ - 'position': 'absolute', - 'display': 'inline-block', - 'top': 0, - 'left': 0 - }).appendTo(getTurtleClipSurface()).home(); + position: 'absolute', + display: 'inline-block', + top: 0, + left: 0 + }); + if (!container || container.nodeType == 9 || $.isWindow(container)) { + container = getTurtleClipSurface(); + } + result.appendTo(container); + + // Move it to the starting pos. + if (clonepos) { + var t = $.style(clonepos, 'transform'); + if (t) { + result.css({transform: $.style(clonepos, 'transform')}); + } else { + result.home(clonepos); + } + } else { + result.home(container); + } // Every hatched turtle has class="turtle". result.addClass('turtle'); @@ -2552,7 +3381,7 @@ function random(arg) { // Simplify setInterval(fn, 1000) to just tick(fn). var tickinterval = null; -function tick(rps, fn) { +function globaltick(rps, fn) { if (fn === undefined && $.isFunction(rps)) { fn = rps; rps = 1; @@ -2567,7 +3396,7 @@ function tick(rps, fn) { } // Allow speed to be set in moves per second. -function defaultspeed(mps) { +function globaldefaultspeed(mps) { if (mps === undefined) { return 1000 / $.fx.speeds.turtle; } else { @@ -2614,7 +3443,8 @@ function turtleevents(prefix) { // Simplify $('body').append(html). function output(html, defaulttag) { if (html === undefined || html === null) { - return $('').img('turtle').appendTo('body'); + // Print a turtle shell when no arguments. + return $('').wear('turtle').css({background: 'none'}).appendTo('body'); } var wrapped = false, result = null; html = '' + html; @@ -2623,12 +3453,17 @@ function output(html, defaulttag) { // to trust a surrounding tag but found multiple bits. if (html.charAt(0) != '<' || html.charAt(html.length - 1) != '>' || (result !== null && result.length != 1)) { - html = '<' + defaulttag + '>' + html + ''; + html = '<' + defaulttag + ' style="display:inline-block">' + + html + ''; wrapped = true; } result = $(html); } - return result.appendTo('body'); + result.appendTo('body'); + if (wrapped && defaulttag == 'div') { + result.after('
    '); + } + return result; } // Simplify $('body'>.append('').click(fn). @@ -2650,8 +3485,8 @@ function button(name, callback) { // Simplify $('body').append('' + label) and onchange hookup. -function input(name, callback) { - if ($.isFunction(name) && callback === undefined) { +function input(name, callback, numeric) { + if ($.isFunction(name) && !callback) { callback = name; name = null; } @@ -2670,34 +3505,78 @@ function input(name, callback) { } } function newval() { + if (!validate()) { return false; } var val = textbox.val(); if (debounce && lastseen == val) { return; } dodebounce(); lastseen = val; textbox.remove(); label.append(val); - if ($.isNumeric(val)) { + if (numeric > 0 || ( + numeric >= 0 && $.isNumeric(val) && ('' + parseFloat(val) == val))) { val = parseFloat(val); } if (callback) { callback.call(thisval, val); } } + function validate() { + if (!numeric) return true; + var val = textbox.val(), + nval = val.replace(/[^0-9\.]/g, ''); + if (val != nval || !$.isNumeric(nval)) { + textbox.val(nval); + return false; + } + return true; + } function key(e) { - if (e.which == 13) { newval(); } + if (e.which == 13) { + if (!validate()) { return false; } + newval(); + } + if (numeric > 0 && (e.which >= 32 && e.which <= 127) && + (e.which < '0'.charCodeAt(0) || e.which > '9'.charCodeAt(0))) { + return false; + } } dodebounce(); - textbox.on('keydown', key); + textbox.on('keypress keydown', key); textbox.on('change', newval); $('body').append(label); textbox.focus(); return thisval; } -function table(width, height, cellCss, tableCss) { +function table(height, width, cellCss, tableCss) { + var contents = null, row, col; + if ($.isArray(height)) { + tableCss = cellCss; + cellCss = width; + contents = height; + height = contents.length; + width = 0; + for (row = 0; row < height; row++) { + if ($.isArray(contents[row])) { + width = Math.max(width, contents[row].length); + } else { + width = Math.max(width, 1); + } + } + } var html = ['']; - for (var row = 0; row < height; row++) { + for (row = 0; row < height; row++) { html.push(''); - for (var col = 0; col < width; col++) { - html.push(''); + for (col = 0; col < width; col++) { + if (contents) { + if ($.isArray(contents[row]) && col < contents[row].length) { + html.push(''); + } else if (!$.isArray(contents[row]) && col == 0) { + html.push(''); + } else { + html.push(''); + } + } else { + html.push(''); + } } html.push(''); } @@ -2713,8 +3592,8 @@ function table(width, height, cellCss, tableCss) { margin: '0', padding: '0' }; - result.css($.extend({}, defaultCss, cellCss, - { width: 'auto', height: 'auto', maxWidth: 'auto'}, + result.css($.extend({}, defaultCss, + { width: 'auto', height: 'auto', maxWidth: 'auto', border: 'none'}, tableCss)); result.find('td').css($.extend({}, defaultCss, cellCss)); result.appendTo('body'); @@ -2728,14 +3607,29 @@ function table(width, height, cellCss, tableCss) { var ABCtoken = /\s+|\[|\]|>+|<+|(?:(?:\^\^|\^|__|_|=|)[A-Ga-g](?:,+|'+|))|\d*\/\d+|\d+|\/+|[xzXZ]|./g; var audioTop = null; +function isAudioPresent() { + return !!(window.audioContext || window.webkitAudioContext); +} function getAudioTop() { if (!audioTop) { - var ac = new (window.audioContext || window.webkitAudioContext), - dcn = ac.createDynamicsCompressor(); + var ac = new (window.AudioContext || window.webkitAudioContext), + dcn = ac.createDynamicsCompressor(), + firstTime = null; dcn.connect(ac.destination); audioTop = { ac: ac, - out: dcn + out: dcn, + // Partial workaround for http://crbug.com/254942: + // add little extra pauses before scheduling envelopes. + // A quarter second or so seems to be needed at initial startup, + // then 1/64 second before scheduling each envelope afterwards. + nextStartTime: function() { + if (firstTime === null) { + firstTime = ac.currentTime; + } + return Math.max(firstTime + 0.25, + ac.currentTime + 0.015625); + } } } return audioTop; @@ -2819,11 +3713,15 @@ function durationToTime(duration) { return n / d; } function playABC(elem, args) { + if (!isAudioPresent()) { + if (elem) { $(elem).dequeue(); } + return; + } var atop = getAudioTop(), - start_time = atop.ac.currentTime, end_time = start_time, - firstvoice = 0, voice, freqmult, beatsecs, + firstvoice = 0, argindex, voice, freqmult, beatsecs, volume = 0.5, tempo = 120, transpose = 0, type = ['square'], - envelope = {a: 0.01, d: 0.2, s: 0.1, r: 0.1}, + venv = {a: 0.01, d: 0.2, s: 0.1, r: 0.1}, envelope = [venv], + start_time = null, end_time = atop.ac.currentTime, notes, vtype, time, fingers, strength, i, g, t, atime, slast, rtime, stime, dt, opts; if ($.isPlainObject(args[0])) { @@ -2832,38 +3730,53 @@ function playABC(elem, args) { if ('tempo' in opts) { tempo = opts.tempo; } if ('transpose' in opts) { transpose = opts.transpose; } if ('type' in opts) { type = opts.type; } - if ('envelope' in opts) { $.extend(envelope, opts.envelope); } + if ('envelope' in opts) { + if ($.isArray(opts.envelope)) { + envelope = [] + for (i = 0; i < opts.envelope.length; i++) { + envelope.push($.extend({}, venv, opts.envelope[i])); + } + } else { + $.extend(venv, opts.envelope); + } + } firstvoice = 1; } - voice = firstvoice; beatsecs = 60 / tempo; - freqmult = Math.pow(2, transpose / 12); if (!$.isArray(type)) { type = [type]; } - for (; voice < args.length; voice++) { - notes = parseABCNotes(args[voice]); - vtype = type[(voice - firstvoice) % type.length] || 'square'; - time = start_time; + if (!$.isArray(volume)) { volume = [volume]; } + if (!$.isArray(transpose)) { transpose = [transpose]; } + for (argindex = firstvoice; argindex < args.length; argindex++) { + voice = argindex - firstvoice; + notes = parseABCNotes(args[argindex]); + vtype = type[voice % type.length] || 'square'; fingers = 0; for (i = 0; i < notes.length; i++) { fingers = Math.max(fingers, notes[i].frequency.length); } if (fingers == 0) { continue; } // Attenuate chorded voice so chorded power matches volume. - strength = volume / Math.sqrt(fingers); + strength = volume[voice % volume.length] / Math.sqrt(fingers); + venv = envelope[voice % envelope.length]; + freqmult = Math.pow(2, transpose[voice % transpose.length] / 12); + if (start_time === null) { + start_time = atop.nextStartTime(); + } + time = start_time; for (i = 0; i < notes.length; i++) { t = notes[i].time; if (notes[i].frequency.length > 0) { g = atop.ac.createGainNode(); stime = t * beatsecs + time; - atime = Math.min(t, envelope.a) * beatsecs + time; - rtime = Math.max(0, t + envelope.r) * beatsecs + time; + atime = Math.min(t, venv.a) * beatsecs + time; + rtime = Math.max(0, t + venv.r) * beatsecs + time; if (atime > rtime) { atime = rtime = (atime + rtime) / 2; } if (rtime < stime) { stime = rtime; rtime = t * beatsecs + time; } - dt = envelope.d * beatsecs; + dt = venv.d * beatsecs; g.gain.setValueAtTime(0, time); g.gain.linearRampToValueAtTime(strength, atime); - g.gain.setTargetAtTime(envelope.s * strength, atime, dt); - slast = envelope.s + (1 - envelope.s) * Math.exp((atime - stime) / dt); + g.gain.setTargetAtTime(venv.s * strength, atime, dt); + slast = venv.s + (1 - venv.s) * Math.exp((atime - stime) / dt); g.gain.setValueAtTime(slast * strength, stime); g.gain.linearRampToValueAtTime(0, rtime); g.connect(atop.out); @@ -2949,6 +3862,7 @@ function init(options) { if (options.hasOwnProperty('history')) { uselocalstorage = options.history; } if (options.hasOwnProperty('coffee')) { coffeescript = options.coffee; } if (options.hasOwnProperty('abbreviate')) { abbreviate = options.abbreviate; } + if (options.hasOwnProperty('consolehook')) { consolehook= options.consolehook; } if (options.hasOwnProperty('noconflict')) { noconflict(options.noconflict); } if (panel) { // panel overrides element and autoscroll. @@ -2984,7 +3898,7 @@ function seeeval(scope, code) { var varpat = '[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*'; var initialvardecl = new RegExp( - '^\\s*var\\s+(?:' + varpat + '\\s*,)*' + varpat + '\\s*;\\s*'); + '^\\s*var\\s+(?:' + varpat + '\\s*,\\s*)*' + varpat + '\\s*;\\s*'); function barecs(s) { // Compile coffeescript in bare mode. @@ -3007,7 +3921,9 @@ function exportsee() { see.eval = seeeval; see.barecs = barecs; see.here = 'eval(' + seepkg + '.init())'; - see.clear = clear; + see.clear = seeclear; + see.hide = seehide; + see.show = seeshow; see.js = seejs; see.cs = '(function(){return eval(' + seepkg + '.barecs(arguments[0]));})'; see.version = version; @@ -3018,7 +3934,7 @@ function noteoldvalue(name) { return { name: name, has: window.hasOwnProperty(name), - value: window[name], + value: window[name] }; } @@ -3523,16 +4439,15 @@ function flushqueue() { var addedpanel = false; var inittesttimer = null; var abbreviate = [{}.undefined]; +var consolehook = null; -function show(flag) { - if (!addedpanel) { return; } - if (arguments.length === 0 || flag) { - $('#_testpanel').show(); - } else { - $('#_testpanel').hide(); - } +function seehide() { + $('#_testpanel').hide(); +} +function seeshow() { + $('#_testpanel').show(); } -function clear() { +function seeclear() { if (!addedpanel) { return; } $('#_testlog').find('._log').not('#_testpaneltitle').remove(); } @@ -3600,6 +4515,7 @@ function tryinitpanel() { $('#_testlog').prepend(formattitle(paneltitle)); } } + $('#_testpanel').show(); } else { if (!window.document.getElementById('_testlog') && window.document.body) { initlogcss(); @@ -3609,7 +4525,7 @@ function tryinitpanel() { state.height = Math.min(wheight(), Math.max(10, wheight() - 50)); } $('body').prepend( - '#jQuery-turtle

    jQuery-turtle

    -

    version 2.0.5

    +

    version 2.0.6

    jQuery-turtle is a jQuery plugin for turtle graphics.

    @@ -72,15 +72,11 @@

    lt 360 / sides pen 'none' fd 40 - move 40, -160 + slide 40, -160

    Try an interactive demo (CoffeeScript syntax) here.

    - -

    JQuery Methods for Turtle Movement

    @@ -93,20 +89,26 @@

    $(x).bk(50) // Back. $(x).rt(90) // Right turn. $(x).lt(45) // Left turn. - $(x).move(x, y) // Move right by x while moving forward by y. - $(x).moveto({pageX: 40, pageY: 140}) // Absolute motion on page. - $(x).turnto(bearing || position) // Absolute direction adjustment. - $(x).play("ccgg") // Plays notes using ABC notation. + $(x).slide(x, y) // Move right by x while moving forward by y. + $(x).rarc(100,60) // Turn right 60 degrees tracing an arc of radius 100. + $(x).larc(50,360) // Left 360 degrees tracing a full circle of radius 50. + $(x).moveto({pageX:x,pageY:y} | [x,y]) // Absolute motion on page. + $(x).turnto(bearing || position) // Absolute direction adjustment. + $(x).play("ccgg") // Plays notes using ABC notation and waits until done. // Methods below happen in an instant, but line up in the animation queue. - $(x).home() // Moves to the origin of the document, with bearing 0. + $(x).home() // Jumps to the center of the document, with bearing 0. $(x).pen('red') // Sets a pen style, or 'none' for no drawing. - $(x).fill('pink') // Fills a shape previously outlined using pen('path'). + $(x).pu() // Pen up - temporarily disables the pen (also pen(false)). + $(x).pd() // Pen down - starts a new pen path. + $(x).pe() // Uses the pen 'erase' style. + $(x).fill('gold') // Fills a shape previously outlined using pen('path'). $(x).dot(12) // Draws a circular dot of diameter 12. - $(x).mark('A') // Prints an HTML inline-block at the turtle location. + $(x).label('A') // Prints an HTML label at the turtle location. $(x).speed(10) // Sets turtle animation speed to 10 moves per sec. - $(x).erase() // Erases the canvas under the turtle collision hull. - $(x).img('blue') // Switches the turtle to a blue picture. Use any url. + $(x).ht() // Hides the turtle. + $(x).st() // Shows the turtle. + $(x).wear('blue') // Switches to a blue shell. Use any image or color. $(x).scale(1.5) // Scales turtle size and motion by 150%. $(x).twist(180) // Changes which direction is considered "forward". $(x).mirror(true) // Flips the turtle across its main axis. @@ -115,36 +117,77 @@

    // and the callback fn can insert into the animation queue. // Methods below this line do not queue for animation. - $(x).origin() // Page coordinate of the turtle's transform-origin. + $(x).getxy() // Local (center-y-up [x, y]) coordinates of the turtle. + $(x).pagexy() // Page (topleft-y-down {pageX:x, pageY:y}) coordinates. $(x).bearing([p]) // The turtles absolute direction (or direction towards p). $(x).distance(p) // Distance to p in page coordinates. $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") $(x).touches(y) // Collision tests elements (uses turtleHull if present). $(x).encloses(y) // Containment collision test. - $(x).within(d, t) // Filters to items with origins within d of t.origin(). + $(x).within(d, t) // Filters to items with centers within d of t.pagexy(). $(x).notwithin() // The negation of within. - $(x).cell(x, y) // Selects the yth row and xth column cell in a table. + $(x).cell(y, x) // Selects the yth row and xth column cell in a table. + $(x).hatch([n,] [img]) // Creates and returns n turtles with the given img.

    When the speed of a turtle is nonzero, the first seven movement -functions animate at that speed, and the remaining mutators also -participate in the animation queue. The default turtle speed is -a leisurely one move per second (as appropriate for the creature), -but you may soon discover the desire to set speed higher.

    +functions animate at that speed (in moves per second), and the +remaining mutators also participate in the animation queue. The +default turtle speed is a leisurely one move per second (as +appropriate for the creature), but you may soon discover the +desire to set speed higher.

    -

    Setting the turtle speed to Infinity will make movement synchronous, +

    Setting the turtle speed to Infinity will make its movement synchronous, which makes the synchronous distance, direction, and hit-testing useful -for realtime game-making. To play music without stalling turtle -movement, use the global function playnow() instead of the turtle -method play().

    - -

    The absolute motion methods moveto and turnto accept any object -that has pageX and pageY properties (or an origin() method that will -return such an object), including, usefully, mouse events. -Moveto and turnto operate in absolute page coordinates and work -properly even when the turtle is nested within further CSS -transformed elements.

    +for realtime game-making.

    + +

    The turtle pen respects canvas styling: any valid strokeStyle is +accepted; and also using a space-separated syntax, lineWidth, lineCap, +lineJoin, miterLimit, and fillStyle can be specified, e.g., +pen('red lineWidth 5 lineCap square'). The same syntax applies for +styling dot and fill (except that the default interpretation for the +first value is fillStyle instead of strokeStyle).

    + +

    The fill method is used by tracing an invisible path using the +pen('path') style, and then calling the fill method. Disconnected +paths can be created using pu() and pd().

    + +

    The play method plays a sequence of notes specified using a subset of +standard ABC notation. Capital C denotes middle C, and lowercase c is +an octave higher. Pitches and durations can be altered with commas, +apostrophes, carets, underscores, digits, and slashes as in the +standard. Enclosing letters in square brackets represents a chord, +and z represents a rest. The default tempo is 120, but can be changed +by passing a options object as the first parameter setting tempo, e.g., +{ tempo: 200 }. Other options include volume: 0.5, type: 'sine' or +'square' or 'sawtooth' or 'triangle', and envelope: which defines +an ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }.

    + +

    The turtle's motion will pause while it is playing notes. To play +notes without stalling turtle movement, use the global function sound() +instead of the turtle method play().

    + +

    The direct method can be used to queue logic (including synchronous +tests or actions) by running a function in the animation queue. Unlike +jquery queue(), direct arranges things so that if further animations +are queued by the callback function, they are inserted (in natural +recursive functional execution order) instead of being appended.

    + +

    The turnto method can turn to an absolute bearing (if called with a +single numeric argument) or towards an absolute position on the +screen. The methods moveto and turnto accept either page or +graphing coordinates.

    + +

    Graphing coordinates are measured upwards and rightwards from the +center of the page, and they are specified as bare numeric x, y +arguments or [x, y] pairs as returned from getxy().

    + +

    Page coordinates are specified by an object with pageX and pageY +properties, or with a pagexy() method that will return such an object. +That includes, usefullly, mouse events and turtle objects. Page +coordinates are measured downward from the top-left corner of the +page to the center (or transform-origin) of the given object.

    The hit-testing functions touches() and encloses() will test for collisions using the convex hulls of the objects in question. @@ -156,9 +199,10 @@

    Turtle Teaching Environment

    A default turtle together with an interactive console are created by -calling eval($.turtle()). This call will expose a the default turtle -methods as global functions. It will also set up a number of other global -symbols to provide beginners with a simplified programming environment.

    +calling eval($.turtle()). That call exposes all the turtle methods +such as (fd, rt, getxy, etc) as global functions operating on the default +turtle. It will also set up a number of other global symbols to provide +beginners with a simplified programming environment.

    In detail, after eval($.turtle()):

    @@ -181,9 +225,13 @@

    keydown // The last keydown event. keyup // The last keyup event. keypress // The last keypress event. + hatch([n,] [img]) // Creates and returns n turtles with the given img. + cs() // Clears the screen, both the canvas and the body text. + cg() // Clears the graphics canvas without clearing the text. + ct() // Clears the text without clearing the canvas. defaultspeed(mps) // Sets $.fx.speeds.turtle to 1000 / mps. tick([perSec,] fn) // Sets fn as the tick callback (null to clear). - random(n) // Returns a random number [0...n-1]. + random(n) // Returns a random number [0..n-1]. random(list) // Returns a random element of the list. random('normal') // Returns a gaussian random (mean 0 stdev 1). random('uniform') // Returns a uniform random [0...1). @@ -191,13 +239,14 @@

    random('color') // Returns a random hsl(*, 100%, 50%) color. random('gray') // Returns a random hsl(0, 0, *) gray. remove() // Removes default turtle and its globals (fd, etc). - hatch([n,], [img]) // Creates and returns n turtles with the given img. see(a, b, c...) // Logs tree-expandable data into debugging panel. - print(html) // Appends html into the document body. - input([label,] fn) // Makes a one-time input field, calls fn after entry. + write(html) // Appends html into the document body. + read([label,] fn) // Makes a one-time input field, calls fn after entry. + readnum([label,] fn) // Like read, but restricted to numeric input. + readstr([label,] fn) // Like read, but never converts input to a number. button([label,] fn) // Makes a clickable button, calls fn when clicked. - table(w, h) // Outputs a table with h rows and w columns. - playnow('CEG') // Plays musical notes now, without queueing. + table(m, n) // Outputs a table with m rows and n columns. + sound('[DFG][EGc]') // Plays musical notes now, without queueing.

    Here is another CoffeeScript example that demonstrates some of @@ -207,7 +256,7 @@

    eval $.turtle() # Create the default turtle and global functions. defaultspeed Infinity - print "Catch blue before red gets you." + write "Catch blue before red gets you." bk 100 r = hatch 'red' b = hatch 'blue' @@ -219,13 +268,13 @@

    b.turnto bearing b b.fd 3 if b.touches(turtle) - print "You win!" + write "You win!" tick off else if r.touches(turtle) - print "Red got you!" + write "Red got you!" tick off else if not b.touches(document) - print "Blue got away!" + write "Blue got away!" tick off @@ -241,22 +290,33 @@

       $(x).css('turtleSpeed', '10');         // default speed in moves per second.
       $(x).css('turtlePosition', '30 40');   // position in local coordinates.
    -  $(x).css('turtlePositionX', '30');     // x component.
    -  $(x).css('turtlePositionY', '40');     // y component.
    -  $(x).css('turtleRotation', '90');      // rotation in degrees.
    +  $(x).css('turtlePositionX', '30px');   // x component.
    +  $(x).css('turtlePositionY', '40px');   // y component.
    +  $(x).css('turtleRotation', '90deg');   // rotation in degrees.
       $(x).css('turtleScale', '2');          // double the size of any element.
       $(x).css('turtleScaleX', '2');         // x stretch after twist.
       $(x).css('turtleScaleY', '2');         // y stretch after twist.
    -  $(x).css('turtleTwist', '45');         // turn before stretching.
    -  $(x).css('turtleForward', '50');       // position in direction of rotation.
    +  $(x).css('turtleTwist', '45deg');      // turn before stretching.
    +  $(x).css('turtleForward', '50px');     // position in direction of rotation.
    +  $(x).css('turtleTurningRadius, '50px');// arc turning radius for rotation.
       $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
       $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
       $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
     

    Arbitrary 2d transforms are supported, including transforms of elements -nested within other elements that have css transforms. Transforms are -automatically decomposed to turtle components when necessary.

    +nested within other elements that have css transforms. For example, arc +paths of a turtle within a skewed div will transform to the proper elliptical +arc. Note that while turtle motion is transformed, lines and dots are not: +for example, dots are always circular. To get transformed circles, trace +out an arc.

    + +

    Transforms on the turtle itself are used to infer the turtle position, +direction, and rendering of the sprite. ScaleY stretches the turtle +sprite in the direction of movement also stretches distances for +motion in all directions. ScaleX stretches the turtle sprite perpendicular +to the direction of motion and also stretches line and dot widths for +drawing.

    A canvas is supported for drawing, but only created when the pen is used; pen styles include canvas style properties such as lineWidth @@ -298,4 +358,4 @@

    - + \ No newline at end of file diff --git a/params.json b/params.json index ca4ac7a..5a1e447 100644 --- a/params.json +++ b/params.json @@ -1 +1 @@ -{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.5\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using turtle graphics methods like fd (forward), bk (back),\r\nrt (right turn), and lt (left turn). The pen function allows\r\na turtle to draw on a full-document canvas as it moves.\r\n\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\n\r\njQuery-turtle provides:\r\n * Relative and absolute motion and drawing.\r\n * Functions to ease basic input, output, and game-making for beginners.\r\n * Operations on sets of turtles, and turtle motion of arbitrary elements.\r\n * Accurate collision-testing of turtles with arbitrary convex hulls.\r\n * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.\r\n * An interactive turtle console in either Javascript or CoffeeScript.\r\n\r\nThe plugin can also create a learning environment with a default\r\nturtle that is friendly for beginners. The following is a complete\r\nCoffeeScript program that uses the default turtle to draw a grid of\r\nsixteen colored polygons.\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle.\r\n\r\n  speed 100\r\n  for color in ['red', 'gold', 'green', 'blue']\r\n    for sides in [3..6]\r\n      pen color\r\n      for x in [1..sides]\r\n        fd 100 / sides\r\n        lt 360 / sides\r\n      pen 'none'\r\n      fd 40\r\n    move 40, -160\r\n
    \r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nThe turtle API is briefly summarized below. All the following\r\nturtle-oriented methods operate on any jQuery object (including\r\nthe default turtle, if used):\r\n\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).move(x, y)   // Move right by x while moving forward by y.\r\n  $(x).moveto({pageX: 40, pageY: 140})  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)      // Absolute direction adjustment.\r\n  $(x).play(\"ccgg\") // Plays notes using ABC notation.\r\n\r\n  // Methods below happen in an instant, but line up in the animation queue.\r\n  $(x).home()       // Moves to the origin of the document, with bearing 0.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).fill('pink') // Fills a shape previously outlined using pen('path').\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).mark('A')    // Prints an HTML inline-block at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).erase()      // Erases the canvas under the turtle collision hull.\r\n  $(x).img('blue')  // Switches the turtle to a blue picture.  Use any url.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,\r\n                    // and the callback fn can insert into the animation queue.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).origin()     // Page coordinate of the turtle's transform-origin.\r\n  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with origins within d of t.origin().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(x, y)   // Selects the yth row and xth column cell in a table.\r\n
    \r\n\r\nWhen the speed of a turtle is nonzero, the first seven movement\r\nfunctions animate at that speed, and the remaining mutators also\r\nparticipate in the animation queue. The default turtle speed is\r\na leisurely one move per second (as appropriate for the creature),\r\nbut you may soon discover the desire to set speed higher.\r\n\r\nSetting the turtle speed to Infinity will make movement synchronous,\r\nwhich makes the synchronous distance, direction, and hit-testing useful\r\nfor realtime game-making. To play music without stalling turtle\r\nmovement, use the global function playnow() instead of the turtle\r\nmethod play().\r\n\r\nThe absolute motion methods moveto and turnto accept any object\r\nthat has pageX and pageY properties (or an origin() method that will\r\nreturn such an object), including, usefully, mouse events.\r\nMoveto and turnto operate in absolute page coordinates and work\r\nproperly even when the turtle is nested within further CSS\r\ntransformed elements.\r\n\r\nThe hit-testing functions touches() and encloses() will test for\r\ncollisions using the convex hulls of the objects in question.\r\nThe hull of an element defaults to the bounding box of the element\r\n(as transformed) but can be overridden by the turtleHull CSS property,\r\nif present. The default turtle is given a turtle-shaped hull.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nA default turtle together with an interactive console are created by\r\ncalling eval($.turtle()). This call will expose a the default turtle\r\nmethods as global functions. It will also set up a number of other global\r\nsymbols to provide beginners with a simplified programming environment.\r\n\r\nIn detail, after eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * Global event listeners are created to update global event variables.\r\n * Methods of $.turtle.* (enumerated below) are exposed as global functions.\r\n\r\nBeyond the functions to control the default turtle, the globals added by\r\n$.turtle() are as follows:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0...n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  hatch([n,], [img])    // Creates and returns n turtles with the given img.\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  print(html)           // Appends html into the document body.\r\n  input([label,] fn)    // Makes a one-time input field, calls fn after entry.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(w, h)           // Outputs a table with h rows and w columns.\r\n  playnow('CEG')        // Plays musical notes now, without queueing.\r\n
    \r\n\r\nHere is another CoffeeScript example that demonstrates some of\r\nthe functions:\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle and global functions.\r\n\r\n  defaultspeed Infinity\r\n  print \"Catch blue before red gets you.\"\r\n  bk 100\r\n  r = hatch 'red'\r\n  b = hatch 'blue'\r\n  tick 10, ->\r\n    turnto lastmousemove\r\n    fd 6\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto bearing b\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      print \"You win!\"\r\n      tick off\r\n    else if r.touches(turtle)\r\n      print \"Red got you!\"\r\n      tick off\r\n    else if not b.touches(document)\r\n      print \"Blue got away!\"\r\n      tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nUnderlying turtle motion are turtle-oriented 2d transform jQuery cssHooks,\r\nwith animation support on all motion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30');     // x component.\r\n  $(x).css('turtlePositionY', '40');     // y component.\r\n  $(x).css('turtleRotation', '90');      // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45');         // turn before stretching.\r\n  $(x).css('turtleForward', '50');       // position in direction of rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. Transforms are\r\nautomatically decomposed to turtle components when necessary.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file +{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.6\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using turtle graphics methods like fd (forward), bk (back),\r\nrt (right turn), and lt (left turn). The pen function allows\r\na turtle to draw on a full-document canvas as it moves.\r\n\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\n\r\njQuery-turtle provides:\r\n * Relative and absolute motion and drawing.\r\n * Functions to ease basic input, output, and game-making for beginners.\r\n * Operations on sets of turtles, and turtle motion of arbitrary elements.\r\n * Accurate collision-testing of turtles with arbitrary convex hulls.\r\n * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.\r\n * An interactive turtle console in either Javascript or CoffeeScript.\r\n\r\nThe plugin can also create a learning environment with a default\r\nturtle that is friendly for beginners. The following is a complete\r\nCoffeeScript program that uses the default turtle to draw a grid of\r\nsixteen colored polygons.\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle.\r\n\r\n  speed 100\r\n  for color in ['red', 'gold', 'green', 'blue']\r\n    for sides in [3..6]\r\n      pen color\r\n      for x in [1..sides]\r\n        fd 100 / sides\r\n        lt 360 / sides\r\n      pen 'none'\r\n      fd 40\r\n    slide 40, -160\r\n
    \r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nThe turtle API is briefly summarized below. All the following\r\nturtle-oriented methods operate on any jQuery object (including\r\nthe default turtle, if used):\r\n\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).slide(x, y)  // Move right by x while moving forward by y.\r\n  $(x).rarc(100,60) // Turn right 60 degrees tracing an arc of radius 100.\r\n  $(x).larc(50,360) // Left 360 degrees tracing a full circle of radius 50.\r\n  $(x).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)        // Absolute direction adjustment.\r\n  $(x).play(\"ccgg\") // Plays notes using ABC notation and waits until done.\r\n\r\n  // Methods below happen in an instant, but line up in the animation queue.\r\n  $(x).home()       // Jumps to the center of the document, with bearing 0.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).pu()         // Pen up - temporarily disables the pen (also pen(false)).\r\n  $(x).pd()         // Pen down - starts a new pen path.\r\n  $(x).pe()         // Uses the pen 'erase' style.\r\n  $(x).fill('gold') // Fills a shape previously outlined using pen('path').\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).label('A')   // Prints an HTML label at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).ht()         // Hides the turtle.\r\n  $(x).st()         // Shows the turtle.\r\n  $(x).wear('blue') // Switches to a blue shell.  Use any image or color.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,\r\n                    // and the callback fn can insert into the animation queue.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.\r\n  $(x).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.\r\n  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with centers within d of t.pagexy().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(y, x)   // Selects the yth row and xth column cell in a table.\r\n  $(x).hatch([n,] [img]) // Creates and returns n turtles with the given img.\r\n
    \r\n\r\nWhen the speed of a turtle is nonzero, the first seven movement\r\nfunctions animate at that speed (in moves per second), and the\r\nremaining mutators also participate in the animation queue. The\r\ndefault turtle speed is a leisurely one move per second (as\r\nappropriate for the creature), but you may soon discover the\r\ndesire to set speed higher.\r\n\r\nSetting the turtle speed to Infinity will make its movement synchronous,\r\nwhich makes the synchronous distance, direction, and hit-testing useful\r\nfor realtime game-making.\r\n\r\nThe turtle pen respects canvas styling: any valid strokeStyle is\r\naccepted; and also using a space-separated syntax, lineWidth, lineCap,\r\nlineJoin, miterLimit, and fillStyle can be specified, e.g.,\r\npen('red lineWidth 5 lineCap square'). The same syntax applies for\r\nstyling dot and fill (except that the default interpretation for the\r\nfirst value is fillStyle instead of strokeStyle).\r\n\r\nThe fill method is used by tracing an invisible path using the\r\npen('path') style, and then calling the fill method. Disconnected\r\npaths can be created using pu() and pd().\r\n\r\nThe play method plays a sequence of notes specified using a subset of\r\nstandard ABC notation. Capital C denotes middle C, and lowercase c is\r\nan octave higher. Pitches and durations can be altered with commas,\r\napostrophes, carets, underscores, digits, and slashes as in the\r\nstandard. Enclosing letters in square brackets represents a chord,\r\nand z represents a rest. The default tempo is 120, but can be changed\r\nby passing a options object as the first parameter setting tempo, e.g.,\r\n{ tempo: 200 }. Other options include volume: 0.5, type: 'sine' or\r\n'square' or 'sawtooth' or 'triangle', and envelope: which defines\r\nan ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }.\r\n\r\nThe turtle's motion will pause while it is playing notes. To play\r\nnotes without stalling turtle movement, use the global function sound()\r\ninstead of the turtle method play().\r\n\r\nThe direct method can be used to queue logic (including synchronous\r\ntests or actions) by running a function in the animation queue. Unlike\r\njquery queue(), direct arranges things so that if further animations\r\nare queued by the callback function, they are inserted (in natural\r\nrecursive functional execution order) instead of being appended.\r\n\r\nThe turnto method can turn to an absolute bearing (if called with a\r\nsingle numeric argument) or towards an absolute position on the\r\nscreen. The methods moveto and turnto accept either page or\r\ngraphing coordinates.\r\n\r\nGraphing coordinates are measured upwards and rightwards from the\r\ncenter of the page, and they are specified as bare numeric x, y\r\narguments or [x, y] pairs as returned from getxy().\r\n\r\nPage coordinates are specified by an object with pageX and pageY\r\nproperties, or with a pagexy() method that will return such an object.\r\nThat includes, usefullly, mouse events and turtle objects. Page\r\ncoordinates are measured downward from the top-left corner of the\r\npage to the center (or transform-origin) of the given object.\r\n\r\nThe hit-testing functions touches() and encloses() will test for\r\ncollisions using the convex hulls of the objects in question.\r\nThe hull of an element defaults to the bounding box of the element\r\n(as transformed) but can be overridden by the turtleHull CSS property,\r\nif present. The default turtle is given a turtle-shaped hull.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nA default turtle together with an interactive console are created by\r\ncalling eval($.turtle()). That call exposes all the turtle methods\r\nsuch as (fd, rt, getxy, etc) as global functions operating on the default\r\nturtle. It will also set up a number of other global symbols to provide\r\nbeginners with a simplified programming environment.\r\n\r\nIn detail, after eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * Global event listeners are created to update global event variables.\r\n * Methods of $.turtle.* (enumerated below) are exposed as global functions.\r\n\r\nBeyond the functions to control the default turtle, the globals added by\r\n$.turtle() are as follows:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  hatch([n,] [img])     // Creates and returns n turtles with the given img.\r\n  cs()                  // Clears the screen, both the canvas and the body text.\r\n  cg()                  // Clears the graphics canvas without clearing the text.\r\n  ct()                  // Clears the text without clearing the canvas.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0..n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  write(html)           // Appends html into the document body.\r\n  read([label,] fn)     // Makes a one-time input field, calls fn after entry.\r\n  readnum([label,] fn)  // Like read, but restricted to numeric input.\r\n  readstr([label,] fn)  // Like read, but never converts input to a number.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(m, n)           // Outputs a table with m rows and n columns.\r\n  sound('[DFG][EGc]')   // Plays musical notes now, without queueing.\r\n
    \r\n\r\nHere is another CoffeeScript example that demonstrates some of\r\nthe functions:\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle and global functions.\r\n\r\n  defaultspeed Infinity\r\n  write \"Catch blue before red gets you.\"\r\n  bk 100\r\n  r = hatch 'red'\r\n  b = hatch 'blue'\r\n  tick 10, ->\r\n    turnto lastmousemove\r\n    fd 6\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto bearing b\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      write \"You win!\"\r\n      tick off\r\n    else if r.touches(turtle)\r\n      write \"Red got you!\"\r\n      tick off\r\n    else if not b.touches(document)\r\n      write \"Blue got away!\"\r\n      tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nUnderlying turtle motion are turtle-oriented 2d transform jQuery cssHooks,\r\nwith animation support on all motion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30px');   // x component.\r\n  $(x).css('turtlePositionY', '40px');   // y component.\r\n  $(x).css('turtleRotation', '90deg');   // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45deg');      // turn before stretching.\r\n  $(x).css('turtleForward', '50px');     // position in direction of rotation.\r\n  $(x).css('turtleTurningRadius, '50px');// arc turning radius for rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. For example, arc\r\npaths of a turtle within a skewed div will transform to the proper elliptical\r\narc. Note that while turtle motion is transformed, lines and dots are not:\r\nfor example, dots are always circular. To get transformed circles, trace\r\nout an arc.\r\n\r\nTransforms on the turtle itself are used to infer the turtle position,\r\ndirection, and rendering of the sprite. ScaleY stretches the turtle\r\nsprite in the direction of movement also stretches distances for\r\nmotion in all directions. ScaleX stretches the turtle sprite perpendicular\r\nto the direction of motion and also stretches line and dot widths for\r\ndrawing.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file From 4b1bae01aab2e50ffb23318271a3592a6ab7fa53 Mon Sep 17 00:00:00 2001 From: David Bau Date: Mon, 8 Jul 2013 08:22:34 -0400 Subject: [PATCH 21/25] Update with iframe. --- index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 2d07dc6..b9c437f 100644 --- a/index.html +++ b/index.html @@ -76,6 +76,9 @@

    Try an interactive demo (CoffeeScript syntax) here.

    +

    JQuery Methods for Turtle Movement

    @@ -358,4 +361,4 @@

    - \ No newline at end of file + From 2366abf2e0a60f3222a514be4294f6fc2a123577 Mon Sep 17 00:00:00 2001 From: David Bau Date: Mon, 8 Jul 2013 08:29:11 -0400 Subject: [PATCH 22/25] Formatting. --- demo.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/demo.html b/demo.html index ba8a269..ed8b62c 100644 --- a/demo.html +++ b/demo.html @@ -8,7 +8,8 @@ - - + + + + + + + jQuery-turtle + -
    -
    -

    jQuery-turtle

    -

    Turtle Graphics for JQuery

    - + +
    +
    + View on GitHub -

    This project is maintained by davidbau

    +

    jQuery-turtle

    +

    Turtle Graphics for JQuery

    +
    + Download this project as a .zip file + Download this project as a tar.gz file +
    +
    +
    -
    -
    + +
    +

    jQuery-turtle

    -

    version 2.0.6

    +

    version 2.0.7

    jQuery-turtle is a jQuery plugin for turtle graphics.

    @@ -64,21 +65,18 @@

    eval $.turtle() # Create the default turtle. speed 100 - for color in ['red', 'gold', 'green', 'blue'] + for color in [red, gold, green, blue] for sides in [3..6] pen color for x in [1..sides] fd 100 / sides lt 360 / sides - pen 'none' + pen null fd 40 slide 40, -160

    Try an interactive demo (CoffeeScript syntax) here.

    -

    JQuery Methods for Turtle Movement

    @@ -127,7 +125,7 @@

    $(x).shown() // Shorthand for is(":visible") $(x).hidden() // Shorthand for !is(":visible") $(x).touches(y) // Collision tests elements (uses turtleHull if present). - $(x).encloses(y) // Containment collision test. + $(x).enclosedby(y)// Containment collision test. $(x).within(d, t) // Filters to items with centers within d of t.pagexy(). $(x).notwithin() // The negation of within. $(x).cell(y, x) // Selects the yth row and xth column cell in a table. @@ -192,7 +190,7 @@

    coordinates are measured downward from the top-left corner of the page to the center (or transform-origin) of the given object.

    -

    The hit-testing functions touches() and encloses() will test for +

    The hit-testing functions touches() and enclosedby() will test for collisions using the convex hulls of the objects in question. The hull of an element defaults to the bounding box of the element (as transformed) but can be overridden by the turtleHull CSS property, @@ -217,6 +215,7 @@

  • Default turtle animation is set to 1 move per sec so steps can be seen.
  • Global event listeners are created to update global event variables.
  • Methods of $.turtle.* (enumerated below) are exposed as global functions.
  • +
  • String constants are defined for the 140 named CSS colors.
  • Beyond the functions to control the default turtle, the globals added by $.turtle() are as follows:

    @@ -326,7 +325,7 @@

    and lineCap.

    A convex hull polygon can be set to be used by the collision detection -and hit-testing functions (encloses, touches). The turtleHull is a list +and hit-testing functions (enclosedby, touches). The turtleHull is a list of (unrotated) x-y coordinates relative to the object's transformOrigin. If set to 'auto' (the default) the hull is just the bounding box for the element.

    @@ -354,11 +353,17 @@

    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    -
    + + + - - + + + diff --git a/javascripts/main.js b/javascripts/main.js new file mode 100644 index 0000000..d8135d3 --- /dev/null +++ b/javascripts/main.js @@ -0,0 +1 @@ +console.log('This would be the main JS file.'); diff --git a/params.json b/params.json index 5a1e447..dcfe0a9 100644 --- a/params.json +++ b/params.json @@ -1 +1 @@ -{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.6\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using turtle graphics methods like fd (forward), bk (back),\r\nrt (right turn), and lt (left turn). The pen function allows\r\na turtle to draw on a full-document canvas as it moves.\r\n\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\n\r\njQuery-turtle provides:\r\n * Relative and absolute motion and drawing.\r\n * Functions to ease basic input, output, and game-making for beginners.\r\n * Operations on sets of turtles, and turtle motion of arbitrary elements.\r\n * Accurate collision-testing of turtles with arbitrary convex hulls.\r\n * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.\r\n * An interactive turtle console in either Javascript or CoffeeScript.\r\n\r\nThe plugin can also create a learning environment with a default\r\nturtle that is friendly for beginners. The following is a complete\r\nCoffeeScript program that uses the default turtle to draw a grid of\r\nsixteen colored polygons.\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle.\r\n\r\n  speed 100\r\n  for color in ['red', 'gold', 'green', 'blue']\r\n    for sides in [3..6]\r\n      pen color\r\n      for x in [1..sides]\r\n        fd 100 / sides\r\n        lt 360 / sides\r\n      pen 'none'\r\n      fd 40\r\n    slide 40, -160\r\n
    \r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nThe turtle API is briefly summarized below. All the following\r\nturtle-oriented methods operate on any jQuery object (including\r\nthe default turtle, if used):\r\n\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).slide(x, y)  // Move right by x while moving forward by y.\r\n  $(x).rarc(100,60) // Turn right 60 degrees tracing an arc of radius 100.\r\n  $(x).larc(50,360) // Left 360 degrees tracing a full circle of radius 50.\r\n  $(x).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)        // Absolute direction adjustment.\r\n  $(x).play(\"ccgg\") // Plays notes using ABC notation and waits until done.\r\n\r\n  // Methods below happen in an instant, but line up in the animation queue.\r\n  $(x).home()       // Jumps to the center of the document, with bearing 0.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).pu()         // Pen up - temporarily disables the pen (also pen(false)).\r\n  $(x).pd()         // Pen down - starts a new pen path.\r\n  $(x).pe()         // Uses the pen 'erase' style.\r\n  $(x).fill('gold') // Fills a shape previously outlined using pen('path').\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).label('A')   // Prints an HTML label at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).ht()         // Hides the turtle.\r\n  $(x).st()         // Shows the turtle.\r\n  $(x).wear('blue') // Switches to a blue shell.  Use any image or color.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,\r\n                    // and the callback fn can insert into the animation queue.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.\r\n  $(x).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.\r\n  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).encloses(y)  // Containment collision test.\r\n  $(x).within(d, t) // Filters to items with centers within d of t.pagexy().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(y, x)   // Selects the yth row and xth column cell in a table.\r\n  $(x).hatch([n,] [img]) // Creates and returns n turtles with the given img.\r\n
    \r\n\r\nWhen the speed of a turtle is nonzero, the first seven movement\r\nfunctions animate at that speed (in moves per second), and the\r\nremaining mutators also participate in the animation queue. The\r\ndefault turtle speed is a leisurely one move per second (as\r\nappropriate for the creature), but you may soon discover the\r\ndesire to set speed higher.\r\n\r\nSetting the turtle speed to Infinity will make its movement synchronous,\r\nwhich makes the synchronous distance, direction, and hit-testing useful\r\nfor realtime game-making.\r\n\r\nThe turtle pen respects canvas styling: any valid strokeStyle is\r\naccepted; and also using a space-separated syntax, lineWidth, lineCap,\r\nlineJoin, miterLimit, and fillStyle can be specified, e.g.,\r\npen('red lineWidth 5 lineCap square'). The same syntax applies for\r\nstyling dot and fill (except that the default interpretation for the\r\nfirst value is fillStyle instead of strokeStyle).\r\n\r\nThe fill method is used by tracing an invisible path using the\r\npen('path') style, and then calling the fill method. Disconnected\r\npaths can be created using pu() and pd().\r\n\r\nThe play method plays a sequence of notes specified using a subset of\r\nstandard ABC notation. Capital C denotes middle C, and lowercase c is\r\nan octave higher. Pitches and durations can be altered with commas,\r\napostrophes, carets, underscores, digits, and slashes as in the\r\nstandard. Enclosing letters in square brackets represents a chord,\r\nand z represents a rest. The default tempo is 120, but can be changed\r\nby passing a options object as the first parameter setting tempo, e.g.,\r\n{ tempo: 200 }. Other options include volume: 0.5, type: 'sine' or\r\n'square' or 'sawtooth' or 'triangle', and envelope: which defines\r\nan ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }.\r\n\r\nThe turtle's motion will pause while it is playing notes. To play\r\nnotes without stalling turtle movement, use the global function sound()\r\ninstead of the turtle method play().\r\n\r\nThe direct method can be used to queue logic (including synchronous\r\ntests or actions) by running a function in the animation queue. Unlike\r\njquery queue(), direct arranges things so that if further animations\r\nare queued by the callback function, they are inserted (in natural\r\nrecursive functional execution order) instead of being appended.\r\n\r\nThe turnto method can turn to an absolute bearing (if called with a\r\nsingle numeric argument) or towards an absolute position on the\r\nscreen. The methods moveto and turnto accept either page or\r\ngraphing coordinates.\r\n\r\nGraphing coordinates are measured upwards and rightwards from the\r\ncenter of the page, and they are specified as bare numeric x, y\r\narguments or [x, y] pairs as returned from getxy().\r\n\r\nPage coordinates are specified by an object with pageX and pageY\r\nproperties, or with a pagexy() method that will return such an object.\r\nThat includes, usefullly, mouse events and turtle objects. Page\r\ncoordinates are measured downward from the top-left corner of the\r\npage to the center (or transform-origin) of the given object.\r\n\r\nThe hit-testing functions touches() and encloses() will test for\r\ncollisions using the convex hulls of the objects in question.\r\nThe hull of an element defaults to the bounding box of the element\r\n(as transformed) but can be overridden by the turtleHull CSS property,\r\nif present. The default turtle is given a turtle-shaped hull.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nA default turtle together with an interactive console are created by\r\ncalling eval($.turtle()). That call exposes all the turtle methods\r\nsuch as (fd, rt, getxy, etc) as global functions operating on the default\r\nturtle. It will also set up a number of other global symbols to provide\r\nbeginners with a simplified programming environment.\r\n\r\nIn detail, after eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * Global event listeners are created to update global event variables.\r\n * Methods of $.turtle.* (enumerated below) are exposed as global functions.\r\n\r\nBeyond the functions to control the default turtle, the globals added by\r\n$.turtle() are as follows:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  hatch([n,] [img])     // Creates and returns n turtles with the given img.\r\n  cs()                  // Clears the screen, both the canvas and the body text.\r\n  cg()                  // Clears the graphics canvas without clearing the text.\r\n  ct()                  // Clears the text without clearing the canvas.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0..n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  write(html)           // Appends html into the document body.\r\n  read([label,] fn)     // Makes a one-time input field, calls fn after entry.\r\n  readnum([label,] fn)  // Like read, but restricted to numeric input.\r\n  readstr([label,] fn)  // Like read, but never converts input to a number.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(m, n)           // Outputs a table with m rows and n columns.\r\n  sound('[DFG][EGc]')   // Plays musical notes now, without queueing.\r\n
    \r\n\r\nHere is another CoffeeScript example that demonstrates some of\r\nthe functions:\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle and global functions.\r\n\r\n  defaultspeed Infinity\r\n  write \"Catch blue before red gets you.\"\r\n  bk 100\r\n  r = hatch 'red'\r\n  b = hatch 'blue'\r\n  tick 10, ->\r\n    turnto lastmousemove\r\n    fd 6\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto bearing b\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      write \"You win!\"\r\n      tick off\r\n    else if r.touches(turtle)\r\n      write \"Red got you!\"\r\n      tick off\r\n    else if not b.touches(document)\r\n      write \"Blue got away!\"\r\n      tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nUnderlying turtle motion are turtle-oriented 2d transform jQuery cssHooks,\r\nwith animation support on all motion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30px');   // x component.\r\n  $(x).css('turtlePositionY', '40px');   // y component.\r\n  $(x).css('turtleRotation', '90deg');   // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45deg');      // turn before stretching.\r\n  $(x).css('turtleForward', '50px');     // position in direction of rotation.\r\n  $(x).css('turtleTurningRadius, '50px');// arc turning radius for rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. For example, arc\r\npaths of a turtle within a skewed div will transform to the proper elliptical\r\narc. Note that while turtle motion is transformed, lines and dots are not:\r\nfor example, dots are always circular. To get transformed circles, trace\r\nout an arc.\r\n\r\nTransforms on the turtle itself are used to infer the turtle position,\r\ndirection, and rendering of the sprite. ScaleY stretches the turtle\r\nsprite in the direction of movement also stretches distances for\r\nmotion in all directions. ScaleX stretches the turtle sprite perpendicular\r\nto the direction of motion and also stretches line and dot widths for\r\ndrawing.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (encloses, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file +{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.7\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using turtle graphics methods like fd (forward), bk (back),\r\nrt (right turn), and lt (left turn). The pen function allows\r\na turtle to draw on a full-document canvas as it moves.\r\n\r\n
    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\n\r\njQuery-turtle provides:\r\n * Relative and absolute motion and drawing.\r\n * Functions to ease basic input, output, and game-making for beginners.\r\n * Operations on sets of turtles, and turtle motion of arbitrary elements.\r\n * Accurate collision-testing of turtles with arbitrary convex hulls.\r\n * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.\r\n * An interactive turtle console in either Javascript or CoffeeScript.\r\n\r\nThe plugin can also create a learning environment with a default\r\nturtle that is friendly for beginners. The following is a complete\r\nCoffeeScript program that uses the default turtle to draw a grid of\r\nsixteen colored polygons.\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle.\r\n\r\n  speed 100\r\n  for color in [red, gold, green, blue]\r\n    for sides in [3..6]\r\n      pen color\r\n      for x in [1..sides]\r\n        fd 100 / sides\r\n        lt 360 / sides\r\n      pen null \r\n      fd 40\r\n    slide 40, -160\r\n
    \r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nThe turtle API is briefly summarized below. All the following\r\nturtle-oriented methods operate on any jQuery object (including\r\nthe default turtle, if used):\r\n\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).slide(x, y)  // Move right by x while moving forward by y.\r\n  $(x).rarc(100,60) // Turn right 60 degrees tracing an arc of radius 100.\r\n  $(x).larc(50,360) // Left 360 degrees tracing a full circle of radius 50.\r\n  $(x).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)        // Absolute direction adjustment.\r\n  $(x).play(\"ccgg\") // Plays notes using ABC notation and waits until done.\r\n\r\n  // Methods below happen in an instant, but line up in the animation queue.\r\n  $(x).home()       // Jumps to the center of the document, with bearing 0.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).pu()         // Pen up - temporarily disables the pen (also pen(false)).\r\n  $(x).pd()         // Pen down - starts a new pen path.\r\n  $(x).pe()         // Uses the pen 'erase' style.\r\n  $(x).fill('gold') // Fills a shape previously outlined using pen('path').\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).label('A')   // Prints an HTML label at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).ht()         // Hides the turtle.\r\n  $(x).st()         // Shows the turtle.\r\n  $(x).wear('blue') // Switches to a blue shell.  Use any image or color.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,\r\n                    // and the callback fn can insert into the animation queue.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.\r\n  $(x).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.\r\n  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).enclosedby(y)// Containment collision test.\r\n  $(x).within(d, t) // Filters to items with centers within d of t.pagexy().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(y, x)   // Selects the yth row and xth column cell in a table.\r\n  $(x).hatch([n,] [img]) // Creates and returns n turtles with the given img.\r\n
    \r\n\r\nWhen the speed of a turtle is nonzero, the first seven movement\r\nfunctions animate at that speed (in moves per second), and the\r\nremaining mutators also participate in the animation queue. The\r\ndefault turtle speed is a leisurely one move per second (as\r\nappropriate for the creature), but you may soon discover the\r\ndesire to set speed higher.\r\n\r\nSetting the turtle speed to Infinity will make its movement synchronous,\r\nwhich makes the synchronous distance, direction, and hit-testing useful\r\nfor realtime game-making.\r\n\r\nThe turtle pen respects canvas styling: any valid strokeStyle is\r\naccepted; and also using a space-separated syntax, lineWidth, lineCap,\r\nlineJoin, miterLimit, and fillStyle can be specified, e.g.,\r\npen('red lineWidth 5 lineCap square'). The same syntax applies for\r\nstyling dot and fill (except that the default interpretation for the\r\nfirst value is fillStyle instead of strokeStyle).\r\n\r\nThe fill method is used by tracing an invisible path using the\r\npen('path') style, and then calling the fill method. Disconnected\r\npaths can be created using pu() and pd().\r\n\r\nThe play method plays a sequence of notes specified using a subset of\r\nstandard ABC notation. Capital C denotes middle C, and lowercase c is\r\nan octave higher. Pitches and durations can be altered with commas,\r\napostrophes, carets, underscores, digits, and slashes as in the\r\nstandard. Enclosing letters in square brackets represents a chord,\r\nand z represents a rest. The default tempo is 120, but can be changed\r\nby passing a options object as the first parameter setting tempo, e.g.,\r\n{ tempo: 200 }. Other options include volume: 0.5, type: 'sine' or\r\n'square' or 'sawtooth' or 'triangle', and envelope: which defines\r\nan ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }.\r\n\r\nThe turtle's motion will pause while it is playing notes. To play\r\nnotes without stalling turtle movement, use the global function sound()\r\ninstead of the turtle method play().\r\n\r\nThe direct method can be used to queue logic (including synchronous\r\ntests or actions) by running a function in the animation queue. Unlike\r\njquery queue(), direct arranges things so that if further animations\r\nare queued by the callback function, they are inserted (in natural\r\nrecursive functional execution order) instead of being appended.\r\n\r\nThe turnto method can turn to an absolute bearing (if called with a\r\nsingle numeric argument) or towards an absolute position on the\r\nscreen. The methods moveto and turnto accept either page or\r\ngraphing coordinates.\r\n\r\nGraphing coordinates are measured upwards and rightwards from the\r\ncenter of the page, and they are specified as bare numeric x, y\r\narguments or [x, y] pairs as returned from getxy().\r\n\r\nPage coordinates are specified by an object with pageX and pageY\r\nproperties, or with a pagexy() method that will return such an object.\r\nThat includes, usefullly, mouse events and turtle objects. Page\r\ncoordinates are measured downward from the top-left corner of the\r\npage to the center (or transform-origin) of the given object.\r\n\r\nThe hit-testing functions touches() and enclosedby() will test for\r\ncollisions using the convex hulls of the objects in question.\r\nThe hull of an element defaults to the bounding box of the element\r\n(as transformed) but can be overridden by the turtleHull CSS property,\r\nif present. The default turtle is given a turtle-shaped hull.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nA default turtle together with an interactive console are created by\r\ncalling eval($.turtle()). That call exposes all the turtle methods\r\nsuch as (fd, rt, getxy, etc) as global functions operating on the default\r\nturtle. It will also set up a number of other global symbols to provide\r\nbeginners with a simplified programming environment.\r\n\r\nIn detail, after eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * Global event listeners are created to update global event variables.\r\n * Methods of $.turtle.* (enumerated below) are exposed as global functions.\r\n * String constants are defined for the 140 named CSS colors.\r\n\r\nBeyond the functions to control the default turtle, the globals added by\r\n$.turtle() are as follows:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  hatch([n,] [img])     // Creates and returns n turtles with the given img.\r\n  cs()                  // Clears the screen, both the canvas and the body text.\r\n  cg()                  // Clears the graphics canvas without clearing the text.\r\n  ct()                  // Clears the text without clearing the canvas.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0..n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  write(html)           // Appends html into the document body.\r\n  read([label,] fn)     // Makes a one-time input field, calls fn after entry.\r\n  readnum([label,] fn)  // Like read, but restricted to numeric input.\r\n  readstr([label,] fn)  // Like read, but never converts input to a number.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(m, n)           // Outputs a table with m rows and n columns.\r\n  sound('[DFG][EGc]')   // Plays musical notes now, without queueing.\r\n
    \r\n\r\nHere is another CoffeeScript example that demonstrates some of\r\nthe functions:\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle and global functions.\r\n\r\n  defaultspeed Infinity\r\n  write \"Catch blue before red gets you.\"\r\n  bk 100\r\n  r = hatch 'red'\r\n  b = hatch 'blue'\r\n  tick 10, ->\r\n    turnto lastmousemove\r\n    fd 6\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto bearing b\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      write \"You win!\"\r\n      tick off\r\n    else if r.touches(turtle)\r\n      write \"Red got you!\"\r\n      tick off\r\n    else if not b.touches(document)\r\n      write \"Blue got away!\"\r\n      tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nUnderlying turtle motion are turtle-oriented 2d transform jQuery cssHooks,\r\nwith animation support on all motion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30px');   // x component.\r\n  $(x).css('turtlePositionY', '40px');   // y component.\r\n  $(x).css('turtleRotation', '90deg');   // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45deg');      // turn before stretching.\r\n  $(x).css('turtleForward', '50px');     // position in direction of rotation.\r\n  $(x).css('turtleTurningRadius, '50px');// arc turning radius for rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. For example, arc\r\npaths of a turtle within a skewed div will transform to the proper elliptical\r\narc. Note that while turtle motion is transformed, lines and dots are not:\r\nfor example, dots are always circular. To get transformed circles, trace\r\nout an arc.\r\n\r\nTransforms on the turtle itself are used to infer the turtle position,\r\ndirection, and rendering of the sprite. ScaleY stretches the turtle\r\nsprite in the direction of movement also stretches distances for\r\nmotion in all directions. ScaleX stretches the turtle sprite perpendicular\r\nto the direction of motion and also stretches line and dot widths for\r\ndrawing.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (enclosedby, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css index c6a6452..e65cedf 100644 --- a/stylesheets/pygment_trac.css +++ b/stylesheets/pygment_trac.css @@ -1,64 +1,65 @@ -.highlight { background: #ffffff; } -.highlight .c { color: #999988; font-style: italic } /* Comment */ -.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ -.highlight .k { font-weight: bold } /* Keyword */ -.highlight .o { font-weight: bold } /* Operator */ -.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ -.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ -.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ -.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f0f3f3; } +.highlight .c { color: #0099FF; font-style: italic } /* Comment */ +.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */ +.highlight .k { color: #006699; font-weight: bold } /* Keyword */ +.highlight .o { color: #555555 } /* Operator */ +.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #009999 } /* Comment.Preproc */ +.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #aa0000 } /* Generic.Error */ -.highlight .gh { color: #999999 } /* Generic.Heading */ -.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ -.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ -.highlight .go { color: #888888 } /* Generic.Output */ -.highlight .gp { color: #555555 } /* Generic.Prompt */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */ +.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ +.highlight .go { color: #AAAAAA } /* Generic.Output */ +.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */ -.highlight .gt { color: #aa0000 } /* Generic.Traceback */ -.highlight .kc { font-weight: bold } /* Keyword.Constant */ -.highlight .kd { font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { font-weight: bold } /* Keyword.Pseudo */ -.highlight .kr { font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ -.highlight .m { color: #009999 } /* Literal.Number */ -.highlight .s { color: #d14 } /* Literal.String */ -.highlight .na { color: #008080 } /* Name.Attribute */ -.highlight .nb { color: #0086B3 } /* Name.Builtin */ -.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ -.highlight .no { color: #008080 } /* Name.Constant */ -.highlight .ni { color: #800080 } /* Name.Entity */ -.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ -.highlight .nn { color: #555555 } /* Name.Namespace */ -.highlight .nt { color: #000080 } /* Name.Tag */ -.highlight .nv { color: #008080 } /* Name.Variable */ -.highlight .ow { font-weight: bold } /* Operator.Word */ +.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #99CC66 } /* Generic.Traceback */ +.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #006699 } /* Keyword.Pseudo */ +.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #FF6600 } /* Literal.Number */ +.highlight .s { color: #CC3300 } /* Literal.String */ +.highlight .na { color: #330099 } /* Name.Attribute */ +.highlight .nb { color: #336666 } /* Name.Builtin */ +.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */ +.highlight .no { color: #336600 } /* Name.Constant */ +.highlight .nd { color: #9999FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #CC00FF } /* Name.Function */ +.highlight .nl { color: #9999FF } /* Name.Label */ +.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #003333 } /* Name.Variable */ +.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mf { color: #009999 } /* Literal.Number.Float */ -.highlight .mh { color: #009999 } /* Literal.Number.Hex */ -.highlight .mi { color: #009999 } /* Literal.Number.Integer */ -.highlight .mo { color: #009999 } /* Literal.Number.Oct */ -.highlight .sb { color: #d14 } /* Literal.String.Backtick */ -.highlight .sc { color: #d14 } /* Literal.String.Char */ -.highlight .sd { color: #d14 } /* Literal.String.Doc */ -.highlight .s2 { color: #d14 } /* Literal.String.Double */ -.highlight .se { color: #d14 } /* Literal.String.Escape */ -.highlight .sh { color: #d14 } /* Literal.String.Heredoc */ -.highlight .si { color: #d14 } /* Literal.String.Interpol */ -.highlight .sx { color: #d14 } /* Literal.String.Other */ -.highlight .sr { color: #009926 } /* Literal.String.Regex */ -.highlight .s1 { color: #d14 } /* Literal.String.Single */ -.highlight .ss { color: #990073 } /* Literal.String.Symbol */ -.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #008080 } /* Name.Variable.Class */ -.highlight .vg { color: #008080 } /* Name.Variable.Global */ -.highlight .vi { color: #008080 } /* Name.Variable.Instance */ -.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ +.highlight .mf { color: #FF6600 } /* Literal.Number.Float */ +.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */ +.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */ +.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */ +.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */ +.highlight .sc { color: #CC3300 } /* Literal.String.Char */ +.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #CC3300 } /* Literal.String.Double */ +.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */ +.highlight .si { color: #AA0000 } /* Literal.String.Interpol */ +.highlight .sx { color: #CC3300 } /* Literal.String.Other */ +.highlight .sr { color: #33AAAA } /* Literal.String.Regex */ +.highlight .s1 { color: #CC3300 } /* Literal.String.Single */ +.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */ +.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #003333 } /* Name.Variable.Class */ +.highlight .vg { color: #003333 } /* Name.Variable.Global */ +.highlight .vi { color: #003333 } /* Name.Variable.Instance */ +.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */ .type-csharp .highlight .k { color: #0000FF } .type-csharp .highlight .kt { color: #0000FF } diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css new file mode 100644 index 0000000..b48c8a8 --- /dev/null +++ b/stylesheets/stylesheet.css @@ -0,0 +1,427 @@ +/******************************************************************************* +Slate Theme for GitHub Pages +by Jason Costello, @jsncostello +*******************************************************************************/ + +@import url(pygment_trac.css); + +/******************************************************************************* +MeyerWeb Reset +*******************************************************************************/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +ol, ul { + list-style: none; +} + +blockquote, q { +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +/******************************************************************************* +Theme Styles +*******************************************************************************/ + +body { + box-sizing: border-box; + color:#373737; + background: #212121; + font-size: 16px; + font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif; + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +h1, h2, h3, h4, h5, h6 { + margin: 10px 0; + font-weight: 700; + color:#222222; + font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif; + letter-spacing: -1px; +} + +h1 { + font-size: 36px; + font-weight: 700; +} + +h2 { + padding-bottom: 10px; + font-size: 32px; + background: url('../images/bg_hr.png') repeat-x bottom; +} + +h3 { + font-size: 24px; +} + +h4 { + font-size: 21px; +} + +h5 { + font-size: 18px; +} + +h6 { + font-size: 16px; +} + +p { + margin: 10px 0 15px 0; +} + +footer p { + color: #f2f2f2; +} + +a { + text-decoration: none; + color: #007edf; + text-shadow: none; + + transition: color 0.5s ease; + transition: text-shadow 0.5s ease; + -webkit-transition: color 0.5s ease; + -webkit-transition: text-shadow 0.5s ease; + -moz-transition: color 0.5s ease; + -moz-transition: text-shadow 0.5s ease; + -o-transition: color 0.5s ease; + -o-transition: text-shadow 0.5s ease; + -ms-transition: color 0.5s ease; + -ms-transition: text-shadow 0.5s ease; +} + +#main_content a:hover { + color: #0069ba; + text-shadow: #0090ff 0px 0px 2px; +} + +footer a:hover { + color: #43adff; + text-shadow: #0090ff 0px 0px 2px; +} + +em { + font-style: italic; +} + +strong { + font-weight: bold; +} + +img { + position: relative; + margin: 0 auto; + max-width: 739px; + padding: 5px; + margin: 10px 0 10px 0; + border: 1px solid #ebebeb; + + box-shadow: 0 0 5px #ebebeb; + -webkit-box-shadow: 0 0 5px #ebebeb; + -moz-box-shadow: 0 0 5px #ebebeb; + -o-box-shadow: 0 0 5px #ebebeb; + -ms-box-shadow: 0 0 5px #ebebeb; +} + +pre, code { + width: 100%; + color: #222; + background-color: #fff; + + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; + font-size: 14px; + + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + + + +} + +pre { + width: 100%; + padding: 10px; + box-shadow: 0 0 10px rgba(0,0,0,.1); + overflow: auto; +} + +code { + padding: 3px; + margin: 0 3px; + box-shadow: 0 0 10px rgba(0,0,0,.1); +} + +pre code { + display: block; + box-shadow: none; +} + +blockquote { + color: #666; + margin-bottom: 20px; + padding: 0 0 0 20px; + border-left: 3px solid #bbb; +} + +ul, ol, dl { + margin-bottom: 15px +} + +ul li { + list-style: inside; + padding-left: 20px; +} + +ol li { + list-style: decimal inside; + padding-left: 20px; +} + +dl dt { + font-weight: bold; +} + +dl dd { + padding-left: 20px; + font-style: italic; +} + +dl p { + padding-left: 20px; + font-style: italic; +} + +hr { + height: 1px; + margin-bottom: 5px; + border: none; + background: url('../images/bg_hr.png') repeat-x center; +} + +table { + border: 1px solid #373737; + margin-bottom: 20px; + text-align: left; + } + +th { + font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif; + padding: 10px; + background: #373737; + color: #fff; + } + +td { + padding: 10px; + border: 1px solid #373737; + } + +form { + background: #f2f2f2; + padding: 20px; +} + +img { + width: 100%; + max-width: 100%; +} + +/******************************************************************************* +Full-Width Styles +*******************************************************************************/ + +.outer { + width: 100%; +} + +.inner { + position: relative; + max-width: 640px; + padding: 20px 10px; + margin: 0 auto; +} + +#forkme_banner { + display: block; + position: absolute; + top:0; + right: 10px; + z-index: 10; + padding: 10px 50px 10px 10px; + color: #fff; + background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%; + font-weight: 700; + box-shadow: 0 0 10px rgba(0,0,0,.5); + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} + +#header_wrap { + background: #212121; + background: -moz-linear-gradient(top, #373737, #212121); + background: -webkit-linear-gradient(top, #373737, #212121); + background: -ms-linear-gradient(top, #373737, #212121); + background: -o-linear-gradient(top, #373737, #212121); + background: linear-gradient(top, #373737, #212121); +} + +#header_wrap .inner { + padding: 50px 10px 30px 10px; +} + +#project_title { + margin: 0; + color: #fff; + font-size: 42px; + font-weight: 700; + text-shadow: #111 0px 0px 10px; +} + +#project_tagline { + color: #fff; + font-size: 24px; + font-weight: 300; + background: none; + text-shadow: #111 0px 0px 10px; +} + +#downloads { + position: absolute; + width: 210px; + z-index: 10; + bottom: -40px; + right: 0; + height: 70px; + background: url('../images/icon_download.png') no-repeat 0% 90%; +} + +.zip_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom left; +} + +.tar_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom right; + margin-left: 10px; +} + +.zip_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top left; +} + +.tar_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top right; +} + +#main_content_wrap { + background: #f2f2f2; + border-top: 1px solid #111; + border-bottom: 1px solid #111; +} + +#main_content { + padding-top: 40px; +} + +#footer_wrap { + background: #212121; +} + + + +/******************************************************************************* +Small Device Styles +*******************************************************************************/ + +@media screen and (max-width: 480px) { + body { + font-size:14px; + } + + #downloads { + display: none; + } + + .inner { + min-width: 320px; + max-width: 480px; + } + + #project_title { + font-size: 32px; + } + + h1 { + font-size: 28px; + } + + h2 { + font-size: 24px; + } + + h3 { + font-size: 21px; + } + + h4 { + font-size: 18px; + } + + h5 { + font-size: 14px; + } + + h6 { + font-size: 12px; + } + + code, pre { + min-width: 320px; + max-width: 480px; + font-size: 11px; + } + +} From 2a251ada155e501e54acaf2c5d39974e6aceae54 Mon Sep 17 00:00:00 2001 From: davidbau Date: Mon, 19 Aug 2013 03:31:19 -0700 Subject: [PATCH 24/25] Create gh-pages branch via GitHub --- index.html | 268 ++++++++++++++++++++++++++++------------------------ params.json | 2 +- 2 files changed, 145 insertions(+), 125 deletions(-) diff --git a/index.html b/index.html index a5de46b..c0fac65 100644 --- a/index.html +++ b/index.html @@ -44,7 +44,7 @@

    a turtle to draw on a full-document canvas as it moves.

    -  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();
    +$('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();
     

    jQuery-turtle provides:

    @@ -62,18 +62,18 @@

    sixteen colored polygons.

    -  eval $.turtle()  # Create the default turtle.
    -
    -  speed 100
    -  for color in [red, gold, green, blue]
    -    for sides in [3..6]
    -      pen color
    -      for x in [1..sides]
    -        fd 100 / sides
    -        lt 360 / sides
    -      pen null 
    -      fd 40
    -    slide 40, -160
    +eval $.turtle()  # Create the default turtle.
    +
    +speed 100
    +for color in [red, gold, green, blue]
    +  for sides in [3..6]
    +    pen color
    +    for x in [1..sides]
    +      fd 100 / sides
    +      lt 360 / sides
    +    pen null
    +    fd 40
    +  slide 40, -160
     

    Try an interactive demo (CoffeeScript syntax) here.

    @@ -86,53 +86,55 @@

    the default turtle, if used):

    -  $(x).fd(100)      // Forward relative motion in local coordinates.
    -  $(x).bk(50)       // Back.
    -  $(x).rt(90)       // Right turn.
    -  $(x).lt(45)       // Left turn.
    -  $(x).slide(x, y)  // Move right by x while moving forward by y.
    -  $(x).rarc(100,60) // Turn right 60 degrees tracing an arc of radius 100.
    -  $(x).larc(50,360) // Left 360 degrees tracing a full circle of radius 50.
    -  $(x).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.
    -  $(x).turnto(bearing || position)        // Absolute direction adjustment.
    -  $(x).play("ccgg") // Plays notes using ABC notation and waits until done.
    -
    -  // Methods below happen in an instant, but line up in the animation queue.
    -  $(x).home()       // Jumps to the center of the document, with bearing 0.
    -  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.
    -  $(x).pu()         // Pen up - temporarily disables the pen (also pen(false)).
    -  $(x).pd()         // Pen down - starts a new pen path.
    -  $(x).pe()         // Uses the pen 'erase' style.
    -  $(x).fill('gold') // Fills a shape previously outlined using pen('path').
    -  $(x).dot(12)      // Draws a circular dot of diameter 12.
    -  $(x).label('A')   // Prints an HTML label at the turtle location.
    -  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.
    -  $(x).ht()         // Hides the turtle.
    -  $(x).st()         // Shows the turtle.
    -  $(x).wear('blue') // Switches to a blue shell.  Use any image or color.
    -  $(x).scale(1.5)   // Scales turtle size and motion by 150%.
    -  $(x).twist(180)   // Changes which direction is considered "forward".
    -  $(x).mirror(true) // Flips the turtle across its main axis.
    -  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)
    -  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,
    -                    // and the callback fn can insert into the animation queue.
    -
    -  // Methods below this line do not queue for animation.
    -  $(x).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.
    -  $(x).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.
    -  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).
    -  $(x).distance(p)  // Distance to p in page coordinates.
    -  $(x).shown()      // Shorthand for is(":visible")
    -  $(x).hidden()     // Shorthand for !is(":visible")
    -  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).
    -  $(x).enclosedby(y)// Containment collision test.
    -  $(x).within(d, t) // Filters to items with centers within d of t.pagexy().
    -  $(x).notwithin()  // The negation of within.
    -  $(x).cell(y, x)   // Selects the yth row and xth column cell in a table.
    -  $(x).hatch([n,] [img]) // Creates and returns n turtles with the given img.
    +$(q).fd(100)      // Forward relative motion in local coordinates.
    +$(q).bk(50)       // Back.
    +$(q).rt(90)       // Right turn.  Optional turning radius second arg.
    +$(q).lt(45)       // Left turn.  Optional turning radius second arg.
    +$(q).slide(x, y)  // Slide right by x while sliding forward by y.
    +$(q).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.
    +$(q).jumpto({pageX:x,pageY:y} | [x,y])  // Like moveto, without drawing.
    +$(q).turnto(bearing || position)        // Absolute direction adjustment.
    +$(q).play("ccgg") // Plays notes using ABC notation and waits until done.
    +
    +// Methods below happen in an instant, but line up in the animation queue.
    +$(q).home()       // Jumps to the center of the document, with bearing 0.
    +$(q).pen('red')   // Sets a pen style, or 'none' for no drawing.
    +$(q).pu()         // Pen up - temporarily disables the pen (also pen(false)).
    +$(q).pd()         // Pen down - starts a new pen path.
    +$(q).pe()         // Uses the pen 'erase' style.
    +$(q).fill('gold') // Fills a shape previously outlined using pen('path').
    +$(q).dot(12)      // Draws a circular dot of diameter 12.  Color second arg.
    +$(q).label('A')   // Prints an HTML label at the turtle location.
    +$(q).speed(10)    // Sets turtle animation speed to 10 moves per sec.
    +$(q).ht()         // Hides the turtle.
    +$(q).st()         // Shows the turtle.
    +$(q).wear('blue') // Switches to a blue shell.  Use any image or color.
    +$(q).scale(1.5)   // Scales turtle size and motion by 150%.
    +$(q).twist(180)   // Changes which direction is considered "forward".
    +$(q).mirror(true) // Flips the turtle across its main axis.
    +$(q).reload()     // Reloads the turtle's image (restarting animated gifs)
    +$(q).direct(fn)   // Like each, but this is set to $(elt) instead of elt,
    +                  // and the callback fn can insert into the animation queue.
    +
    +// Methods below this line do not queue for animation.
    +$(q).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.
    +$(q).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.
    +$(q).bearing([p]) // The turtles absolute direction (or direction towards p).
    +$(q).distance(p)  // Distance to p in page coordinates.
    +$(q).shown()      // Shorthand for is(":visible")
    +$(q).hidden()     // Shorthand for !is(":visible")
    +$(q).touches(y)   // Collision tests elements (uses turtleHull if present).
    +$(q).enclosedby(y)// Containment collision test.
    +$(q).within(d, t) // Filters to items with centers within d of t.pagexy().
    +$(q).notwithin()  // The negation of within.
    +$(q).cell(y, x)   // Selects the yth row and xth column cell in a table.
    +$(q).hatch([n,] [img]) // Creates and returns n turtles with the given img.
     
    -

    When the speed of a turtle is nonzero, the first seven movement +

    +Speed and Turtle Animation

    + +

    When the speed of a turtle is nonzero, the first eight movement functions animate at that speed (in moves per second), and the remaining mutators also participate in the animation queue. The default turtle speed is a leisurely one move per second (as @@ -143,6 +145,9 @@

    which makes the synchronous distance, direction, and hit-testing useful for realtime game-making.

    +

    +Pen and Fill Styles

    +

    The turtle pen respects canvas styling: any valid strokeStyle is accepted; and also using a space-separated syntax, lineWidth, lineCap, lineJoin, miterLimit, and fillStyle can be specified, e.g., @@ -154,6 +159,9 @@

    pen('path') style, and then calling the fill method. Disconnected paths can be created using pu() and pd().

    +

    +Conventions for Musical Notes

    +

    The play method plays a sequence of notes specified using a subset of standard ABC notation. Capital C denotes middle C, and lowercase c is an octave higher. Pitches and durations can be altered with commas, @@ -169,17 +177,26 @@

    notes without stalling turtle movement, use the global function sound() instead of the turtle method play().

    +

    +Directing Logic in the Animation Queue

    +

    The direct method can be used to queue logic (including synchronous tests or actions) by running a function in the animation queue. Unlike jquery queue(), direct arranges things so that if further animations are queued by the callback function, they are inserted (in natural recursive functional execution order) instead of being appended.

    +

    +Turnto and Absolute Bearings

    +

    The turnto method can turn to an absolute bearing (if called with a single numeric argument) or towards an absolute position on the screen. The methods moveto and turnto accept either page or graphing coordinates.

    +

    +Moveto and Two Flavors of Cartesian Coordinates

    +

    Graphing coordinates are measured upwards and rightwards from the center of the page, and they are specified as bare numeric x, y arguments or [x, y] pairs as returned from getxy().

    @@ -190,6 +207,9 @@

    coordinates are measured downward from the top-left corner of the page to the center (or transform-origin) of the given object.

    +

    +Hit Testing

    +

    The hit-testing functions touches() and enclosedby() will test for collisions using the convex hulls of the objects in question. The hull of an element defaults to the bounding box of the element @@ -220,64 +240,64 @@

    $.turtle() are as follows:

    -  lastclick             // Event object of the last click event in the doc.
    -  lastmousemove         // The last mousemove event.
    -  lastmouseup           // The last mouseup event.
    -  lastmousedown         // The last mousedown event.
    -  keydown               // The last keydown event.
    -  keyup                 // The last keyup event.
    -  keypress              // The last keypress event.
    -  hatch([n,] [img])     // Creates and returns n turtles with the given img.
    -  cs()                  // Clears the screen, both the canvas and the body text.
    -  cg()                  // Clears the graphics canvas without clearing the text.
    -  ct()                  // Clears the text without clearing the canvas.
    -  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.
    -  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).
    -  random(n)             // Returns a random number [0..n-1].
    -  random(list)          // Returns a random element of the list.
    -  random('normal')      // Returns a gaussian random (mean 0 stdev 1).
    -  random('uniform')     // Returns a uniform random [0...1).
    -  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.
    -  random('color')       // Returns a random hsl(*, 100%, 50%) color.
    -  random('gray')        // Returns a random hsl(0, 0, *) gray.
    -  remove()              // Removes default turtle and its globals (fd, etc).
    -  see(a, b, c...)       // Logs tree-expandable data into debugging panel.
    -  write(html)           // Appends html into the document body.
    -  read([label,] fn)     // Makes a one-time input field, calls fn after entry.
    -  readnum([label,] fn)  // Like read, but restricted to numeric input.
    -  readstr([label,] fn)  // Like read, but never converts input to a number.
    -  button([label,] fn)   // Makes a clickable button, calls fn when clicked.
    -  table(m, n)           // Outputs a table with m rows and n columns.
    -  sound('[DFG][EGc]')   // Plays musical notes now, without queueing.
    +lastclick             // Event object of the last click event in the doc.
    +lastmousemove         // The last mousemove event.
    +lastmouseup           // The last mouseup event.
    +lastmousedown         // The last mousedown event.
    +keydown               // The last keydown event.
    +keyup                 // The last keyup event.
    +keypress              // The last keypress event.
    +hatch([n,] [img])     // Creates and returns n turtles with the given img.
    +cs()                  // Clears the screen, both the canvas and the body text.
    +cg()                  // Clears the graphics canvas without clearing the text.
    +ct()                  // Clears the text without clearing the canvas.
    +defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.
    +tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).
    +random(n)             // Returns a random number [0..n-1].
    +random(list)          // Returns a random element of the list.
    +random('normal')      // Returns a gaussian random (mean 0 stdev 1).
    +random('uniform')     // Returns a uniform random [0...1).
    +random('position')    // Returns a random {pageX:x, pageY:y} coordinate.
    +random('color')       // Returns a random hsl(*, 100%, 50%) color.
    +random('gray')        // Returns a random hsl(0, 0, *) gray.
    +remove()              // Removes default turtle and its globals (fd, etc).
    +see(a, b, c...)       // Logs tree-expandable data into debugging panel.
    +write(html)           // Appends html into the document body.
    +read([label,] fn)     // Makes a one-time input field, calls fn after entry.
    +readnum([label,] fn)  // Like read, but restricted to numeric input.
    +readstr([label,] fn)  // Like read, but never converts input to a number.
    +button([label,] fn)   // Makes a clickable button, calls fn when clicked.
    +table(m, n)           // Outputs a table with m rows and n columns.
    +sound('[DFG][EGc]')   // Plays musical notes now, without queueing.
     

    Here is another CoffeeScript example that demonstrates some of the functions:

    -  eval $.turtle()  # Create the default turtle and global functions.
    -
    -  defaultspeed Infinity
    -  write "Catch blue before red gets you."
    -  bk 100
    -  r = hatch 'red'
    -  b = hatch 'blue'
    -  tick 10, ->
    -    turnto lastmousemove
    -    fd 6
    -    r.turnto turtle
    -    r.fd 4
    -    b.turnto bearing b
    -    b.fd 3
    -    if b.touches(turtle)
    -      write "You win!"
    -      tick off
    -    else if r.touches(turtle)
    -      write "Red got you!"
    -      tick off
    -    else if not b.touches(document)
    -      write "Blue got away!"
    -      tick off
    +eval $.turtle()  # Create the default turtle and global functions.
    +
    +defaultspeed Infinity
    +write "Catch blue before red gets you."
    +bk 100
    +r = hatch red
    +b = hatch blue
    +tick 10, ->
    +  turnto lastmousemove
    +  fd 6
    +  r.turnto turtle
    +  r.fd 4
    +  b.turnto bearing b
    +  b.fd 3
    +  if b.touches(turtle)
    +    write "You win!"
    +    tick off
    +  else if r.touches(turtle)
    +    write "Red got you!"
    +    tick off
    +  else if not b.enclosedby(document)
    +    write "Blue got away!"
    +    tick off
     

    The turtle teaching environment is designed to work well with either @@ -290,20 +310,20 @@

    with animation support on all motion:

    -  $(x).css('turtleSpeed', '10');         // default speed in moves per second.
    -  $(x).css('turtlePosition', '30 40');   // position in local coordinates.
    -  $(x).css('turtlePositionX', '30px');   // x component.
    -  $(x).css('turtlePositionY', '40px');   // y component.
    -  $(x).css('turtleRotation', '90deg');   // rotation in degrees.
    -  $(x).css('turtleScale', '2');          // double the size of any element.
    -  $(x).css('turtleScaleX', '2');         // x stretch after twist.
    -  $(x).css('turtleScaleY', '2');         // y stretch after twist.
    -  $(x).css('turtleTwist', '45deg');      // turn before stretching.
    -  $(x).css('turtleForward', '50px');     // position in direction of rotation.
    -  $(x).css('turtleTurningRadius, '50px');// arc turning radius for rotation.
    -  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    -  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
    -  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
    +$(q).css('turtleSpeed', '10');         // default speed in moves per second.
    +$(q).css('turtlePosition', '30 40');   // position in local coordinates.
    +$(q).css('turtlePositionX', '30px');   // x component.
    +$(q).css('turtlePositionY', '40px');   // y component.
    +$(q).css('turtleRotation', '90deg');   // rotation in degrees.
    +$(q).css('turtleScale', '2');          // double the size of any element.
    +$(q).css('turtleScaleX', '2');         // x stretch after twist.
    +$(q).css('turtleScaleY', '2');         // y stretch after twist.
    +$(q).css('turtleTwist', '45deg');      // turn before stretching.
    +$(q).css('turtleForward', '50px');     // position in direction of rotation.
    +$(q).css('turtleTurningRadius, '50px');// arc turning radius for rotation.
    +$(q).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.
    +$(q).css('turtlePenDown', 'up');       // default 'down' to draw with pen.
    +$(q).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.
     

    Arbitrary 2d transforms are supported, including transforms of elements diff --git a/params.json b/params.json index dcfe0a9..fa93323 100644 --- a/params.json +++ b/params.json @@ -1 +1 @@ -{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.7\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using turtle graphics methods like fd (forward), bk (back),\r\nrt (right turn), and lt (left turn). The pen function allows\r\na turtle to draw on a full-document canvas as it moves.\r\n\r\n

    \r\n  $('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\n\r\njQuery-turtle provides:\r\n * Relative and absolute motion and drawing.\r\n * Functions to ease basic input, output, and game-making for beginners.\r\n * Operations on sets of turtles, and turtle motion of arbitrary elements.\r\n * Accurate collision-testing of turtles with arbitrary convex hulls.\r\n * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.\r\n * An interactive turtle console in either Javascript or CoffeeScript.\r\n\r\nThe plugin can also create a learning environment with a default\r\nturtle that is friendly for beginners. The following is a complete\r\nCoffeeScript program that uses the default turtle to draw a grid of\r\nsixteen colored polygons.\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle.\r\n\r\n  speed 100\r\n  for color in [red, gold, green, blue]\r\n    for sides in [3..6]\r\n      pen color\r\n      for x in [1..sides]\r\n        fd 100 / sides\r\n        lt 360 / sides\r\n      pen null \r\n      fd 40\r\n    slide 40, -160\r\n
    \r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nThe turtle API is briefly summarized below. All the following\r\nturtle-oriented methods operate on any jQuery object (including\r\nthe default turtle, if used):\r\n\r\n
    \r\n  $(x).fd(100)      // Forward relative motion in local coordinates.\r\n  $(x).bk(50)       // Back.\r\n  $(x).rt(90)       // Right turn.\r\n  $(x).lt(45)       // Left turn.\r\n  $(x).slide(x, y)  // Move right by x while moving forward by y.\r\n  $(x).rarc(100,60) // Turn right 60 degrees tracing an arc of radius 100.\r\n  $(x).larc(50,360) // Left 360 degrees tracing a full circle of radius 50.\r\n  $(x).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.\r\n  $(x).turnto(bearing || position)        // Absolute direction adjustment.\r\n  $(x).play(\"ccgg\") // Plays notes using ABC notation and waits until done.\r\n\r\n  // Methods below happen in an instant, but line up in the animation queue.\r\n  $(x).home()       // Jumps to the center of the document, with bearing 0.\r\n  $(x).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n  $(x).pu()         // Pen up - temporarily disables the pen (also pen(false)).\r\n  $(x).pd()         // Pen down - starts a new pen path.\r\n  $(x).pe()         // Uses the pen 'erase' style.\r\n  $(x).fill('gold') // Fills a shape previously outlined using pen('path').\r\n  $(x).dot(12)      // Draws a circular dot of diameter 12.\r\n  $(x).label('A')   // Prints an HTML label at the turtle location.\r\n  $(x).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n  $(x).ht()         // Hides the turtle.\r\n  $(x).st()         // Shows the turtle.\r\n  $(x).wear('blue') // Switches to a blue shell.  Use any image or color.\r\n  $(x).scale(1.5)   // Scales turtle size and motion by 150%.\r\n  $(x).twist(180)   // Changes which direction is considered \"forward\".\r\n  $(x).mirror(true) // Flips the turtle across its main axis.\r\n  $(x).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n  $(x).direct(fn)   // Like each, but this is set to $(elt) instead of elt,\r\n                    // and the callback fn can insert into the animation queue.\r\n\r\n  // Methods below this line do not queue for animation.\r\n  $(x).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.\r\n  $(x).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.\r\n  $(x).bearing([p]) // The turtles absolute direction (or direction towards p).\r\n  $(x).distance(p)  // Distance to p in page coordinates.\r\n  $(x).shown()      // Shorthand for is(\":visible\")\r\n  $(x).hidden()     // Shorthand for !is(\":visible\")\r\n  $(x).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n  $(x).enclosedby(y)// Containment collision test.\r\n  $(x).within(d, t) // Filters to items with centers within d of t.pagexy().\r\n  $(x).notwithin()  // The negation of within.\r\n  $(x).cell(y, x)   // Selects the yth row and xth column cell in a table.\r\n  $(x).hatch([n,] [img]) // Creates and returns n turtles with the given img.\r\n
    \r\n\r\nWhen the speed of a turtle is nonzero, the first seven movement\r\nfunctions animate at that speed (in moves per second), and the\r\nremaining mutators also participate in the animation queue. The\r\ndefault turtle speed is a leisurely one move per second (as\r\nappropriate for the creature), but you may soon discover the\r\ndesire to set speed higher.\r\n\r\nSetting the turtle speed to Infinity will make its movement synchronous,\r\nwhich makes the synchronous distance, direction, and hit-testing useful\r\nfor realtime game-making.\r\n\r\nThe turtle pen respects canvas styling: any valid strokeStyle is\r\naccepted; and also using a space-separated syntax, lineWidth, lineCap,\r\nlineJoin, miterLimit, and fillStyle can be specified, e.g.,\r\npen('red lineWidth 5 lineCap square'). The same syntax applies for\r\nstyling dot and fill (except that the default interpretation for the\r\nfirst value is fillStyle instead of strokeStyle).\r\n\r\nThe fill method is used by tracing an invisible path using the\r\npen('path') style, and then calling the fill method. Disconnected\r\npaths can be created using pu() and pd().\r\n\r\nThe play method plays a sequence of notes specified using a subset of\r\nstandard ABC notation. Capital C denotes middle C, and lowercase c is\r\nan octave higher. Pitches and durations can be altered with commas,\r\napostrophes, carets, underscores, digits, and slashes as in the\r\nstandard. Enclosing letters in square brackets represents a chord,\r\nand z represents a rest. The default tempo is 120, but can be changed\r\nby passing a options object as the first parameter setting tempo, e.g.,\r\n{ tempo: 200 }. Other options include volume: 0.5, type: 'sine' or\r\n'square' or 'sawtooth' or 'triangle', and envelope: which defines\r\nan ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }.\r\n\r\nThe turtle's motion will pause while it is playing notes. To play\r\nnotes without stalling turtle movement, use the global function sound()\r\ninstead of the turtle method play().\r\n\r\nThe direct method can be used to queue logic (including synchronous\r\ntests or actions) by running a function in the animation queue. Unlike\r\njquery queue(), direct arranges things so that if further animations\r\nare queued by the callback function, they are inserted (in natural\r\nrecursive functional execution order) instead of being appended.\r\n\r\nThe turnto method can turn to an absolute bearing (if called with a\r\nsingle numeric argument) or towards an absolute position on the\r\nscreen. The methods moveto and turnto accept either page or\r\ngraphing coordinates.\r\n\r\nGraphing coordinates are measured upwards and rightwards from the\r\ncenter of the page, and they are specified as bare numeric x, y\r\narguments or [x, y] pairs as returned from getxy().\r\n\r\nPage coordinates are specified by an object with pageX and pageY\r\nproperties, or with a pagexy() method that will return such an object.\r\nThat includes, usefullly, mouse events and turtle objects. Page\r\ncoordinates are measured downward from the top-left corner of the\r\npage to the center (or transform-origin) of the given object.\r\n\r\nThe hit-testing functions touches() and enclosedby() will test for\r\ncollisions using the convex hulls of the objects in question.\r\nThe hull of an element defaults to the bounding box of the element\r\n(as transformed) but can be overridden by the turtleHull CSS property,\r\nif present. The default turtle is given a turtle-shaped hull.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nA default turtle together with an interactive console are created by\r\ncalling eval($.turtle()). That call exposes all the turtle methods\r\nsuch as (fd, rt, getxy, etc) as global functions operating on the default\r\nturtle. It will also set up a number of other global symbols to provide\r\nbeginners with a simplified programming environment.\r\n\r\nIn detail, after eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * Global event listeners are created to update global event variables.\r\n * Methods of $.turtle.* (enumerated below) are exposed as global functions.\r\n * String constants are defined for the 140 named CSS colors.\r\n\r\nBeyond the functions to control the default turtle, the globals added by\r\n$.turtle() are as follows:\r\n\r\n
    \r\n  lastclick             // Event object of the last click event in the doc.\r\n  lastmousemove         // The last mousemove event.\r\n  lastmouseup           // The last mouseup event.\r\n  lastmousedown         // The last mousedown event.\r\n  keydown               // The last keydown event.\r\n  keyup                 // The last keyup event.\r\n  keypress              // The last keypress event.\r\n  hatch([n,] [img])     // Creates and returns n turtles with the given img.\r\n  cs()                  // Clears the screen, both the canvas and the body text.\r\n  cg()                  // Clears the graphics canvas without clearing the text.\r\n  ct()                  // Clears the text without clearing the canvas.\r\n  defaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\n  tick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\n  random(n)             // Returns a random number [0..n-1].\r\n  random(list)          // Returns a random element of the list.\r\n  random('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\n  random('uniform')     // Returns a uniform random [0...1).\r\n  random('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\n  random('color')       // Returns a random hsl(*, 100%, 50%) color.\r\n  random('gray')        // Returns a random hsl(0, 0, *) gray.\r\n  remove()              // Removes default turtle and its globals (fd, etc).\r\n  see(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\n  write(html)           // Appends html into the document body.\r\n  read([label,] fn)     // Makes a one-time input field, calls fn after entry.\r\n  readnum([label,] fn)  // Like read, but restricted to numeric input.\r\n  readstr([label,] fn)  // Like read, but never converts input to a number.\r\n  button([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\n  table(m, n)           // Outputs a table with m rows and n columns.\r\n  sound('[DFG][EGc]')   // Plays musical notes now, without queueing.\r\n
    \r\n\r\nHere is another CoffeeScript example that demonstrates some of\r\nthe functions:\r\n\r\n
    \r\n  eval $.turtle()  # Create the default turtle and global functions.\r\n\r\n  defaultspeed Infinity\r\n  write \"Catch blue before red gets you.\"\r\n  bk 100\r\n  r = hatch 'red'\r\n  b = hatch 'blue'\r\n  tick 10, ->\r\n    turnto lastmousemove\r\n    fd 6\r\n    r.turnto turtle\r\n    r.fd 4\r\n    b.turnto bearing b\r\n    b.fd 3\r\n    if b.touches(turtle)\r\n      write \"You win!\"\r\n      tick off\r\n    else if r.touches(turtle)\r\n      write \"Red got you!\"\r\n      tick off\r\n    else if not b.touches(document)\r\n      write \"Blue got away!\"\r\n      tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nUnderlying turtle motion are turtle-oriented 2d transform jQuery cssHooks,\r\nwith animation support on all motion:\r\n\r\n
    \r\n  $(x).css('turtleSpeed', '10');         // default speed in moves per second.\r\n  $(x).css('turtlePosition', '30 40');   // position in local coordinates.\r\n  $(x).css('turtlePositionX', '30px');   // x component.\r\n  $(x).css('turtlePositionY', '40px');   // y component.\r\n  $(x).css('turtleRotation', '90deg');   // rotation in degrees.\r\n  $(x).css('turtleScale', '2');          // double the size of any element.\r\n  $(x).css('turtleScaleX', '2');         // x stretch after twist.\r\n  $(x).css('turtleScaleY', '2');         // y stretch after twist.\r\n  $(x).css('turtleTwist', '45deg');      // turn before stretching.\r\n  $(x).css('turtleForward', '50px');     // position in direction of rotation.\r\n  $(x).css('turtleTurningRadius, '50px');// arc turning radius for rotation.\r\n  $(x).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n  $(x).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n  $(x).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. For example, arc\r\npaths of a turtle within a skewed div will transform to the proper elliptical\r\narc. Note that while turtle motion is transformed, lines and dots are not:\r\nfor example, dots are always circular. To get transformed circles, trace\r\nout an arc.\r\n\r\nTransforms on the turtle itself are used to infer the turtle position,\r\ndirection, and rendering of the sprite. ScaleY stretches the turtle\r\nsprite in the direction of movement also stretches distances for\r\nmotion in all directions. ScaleX stretches the turtle sprite perpendicular\r\nto the direction of motion and also stretches line and dot widths for\r\ndrawing.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (enclosedby, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file +{"name":"jQuery-turtle","tagline":"Turtle Graphics for JQuery","body":"jQuery-turtle\r\n=============\r\n\r\nversion 2.0.7\r\n\r\njQuery-turtle is a jQuery plugin for turtle graphics.\r\n\r\nWith jQuery-turtle, every DOM element is a turtle that can be\r\nmoved using turtle graphics methods like fd (forward), bk (back),\r\nrt (right turn), and lt (left turn). The pen function allows\r\na turtle to draw on a full-document canvas as it moves.\r\n\r\n
    \r\n$('#turtle').pen('red').rt(90).fd(100).lt(90).bk(50).fadeOut();\r\n
    \r\n\r\njQuery-turtle provides:\r\n * Relative and absolute motion and drawing.\r\n * Functions to ease basic input, output, and game-making for beginners.\r\n * Operations on sets of turtles, and turtle motion of arbitrary elements.\r\n * Accurate collision-testing of turtles with arbitrary convex hulls.\r\n * Simplified access to CSS3 transforms, jQuery animations, Canvas, and Web Audio.\r\n * An interactive turtle console in either Javascript or CoffeeScript.\r\n\r\nThe plugin can also create a learning environment with a default\r\nturtle that is friendly for beginners. The following is a complete\r\nCoffeeScript program that uses the default turtle to draw a grid of\r\nsixteen colored polygons.\r\n\r\n
    \r\neval $.turtle()  # Create the default turtle.\r\n\r\nspeed 100\r\nfor color in [red, gold, green, blue]\r\n  for sides in [3..6]\r\n    pen color\r\n    for x in [1..sides]\r\n      fd 100 / sides\r\n      lt 360 / sides\r\n    pen null\r\n    fd 40\r\n  slide 40, -160\r\n
    \r\n\r\n[Try an interactive demo (CoffeeScript syntax) here.](\r\nhttp://davidbau.github.io/jquery-turtle/demo.html)\r\n\r\n\r\nJQuery Methods for Turtle Movement\r\n----------------------------------\r\n\r\nThe turtle API is briefly summarized below. All the following\r\nturtle-oriented methods operate on any jQuery object (including\r\nthe default turtle, if used):\r\n\r\n
    \r\n$(q).fd(100)      // Forward relative motion in local coordinates.\r\n$(q).bk(50)       // Back.\r\n$(q).rt(90)       // Right turn.  Optional turning radius second arg.\r\n$(q).lt(45)       // Left turn.  Optional turning radius second arg.\r\n$(q).slide(x, y)  // Slide right by x while sliding forward by y.\r\n$(q).moveto({pageX:x,pageY:y} | [x,y])  // Absolute motion on page.\r\n$(q).jumpto({pageX:x,pageY:y} | [x,y])  // Like moveto, without drawing.\r\n$(q).turnto(bearing || position)        // Absolute direction adjustment.\r\n$(q).play(\"ccgg\") // Plays notes using ABC notation and waits until done.\r\n\r\n// Methods below happen in an instant, but line up in the animation queue.\r\n$(q).home()       // Jumps to the center of the document, with bearing 0.\r\n$(q).pen('red')   // Sets a pen style, or 'none' for no drawing.\r\n$(q).pu()         // Pen up - temporarily disables the pen (also pen(false)).\r\n$(q).pd()         // Pen down - starts a new pen path.\r\n$(q).pe()         // Uses the pen 'erase' style.\r\n$(q).fill('gold') // Fills a shape previously outlined using pen('path').\r\n$(q).dot(12)      // Draws a circular dot of diameter 12.  Color second arg.\r\n$(q).label('A')   // Prints an HTML label at the turtle location.\r\n$(q).speed(10)    // Sets turtle animation speed to 10 moves per sec.\r\n$(q).ht()         // Hides the turtle.\r\n$(q).st()         // Shows the turtle.\r\n$(q).wear('blue') // Switches to a blue shell.  Use any image or color.\r\n$(q).scale(1.5)   // Scales turtle size and motion by 150%.\r\n$(q).twist(180)   // Changes which direction is considered \"forward\".\r\n$(q).mirror(true) // Flips the turtle across its main axis.\r\n$(q).reload()     // Reloads the turtle's image (restarting animated gifs)\r\n$(q).direct(fn)   // Like each, but this is set to $(elt) instead of elt,\r\n                  // and the callback fn can insert into the animation queue.\r\n\r\n// Methods below this line do not queue for animation.\r\n$(q).getxy()      // Local (center-y-up [x, y]) coordinates of the turtle.\r\n$(q).pagexy()     // Page (topleft-y-down {pageX:x, pageY:y}) coordinates.\r\n$(q).bearing([p]) // The turtles absolute direction (or direction towards p).\r\n$(q).distance(p)  // Distance to p in page coordinates.\r\n$(q).shown()      // Shorthand for is(\":visible\")\r\n$(q).hidden()     // Shorthand for !is(\":visible\")\r\n$(q).touches(y)   // Collision tests elements (uses turtleHull if present).\r\n$(q).enclosedby(y)// Containment collision test.\r\n$(q).within(d, t) // Filters to items with centers within d of t.pagexy().\r\n$(q).notwithin()  // The negation of within.\r\n$(q).cell(y, x)   // Selects the yth row and xth column cell in a table.\r\n$(q).hatch([n,] [img]) // Creates and returns n turtles with the given img.\r\n
    \r\n\r\n\r\nSpeed and Turtle Animation\r\n--------------------------\r\n\r\nWhen the speed of a turtle is nonzero, the first eight movement\r\nfunctions animate at that speed (in moves per second), and the\r\nremaining mutators also participate in the animation queue. The\r\ndefault turtle speed is a leisurely one move per second (as\r\nappropriate for the creature), but you may soon discover the\r\ndesire to set speed higher.\r\n\r\nSetting the turtle speed to Infinity will make its movement synchronous,\r\nwhich makes the synchronous distance, direction, and hit-testing useful\r\nfor realtime game-making.\r\n\r\nPen and Fill Styles\r\n-------------------\r\n\r\nThe turtle pen respects canvas styling: any valid strokeStyle is\r\naccepted; and also using a space-separated syntax, lineWidth, lineCap,\r\nlineJoin, miterLimit, and fillStyle can be specified, e.g.,\r\npen('red lineWidth 5 lineCap square'). The same syntax applies for\r\nstyling dot and fill (except that the default interpretation for the\r\nfirst value is fillStyle instead of strokeStyle).\r\n\r\nThe fill method is used by tracing an invisible path using the\r\npen('path') style, and then calling the fill method. Disconnected\r\npaths can be created using pu() and pd().\r\n\r\nConventions for Musical Notes\r\n-----------------------------\r\n\r\nThe play method plays a sequence of notes specified using a subset of\r\nstandard ABC notation. Capital C denotes middle C, and lowercase c is\r\nan octave higher. Pitches and durations can be altered with commas,\r\napostrophes, carets, underscores, digits, and slashes as in the\r\nstandard. Enclosing letters in square brackets represents a chord,\r\nand z represents a rest. The default tempo is 120, but can be changed\r\nby passing a options object as the first parameter setting tempo, e.g.,\r\n{ tempo: 200 }. Other options include volume: 0.5, type: 'sine' or\r\n'square' or 'sawtooth' or 'triangle', and envelope: which defines\r\nan ADSR envelope e.g., { a: 0.01, d: 0.2, s: 0.1, r: 0.1 }.\r\n\r\nThe turtle's motion will pause while it is playing notes. To play\r\nnotes without stalling turtle movement, use the global function sound()\r\ninstead of the turtle method play().\r\n\r\nDirecting Logic in the Animation Queue\r\n--------------------------------------\r\n\r\nThe direct method can be used to queue logic (including synchronous\r\ntests or actions) by running a function in the animation queue. Unlike\r\njquery queue(), direct arranges things so that if further animations\r\nare queued by the callback function, they are inserted (in natural\r\nrecursive functional execution order) instead of being appended.\r\n\r\nTurnto and Absolute Bearings\r\n----------------------------\r\n\r\nThe turnto method can turn to an absolute bearing (if called with a\r\nsingle numeric argument) or towards an absolute position on the\r\nscreen. The methods moveto and turnto accept either page or\r\ngraphing coordinates.\r\n\r\nMoveto and Two Flavors of Cartesian Coordinates\r\n-----------------------------------------------\r\n\r\nGraphing coordinates are measured upwards and rightwards from the\r\ncenter of the page, and they are specified as bare numeric x, y\r\narguments or [x, y] pairs as returned from getxy().\r\n\r\nPage coordinates are specified by an object with pageX and pageY\r\nproperties, or with a pagexy() method that will return such an object.\r\nThat includes, usefullly, mouse events and turtle objects. Page\r\ncoordinates are measured downward from the top-left corner of the\r\npage to the center (or transform-origin) of the given object.\r\n\r\nHit Testing\r\n-----------\r\n\r\nThe hit-testing functions touches() and enclosedby() will test for\r\ncollisions using the convex hulls of the objects in question.\r\nThe hull of an element defaults to the bounding box of the element\r\n(as transformed) but can be overridden by the turtleHull CSS property,\r\nif present. The default turtle is given a turtle-shaped hull.\r\n\r\nTurtle Teaching Environment\r\n---------------------------\r\n\r\nA default turtle together with an interactive console are created by\r\ncalling eval($.turtle()). That call exposes all the turtle methods\r\nsuch as (fd, rt, getxy, etc) as global functions operating on the default\r\nturtle. It will also set up a number of other global symbols to provide\r\nbeginners with a simplified programming environment.\r\n\r\nIn detail, after eval($.turtle()):\r\n * An <img id=\"turtle\"> is created if #turtle doesn't already exist.\r\n * An eval debugging panel (see.js) is shown at the bottom of the screen.\r\n * Turtle methods on the default turtle are packaged as globals, e.g., fd(10).\r\n * Every #id element is turned into a global variable: window.id = $('#id').\r\n * Default turtle animation is set to 1 move per sec so steps can be seen.\r\n * Global event listeners are created to update global event variables.\r\n * Methods of $.turtle.* (enumerated below) are exposed as global functions.\r\n * String constants are defined for the 140 named CSS colors.\r\n\r\nBeyond the functions to control the default turtle, the globals added by\r\n$.turtle() are as follows:\r\n\r\n
    \r\nlastclick             // Event object of the last click event in the doc.\r\nlastmousemove         // The last mousemove event.\r\nlastmouseup           // The last mouseup event.\r\nlastmousedown         // The last mousedown event.\r\nkeydown               // The last keydown event.\r\nkeyup                 // The last keyup event.\r\nkeypress              // The last keypress event.\r\nhatch([n,] [img])     // Creates and returns n turtles with the given img.\r\ncs()                  // Clears the screen, both the canvas and the body text.\r\ncg()                  // Clears the graphics canvas without clearing the text.\r\nct()                  // Clears the text without clearing the canvas.\r\ndefaultspeed(mps)     // Sets $.fx.speeds.turtle to 1000 / mps.\r\ntick([perSec,] fn)    // Sets fn as the tick callback (null to clear).\r\nrandom(n)             // Returns a random number [0..n-1].\r\nrandom(list)          // Returns a random element of the list.\r\nrandom('normal')      // Returns a gaussian random (mean 0 stdev 1).\r\nrandom('uniform')     // Returns a uniform random [0...1).\r\nrandom('position')    // Returns a random {pageX:x, pageY:y} coordinate.\r\nrandom('color')       // Returns a random hsl(*, 100%, 50%) color.\r\nrandom('gray')        // Returns a random hsl(0, 0, *) gray.\r\nremove()              // Removes default turtle and its globals (fd, etc).\r\nsee(a, b, c...)       // Logs tree-expandable data into debugging panel.\r\nwrite(html)           // Appends html into the document body.\r\nread([label,] fn)     // Makes a one-time input field, calls fn after entry.\r\nreadnum([label,] fn)  // Like read, but restricted to numeric input.\r\nreadstr([label,] fn)  // Like read, but never converts input to a number.\r\nbutton([label,] fn)   // Makes a clickable button, calls fn when clicked.\r\ntable(m, n)           // Outputs a table with m rows and n columns.\r\nsound('[DFG][EGc]')   // Plays musical notes now, without queueing.\r\n
    \r\n\r\nHere is another CoffeeScript example that demonstrates some of\r\nthe functions:\r\n\r\n
    \r\neval $.turtle()  # Create the default turtle and global functions.\r\n\r\ndefaultspeed Infinity\r\nwrite \"Catch blue before red gets you.\"\r\nbk 100\r\nr = hatch red\r\nb = hatch blue\r\ntick 10, ->\r\n  turnto lastmousemove\r\n  fd 6\r\n  r.turnto turtle\r\n  r.fd 4\r\n  b.turnto bearing b\r\n  b.fd 3\r\n  if b.touches(turtle)\r\n    write \"You win!\"\r\n    tick off\r\n  else if r.touches(turtle)\r\n    write \"Red got you!\"\r\n    tick off\r\n  else if not b.enclosedby(document)\r\n    write \"Blue got away!\"\r\n    tick off\r\n
    \r\n\r\nThe turtle teaching environment is designed to work well with either\r\nJavascript or CoffeeScript.\r\n\r\nJQuery CSS Hooks for Turtle Geometry\r\n------------------------------------\r\n\r\nUnderlying turtle motion are turtle-oriented 2d transform jQuery cssHooks,\r\nwith animation support on all motion:\r\n\r\n
    \r\n$(q).css('turtleSpeed', '10');         // default speed in moves per second.\r\n$(q).css('turtlePosition', '30 40');   // position in local coordinates.\r\n$(q).css('turtlePositionX', '30px');   // x component.\r\n$(q).css('turtlePositionY', '40px');   // y component.\r\n$(q).css('turtleRotation', '90deg');   // rotation in degrees.\r\n$(q).css('turtleScale', '2');          // double the size of any element.\r\n$(q).css('turtleScaleX', '2');         // x stretch after twist.\r\n$(q).css('turtleScaleY', '2');         // y stretch after twist.\r\n$(q).css('turtleTwist', '45deg');      // turn before stretching.\r\n$(q).css('turtleForward', '50px');     // position in direction of rotation.\r\n$(q).css('turtleTurningRadius, '50px');// arc turning radius for rotation.\r\n$(q).css('turtlePenStyle', 'red');     // or 'red lineWidth 2px' etc.\r\n$(q).css('turtlePenDown', 'up');       // default 'down' to draw with pen.\r\n$(q).css('turtleHull', '5 0 0 5 0 -5');// fine-tune shape for collisions.\r\n
    \r\n\r\nArbitrary 2d transforms are supported, including transforms of elements\r\nnested within other elements that have css transforms. For example, arc\r\npaths of a turtle within a skewed div will transform to the proper elliptical\r\narc. Note that while turtle motion is transformed, lines and dots are not:\r\nfor example, dots are always circular. To get transformed circles, trace\r\nout an arc.\r\n\r\nTransforms on the turtle itself are used to infer the turtle position,\r\ndirection, and rendering of the sprite. ScaleY stretches the turtle\r\nsprite in the direction of movement also stretches distances for\r\nmotion in all directions. ScaleX stretches the turtle sprite perpendicular\r\nto the direction of motion and also stretches line and dot widths for\r\ndrawing.\r\n\r\nA canvas is supported for drawing, but only created when the pen is\r\nused; pen styles include canvas style properties such as lineWidth\r\nand lineCap.\r\n\r\nA convex hull polygon can be set to be used by the collision detection\r\nand hit-testing functions (enclosedby, touches). The turtleHull is a list\r\nof (unrotated) x-y coordinates relative to the object's transformOrigin.\r\nIf set to 'auto' (the default) the hull is just the bounding box for the\r\nelement.\r\n\r\nLicense (MIT)\r\n-------------\r\n\r\nCopyright (c) 2013 David Bau\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file From 0647f77f4d46e2e9c91f47425096874464c60f8f Mon Sep 17 00:00:00 2001 From: davidbau Date: Mon, 19 Aug 2013 03:31:53 -0700 Subject: [PATCH 25/25] Create gh-pages branch via GitHub --- index.html | 65 +++++++++---------- stylesheets/pygment_trac.css | 117 +++++++++++++++++------------------ 2 files changed, 87 insertions(+), 95 deletions(-) diff --git a/index.html b/index.html index c0fac65..b4a295f 100644 --- a/index.html +++ b/index.html @@ -1,36 +1,35 @@ - + - - - - - - - - jQuery-turtle + + + jQuery-turtle by davidbau + + + + + + - +
    +
    +

    jQuery-turtle

    +

    Turtle Graphics for JQuery

    - -
    -
    - View on GitHub + -

    jQuery-turtle

    -

    Turtle Graphics for JQuery

    +

    This project is maintained by davidbau

    -
    - Download this project as a .zip file - Download this project as a tar.gz file -
    -
    -
    - -
    -
    +
    +

    jQuery-turtle

    @@ -373,17 +372,11 @@

    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    -
    - - - - - - + + - + \ No newline at end of file diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css index e65cedf..c6a6452 100644 --- a/stylesheets/pygment_trac.css +++ b/stylesheets/pygment_trac.css @@ -1,65 +1,64 @@ -.highlight .hll { background-color: #ffffcc } -.highlight { background: #f0f3f3; } -.highlight .c { color: #0099FF; font-style: italic } /* Comment */ -.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */ -.highlight .k { color: #006699; font-weight: bold } /* Keyword */ -.highlight .o { color: #555555 } /* Operator */ -.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #009999 } /* Comment.Preproc */ -.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */ -.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ +.highlight { background: #ffffff; } +.highlight .c { color: #999988; font-style: italic } /* Comment */ +.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight .k { font-weight: bold } /* Keyword */ +.highlight .o { font-weight: bold } /* Operator */ +.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ +.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ .highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #FF0000 } /* Generic.Error */ -.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */ -.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ -.highlight .go { color: #AAAAAA } /* Generic.Output */ -.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */ +.highlight .gr { color: #aa0000 } /* Generic.Error */ +.highlight .gh { color: #999999 } /* Generic.Heading */ +.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #99CC66 } /* Generic.Traceback */ -.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #006699 } /* Keyword.Pseudo */ -.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */ -.highlight .m { color: #FF6600 } /* Literal.Number */ -.highlight .s { color: #CC3300 } /* Literal.String */ -.highlight .na { color: #330099 } /* Name.Attribute */ -.highlight .nb { color: #336666 } /* Name.Builtin */ -.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */ -.highlight .no { color: #336600 } /* Name.Constant */ -.highlight .nd { color: #9999FF } /* Name.Decorator */ -.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #CC00FF } /* Name.Function */ -.highlight .nl { color: #9999FF } /* Name.Label */ -.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #003333 } /* Name.Variable */ -.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */ +.highlight .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight .kc { font-weight: bold } /* Keyword.Constant */ +.highlight .kd { font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #009999 } /* Literal.Number */ +.highlight .s { color: #d14 } /* Literal.String */ +.highlight .na { color: #008080 } /* Name.Attribute */ +.highlight .nb { color: #0086B3 } /* Name.Builtin */ +.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ +.highlight .no { color: #008080 } /* Name.Constant */ +.highlight .ni { color: #800080 } /* Name.Entity */ +.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ +.highlight .nn { color: #555555 } /* Name.Namespace */ +.highlight .nt { color: #000080 } /* Name.Tag */ +.highlight .nv { color: #008080 } /* Name.Variable */ +.highlight .ow { font-weight: bold } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mf { color: #FF6600 } /* Literal.Number.Float */ -.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */ -.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */ -.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */ -.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */ -.highlight .sc { color: #CC3300 } /* Literal.String.Char */ -.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #CC3300 } /* Literal.String.Double */ -.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */ -.highlight .si { color: #AA0000 } /* Literal.String.Interpol */ -.highlight .sx { color: #CC3300 } /* Literal.String.Other */ -.highlight .sr { color: #33AAAA } /* Literal.String.Regex */ -.highlight .s1 { color: #CC3300 } /* Literal.String.Single */ -.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */ -.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #003333 } /* Name.Variable.Class */ -.highlight .vg { color: #003333 } /* Name.Variable.Global */ -.highlight .vi { color: #003333 } /* Name.Variable.Instance */ -.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */ +.highlight .mf { color: #009999 } /* Literal.Number.Float */ +.highlight .mh { color: #009999 } /* Literal.Number.Hex */ +.highlight .mi { color: #009999 } /* Literal.Number.Integer */ +.highlight .mo { color: #009999 } /* Literal.Number.Oct */ +.highlight .sb { color: #d14 } /* Literal.String.Backtick */ +.highlight .sc { color: #d14 } /* Literal.String.Char */ +.highlight .sd { color: #d14 } /* Literal.String.Doc */ +.highlight .s2 { color: #d14 } /* Literal.String.Double */ +.highlight .se { color: #d14 } /* Literal.String.Escape */ +.highlight .sh { color: #d14 } /* Literal.String.Heredoc */ +.highlight .si { color: #d14 } /* Literal.String.Interpol */ +.highlight .sx { color: #d14 } /* Literal.String.Other */ +.highlight .sr { color: #009926 } /* Literal.String.Regex */ +.highlight .s1 { color: #d14 } /* Literal.String.Single */ +.highlight .ss { color: #990073 } /* Literal.String.Symbol */ +.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #008080 } /* Name.Variable.Class */ +.highlight .vg { color: #008080 } /* Name.Variable.Global */ +.highlight .vi { color: #008080 } /* Name.Variable.Instance */ +.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ .type-csharp .highlight .k { color: #0000FF } .type-csharp .highlight .kt { color: #0000FF }

    ' + escapeHtml(contents[row][col]) + '' + escapeHtml(contents[row]) + '