Phonon Framework

Phonon

Navigator

Navigator is a tiny JavaScript page manager and router and is inspired by Android Activities. It is designed for handling the pages of a single page application by calling their activity.

The activity takes care of creating a window for you in which you can place your UI with. An activity is based on several window states that we call the activitiy life cycle:

Event Name Description
onCreate() called when the activity is first created. This is where you should do all of your normal static set up. This callback is called once unless you set data-nocache="true" to its page container.
onReady() called when the activity is becoming visible to the user.
onTransitionEnd() called when the page transition is finished.
onClose() called when the activity is no longer active, but always visible.
onHidden() called when the activity is no longer visible to the user.
onHashChanged() called when the hash changes.
onTabChanged() called when the user changes the active tab (tabs feature required).

Cordova Backbutton

This is a Phonegap/Cordova event that fires when the user presses the back button on Android. Navigator supports it and will navigate to the previous page automatically.


Usage

This module is included in phonon-core.js.

RequireJS Compatible

require(['phonon-core'], function(phonon)) {
    phonon.navigator(...);
});

Adding a page

Page Container

Create page containers inside your index.html file with the mandatory attribute data-page="true".

<home data-page="true" data-loader="true" data-nocache="true"></home>
<pagetwo data-page="true"></pagetwo>

Page Content

There are 2 options.

1) Create page templates files

We recommend this option because it reduces the index.html file size and because Navigator can load templates dynamically.

home.html

<home class="app-page">
    <header class="header-bar">
        <h1 class="title">Home</h1>
    </header>
    <div class="content">
        <!-- page content goes here -->
    </div>
</home>
<script>
    // JavaScript code can be executed when the content is loaded
    // The variable "page" is injected so that you can use page.onEvent as you want

    // global event works
    document.on('pagecreated', function(evt) {

    });

    // adding an event is ok
    phonon.navigator().onPage('home').addEvent('create', function () {

    });

    // or the new shortcut is also working :)
    page.onCreate = function () {

    };

</script>

2) Put the page content inside its page container in index.html file.

<home data-page="true">
    <header class="header-bar">
        <h1 class="title">Home</h1>
    </header>
    <div class="content">
        <!-- page content goes here -->
    </div>
</home>

Navigation between Pages

Navigate to another page.

<button data-navigation="page-name">Go to page</button>

Navigate to the previous page with $previous-page.

<button data-navigation="$previous-page">Back</button>

Navigate with links.

<a href="#!page-name">Go to page</a>

Navigate with parameters.

Add the parameter inside the data-navigation attribute. For example:

<button class="btn" data-navigation="page-name/a/b/c">Go to page</button>

JavaScript

App Setup

Navigation and i18n options are defined in the app options.

phonon.options({

    navigator: {
        defaultPage: 'home',
        hashPrefix: '!', // default !pagename
        animatePages: true,
        enableBrowserBackButton: true,
        templateRootDirectory: '',
        //defaultTemplateExtension: 'html', // if you use page templates
        useHash: true // true to enable hash routing, false otherwise
    },

    i18n: { // i18n: null if you do not want to use internationalization
        directory: 'res/lang/',
        localeFallback: 'en',
        localePreferred: 'en-US'
    }
});

on(Object pageObject, Function activity)

The page namespace permits you to listen to the page events. Furthermore, you can add options such as preventing the automatic close and adding a delay before calling the onReady callback.

pageObject parameters

Parameter Type Description
page string The page name
content string / null The page content if defined
preventClose boolean true if you desire to prevent the automatic close, false otherwise
readyDelay number add a delay when the onReady callback is called

The activity function is optional, use it in order to define page events.

Example

phonon.navigator().on({page: 'pagename', content: 'content.html', preventClose: false, readyDelay: 1}, function(activity) {

    activity.onCreate(function() {});

    activity.onReady(function() {});

    activity.onTransitionEnd(function() {});

    // activity.onClose(function(self) {}); // use it only if preventClose is true with self.close();

    activity.onHidden(function() {});

    activity.onHashChanged(function(req1, req2, ...) {});

    activity.onTabChanged(function() {});
});

// or
phonon.navigator().on({page: 'pagename', content: 'content.html', preventClose: false, readyDelay: 1});

OnPage events without a global (activity) scope

You can also add individual page events without the page's scope (activity).

phonon.navigator().onPage('home').addEvent('create', function () {
})
phonon.navigator().onPage('home').addEvent('ready', function () {
})
phonon.navigator().onPage('home').addEvent('transitionend', function () {
})
phonon.navigator().onPage('home').addEvent('hidden', function () {
})
phonon.navigator().onPage('home').addEvent('tabchanged', function (tabNumber) {
})
phonon.navigator().onPage('home').addEvent('close', function (api) {
    api.close()
})
phonon.navigator().onPage('home').addEvent('hashchanged', function (param) {
    console.log('params ' + param)
})

Starting the App

phonon.navigator().start();

Change Page Programatically

You can also pass a parameter if you want to. The parameter will be added to the URL.

phonon.navigator().changePage('page-name', 'optional-parameter');

Get the Current Page

Returns the current visible page.

phonon.navigator().currentPage;

Get the Previous Page

Returns the previous page.

phonon.navigator().previousPage;

POST request for changing a page

By creating a form and posting it (action) to a valid hash, the page will be loaded using a POST call instead of a GET, and the serialized form will be posted.

<form method="post" action="#!my-page">...</form>

Global events

document.on('pagecreated', function(event) {
    console.log('global state pagecreated: ' + event.detail.page)
})

document.on('pageopened', function(event) {
    console.log('global state pageopened: ' + event.detail.page)
})

document.on('pagetransitionend', function(event) {
    console.log('global state pagetransitionend: ' + event.detail.page)
})

document.on('pagehidden', function(event) {
    console.log('global state pagehidden: ' + event.detail.page)
})

document.on('pagetabchanged', function(event) {
    console.log('global state pagetabchanged: ' + event.detail.page)
})

document.on('pageclosed', function(event) {
    console.log('global state pageclosed: ' + event.detail.page)
})

document.on('pagehash', function(event) {
    // For the given hash: #!onepage/a/b/c
    console.log('global state pagehash: ' + event.detail.page)
    console.log(event.detail.req[0]); // a
    console.log(event.detail.req[1]); // b
    console.log(event.detail.req[2]); // c
})