How to add a new window to the ygwm framework ?
20120829: init by whygee@f-cpu.org 20120906

UNFINISHED


 

Windows and keys

A window or tool can be started/launched/run by

All these mechanisms rely on an internal system of "keys" : a key is a short string that names and identify the window. So the first thing to do is to choose a key that doesn't exist yet. Look at keys.js to find a suitable key : unambiguous, distinctive, human-readable but short.

Here is a list of the keys currently used on this interface :

Then look at the template and how it is written, as well as how it is connected to the other parts. The template files are available at

 test/template.js
 test/template.en.html

HTML

Languages and names

The .html suffix is always preceded by a 2-characters language name. Always have a .en.html available because this is the fallback language when the currently selected language has no translation. For a list of the currently supported languages, look at gui-js/lang.js

Basically you can start by writing a HTML page containing your text, with all the markup but keep the JavaScript separate because it will not be interpreted inside the HTML page.

Except for special cases, the convention is to use the same file name for the JavaScript and HTML files, in the same directory.

Format

The HTML files contain a normal page but stripped from headers, so it's the contents of the <body> tag. There is often a special header so people can still see the contents but without all the style sheets and dynamic alterations. It is also search engine friendly :-)

Anything in the HTML file before the <!--startHTMI--> tag or after <!--endHTMI--> is ignored and not displayed in a ygwm window.

The HTML can also be post-processed after it is displayed by gui-js/winman.js:patchInnerLinks() so you can add some nifty stuff:

 

Gluing it all with JavaScript

So you can write your HTML code and look at it in a normal browser (more or less). Integrating this HTML, which can get VERY dynamic and depend on many other features offered by ygwm and all the other files, can be quite delicate.

The easy way : doc.js

doc/doc.js starts with a list of keys it handles itself, with the necessary properties such as menu bar title, menu bar name, color style, and JS code to execute when creating the page.

You may add your own page in the list, with the caveat that the key name is also the path to your file. The language (en, fr...) and .html suffixes are appended automatically.

The harder way : write your own code

The presentation is rendered from HTML but is controlled (through the browser's DOM) by JavaScript. So you need to write JavaScript code that gets integrated into the whole ygwm system.

This starts with a .js file, ideally of the same name as the key (or similar). The first thing to do is to declare a new object, which will contain all our data and code, cleanly separated from the rest of the software :

// MyKey.js file
MyKey={
  // my private data and code
}
But to work and become integrated into ygwm, it must be "connected" somehow.

The method needs these steps :

• Register the new .js file at the end of the list in index.dev.js

It contains the js_list array, with the names of all the files to use. It's the first level of loading the whole site, the objects and codes are loaded and analysed in order but initialisation comes later.

It works a bit like a fstab file: just put 1 and 1, because a 0 will prevent your file to work both in the development and production versions of the site.

 [1, 1, "Mydirectory/MyKey"], // the .js extension is added automaticly
Be careful to add your filename at the end, BUT before the "keys" and "body_start" files.

• Register the new object by "pushing" it in the list of objects.

The list of all the objects to initialise is called init_obj, as defined in body_first.js. To register a new object in it, just surround the object declaration with some code :
init_obj.push(MyKey={
  // my private data and code
});

• Add a startup/initialisation function in your object

init_obj[] is scanned after all the files are loaded and analysed. For each of the objects in the array, the initialisation code will execute a function inside them, called init_obj() indeed.

This initialisation code typically adds a new entry in the menu bar and/or instantiates or resets data. This is the second stage of startup.

init_obj.push(MyObj={
  // my private data and code

  init_obj: function(){
    // Adds a new menu item for the key "MyKey"
    menu.subMenuItem(menu.list["Doc"],["My Key","Ma clĂ©"], "MyKey");
  }
});

If your code does not need any initialisation or integration in the menu bar, you can skip all the init_obj steps.

 

Registering the new key

If you don't go through doc/doc.js, there are two other ways to register a new key :

 

Starting the key's window

When the key is called, winman.js will look at the key list, find the associated JavaScript object and call the start() inside it.

That is where the window is created. start() will return the window ID that was created so the key can be marked as "open" in case multiple open windows are not allowed.

The window creation, population, initialisation etc. is the responsibility of start(), that you have to create and adapt to your needs. Look at the template and similar files for details of how to call ygwm.new_window().

 

Triggers

Keys can receive parameters or new data. Yes ! You can send messages or force a configuration parameter if you provide the code to analyse it. The only limitation is the size and encoding: these data are passed as a string and may be in a URL, such as this one :
<a href="#!ASM/asm#a?MOV%208000h%20R1">

The whole key starts after the #! signs but it can also contain other # signs, which are separately passed to the window AFTER it is opened.

The magic happens by declaring a function called "trigger" in the window object. This function will be called by the keys manager in winman.js, passing everything that follows the first # sign/

 

Compaction

In the above procedure, I assumed that you are using index.dev.html because this is the one that loads the other .js files dynamicly.

The file index.html however is generated by a compaction system which gathers all the .js files and reduces the size.

Once your code is working well with index.dev.html, you can regenerate the index.html with the following procedure :

1) Flush your browser's cache. You don't want old versions of the files to be used.

2) start index.dev.html#!compact

3) click on "Save index.prod.html"

4) save the generated file in the same subdirectory as the currently running index.dev.html

5) if a JavaScript error appears when running index.html, re-do 4) after enabling the "Debug \n" option, so you can locate the error's cause more easily. A forgotten semicolon is the most probable cause. Then redo 4) without the option to check that it still works.