npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

backbone-viewport

v0.5.3

Published

Tiny single page application framework built on Backbone

Downloads

1

Readme

backbone-viewport

Tiny single page application framework. Based on jQuery and Backbone, it provides an API to create single page applications. Supports HTML5 history.pushState method and hash routing.

Viewport stores pages as Backbone's models with related Views. When [URL changes] user goes to some page, it retrieves URI, creates page Model, renders page View, and put model into Collection with unique URI, and shows it. If page for URI exists in Collection, it just shown.

Requirements

  • jQuery/Zepto/$-compatible framework can be used by Backbone.js
  • Backbone.js

Release

Development version

Minimized production version

Examples

Example with hash method

Classes

Viewport.View

Inherited from Backbone.View. Represents page view. View is rendered on any model's change.

Attributes

| Name | Type | Default | Description | | ------- | ------ | ------- | ----------- | | tagName | string | 'div' | Inherited from Backbone.View. Tag name of container element |

Methods

.template(data)

Must be overridden. Receives model attributes and return rendered string.

It is common to use html templates in <script type="text/html"> elements and use underscore to render them. Here is an example how .template() may look like:

<script type="text/html" id="template-page-discovery">
    <h1><%= name %></h1>
    ...content...
</script>
var View = Viewport.View.extend({
    // ...
    template: function(data) {
        var template = $('#template-page-' + this.model.get("name")),
            templateFn = _.template(template.html());

        return templateFn(data);
    }
});

// Extending classes and configuring router...

// In Router's action:
router.go({ name: "discovery", content: "" /* , ... */ });

...will cause script[id="template-page-discovery"] will be rendered with data:

<h1>discovery</h1>
...content...
.render()

Renders model attributes by template.

.toggle(active)

Set display: block css style to page container if active=true, or display:none if false. Override it to use different behaviour.

Events

| Event type | Description | | ---------- | ------------ | | rendered | Fires when .render was called. |

Viewport.Model

Inherited from Backbone.Model. Contains page's attributes and data, which can be rendered in view.

Attributes

| Name | Type | Default | Description | | ------ | ------- | ------- | ----------- | | uri | string | | Generated automatically if not given. Unique identifier of every page. Viewport uses Backbone.history methods getPath() and getHash() for history.pushState and hash routing. | | active | boolean | true | Indicates visibility of a page. When changed, page container is set display: block css style if true, and display:none if false. Override Viewport.View.toggle() to use whatever behaviour. |

All model's attributes are available in view.template().

Methods

.show()

Set page.active property to true. Triggers shown event.

.hide()

Set page.active property to false. Triggers hidden event.

.getFetchOptions()

Extend this method to provide options for ajax fetch call:

var Page = Viewport.Model.extend({
    // ...
    getFetchOptions: function() {
        var defaults = Page.__super__.getFetchOptions.call();

        return _.extend({}, defaults, {
            beforeSend: function() {
                // custom beforeSend callback
            },
            error: function() {
                // custom error handling
            },
            complete: function() {
                // custom callback on complete
            }
        });
    }
});

Events

| Event type | Description | | ---------- | ------------ | | shown | Fires when page was hidden and became shown. | | hidden | Fires when page was shown and became hidden. | | render | Fires when page content needed to be rendered. |

var Page = Viewport.Model.extend({
    initialize: function() {
        this.on("shown", this.onShown);
    },
    onShown: function() {
        // event handling
    }
});

Viewport.Collection

Inherited from Backbone.Collection. Stores pages. Accessing pages to add/toggle them. When page is added, new Viewport.View is created and linked to this page.

Properties

| Name | Type | Default | Description | | ----- | -------------- | ----------- | ----------- | | el | jQuery | $('body') | Pages container. Available after router initialized. Not allowed in extend(). | | model | Backbone.Model | Viewport.Model | Type of model used by collection. | | view | Backbone.View | Viewport.View | Type of view used by collection. Will be created on collection.add(). |

Methods

.open(uri)

Open page with given uri and hide others. Find and show() page with uri, hide() other pages.

.pushPage(attributes, $el)

Create a page with given attributes and existing HTML-element ($el) and insert into collection. Useful for rendering start page without loading data. Returns added page.

Viewport.Router

Inherited from Backbone.Router. Listening to URI changes and handling assigned events. Contains Viewport.Collection and accessing it to handle pages.

Properties

| Name | Type | Default | Description | | ---------- | ------------------- | -------------- | ----------- | | collection | Backbone.Collection | Viewport.Collection | Type of collection used by Router. |

Methods:

constructor / .initialize([options])

Creates new instance of Viewport.Router. If start=true, runs Backbone.history.start() when initialized and begin listening to URL changes. Options are:

| Name | Type | Default | Description | | --------- | -------- | ----------- | ----------- | | el | jQuery | $('body') | Container of pages' views. | | start | boolean | true | Start to listen URI changes when initialized (Run Router.start()). | | pushState | boolean | false | Defines which type of routing to use: history.pushState or hash. Will be transmitted to Backbone.history.start(). | | silent | boolean | false | Tells router not to navigate (in case if page is already rendered). Will be transmitted to Backbone.history.start(). | | root | string | '/' | Make sense only if pushState=true Will be transmitted to Backbone.history.start(). | | pages | Object[] | [] | Initial array of pages. |

var Router = Viewport.Router.extend({
    // extend default router by routes and methods...
});

var router = new Router({
    el: $('#viewport'),
    pushState: true,
    root: '/path/custom/'
});
.start([options])

Run Backbone.history.start() with pushState, root and silent provided in constructor and overridden by provided directly.

.stop()

Stop watching uri changes (Run Backbone.history.stop()).

.go(attributes[, options])

Read document uri and activate page with given attributes (PlainObject). If page not exists in collection, it will be created with given attributes, and added to collection. URI is generated automatically:

  • If pushState=true: full URI of document
  • If pushState=false: hash part of URI

If page has been already added in collection, it will be just shown, none of attributes will be updated and view will not be re-rendered.

Options are:

| Name | Type | Default | Description | | ----- | ------- | ------- | ----------- | | force | boolean | false | Update properties of model and make it re-render its view if page is already exists. | | load | boolean | false | (For pushState:true) Make request to server with url=page's uri (run Viewport.Model.fetch()), update model with received data |

Viewport.Router.go() is not supposed to be used anywhere except for Router's actions.

.navigate(fragment[, options])

Backbone.Router.navigate inherited from Backbone.Router. Use it in code to navigate to some page:

router.navigate("product/1", {
    trigger: true
});

Extending classes

Viewport classes are unsuitable for end use and must be extended. At least, .template() must be provided for Viewport.View:

var View = Viewport.View.extend({
    className: 'my-page-class',
    template: function(data) {
        return _.template('<h1>Page title: <%= title %><h1> ...content... ', data);
    }
});

Viewport.Collection must be extended to use View (also provide model if extended):

var Collection = Viewport.Collection.extend({
    view: View
});

Router must be extended to use Collection and set routes and handlers. Refer Backbone.Router.routes for routing syntax.

var Router = Viewport.Router.extend({
    collection: Collection,
    routes: {
        '': 'home',
        'discovery': 'discovery',
        'product/:name': 'product'
    },
    home: function() {
        this.go({ title: 'Home &ndash; My SPA' });
    },
    discovery: function() {
        this.go({ title: 'Discovery &ndash; My SPA' });
    }
    product: function(name) {
        this.go({ title: name + ' &ndash; My SPA', productName: name });
    }
});

Now application classes are ready to use, but it is not started yet. To start the application, create instance of extended Router:

var router = new Router({
    // options
});

Refer Router.initialize() for options.

Routing process

When Router is initialized, or when URI is changed, Router begin to look for matching routes through routes property and if found, runs route's action. In an action, you can analyze route params, and maybe load some data from server to get some data required by page. this in actions points to current router, so this.go() can be called to open a page with its attributes and data.

Viewport considers each page as unique for different uri. But it may be useful to have one page for many uris, e.g one homepage for / and /#!/. To make it, provide uri manually when go to a page:

var Router = Viewport.Router.extend({
    // ...
    routes: {
        '': 'home',
        '#!/': 'home'
        // other routes
    },
    home: function() {
        this.go({
            uri: '/'
            // page properties
        });
    }
    // other actions
});

Handling hyperlinks

Viewport does not handle any events on hyperlinks. They must be handled manually. Possible example:

// Ensure router is instance of Viewport.Router
$(document).on('click', 'a.spa-link', function(e) {
    if (!e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
        e.preventDefault();

        var url = $(this).attr("href").replace(/^\//,'').replace('\#\!\/','');

        router.navigate(url, {
            trigger: true
        });

        return false;
    }
});

In this example, all hyperlinks with spa-link class will be handled to use Viewport router instead of common behavior.

Updating title

Viewport does not update browser page's title automatically. Page title can be changed on Page shown event:

var Page = Viewport.Model.extend({
    initialize: function() {
        this.on("shown", function() {
            $("title").html(this.get("title"));
        });
    }
});