GithubHelp home page GithubHelp logo

erkyrath / glkote Goto Github PK

View Code? Open in Web Editor NEW
26.0 26.0 11.0 2.64 MB

A Javascript display library for IF interfaces

Home Page: http://eblong.com/zarf/glk/glkote.html

License: MIT License

CSS 2.73% JavaScript 77.43% HTML 19.84%

glkote's People

Contributors

curiousdannii avatar erkyrath avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

glkote's Issues

Last space on the line collapses

When I set up the glkote HTML structure, I didn't use white-space: pre-wrap because it was 2008. Instead I used   in the minimal number of places to preserve output spacing.

I didn't use   for trailing spaces at the end of a line. This was a compromise -- a lot of games print trailing spaces on paragraphs, due to sloppy coding. If I change those to special characters, I'm making copy-and-paste significantly fuglier in a fairly common case.

However, Dannii points out that Jigsaw uses meaningful trailing space when displaying the jigsaw pieces.

Obvious options:

  • Switch to pre-wrap.
  • Transform trailing spaces.
  • Transform trailing spaces, but only in spans that have non-normal style.

Support multiple instances of each module

Currently, every module in the Glk JS ecosystem is a global object (window.GlkOte, window.Dialog, window.Quixe, etc). We would like to support the possibility of more than one. It should be possible to create instances of each and start them running, with each one talking only to its peers.

This was one of the issues mentioned when talking about ES modules (#39). However, I want to address this separately and first.

The plan is as follows:

Every module will define a JS class (e.g. GlkOteClass). (Recall that JS classes are just functions that you instantiate by writing new GlkOteClass().)

For backwards compatibility, each module will define an instance of its class (GlkOte). If you load the module.js in the old-fashioned way, you will wind up with window.GlkOteClass and window.GlkOte. A page can go ahead using window.GlkOte just as before. However, you can create more instances as needed.

An instance must be inited by calling its init() method. You may pass in associated module instances if you want:

GlkOte.init({ Dialog: new DialogClass() });

If you don't, the instance will create its own module instances where needed.

Each class has two new methods:

  • inited(): Returns whether the instance has been succcessfully inited.
  • getlibrary(val): Returns the associated module instance by name.

For example, GlkOte.getlibrary('Dialog') will return the Dialog instance being used by that GlkOte instance. Glk.getlibrary('GlkOte') will return the GlkOte being used by that Glk API instance. And so on.

When implementing higher-level modules, it's generally cleaner to fetch low-level modules using getlibrary() rather than trying to cache a reference at init() time. (Init order is a pain in the butt.)

Mobile: Provide a user-visible way to bring up the keyboard

Apropos #48

iOS native IF interpreters (including, at least, Frotz and iosglk) have a feature in common: they have a header bar at the top of the screen with a keyboard button on it. When you click the keyboard button, the keyboard opens; when you click it again, the keyboard dismisses.

That button is especially important on the web, because it's easy to accidentally dismiss the keyboard by tapping anywhere on the screen except on the input line. When you do that, the only way to bring the keyboard back is to guess where the input line is and tap there.

Plus, sometimes you want to dismiss the keyboard (to see more text on the screen), and then easily bring it back again.

I think glkote (or Parchment??) should offer a header bar like this. The bar should include the title of the game and a keyboard button. (And maybe someday it should include text styling options: font, size, light/dark theme, etc.)

Add reasonable default metrics

Unlike RemGlk, GlkApi can't handle an incomplete metrics definition, producing NaNs in glk_window_get_size (and probably other functions). It should ideally support incomplete metrics (such as just providing a width and height), giving reasonable defaults for the other properties.

Poorly sorted files

In dialog.js, if you hit Edit, the list of data files isn't always properly ordered. It's supposed to be Saves, Transcripts, Data but I've seen categories listed twice.

This turned up after running externalfile.ulx and then Advent.ulx.

Possible improvement for screen readers

@dfabulich wrote

Lectrote is only slightly better in this sense: it uses an HTML renderer, so it can tell VoiceOver about individual paragraphs. When you type a command, you remain focused on the command area, and you have to navigate backward through the text to find the new text and read that. But at least on Lectrote it is possible to navigate paragraph by paragraph. (Lectrote does mark the transcript window as a live region, but macOS VoiceOver doesn't appear to notice.)

I wonder if all that would need to be done to improve this would be to stop GlkOte from manually focusing the input element (with an option, the current code is probably best for non screenreader users.)

Use native map, each, etc

There's no need to use jQuery map/each/etc functions, and it just makes debugging so much harder (as the debugger will step through all the layers of jQuery code.)

glk_request_line_event and non make_arg_array arrays

So I've run into a problem with my new project: Calling glkapi.js's glk_request_line_event doesn't work for arrays which haven't been passed to make_arg_array, and there doesn't seem to be an easy way to pass them to make_arg_array because neither it nor ArgInt/ArgChar are exposed on GiDispa. (We mustn't have ever tested ZVM with GiDispa or it wouldn't have worked.)

I see two options: expose those functions, or make retain_array not throw if it doesn't work. But I don't really understand the purpose of the system, so I don't know which option to take.

No 'content_box' in glk_window_close

Towards the bottom of glk_window_close it tries to set box = content_box;, but there is no content_box in the file.

This must mean that that branch is never run. And so the whole keydamage_flag stuff is unncessary?

Stylehint support

Issue for tracking progress.

Code: https://github.com/curiousdannii/glkote/tree/stylehints2

  • Basic stylehint support
  • Check how it works with autorestoring
  • Support for garglk text formatting
  • Window background colours
  • Gargoyle style window padding?
  • Paragraph stylehints
  • Handle window clearing
  • Update glkote.css
  • Finalise stylehint protocol
  • Style distinguish/measure
  • Add glkote option to disable stylehints (useful for a terp to expose to the user)
  • Documentation

Mobile: Invite the user to tap to bring up the keyboard on first load

https://iplayif.com/?story=http%3A%2F%2Fwww.ifarchive.org%2Fif-archive%2Fgames%2Fzcode%2FBronze.zblorb

Glkote automatically focuses the primary <input> element on first load, but this doesn't actually open the on-screen keyboard on iOS Safari.

Worse, it does kinda sorta "pseudo-focus" the <input> element, such that my PR #51 doesn't show the "Tap here to type" hint, because it thinks that the <input> element is "already focused." (It is the document.activeElement in that case.) 😒

Believe it or not, I think the best thing is actually not to focus the <input> tag on first load on touchscreen devices, and to instead rely on my PR #51 "Tap here to type" to get folks into the game. (Or perhaps make tapping anywhere activate the on-screen keyboard, but only the first tap on first load…?)

Async API

So a couple of years ago, I tried out how an async GlkOte API might work. I'd like to revisit this as an option for GlkOte itself rather than pursuing it as a fork.

So the main issue is that it's just not possible to synchronously access the filesystem on some systems which I'd be interested in bringing GlkOte to, namely cloud file hosting services like Dropbox and Google Drive, as well as mobile apps using Cordova, and even IndexedDB in the browser. But it would also give the opportunity to make the JS API simpler: rather than having the user set up callbacks and then a handler that has to distinguish whether it's a Glk even or a special event and then call the callback func, which now has a different context than the original function, an async API would let you simply call the one function you want, and get back the result in the same function context, just like the C API! So if you call glk_select you'll get back a Glk event and nothing else (ideally without even needing to call Glk.update - that should be handled internally), if you call glk_fileref_create_by_prompt you'll get back the file result without needing to worry about handling arrange events that might have occurred, etc.

The main disadvantage is that this would be a major breaking change, not just to how GlkOte is used, but it could require substantial changes to the end applications, Quixe etc. But I'd be willing to make those changes if we went forward in this direction.

So previously I guessed that too many Glk functions would need to be async. Partly this was because I thought that the glk_get_ functions might be able to pull data from the filesystem as it went. For something like Dropbox that's just not going to be feasible. Instead the Dialog system should be simplified to say that files to be read just need to be read and buffered in their entirety. (Files being written could perhaps still be periodically flushed, as feedback from that wouldn't need to be received back immediately.) So the functions I think would need to be made async would be:

  • glk_fileref_create_by_prompt
  • glk_fileref_does_file_exist
  • glk_select
  • glk_stream_open_file(_uni)

Possibly these:

  • glk_exit?
  • glk_fileref_delete_file? (probably not as it gives no feedback as to whether it was successful?)
  • glk_image_get_info (for non-blorbed images)
  • glk_select_poll (but only for symmetry)
  • glk_stream_open_resource(_uni)? (probably not necessary)

I had originally included some window functions as I thought it would be better to not just assume that new windows can always be opened. I'd also included the sound channel functions, because who knows, they might need to be async? We could reconsider them later. It may be possible to shift them to async without an addition breaking change, or that could be GlkOte version 4.

Alternative autosave format

I've been brainstorming about how I would like to implement autosaving in ZVM, and if the memory and stack start as typed arrays then it would make sense to keep them that way. What if an autosave file was a Quetzal file with an extra chunk of JSON data for the remaining VM properties, either stored as ASCII or as UTF-16 if necessary. (Not UTF-8 to simplify processing - although that would really be up to the VM.)

I'm raising this here because it would need a change to the Dialog libraries.

When Quixe changes to using typed arrays you may want to change the format as well. Though the 100MB+ blorbs are mostly media, and the VM's RAM would still fit in a JS Array so the current format would work.

Add timer to the API

A (repeating) timer interval should be added to the JSON API, so that RemGlk can request timer events.

Possible plan for node compatibility etc

Many years ago I sent a PR for node support (#18). I think I've come up with a better plan now.

So the main problem with how the various components are organised at present is that the references to the other components are hardcoded using globals. I think it's much better if each component is a factory function rather than a singleton, so that the framework that uses GlkOte can construct the components in the order it wants, and pass in the references to the other components dynamically.

So like my old PR, I'd like to keep that aspect of it. The differences from the old PR would be:

  • use ES modules rather than CommonJS modules
  • provide a file that would load the components and set them up
  • use Rollup to bundle that file and the component files to produce an output file that would be a drop-in replacement for the current concatenated glkote.js used by Quixe

It should be possible to do this with literally no other changes required for classic Quixe usage, but to then give Parchment/Lectrote/etc the flexible to use the components as they need.

GlkApi notes

GlkApi's gli_get_line doesn't add a NULL byte.

Also, just to check my understanding of the spec, if it reads a line break, that line break should be copied to the buffer and then a NULL, not replaced by the NULL, right?

Support style hints

glkapi.js still says:

/* Style hints are not supported. We will use the new style system. */

At least six years later, the new style system has yet to manifest. :) In the meantime it would be really nice if quixe could use the old style system. (And perhaps add a couple more user styles to glk to tide us over in the meantime?)

Escape key works inconsistently between Safari and Chrome

Noted in this thread: https://intfiction.org/t/release-along-with-parchment-interpreter/61411/20

Testing in https://eblong.com/zarf/glulx/quixe/quixe/play-remote.html?story=stories/Advent.ulx.js : If the input focus is off the input line, hitting a normal key (e.g. space bar) refocuses and enters the key. Does escape do the same? Yes in Safari, no in Chrome.

Same problem with the delete key, now that I check.

This becomes noticeable in keystroke input. (Type HELP for example.) Hitting escape should quit the help menu, but this breaks in Chrome if the input focus has come loose. It's a little shaky even in Safari, where you may have to hit escape twice.

Unicode functions are not TypedArray safe.

The truncation tests in unicasetest.inf fail if glk_buffer_canon_normalize_uni is passed a Uint32Array. Possibly the other functions would fail under the right circumstances, so I'm going to pass normal arrays to all of them just to be safe.

(I know GlkApi wasn't written to be used with TypedArrays, so it's a testament to its quality that everything else up until this point has worked!)

Move Blorb functionality from Quixe's GiLoad to a Blorb class/library in this repo

GlkOte and GlkApi both depend on GiLoad, but purely for its Blorb functions. I think it would make more sense for those to be found in this repository, so that there aren't any external dependencies, and so Quixe isn't required for other VMs. It could be called "Blorb", but would also need to support the JSON external resources system.

A text buffer status window keeps wanting to be scrolled

https://github.com/curiousdannii/parchment/tree/glkote-test

I've rejigged Parchment to use the code from the master branch of glkote. You'll need to ensure your checkout has retrieved all the submodules, but you won't need to run any build step. It will need to run from a webserver (not just a "file:" URL).

screenshot of the problem

So TADS creates a two line text buffer status window, and something must be up with the measurements because it keeps trying to scroll and putting up the More indicator.

Undeclared fref variables

In two places variables called fref are used without declaring them first, which causes an error to be thrown in strict mode:

glk_fileref_create_temp

glkote/glkapi.js

Line 4896 in dd0c77d

fref = gli_new_fileref(ref.filename, usage, rock, ref);

glk_fileref_create_by_name

glkote/glkapi.js

Line 4904 in dd0c77d

fref = gli_new_fileref(filename, usage, rock, null);

I don't think they need to be global variables so they could just be changed to var fref?

In a typical single text-buffer set up move the scrollbar to the page side

It would in theory be possible to detect whether the window arrangement has a typical single text-buffer, and if so to do some shenanigans to move the scroll bar to the side of the page. Maybe the <div> dimensions would be stretched to the page limits, and an inner div (or padding?) was used to limit the width of the window. If GlkOte was ever changed to use the flex box system it might be simpler?

Low priority, and rather hacky, but raising this issue so that the idea isn't forgotten.

Support a transcript-saving option

An option to fling every input and output at an AJAX handler, so the server can save user transcripts.

Actually, use JSON (in the GlkOte standard form).

This imitates what IFComp currently does, but better. (Take a look at that to make sure I'm not missing any features. Game ID?)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.