Introducing Kendo UI Mobile – Adaptive Rendering Framework

June 29, 2012By 12 Comments

I recently discovered a neat framework I wanted to blog about to inform people of another great option for developing in mobile. This framework might especially appeal to Flex/AIR developers as well, so take a moment to read on. It’s called Kendo UI Mobile, but this same company also has libraries for web and data visualization. In this post I’m going to specifically focus on mobile, though the data visualization and web components play nicely with mobile as well according to the documentation and the things that I tried.

The framework is built on HTML5 and uses JavaScript/CSS to style the components to work cross-platform and automatically adapt to the look and feel of the native OS without the developer making any changes. It currently supports iOS, Android and Blackberry, and also has a theme for Windows Metro. It contains a set of CSS styles specifically for the different platforms so you can easily customize them to your liking by overriding the CSS class. The framework offers more than just UI components, it also has plumbing to do things like navigation between views, transitions, an extensive datasource and data binding implementation, drag-n-drop, validation, globalization support and more. I found their documentation and samples very well done and useful, and was impressed at how fast I was able to build things quickly and cleanly cross-platform. Coupled with PhoneGap, this could be a very powerful combination for mobile development.

Before I go further, I do need to point out that this is not a free solution, there is a developer licensing fee of $199/yr for royalty free development using their mobile framework. You can review their whole pricing model here. I personally was impressed with it and would pay for it because I believe the time savings you could gain is well worth it. If you’re coming from Adobe Flex/AIR I think you might find it especially easy to adapt to as well, I noticed many similar concepts.

To use it you simply download their set of JavaScript and CSS files and include them in your application. There’s a kendo.mobile.min.js and .css file that includes everything (minified), but there are also specific files for different components if you’re concerned about size and only need to utilize a certain feature. Also, every application needs to include a JavaScript kendoMobileApplication definition such as the following:

...
window.kendoMobileApplication = new kendo.mobile.Application(document.body);
...

When building your application, you can either depend on the jQuery-based calls for the Kendo components, or use the HTML5 data attributes as prescribed in their docs to achieve the same thing. So for instance you could define a back button in either way below:

<a data-role="backbutton">Back</a>

or

var button = $("#button").kendoMobileBackButton();

Views are defined within an HTML file using the data-role=”view” attribute with an id. When you want to transition to one of these views, you simply use the hash sign # followed by the id of the view to transition to on an anchor tag. For instance, in the snippet below I define a view and an anchor tag that when clicked will transition to that view:

<div id="about" data-role="view" data-title="About" data-layout="app">
    <h2>This is the About View...</h2>
</div>
...
<a href="#about" data-icon="about">About</a>

I can also control the type of transition that will occur. The default is slide, but other transition options include zoom, fade and overlay. So for example, if I wanted to change the transition of my view above to a zoom, I could simply add the following data-transition attribute to the view:

<div id="about" data-role="view" data-transition="zoom" data-title="About" data-layout="app">

Note:If you exclude the hash sign, a remote ajax call will be assumed. You can also control the direction and duration of the transition. See the documentation for more details.

Another thing I found particularly interesting with the Kendo framework, it that it includes a DataSource component you can use as an abstraction for local and remote (XML, JSON, JSONP) data. It supports CRUD (Create, Read, Update, Destroy) data operations and provides local and server-side support for Sorting, Paging, Filtering etc. and simplifies data binding and data operations in general. I created a simple application to try out the framework which used a DataSource for doing an ajax service call to search the Yahoo Local Search APIs. My DataSource code definition is shown below:

function getData(callback) {
    var template =  kendo.template($("#customListViewTemplate").html());
    var dataSource = new kendo.data.DataSource({
        transport: {
            read: {
                url: 'http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=YahooDemo&query='+search.value+'&zip='+zip.value+'&output=json&results=15',
                dataType: "jsonp"
            }
        },
        schema: {
            data: "ResultSet.Result"
        },
        error: function(e) {
            console.log("Error " + e);
        },
        change: function() {
            $("#resultListView").html(kendo.render(template, this.view()));
        }
    });
    dataSource.sort = ({field: "Distance", dir: "asc"});
    dataSource.read();
    $("#resultListView").kendoMobileListView({dataSource:dataSource,template: $("#customListViewTemplate").html()});
}

The template I’m referring to above that will be used for mapping the returned data looks like the following:

<script type="text/x-kendo-template" id="customListViewTemplate">
    <h4>${Title}</h4>
    <p>${Address}</p>
    <h4 id="distance">${Distance} miles</h4>
    <a data-role="button" class="details-link">Visit Website</a>
</script>

For my sample Biz Finder app, I also wanted to create a header and footer for the mobile application. What’s nice with Kendo is that I was able to define a layout containing a header and footer globally to be used among multiple views. I just set up the layout with a data-id that is then referred to by the views I want to use it. So for instance, below is my global layout definition for my sample app:

<!-- define multi-use layout for header/footer -->
    <div data-role="layout" data-id="app">
        <header data-role="header">
            <div data-role="navbar">
                <span id="ttl" data-role="view-title"></span>
                <a data-align="right"  data-role="button" data-icon="settings" href="#settings"></a>
                <a data-align="left" data-role="backbutton" href="#index">Back</a>
            </div>
        </header>
        <footer data-role="footer">
            <div data-role="tabstrip">
                <a href="#index" data-icon="info">Info</a>
                <a href="#schedule" data-icon="toprated">Schedule</a>
            </div>
        </footer>
    </div>

And here’s an example of one of the views I defined with the data-layout equal to the value of the data-id defined above:

     <div id="resultsView" data-role="view" data-title="Biz Finder" data-layout="app">
        <input type="text" maxlength="5" size="5"/>
        <input type="search" value="spa" onchange="getData(onResult)"/>
        <ul id="resultListView"/>        
    </div>

Below is the result of my sample Biz Finder app running on the iPad:

and here is the same code running on the Galaxy tablet (Android OS):

Notice how the header and footer, buttons and entire look and feel are changed to adapt to the platform without any changes to the code. If you do want to control something for a specific platform, you can override or extend the CSS styles for them. For instance, I could define something like the following to control the paragraph element on each platform specifically:

    .km-ios p {
        color: #545454;
        font-size: 18px;
    }
    .km-android p {
        color: #FFFFFF;
        font-size: 16px;
    }

Note: There are a number of button icons included by default to mirror the native OS for things like search, settings, favorites etc. You can set a data-icon attribute on the HTML button tag to set a specific one. A list of those included can be found here. Below is a screenshot showing a sample of some included icons.

There’s also a Themebuilder offered by Kendo to be aware of, that allows you to choose styles and export a CSS file to be used with your application.

Other things worth noting…

  • Kendo supports the MVVM pattern (Model-View View-Model
  • You can integrate Kendo UI with frameworks such as knockout.js or backbone.js. There’s an interesting project here that provides bindings for knockout.js and kendo.js.
  • Each mobile view instantiates a scroller for its content. In addition you can specify data-role=”scroller” to add one to any element.
  • The UI controls were designed with responsive design in mind allowing for a fluid experience across devices (automatically sized).

Below are some screenshots showing some of the default mobile components for iOS to give an idea of what’s included:

ActionSheet

Button Styles

Loading Popup

TabBar

Switch

Kendo UI for mobile can be used along with PhoneGap/Cordova easily. A summary of the steps are listed below (assumes Mac OSX), but see this post for a more specific walkthrough:

1) In XCode, create a Cordova-based project
2) Run the project to generate the needed www folder
3) Right click the root of the project and click ‘Show in Finder’
4) Copy the www folder that was just generated into your XCode project by dragging it in and selecting the ‘Create folder references for any added folders’ option only (do not check the Copy items… checkbox).
5) Copy the kendo js, css and jquery files from your kendo download into your project
6) Add references to the kendo js, css and jquery files in your index.html after the cordova include, such as:

        <script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
        <script src="js/jquery.min.js"></script>
        <script src="js/kendo.mobile.min.js"></script>
        <link href="styles/kendo.mobile.all.min.css" rel="stylesheet" />

Note: In my example above I created the js and styles folders under my www folder and copied the files into those subfolders in step 5 accordingly.

7) Initialize a KendoMobileApplication object:

      <script>
          window.kendoMobileApplication = new kendo.mobile.Application(document.body);
      </script>
     

8) That’s it, you’re ready to build your app and access the native device via cordova/phonegap APIs, or take advantage of the kendo framework elements!

Related Links
Device Simulator – Quickly test out Kendo on different devices here
Kendo UI Mobile Documentation
What’s new in Kendo UI’s next release? Register for webinar here

The sample code for my Biz Finder app is shown below for full reference:

<!DOCTYPE HTML>
<html>
<head>
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
    <meta charset="utf-8">


    <script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
    <script src="js/jquery.min.js"></script>
    <script src="js/kendo.mobile.min.js"></script>
    <script src="js/console.js"></script>
    <link href="styles/kendo.common.min.css" rel="stylesheet" />
    <link href="styles/kendo.mobile.all.min.css" rel="stylesheet" />

    <script type="text/javascript">
        function onBodyLoad()
        {
            document.addEventListener("deviceready", onDeviceReady, false);
            // Use the following for testing in the browser
            getData(onResult);
   }

        /* When this function is called, Cordova has been initialized and is ready to roll */
        /* If you are supporting your own protocol, the var invokeString will contain any arguments to the app launch.
         see http://iphonedevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html
         for more details -jm */
        function onDeviceReady() {
            getData(onResult);
        }

        function getData(callback) {
            var template =  kendo.template($("#customListViewTemplate").html());
            var dataSource = new kendo.data.DataSource({
                transport: {
                    read: {
                        url: 'http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=YahooDemo&query='+search.value+'&zip='+zip.value+'&output=json&results=15',
                        dataType: "jsonp" // JSONP (JSON with padding) is required for cross-domain AJAX
                    }
                },
                schema: {
                    data: "ResultSet.Result"
                },
                error: function(e) {
                    console.log("Error " + e);
                },
                change: function() {
                    $("#resultListView").html(kendo.render(template, this.view()));
                }
            });
            dataSource.sort = ({field: "Distance", dir: "asc"});
            dataSource.read();
            $("#resultListView").kendoMobileListView({dataSource:dataSource,template: $("#customListViewTemplate").html()});
        }

        function onResult(resultData) {
            console.log("Results " + resultData);
            $("#resultListView").kendoMobileListView({dataSource: kendo.data.DataSource.create({data:resultData,sort: { field: "Distance", dir: "asc" }}),
                template: $("#customListViewTemplate").html()});
        }
    </script>
</head>

<body onload="onBodyLoad()">
<script type="text/x-kendo-template" id="customListViewTemplate">
    <h4>${Title}</h4>
    <p>${Address}</p>
    <h4 id="distance">${Distance} miles</h4>
    <a data-role="button" class="details-link">Visit Website</a>
</script>

<div id="resultsView" data-role="view" data-title="Biz Finder" data-layout="app">
    <div class="form">
        <div id="leftcol"></div>
            <div id="centercol">
                <label id="lblZip" for="zip">Zip</label>
                <input id="zip" type="search" value="90210" maxlength="5" size="5" onchange="getData(onResult)"/>
                <label for="search">Search</label>
                <input id="search" size="10" maxlength="10" type="search" value="spa" onchange="getData(onResult)"/>
            </div>
        <div id="rightcol"></div>
    </div>
    <ul id="resultListView"/>
</div>

<div id="settings" data-role="view" data-title="Settings" data-layout="app">
    <h2>This is the Settings View...</h2>
</div>

<div id="about" data-role="view" data-title="About" data-layout="app">
    <h2>This is the About View...</h2>
</div>

<!-- define multi-use layout for header/footer -->
<div data-role="layout" data-id="app">
    <header data-role="header">
        <div data-role="navbar">
            <span id="ttl" data-role="view-title"></span>
            <a data-align="right"  data-role="button" data-icon="settings" href="#settings"></a>
            <a data-align="left" data-role="backbutton" href="#index">Back</a>
        </div>
    </header>
    <footer data-role="footer">
        <div data-role="tabstrip">
            <a href="#resultsView" data-icon="search">Search</a>
            <a href="#about" data-icon="about">About</a>
        </div>
    </footer>
</div>

<style scoped>
    #customListViewTemplate {
        margin:0;
        padding-right: 5px;
    }

    #leftcol {
        position:relative;
        top:-10px;
        left:-10px;
        float:left;
        width:2%;
        margin:0 0 -10px 0;
        padding:10px;
        z-index:100;
    }

    #rightcol {
        position:relative;
        top:-10px;
        right:-10px;
        float:right;
        voice-family: "\"}\"";
        voice-family:inherit;
        width:5%;
        margin:0 0 -10px 0;
        padding:10px;
        z-index:99;
    }
    
    #settings h2, #about h2 {
        margin: 10px;
        font-family: Tahoma;
    }

    #centercol {
        position:relative;
        padding-left: 30%;
    }
    .form h3 {
        padding-left: 30%;
    }
   
    .form {
        width: 100%;
        padding-top: 10px;
        padding-bottom: 15px;
        padding-left: 12px;

        background-size: 100% auto;
        background-image: -moz-linear-gradient(center top , rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.45) 6%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.15) 50%, rgba(100, 100, 100, 0));
        background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(0, rgba(255, 255, 255, 0.5)), color-stop(0.06, rgba(255, 255, 255, 0.45)), color-stop(0.5, rgba(255, 255, 255, 0.2)), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(1, rgba(100, 100, 100, 0)));
        background-color: #ef652a;
        color: #fff;
    }
    
    h3, h4, p {
        margin:0;
        padding:0;
        font-family: fantasy;
    }

    label {
        font-size: 18px;
    }
    .km-ios p {
        color: #545454;
        font-size: 18px;
    }
    .km-android p {
        color: #FFFFFF;
        font-size: 16px;
    }
    .km-android #distance {
        color: #CCCCCC;
        font-size: 16px;
    }
    .km-ios #distance {
        color: #808080;
        font-size: 16px;
    }
    #distance {
        color: #808080;
        font-size: 16px;
    }
    #content {
        margin: 0px;
        padding: 0px;
    }
    #header {
        background-color: pink;
    }
    #resultListView {
        background-size: 100%;
        background-image: -moz-linear-gradient(center top , rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.45) 6%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.15) 50%, rgba(100, 100, 100, 0));
        background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(0, rgba(255, 255, 255, 0.5)), color-stop(0.06, rgba(255, 255, 255, 0.45)), color-stop(0.5, rgba(255, 255, 255, 0.2)), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(1, rgba(100, 100, 100, 0)));
        margin: -10px;
        padding: 5px;
    }
    .details-link {
        margin-top: -1em;
        position: absolute;
        right: 0.6em;
        top: 50%;
    }
    </style>
    <script>
        window.kendoMobileApplication = new kendo.mobile.Application(document.body);
    </script>
</body>
</html>

Filed in: Mobile DevelopmentPhoneGap Tags:

About the Author ()

Comments (12)

Trackback URL | Comments RSS Feed

  1. Ben Hayat says:

    Hi Holly;

    Nice article; The team behind Kendo UI come from years of experience developing high-end Telerik Web controls. That’s why you see great quality and it’s well thought out. Looking forward to your future blogs!
    ..Ben

  2. George says:

    Hi Holly,
    Very good article. With regard to the transitions, these are originated from the JQuery Mobile framework and not the KendonUI, am I right.

    Thanks,

  3. Ihor says:

    Telerik is High level taeam and their KendoUI is very nice product, but not FREE :)

    • Ben Hayat says:

      @Ihor;

      There is nothing for FREE. You either pay straight forward for the goods you get, like Electricity, Rent, Food, software or you pay in a hidden way.

      Telerik deals with it’s customers in a straight upfront none-hidden way. That’s why they’re growing everyday, unlike some of those “FREE” software companies.
      ..Ben

  4. Todd says:

    Hey Holly-

    Thanks for the great Kendo UI Mobile write-up! We really appreciate the review.

    @George- Nope. Kendo UI’s only external dependency is jQuery core. It does not build on jQuery Mobile or UI. All Kendo UI animations/transitions attempt to use CSS3 first (for the improved, hardware accelerated perf) and then JS as a fallback.

    -Todd

  5. whoizz says:

    Hi Holy,

    nice article. It really seems Adobe completely dropped Flex and all evangelists that used to work with Flex to HTML/JS – but I’m still waiting a nice UI component set to make my transition (or have a go with dart-flash and see if I can remain close to Flex) – also, do you know if these folks from Kendo have any support to SOAP?

    @Ben: I’m sorry my friend, but your statement was just dumb – there are open source software out there “cost-free” – and PhoneGap is one of those case you wonder – not that I’m really concerned with 200$ – but somehow you tie up with another license to deploy and I can see a lot of potential issues there.. (why choose open-standards on open-source stack to deal with license on the UI component set?)

    @Todd: so it seems performance may vary ‘a lot’ from device to device, is that right? – is it possible to have a 60fps transition / scroll on CPU only? (in this case, not making use of CSS3..)

  6. Todd says:

    @whoizz-

    Yes, perf clearly will vary from device to device, just as it does for any programming language or run-time. HTML5 is not magic. :) Kendo UI simply uses all of the tricks available to sub-optimize for performance- more than most JS/H5 frameworks.

    And to comment on the licensing, Kendo UI tries hard to not let licensing get in the way. We’re not “free open source” because we make a living off our tools, but we also make commercial licensing very easy (royalty free, no keys, etc.).

    As long as you’re not trying to build an MIT (or “copy free”) OSS project, Kendo UI is very easy to license and include in your project.

    Hope that helps.
    -Todd

  7. Nice post. Im happy to see ppl writing about this awesome tool.

    I just love working with KENDO UI…recently acquired a mobile license and the performance factor played the major role for my decision.

    Im not part of KENDO UI team…im a solo developer from Brazil, and Im currently thinking about writing a kind of Portuguese version of KENDO UI Mobile initial steps.

    Congrats and keep doing this great job!

  8. Diya says:

    I want to like Kendo UI. The telerik component set is very impressive. Unfortunately I’m expecting behavior in their grid to be more like SmartClients out of the box. Maybe they should take a look and see if they can make their demo a little more impressive.

    I was even lately trying to explore JQuery Mobile stuff too. I am still confused of using Kendo UI or JQuery Mobile.

    JQuery Mobile has open source community advantage and it is really hard decision to switch over to Kendo UI. Is it possible for you to write a good blog post about why i should switch to Kendo UI over JQuery Mobile?

    • Todd says:

      @Diya- We’d love to know more about what you want to see in the Kendo UI Grid that it does not offer today. Feel free to share ideas on our UserVoice site (http://feedback.kendoui.com).

      As for jQuery Mobile vs Kendo UI Mobile, clearly there will be fans of both. For Kendo UI Mobile, our approach is very different. We want to help you build mobile apps that look and feel native wherever they’re run, whereas jQuery Mobile focuses more on providing a “one size fits all” mobile experience. If your goal is to create a native-like app, Kendo UI Mobile may help you do that more directly.

      Hope that helps.

  9. peter says:

    Hi –
    How would I load related data- like a master detail list. Actually what I want is a List -> select one shows another list -> select one shows the details . How do you pass the id about and load the page? each list gets it data based on the previous – so getData.php, then getSubData.php?id=2, and so on

Leave a Reply