Intro

Wamer is a toolkit for developing Web-applications. It includes text editor with syntax highlighting (CodeMirror), accompanied with variety of supporting tools like The key feature of Wamer is the component-based development support, which allows decomposing and assembling your web application to/from relatively small independent reusable components.

Wamer doesn't include any third-party "engines" into your web pages. Your application will be pre-assembled to pure HTML/CSS/JS files.
[The only exclusion: jQuery lib will be referred from your page if js is in use]

It’s assumed the user is familiar with HTML, CSS and JS coding.
online tool for developing high-performance Web Applications

Basics

That's how Wamer screen is usually looks

1) main menu;

2) frequently used command buttons;

3) different view tabs;

4) editor command buttons;

5) editor area;

6) stencil nav panel (stencil is a decomposition unit. See below about it);

7) status bar contains info about object under edit (here it is the page named "index" from the project "Wamer Doc")


It's easy as 1-2-3

Run Wamer. online tool for developing high-performance Web Applications tab is active.


Enter some markup, for example <h1>It's easy</h1>
Click online tool for developing high-performance Web Applications button (leftmost in editor command buttons) to save the changes.

online tool for developing high-performance Web Applications

Then click online tool for developing high-performance Web Applications tab and see a result.

online tool for developing high-performance Web Applications

Let's add some style to the page.
Open tab and enter h1 {color: red;}
Click online tool for developing high-performance Web Applications button.

online tool for developing high-performance Web Applications

Click online tool for developing high-performance Web Applications tab to see the result.

online tool for developing high-performance Web Applications

Let's now "animate" the page with some js code.
Open online tool for developing high-performance Web Applications tab and enter $('h1').click (function () { $(this).css ('color', 'blue'); });

online tool for developing high-performance Web Applications

Again, click online tool for developing high-performance Web Applications button, then online tool for developing high-performance Web Applications tab.
Click on red "It's easy" caption.
It will change to blue.

online tool for developing high-performance Web Applications
Now then

To create some small web-page we make markup under online tool for developing high-performance Web Applications tab, add some style under online tool for developing high-performance Web Applications tab, and accompany with the js code under online tool for developing high-performance Web Applications tab. (And yes, we use jQuery)
We may see an interim results under online tool for developing high-performance Web Applications tab.

Assembly results

To get your application assembled and ready to use click online tool for developing high-performance Web Applications button (to the right of main menu).

In the dialog box that opens, click on here reference and save one zipped file where you want.
The file name is of the form WAPD<some unique number>.ZIP

What is in the ZIP:
<page name>.HTML, <page name>.CSS, <page name>.JS - HTML file of the web-page, accompanied with its CSS and JS;
backup folder - backed-up source of the project. It may be used to restore your project in the case of any trouble.
You may import the entire project (file with extension .wamerprj) via Project | Import, or copy/paste codes from individual parts of the project contained in the unpacked subfolder.

Editor functions

There are 5 commands buttons on the editor panel for frequently used functions

online tool for developing high-performance Web Applications

Their purpose (left to right):
Save - validate and save the tab content. (See the section below about the validation);
Undo - undo the last change;
Redo - redo the last undone change;
Validate - validate the tab content;
Help - help on editor key combinations.

Press F1 in editor or click the Help button for more info.

Validation

Validation refers to a certain procedure that will ensure that you have coded exactly what you mean.
Press Validate (online tool for developing high-performance Web Applications) button when in editor. You'll get "OK" message if no problems will be found.
Your code is also validated before saving.

Script is validated by well-known JSHint tool, which scans a program written in JavaScript and reports about commonly made mistakes and potential bugs. (C)

Style is validated via preprocessing with Less tool. It doesn't mean that you have to use Less features (like variables, mixins, etc.) in your style, but valid CSS is also valid Less code. So, if you make a typo in your style then you'll most likely will get LESSParseError.

Validity criteria for markup are rather fuzzy, because of nature of the language and so-called browser error tolerance.
We assume that a valid markup should be well-formed at least. So we use XML parser to check it. This imposes a few simple restrictions.
In essence:

Project operations

Now assume that you want to have more then one web page in your application. We'll refer such a set of pages as project.
Wamer allows a number of common operations with your pages and projects: create, copy, delete etc. Let's look at the menu.

Project/Page menu options

online tool for developing high-performance Web Applications

New, Open, ..., Delete    commands allow common operations with your projects.

Assemble    command assembles your project (the same as online tool for developing high-performance Web Applications button does).

Settings    command opens current project's settings in the editor.
Project settings are discussed below.


online tool for developing high-performance Web Applications

New, Open, Rename, Delete    commands allow common operations with your pages.

Copy to Clip Box, Paste from Clip Box    allow to duplicate currently opened page or to copy it into another project.
Clip Box operations are discussed below.


Naming convention

At some point, the projects and pages are converted into folders and files. So we require that their names should be the correct names in the file systems. There are the following requirements common for Windows and Linux:

Clip-box functions

Clip Box tool opens here

online tool for developing high-performance Web Applications

All copied pages (and also copied stencils as described below) fall into this magic box.
Then you can paste objects from here to another place.
So you can copy pages and stencils from one project to another.

Let's look into Clip Box with some objects already in it.

online tool for developing high-performance Web Applications



Each object is shown by its type ([page] or [stencil]) and name.
You can remove object from Clip Box by online tool for developing high-performance Web Applications button.
There are two zones: inactive (colored in black) and active (colored in blue).
Only objects from the active zone take place in paste operation.
When you copy an object (or group of objects) to Clip Box, all objects from the active zone are moved to inactive zone, and newly copied object is plased into the active zone.
You can move objects between zones by online tool for developing high-performance Web Applications and online tool for developing high-performance Web Applications buttons.
You can remove all objects from inactive zone by online tool for developing high-performance Web Applications button.



Q.    What if i paste the page from Clip Box but there is the page with the same name in my project?
A.    A numerical index will be added to the name of pasted page, something like MyPage(2), MyPage(3) etc.

Advanced coding

Here we discuss a few more sophisticated options.
Some of them will become more apparent in conjunction with the "Decomposition" below.

Markup: templates and options

Let's return to our example from "Basics" section.
Open tab. There are some JSON object.
Its meaning will be discussed later in this section. Now we are interested only an "options" variable.
Let's change it so way: "options": {"easy": "optional"}
Click button.

online tool for developing high-performance Web Applications

Click online tool for developing high-performance Web Applications tab.
Change the markup to <h1>It's <%= easy %></h1>
Click online tool for developing high-performance Web Applications button.

online tool for developing high-performance Web Applications

Click online tool for developing high-performance Web Applications tab to see the result.

online tool for developing high-performance Web Applications

This occurs because Wamer preprocessed the markup with Underscore.js template.
Template functions may

A template function uses our settings.options object as a set of the free variables.
Note that this mechanism works on assembly stage, and has no relation to run-time processing on client-side of your application.

How one can use it?

1) Make the markup more maintainable. For example, we may have dozens of references to resources on the page like this:
    <img src="/mypage/resources/images/img1.png" />
What if we'll decide to change the path?
The form
    <img src="<%= path_to_images %>img1.png" />
looks more convenient, isn't it?

2) Make conditional sections in the markup. It may be useful to have two different (debug and deployment) versions of the markup, something like this: <% if (debug) { %> Debug output <% } %>
and control it via debug variable in settings.options.

3) Get rid of copy-paste in the markup. For example: <% for (var i = 0; i < N; i++) { %> some tedious markup, differences are in <%= my_var[i] %> <% } %>

Note: Wamer also adds some variables to options and they can be used in template functions. We'll discuss them later in this and next sections. Names of such variables start with '_' symbol, so we recommend to not use '_' as starting symbol in user variable names.

Style: Less and templates

Less is CSS-preprocessor with variables, formulas and other cakes.
Style is passed through Less. For example: @nice-blue: #5B83AD; @light-blue: @nice-blue + #111; #header { color: @light-blue; }

translates to: #header { color: #6c94be; }

Wamer also pre-processes style with Underscore.js template.
It gives us an ability to control style via settings.options variables.
For example: @color-scheme: <%= color_scheme %>; .mixin (@x) when (@x = BW) { color: black; background-color: white; } .mixin (@x) when (@x = brown) { color: brown; background-color: yellow; } // etc. #header { .mixin (@color-scheme); }

will be translated to one of predefined color schemes depending on color_scheme parameter.

Scripting with jQuery

As mentioned above, we can use jQuery in our scripts with no additional "magical passes". Reference to jQuery library will be included into your page if there are any script. Script also will be wrapped into the code: jQuery (function($) { // "on document ready" alias // Your code using failsafe $ alias here... }(jQuery));
It allows to use $ as usual, and don't bother about document.ready condition.

More assembly options

There are some more options that also influence the assembly result.
Let's look into the page .

"icon": icon_ref    defines the icon of the page and goes for <link rel="shortcut icon" href="icon_ref" /> in the assembled HTML file;

"title": title    defines the title of the page and goes for <title> title </title>;

"meta": {key: value, ...}    defines the set of meta tags and goes for an array of <meta name="key" content="value" />;

"depends": [...]    is an array of "dependencies" of the page. It allows to include external libraries to the page, in conjunction with Project/Settings "dependencies" clause. Each element of the "depends" array is a reference to the Project/Settings "dependencies" object.
For example, there is the "jquery-ui" entry in Project/Settings "dependencies". If one change to "depends": ["jquery-ui"] in the page settings then reference to jQuery UI library will be included into the assembled page;

"uses": {}    clause will be descussed later along with stencils;

"options": {}    is already discussed above.

Now let's look into Project/Settings object.

"page_defaults": {}    defines the settings of the newly created page;

"dependencies": {}    is the set of references to the third-paety libraries. Each element of the set has the form "key": {"depends": [...], "js": string or [...], "css": string or [...]}, where
   key is a label of the entry,
   depends says that the library depends on another library(s),
   js is the reference (or array of the referencef) to JS files(s) of the library,
   css is the reference (or array of the referencef) to CSS files(s) of the library;

"app": {}    defines an arbitrary set of variables.
It is added to the template options as _app variable, and also to assembled js code as _app[""] object.
So you may define some project-wide constants for your application via "app" clause.
Let's assume that we have "app": {"font": "Helvetica"} defined.
Then we can refer it as <%= _app.font %> in markup, @font: <%= _app.font %>; in style, and var font = _app[""].font; in script.

Note that "app" clause may be redefined (or extended) on the page level, via inclusion of the "app" clause into the page settings.

(De)composition: Components and Stencils

Wamer provides a mechanism for component-based web application development.
We are using two terms: stencil and component.
Let's look at the mockup of some thinkable application.

We'd point out five components on it, say "aside_left", "aside_right", and "main_content" which includes "nav" and "thumbnails".

We'd realize it via four stencils, say "Aside Bar" and "Main Content" which involves "Nav" and "Thumbnails".

Why only one stencil for both asides? Because it probably would have the same code for both.

One can regard stencil and component as a detail drawing and implementation, or as a class and an instance (in OOP terms), or more exactly as macro-definition and macro-expansion in assembly languages.

So components and stencils do two things:
1) split the design to relatively small parts;
2) allow to reuse a code.

Adding component to a page

Let's now make a page with a component in it.

Open the page menu and click New.


Enter new page name, say "Page 2", and click "OK".


It's time to get acquainted with the Stencils nav bar.
There are two tabs: PAGE and PROJECT, each represents a list of stencils in corresponding level. Page-level stencils belong to the current page and can be used inside, and project-level stencils are project-wide visible can be used insige any page of the project.
There are also a number of buttons which allow to add, remove, rename, copy sencils to/from Clip Box etc.


Click PAGE tab, then "New" button marked by red arrow.
Let's call it "Circle".
Note: Stencil names follow the same rules as the names of pages and projects (see Naming convention above).


To open newly created "Circle" stencil for edit:
double click it,
or click it and press Enter key,
or click it then click "Open" button abowe.


Add some markup to our stencil
<div class="circle"> </div>


and some style
.circle { width: 200px; height: 200px; border-radius: 100px; margin: 20px; background-color: red; }


Now we have to reopen the page to edit it.
There are two ways:

longer: in the menu Page/Open click "Page 2"...


... or shorter: click "Reopen Last Page" button on Stencils nav panel (marked by red arrow).


Enter the following string in page's markup:
<script type="wamer/component" name="Circle"></script>


Click , then click tab and see a result.


Now then

We add a stencil via Stencil nav functions to the page.
We add a stencil instance (component) to the page via script tag with special type = "wamer/component" and name = name of stencil.
If we regard stencil as macro-definition, then we also can regard this "script ... name=".."" as macro-call.
Our "macro-call" may also have yet another two: features:
1) id attribute to identify components. It's important when we need to distinguish two or more components, based on one stencil;
2) parameters which are added as a body of the script tag.
More formally, component instantiation have a form: <script type="wamer/component" name="stencil name" id="component ID"> { ... parameters here, JSON object ...} </script>

To make our example more interesting, let's add some options and behavior.

Open Circle stencil (just double-click it in Stencils nav) and add some options under "Settings" tab "dark": "rgb(128, 0, 0)", "light": "rgb(255, 0, 0)"


Change style this way: .circle { width: 200px; height: 200px; border-radius: 100px; margin: 20px; background-color: <%= dark %>; } .circle.light {background-color: <%= light %>;}

Now background-color is defined by dark variable, and we add a subclass light with another background-color defined by light variable,


Add script $('.circle').click (function () { $(this).addClass ('light'); });


Now if you reopen page and open Design tab you'll see dark-red circle, and color will change to "normal" red after click on the circle.

Reuse stencil and component ID (CID)

Now we extend our example so that there will be a hierarchy of components and reuse of stencils.

Create new stencil calling it Traffic light.
Open its markup and put there: <script type="wamer/component" name="Circle"></script> <script type="wamer/component" name="Circle"></script> <script type="wamer/component" name="Circle"></script>


Reopen the page and change "callee" name in the markup to Traffic light. <script type="wamer/component" name="Traffic light"></script>


Go to page's Design tab. Now there is 3 red circles which light up by mouse click. (Not so interesting)

Now let's look at assembly of our project. Click button or Prpject | Assemble in the menu, and look into a result.
Page 2.html    contains 3 divs of class="Circle" corresponding to our 3 components.
Page 2.css    contains style for class "circle" repeated 3 times. It's not good.
Page 2.js    contains global variable _app and two entities inside it:
   _app[''] - it's empty for our page. In the general case here goes the object specified in the project settings.app (possibly modified in page settings).
   _app['Circle'] - there is a program module containing the script of our 'Circle' stencil.

Now let's give our components more personality.

Open Traffic light stencil and change its markup so way: <script type="wamer/component" name="Circle" id="red"> { "dark": "rgb(128, 0, 0)", "light": "rgb(255, 0, 0)" } </script> <script type="wamer/component" name="Circle" id="yellow"> { "dark": "rgb(128, 128, 0)", "light": "rgb(255, 255, 0)" } </script> <script type="wamer/component" name="Circle" id="green"> { "dark": "rgb(0, 128, 0)", "light": "rgb(0, 255, 0)" } </script>


We did two things: (1) each component have now an ID; (2) different actual parameters.

We also need to change the 'Circle' stencil so that it can absorb these innovations.

Open Circle stencil and change its markup to: <div class="circle" id="{*}"> </div>
This '{*}' symbol will be substituted by assembler to an actual component ID.


Change Circle style to: <% if (_first_time) { %> .circle { width: 200px; height: 200px; border-radius: 100px; margin: 20px; } <% } %> #{*} {background-color: <%= dark %>;} #{*}.light {background-color: <%= light %>;}
The _first_time variable is supplied by assembler.
Its value is true only the first time the stencil is "called".
Again, the '{*}' symbol will be substituted by assembler to an actual component ID.


Open page's Design tab again. Now it should be something like this.


Note: Assembler also adds the variable _cid to component options, its value = the current component ID. So one can use an alternative form <%= _cid %> instead of {*}. For example: <div class="circle" id="<%= _cid %>"> </div> ... #<%= _cid %> {background-color: <%= dark %>;}
have the same meaning as in codes above.

Now let's change the script of our stencils to make the behavior more interesting.

First we change Circle script: function init (callback) { $('.circle').click (function () { callback (); $(this).addClass ('light'); }); } return init;
We added some code which allow us to know when the circle is clicked.


Second we change Traffic light script: function turn_off_all () { $('.circle').removeClass ('light'); } _app.Circle (turn_off_all);
Here we initialize the Circle module with a callback function which "turns off all lights" before the clicked one will be "turned on".


You can see changes on the page's Design tab. Now it works more like a traffic light: circles light up one by one.

And yet another small change.

Open Traffic light settings and add "circle_init": "Circle" to uses clause.


Then open Traffic light script and change _app.Circle to circle_init


If you open the assembled "Page 2.js" file then you'll see that the assembler adds
var circle_init = _app['Circle'];
line to the beginning of the 'Traffic light' module.
So this circle_init variable becomes an alias to refer to the module of Circle stencil.
What we have in mind: we don't recommend to use direct references to other stencils (modules), like _app['Module Name'], in scripts.
Instead, we strongly recommend to use "local_name": "Module Name" substitution in settings.uses and then use this local_name in your script as an alias.
What it gives to us?
1) This facilitates the analysis of the relationships between modules.
2) This simplifies the changes when the module name changes.
3) What if the stencil name is misspelled? If it's in uses then assembler will indicate an error. Otherwise you will realize it only at runtime.

Now we slightly change our example to show how a hierarchy of components and composite IDs are created.

First we make our Traffic light more abstract.

In Circle script we'll use more abstract selector instead of hardcoded '.circle': function init (selector, callback) { $(selector).click (function () { callback (); $(this).addClass ('light'); }); } return init;


In Traffic light markup we add wrapper div with its own component ID and change underlying component IDs to depend on this higher-level identifier: <div class="traffic_light" id="{*}"> <script type="wamer/component" name="Circle" id="{*}-red"> { "dark": "rgb(128, 0, 0)", "light": "rgb(255, 0, 0)" } </script> <script type="wamer/component" name="Circle" id="{*}-yellow"> { "dark": "rgb(128, 128, 0)", "light": "rgb(255, 255, 0)" } </script> <script type="wamer/component" name="Circle" id="{*}-green"> { "dark": "rgb(0, 128, 0)", "light": "rgb(0, 255, 0)" } </script> </div>


In Traffic light scrip we wrap the code into init function and add circle_selector which depends on component ID: function init (id) { var circle_selector = '#' + id + ' .circle'; function turn_off_all () { $(circle_selector).removeClass ('light'); } circle_init (circle_selector, turn_off_all); } return init;


In the page markup we add CID to Traffic light "call": <script type="wamer/component" name="Traffic light" id="tl1"></script>


In the page settings we add "traffic_light": "Traffic light" definition into uses clause.


In the page script we add Traffic light initialization code: traffic_light ('tl1');


If you open the page's Design tab you can find no changes. But we made our 'Traffic light' stencil more abstract and reusable.
Let's demonstrate it.

Add two another "calls" to Traffic light markup with different IDs ('tl2' and 'tl3'): <script type="wamer/component" name="Traffic light" id="tl1"></script> <script type="wamer/component" name="Traffic light" id="tl2"></script> <script type="wamer/component" name="Traffic light" id="tl3"></script>


Add some style to Traffic light: .traffic_light { float: left; margin-right: 50px; }
This style defines the location of our "traffic lights" in a row.


Add some script to Traffic light to initialize this two new objects: traffic_light ('tl1'); traffic_light ('tl2'); traffic_light ('tl3');


Now you can see three independent "traffic lights" on the page's Design tab.

Important:
You may be have noticed how we used the CID to identify a subcomponent:
   {*}-local_id
We use symbol '-' to devide CID part from the local part of ID.
Let's assume that there are a page with some sections, one of it is marked as 'Music', and this section is subdevided by genre then further by groups and then by albums.
Assume that there are the following sequence of local IDs in the nested components:
   {*}-Progressive_rock ... {*}-Pink_Floyd ... {*}-The_Dark_Side_of_the_Moon
Then the assembled ID of the item will be:
   Music-Progressive_rock-Pink_Floyd-The_Dark_Side_of_the_Moon
It's important here, that we use the '-' signt ONLY for separating {*} from the local ID and DO NOT use it inside the local part of ID.
This convention ensures that locally unique ID within a stencil leads to assembly globally unique ID within a page.

Auto-initialized components

The assembler generates one js module for each stencil. If our page has several components that are based on the same stencil, then it is likely that we will need some kind of initialization for each component. As in the example above, this initialization often requires a single parameter - the ID of the generated component.

Wamer assembler provides a mechanism for such cases, we call it auto-initialization.
It is sufficient to specify "auto_init": true in a stencil settings.
In this case there is no need to explicitly call the component initialization, because the assembler adds _app ["Name stencil"] (CID); to the generated code for each component, where CID - the ID of the component.

In our example above,

open Traffic light settings and add "auto_init": true
to it;


open the page script and remove all the code from it


You can see that it still works on the page's Design tab.
You also can see that assembler added this 3 lines to the page scipt file: _app['Traffic light']('tl1'); _app['Traffic light']('tl2'); _app['Traffic light']('tl3');

There is the second form for auto_init setting: "auto_init": "init_function_name"
In many cases the stencil script may expose more then only initialization function.
For example, we can add to our "Traffic light" the abilities to turn off all lights, or to turn on some light; something like this: function init (id) { //...code here } function turn_off () { //...code here } function turn_on (id) { //...code here } return { init: init, off: turn_off, on: turn_on }
In this case you should change Traffic light auto_init setting to "auto_init": "init"

Singletons

Very often, the component exists as a single instance on a page.
For example, it may be "header", "footer", and "content" on a page, each of them in a single copy.
In this case, when you create a stencil, you can not take care of many problems associated with multiple instances.

Wamer assembler provides some service for these stencils.
Define "singleton": true in a stencil settings.
Then assembler do two things:
1) issues a message when you try to use the stencil on the page repeatedly;
2) passes the _cid argument to the function-module of the stencil.
  Value of _cid variable is equal to ID of the only instance of the component.

Advanced design

In this section we look at two more chips included in Wamer. They are not basic, but could give impetus to an understanding of Wamer and to the development of your project.

Design/Edit mode functions

Perhaps you have noticed the two buttons in the page's Design tab.
Second button opens Edit Mode. This mode allows you to change the design of the page in some way. First button saves your changes (if any).


You can drag a stencil from the stencils panel directly onto the page.
If the stencil has the special property "position", then you'll see the outline of the component on the page. Otherwise you will see an icon of the component in the "bag" at the bottom of the page.
You also can change position and size of the component if its stencil has the special properties "position" and "size".

Special properties "position" and "size" are defined in settings.options of the stencil, in "_design" variable.
These properties should influence the position and size of the component in terms of its style.
See some examples of such stencils in the Stencils Gallery.

You can delete a component from the page by Del key when the mouse is over the component.
Newly added component will be deleted immediately.
Component, which was already on the page, will be marked for deletion.
You can remove deletion mark from the component by Shift-Del key.
You can select a group of components (for deletion/undeletion) if Ctrl key is pressed when you click on the component.
Marked components will be deleted from the page when you click "Save" button.