• If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

Todos 03-Build Your Views

Page history last edited by two-bit-fool 13 years, 6 months ago

Now that we have some model data, we want to add some views. A view in SproutCore is a JavaScript class that manages the display (through HTML) of your application as well as incoming events. You configure the views you want to use in your application through a special API called a “page design”.

 

Pages and Views

 

Inside your new application, you will find a default page design at apps/todos/resources/main_page.js.  This is where you will put your initial set of views, so let’s open that file and take a look at it.

 

Your default main_page document should look something like this (comments removed):

 

Todos.mainPage = SC.Page.design({

  mainPane: SC.MainPane.design({ 

    childViews: 'labelView'.w(),

         

    labelView: SC.LabelView.design({ 

      layout: { centerX: 0, centerY: 0, width: 200, height: 18 },

      textAlign: SC.ALIGN_CENTER,

      tagName: "h1",

      value: "Welcome to SproutCore!"

    })   

  })  

});

 

The first thing you will notice here are two new classes: SC.Page and SC.MainPane.

 

SC.Page is simply a “bucket” for placing your configured views. It can instantiate views for you automatically when you request them in your application. Most applications will have at least one page object called “mainPage”. The SC.Page object can contain any desired number of views, but it will almost always have a view called mainPane or mainView.

 

NOTE: In SproutCore 0.9 or earlier, all applications had a single SC.page object that contained all of your views. It was generated by the ruby view helpers. SproutCore 1.0 pages are similar but you can now have as many as you like in your application. Very large projects may contain several dozen of these, loaded lazily as they are needed.

 

SC.MainPane is a subclass of SC.Pane that will act as the root view for your application. In SproutCore 1.0 all views must have a parent view except for SC.Pane, which is a special type of view that can root itself directly in your HTML page. Suffice to say, any view hierarchy that you need to add directly to your HTML body must subclass from SC.Pane.

 

Since most applications have a single root view that fills the entire browser window, SproutCore provides a special subclass, called SC.MainPane, that provides some of the common functions needed by a main pane.

 

In this case, we have a MainPane with a single child view called labelView that displays the string “Welcome to SproutCore”. This is the default content we are going to replace in this step of the tutorial.

 

Despite their appearance as plain JavaScript files, page designs are actually data files that describe how views should be configured just before display.  In fact, SproutCore has built in support for read and write page design files programatically (for use by a visual UI designer).  This is why page design files belong in your resources directory and not with the regular application code. 

 

Showing Views In Your Window

 

Before we start editing this text, let’s take a quick look at how these views end up on your screen. Open your apps/todos/main.js file and you will see this line:

 

Todos.getPath('mainPage.mainPane').append();

 

This is the line that makes your application come alive. This line will fetch the mainPane object from the mainPage and then ask it to append() itself to your HTML body element. If you comment this line and reload your app, you will see that your screen remains largely blank (except for the loading screen).

 

Designing Your Views

 

Let’s start by adding a simple three part layout. In your main_page.js file, replace the mainPane property with:

 

  mainPane: SC.MainPane.design({

    childViews: 'middleView topView bottomView'.w(),

    

    topView: SC.ToolbarView.design({

      layout: { top: 0, left: 0, right: 0, height: 36 },

      anchorLocation: SC.ANCHOR_TOP

    }),

    

    middleView: SC.ScrollView.design({

      hasHorizontalScroller: NO,

      layout: { top: 36, bottom: 32, left: 0, right: 0 },

      backgroundColor: 'white',

 

      contentView: SC.ListView.design({

      })

    }),

    

    bottomView: SC.ToolbarView.design({

      layout: { bottom: 0, left: 0, right: 0, height: 32 },

      anchorLocation: SC.ANCHOR_BOTTOM

    })

  })

 

 

This code adds three child views to your main pane. You can see the childViews property above tells SproutCore the name and order of each view. (w() is a convenience function that splits the string into an array of words).

 

Below the childViews property are the three views. The topView and bottomView will form the toolbars in our application. They both use the SC.ToolbarView class to make them appear as toolbars in our theme.  They set the "anchorLocation" property to allow the ToolbarView to display in the proper direction.  (This is a ToolbarView-specific feature.)

 

The middleView will contain our list of Tasks. For now we’ve just placed a SC.ScrollView there and given it a white background.

 

In your browser, hit refresh to view your new app. It should look something like this:

 

Todos

 

Setting Your Layout

 

One of the most important things you will do in your page designs is to position your views on screen. SproutCore views are positioned using a special property called “layout”. A layout contains several CSS-like attributes that describe your view’s positioning.

 

Unlike desktop systems that have you simply specify sizing using a frame rectangle, SproutCore layout properties allow you to specify both the initial dimensions of your view and how you want it to resize. For example, if you name both a left and a right property in your layout, but no width, the view will automatically resize its width when you resize the window.

 

It is important that you design your SproutCore applications to make maximum use of this automated resizing ability of layouts because SproutCore can make maximum use of the browser’s built-in ability to make resizing smooth and error free.

 

In the example above, we want the topView and bottomView to be anchored to the top and bottom of the window respectively. They should have a fixed height and should resize their width only. To implement this, the layouts name a left and right edge of 0 along with a fixed height. Their top and bottom edges are also fixed respectively.

 

The middle view, on the other hand, should have both a flexible width and height when the browser resizes. To support this, the layout for this view has a left, right, top and bottom but no width or height, allowing those to change as the browser resizes.

 

Resize your browser window with your app loaded to see this effect.

 

All layout measurements are in pixels and are relative to their parent view.

 

Adding Some Controls

 

Now that we have the basic layout of our page set, let’s add some controls. We want to have a label view in the top left corner, a button to Add tasks in the top right and a label at the bottom that will contain the item count. Modify your main page design to match the example below.

 

  mainPane: SC.MainPane.design({

    childViews: 'middleView topView bottomView'.w(),

    

    topView: SC.ToolbarView.design({

      layout: { top: 0, left: 0, right: 0, height: 36 },

      childViews: 'labelView addButton'.w(),

      anchorLocation: SC.ANCHOR_TOP,

      

      labelView: SC.LabelView.design({

        layout: { centerY: 0, height: 24, left: 8, width: 200 },

        controlSize: SC.LARGE_CONTROL_SIZE,

        fontWeight: SC.BOLD_WEIGHT,

        value:   'Todos'

      }),

      

      addButton: SC.ButtonView.design({

        layout: { centerY: 0, height: 24, right: 12, width: 100 },

        title:  "Add Task"

      })

    }),

    

    middleView: SC.ScrollView.design({

      hasHorizontalScroller: NO,

      layout: { top: 36, bottom: 32, left: 0, right: 0 },

      backgroundColor: 'white',

 

      contentView: SC.ListView.design({

      })

    }),

    

    bottomView: SC.ToolbarView.design({

      layout: { bottom: 0, left: 0, right: 0, height: 32 },

      childViews: 'summaryView'.w(),

      anchorLocation: SC.ANCHOR_BOTTOM,

      

      summaryView: SC.LabelView.design({

        layout: { centerY: 0, height: 18, left: 20, right: 20 },

        textAlign: SC.ALIGN_CENTER,

        

        value: "Item Count"

      })

    })

  })

 

 

Like the container views you setup before, these controls also have layout properties. In fact, layout is the one property you will set on almost all of the views you design. These controls also have value properties that will populate with dynamic content later. For now we just want to test so we are filling things in here.

 

When you are designing views in SproutCore, you are really creating custom subclasses of your views. You can add any property to the views that you might add in a subclass. If you want to know what properties you can set on a view that will have an effect, just look at the documentation for the class. Any properties defined there will work in your design.

 

Reload your webpage now and give it a whirl. Try clicking the button and resize the window. It should look something like this:

 

Todos

The button won’t do anything yet of course. You haven’t hooked it up to your data yet. That is the point of the next step.

 

Continue to Step 4: Hook Up Your Data »

Comments (8)

Pedro Luz said

at 1:46 pm on Aug 27, 2009

No view with name labelView has been found in SC.ToolbarView:sc272
No view with name addButton has been found in SC.ToolbarView:sc272
No view with name summaryView has been found in SC.ToolbarView:sc273
childViews[idx].awake is not a function

im getting this errors in firebug :(

Pedro Luz said

at 4:04 pm on Aug 27, 2009

just found the problem :)

Cristian Bodnar said

at 5:48 am on Sep 15, 2009

i have the same issue: childViews[idx].awake is not a function
can you please tell me what is the problem?

Cristian Bodnar said

at 5:48 am on Sep 15, 2009

i have the same issue: childViews[idx].awake is not a function
can you please tell me what is the problem?

Juan Pinzon said

at 2:37 pm on Sep 21, 2009

check the names of your childviews for the status toolbar. This happens if it doesn't find a view that matches the ones in childviews.

Charles Jolley said

at 10:01 am on Oct 2, 2009

Also make sure you add the w() helper to the end of the string..

Israel Romero Ponce said

at 3:36 pm on Feb 1, 2010

Somevary have a example with MenuPane and MenuItemView????

Paulmichael said

at 1:54 pm on Jul 23, 2010

User jjquimora put this in:
"You can do some ipod to pc transfer before you continue."
It linked to some software completely unrelated to the article... Might want to watch that account.

You don't have permission to comment on this page.