A Simple Introduction to Salmon V3 for Front-end Developers

- Compatibility with Prior Applications
- System Configuration Tables
- Enhanced Data Access Rules
- Container Model
- SEO Mechanisms
- CMS Blocks

Compatibility with Prior Applications

If you previously had a web application built on Salmon, the good news is that will still be working well. You won't have to make any changes. Updating to V3 will not break your site.

You can still code and use V3 the same ways you did under previous Salmon versions. However, V3 brings additional features and concepts that we suggest you take advantage of to open new possibilities on your site.

System Configuration Tables

In order to smoothly deliver new features, we have added some database tables that are used for Salmon internal purposes. Table e2c_env is one of these tables, which keeps track of some environment variables.

For example, key e2c_cart_cookie_name allows you to configure the name of the cookie that will be set when a web visitor adds an item to the cart. The default value is e2c_cart.

These key-value pairs are for Salmon internal processes and can be adjusted though the admin panel. While technically these variables can be available to the front end, we cannot find a practical reason to expose them to your visitors. Doing so may add to the potential for security breaches.

It is useful, however, for the site admin - allowing for the setup of data access rules, site configuration, and for other server-side purposes.

Enhanced Data Access Rules

Data access rules have been reworked, providing better overall security and easing data management tasks. The rules are saved into the internal table db_rules, which can be adjusted though Salmon admin panel.

Some noticeable changes are reflected in the Data API as below:

- e2cGet and e2cList can now use a w parameter in the request.
- e2cList and e2cGet can now use a r parameter in the request.

The effects are not exactly the same, as we will further explain, because of the differences in how get rules and list rules behave.

e2cGet?t=items&r=101, e2cGet?t=items&w=itemID:101, e2cList?t=items&r=101, e2cList?t=items&w=itemID:101 will all resolve into the SQL select * from items where itemID = 101.

e2cList?t=items&w=category:7;limit:4 will return 4 rows, while e2cGet?t=items&w=category:7;limit:4 will return only 1 row (the latest of the 4).
e2cGet?t=items&w=category:7;limit:1 will return only 1 row (the first).

As you already know, the purpose of e2cGet is to select a single row, and e2cList is meant to select multiple rows. The interoperability is generally aimed at convenience.

There are further nuances, but those are relevant to administration of data access rules rather than front-end development.

Container Model

As you know, designing your web pages to take advantage of the Salmon platform is made as simple as giving element IDs that correspond to the columns in your tables.

Yet, when you create an HTML block to contain a list of data, such as a product list on a category page, the task can become repetitive. To deal with this issue, you can now create a container.

For example:

<div class="prod_listing">
<h3 class="subheading">New products for <span class="e2cCatName">this</span> category</h3>
   <ul id="e2clatest">
<!-- e2c_container start -->
    <li>
      <a id="e2clastitemIDlink" href="" onclick="return e2c_action('PID','','','act=1;', 'PURL');"><img class="prodlist" id="e2clastpics" src="pics/large/" alt="" /></a>
      <p class="title" id="e2clastname"></p>
      <p>#<span id="e2clastitemID"></span> <span id="e2clasturl" style="display: none;"></span> <span class="price bold">$</span> <span id="e2clastprice" class="price bold"></span></p>
      <a id="e2clastcartproductID" href="javascript: e2c_pushToCart(PID,1);" class="button"><span>Buy Now</span></a>
    </li>
<!-- e2c_container end -->
   </ul>   
</div>
In the code above, you already know that the elements will be populated with dynamic data when your web page is loaded. What we do now is save your time by being able to somewhat clone this block as many times as necessary in order to handle longer listings.

The trick on your side is to simply add <!-- e2c_container start --> and <!-- e2c_container end -->, and Salmon will use the container as a matrix for the repetitive rendering task.

In our example above, the container name is e2clatest. Please note that ID names will be incremented for each copy, so that unique IDs are kept in the DOM. So, id="e2clastname" will become id="e2clastname0", then id="e2clastname1", then id="e2clastname2", and so on.

Even in cases when a container only uses a single copy, it is good practice to set the container start and end, so that Salmon may apply container specific logic when needed.

Containers can be pushed into a buffer at page load, allowing for clean reset, refresh, and various container specific operations. For example, you can use the JavaScript function loadContainers() and resetContainers() to accomplish these tasks. Please note, however, that with the new SEO engine that ships with V3, it is better to use loadContainersIf() over loadContainers(), because loadContainersIf() will only load the containers if they have not been already.

The container model is pretty useful in regards to UI interfaces as well, as you may create views and reuse them as needed.

SEO Mechanisms

Salmon V3 handles SEO issues in a developer friendly way.

One of the main SEO issues is that search engines have almost no interest in your JavaScript content. They are essentially blind to this code. As your content is dynamically generated, it would be unlikely to be indexed.

Furthermore, bookmarking and history is usually made complex in a client-side application. If you have ever developed a Single Page Application, you surely know the difficulties this can bring.

Salmon will therefore create pages that can be indexed by search engines, can be bookmarked, and will work with a browser's history feature, letting 'human' visitors still enjoy the power and advantages of an Salmon application.

As a web site designer, you will simply provide a bit of information to Salmon to allow it to construct and serve a page for SEO purposes.

This is done in top of the container model by extending the <!-- e2c_container start --> comment.

For example:

<!-- e2c_container start [id=0;t=items;w=reference=*data*] -->
Between the brackets we place SEO commands.

Here, id gives the container an integer value for ordering containers, t is the target table for the content to be inserted, w is the where clause statement, separated by a ;. Important, there is no ; at the end before the closing bracket.

In our example above, you may have noticed the *data* command. This tells Salmon to use the relevant value of this page key item. For example, if you created a product page, in V2 you used to provide the item in the URL as &item=101 where 101 is the item reference.

Now, because we use search engine friendly URLs, it would be, for example, gold-necklace.html. Internally this still resolve to item = 101. The current page main item is available also on JS side as var keyitem in e2c.js.

Using id has an interesting benefit - you can use a calculated value from another container.

For example,
<!-- e2c_container start [id=1;t=users_profile;c=0;w=userID=e2cvendor;pf=e2cvendor] -->
The c value in the comment above is set to 0, just before the w value. We are simply saying to Salmon this container userID in users_profile table for the where statement should be set to the value of element with ID e2cvendor from container 0.

Note we can only use a container value that has already been produced, therefore why the id sort. You can not ask container 2 to use a value from container 3, which is not yet processed. Should you need so, which is pretty rare, you could create a small container, hidden, with id 0, and store such values in it first, then you could use such values in any other container.

pf is mainly the prefix, within current container, that starts elements IDs.

For example, in <span id="e2c_abc_price"></span> the PF is e2c_abc.

You can also set the number of container copies that should be generated for the rendering.

See bellow,
<!-- e2c_container start [id=2;t=items;c=0;w=category=e2ccategory limit 4;pf=e2clast;loops=4] -->
Here, loops is set to 4. Salmon will render the container on this SEO page with 4 copies of the container, each populated with data.

We can also do more elaborate operations. Under the <!-- e2c_container start -->, we can define how this container data should be manipulated.

This is done though equivalences, with the comment <!-- e2c_eq -->.

For example,
<!-- e2c_container start [id=0;t=items;w=reference=*data*] --> 
            <!-- e2c_eq picimg=pics;cartproductID=*replace(PID,itemID)* -->
As you see, the second comment line is a <!-- e2c_eq --> comment with values. First you can set the equivalence of ID, where DOM element ID naming is different from the expected table column naming.

picimg=pics says we want the data from table pics to be placed into the element with ID picimg. The id="e2cpicimg" would take the pics value. This allows us to have more than a single element using the same value into the same container.

Also, we can replace some text with a value, using the *replace(string, replacement)* command.

Using cartproductID=*replace(PID,itemID)* means that in the current container, the element cartproductID - PID is replaced with the value of itemID.

In your container, let say you had something like this:

<a id="e2ccartproductID" href="javascript: e2c_pushToCart(PID,1);" class="button"><span>Add to Cart</span></a>

If the value of itemID is 200, your code, for the SEO page, would be rendered as:

<a id="e2ccartproductID" href="javascript: e2c_pushToCart(200,1);" class="button"><span>Add to Cart</span></a>

Let's look at a more elaborate example:

<!-- e2c_container start [id=2;t=items;c=0;w=category=e2ccategory limit 4;pf=e2clast;loops=4] -->
	 <!-- e2c_eq itemIDlink=*seo_url(itemID)*;cartproductID=*replace(PID,itemID)*;itemIDlink=*replaceAll(PID,itemID)*;itemIDlink=*replaceAll(PURL,url)* -->
Here you can see we use both replace and replaceAll.

The replace command will only replace:

- within the src attribute if tag is <img>
- within the href attribute if tag is <a>
- else within the opening and closing tags of the element

The replaceAll command will replace text anywhere from the beginning to end of the tag. If there is no separate ending tag, then it will proceed to the next opening tag.

For example, let's say we have this in the container:
<span id='title'>my PID item is cool</span><span id='name'>another PID item</span>
<div><img id='pic' src='somepath/PID' />this is a nice PID item</div>
using replace with title=*replace(PID,title)*; name=*replace(PID,name)*; pic=*replace(PID,pic)*, the result will be:
<span id='title'>my green item is cool</span><span id='name'>another green item</span> <div><img id='pic' src='somepath/green' />this is a nice PID item</div>
Now using replace and replaceAll with title=*replace(PID,title)*; name=*replace(PID,name)*; pic=*replaceAll(PID,pic)*, the result will be:
<span id='title'>my green item is cool</span><span id='name'>another green item</span> <div><img id='pic' src='somepath/green' />this is a nice green item</div>

Remember the JavaScript keyitem value that we used to render *data*? Well, we can also reverse this, asking Salmon to replace that keyitem value with its SEO friendly URL. We can even attach a SEO friendly URL to any item.

We can do so with *seo_url(x)*, where x is the current itemID. The corresponding URL tables for items that can be reached though a URL are built internally, according to the admin settings. You don't have to worry about that.

For example, itemIDlink=*seo_url(itemID)* will give the itemIDlink element a value that is based on itemID, but translated to its SEO friendly URL.

Assuming this itemID has a value of 103 and the corresponding URL for itemID 103 is blue_shampoo.html, a link, such as <a id="e2clastitemIDlink" href="">, would become <a id="e2clastitemIDlink" href=" blue_shampoo.html'>.

Using any combination of the equivalences we explained above, you can achieve elaborate SEO page data rendering.

We are fully aware the SEO mechanisms in V3 involve a small learning curve which can be a bit intimidating for beginner front-end developers. However, it is not that complicated either, especially considering that, in most cases, you can simply copy the examples we have provided here.

The most important point is that your application will be finely tuned for SEO purposes, something that usually requires much more complexity to achieve when it comes to client-side applications.

CMS blocks

With Salmon V3's container model, adding a CMS block into any page is extremely simple.

You create a container, within an HTML design that you feel appropriate, and load data into it from your CMS content table in a similar manner as items from the items table.

Let's say, for example, we previously created a table articles, then added to the user accounts interface the possibility to create, save, edit and delete some text content into this table. We could even add a nice JQuery plug-in as text editor. Now we have a blog.

Your container might look something like this:

<div id="e2c_article">
<!-- e2c_container start [id=3;t=articles;w=articleID=*data*;pf=e2c_art_] -->
<h3 id="e2c_art_title"></h3>
Author: <span id="e2c_art_author"></span>, <span id="e2c_art_date"></span>
<div id="e2c_art_text"></div>
<div id="e2c_art_footer"></div>
<!-- e2c_container end -->
</div>
And the helper could be:
function e2c_myBlog_Articles(itemref, subbcode, gdmethod, xdata){
subbcode=resetSubbcode(subbcode, 4); //or any relevant subbcode
var apidata='t=articles&r='+itemref;
xdata=setXdata(xdata, "container=", "e2c_article", ";", true); xdata=setXdata(xdata, "eid=", "e2c_art_", ";", true);
e2c_getData('e2cGet',apidata, '20', subbcode, gdmethod, xdata); //here using B20, of course could use your own behavior
}

In another example, let's say we created a table banners. If you set a container where you want to render the banners, you could use a helper to request a specific banner or an array of banners URLs which could be randomly rendered.

Your container would look something like this:
<div id="e2c_banners">
<!-- e2c_container start [id=5;t=banners;w=bannerType=enabled limit 10;pf=e2c_banner] -->
<div><img id="e2c_banner_pic" src=""></div>
<!-- e2c_container end -->
</div>
And the helper could be:
function e2c_myBanners(itemref, subbcode, gdmethod, xdata){
subbcode=resetSubbcode(subbcode, 4); //or any relevant subbcode
var apidata='t=banners&r='+itemref;
xdata=setXdata(xdata, "container=", "e2c_banners", ";", true); xdata=setXdata(xdata, "eid=", "e2c_banners", ";", true);
e2c_getData('e2cGet',apidata, '20', subbcode, gdmethod, xdata); //here using B20, of course could use your own behavior
}

You are not at all limited in what the content should be. You could inject a script, a plug-in, social media code, etc - it is completely up to you what you want to render.

Actually, we use this CMS approach to quickly develop and deploy new features for Salmon V3. For example, as part of SEO, the metadata are injected though a very simple container wich we place in <head>:
<!-- e2c_container start [id=2000;t=META-HEAD;w=keyitem=*data*] -->
         <!-- Salmon Generated SEO Data -->   
<!-- e2c_container end -->

In other words, with the container model and CMS approach that we described above, you can create extensions, add-ons, and even a totally new client-side application to run on the Salmon platform.

From idea to completion, first create a database table to be uploaded on server. Next, set a helper and behavior for that container so that it renders dynamically, and finally set the container SEO commands so that it will render well for search engines.

It's that simple.