BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles How to Collect Pieces of Data

How to Collect Pieces of Data

Leia em Português

Bookmarks

Key Takeaways

  • Pieces is a JavaScript library that provides page transitions with routing and animation
  • Pieces provides a collection of navigation objects with a uniform interface
  • Pieces together with a small number of other libraries could amount to a reasonable, lightweight alternative to a comprehensive web framework
  • Pieces can also help provide the polish that people expect from native mobile apps
  • Using Pieces could open up opportunities to simplify web app design

A big change happened in the way we write web applications more than a few years ago now. On the web of the 90s and up until the mid-late 2000s a web page was a single document, that is mainly static text and images. If we wanted to provide a more interesting experience to our users we had to create several pages and connect them together with hyperlinks. It was a halcyon time when GIFs were cool and I was writing .NET MVC applications with barely any JavaScript.

That all changed, and much for the better, with the arrival of single-page applications. Now the data displayed on the page could be changed during the runtime of the application without reloading the page and background HTTP requests allowed us to fetch data from the server in response to user input making greater interactivity possible.

There is one aspect of traditional web pages that is not immediately clear how to carry over to the world of single-page applications: what happens with the URL displayed in the address bar? For traditional applications the address just identified the page that you were currently viewing. For single-page applications the address doesn’t automatically change even as we change the part of the application that we’re viewing. If we are not to lose the ability to link to particular parts of websites, some mechanism is needed for changing the URL as we navigate through an application and conversely routing the user to a particular part of the application according to what is typed in the address bar.

That brings us to the related issue of page transitions. Transitions between traditional web pages involved reloading the entire page. The browser would go blank momentarily and you’d need to wait for everything to be rebuilt on the screen, which is not a great user experience. Single-page applications don’t just make the equivalent transitions much faster, they open up some entirely new possibilities. Instead of just replacing one part of the page with another why not animate the transition between them? Sliding, fading and other animations are possible once JavaScript is in control of the web page.

Pieces, a new JavaScript library I have created, takes these two problems of routing and page transitions and tackles them together. After all, they're both concerned with what happens when the app changes from one view to another. The idea is that the developer creates the individual pages and let’s Pieces worry about everything involved in changing between them.

Pieces relies on a data binding library called Datum (See the Datum introduction and Datum quickstart guide for more information). Datum is a nifty little library that is well capable of creating single-page applications on its own, but it leaves the important questions of routing and page transitions unanswered. Pieces provides one possible answer to those questions.

It’s important to remember though that neither Datum nor Pieces is a web framework. They are separate libraries each with the goal of solving their own specific problems. They are not tightly integrated, Pieces depends on Datum but Datum exposes no specific API to help Pieces do its job. While Pieces intends to work in a way that is general enough to apply to most web applications it does make some decisions about website behaviour that won’t conform to everyone’s opinion. If this is the case with you then Datum can be used on its own or in conjunction with an alternative library.

In Datum, application components are just JavaScript objects. Pieces expects you to create components as objects using Datum then pass them to the constructor of a navigation piece that Pieces provides. Which navigation piece you choose determines what kind of navigation behaviour the application will have. The navigation pieces themselves are also just JavaScript objects so you just add them to the view model according to where they should appear on the page.

Most of the navigation pieces have the same interface. A simple example would look something like this with a fading animation between three pages and some buttons to trigger the transition:

function Fade() {

    this.onBind = function(element) {

        $(element).load("html/fade.html");
    };

    // Create a navigation container with pages and routes.
    this.content =
        new FadeNavPiece([

            { route: "one", page: new FirstPage() },
            { route: "two", page: new SecondPage() },
            { route: "three", page: new ThirdPage() }
        ]);

    // Navigation buttons.
    this.one = new NavButton(0, this.content);
    this.two = new NavButton(1, this.content);
    this.three = new NavButton(2, this.content);
}

By the way this fade transition both fades-in and fades-out simultaneously which is not an easy trick to achieve!

Slide navigation is similar to fade navigation except the animation will be a horizontal sliding motion instead of fading in and out. The scroll navigation piece is a bit different from the fading and sliding navigation pieces as all sub-pages will get displayed at once one below the other. The animation just scrolls up and down the page to the appropriate components.

The Router Piece doesn’t have any animation associated with it. Instead it is there to be kind of an "or anything else" point of extensibility. If Pieces doesn’t provide some behaviour out of the box then it can probably be implemented using the Router Piece. The Router Piece takes just one component as a parameter and it looks for a property on it called route. The value of that route property is what appears in the URL path. If the property is updated then the URL will be updated and if the URL changes then the route property can change. Any functionality that depends on the value of the route property will therefore be synced with the URL. This example displays a picture of an animal according to what animal the Router Piece finds in the URL.

function Router() {

    // The router piece looks for a property named route.
    this.route = "";

    this.onBind = function(element) {

        // Load the template.
        $(element).load("html/animalTemplate.html");
    };

    // The update callback is called whenever the animal gets updated.
    this.image =
        new Update(function(element) {

            // Display the image.
            element.src =
                "images/animals/" + this.route + ".jpg";
        });

    // Wrap the object in the router piece.
    return new RouterPiece(this);
}

Now comes the fun part: nesting. The path of a web page usually isn’t just one word, it’s a list of words like /path/to/my/web/page. Equally one page of a single-page application can contain its own elements of interactivity and even its own sub-pages. Pieces will automatically combine the routes of nested navigation pieces into one path. You’re not constrained to using one style of navigation for the whole application. By nesting navigation objects, different parts of the application can use different transitions. Perhaps the top-level navigation might be sliding between pages, but one of those pages could display information in an interesting way by fading between different snippets of text. Pieces will connect the routes for these different elements into one route so different parts of the application can get easily linked to.

We can combine the two examples above by having a fading top-level navigation and our animal example as one of its pages.

new FadeNavPiece([

    { route: "one", page: new FirstPage() },
    { route: "two", page: new SecondPage() },
    { route: "three", page: new ThirdPage() },
    { route: "router", page: new Router() }
]);

In this case we can see a cat by writing #router/cat at the end of the url.

This gives us all we need to write single-page applications. Most likely you’ll also need a UI widget library and perhaps others for data validation and other functionality, but the mechanics of arranging components on a web page and transitioning between them are here. For other libraries there are many good options available and ones that aren’t specific to a particular framework should work fine in this context. There could be quite a bit more to say about web app design, but I won’t expand too much on that here. It’s worth noting though that if you are used to the MVC style of application design, then what we’ve seen will have been quite different. It would be possible to create separate model and controller objects and use the objects we used above as the view but that would probably be overkill, especially if there is also a data model on the server-side. We can keep it simple and use objects like those in our examples to represent the entire state of the web app because there is enough flexibility in this kind of view model to handle any differences between how we receive data from the server and how it gets displayed on the page.

Motivation

My aim in creating Pieces is to show that heavyweight web frameworks are not the only solution for easy web application development. A convenient feature like tightly-integrated routing and page transitions is achievable with just a simple library. Some of today's frameworks struggle from either being too heavyweight or being a largely inconsistent collection of features without consistent design, negating the benefits of a framework.

Systems that are designed as small flexible pieces form the foundation for building your own lightweight framework. We see this trend with modern tools like Svelte, Dojo, Preact, and many others, and Pieces follows this mindset of doing focused things well without trying and failing to be everything to everyone.

Pieces is not the right tool for every web app you create, but it’s a good choice for many applications and a useful leg up for those who don’t want to roll their own routing and page transition module. With small flexible modules you can choose to use it or not. That’s the point!

In the ongoing debate of whether to use web frameworks or native frameworks for mobile applications, there is a lot of temptation to choose more integrated environments provided by iOS and Android. Developers may not want to spend time reinventing functionality that is common across apps so will tend to choose application platforms that provide them with a lot of functionality out of the box. Learning to be productive on a new platform can seem daunting to less experienced developers so the temptation is to make life easy for them by giving them all the key tools they'll need in one place. Once they have gained more experience though those developers will rightly ask why they are forced to do things in the prescribed way. There seems to be a tradeoff where the more you try to give developers tools to enable them the more you create a highly coupled environment that restricts their choices. The challenge is to give developers something really useful without restricting their choices of how to do anything else. I do think this is possible though it requires careful thought about the way different components of a web app interact.

The question of decoupling should be of particular concern when we are talking about the web. The web does not have the advantage of being carefully designed by a single company in the way that other platforms were. The web is more of a collaborative effort with different technologies that have proved themselves over the years layered on top of each other. I tend to think that the web is better off for this. In the end it means not just more people writing libraries for the web but the advantage of more approaches and perspectives added to the mix. I think this should influence the way we write libraries. The ideal would be to have a selection of decoupled libraries that can be used or not according to preference. Those who want lots of help could choose to use lots of libraries and those wanting more customisation could use fewer, but we’d all be
working in the same environment, not each community in it’s own silo.

Some of the challenges with this are choosing the correct abstractions and promoting the right foundational APIs to avoid substantial duplication across modules. For example, before promises and modules were standardized, there was significant work to make different libraries work consistently with asynchronous patterns and modules. Perhaps the proposed JavaScript Standard Library ( https://github.com/tc39/proposal-javascript-standard-library ) can further help define this balance between platform vs. module or framework.

I have found that clearly defining the interface between JavaScript and HTML is a valuable abstraction and with Pieces I have used that abstraction to separate the visual elements of an application from the behaviour that connects those visual elements together. I hope this will help developers write applications, but I also hope it will inspire library writers to create more abstract and decoupled libraries that will further increase the power of the web.

Pieces is open source software available under the LGPL version 3 license. Visit piecesofdata.com to get started with Pieces.

About the Author

Martin Rixham works in IT consulting, applying years of experience in web development and various JVM languages. He divides his time between London and Bangalore where he has the privilege of being part of two great IT communities.

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT