61 Commits

Author SHA1 Message Date
4d45ea5bf2 js: Turn the resize handle into embedded SVG
This means that it can inherit the current colour from the HTML around
it, and hence adapt properly to changes of colour scheme.
2023-12-07 18:46:03 +00:00
43db4aa38e Support user preferences in the Emscripten frontend.
Here, user preferences are stored in localStorage, so that they can
persist when you come back to the same puzzle page later.

localStorage is global across a whole web server, which means we need
to take care to put our uses of it in a namespace reasonably unlikely
to collide with unrelated web pages on the same server. Ben suggested
that a good way to do this would be to store things in localStorage
under keys derived from location.pathname. In this case I've appended
a fragment id "#preferences" to that, so that space alongside it
remains for storing other things we might want in future (such as
serialised saved-game files used as quick-save slots).

When loading preferences, I've chosen to pass the whole serialised
preferences buffer from Javascript to C as a single C string argument
to a callback, rather than reusing the existing system for C to read
the save file a chunk at a time. Partly that's because preferences
data is bounded in size whereas saved games can keep growing; also
it's because the way I'm storing preferences data means it will be a
UTF-8 string, and I didn't fancy trying to figure out byte offsets in
the data on the JS side.

I think at this point I should stop keeping a list in the docs of
which frontends support preferences. Most of the in-tree ones do now,
and that means the remaining interesting frontends are ones I don't
have a full list of. At this moment I guess no out-of-tree frontends
support preferences (unless someone is _very_ quick off the mark), but
as and when that changes, I won't necessarily know, and don't want to
have to keep updating the docs when I find out.
2023-04-24 10:17:33 +01:00
02f1d55a02 js: Allow CSS to set the font used by the puzzle
This means that the calculated font properties of the HTML canvas now
control what font is used.  The size is overridden, and for monospaced
text so is the family.

I'd like to be able to also specify the monospaced font, maybe using a
CSS variable, but that looks like being quite a lot of extra complexity.

My experience when testing this was that constructing a valid "font"
string for a canvas context is prone to breakage, but broke in a way
that left the font unchanged, so we always set a simple specification
first before trying to construct one from CSS.
2022-12-10 15:30:49 +00:00
7d61c4cee4 js: Explicitly set the height of the status bar
Otherwise it varies depending on whether it has any text in it, which
is distracting.
2022-12-06 21:48:44 +00:00
db5d3bf10e js: Remove align=center from main <div> and make it a <main>
Instead of an align=center HTML attribute, we now centre its contents
using CSS.  Also, this element contains all the important contents of
the page, so it seems appropriate to us the HTML5 <main> element for
this.
2022-12-05 14:07:03 +00:00
83b504af27 js: Remove a layer of <div> from the HTML page
It wasn't doing anything useful, and I was getting fed up with having to
expand it in the inspector.
2022-12-05 14:07:03 +00:00
9cb0abb584 js: Specify a font for the puzzle canvas in CSS
I'd like to use this, but (a) I need it in the HTML for a little while
first, and (b) I think my current implementation may be a bit fragile.
2022-12-05 14:01:53 +00:00
acd1f45152 js: Add an SVG resize handle to the HTML
This is more compact than carefully drawing it on a canvas in
JavaScript.  More importantly, the SVG resize handle scales nicely as
the page is zoomed, or on high-DPI screens.

At the moment, the nice SVG resize handle is removed by JavaScript,
but we need to wait a little while for everyone to get the new HTML
cached before changing that.
2022-12-02 23:43:51 +00:00
e8cdac58e5 js: Don't word-wrap the status bar
With word-wrapping disabled, long status-bar texts fall off the
right-hand end rather than wrapping onto an invisible second line.
This is less confusing because it makes the overflow more obvious.
I've also turned on "text-overflow: ellipsis" for extra obviousness.
Finally, this also the need to explicitly set the height of the status
bar, not that that was doing any harm.
2022-11-28 22:49:30 +00:00
c6e312b252 js: Remove "width" and "height" attributes from HTML <canvas>
They were set to "1px", which isn't a valid value since they're meant to
be integers.  Since they weren't valid, they were ignored.  This doesn't
seem to have caused any trouble, so they may as well be removed.  In any
case, the canvas is invisible until after its size has been set by
JavaScript.
2022-11-27 19:39:18 +00:00
19540d2ef8 js: Hide menus and resize handle when printing 2022-11-26 08:55:36 +00:00
5a2ea91cad js: Subtle extra padding for menus
Each menu item has a -0.5px margin so that the borders of adjacent menu
items overlap, but we don't actually want the menu items to protrude
beyond the containing <ul>.  Adding 0.5px of padding to the <ul>
achieves that.
2022-11-24 23:28:28 +00:00
271fb7f47c js: More conventional marking of menu item types
Menu items that open dialogue boxes are now marked with ellipses, while
menu items that lead to submenus have pointing triangles.

The triangles are implemented as SVG files embedded in data: URLs in the
CSS, which is kind of silly but also works really well.  There are
suitable characters in Unicode, but some of my test systems don't have
fonts containing them, so maybe the SVG is better.
2022-11-24 16:24:59 +00:00
fe29d1cbf5 js: Replace status-bar holder in HTML with status bar itself
This makes the HTML simpler, and will allow for simplifying the JS too.
2022-11-23 23:19:28 +00:00
8445f07827 js: Replace :focus-within with JS-maintained .focus-within
Old browsers (like KaiOS 2.5) don't have :focus-within, but it's pretty
easy to replace the pseudo-class with a real .focus-within class
maintained by JavaScript event handlers.  This is made only marginally
fiddlier by the odd fact that "focus" and "blur" events don't bubble.
2022-11-23 21:56:42 +00:00
52cd58043a js: Add keyboard navigation for menus
Once the input focus is in the menu system (for instance by Shift+Tab
from the puzzle), you can move left and right through the menu bar and
up and down within each menu.  Enter selects a menu item.  The current
menu item is tracked by giving it the input focus.
2022-11-23 21:53:59 +00:00
51b496e118 mines: Grammar fix in instructions 2022-11-18 00:11:39 +00:00
ff406d4edc js: Convert space after tick in menus to a space character
Older Firefox versions don't support "-moz-appearance: none" on radio
buttons, which seems to mean that the specifies padding for them
doesn't appear.  Using a space character instead works fine, so do that
everywhere.  This seems to move the text slightly closer to the tick on
browsers that do support "appearance: none", but the result is quite
acceptable.

This also makes the focus outline on the ticks slightly less weird.
2022-11-15 01:31:01 +00:00
a55c0c188b js: Use -moz-appearance and -webkit-appearance
The "appearance" property is newer than WebAssembly, but major browsers
have much older namespaced versions that we can support as well.
2022-11-15 01:06:35 +00:00
8ef28a4fd6 js: Remove class="text/css" from <style> element
This is the wrong attribute, and the correct type="text/css" is
deprecated by MDN.  Since it's never worked, the deprecated attribute
presumably isn't needed either.
2022-11-12 15:32:18 +00:00
4e3bb8f257 js: Use <li role="separator"> in place of <li class="separator">
ARIA has a "separator" role that has the semantics we want, so let's use
it.
2022-11-12 12:18:59 +00:00
8f40128f08 js: Prettify menu HTML
Now that we're using flex layout, whitespace in the menu isn't scary and
we can use it to make the HTML readable.

Also finally remove the "afterseparator" class that's long obsolete.
You can always use ".separator + *" as a selector instead.
2022-11-12 11:28:39 +00:00
27d41e7cf0 js: Simplify menu CSS a little
Mostly removing redundant rules and simplifying selectors.
2022-11-12 11:22:43 +00:00
60d2bf5930 js: Convert menus to use semantically appropriate HTML elements
Presets are now radio buttons with labels, and menu items that take
actions are now buttons.  The <li> representing each menu item is now a
thin wrapper around another element: a <label> for radio buttons, a
<button> for other buttons, and a <div> for submenu headings.  All of
the things that previously applied to the <li> now apply to that inner
element instead.

This means that presets can now use the standard "checked" attribute to
indicate which one is selected, and buttons can be disabled using the
standard "disabled" attribute.  It also means that we can query and set
the state of all the presets at once through their RadioNodeList.

I think this should also make the menus more accessible, and make it
easier to make them keyboard-controllable.
2022-11-12 09:48:31 +00:00
289342ec33 js: Adjust z-indices of sub-menus and resize handle
The sub-menus should appear in front of the resize handle (but still
behind any dialogue box).
2022-11-01 09:23:41 +00:00
24ce6260d5 js: Pay attention to the device pixel ratio
The CSS "px" unit isn't always a device pixel.  On devices with
high-DPI displays, there can often be multiple device pixels to a CSS
px, while in particularly low-resolution displays (like feature
phones), the user might zoom out to get several CSS px to a device
pixel.  And even on desktop browsers, text zooming controls can change
the ratio.

To make Puzzles' rendering look good on an arbitrary device pixel
ratio, we really want the pixels of the canvas to be device pixels,
not CSS px, so that the canvas doesn't have to be scaled by the
browser for display.  To correct this, we now control the CSS size of
the puzzle canvas, via its containing <div>, to be the canvas size
divided by the device pixel ratio.

There is a significant gap, which is that this doesn't yet track
changes to the device pixel ratio.  This is slightly complicated, so
I'll put it off to the next commit.
2022-10-22 13:55:55 +01:00
9be9a12476 js: Move some styling from style attributes to stylesheet
For consistency as much as anything else.
2022-10-22 13:55:55 +01:00
dbbe9d3750 js: Make the dialogue box heading actually be an <h2>
This is semantically more correct and less ugly as well.
2022-10-18 01:00:49 +01:00
49849e40ec js: Move dialogue-box sizing and positioning from JavaScript to CSS
This has the advantage that if you resize the window while a dialogue
box is active, the dialogue box adjusts itself accordingly.
2022-10-17 23:16:31 +01:00
c90d64f243 js: Move most style settings from JavaScript to CSS
Some elements (generally those created by JavaScript) had their style
parameters set directly by JavaScript.  Putting styles in CSS generally
makes them easier to understand (and fiddle with), so I've done that.
The only styles left in JavaScript are those that are calculated by
JavaScript (like the status-bar size) and the random-seed permalink
visibility because I wasn't quite sure how to handle it.
2022-10-17 22:04:16 +01:00
85d2a7da62 Hide some words in top-level menu items on small viewports
In their normal state, most of the top-level menu items are a verb and
an object, like "Undo move".  This is admirably clear, but on a small
screen the menu can take a lot of space.  In each case the verb alone
is sufficient to know what the button does, so use a media query to
suppress the noun is the viewport is very narrow.  "Very narrow" here
is roughly where the menus would overflow onto four lines in my
browser.
2022-10-07 17:55:06 +01:00
e98ede7a72 Make JavaScript game controls work better in small viewports
In the old design, when they wrapped onto multiple lines, various bad
things happened.  The lines overlapped one another, the lines got
broken within buttons but not between buttons, and if they had got
broken between buttons the left button on each line would have lacked
a left border.

I've made two major changes to fix this.  First, I've switched from
flow layout to flex layout.  This has much better default behaviour,
breaking lines in the right places, not overlapping lines, and even
arranging line-wrapping within a button when the viewport gets really
narrow.

Second, I've given each button a border on all four sides and then
used negative margins to overlap them.  This required changing the
borders from transparent black to opaque grey to make them display
correctly when overlapping.

The result is not quite identical to the old version on a wide
viewport, but I think it's as close as I can get while keeping the new
CSS pleasant.

Ideally, the separator would vanish when it was adjacent to a line
break, but I've not worked out how to do that yet.
2022-10-05 12:52:03 +01:00
0377184510 New puzzle: 'Mosaic'.
This is similar in concept to Minesweeper, in that each clue tells you
the number of things (in this case, just 'black squares') in the
surrounding 3x3 grid section.

But unlike Minesweeper, there's no separation between squares that can
contain clues, and squares that can contain the things you're looking
for - a clue square may or may not itself be coloured black, and if
so, its clue counts itself.

So there's also no hidden information: the clues can all be shown up
front, and the difficulty arises from the game generator choosing
which squares to provide clues for at all.

Contributed by a new author, Didi Kohen. Currently only has one
difficulty level, but harder ones would be possible to add later.
2021-04-25 09:59:15 +01:00
77866e1335 wasm/js/emscripten: Fix page loading race
Using a stunt webserver which artificially introduces a 3s delay just
before the last line of the HTML output, I have reproduced a
uwer-reported loading/startup race bug:

Previously the wasm loading was started by the <script> element,
synchronously. If the wasm loading is fast, and finishes before the
HTML loading, the onRuntimeInitialized event may occur before
initPuzzles.  But initPuzzles sets up the event handler.

Fix this bug, and introduce a new comment containing an argument for
the correctness of the new approach.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-04-22 21:22:48 +01:00
69b5e7513a Another rewrite of the WASM apology message.
Now I've had a chance to collect some more data from browser users,
it's got a list of browsers in which we've definitely seen the WASM
puzzle working (so that if _your_ instance of one of those browsers
fails, you should check it for problems at your end, like
configuration details or overzealous web filtering software), and some
thoughts about what to report.

The result is a lot longer than the previous error message, so I've
put the bulk of it in a <details>. That way it won't look so silly
when it initially flashes up while things are loading.
2021-04-08 18:16:26 +01:00
245e4f8ab4 Reword the apology when web puzzles fail to load.
The old one was totally out of date (it mentioned typed arrays and a
specific set of browser versions against which the previous Emscripten
build had been tested).

Also, a couple of users in the last day or two have reported
mysterious failures of the WASM puzzles, which I haven't been able to
reproduce in the same version of the same browser. So something odd is
going on, and this seems like a good place to put suggestions about
what diagnostic information to send.
2021-04-07 07:16:01 +01:00
1db5961b8b Fix docs link from the JS Rectangles page.
It pointed to rectangles.html, which doesn't exist, in place of
rect.html which does.
2018-07-24 18:38:00 +01:00
12cb1adc88 Galaxies: clarify wording of completion condition.
A user mailed me today having found it less than clear from the docs
that Galaxies will only accept a solution if the set of filled-in grid
edges consists of _exactly_ the ones that separate two distinct
regions, rather than consisting of _at least_ those and perhaps others
which neither break rotational symmetry or disconnect any region.
2018-04-17 18:30:48 +01:00
61e7111784 Build test HTML wrapper pages for the Javascript puzzles.
This should make it less annoying for me to do local testing of the JS
output of a build, before I push a change. There's a new
build.out/jstest directory containing .html files suitable for loading
in a local browser, which refer to the JS files via an appropriate
relative path to the existing build.out/js directory.
2017-09-20 18:03:44 +01:00
a0a581c8b5 Fix borders on the HTML menu bar.
Commit ef39e6e17 made a goof in which the 'New game' button had no
border on the left and an accidental extra one on the right, which I'm
really not sure how I failed to spot when I tested it yesterday.
2017-09-07 18:44:58 +01:00
ef39e6e173 HTML: move 'New game' back out of the drop-down menu.
The only user to send me a comment today on the new layout said that
that menu item in particular is annoying to have hidden behind more
clicks, so by a vote of one to nothing, it's back out in the open.
2017-09-06 21:49:39 +01:00
721119e4a6 Support for loading games in Javascript puzzles.
This is done by showing a dialog containing an <input type="file">
through which the user can 'upload' a save file - though, of course,
the 'upload' doesn't go to any HTTP server, but only into the mind of
the Javascript running in the same browser.

It would be even nicer to support drag-and-drop as an alternative UI
for getting the save file into the browser, but that isn't critical to
getting the first version of this feature out of the door.
2017-09-05 20:58:05 +01:00
1bf591a573 Support for saving games in Javascript puzzles.
This is done by getting midend_serialise to produce the complete
saved-game file as an in-memory string buffer, and then encoding that
into a data: URI which we provide to the user as a hyperlink in a
dialog box. The hyperlink has the 'download' attribute, which means
clicking on it should automatically offer to save the file, and also
lets me specify a not-too-silly default file name.
2017-09-05 20:56:55 +01:00
5e53ec5e36 Organise the JS menus/buttons bar more like a menu.
I'm about to introduce a few more options, and the button bar is
already a bit wide, so I think I should shrink it horizontally before
putting more stuff on it. So I've organised the options into something
more like the Game and Type submenus that the desktop versions use.

However, I haven't gone quite all the way, on the basis that the web
versions will be at least slightly playable on devices without much
keyboard, which makes it worth keeping the in-play actions (Undo,
Redo, and to a lesser extent Restart and Solve) accessible as
top-level buttons in a single click each.

As part of this change, I've also separated the menu bar into a
drop-down menus section and a top-level buttons section with a gap
between them, and put a signalling "..." on the end of the titles in
the former section.

This change also removes the class="left" on the game-type menu and
its submenus, which were previously there to deal with that menu being
all the way over on the far right of the menu bar. But the CSS for
those classes is still there in jspage.pl, and should still work if I
need it again in future.
2017-09-05 20:54:19 +01:00
bc2c1f69fd Javascript puzzles: switch to a CSS-based drop-down system.
The previous control buttons and dropdowns based on form elements were
always a bit ugly: partly in a purely visual sense, and partly because
of the nasty bodge I had to do with splitting the usual 'Custom' game
type menu item into two (to get round the fact that if an element of a
<select> is already selected, browsers won't send an event when it's
re-selected). Also, I'm about to want to introduce hierarchical
submenus in the Type menu, and <select> doesn't support that at all.

So here's a replacement system which does everything by CSS
properties, including the popping-up of menus when the mouse moves
over their parent menu item. (Thanks to the Internet in general for
showing me how that trick is done.)
2017-04-26 21:48:11 +01:00
6860c65bb3 Add a new puzzle: Palisade. 2015-10-18 17:53:28 +01:00
f306b9db55 Magnets: you can now mark clues as done 2015-06-10 21:58:59 +01:00
f0750894ff Undead: you can now mark clues as done 2015-05-26 22:04:35 +01:00
486d2c8a76 Towers: you can now mark clues done 2015-05-22 08:18:53 +01:00
362bf8d450 New puzzle from James Harvey: 'Tracks'. 2015-02-08 16:23:32 +00:00