diff --git a/scratch/Makefile b/scratch/Makefile
new file mode 100644
index 00000000..92112b48
--- /dev/null
+++ b/scratch/Makefile
@@ -0,0 +1,22 @@
+# File: Makefile
+# Author: Bert Freudenberg
+#
+# copy files to publishing directory and create an offline manifest
+
+TARGET=../gh-pages/scratch
+MANIFEST=$(TARGET)/offline.appcache
+FILES=../lib/squeak.js ../vm.js index.html scratch.css scratch.js scratch.png \
+ ../lib/lz-string.js ../lib/addtohomescreen.css ../lib/addtohomescreen.js ../lib/gh-fork-ribbon.css
+EXTRA=http://freudenbergs.de/bert/squeakjs/scratch/Scratch.image
+
+$(MANIFEST): Makefile $(TARGET)
+ @rm -f $@
+ @echo "CACHE MANIFEST" > $@
+ @stat -f '# %Sm' `ls -t $(FILES) | head -n1` | tee -a $@
+ @for f in $(FILES) $(EXTRA); do echo $$f >> $@ ; done
+
+$(TARGET): $(FILES)
+ @mkdir -pv $@ $@/../lib
+ @for f in $^ ; do install -pvm 444 $$f $@/$$f ; done
+ @touch $@
+
diff --git a/scratch/index.html b/scratch/index.html
new file mode 100644
index 00000000..769754d2
--- /dev/null
+++ b/scratch/index.html
@@ -0,0 +1,56 @@
+
+
+
+
+ScratchJS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scratch/scratch.css b/scratch/scratch.css
new file mode 100644
index 00000000..84099623
--- /dev/null
+++ b/scratch/scratch.css
@@ -0,0 +1,30 @@
+body {
+ background-color: #eae6d1;
+ font-family: sans-serif;
+}
+canvas {
+ position: absolute;
+ background: #000;
+ cursor: default;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+div#sqHeader {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ padding: 10px;
+ border-bottom: 6px double gray;
+}
+div#sqFooter {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: 10px;
+ border-top: 6px double gray;
+}
diff --git a/scratch/scratch.js b/scratch/scratch.js
new file mode 100644
index 00000000..e980d649
--- /dev/null
+++ b/scratch/scratch.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013,2014 Bert Freudenberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+var fullscreen = navigator.standalone;
+
+window.onload = function() {
+ if (fullscreen) {
+ document.body.style.margin = 0;
+ document.body.style.backgroundColor = 'black';
+ sqHeader.style.display = 'none';
+ sqFooter.style.display = 'none';
+ }
+ var display = createSqueakDisplay(sqCanvas, {fullscreen: fullscreen, header: sqHeader, footer: sqFooter});
+ function loadAndRunImage(url) {
+ //url = "../demo/mini.image" // for debugging
+ var imageName = Squeak.splitFilePath(url).basename;
+ if (document.location.hostname == "localhost") url = imageName; // load from local folder while debugging
+ display.showBanner("Downloading " + imageName);
+ display.showProgress(0);
+ var rq = new XMLHttpRequest();
+ rq.open('GET', url);
+ rq.responseType = 'arraybuffer';
+ rq.onprogress = function(e) {
+ if (e.lengthComputable) display.showProgress(e.loaded / e.total);
+ }
+ rq.onload = function(e) {
+ display.showBanner("Initializing, please wait");
+ window.setTimeout(function(){
+ var image = new Squeak.Image(rq.response, imageName);
+ var vm = new Squeak.Interpreter(image, display);
+ display.clear();
+ var run = function() {
+ try {
+ vm.interpret(20, function(ms) {
+ if (typeof ms === 'number') { // continue running
+ window.setTimeout(run, ms);
+ } else { // quit
+ sqCanvas.style.webkitTransition = "-webkit-transform 0.5s";
+ sqCanvas.style.webkitTransform = "scale(0)";
+ window.setTimeout(function(){sqCanvas.style.display = 'none'}, 500);
+ }
+ });
+ } catch(error) {
+ console.error(error);
+ alert(error);
+ }
+ };
+ run();
+ }, 0);
+ };
+ rq.send();
+ };
+ loadAndRunImage("http://freudenbergs.de/bert/squeakjs/scratch/Scratch.image");
+};
+
+if (addToHomescreen.isStandalone)
+ fullscreen = true;
+else addToHomescreen({
+ appID: 'squeakjs.scratch.add2home',
+});
diff --git a/scratch/scratch.png b/scratch/scratch.png
new file mode 100644
index 00000000..3e54066d
Binary files /dev/null and b/scratch/scratch.png differ