Blog

04.View

Last modified by kashi on 2015/04/30, 11:31

Overview

In JavaScript, you can perform view manipulation (also called screen or DOM manipulation) from anywhere.
As result, on a screen that enables functions to be flexibly written, it is difficult to recognize where and which processing is being executed, and modify view even a little at maintenance phase.

In hifive,  in principle, view manipulation is only defined within the controller. 
Therefore, it is clear that "the controller will perform view manipulation",making it easier for user to understand
where to perform maintenance and inheritance.

In order to generate view, hifive features  EJS template engine. 
Using template engine, complex structure tags can be visually edited, increasing maintainability and readability.

Manipulate with a single element

If you want to, for example, read <input> tag value, or pass a string to <div> tag, use jQuery to read and write
to a single element.

However, if you are working with a DOM element,
use this.$find() method which is available to use in the controller instead of jQuery $().
This method searches for an element from subordinates of the element that controller is bound to, preventing
wrongly manipulating with an element that is out of scope of the element (that controller is bound to).

What if I want to search for the element that controller is bound to? 

Using the  rootElement  property of the controller instance
can enable you to refer to the element that controller is bound to.
By using $(this.rootElement), you can use jQuery to manipulate with that element.

Operation example

※Since this.$find() returns "a jQuery object in such status as an element specified by selector is selected",
after it is selected, you can manipulate with the element same as a normal jQuery object.

Manipulating activitiesImplementation method
Generating an element$(tag)
Selecting an elementthis.$find(selector);
Removing an elementthis.$find(selector).remove();
Updating element content this.$find(selector).html(element);
this.$find(selector).text(value);
this.$find(selector).val(value);

※"this" indicates the controller itself.

Generating a complex view (using template)

Basic syntax

A view template should be used in order to generate a complex view (containing various complex tags)
A template is defined by  <script type="text/ejs"></script>  tags.
Each template must be assigned an unique ID (set the id attribute in <script> tag).

EJS syntax is very similar to JSP.
JavaScript code is opened and closed with  [%  and  %] . You can put  [% %]  anywhere in the code.
You can use for and if statements etc. to customize view:

<script type="text/ejs" id="list">
  [% for (var i = 1, len = num + 1; i < len; i++) { %]
    <li>
      <span style="[%= 'color: ' + (i % 2 === 0 ? 'blue;': 'red;') %]">[%= i %]</span>
    </li>
  [% } %]
</script>

Defining template

Template can be defined:

  1. in an independent file
  2. or directly in the HTML file

Basically, it is recommended that a template is defined in an independent file. However, in following cases:

  • the template is only used for a specific view (HTML).
  • in case you want to minimize the number of HTTP request:
    • in fact, a HTTP request occurs for each file the template is defined.
      template should be defined directly in the HTML file.

If you define a template as an independent file, it is recommended to use .ejs extension

Loading template file

var sampleController = {  
  
  __templates: ['view/template1.ejs', 'view/template2.ejs'],  
  
}; 
  • If a template is defined as an external file, insert the template file url in templates property
    of the controller that uses the file, so that it will automatically be imported at controllization time.
    Since the controller starts operation after the specified template file is imported,
    certainly the event handler can also make use of the template file.
  • If a template is defined directly in a HTML file, it is available for use at anytime (no need to define templates property).

Installing debug library for syntax checking

If a wrongly defined template is loaded, it is impossible to understand where the error happens in the template just by reading error messages. 

Using an ejs library that can give detailed error messages and line number where error happens, can be a solution to the problem. 
You can download from the link below:
    http://embeddedjavascript.googlecode.com/files/ejs_fulljslint.js
Refer to the following links for guidelines about how to use the library.
    EJS - google code
    EJS公式HP

Working with template

The following this.view methods are used in the controller when customizing view using template.
※this indicates the controller itself.
(The following methods can be used in the controller )

Method nameDescription
update(target element object or selector, templateID, parameter)Update target element content with specified template.
append(target element object or selector, templateID, parameter)Append the specified template to the end of target element.
prepend(target element object or selector, templateID, parameter)Append the specified template at the beginning of target element.

If you want to get the returned HTML tag (using code) without directly displaying to view, use
this.view.get(templateID, substitution parameter).

Implementation example

1.Write a HTML file.

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <script src="jquery.js"></script>
     <script src="ejs-1.0.h5mod.js"></script>
    <script src="h5.js"></script>
    <!-- Import your js file here -->
    <script src="step5.js"></script>
     <title>Manipulating with view in hifive</title>
  </head>
  <body>
    <div id="container">
      <div>
        From 1 to entered value, print to view: even numbers are colored <span style="color: red;">red</span>,
        odd numbers are colored <span style="color: blue;">blue</span>.
      </div>
      <input type="text" id="to" value="" />
      <input type="button" id="output" value="出力" />
      <ul id="list"></ul>  <!-- Template outputs flushed here -->
    </div>
  </body>
</html>

2. Create list.ejs file

<script type="text/ejs" id="list">
[% for (var i = 1, len = num + 1; i < len; i++) { %]
<li>
  <span style="[%= 'color: ' + (i % 2 === 0 ? 'blue;': 'red;') %]">[%= i %]</span>
</li>
[% } %]
</script>

※ The  list  in  id  attribute of <script> tag will become required  template ID  when this.view.get() is called.

3. Create step5.js file.

$(function() {
 // Create an object that is source of the controller
 var controller = {

 // Set controller name
 __name: 'NumListController',

 // Define template file path
 __templates: 'list.ejs',  // Declare an array if you want to import multiple ejs files.

 // Define an event handler that processes when id=output is pressed
 '#output click': function() {
   // Get input value
   var to = this.$find('#to').val();
   // Exit processing unless value exists in #to
   if (!to) {
     return;
    }
   // Convert from String to Number. Exit processing if conversion fails
   try {
      to = parseInt(to);
    } catch(e) {
     return;
    }

   // Print template with value entered to view
     this.view.append('#list', 'list', {num: to});
    }
  };

 // Bind controller to id="container" element
 h5.core.controller('#container', controller);
});

4. Open HTML file in browser.

5. Enter a number value in textbox then click output button.

Checking operation

Tutorial/step5

How to pass value to template

Similar to JSP, in hifive template you can insert any optional value between  [% %]  or  [%= %] . Text between  [%= %]  will automatically be HTML escaped. Using  [%:= %]  wiil not make text be escaped.
You can pass a value to template using the syntax below:

{template variable name: value}

Example (1)

this.view.append('#container', 'templateId1', {ar: [10, 20, 30]});

Example (2)

Similar to object literal, if you want to pass several values:

{template variable name: value, template variable name: value, ...}

You can define as above.

this.view.append('#container', 'templateId1', {ar: [10, 20, 30], str:'Hello World!'});

In the above implementation example, in line 27 of step5.js file:

this.view.append('#list', 'list', {num: to});

value is passed to the third argument {num: to}. In line 2 of list.ejs file:

[% for (var i = 1, len = num + 1; i < len; i++) { %]

this value is used for  num  .

As result, by specifying same name as template variable name for object key, value can be passed using view.get(), view.append(), view.update(), view.prepend() methods.

Defining various templates

You can define various templates, even in external file or directly in HTML file. However, remember that id must be unique.

<script type="text/ejs" id="list1">
  <div>Test 1</div>
</script>
<script type="text/ejs" id="list2">
  <span>Test 2</span>
</script>

Actions performed after importing a template containing duplicated template ID

If id is duplicated, the later imported id will be prioritized (overwrite).
Otherwise, you will have to specify an unique id, regardless of defining in the same HTML file or in other files.

Importing priority order for ejs file is as below.

  1. Since the priority order is from top down, the last definition will be prioritized.
  2. If multiple ejs files is specified to controller __templates property, the last specified ejs file will be prioritized.

For example, executing the below code will display "hello 2".

view.ejs

<script type="text/ejs" id="list">
  hello 1
</script>
<script type="text/ejs" id="list">
  hello 2
</script>

test.js

var testController = {
  __name: 'TestController',
  __templates: 'view.ejs',
  __ready: function() {
    alert(this.view.get('list'));
  }
}

h5.core.controller('body', testController);

test.html

<!doctype html>
<html>
 <head>
   <meta charset="UTF-8">
   <script src="jquery.js"></script>
   <script src="jquery.blockUI.js"></script>
   <script src="ejs-1.0.h5mod.js"></script>
   <script src="h5.js"></script>
   <script src="test.js"></script>
 </head>
 <body>
 </body>
</html>

View manipulating cautions (unique id))

id set for an element must be unique on view. 
This is specification of HTML.

  • Similar to list, when displaying multiple times on view, instead of using id, you can  use CSS class, or assign unique ID to data-* attribute . 
  • You need to pay special attention while dynamically rewriting view using Ajax.
  • In case multiple elements have same id, if you get the element using this.$find('#id') or document.getElementById('id'), in many browsers, the first element with specified id will be retrieved. However, the operation may vary depending on the system.

Just by separating View (template) and Controller (event handling), code becomes considerably comprehensive.
If there's not much calculation code at client side, using only these two features is OK.
Next chapter will describe about Logic that handles calculation and communication processing.

Next chapter ⇒ 05.Logic

Reference


Copyright (C) 2012-2017 NS Solutions Corporation, All Rights Reserved.