Heads up! Phonon v2 is now available. This site is only for v1.x

Phonon Framework

A light weight, scalable, flexible and customizable HTML5 Web - Hybrid Mobile App Framework

Working with a page manager / router inspired by Android Activities

Support Apache Cordova / PhoneGap

JavaScript and CSS components are based on Material Design specs

Download
Fork me on GitHub

Phonon

About

Originally, Phonon has been created for building hybrid apps with Apache Cordova by using web technologies such as HTML, CSS and JavaScript. Of course, there are many frameworks well known, but Phonon gives an intuitive and amuzing way of building apps. For example, the app's workflow can be defined with page events. When the user access on the page-X for the first time, the onCreate callback is called, when the page becomes visible, the onReady callback is called, etc. You can also prevent the automatic close if an action is required.

Furthermore, this framework is also an UI framework proposing many features that are generic, which means they don't differ from mobile platforms. On the other hand, you can define your style according to the platform, because Phonon adds the OS class in the body tag.

Why use Phonon Framework?

Light weight Mobile Framework

phonon-core.js is only 23 kB! This file is the minimal file for running Phonon with basic CSS only components. Then you can load each component that you need. In this table, we compare Phonon to other frameworks with the file named phonon.js which contains the entire framework.

Framework Version Minified Size Size with required dependencies
Ionic 1.1.0 209.4 kB (ionic.js, ionic-angular.js) 414.5 kB (ionic-bundle.js)
OnSenUI 1.3.8 265.6 kB 535.1 kB
Framework7 1.2.0 253.8 kB 253.8 kB
Phonon 1.0.0 62.1 kB ♥ 62.1 kB ♥
Phonon + Riot 1.0.0 - 2.2.4 # 74.85 kB
Phonon + Angular 1.0.0 - 1.4.3 # 207.6 kB
Phonon + React 1.0.0 - 1.4.3 # 183.6 kB

User Interface Event Control

Phonon takes care to act in a native way with active UI components. One practical example is if a dialog box is opened and the user clicks on the back button on Android, instead of going back to the previous page, the event controller will close the active dialog automatically.

Furthermore, you can define page event callbacks in order to organize tasks at a specific moment. The Navigator module is the master of page events: onCreate, onReady, onTransitionEnd, onClose, onHidden, etc. OnCreate is called when the page is first created. This is where you should do all of your normal static set up (this callback is called once). onReady is called every time the page becomes visible to the user, onClose is called only if data-prevent-close is true, this permits to prevent the page close if we want to keep the user on the same page (for example to accept conditions before using the app).

Library Agnostic

Phonon does not use and does not depend on any third party libraries.

Choose the right framework according to your needs and your project's size! You are free to use React, Vue, Angular, jQuery, Zepto, Riot, etc.

Phonon plays well with Riot, Angular and Vue

Riot is a react-like user interface micro-library. Phonon is probably the first Framework that supports Riot completely including the virtual DOM and tags.
If you use Riot, please see our example.

Example of a tag with page events:

					<home class="app-page">
    <div class="content">
        <p class="padded-full">{title}</p>
    </div>
    <script>
        this.title = 'Hello World!'

        this.on('create', function() { })
        this.on('ready', function() { })
        this.on('transitionend', function() { })
        this.on('close', function(self) { self.close(); })
        this.on('hidden', function() { })
        this.on('hash', function(req) { })
        this.on('tabchanged', function(tabNumber) { })
    </script>
</home>


Angular's hash prefix (#/!) is supported.
If you use Angular, please see our example.

Vue is now supported!
If you use Vue, please see our example.

An UI Framework that provide a Native Experience

Hybrid apps tend to be sluggish and poorly designed. The native look and feel is an important point.

Discover UI Components →

Ultra Simple to Internationalize your App

The i18n module loads the user's language if the file is available otherwise it will load the default app's language. Then it binds HTML templates where data-i18n attributes are present.

Can be Used for building Web Apps or Hybrid Apps

Phonon is friendly with PhoneGap / Cordova. It supports the back button for example and can be optionally started after the device ready event.

Since the version 1.0.0 released on 2015 August, you can build both Web Apps and Hybrid Apps.

Open source code (MIT License)

The MIT License is a permissive free software license. Phonon is completely open source. Build free or paid apps!

More Features

Auto update for i18n

When the user changes the app's language, simply call updateLocale() in order to update your app.

Mobile and Tablet Friendly

Use the grid system in order to create smartphone and tablet layouts with the default 12-column.

Side panels can be exposed on tablet screens and closed by default on mobile screens.

Preprocessors

Phonon uses Stylus to compile CSS files and Gulp as a streaming build system.

Easy to customize

Modify stylus variables, then compile your custom CSS.

Compatibility

Android iOS IE Chrome Firefox Opera
4.1+ 7+ 10+ 30+ 10+ 12+

IE9 is supported partially, you need the following polyfills:

Test Environment

Dear developer, if your device or OS/Browser's version is not in the list, please open an issue on Github or contact the lead developer so that we can add it in the list!

Android:

iOS:

Browsers:

Help Us

As a 100% free open-source project, developer participation is encouraged, as much or little as possible.

Fork it, open issues and star the project!

Buy Us a Coffee

If this framework saved your day and you wish to support future developments you may consider sending some funds via PayPal.

Start building your hybrid or Web app with Phonon Framework

Create the Cordova App

$ cordova create hello com.example.hello HelloWorld

Add Platforms

					$ cd hello
$ cordova platform add ios
$ cordova platform add android
	...

Install Phonon

You have the choice between several ways to install Phonon:

  • Download from Github
  • npm install phonon@v1
  • bower install phonon#v1
  • git clone https://github.com/phonon-framework/phonon.git -b v1

  1. Copy and paste the phonon stylesheet and link it in the header of your index.html file.
  2. Create page containers inside your index.html file with the data-page="true" attribute.
  3. Optional: create page templates or put the page template inside its page container. We recommend to use page templates firstly because it reduces the index.html file size and because Navigator can load templates dynamically.
  4. Important: anything that's not a .panel, .side-panel, .notification and .dialog should be put in a div with the class .content.
  5. Setup Phonon options.
  6. Start the app.

Demo
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />

        <link rel="stylesheet" href="../../dist/css/phonon.css" />
        <title>App</title>
    </head>
    <body>

        <!-- Panel tags go here -->

        <!-- Side Panel tags go here -->

        <!-- Notification tags go here -->

        <!-- Dialog tags go here -->

        <!-- Popover tags go here -->

        <!-- the home page is the default one. This page does not require to call its content because we define on its tag.-->
        <home data-page="true">

            <header class="header-bar">
                <div class="center">
                    <h1 class="title">Phonon Example</h1>
                </div>
            </header>
            <div class="content">

                <ul class="list">
                    <li class="divider">Select a pizza</li>
                    <li><a class="padded-list" href="#!pagetwo/margherita">Margherita</a></li>
                    <li><a class="padded-list" href="#!pagetwo/calzone">Cheese Calzone</a></li>
                    <li><a class="padded-list" href="#!pagetwo/pesto">Pesto Pizza</a></li>
                    <li><a class="padded-list" href="#!pagetwo/roma">Roma</a></li>
                    <li><a class="padded-list" href="#!pagetwo/prosciutto">Prosciutto</a></li>
                    <li><a class="padded-list" href="#!pagetwo/funghi">Funghi</a></li>
                </ul>

            </div>
        </home>

        <!-- for the second page, Phonon will load its content. -->
        <pagetwo data-page="true"></pagetwo>


        <!-- scripts -->
        <script src="../../dist/js/phonon.js"></script>

        <!-- our app config -->
        <script src="app.js"></script>
    </body>
</html>
phonon.options({
    navigator: {
        defaultPage: 'home',
        animatePages: true,
        enableBrowserBackButton: true,
        templateRootDirectory: './tpl'
    },
    i18n: null // for this example, we do not use internationalization
});


var app = phonon.navigator();

/**
 * The activity scope is not mandatory.
 * For the home page, we do not need to perform actions during
 * page events such as onCreate, onReady, etc
*/
app.on({page: 'home', preventClose: false, content: null});

/**
 * However, on the second page, we want to define the activity scope.
 * [1] On the create callback, we add tap events on buttons. The OnCreate callback is called once.
 * [2] If the user does not tap on buttons, we cancel the page transition. preventClose => true
 * [3] The OnReady callback is called every time the user comes on this page,
 * here we did not implement it, but if you do, you can use readyDelay to add a small delay
 * between the OnCreate and the OnReady callbacks
*/
app.on({page: 'pagetwo', preventClose: true, content: 'pagetwo.html', readyDelay: 1}, function(activity) {

    var action = null;

    var onAction = function(evt) {
        var target = evt.target;
        action = 'ok';

        if(target.getAttribute('data-order') === 'order') {
            phonon.alert('Thank you for your order!', 'Dear customer');

        } else {
            phonon.alert('Your order has been canceled.', 'Dear customer');
        }
    };

    activity.onCreate(function() {
        document.querySelector('.order').on('tap', onAction);
        document.querySelector('.cancel').on('tap', onAction);
    });

    activity.onClose(function(self) {
        if(action !== null) {
            self.close();
        } else {
            phonon.alert('Before leaving this page, you must perform an action.', 'Action required');
        }
    });

    activity.onHidden(function() {
        action = null;
    });

    activity.onHashChanged(function(pizza) {
        document.querySelector('.pizza').textContent = pizza;
    });
});

// Let's go!
app.start();
<pagetwo class="app-page">
    <header class="header-bar">
        <div class="left">
            <button class="btn pull-left icon icon-arrow-back" data-navigation="$previous-page"></button>
            <h1 class="title">Page Two</h1>
        </div>
    </header>

    <div class="content">
        <div class="padded-full">

            <h2>Order</h2>

            <p>1x Pizza: <span class="pizza"></span></p>

            <p class="message"></p>

            <button class="btn negative cancel" data-order="cancel">Cancel</button>
            <button class="btn btn-flat primary order" data-order="order">Order</button>
        </div>
    </div>
</pagetwo>

<script>
	/*
	 * JavaScript code can be executed when the template is loaded
	 */
</script>

Done!

Your app is configured and ready to be launched. Phonon does the rest for you.

You are now invited to → read the docs in order to use the Phonon framework like a boss.

For example how to use more options, exposed side panel on tablets, etc..

Feel free to contribute to Phonon, we need your support as it is an open source project.

Open an issue, star and fork this project on Github (very important :) )