My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
Pages  
Updated Oct 20, 2010 by maxkugland@gmail.com

Pages

The most convenient option to create a page is to simply extend the Page class. The Page class unites the IPage and IPageSupplier interfaces and provides it's subclasses with page related data and options. (For instance a page id, a page title, a navigationCommand to change to another page, ...) Each Page subclass corresponds to a previously configured page. When deepsplink boots, it instantiates all configured pages with an IPageSupplier instance as constructor argument. Then it (optionally) injects dependencies using injectors and navigates to the first page.

A minimal page looks like this:

public class TestPage extends Page {
	public function TestPage(supplier : IPageSupplier) {
		super(supplier);
	}
	
	/**
	 * create and render the page content
	 * perhaps create a navigation for the child pages (not shown)
	 * set the show & hide strategy for the page
	 */
	override public function initialize() : void {		
		var btn : SomeBtn = new SomeBtn();
		btn.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) : void {
			navigationCommand.gotoPage("somePageId")
		});
		display.addChild(btn);
		
		setShowStrategy(new QTween(display).duration(300).add(QTweenConst.ALPHA, 1));
		setHideStrategy(new QTween(display).duration(300).add(QTweenConst.ALPHA, 0));
		
		// When initialization is complete setInitialized must be invoked
		setInitialized();
	}
	
	/**
	 * stop current operations
	 * dispose of the page content	
	 * remove event listeners
	 * cleanup resources for the garbage colletor
	 */
	override public function finalize() : void {
		while(display.numChildren > 0) {
			display.removeChildAt(0);
		...
	}
}

Note that each Page is only instantiated once. Then the page instance stays alive and can adopt different states. You can identify the current page state by invoking the state method inside a Page subclass.

Show/Hide strategies

You can set a show- and a hide strategy for each page. These strategies are responsible for showing and hiding a page. It often happens that several pages show and hide in a similar fashion, so the concept of strategies enables you to reuse this code across pages. Often the strategies are created during initialization of a page:

override public function initialize() : void {		
	setShowStrategy(new ShowStrategy(display));
	setHideStrategy(new HideStrategy(display));

A custom strategy implementation might look like this:

public class ShowStrategy extends Qable implements IQable {
	public function ShowStrategy(display : DisplayObject) {
		_display = display;
	}
	
	// invoked after the setInitialized call inside the corresponding page
	override protected function doStart() : void {
		if(_display is DisplayObjectContainer) {
			for each(var child : DisplayObject in DisplayObjectContainer(_display)) {
				tween(child, delay...
			}
		}
	}
}

For a more detailed explaination on IQable read more about queues. As the setShowStrategy and the setHideStrategy methods expect an IQable implementation you can also just use a QTween to alpha-tween to whole page display:

	setShowStrategy(new QTween(display).duration(300).add(QTweenConst.ALPHA, 1));
	setHideStrategy(new QTween(display).duration(300).add(QTweenConst.ALPHA, 0));

The Page lifecycle

Each page can adopt the following states:

  • instantiated
  • initializing
  • initialized
  • showing
  • shown
  • hiding
  • hidden
  • finalized

Page activation

Each page is instantiated when deepsplink boots. If a page needs to become active, it's initialize method is invoked. Until the page calles setInitialized the page adopts the initializing state. When setInitialized is eventually called, the page state changes to initialized. Next the showStrategy of the page is started and the page state changes to showing. Upon showStrategy completion, the page state changes to shown.

Page deactivation

If a page needs to become inactive, it's hideStrategy is started and the page state changes to hiding. When the hideStrategy completes, the page state changes to hidden. Lastly the finalize method of the page is invoked and after the finalize method has been executed the page state changes to finalized.

Page request ordering:

Pages are arranged in a tree. The tree consists of page branches which all lead up to a root page. If a page is active, all pages between the active page and the root page are active too. All pages outside this branch are inactive:

root
    page1 (active)
	page2 (active)
	    page3 (active)
	page4 (inactive)
	    page5 (inactive)

If the user navigates from one page branch to another, the current branch is hidden and the new branch is shown:

root
    page1 hide->inactive
	page2 hide->inactive
	    page3 hide->inactive
	page4 show->active
	    page5 show->active

Now you can control the order in which page branches are activated and deactivated with the aid of request builders. The default request builder is the "hide-initshow-finalize" request builder. If no request is configured, this default request builder is used. You can configure such a request builder for each page. This request builder is then used for each of the child pages until another request builder turns up inside one of the child pages.

Suppose the following configuration (irrelevant attributes are left out) :

<page id="root" request="hide-initshow-finalize">
	<page id="home" >
		<page id="page1" />
		<page id="page2" >
			<page id="page3" />
		</page>
	</page>
</page>

Assuming the currently active page is page1 and a change to page3 is requested, the request builder is looked up from the target page (page3) point of view. The page3 branch is searched (page2 -> home -> root) for a request builder and eventually the "hide-initshow-finalize" request builder is found on the root page. This request builder builds the request in the the following order:

  • hide page1
  • page1 hidden
  • initialize page2
  • page 2 initialized
  • show page2
  • page2 shown
  • initialize page3
  • page3 initialized
  • show page3
  • page3 shown
  • finalize page1
  • page1 finalized

There are serveral request builders, namely:

  • hide-initshow-finalize (default)
    • hides all pages in succession which need to be hidden
    • initializes and shows all pages in succession which need to be shown
    • finalizes all previously hidden pages in succession

  • hide-init-show-finalize
    • hides all pages in succession which need to be hidden
    • initializes all pages in succession which need to be shown
    • shows all pages in succession which need to be shown
    • finalizes all previously hidden pages in succession
  • initshow-hide-finalize
    • initializes and shows all pages in succession which need to be shown
    • hides all pages in succession which need to be hidden
    • finalizes all previously hidden pages in succession
  • init-show-hide-finalize
    • initializes all pages in succession which need to be shown
    • shows all pages in succession which need to be shown
    • hides all pages in succession which need to be hidden
    • finalizes all previously hidden pages in succession
  • init-hide-show-finalize
    • initializes all pages in succession which need to be shown
    • hides all pages in succession which need to be hidden
    • shows all pages in succession which need to be shown
    • finalizes all previously hidden pages in succession
The current deepsplink version inside the repo trunk also contains the following request builder which enables to have "cross transitions": (note that it depends on the current splinklibrary trunk)

  • init-hideshow-finalize
    • initializes all pages in succession which need to be shown
    • hides and shows all pages in parallel to reach the desired state
    • finalizes all previously hidden pages in succession

Because you can associate a request builder with each page, you can apply different request builders to different page branches. The rules are simple: If a page is requested, it searches it's parent pages until a request builder is found. Then this request builder is used to activate the requested page branch.

Page Parameters

Page parameters enable dynamic pages. Imagine a shop with hunderts of products with a details page for each product. It would be a nightmare to declare a product detail page for each product inside the configuration. Instead you just declare one ProcuctDetail page and use page parameters to render the details of different products.

So instead of

http://www.xyz.com/#product-1-details
http://www.xyz.com/#product-2-details
http://www.xyz.com/#product-3-details

you have:

http://www.xyz.com/#product-details?product-id=1

At initialization time the page already knows it's page parameters. So you can use the getParamValueForKey method to retrieve the value for any parameter.

override public function initialize() : void {		
	var productId : String = getParamValueForKey("product-id");
}

If the page is already shown and the page parameters change the onParamsChanged method is invoked. So if you need to know when the parameters of a page change, ovverride onParamsChanged.

override public function onParamsChanged(params : Array) : void {
	var productId : String = getParamValueForKey("product-id");
}

To change the parameters of a page yourself you can employ the navigationCommand

var params : Array = new Array();
params.push(new PageParameter("product-id", "2");
params.push(new PageParameter("anotherParam", "anotherValue");
navigationCommand.gotoPage("somePageId", params);

If the parameters of a page change actually the parameters of all active pages change. So a complete page branch can react on a page parameter change. The onParamsChanged method is always invoked starting with the root page and ending with the topmost active page.


Sign in to add a comment
Powered by Google Project Hosting