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

spapp

v1.0.0

Published

c-smile's minimal spa router

Downloads

3

Readme

SPApp

Single Page Application Micro Framework

Supports views, controllers and routing in 60 lines of code!

Introduction

If you heard anything about MVC in web applications, in particular words like "views", "controllers", "routing" and don't feel that you need more than jQuery in your project then this small library is for you.

Structure of your SPApp

Let's consider structure of simple "contact list" web application:

<script type="text/javascript" src="spapp.js"></script>
<body>

  <nav>
    <a href="#contact-list">Contacts</a>
    <a href="#about">About</a>
  </nav>
  
  <section id="contact-list" src="pages/contact-list.htm" default></section>
  <section id="contact-details" src="pages/contact-details.htm"></section>
  <section id="about" src="pages/about.htm"></section>

</body>

We have <nav>igation section here and collection of <section>s - views that need to be presented when user clicks on one of hyperlinks in the nav bar (or anywhere else). Also, if you want to load a section by default, simply add the default attribute.

Routing

By definig <section id="some id"> element in your markup you actually define a route. When browser is navigated to {url of your app}#id-of-section the SPApp module catches this event and shows <section> with that ID.

No special mechanism for declaring routes is required - simply declare <section>s with proper IDs.

Views and Controllers

Notice that each <section> above has src={url} attribute declared. That URL points to partial HTML fragment that defines content of the view and its controller function.

Typical structure of a view looks like this:

  <h2>Contact Details</h2>

  <label>First name</label> <input name="firstName">
  <label>Last name</label> <input name="lastName">
  ... 

<script>
//|
//| view controller
//|
//| Note the name below shall match id of the section
//|
  window.app.page("contact-details", function() // registering the controller
  {
    // initialize view variables in localscope
    
    var $firstName = $(this).find('[name="firstName"]');
    var $lastName = $(this).find('[name="lastName"]');
    ...
    
    // presenter of the view - load data and show: 
    return function(params) {
      var contactId = params; 
      contact = contacts[contactId];
      // show values 
      $firstName.val(contact.firstName);
      $lastName.val(contact.lastName);
      ...
      
    }
  }); 
</script>

As you see markup above contains two sections:

  1. html markup of the view per se and
  2. script block with app.page("{name}",scopeInitializerAndController ) function.

The scopeInitializerAndController function above serves two tasks:

  1. initilizes the view and its scope variables and

  2. returns function (a.k.a. "controller"). That function will be called each time the view needs to be presented/rendered.

Switching views and passing parameters

The application can be switched to show different views in one of these ways:

  1. By user navigating browser to {your app url}#name-of-the-view:optional-parameter;
  2. By user clicking on <a href="#name-of-the-view:optional-parameter"> hyperlinks on app page;
  3. By code, calling window.app("name-of-the-view", parameters) function.

In all cases the SPApp framework will call controller registered for the view passing given parameter to it.

View events

While switching the view the SPAapp will trigger two events:

  1. "page.hidden" with event.target set on <section> to be "closed" and
  2. "page.shown" with event.target set on <section> to be "shown".

So by subscribing on these events any code inside or outside controllers can receive notification about application state change.

Styling application and view states.

When the application navigates to particular view defined in <section id="view-a"> it is said that it is in "view-a" state. SPApp marks this state by assigning "view-a" class to the <body> element in your document. Having this you can define view visibility rules in your CSS:

/* all sections are off by default */
body > section { display:none; }
/* app state -> view visibility rules: */
body.view-a > section#view-a,
body.view-b > section#view-b,
body.view-c > section#view-c  { display:block; }

Note that switching the view into different states may require not only to hide/show some sections but also to style some other indicators like nav-bar items highlighting:

/* nav highlightion rules */
body.view-a > nav > a[href="#view-a"],
body.view-b > nav > a[href="#view-b"],
body.view-c > nav > a[href="#view-c"] { background:white; color:black; }

Wrapping up

It is not strictly required for controller's code to be placed inside the view markup, you can put them in separate script files and include as any other scripts:

<script type="text/javascript" src="controller-a.js"></script>
<script type="text/javascript" src="controller-b.js"></script>
...

The only thing that required is that scopeInitializerAndControoler function must be registered by calling

window.app.page("view-a", function() // registering the controller
  {
    ... initialization ...
    return function(params) {
      ... presentation ...
    }
  });

In the same way markup for views can be provided inline without use of external files:

  <section id="view-a" >
    ... markup of view-a ...
  </section>
  <section id="view-b" >
    ... markup of view-b ...
  </section>

#Live Demo

Check this SPApp in action demo. I've created it in explicitly simple and minimalistic fashion in order to highlight just SPAapp. I have projects where it works in Twitter Bootstrap environment for example.