chiark / gitweb /
Remove trailing commas at the ends of initialiser lists. IE 8 and 9
[sgt-puzzles.git] / emcclib.js
index cc6df284ecdd7ca0af9aa488bf117ff026675b2e..57dd2c4fd649b92e0cc83bce3afd3ef1ec4bdef2 100644 (file)
@@ -2,7 +2,11 @@
  * emcclib.js: one of the Javascript components of an Emscripten-based
  * web/Javascript front end for Puzzles.
  *
- * The other parts of this system live in emcc.c and emccpre.js.
+ * The other parts of this system live in emcc.c and emccpre.js. It
+ * also depends on being run in the context of a web page containing
+ * an appropriate collection of bits and pieces (a canvas, some
+ * buttons and links etc), which is generated for each puzzle by the
+ * script html/jspage.pl.
  *
  * This file contains a set of Javascript functions which we insert
  * into Emscripten's library object via the --js-library option; this
@@ -61,13 +65,56 @@ mergeInto(LibraryManager.library, {
      * the name of the preset. (The corresponding game_params stays on
      * the C side and never comes out this far; we just pass a numeric
      * index back to the C code when a selection is made.)
+     *
+     * The special 'Custom' preset is requested by passing NULL to
+     * this function, rather than the string "Custom", since in that
+     * case we need to do something special - see below.
      */
     js_add_preset: function(ptr) {
+        var name = (ptr == 0 ? "Custom..." : Pointer_stringify(ptr));
+        var value = gametypeoptions.length;
+
         var option = document.createElement("option");
-        option.value = gametypeoptions.length;
-        option.appendChild(document.createTextNode(Pointer_stringify(ptr)));
+        option.value = value;
+        option.appendChild(document.createTextNode(name));
         gametypeselector.appendChild(option);
         gametypeoptions.push(option);
+
+        if (ptr == 0) {
+            // Create a _second_ element called 'Custom', which is
+            // hidden.
+            //
+            // Hiding this element (that is, setting it display:none)
+            // has the effect of making it not show up when the
+            // drop-down list is actually opened, but still show up
+            // when the item is selected.
+            //
+            // So what happens is that there's one element marked
+            // 'Custom' that the _user_ selects, but a second one to
+            // which we reset the dropdown after the config box
+            // returns (if we don't then turn out to select a
+            // different preset anyway). The point is that if the user
+            // has 'Custom' selected, but then wants to customise
+            // their settings a second time, we still get an onchange
+            // event when they select the Custom option again, which
+            // we wouldn't get if the browser thought it was already
+            // the selected one. But here, it's _not_ the selected
+            // option already; its invisible evil twin is selected.
+            //
+            // (Actually, they're not _identical_ evil twins: we label
+            // the two slightly differently. The visible one that the
+            // user can select is labelled "Custom..." to hint that it
+            // opens a dialog box, whereas the invisible one that's
+            // left shown after the box closes is just "Custom",
+            // because that's telling you what you _have_ got
+            // selected.)
+            option = document.createElement("option");
+            option.value = value;
+            option.appendChild(document.createTextNode("Custom"));
+            option.style.display = "none";
+            gametypeselector.appendChild(option);
+            gametypehiddencustom = option;
+        }
     },
 
     /*
@@ -93,7 +140,14 @@ mergeInto(LibraryManager.library, {
      * which turn out to exactly match a preset).
      */
     js_select_preset: function(n) {
-        gametypeoptions[n].selected = true;
+        if (gametypeoptions[n].value == gametypehiddencustom.value) {
+            // If we're asked to select the visible Custom option,
+            // select the invisible one instead. See comment above in
+            // js_add_preset.
+            gametypehiddencustom.selected = true;
+        } else {
+            gametypeoptions[n].selected = true;
+        }
     },
 
     /*
@@ -271,8 +325,8 @@ mergeInto(LibraryManager.library, {
         ctx.moveTo(x1 + 0.5, y1 + 0.5);
         ctx.lineTo(x2 + 0.5, y2 + 0.5);
         ctx.lineWidth = width;
-        ctx.lineCap = '1';
-        ctx.lineJoin = '1';
+        ctx.lineCap = 'round';
+        ctx.lineJoin = 'round';
         ctx.strokeStyle = colour;
         ctx.stroke();
         ctx.fillStyle = colour;
@@ -300,8 +354,8 @@ mergeInto(LibraryManager.library, {
             ctx.fill();
         }
         ctx.lineWidth = '1';
-        ctx.lineCap = '1';
-        ctx.lineJoin = '1';
+        ctx.lineCap = 'round';
+        ctx.lineJoin = 'round';
         ctx.strokeStyle = Pointer_stringify(outline);
         ctx.stroke();
     },
@@ -321,8 +375,8 @@ mergeInto(LibraryManager.library, {
             ctx.fill();
         }
         ctx.lineWidth = '1';
-        ctx.lineCap = '1';
-        ctx.lineJoin = '1';
+        ctx.lineCap = 'round';
+        ctx.lineJoin = 'round';
         ctx.strokeStyle = Pointer_stringify(outline);
         ctx.stroke();
     },
@@ -421,6 +475,7 @@ mergeInto(LibraryManager.library, {
         blitters[id] = document.createElement("canvas");
         blitters[id].width = w;
         blitters[id].height = h;
+        return id;
     },
 
     /*
@@ -692,5 +747,5 @@ mergeInto(LibraryManager.library, {
      */
     js_focus_canvas: function() {
         onscreen_canvas.focus();
-    },
+    }
 });