Telerik blogs

One of the early (great) pieces of feedback we received during the Kendo UI beta is that you want to see more examples of Kendo UI in action. Sure, there is a huge (and growing) Kendo UI demo center, loaded with focused demos for Kendo UI widgets and framework components (like the Data Source, Templates, and Drag-and-Drop). But you want to see more Kendo UI widgets and components working together in so-called "integration" examples.

Ask and ye shall receive.

Kendo UI Feed Reader

This is a very basic demo app built with Kendo UI (by me, not by the product team, so any "non-Jedi" code is my fault, not theirs), designed to be simple enough to showcase a few Kendo UI widgets in-action with some "good practice" JavaScript and CSS.

As the name implies, this is a simple app that lets users add RSS feeds, review post summaries in a grid, and click on interesting posts to see the details (or as much detail as the RSS feed provides).

The demo features the following:

You can try a live version of the demo now. Let's talk about some of the more interesting aspects of this app.

App Layout

The basic app has three sections: a list of feeds (A), a list of posts from a selected feed (B), and an area to load and view post content (C).

SNAGHTML66ee8d9

Right off the bat, you can see where the various Kendo UI widgets have been used to make this a rich app experience:

  • Panelbar is used to display a list of saved feeds
  • Splitter is used to provide a dynamic panel layout (complete with min/max sizes, user resizable bars)
  • Grid is used to display posts, using Templates for custom row formatting (complete with sorting and scrolling)
  • Window (not picture) is used when "Add Feed" is clicked to allow the user to input a new RSS URL
  • Button*, while not a formal widget, is used for consistent theming (via the Kendo UI .k-button CSS class)

Project Structure

Good, consistent project structure is imperative with HTML and JavaScript apps. Most of the code you write is being "shipped" to the client, so a well structured project not only becomes easier to maintain, but it looks more professional.

There is no definitive right way to structure your project. There many guidelines. Just pick a structure that makes sense for your project and stick to it. For this project, I used the following layout:

image

Feed Reader is a single-page app, so all of the "core" HTML is in index.html (and it's remarkably little thanks to Kendo UI). I then have these conventions:

  1. Content: For any static site content, like images
  2. Scripts: For any local scripts used by the app (a few more come from remote CDNs, like jQuery and LESS)
    • File naming: [associated page].[extension].js
    • Modules: [app name].[module name].js
  3. Styles: For all site CSS (and in this case, LESS) files and supporting CSS sprites
  4. Templates: For all external Kendo UI template definitions
    • File naming: _[associated page name].tmpl.htm

Are there other ways to do this? Of course. But this structure is clean and easy to understand. You can also see that I've included my builds of Kendo UI JS and CSS.

Loading Feeds with Kendo UI Data Source

Under the covers, this demo uses the Kendo UI Data Source to load and retrieve feeds. Of course, if we try to fetch RSS feeds directly from the browser, we'd get an error like this:

XMLHttpRequest cannot load http://www.engadget.com/rss.xml. Origin http://htmlui.com is not allowed by Access-Control-Allow-Origin.

Browser security prevents direct fetching of resources from other domains unless the domain host includes the Access-Control-Allow-Origin header. Unfortunately, not many servers includes these headers today, so we have find other ways to work around the security sandbox.

The most common solution is a proxy. Two kinds of proxies can be used:

  1. Same Domain Proxy - Your client-side code can talk asynchronously to servers on the same origin as the page (i.e. your servers). Therefore, you can create a server-side proxy that can fetch content from remote domains and return it directly to your JavaScript XHR code. Powerful, but requires you to build and maintain the proxy.
  2. JSOP Proxy - In this case, you can use proxies hosted on other domains as long as those proxies provide JSONP responses. The remote proxy still serves as a middle-man, fetching the remote content, but rather than returning the response directly, a JSONP callback is leveraged.

YQL is a very mature version of the second type of proxy. It provides a robust querying language that allows you to grab almost any content from the web and return it as a JSONP response. By using YQL to grab our RSS feeds, we end-up with a Data Source configuration that looks something like this:

//To fetch XML locally, create YQL proxy
var proxyUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'" + encodeURIComponent(url) +"'";

_feedItemDS = new kendo.data.DataSource({
    transport:{
        read:{
            url: proxyUrl,
            dataType: "xml"
        }
    },
    schema:{
        type:"xml",
        data:"query/results/rss/channel/item",
        model:{
            id:"guid",
            fields:{
                title: "title/text()",
                pubDate: "pubDate/text()",
                story: "description/text()",
                url: "link/text()",
                id: "guid/text()"            
            }
        }
    }
});

As you can see, we construct our "proxy" URL using YQL and the URL encoded address of our target RSS feed, and then we configure our Kendo UI data source to work with the XML results. Super easy.

The Kendo UI Data Source will even auto-cache items that have been loaded such that they will not be re-fetched from the remote end-point as we click-around our application and switch between feeds.

(The truly astute readers may have also realized that we could have wrapped YQL support in a new Kendo UI data source type provider and made the syntax even more elegant!)

Loading Templates from External Files

Kendo UI Templates are used in a few places in this demo. Panelbar items are templated. Grid rows are templated. Kendo UI templates are even used for the "post detail" area rendering.

Rather than store these template definitions in the main page HTML, where they're not really supposed to be part of the DOM, I placed the templates in an external file: _index.tmpl.htm. The templates are then loaded asynchronously and the Kendo UI widgets are initialized when the templates are ready.

The naming convention is not a "rule," but it is good practice:

  • Using "_" (underscore) prefixes is a good convention, both in file naming and JavaScript for indicating that resource should be private. In the case of a HTML resource, it indicates that the page should never be directly loaded (you could even create server rules to prevent non-async loading of underscore resources).
  • Matching the name of the template file to the name of the view the templates are used by helps with organization.
  • Using the "tmpl" extension further helps make it clear the file contains template definitions instead of random HTML. The final "htm" extension is used to eliminate the need to configure web servers to understand a custom extension.

Templates cleanly separated, they are fetched and cached in to the page DOM using a script like this:

var templateLoader = (function($,host){
    //Loads external templates from path and injects in to page DOM
    return{
        loadExtTemplate: function(path){
            var tmplLoader = $.get(path)
                .success(function(result){
                    //Add templates to DOM
                    $("body").append(result);
                })
                .error(function(result){
                    alert("Error Loading Templates -- TODO: Better Error Handling");
                })
                
            tmplLoader.complete(function(){
                $(host).trigger("FEED_MANAGER_TEMPLATE_LOADED", [path]);
            });
        }
    };
})(jQuery, document);

The only thing worth additional highlight here is the use of jQuery Triggers as a simple pub/sub pattern. When templates are finished loading, they trigger a custom event using jQuery. Any other function in the app can bind to that event and take actions when it occurs (such as initializing Kendo UI widgets that depend on the templates).

Site Styling

Clearly, Feed Reader does not require complicated styling. Kendo UI provides the nice Blue Opal theme used for the UI widgets, and I use some simple matching CSS for the rest of the site. In a future post, I'll talk about customizing the Kendo UI styles.

Feed Reader does use LESS for CSS. I'm a huge LESS fan since it makes CSS writing much more powerful and easy to maintain. For better learning, I don't pre-process the LESS styles on the server. Instead, I serve the "raw" .less files and let the LESS.js file do on-the-fly pre-processing. You can inspect the source to see how LESS is being used deliver features like CSS variables and nested rules. For example:

.post{
    header{
        background: #EEE;
        border-bottom: 1px solid #333;
        margin-bottom: 10px;
        padding: 5px;
        
        h2{
            font-size: 1.2em;
            line-height: 1.5em;
            margin: 0;
        }
    }
    
}

When this LESS is processed, it produces this "normal" CSS that works in any browser for Feed Reader:

.post header {  
    background: #EEE; 
    border-bottom: 1px solid #333;  
    margin-bottom: 10px;  
    padding: 5px;
}

.post header h2 {  
    font-size: 1.2em;  
    line-height: 1.5em;  
    margin: 0;
}

 

Normalize.css is also used instead of a more draconian "CSS Reset" (which blows away useful browser style defaults) so that my styles are consistent across browsers.

Handling User Actions

One of the more difficult things to do "correctly" with my JavaScript is handle the basic user actions, like clicking on a button. It is generally regarded as improper (for many good reasons) to directly connect a UI element, like an HTML button, to a specific JavaScript event handler. In other words, you don't want to do this:

<button id="myButton" onclick="onMyButtonClick();">Click Me</button>

This is brittle. It mixes "code with markup." And it can produce unexpected results if the button is clicked before the JavaScript handling the click is ready.

For Feed Reader, I used HTML data attributes + jQuery to bind my buttons to JavaScript event handlers during my application "init" process. The code looks something like this:

HTML

<div class="buttonBar">
    <button class="k-button" data-event="addFeed" id="btnAddFeed">Add Feed</button>
    <button class="k-button" data-event="removeFeed" id="btnRemoveFeed">Remove Feed</button>
</div>

JAVASCRIPT

//[Excerpted code]

//Define a collection of event handlers
_clickHandlers = {
    "addFeed": function(){
        //Do something to add feed
    },
    "removeFeed": function() {
        //Do something to remove feed
    }
}

//Bind the handlers to the appropriate elements using jQuery delegate 
//based on the HTML5 data-event attribute for each button
//during JS
init _private: {
    initDelegates: function(){
        $(document).delegate("button", "click", function(e){
            var that = $(this),
            eventData = that.data("event");
            
            _clickHandlers[eventData](e);
        });              
    }
}

What's happening?

Instead of polluting the page (and browser memory) with a bunch of individual event handlers for every button, I use jQuery delegate to bind the click action for any button in my app to a single function. Inside of this single event handler, I easily fire the appropriate function using the named event associated with the button.

Rich UI Widget Features

Of course, in all of this Kendo UI is providing a rich UI experience for users. When you play with the live demo you can see these features in action, but among the features to look for:

  • GRID
    • Sorting by Title or Date - Even with the custom row template, you can still sort the data by these fields
    • Scrolling - The headers are always visible with Grid scrolling enabled
    • Keyboard navigation - Move between posts using the arrow keys, select with the spacebar
  • SPLITTER
    • Pane Resizing - Users can easily resize the horizontal or vertical app panes
    • Min/Max Pane Size - The vertical pane has min/max width limits to make sure it's never over- or under-sized
  • WINDOW
    • Animation - The window will smoothly animate in to (and out of) position when "Add Feed" is clicked
    • Modal dialog - With simple configuration, the window is made modal
    • Draggable - While a Kendo UI Window can be resizable and maximizable, we just use the draggable feature in Feed Reader

Each UI widget adds just enough richness, tested out-of-the-box to work in all Class-A browsers (including touchscreen browsers!), to make the Kendo UI Feed Reader experience natural and intuitive.

Next Steps

There is clearly a lot more happening the actual source for this simple demo than highlighted in this post. Check it out. Learn by example. Hopefully this helps highlight a few of the simple ways you can use the pieces of Kendo UI together to build things.

In future posts, I'll highlight how HTML5 Local Storage is used to provide some basic caching, and how jQuery selectors are cached to reduce DOM scanning (thus improving performance). For now, check-out the demo and let me know A) if you have any questions, or B) how it can be improved (because v1 code always can be improved)!

Try the Kendo UI Feed Reader Live Demo
(Source code is just a right-click, View Source away…it's just JavaScript & HTML)


ToddAnglin_164
About the Author

Todd Anglin

Todd Anglin is Vice President of Product at Progress. Todd is responsible for leading the teams at Progress focused on NativeScript, a modern cross-platform solution for building native mobile apps with JavaScript. Todd is an author and frequent speaker on web and mobile app development. Follow Todd @toddanglin for his latest writings and industry insights.

Comments

Comments are disabled in preview mode.