Thunderbird/NextGeneration/View
Our view consists of 4 parts:
- HTML, which defines the window layout, i.e. where which element is placed
- CSS, which defines the window looks, i.e. colors, sizes, margins, borders, and icons
- JavaScript that
- populates the data in the view
- handles user input and reacts to it
- Localization strings
HTML
The HTML defines the window content.
Our HTML should be purely structural and contain only elements for widgets, and for layout boxes. It should avoid all style, and all code.
Event handlers can be added in JavaScript using addEventListener(), e.g. in an init() function.
CSS
CSS should contain all style, and only style.
Style means colors, sizes, margins, borders, icons, UI animations, and similar things usually defined by CSS.
All images should be references in CSS, not the HTML.
All CSS should be in a file with the same filename as the HTML, with the file suffix .css, and placed in the same directory. This is unlike XUL, but makes it much easier to edit.
Themes/skins can selectively override CSS rules of the standard application, and do not need to copy the entire set of CSS rules. Furthermore, the application CSS should try hard to centralize global values like background and foreground colors, to make it easy for themes to override them globally, in a way that does not break often.
Localization
All user-visible text and messages (aside from values) are in localization files.
File type will be .properties files, in a name=value format, whereby value might contain named placeholders like %servername%.
HTML will be localized with a library function that replaces text nodes and element attributes with the localization strings.
- E.g. <button tr-attr=”title:reply.tooltip” translate=”reply” /> will be filled out as <button title=”Create a new message with...”>Reply</button>
JavaScript will have convenient access to translations, including variable replacement
- E.g. tr(“reply”) == “Reply”
- or tr(“hostNotFound”, { servername : “imap.mail.yahoo.com” }) == “Server imap.mail.yahoo.com not found. DNS resolution failed”.
JavaScript
Each HTML file has a corresponding js file with the same filename and .js suffix, in the same directory.
Populate data
When a window or a frame is shown and loaded, it needs to be filled with data. Each window or section should have a function load(obj) whereby obj is the model class for the data that the window shows. The function should access the model properties and fill them into the corresponding HTML elements.
It should then install observers on the model object, to be notified of changes. If changes happen, this object should be displayed again, to update the UI with the changes.
React to user input
Each button, menu item, hotkey and drag and drop action is wired to a JS function that handles this UI feature.
As discussed under section All logic in model, the code here should be minimal.
- Example: Ideally, the Reply button handler would be only 2 lines:
- Message replyMessage = currentMessage.reply();
- Composer.open(replyMessage);
- The code to create a reply is then in the model function Message.reply(). This creates the recipient lists, the subject with “Re: “, the quoted body etc., and none of that needs access to the UI. The Composer.open() then does all the work to open a new composer window or frame, and populate this message in the composer edit fields.