From 7500866755ac545294821ccf2b166ff84db685d8 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 21 Jan 2014 11:44:31 -0500 Subject: autoload first shader --- shader-api.html | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'shader-api.html') diff --git a/shader-api.html b/shader-api.html index 9020136..0aed936 100644 --- a/shader-api.html +++ b/shader-api.html @@ -8,7 +8,7 @@ div { float: left; padding: 10px;} form { display: inline-block; } #shader-api,#gallery { clear: right; width:100%; padding: 0; } -#shader-gallery,#gallery-images { display: block; max-height: 210px; overflow-y: auto; width: 100%; } +#shader-gallery,#gallery-images { display: block; min-height: 152px; max-height: 210px; overflow-y: auto; width: 100%; } #shader-gallery img,#shader-gallery canvas,#gallery-images img, #gallery-images canvas { max-width: 200px; height: 100px; margin: 5px; cursor: pointer; } .shader { width: 100px; @@ -83,6 +83,7 @@ a { color: #00f; } var cc = cq(0,0).appendTo("#workspace") var w, h +var firsttime = true $(init) @@ -116,6 +117,10 @@ function init(){ $el.append( $shader ) } + if (firsttime) { + firsttime = false + run(shaders[0]) + } } ShaderAPI.list_users(function(err, users){ @@ -136,10 +141,10 @@ function init(){ run( $(this).data("shader") ) }) - load() + // load() document.getElementById('shader').addEventListener('input', shader_build); - shader_build() + // shader_build() requestAnimationFrame(animate) } -- cgit v1.2.3-70-g09d2 From 08333b714e73034ca9098692950051d5d9d78220 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 21 Jan 2014 13:51:57 -0500 Subject: split off shader localstorage version --- dither-localstorage.html | 132 ----------------------------- js/api/localstorage.js | 106 ++++++++++++++++++++++++ js/api/set.js | 71 ++++++++-------- js/user.js | 106 ------------------------ shader-api.html | 9 +- shader-localstorage.html | 211 +++++++++++++++++++++++++++++++++++++++++++++++ shader-picker.html | 1 + 7 files changed, 359 insertions(+), 277 deletions(-) delete mode 100644 dither-localstorage.html create mode 100644 js/api/localstorage.js create mode 100644 shader-localstorage.html (limited to 'shader-api.html') diff --git a/dither-localstorage.html b/dither-localstorage.html deleted file mode 100644 index 5e9bff9..0000000 --- a/dither-localstorage.html +++ /dev/null @@ -1,132 +0,0 @@ - - - -Dither - - - - - - -
- - - - - - - - - -
-
- - - - - - - - - - - - - diff --git a/js/api/localstorage.js b/js/api/localstorage.js new file mode 100644 index 0000000..0ec7cad --- /dev/null +++ b/js/api/localstorage.js @@ -0,0 +1,106 @@ + +user.shaders = new function(){} +user.shaders.init = function(){ + user.shaders.bind() +} +user.shaders.bind = function(){ + user.shaders.buttons = {} + if ('SHADERS' in window) { + user.shaders.bindButtons( window.SHADERS ) + } + user.shaders.bindButtons( user.shaders.getShaders() ) + document.getElementById("add-shader").addEventListener("click", user.shaders.save, false) + document.getElementById("remove-shader").addEventListener("click", user.shaders.remove, false) +} +user.shaders.bindButtons = function(shaders){ + for (var i = 0; i < shaders.length; i++){ + user.shaders.bindButton(shaders[i]) + } +} +user.shaders.bindButton = function(data){ +// console.log("button >> " + data.name) + var button = document.createElement("button") + button.innerHTML = data.name + button.addEventListener("click", user.shaders.load.bind(this, data), false) + document.getElementById("shaders").appendChild(button) + user.shaders.buttons[data.name] = button +} +user.shaders.load = function(data){ + var shader = data.shader + if (shader && shader.length > 0) { + user.shaders.name = data.name + $("#shader").val(shader) + // pause here? + shader_build() + $(".active").removeClass("active") + $(user.shaders.buttons[data.name]).addClass("active") + user.shaders.setLastAccessed(data.name) + } +} +user.shaders.loadLastAccessed = function(){ + var name = localStorage.getItem("im.lastShader") || "colorcycle" + if (name in user.shaders.buttons) { + $(user.shaders.buttons[name]).trigger("click") + } +} +user.shaders.setLastAccessed = function(name){ + localStorage.setItem("im.lastShader", name) +} + +user.shaders.getShaderByName = function(name){ + return { name: name, shader: user.shaders.getShaderBody(name) } +} +user.shaders.getShaderIndex = function(){ + return JSON.parse( localStorage.getItem("im.shaders") ) || [] +} +user.shaders.getShaderBody = function(name){ + return localStorage.getItem("im.shaders."+name) || null +} +user.shaders.getShaders = function(){ + var shaders = user.shaders.getShaderIndex() + return shaders.map(function(name){ return { name: name, shader: user.shaders.getShaderBody(name) } }) +} +user.shaders.setShaderIndex = function(shaders){ + localStorage.setItem("im.shaders", JSON.stringify(shaders)) +} +user.shaders.setShader = function(name, shader){ + if (! name.length || ! shader.length || !name.length || !shader.length) return + localStorage.setItem("im.shaders." + name, shader) +} +user.shaders.removeShader = function(name){ + localStorage.removeItem("im.shaders." + name) +} + +user.shaders.save = function(){ + var name = prompt("enter shader name") + var shader = $("#shader").val() + + if (! name) return; + if (shade !== shade_no_error_handling) return; + + user.shaders.setShader(name, shader) + + var shaders = user.shaders.getShaderIndex() + shaders.push(name) + user.shaders.setShaderIndex(shaders) + + user.shaders.name = name + user.shaders.bindButton({ name: name, shader: shader }) + + $(".active").removeClass("active") + $(user.shaders.buttons[name]).addClass("active") + user.shaders.setLastAccessed(name) +} + +user.shaders.remove = function(){ + var name = user.shaders.name + if (! name || ! name.length) return + + var shaders = user.shaders.getShaderIndex() + if (shaders.splice( shaders.indexOf(name), 1 )) { + user.shaders.setShaderIndex(shaders) + user.shaders.removeShader(name) + $(user.shaders.buttons[name]).remove() + user.shaders.name = "" + } +} diff --git a/js/api/set.js b/js/api/set.js index 1e7e31f..834eaa8 100644 --- a/js/api/set.js +++ b/js/api/set.js @@ -1,39 +1,40 @@ function save_shader(){ - typeof shader_id_root == 'undefined' ? shader_id_root = "" : shader_id_root - var params = { - script : $("#shader").val(), - image_url : $("#url").val(), - username : user.username, - shader_id : shader_id_root - } - console.log(params) - $.post("/cgi-bin/im/shader/save", params, function(resp){ - console.log(resp); - data = JSON.parse(resp) - if (data.ERROR ){ - alert(data.ERROR) - return false - } - if (! shader_id_root) { - shader_id_root = data.id; - } + typeof shader_id_root == 'undefined' ? shader_id_root = "" : shader_id_root + var params = { + script: $("#shader").val(), + image_url: $("#url").val(), + username: user.username, + name: $("#shader-name").val() || "", + shader_id: shader_id_root + } + console.log(params) + $.post("/cgi-bin/im/shader/save", params, function(resp){ + console.log(resp); + data = JSON.parse(resp) + if (data.ERROR ){ + alert(data.ERROR) + return false + } + if (! shader_id_root) { + shader_id_root = data.id; + } - var blob = dataUriToBlob(cc.clone().resize(200,200).canvas.toDataURL("image/png")) - var form = new FormData(); - - form.append("id", data.id); - form.append("qqfile", blob); - $.ajax({ - url: "/cgi-bin/im/shader/thumbnail_upload", - type: "POST", - data: form, - processData: false, - contentType: false, - }).done(function(resp){ - console.log(resp); - }); + var blob = dataUriToBlob(cc.clone().resize(200,200).canvas.toDataURL("image/png")) + var form = new FormData(); - }) - //maintain the shader_id_root... - return shader_id_root; + form.append("id", data.id); + form.append("qqfile", blob); + $.ajax({ + url: "/cgi-bin/im/shader/thumbnail_upload", + type: "POST", + data: form, + processData: false, + contentType: false, + }).done(function(resp){ + console.log(resp); + }); + + }) + //maintain the shader_id_root... + return shader_id_root; } diff --git a/js/user.js b/js/user.js index 296974e..a1ac53e 100644 --- a/js/user.js +++ b/js/user.js @@ -37,109 +37,3 @@ user.setCookie = function(username){ document.cookie = "imname="+username+";path=/;domain=.asdf.us;max-age=1086400" localStorage.setItem("im.name", username); } - -user.shaders = new function(){} -user.shaders.init = function(){ - user.shaders.bind() -} -user.shaders.bind = function(){ - user.shaders.buttons = {} - if ('SHADERS' in window) { - user.shaders.bindButtons( window.SHADERS ) - } - user.shaders.bindButtons( user.shaders.getShaders() ) - document.getElementById("add-shader").addEventListener("click", user.shaders.save, false) - document.getElementById("remove-shader").addEventListener("click", user.shaders.remove, false) -} -user.shaders.bindButtons = function(shaders){ - for (var i = 0; i < shaders.length; i++){ - user.shaders.bindButton(shaders[i]) - } -} -user.shaders.bindButton = function(data){ -// console.log("button >> " + data.name) - var button = document.createElement("button") - button.innerHTML = data.name - button.addEventListener("click", user.shaders.load.bind(this, data), false) - document.getElementById("shaders").appendChild(button) - user.shaders.buttons[data.name] = button -} -user.shaders.load = function(data){ - var shader = data.shader - if (shader && shader.length > 0) { - user.shaders.name = data.name - $("#shader").val(shader) - // pause here? - shader_build() - $(".active").removeClass("active") - $(user.shaders.buttons[data.name]).addClass("active") - user.shaders.setLastAccessed(data.name) - } -} -user.shaders.loadLastAccessed = function(){ - var name = localStorage.getItem("im.lastShader") || "colorcycle" - if (name in user.shaders.buttons) { - $(user.shaders.buttons[name]).trigger("click") - } -} -user.shaders.setLastAccessed = function(name){ - localStorage.setItem("im.lastShader", name) -} - -user.shaders.getShaderByName = function(name){ - return { name: name, shader: user.shaders.getShaderBody(name) } -} -user.shaders.getShaderIndex = function(){ - return JSON.parse( localStorage.getItem("im.shaders") ) || [] -} -user.shaders.getShaderBody = function(name){ - return localStorage.getItem("im.shaders."+name) || null -} -user.shaders.getShaders = function(){ - var shaders = user.shaders.getShaderIndex() - return shaders.map(function(name){ return { name: name, shader: user.shaders.getShaderBody(name) } }) -} -user.shaders.setShaderIndex = function(shaders){ - localStorage.setItem("im.shaders", JSON.stringify(shaders)) -} -user.shaders.setShader = function(name, shader){ - if (! name.length || ! shader.length || !name.length || !shader.length) return - localStorage.setItem("im.shaders." + name, shader) -} -user.shaders.removeShader = function(name){ - localStorage.removeItem("im.shaders." + name) -} - -user.shaders.save = function(){ - var name = prompt("enter shader name") - var shader = $("#shader").val() - - if (! name) return; - if (shade !== shade_no_error_handling) return; - - user.shaders.setShader(name, shader) - - var shaders = user.shaders.getShaderIndex() - shaders.push(name) - user.shaders.setShaderIndex(shaders) - - user.shaders.name = name - user.shaders.bindButton({ name: name, shader: shader }) - - $(".active").removeClass("active") - $(user.shaders.buttons[name]).addClass("active") - user.shaders.setLastAccessed(name) -} - -user.shaders.remove = function(){ - var name = user.shaders.name - if (! name || ! name.length) return - - var shaders = user.shaders.getShaderIndex() - if (shaders.splice( shaders.indexOf(name), 1 )) { - user.shaders.setShaderIndex(shaders) - user.shaders.removeShader(name) - $(user.shaders.buttons[name]).remove() - user.shaders.name = "" - } -} \ No newline at end of file diff --git a/shader-api.html b/shader-api.html index 0aed936..8a4bc86 100644 --- a/shader-api.html +++ b/shader-api.html @@ -10,10 +10,9 @@ form { display: inline-block; } #shader-api,#gallery { clear: right; width:100%; padding: 0; } #shader-gallery,#gallery-images { display: block; min-height: 152px; max-height: 210px; overflow-y: auto; width: 100%; } #shader-gallery img,#shader-gallery canvas,#gallery-images img, #gallery-images canvas { max-width: 200px; height: 100px; margin: 5px; cursor: pointer; } -.shader { - width: 100px; -} +.shader { width: 100px; } #username { width: 40px; } +#shader-name { width: 40px; } a { color: #00f; } #shader-id { width: 40px; } @@ -52,6 +51,8 @@ a { color: #00f; }
+ +

@@ -76,7 +77,7 @@ a { color: #00f; } + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shader-picker.html b/shader-picker.html index d482a6b..cc4bd18 100644 --- a/shader-picker.html +++ b/shader-picker.html @@ -115,6 +115,7 @@ a { color: #00f; } + -- cgit v1.2.3-70-g09d2 From 84dafcdeda395584707e2c763c0637000ba737ad Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 21 Jan 2014 14:06:07 -0500 Subject: add save/pause/reset buttons --- js/api/set.js | 4 ++-- shader-api.html | 59 ++++++++++++++++++++++++++++++++------------------------- 2 files changed, 35 insertions(+), 28 deletions(-) (limited to 'shader-api.html') diff --git a/js/api/set.js b/js/api/set.js index 834eaa8..4e5b080 100644 --- a/js/api/set.js +++ b/js/api/set.js @@ -8,7 +8,7 @@ function save_shader(){ shader_id: shader_id_root } console.log(params) - $.post("/cgi-bin/im/shader/save", params, function(resp){ + $.post("http://asdf.us/cgi-bin/im/shader/save", params, function(resp){ console.log(resp); data = JSON.parse(resp) if (data.ERROR ){ @@ -25,7 +25,7 @@ function save_shader(){ form.append("id", data.id); form.append("qqfile", blob); $.ajax({ - url: "/cgi-bin/im/shader/thumbnail_upload", + url: "http://asdf.us/cgi-bin/im/shader/thumbnail_upload", type: "POST", data: form, processData: false, diff --git a/shader-api.html b/shader-api.html index 8a4bc86..ffe234b 100644 --- a/shader-api.html +++ b/shader-api.html @@ -2,7 +2,7 @@ @@ -58,6 +58,9 @@ a { color: #00f; }
+ + +
@@ -71,6 +74,7 @@ a { color: #00f; } + @@ -90,6 +94,8 @@ $(init) function init(){ $("#url").change(load) + $("#reset").click(reset) + $("#pause").click(pause) // run('#first') // $("#shader-id") @@ -103,26 +109,7 @@ function init(){ // $("#fetch-next-page") // $("#fetch-history") - function load_shaders(err, shaders){ - var $el = $("#shader-gallery").empty() - var template = $("#shader-gallery-template").html() - - for (var i in shaders) { - var $shader = $("
").addClass("shader") - $shader.data("shader", shaders[i]) - var html = template - for (var field in shaders[i]) { - html = html.replace("{" + field + "}", shaders[i][field]) - } - $shader.html(html) - - $el.append( $shader ) - } - if (firsttime) { - firsttime = false - run(shaders[0]) - } - } + $("#shader-save").click(save_shader) ShaderAPI.list_users(function(err, users){ var $el = $("#pick-user").empty() @@ -142,18 +129,38 @@ function init(){ run( $(this).data("shader") ) }) - // load() - + user.init() + document.getElementById('shader').addEventListener('input', shader_build); - // shader_build() requestAnimationFrame(animate) } +function load_shaders(err, shaders){ + var $el = $("#shader-gallery").empty() + var template = $("#shader-gallery-template").html() + + for (var i in shaders) { + var $shader = $("
").addClass("shader") + $shader.data("shader", shaders[i]) + var html = template + for (var field in shaders[i]) { + html = html.replace("{" + field + "}", shaders[i][field]) + } + $shader.html(html) + + $el.append( $shader ) + } + if (firsttime) { + firsttime = false + run(shaders[0]) + } +} function run(shader_object){ console.log(shader_object) $("#url").val( shader_object.image_url ) $("#shader").html(shader_object.script) $("#shader-id").val(shader_object.id) + $("#shader-name").val( shader_object.name || "") load() shader_build() } -- cgit v1.2.3-70-g09d2 From b14f35a2d8ef846f43c99639c544bc25be865e6c Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 21 Jan 2014 14:36:34 -0500 Subject: save ..? --- js/api/set.js | 5 ++--- shader-api.html | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'shader-api.html') diff --git a/js/api/set.js b/js/api/set.js index 4e5b080..6c6c917 100644 --- a/js/api/set.js +++ b/js/api/set.js @@ -1,5 +1,6 @@ +var shader_id_root = null; function save_shader(){ - typeof shader_id_root == 'undefined' ? shader_id_root = "" : shader_id_root + shader_id_root = shader_id_root || "" var params = { script: $("#shader").val(), image_url: $("#url").val(), @@ -35,6 +36,4 @@ function save_shader(){ }); }) - //maintain the shader_id_root... - return shader_id_root; } diff --git a/shader-api.html b/shader-api.html index ffe234b..164a531 100644 --- a/shader-api.html +++ b/shader-api.html @@ -109,7 +109,7 @@ function init(){ // $("#fetch-next-page") // $("#fetch-history") - $("#shader-save").click(save_shader) + $("#save-shader").click(save_shader) ShaderAPI.list_users(function(err, users){ var $el = $("#pick-user").empty() @@ -157,6 +157,7 @@ function load_shaders(err, shaders){ } function run(shader_object){ console.log(shader_object) + shader_id_root = shader_object.shader_id $("#url").val( shader_object.image_url ) $("#shader").html(shader_object.script) $("#shader-id").val(shader_object.id) -- cgit v1.2.3-70-g09d2 From 73a52b55dc51152a32e68f1a48af4bec04b33e61 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 21 Jan 2014 14:46:10 -0500 Subject: forgot datauri --- shader-api.html | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shader-api.html') diff --git a/shader-api.html b/shader-api.html index 164a531..3019771 100644 --- a/shader-api.html +++ b/shader-api.html @@ -70,6 +70,8 @@ a { color: #00f; } + + -- cgit v1.2.3-70-g09d2 From d8dad4902c6df11414bcca744ef531d4be207806 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 21 Jan 2014 15:27:26 -0500 Subject: checkbox to persist image --- shader-api.html | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'shader-api.html') diff --git a/shader-api.html b/shader-api.html index 3019771..78f86c8 100644 --- a/shader-api.html +++ b/shader-api.html @@ -7,9 +7,9 @@ #shader { width: 400px; height: 247px; font-family: fixed; } div { float: left; padding: 10px;} form { display: inline-block; } -#shader-api,#gallery { clear: right; width:100%; padding: 0; } +#shader-api,#gallery { clear: right; width:100%; padding: 0; font-size: 12px; } #shader-gallery,#gallery-images { display: block; min-height: 152px; max-height: 210px; overflow-y: auto; width: 100%; } -#shader-gallery img,#shader-gallery canvas,#gallery-images img, #gallery-images canvas { max-width: 200px; height: 100px; margin: 5px; cursor: pointer; } +#shader-gallery img,#shader-gallery canvas,#gallery-images img, #gallery-images canvas { max-width: 200px; height: 100px; margin: 5px; cursor: pointer; clear: right; } .shader { width: 100px; } #username { width: 55px; } #shader-name { width: 75px; } @@ -44,6 +44,8 @@ a { color: #00f; } + + @@ -84,7 +86,7 @@ a { color: #00f; } + -- cgit v1.2.3-70-g09d2 From 3a51572e8a6628f90e73e2ab0bca52a98d9540e7 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 23 Jan 2014 10:10:19 -0500 Subject: more shuffling --- js/frames.js | 32 ++++++++++++++++++++++++++++++++ shader-api.html | 44 ++++++++++++++++++++++---------------------- shader-picker.html | 26 +++----------------------- 3 files changed, 57 insertions(+), 45 deletions(-) (limited to 'shader-api.html') diff --git a/js/frames.js b/js/frames.js index 0ae256c..c9c844d 100644 --- a/js/frames.js +++ b/js/frames.js @@ -1,4 +1,36 @@ +var frame_editor = {} + +frame_editor.init = function(){ + frame_editor.bind() +} + +frame_editor.bind = function(){ + $("#add-frame").click(add_frame) + $("#frames").sortable({ + start: drag_start, + stop: drag_stop + }); + $(document).on("click","#frames .remove",remove_frame) + $("#framecount").change(function(){ + var val = $(this).int() + if (val < 1 || isNaN(val)) $(this).val(val = 1) + if (val == 1) $("#add-frame").html("+add frame") + else $("#add-frame").html("+add frames") + }) + + $("#frames").disableSelection(); + $("#remove-all-frames").click(remove_all_frames) + $("#weave-frames").click(weave_frames) + $("#shuffle-frames").click(shuffle_frames) + $("#reverse-frames").click(reverse_frames) + $("#sort-frames").click(sort_frames) + + $("#render").click(render) + $("#save").click(save) + $("#upload").click(upload) +} + function add_frame(){ var frame_count = $("#framecount").int() if (frame_count < 2) { diff --git a/shader-api.html b/shader-api.html index dc22d10..ba8530e 100644 --- a/shader-api.html +++ b/shader-api.html @@ -22,15 +22,15 @@ a { color: #00f; } @@ -57,15 +57,15 @@ a { color: #00f; } -
-
+
+
- -
- - - -
+ +
+ + + +
@@ -102,16 +102,16 @@ var shader_gallery_template = $("#shader-gallery-template").html() $(init) function init(){ - $("#url").change(load) - $("#reset").click(reset) - $("#pause").click(pause) + $("#url").change(load) + $("#reset").click(reset) + $("#pause").click(pause) user.init() shader_gallery.init() - document.getElementById('shader').addEventListener('input', shader_build); + document.getElementById('shader').addEventListener('input', shader_build); - requestAnimationFrame(animate) + requestAnimationFrame(animate) } diff --git a/shader-picker.html b/shader-picker.html index 923f1b6..0f27d6a 100644 --- a/shader-picker.html +++ b/shader-picker.html @@ -147,32 +147,13 @@ function init(){ mousey = e.pageY }) - $("#add-frame").click(add_frame) - $("#frames").sortable({ - start: drag_start, - stop: drag_stop - }); - $(document).on("click","#frames .remove",remove_frame) - $("#framecount").change(function(){ - var val = $(this).int() - if (val < 1 || isNaN(val)) $(this).val(val = 1) - if (val == 1) $("#add-frame").html("+add frame") - else $("#add-frame").html("+add frames") - }) $("#background").change(function(){ document.body.style.backgroundColor = $("#background").string() }) - $("#frames").disableSelection(); - $("#remove-all-frames").click(remove_all_frames) - $("#weave-frames").click(weave_frames) - $("#shuffle-frames").click(shuffle_frames) - $("#reverse-frames").click(reverse_frames) - $("#sort-frames").click(sort_frames) - - $("#render").click(render) - $("#save").click(save) - $("#upload").click(upload) + frame_editor.init() + + $(window).on("scroll DOMMouseScroll mousewheel", function(){ scrolling = true }) $("#help,#instructions .close").click(function(){ $("#instructions").toggle() }) $("#instructions").draggable({ start: drag_start, @@ -181,7 +162,6 @@ function init(){ $("#instructions").disableSelection(); load() - $(window).on("scroll DOMMouseScroll mousewheel", function(){ scrolling = true }) gallery.choose = choose gallery.init() -- cgit v1.2.3-70-g09d2 From 65d561be1d64767c3434137ae17b380067e1ef19 Mon Sep 17 00:00:00 2001 From: timb Date: Fri, 24 Jan 2014 06:22:38 -0800 Subject: tiny css edit to get rid of horizontal scrollbar --- shader-api.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shader-api.html') diff --git a/shader-api.html b/shader-api.html index ba8530e..b17c45b 100644 --- a/shader-api.html +++ b/shader-api.html @@ -8,7 +8,7 @@ div { float: left; padding: 10px;} form { display: inline-block; } #shader-api,#gallery { clear: right; width:100%; padding: 0; font-size: 12px; } -#shader-gallery,#gallery-images { display: block; min-height: 152px; max-height: 210px; overflow-y: auto; width: 100%; } +#shader-gallery,#gallery-images { display: block; min-height: 152px; max-height: 210px; overflow-y: auto; width: 100%; padding: 0; } #shader-gallery img,#shader-gallery canvas,#gallery-images img, #gallery-images canvas { max-width: 200px; height: 100px; margin: 5px; cursor: pointer; clear: right; } .shader { width: 100px; } .shader span { display: block } -- cgit v1.2.3-70-g09d2 From 89bf91e68f1fac2d88eb97c7fe324753a5ef76cf Mon Sep 17 00:00:00 2001 From: timb Date: Fri, 24 Jan 2014 07:58:46 -0800 Subject: a try at error highlighting --- js/error.highlight.js | 160 +++++ js/shader.js | 28 + js/vendor/acorn.js | 1768 +++++++++++++++++++++++++++++++++++++++++++++++++ shader-api.html | 2 + shader-picker.html | 2 + 5 files changed, 1960 insertions(+) create mode 100644 js/error.highlight.js create mode 100644 js/vendor/acorn.js (limited to 'shader-api.html') diff --git a/js/error.highlight.js b/js/error.highlight.js new file mode 100644 index 0000000..b7c583e --- /dev/null +++ b/js/error.highlight.js @@ -0,0 +1,160 @@ +(function(){ + +var html +var textarea +var dom = {} +var style = {} +var pos = {} +// i use this because a plain
collapses vertically sometimes... +var zero_width_space = '' + +var off = function(){ + dom.highlight.style.display = 'none' +} + +var height_until_error = 0; +var height_with_error = 0; + +var on = function(line_num){ + pos = textarea.getBoundingClientRect() + var text = textarea.value; + + var lines = text.split('\n') + var lines_until_error = lines.slice(0, line_num) + var line_with_error = lines[line_num] + + if (lines_until_error.length === 1) + dom.textmeasure.innerHTML = lines_until_error + zero_width_space + else + dom.textmeasure.innerHTML = lines_until_error.join('
' + zero_width_space) + + height_until_error = dom.textmeasure.offsetHeight + + dom.textmeasure.innerHTML = line_with_error + zero_width_space + + height_with_error = dom.textmeasure.offsetHeight + + reposition_highlight() + +}; + +var reposition_highlight = function(){ + dom.highlight.style.display = 'block' + + var bounds_bottom = pos.top + pos.height + + if (textarea.scrollHeight > textarea.clientHeight) // scrollbar exists + dom.highlight.style.width = pos.width - scrollbar_width + "px" + else + dom.highlight.style.width = pos.width + "px" + + dom.highlight.style.left = pos.left + "px" + + var y_pos = pos.top + height_until_error - textarea.scrollTop + + dom.highlight.style.top = y_pos + html.scrollTop + "px" + + var height_of_highlight = height_with_error; + + // nice clip on bottom + if (y_pos + height_of_highlight > bounds_bottom) + height_of_highlight = Math.max(0, bounds_bottom - y_pos) + // crap clip on top + if (y_pos < pos.top) + height_of_highlight = 0 + + dom.highlight.style.height = height_of_highlight + "px" +} + +var calc_textarea_style = function(){ + var $textarea = $("#shader") + textarea = $textarea[0] + // GG = textarea + + var props = ['lineHeight', 'fontFamily', 'fontSize', 'padding', 'margin', 'borderWidth', 'width'] + + for (var i=0, p; p=props[i]; i++){ + style[p] = $textarea.css(p) + } + console.log(style) + +} + + +var calc_scrollbar_width = function() { + var outer = document.createElement("div"); + outer.style.visibility = "hidden"; + outer.style.width = "100px"; + document.body.appendChild(outer); + + var width_no_scroll = outer.offsetWidth; + // force scrollbars + outer.style.overflow = "scroll"; + + // add innerdiv + var inner = document.createElement("div"); + inner.style.width = "100%"; + outer.appendChild(inner); + + var width_with_scroll = inner.offsetWidth; + // remove divs + outer.parentNode.removeChild(outer); + + return width_no_scroll - width_with_scroll; +} + +var create_el_textmeasure = function(){ + var el = dom.textmeasure = document.createElement('div') + el.id = 'textmeasure' + var s = el.style + for (var key in style) + s[key] = style[key] + + s.wordWrap = 'break-word' + s.wordBreak = 'break-all' + s.border = '1px solid red' + s.padding = '0' + s.display = 'block' + s.position = 'absolute' + s.left = "-5000px" + document.body.appendChild(el) +} + +var create_el_highlight = function(){ + var el = dom.highlight = document.createElement('div') + var s = el.style + for (var key in style) + s[key] = style[key] + + s.pointerEvents = 'none' + s.opacity = '0.2' + s.backgroundColor = '#f00' + s.position = 'absolute' + s.lineHeight = '0' + s.fontSize = '0' + s.padding = '0' + s.borderWidth = '0' + s.display = 'block' + document.body.appendChild(el) +} + +var scrollbar_width = 0; +var init = function(){ + calc_textarea_style() + create_el_highlight() + create_el_textmeasure() + scrollbar_width = calc_scrollbar_width() + textarea.addEventListener('scroll', reposition_highlight) + html = document.querySelector('html') +} + +error_highlight = { + init: init, + on: on, + off: off +} + + +})(); + +error_highlight.init() diff --git a/js/shader.js b/js/shader.js index 19c049b..003f543 100644 --- a/js/shader.js +++ b/js/shader.js @@ -4,8 +4,16 @@ var shader_build = function(){ try { var fn = new Function('x','y','t','d', fn_str) shader = fn + error_highlight.off() shade = shade_error_handling } catch (e) { + try { + acorn.parse(fn_str) + } catch(e){ + /* loc: {column: 0, line: 1} */ + /* line is 1-based for some goddamn reason*/ + error_highlight.on(e.loc.line-1) + } throw Error ("Shader compilation error") } } @@ -36,6 +44,9 @@ function shade_no_error_handling(frame, t){ cc.putImageData(imgData,0,0) } +var chrome_stack_regexp = /:([0-9]+)/; +var firefox_stack_regexp = /:([0-9]+)$/; + function shade_error_handling(frame, t){ if (! t || isNaN(t)) throw Error ("No time specified") if (! frame) throw Error ("No frame specified") @@ -61,6 +72,20 @@ function shade_error_handling(frame, t){ } } catch(e){ + var lines = (e.stack + "").split('\n') + if (lines[0].substr(0,10) === "anonymous@") { //firefox + var matches = lines[0].match(firefox_stack_regexp) + if (matches.length > 1) { + var line = parseInt(matches[1]) - 5 + error_highlight.on(line) + } + } else if (lines.length > 1) { // attempt chrome match + var matches = lines[1].match(chrome_stack_regexp) + if (matches.length > 1) { + var line = parseInt(matches[1]) - 3 + error_highlight.on(line) + } + } // console.log(e.stack) throw Error ("Shader execution error") } @@ -69,3 +94,6 @@ function shade_error_handling(frame, t){ } shade = shade_error_handling + +// :4:11) +// "anonymous@http://dither.local/js/shader.js:6" \ No newline at end of file diff --git a/js/vendor/acorn.js b/js/vendor/acorn.js new file mode 100644 index 0000000..c335f65 --- /dev/null +++ b/js/vendor/acorn.js @@ -0,0 +1,1768 @@ +// Acorn is a tiny, fast JavaScript parser written in JavaScript. +// +// Acorn was written by Marijn Haverbeke and released under an MIT +// license. The Unicode regexps (for identifiers and whitespace) were +// taken from [Esprima](http://esprima.org) by Ariya Hidayat. +// +// Git repositories for Acorn are available at +// +// http://marijnhaverbeke.nl/git/acorn +// https://github.com/marijnh/acorn.git +// +// Please use the [github bug tracker][ghbt] to report issues. +// +// [ghbt]: https://github.com/marijnh/acorn/issues +// +// This file defines the main parser interface. The library also comes +// with a [error-tolerant parser][dammit] and an +// [abstract syntax tree walker][walk], defined in other files. +// +// [dammit]: acorn_loose.js +// [walk]: util/walk.js + +(function(root, mod) { + if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS + if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD + mod(root.acorn || (root.acorn = {})); // Plain browser env +})(this, function(exports) { + "use strict"; + + exports.version = "0.4.1"; + + // The main exported interface (under `self.acorn` when in the + // browser) is a `parse` function that takes a code string and + // returns an abstract syntax tree as specified by [Mozilla parser + // API][api], with the caveat that the SpiderMonkey-specific syntax + // (`let`, `yield`, inline XML, etc) is not recognized. + // + // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + + var options, input, inputLen, sourceFile; + + exports.parse = function(inpt, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(); + return parseTopLevel(options.program); + }; + + // A second optional argument can be given to further configure + // the parser process. These options are recognized: + + var defaultOptions = exports.defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must + // be either 3 or 5. This + // influences support for strict mode, the set of reserved words, and + // support for getters and setter. + ecmaVersion: 5, + // Turn on `strictSemicolons` to prevent the parser from doing + // automatic semicolon insertion. + strictSemicolons: false, + // When `allowTrailingCommas` is false, the parser will not allow + // trailing commas in array and object literals. + allowTrailingCommas: true, + // By default, reserved words are not enforced. Enable + // `forbidReserved` to enforce them. + forbidReserved: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null + }; + + function setOptions(opts) { + options = opts || {}; + for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt)) + options[opt] = defaultOptions[opt]; + sourceFile = options.sourceFile || null; + } + + // The `getLineInfo` function is mostly useful when the + // `locations` option is off (for performance reasons) and you + // want to find the line/column position for a given character + // offset. `input` should be the code string that the offset refers + // into. + + var getLineInfo = exports.getLineInfo = function(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreak.lastIndex = cur; + var match = lineBreak.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } else break; + } + return {line: line, column: offset - cur}; + }; + + // Acorn is organized as a tokenizer and a recursive-descent parser. + // The `tokenize` export provides an interface to the tokenizer. + // Because the tokenizer is optimized for being efficiently used by + // the Acorn parser itself, this interface is somewhat crude and not + // very modular. Performing another parse or call to `tokenize` will + // reset the internal state, and invalidate existing tokenizers. + + exports.tokenize = function(inpt, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(); + + var t = {}; + function getToken(forceRegexp) { + lastEnd = tokEnd; + readToken(forceRegexp); + t.start = tokStart; t.end = tokEnd; + t.startLoc = tokStartLoc; t.endLoc = tokEndLoc; + t.type = tokType; t.value = tokVal; + return t; + } + getToken.jumpTo = function(pos, reAllowed) { + tokPos = pos; + if (options.locations) { + tokCurLine = 1; + tokLineStart = lineBreak.lastIndex = 0; + var match; + while ((match = lineBreak.exec(input)) && match.index < pos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + tokRegexpAllowed = reAllowed; + skipSpace(); + }; + return getToken; + }; + + // State is kept in (closure-)global variables. We already saw the + // `options`, `input`, and `inputLen` variables above. + + // The current position of the tokenizer in the input. + + var tokPos; + + // The start and end offsets of the current token. + + var tokStart, tokEnd; + + // When `options.locations` is true, these hold objects + // containing the tokens start and end line/column pairs. + + var tokStartLoc, tokEndLoc; + + // The type and value of the current token. Token types are objects, + // named by variables against which they can be compared, and + // holding properties that describe them (indicating, for example, + // the precedence of an infix operator, and the original name of a + // keyword token). The kind of value that's held in `tokVal` depends + // on the type of the token. For literals, it is the literal value, + // for operators, the operator name, and so on. + + var tokType, tokVal; + + // Interal state for the tokenizer. To distinguish between division + // operators and regular expressions, it remembers whether the last + // token was one that is allowed to be followed by an expression. + // (If it is, a slash is probably a regexp, if it isn't it's a + // division operator. See the `parseStatement` function for a + // caveat.) + + var tokRegexpAllowed; + + // When `options.locations` is true, these are used to keep + // track of the current line, and know when a new line has been + // entered. + + var tokCurLine, tokLineStart; + + // These store the position of the previous token, which is useful + // when finishing a node and assigning its `end` position. + + var lastStart, lastEnd, lastEndLoc; + + // This is the parser's state. `inFunction` is used to reject + // `return` statements outside of functions, `labels` to verify that + // `break` and `continue` have somewhere to jump to, and `strict` + // indicates whether strict mode is on. + + var inFunction, labels, strict; + + // This function is used to raise exceptions on parse errors. It + // takes an offset integer (into the current `input`) to indicate + // the location of the error, attaches the position to the end + // of the error message, and then raises a `SyntaxError` with that + // message. + + function raise(pos, message) { + var loc = getLineInfo(input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = tokPos; + throw err; + } + + // Reused empty array added for node fields that are always empty. + + var empty = []; + + // ## Token types + + // The assignment of fine-grained, information-carrying type objects + // allows the tokenizer to store the information it has about a + // token in a way that is very cheap for the parser to look up. + + // All token type variables start with an underscore, to make them + // easy to recognize. + + // These are the general types. The `type` property is only used to + // make them recognizeable when debugging. + + var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"}; + var _name = {type: "name"}, _eof = {type: "eof"}; + + // Keyword tokens. The `keyword` property (also used in keyword-like + // operators) indicates that the token originated from an + // identifier-like word, which is used when parsing property names. + // + // The `beforeExpr` property is used to disambiguate between regular + // expressions and divisions. It is set on all token types that can + // be followed by an expression (thus, a slash after them would be a + // regular expression). + // + // `isLoop` marks a keyword as starting a loop, which is important + // to know when parsing a label, in order to allow or disallow + // continue jumps to that label. + + var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"}; + var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"}; + var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true}; + var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"}; + var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"}; + var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"}; + var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true}; + var _this = {keyword: "this"}; + + // The keywords that denote values. + + var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true}; + var _false = {keyword: "false", atomValue: false}; + + // Some keywords are treated as regular operators. `in` sometimes + // (when parsing `for`) needs to be tested against specifically, so + // we assign a variable name to it for quick comparing. + + var _in = {keyword: "in", binop: 7, beforeExpr: true}; + + // Map keyword names to token types. + + var keywordTypes = {"break": _break, "case": _case, "catch": _catch, + "continue": _continue, "debugger": _debugger, "default": _default, + "do": _do, "else": _else, "finally": _finally, "for": _for, + "function": _function, "if": _if, "return": _return, "switch": _switch, + "throw": _throw, "try": _try, "var": _var, "while": _while, "with": _with, + "null": _null, "true": _true, "false": _false, "new": _new, "in": _in, + "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, + "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, + "void": {keyword: "void", prefix: true, beforeExpr: true}, + "delete": {keyword: "delete", prefix: true, beforeExpr: true}}; + + // Punctuation token types. Again, the `type` property is purely for debugging. + + var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true}; + var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"}; + var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true}; + var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _question = {type: "?", beforeExpr: true}; + + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. `isUpdate` specifies that the node produced by + // the operator should be of type UpdateExpression rather than + // simply UnaryExpression (`++` and `--`). + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true}; + var _assign = {isAssign: true, beforeExpr: true}; + var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true}; + var _logicalOR = {binop: 1, beforeExpr: true}; + var _logicalAND = {binop: 2, beforeExpr: true}; + var _bitwiseOR = {binop: 3, beforeExpr: true}; + var _bitwiseXOR = {binop: 4, beforeExpr: true}; + var _bitwiseAND = {binop: 5, beforeExpr: true}; + var _equality = {binop: 6, beforeExpr: true}; + var _relational = {binop: 7, beforeExpr: true}; + var _bitShift = {binop: 8, beforeExpr: true}; + var _plusMin = {binop: 9, prefix: true, beforeExpr: true}; + var _multiplyModulo = {binop: 10, beforeExpr: true}; + + // Provide access to the token types for external users of the + // tokenizer. + + exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR, + parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, + dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof, + num: _num, regexp: _regexp, string: _string}; + for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; + + // This is a trick taken from Esprima. It turns out that, on + // non-Chrome browsers, to check whether a string is in a set, a + // predicate containing a big ugly `switch` statement is faster than + // a regular expression, and on Chrome the two are about on par. + // This function uses `eval` (non-lexical) to produce such a + // predicate from a space-separated string of words. + // + // It starts by sorting the words by length. + + function makePredicate(words) { + words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + + // Otherwise, simply generate a flat `switch` statement. + + } else { + compareTo(words); + } + return new Function("str", f); + } + + // The ECMAScript 3 reserved word list. + + var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"); + + // ECMAScript 5 reserved words. + + var isReservedWord5 = makePredicate("class enum extends super const export import"); + + // The additional reserved words in strict mode. + + var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield"); + + // The forbidden variable names in strict mode. + + var isStrictBadIdWord = makePredicate("eval arguments"); + + // And the keywords. + + var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"); + + // ## Character categories + + // Big ugly regular expressions that match characters in the + // whitespace, identifier, and identifier-start categories. These + // are only applied when a character is found to actually have a + // code point above 128. + + var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; + var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; + var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); + var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + + // Whether a single character denotes a newline. + + var newline = /[\n\r\u2028\u2029]/; + + // Matches a whole line break (where CRLF is considered a single + // line break). Used to count lines. + + var lineBreak = /\r\n|[\n\r\u2028\u2029]/g; + + // Test whether a given character code starts an identifier. + + var isIdentifierStart = exports.isIdentifierStart = function(code) { + if (code < 65) return code === 36; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123)return true; + return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); + }; + + // Test whether a given character is part of an identifier. + + var isIdentifierChar = exports.isIdentifierChar = function(code) { + if (code < 48) return code === 36; + if (code < 58) return true; + if (code < 65) return false; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123)return true; + return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); + }; + + // ## Tokenizer + + // These are used when `options.locations` is on, for the + // `tokStartLoc` and `tokEndLoc` properties. + + function line_loc_t() { + this.line = tokCurLine; + this.column = tokPos - tokLineStart; + } + + // Reset the token state. Used at the start of a parse. + + function initTokenState() { + tokCurLine = 1; + tokPos = tokLineStart = 0; + tokRegexpAllowed = true; + skipSpace(); + } + + // Called at the end of every token. Sets `tokEnd`, `tokVal`, and + // `tokRegexpAllowed`, and skips the space after the token, so that + // the next one's `tokStart` will point at the right position. + + function finishToken(type, val) { + tokEnd = tokPos; + if (options.locations) tokEndLoc = new line_loc_t; + tokType = type; + skipSpace(); + tokVal = val; + tokRegexpAllowed = type.beforeExpr; + } + + function skipBlockComment() { + var startLoc = options.onComment && options.locations && new line_loc_t; + var start = tokPos, end = input.indexOf("*/", tokPos += 2); + if (end === -1) raise(tokPos - 2, "Unterminated comment"); + tokPos = end + 2; + if (options.locations) { + lineBreak.lastIndex = start; + var match; + while ((match = lineBreak.exec(input)) && match.index < tokPos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + if (options.onComment) + options.onComment(true, input.slice(start + 2, end), start, tokPos, + startLoc, options.locations && new line_loc_t); + } + + function skipLineComment() { + var start = tokPos; + var startLoc = options.onComment && options.locations && new line_loc_t; + var ch = input.charCodeAt(tokPos+=2); + while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { + ++tokPos; + ch = input.charCodeAt(tokPos); + } + if (options.onComment) + options.onComment(false, input.slice(start + 2, tokPos), start, tokPos, + startLoc, options.locations && new line_loc_t); + } + + // Called at the start of the parse and after every token. Skips + // whitespace and comments, and. + + function skipSpace() { + while (tokPos < inputLen) { + var ch = input.charCodeAt(tokPos); + if (ch === 32) { // ' ' + ++tokPos; + } else if (ch === 13) { + ++tokPos; + var next = input.charCodeAt(tokPos); + if (next === 10) { + ++tokPos; + } + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch === 10 || ch === 8232 || ch === 8233) { + ++tokPos; + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch > 8 && ch < 14) { + ++tokPos; + } else if (ch === 47) { // '/' + var next = input.charCodeAt(tokPos + 1); + if (next === 42) { // '*' + skipBlockComment(); + } else if (next === 47) { // '/' + skipLineComment(); + } else break; + } else if (ch === 160) { // '\xa0' + ++tokPos; + } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++tokPos; + } else { + break; + } + } + } + + // ### Token reading + + // This is the function that is called to fetch the next token. It + // is somewhat obscure, because it works in character codes rather + // than characters, and because operator parsing has been inlined + // into it. + // + // All in the name of speed. + // + // The `forceRegexp` parameter is used in the one case where the + // `tokRegexpAllowed` trick does not work. See `parseStatement`. + + function readToken_dot() { + var next = input.charCodeAt(tokPos + 1); + if (next >= 48 && next <= 57) return readNumber(true); + ++tokPos; + return finishToken(_dot); + } + + function readToken_slash() { // '/' + var next = input.charCodeAt(tokPos + 1); + if (tokRegexpAllowed) {++tokPos; return readRegexp();} + if (next === 61) return finishOp(_assign, 2); + return finishOp(_slash, 1); + } + + function readToken_mult_modulo() { // '%*' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(_multiplyModulo, 1); + } + + function readToken_pipe_amp(code) { // '|&' + var next = input.charCodeAt(tokPos + 1); + if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2); + if (next === 61) return finishOp(_assign, 2); + return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1); + } + + function readToken_caret() { // '^' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(_bitwiseXOR, 1); + } + + function readToken_plus_min(code) { // '+-' + var next = input.charCodeAt(tokPos + 1); + if (next === code) { + if (next == 45 && input.charCodeAt(tokPos + 2) == 62 && + newline.test(input.slice(lastEnd, tokPos))) { + // A `-->` line comment + tokPos += 3; + skipLineComment(); + skipSpace(); + return readToken(); + } + return finishOp(_incDec, 2); + } + if (next === 61) return finishOp(_assign, 2); + return finishOp(_plusMin, 1); + } + + function readToken_lt_gt(code) { // '<>' + var next = input.charCodeAt(tokPos + 1); + var size = 1; + if (next === code) { + size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; + if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); + return finishOp(_bitShift, size); + } + if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 && + input.charCodeAt(tokPos + 3) == 45) { + // `
+ @@ -74,6 +82,7 @@ a { color: #00f; } + @@ -122,4 +131,3 @@ function init(){ -- \ No newline at end of file diff --git a/shader-picker.html b/shader-picker.html index 0896609..7efe39f 100644 --- a/shader-picker.html +++ b/shader-picker.html @@ -130,6 +130,12 @@ a { color: #00f; } + + + - -- cgit v1.2.3-70-g09d2 From 9f1b5a177eee98f64e7581756cd5fdc7635691ca Mon Sep 17 00:00:00 2001 From: jules Date: Sun, 26 Jan 2014 00:58:01 -0500 Subject: css shakeup --- js/gallery.js | 1 + shader-api.html | 1 + shader-combo.html | 57 ++++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 46 insertions(+), 13 deletions(-) (limited to 'shader-api.html') diff --git a/js/gallery.js b/js/gallery.js index a9430fc..b9acfc0 100644 --- a/js/gallery.js +++ b/js/gallery.js @@ -46,6 +46,7 @@ gallery.image = function(im){ $(thumb.canvas).show() }) $(img).click(gallery.choose); + $("#persist-image").attr("checked", false) } try { img.src = im.url; } catch(e){ return; } diff --git a/shader-api.html b/shader-api.html index b860093..dc96762 100644 --- a/shader-api.html +++ b/shader-api.html @@ -79,6 +79,7 @@ a { color: #00f; }
+
diff --git a/shader-combo.html b/shader-combo.html index aa6edd2..6d402da 100644 --- a/shader-combo.html +++ b/shader-combo.html @@ -3,28 +3,50 @@ @@ -43,8 +65,9 @@ a { color: #00f; } | - - | + + + @@ -53,16 +76,14 @@ a { color: #00f; } - + - -
@@ -79,11 +100,21 @@ a { color: #00f; } + +
+ + + +
+ +
+
+
@@ -148,14 +179,14 @@ function init(){ $("#shader-api-form").show() $(".bold").removeClass("bold") $(this).addClass("bold") - }).trigger("click") + }) // .trigger("click") $("#toggle-images").click(function(){ $("#header .form").hide() $("#gallery-form").show() $(".bold").removeClass("bold") $(this).addClass("bold") }) - $("#toggle-off").click(function(){ + $(".toggle-off").click(function(){ $("#header .form").hide() $(".bold").removeClass("bold") }) -- cgit v1.2.3-70-g09d2