shithub: puzzles

Download patch

ref: 9826ecd5c3b79320823cd762880c302253e88d06
parent: 3e39f6b80b2b6e4308e2d3a9fa436cbbb9d9b621
author: Simon Tatham <anakin@pobox.com>
date: Sun Mar 31 05:58:46 EDT 2013

Apply a bodge to arrange that if the user selects Custom from the game
type dropdown, we still get an 'onchange' event if they select it a
second time. Normally this wouldn't happen, because onchange means
what it says and we only get it if a _different_ element is selected.

My solution is to create two list items called Custom, set one of them
as display:none to stop it showing up when the list is dropped down,
and to select it after the configuration box closes.

[originally from svn r9788]

--- a/emcc.c
+++ b/emcc.c
@@ -723,7 +723,7 @@
         js_add_preset(name);
     }
     if (thegame.can_configure)
-        js_add_preset("Custom");
+        js_add_preset(NULL);           /* the 'Custom' entry in the dropdown */
     else if (custom_preset == 0)
         js_remove_type_dropdown();
 
--- a/emcclib.js
+++ b/emcclib.js
@@ -61,13 +61,48 @@
      * 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.
+            option = document.createElement("option");
+            option.value = value;
+            option.appendChild(document.createTextNode(name));
+            option.style.display = "none";
+            gametypeselector.appendChild(option);
+            gametypehiddencustom = option;
+        }
     },
 
     /*
@@ -93,7 +128,14 @@
      * 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;
+        }
     },
 
     /*
--- a/emccpre.js
+++ b/emccpre.js
@@ -78,7 +78,14 @@
 // The <select> object implementing the game-type drop-down, and a
 // list of the <option> objects inside it. Used by js_add_preset(),
 // js_get_selected_preset() and js_select_preset().
+//
+// gametypehiddencustom is a second copy of the 'Custom' dropdown
+// element, set to display:none. This is used by a bodge in emcclib.js
+// (see comment in js_add_preset) to arrange that if the Custom
+// element is (apparently) already selected, we still find out if the
+// user selects it again.
 var gametypeselector = null, gametypeoptions = [];
+var gametypehiddencustom = null;
 
 // The two anchors used to give permalinks to the current puzzle. Used
 // by js_update_permalinks().