EnyoJS Tutorial #2 – Pages & Fittables

Today I’m going to talk about how typical EnyoJS pages are created and how they are linked etc then, we move on the dynamics of EnyoJS Layout system (aka. Fittables). This tutorials is going to make use of the bootplate folder structure as discussed in Part #1.

By the end of this tutorial, you should be able to grasp :-

  1. Concept of basic enyo page, and how to basically link them up.
  2. Create basic control like header and footer.
  3. Link multiple pages together
  4. The fittable layout exercise.

Enyo pages are simple, they are basically a control that renders into document.body. All enyo simple pages does not animate. In order to animate, we use a higher level control called panel which will be covered in part 3 tutorial.  You may view the sample code as you wish in the sampler in enyojs.com.

Note: I normally used simple pages for main page or login where sometimes, you just want stuff to load fast and optimized for all devices.

Step 1

We are going to make a simple app that have a simple header and the footer. A scrollable  content in the middle that have a button. See picture below.

Let’s start with simple “kind” (a class in enyo is called Kind) code for a page. Make sure, you have your index.html that renders App into document.body. If you have all the necessary files for enyo. Start modify/create your App.js content inside source folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
enyo.kind({
	name: "App",
	kind: "FittableRows",
	classes: "enyo-fit enyo-unselectable",
	components: [
		{
                   content:"Hello World"
		}
	],
	create: function(){
		this.inherited(arguments);
		// create and rendered are both overridable default methods of enyoJS class/kind.
		// For each overridable default method, there's always this.inherited(arguments); added to it.
		// This will allowed the default arguments to be inherited from here onwards.
		console.log("App is created in memory");
	},
	rendered : function(){
		this.inherited(arguments);
		//Do stuff afterRendered
		console.log("App is created in rendered into DOM");
	}
});
Step 2

Next, we are going to make a going to make a simple inline code of 3 components. For this we make use of Enyo’s UI framework called Onyx.

  1. A header using Onyx.ToolBar – usually is what we use for persistent footer and header as well.
  2. A scroller control – that eventually contains the content “Hello World”
  3. A footer also by using Onyx.ToolBar – which contains a button to goto another page.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
enyo.kind({
	name: "App",
	kind: "FittableRows",
	classes: "enyo-fit enyo-unselectable",
	components: [
		{
                    kind: "onyx.Toolbar",
                    // layoutKind:"FittableColumnsLayout",
                    // Notice I commented FittableColumnsLayout out. Leave it be for now.
                    // In EnyoJS, components structure looked like "nested Div" days we used to code long html5 codes.
                    components: [
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:green;",
                            // you can restyle onyx.Button to any CSS style you want, by using style attribute.
                            content:"Back"
                        },
                        {
                            content:"Header",
                            fit:true
                            // Notice I use fit:true again. This time it doesn't work.
                        },
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:red;",
                            content:"Next"
                        }
                    ]
                },
                {
                     tag:"h1",
                     content:"This is content area...Hello World!!!"
                     // Notice, this time i use an attribute named "tag", tag can be anything of a html tag. It simply to
                     // tell enyo Renderer to render the tag h1 wrapping with the text in content. Give it a try.
                }
	],
	create: function(){
		this.inherited(arguments);
		// create and rendered are both overridable default methods of enyoJS class/kind.
		// For each overridable default method, there's always this.inherited(arguments); added to it.
		// This will allowed the default arguments to be inherited from here onwards.
		console.log("App is created in memory");
	},
	rendered : function(){
		this.inherited(arguments);
		//Do stuff afterRendered
		console.log("App is created in rendered into DOM");
	}
});

Ok, try changing the code like above, and see the result. You will notice a few things.

  • The header button are aligned too near each other. They do not space out like a normal app do. Notice I’ve used fit:true in the middle of the toolbar. By right, it should “auto-calculate” width of the remaining width and expand automatically.
  • Note: fit:true , will only work when the parent component has layoutKind:”FittableColumnsLayout” or the parent itself is a kind:”FittableColumns”/”FittableRows”.
  • Try uncommenting layoutKind:”FittableColumnsLayout” and give it a try. Notice, enyo also calculate the layout as the browser resize so that, it works in all browser including mobile.
  • IMPORTANT Note, layoutKind:”FittableColumnsLayout” governs fit:true in horizontal positioning and layoutKind:”FittableRowsLayout” governs fits in vertical positioning. However, only one fit:true is effective in the group.
  • You can introduce html tag into components, and use style attribute to insert CSS. You can also use an external CSS file, inserted into source’s package.js loaded from assets/css or linked them up manually using index.html. To use external css class, you attribute classes instead.
  • Components attribute are like nested div, e.g. if you have a tag:”div” with components it means the content of the components is nested within the tag:”div”.

 

Step 3

Let’s finish up our objective by introducing the footer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
enyo.kind({
	name: "App",
	kind: "FittableRows", 
	classes: "enyo-fit enyo-unselectable",
	components: [
		{
                    kind: "onyx.Toolbar",
                    layoutKind:"FittableColumnsLayout",
                    components: [
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:green;",
                            // you can restyle onyx.Button to any CSS style you want, by using style attribute.
                            content:"Back"
                        },
                        {
                            content:"Header",
                            style:"text-align:center;",
                            fit:true
                            // Notice I use fit:true again. This time it doesn't work.
                        },
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:red;",
                            content:"Next"
                        }
                    ]
                },
                {
                     tag:"h1",
                     // fit:true
                     content:"This is content area...Hello World!!!"
                     // Notice, this time i use an attribute named "tag", tag can be anything of a html tag. It simply to
                     // tell enyo Renderer to render the tag h1 wrapping with the text in content. Give it a try.
                },
                {
                      kind: "onyx.Toolbar",
                      // The footer
                      layoutKind:"FittableColumnsLayout",
                      components:[
                          {
                                kind:"onyx.Button",
                                content:"Go Next Page",
                                fit:true   
                          }
                      ]
                }
	],
	create: function(){
		this.inherited(arguments);
		// create and rendered are both overridable default methods of enyoJS class/kind.
		// For each overridable default method, there's always this.inherited(arguments); added to it.
		// This will allowed the default arguments to be inherited from here onwards.
		console.log("App is created in memory");
	},
	rendered : function(){
		this.inherited(arguments);
		//Do stuff afterRendered
		console.log("App is created in rendered into DOM");
	}
});

Take note, that the content now doesn’t stretch downwards like it should in all apps, therefore, making the footer snaps downwards. Why? Correct! the content portion of h1 doesn’t have fit:true! (just uncomment that part) Now go add it and try it out. For convinient sake, I’ve save all the tutorials in jsfiddle.net here. You may edit and try it out later to practice some more.

 

Step 4

Let’s make add a scroller and make our middle content scrollable. It will be useful, if you want to add long content/form and etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
enyo.kind({
	name: "App",
	kind: "FittableRows", 
	classes: "enyo-fit enyo-unselectable",
	components: [
		{
                    kind: "onyx.Toolbar",
                    layoutKind:"FittableColumnsLayout",
                    components: [
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:green;",
                            content:"Back"
                        },
                        {
                            content:"Header",
                            style:"text-align:center;",
                            fit:true
                            // Notice I use fit:true again. This time it doesn't work.
                        },
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:red;",
                            content:"Next"
                        }
                    ]
                },
                {
                    kind: "Scroller", 
                    horizontal:"hidden", 
                    touch:true,
                    fit:true,
                    thumb:true, 
                    // this feature is to make sure there's a scroll indicator so that, users can scroll with thumb.
                    components:[
                       {
                            tag:"h1",
                            content:"This is content area...Hello World!!!"
                        }
                    ]              
                },
                {
                      kind: "onyx.Toolbar",
                      // The footer
                      layoutKind:"FittableColumnsLayout",
                      components:[
                          {
                                kind:"onyx.Button",
                                content:"Go Next Page",
                                fit:true   
                          }
                      ]
                }
	],
	create: function(){
		this.inherited(arguments);
		console.log("App is created in memory");
	},
	rendered : function(){
		this.inherited(arguments);
		console.log("App is created in rendered into DOM");
	}
});

 

Step 5

Let’s attached listener to the button we create. You can attached these listeners to each controls, see below. For more read article here

  • ontap
  • ondown
  • onup
  • onflick
  • onclick
  • ondrag
  • onhold
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
enyo.kind({
	name: "App",
	kind: "FittableRows", 
	classes: "enyo-fit enyo-unselectable",
	components: [
		{
                    kind: "onyx.Toolbar",
                    layoutKind:"FittableColumnsLayout",
                    components: [
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:green;",
                            ontap:"handleBtnBack", 
                            // This is how we attached events and pair the handler method.
                            content:"Back"
                        },
                        {
                            content:"Header",
                            style:"text-align:center;",
                            fit:true
                        },
                        {
                            kind:onyx.Button,
                            style:"width:80px;background:red;",
                            ontap:"handleBtnNext",
                            // This is how we attached events and pair the handler method.
                            content:"Next"
                        }
                    ]
                },
                {
                    kind: "Scroller", 
                    horizontal:"hidden", 
                    touch:true,
                    fit:true,
                    thumb:true, 
                    components:[
                       {
                            tag:"h1",
                            content:"This is content area...Hello World!!!"
                        }
                    ]              
                },
                {
                      kind: "onyx.Toolbar",
                      // The footer
                      layoutKind:"FittableColumnsLayout",
                      components:[
                          {
                                kind:"onyx.Button",
                                content:"Go Next Page",
                                ontap:"handleBtnNextPage",
                                fit:true   
                          }
                      ]
                }
	],
	create: function(){
		this.inherited(arguments);
		console.log("App is created in memory");
	},
	rendered : function(){
		this.inherited(arguments);
		console.log("App is created in rendered into DOM");
	},
        handleBtnNextPage : function(inSender,inEvent){
               //For each enyo event handler comes with inSender, the control that sends the event and the inEvent the actual event itself.
               alert("Next Page Tapped");
        },
        handleBtnNext: function(inSender,inEvent){
               //For each enyo event handler comes with inSender, the control that sends the event and the inEvent the actual event itself.
               alert("Next Button");
        },
        handleBtnBack: function(inSender,inEvent){
               //For each enyo event handler comes with inSender, the control that sends the event and the inEvent the actual event itself.
               alert("Back Button");
        }
});

 

Step 6

Let’s link up another enyo page. To speed things up. Let’s create a enyo kind page file known as Page2.js save it into source folder. Make sure link them up in package.js within source. The Page2.js source should look like this (see source below). You have to download the full tutorial files that comes with the image and css file below.

Tutorial files
Enyo2 Tutorial #2 (940 downloads)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
enyo.kind({
	name: "Page2",
	kind: "FittableRows", 
	classes: "enyo-fit enyo-unselectable",
	components: [
		  {
          kind: "onyx.Toolbar",
          layoutKind:"FittableColumnsLayout",
          components: [
              {
                  kind:onyx.Button,
                  style:"width:80px;background:green;",
                  ontap:"handleBtnBack", 
                  content:"Back"
              },
              {
                  content:"Header",
                  style:"text-align:center;",
                  fit:true
              },
              {
                  kind:onyx.Button,
                  style:"width:80px;background:red;",
                  ontap:"handleBtnNext",
                  content:"Next"
              }
          ]
      },
      {
          tag:"div",
          classes:"padding15px orangeBg",
          // You can also add multiple classes of css into classes attribute.
          fit:true,
          components:[
            {
                tag:"h3",
                content:"This is page 2!"    
            },
            {
                kind:"Image",
                style:"width:128px;height:128px",
                src:"assets/img/icon.png"    
            }
          ]
      },
      {
            kind: "onyx.Toolbar",
            // The footer
            layoutKind:"FittableColumnsLayout",
            components:[
                {
                      kind:"onyx.Button",
                      content:"Go Next Page",
                      ontap:"handleBtnNextPage",
                      fit:true   
                }
            ]
      }
	],
	create: function(){
		this.inherited(arguments);
		console.log("Page 2 is created in memory");
	},
	rendered : function(){
		this.inherited(arguments);
		console.log("Page 2 is created in rendered into DOM");
	},
        handleBtnNextPage : function(inSender,inEvent){
            //For each enyo event handler comes with inSender, the control that sends the event and the inEvent the actual event itself.
            alert("End of Page");
        },
        handleBtnNext: function(inSender,inEvent){
            //For each enyo event handler comes with inSender, the control that sends the event and the inEvent the actual event itself.
            alert("End of Page");
        },
        handleBtnBack: function(inSender,inEvent){
            new App().renderInto(document.body);
        }
});

Because, the nature of EnyoJS, we normally initialized our page then render them into body. To call for a new page, we instantiate the name of the page name and render it into document.body, just like we did in index.html. See example below. I’ve modify the next button and the footer button to navigate to Page2.js.

Go ahead explore more by changing the content and refer codes on how to use other controls in enyo sampler here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
enyo.kind({
	name: "App",
	kind: "FittableRows", 
	classes: "enyo-fit enyo-unselectable",
	components: [
		  {
          kind: "onyx.Toolbar",
          layoutKind:"FittableColumnsLayout",
          components: [
              {
                  kind:onyx.Button,
                  style:"width:80px;background:green;",
                  ontap:"handleBtnBack", 
                  content:"Back"
              },
              {
                  content:"Header",
                  style:"text-align:center;",
                  fit:true
              },
              {
                  kind:onyx.Button,
                  style:"width:80px;background:red;",
                  ontap:"handleBtnNext",
                  content:"Next"
              }
          ]
      },
      {
          kind: "Scroller", 
          horizontal:"hidden", 
          touch:true,
          fit:true,
          thumb:true, 
          components:[
             {
                  tag:"h1",
                  content:"This is content area...Hello World!!!"
              }
          ]              
      },
      {
            kind: "onyx.Toolbar",
            // The footer
            layoutKind:"FittableColumnsLayout",
            components:[
                {
                      kind:"onyx.Button",
                      content:"Go Next Page",
                      ontap:"handleBtnNextPage",
                      fit:true   
                }
            ]
      }
	],
	create: function(){
		this.inherited(arguments);
		console.log("App is created in memory");
	},
	rendered : function(){
		this.inherited(arguments);
		console.log("App is created in rendered into DOM");
	},
        handleBtnNextPage : function(inSender,inEvent){
            new Page2().renderInto(document.body);
        },
        handleBtnNext: function(inSender,inEvent){
            new Page2().renderInto(document.body);
        },
        handleBtnBack: function(inSender,inEvent){
            alert("Back Button");
        }
});

That will be all for today. I hope this tutorial helps to enlighten your path in EnyoJS. Next tutorial, I’ll cover more on make reusable kind and custom vs broadcast events.

As for tutorials content for today…
Enyo2 Tutorial #2 (940 downloads)

PS: Btw, if you are wondering about the class called enyo-fit and have question about whether it does the same function as fittable attribute. The answer is no. enyo-fit is basically a default class that blow up the div to a 100% width and 100% height (good for page kind). They are not related to the fittableRows and fittableColumns, where those can be controlled by script.

 

Comments

comments

Leave a Reply

Your email address will not be published. Required fields are marked *