alt-seven, the client-side JavaScript framework
This is the multi-page printable view of this section. Click here to print.
Documentation
- 1: Overview
- 2: Getting Started
- 2.1: Simple Example
- 3: Concepts
- 4: Core Tasks
- 4.1: User Authentication
- 5: Tutorials
- 5.1: Authentication
- 5.2: Configuring Your Application
- 6: Reference
- 6.1: API Reference
- 7: Contribution Guidelines
- 8: Examples
1 - Overview
This page provides a brief overview of the alt-seven framework, how it came about, and why you might want to use it.
Just what is alt-seven?
In short, alt-seven is a reactive JavaScript framework intended for building single page applications (SPA). Alt-seven attempts to simplify SPA JavaScript development by relying on core JavaScript language constructs like Template Literals for templating rather than extensions like JSX that require transpiling prior to deployment. Alt-seven has no external code dependencies, though it does offer integration with different third party libraries, and contains hooks to allow you to intgrate others in certain places. Because there is no parsing/transpiling/packaging step in alt-seven development, there is no tree shaking at this point.
How was alt-seven created?
The framework started as an exploration in reactive JavaScript development to see if it was possible to build a reactive framework for SPAs using Template Literals for templating simple, core JavaScript language, and without a build process as a necessary step for deployment. After proving those concepts, the author built the core of the framework and created some simple applications to show it off.
Why would I want it?
If you are looking for a reactive JavaScript framework for a single page application project, you should give alt-seven a look. If you are learning about JavaScript-based Web application development, you should also give alt-seven a look, as it demonstrates a lot of concepts in modern JavaScript.
-
What is it good for?: Alt-seven provides an easy way to build reactive applications in JavaScript without having to concern yourself with a lot of the details of reactive development. Some useful features:
- remote package that provides an easy way to communicate with a back-end server via JSON
- model for storing data
- authentication mechanism with some back-end code examples to use for different back-ends, including Node.JS
- logging system with multiple log levels
- in-browser console that allows you to see log messages in the browser in real-time ( this is really useful for integrating back-end logging in real-time so you can see back-end log messages in the browser )
- error capture
- application router
- simple custom event binding for components
- publish/subscribe event model
-
What is it not good for?: If you are looking for a framework that compiles, packages, and obfuscates your application code, that’s not alt-seven.
-
What is it not yet good for?: Alt-seven has not yet been used to build a large scale deployed application, so if you are looking for a framework that is already been proved in large scale deployments, you will need to look to other frameworks like React.JS and Vue.JS.
Where should I go next?
- Getting Started: Get started with alt-seven.
- Examples: Check out some example code!
2 - Getting Started
This page covers your first steps with the alt-seven framework.
Prerequisites
Alt-seven is a client-side JavaScript framework. It runs in the context of a web browser, and typically- though not necessarily- runs on the Internet in the context of a web application served by a web server such as NGINX, IIS, or Apache Web Server.
Installation
The simplest method to install alt-seven is via npm.
$ npm install alt-seven
You can also download alt-seven from GitHub:
https://github.com/shoestringlab/altseven
Setup
Depending on how you installed alt-seven, you will need to reference it from your root HTML file in your project.
-
If you installed via npm, the framework will be located at: node_modules/altseven from the project root.
-
If you downloaded via git clone, the framework will be located in the /dist folder of the cloned alt-seven project.
-
If you downloaded an archive from GitHub, the framework will be located in the /dist folder inside the archive.
In the case of downloading via npm, you may want to create an alias that you use to reference the location of altseven.
For example, in a Node.js application using Express, you may set up a client-side reference like so:
`app.use( "/lib/altseven", express.static( 'node_modules/altseven' ) );`
Try it out!
2.1 - Simple Example
This page shows code for a very simple alt-seven application.
index.html
<!doctype html>
<html>
<head>
<title>alt-7 example</title>
<script type="module">
import {application} from './app.js';
var app = application();
</script>
</head>
<body>
<div name="main">
</div>
</body>
</html>
app.js
import {a7} from '/dist/a7.js';
var app = {
main: (function() {
return {
init: function(state) {
// render the hello page
app.components.Hello( { id: 'hello', selector: "div[name='main']" } );
}
};
})(),
components: (function() {
function Hello(props) {
var hello = a7.components.Constructor(a7.components.View, [props], true);
hello.state = {
text: " World!"
};
hello.template = function(){
return `<h3>Hello ${hello.state.text}</h3>`;
};
return hello;
}
return {
Hello: Hello
};
})()
};
export var application = function init() {
var options = {};
var p = new Promise(function(resolve, reject) {
a7.init(options, resolve, reject);
});
p.then(function(state) {
app.main.init();
a7.log.info("App init.");
});
p['catch'](function(message) {
console.log(message);
});
return app;
};
3 - Concepts
This page shares some underlying concepts about how alt-seven works.
ES Modules
Alt-seven uses the ECMAScript standard for module imports. Familiarize yourself with how to structure individual modules for export and how to import them into another module.
Configuration Options
Alt-seven offers many application level configuration options that are specified when the application is initialized. As you can see in the simple example, no options are required, so you can pass options = {};
, or you can specify any number of options on initialization that affects how the application functions.
Template Literals
Template literals are a key concept in ES6 for building web applications. They are string literals delimited by backticks (`) that allow you to create multi-line templates. See the documentation on template literals at the Mozilla Developer Network.
Template literals allow a developer to build complex HTML displays without resorting to third-party extensions like JSX. One of the initial questions during the development of alt-seven was whether event attributes could be embedded in the template literals and become part of the active application. The answer was that event attributes would not generate event listeners, so something else needed to be done, and that something is to use the data- attribute notation to add event attributes that can be parsed and used to generate event listeners once the HTML is generated.
In the example below, alt-seven sees the data-onclick attributes, parses them, and adds event listeners for them. In this case, the view component is called gallery and it has a section called gallery.eventHandlers that contains the event handlers listed in the template literal. In this way, the developer can specify dynamic interactivity that happens as HTML is generated on the fly in the application.
Note that for the sake of legacy application porting, alt-seven also include support for Mustache and Handlebars as templating libraries.
`
<div>
<img id="galleryImage" data-zoomable="true" src="/assets/img/` + state.images[state.currentIndex] + `">
</div>
<div id="galleryNavBar" class="slidecontainer,inline">
<input type="range" min="0" max="` + (state.images.length - 1) + `"
value="` + state.currentIndex + `" class="slider" id="gallerySlider" data-onchange="changeImage">
</div>
<div class="galleryNav">
<span data-onclick="decrementIndex"><i data-feather="arrow-left"></i></span>
` + (parseInt( state.currentIndex, 10 ) + 1 ) + ` of ` + state.images.length + `
<span data-onclick="incrementIndex"><i data-feather="arrow-right"></i></span>
</div>
`
gallery.eventHandlers = {
changeImage: function( event ){
gallery.setState( Object.assign( gallery.getState(), { currentIndex: event.target.value }));
},
decrementIndex: function( event, x ){
let value = (x === undefined ? 1 : x );
let state = gallery.getState();
gallery.setState( Object.assign( state, { currentIndex: Math.max( 0, state.currentIndex - value ) } ));
},
incrementIndex: function( event, x ){
let value = (x === undefined ? 1 : x );
let state = gallery.getState();
gallery.setState( Object.assign( state, { currentIndex: Math.min( state.images.length-1, state.currentIndex + value ) } ));
}
};
Events
Alt-seven uses events to control program flow. Naming of events is left up to the programmer, but a standard convention is to organize events by area of the application. For example, all events related to users might be contained inside the “user.” space. In a given view, clicking links may call events that then call other components to carry out the intended actions.
a7.events.subscribe( "user.confirm", function( obj ){
// code to confirm the user account
});
a7.events.subscribe( "user.profile", function( obj ){
// code to retrieve and display the user profile
});
// called in a view
a7.events.publish( "user.profile", { userID: user.userID } );
URL Routes
Alt-seven includes a URL router to allow bookmarking and browser history inside your application. Routes are mapped to events and can be specified in a single file.
Here is an example of route mapping:
export var routes = [
[ '/comment/showform', 'comment.showForm' ],
[ '/', 'main.home' ]
];
Routes can then be called from anywhere in the application. Routes may also pass an arbitrary data structure as parameters to be passed to the event mapped to the route.
// simple opening of a route
a7.router.open( "/" );
// pass a parameter to the event
a7.router.open( "/comment/showForm", { message: "Say something..." });
4 - Core Tasks
This page shows some core tasks that you can tackle using alt-seven.
4.1 - User Authentication
User Authentication
Alt-seven includes a built-in authentication mechanism that allows you to authenticate users against your back end server. Rather than using a custom authentication system, alt-seven uses HTTP Basic Authentication, sending an Authorization header with encoded username and password to the server via remote fetch. The framework sends back an X-Token response header that contains an encoded payload with the authenticated user’s information.
Because the authentication methods are included in the framework, all the programmer needs to do is configure the loginURL, logoutURL, and refreshURL in the application configuration, then call the auth.login event in the framework. The method then calls the specified loginURL and passes the username and password to the authentication URL. See more information in the authentication tutorial.
5 - Tutorials
This is a placeholder page that shows you how to use this template site.
Tutorials are complete worked examples made up of multiple tasks that guide the user through a relatively simple but realistic scenario: building an application that uses some of your project’s features, for example. If you have already created some Examples for your project you can base Tutorials on them. This section is optional. However, remember that although you may not need this section at first, having tutorials can be useful to help your users engage with your example code, especially if there are aspects that need more explanation than you can easily provide in code comments.
5.1 - Authentication
alt-seven authentication tutorial
In order to enable built-in authentication, you must configure your application with the correct options. Here is a sample of the authentication options to be passed to the framework:
remote: {
modules: app.remote,
loginURL: "/api/auth/login",
logoutURL: "/api/auth/logout",
refreshURL: "api/auth/refresh"
},
In addition to the authentication methods, the a7 model must be enabled for authentication to work. See the page on configuring your application to understand all the options available to you.
In the login form, the programmer can then specify success and failure parameters, which can be methods, event names, or router destinations. In the below example, the loginform sends the username and password and then specifies success and failure methods to run after the authentication method returns from the server.
handleClick: function(event) {
let state = loginform.getState();
loginform.showMessage("");
a7.events.publish('auth.login', {
username: loginform.state.username,
password: loginform.state.password,
success: function( json ){
main.runApp();
},
failure: function( json ){
state.message = json.message;
state.username = "";
state.password = "";
loginform.setState( state );
loginform.fireEvent("mustRender");
}
});
}
Success and failure could also be specified as events, such as:
success: "auth.loginSuccess",
failure: "auth.loginFailure"
or as router destinations:
success: "auth/loginSuccess",
failure: "auth/loginFailure"
The programmer must then create the events or router destinations named:
a7.events.subscribe( "auth.loginSuccess", function( obj ){
// handle login success tasks
});
Note that routes are simply URL destinations that are mapped to events. The purpose of routes is to give the user a URL in the browser’s location bar.
Routes mapped in an application may look like this:
export var routes = [
[ '/auth/loginSuccess', 'auth.loginSuccess' ],
[ '/', 'main.home' ]
];
If routes are enabled in the application, the strings will be assumed to be route destinations, otherwise they will be treated as events.
5.2 - Configuring Your Application
alt-seven configuration options tutorial
You configure your alt-seven application by passing an options structure to the a7.init method. There are a host of options that you can tailor to your needs.
The structure accepts these configuration options, listed with their data types and default values:
-
auth
- sessionTimeout (milliseconds)
-
console
-
enabled (boolean, false)
-
wsServer (host, “”)
-
container (object, “”)
-
top (integer, 100)
-
left (integer, 500)
-
width (integer, 500)
-
height (integer, 300)
-
logging
- logLevel (list (“ERROR,FATAL,INFO,TRACE,WARN”), “ERROR,FATAL,INFO”)
- toBrowserConsole (boolean, false)
-
-
model (object, a7.model)
-
remote
- modules ( structure, {})
-
router
- useEvents (boolean, true)
- routes ( object, undefined)
-
ui
- renderer (string (Mustache, Handlebars, templateLiterals), templateLiterals )
- timeout (milliseconds, 600000)
All options have a default value, so in the simplest example, you can call a7.init( {} );
.
6 - Reference
This is a placeholder page that shows you how to use this template site.
If your project has an API, configuration, or other reference - anything that users need to look up that’s at an even lower level than a single task - put (or link to it) here. You can serve and link to generated reference docs created using Doxygen,
Javadoc, or other doc generation tools by putting them in your static/
directory. Find out more in Adding static content. For OpenAPI reference, Docsy also provides a Swagger UI layout and shortcode that renders Swagger UI using any OpenAPI YAML or JSON file as source.
6.1 - API Reference
The API reference details the methods available in the alt-seven framework.
Modules
-
a7
- init( options )
-
a7.components
-
a7.components.model
- The built-in model of the alt-seven framework. The a7.model component uses this model object by default to implement the model functionality of the application.
-
a7.components.User
- User is a generic object with no pre-set properties to be used to hold arbitrary properties set by the authentitcation endpoint of the program and returned during the authentication routine.
methods - getMemento - Returns whatever arbitrary properties have been set by the application.
-
a7.components.View The View component is the base component for all views in alt-seven applications. A view is created using the Constructor component, which allows event bindings of the object level events in the View component to be added to the new view.
properties - template - Each view must have a template property that must return a string representation of the HTML for the view. The template property may be a string or a function that returns a string so that views can be dynamically rendered. - skipRender - boolean - Determines whether a view should be rendered.
methods
- config()
- getState()
- Returns a structure of the current state of the view.
- setState( args )
- Sets the args structure as the current state of the view.
- addChild( view )
- Adds another view as a child of the current view.
- removeChild( view )
- Removes a view from the stack of child views of the current view.
- clearChildren()
- Removes all child views of the current view.
- render()
- Renders the current view. Render returns an HTML string representing the current view. The method may contain template literal or a function that produces an HTML string.
- getParent()
- Returns the parent view of the current view.
- shouldRender()
- Returns a boolean value whether the current view should be rendered based on whether skipRender is set to true or false.
- onRendered()
- Renders the child views of the current view after the current view is rendered. Called automatically by the framework.
- checkRenderStatus()
- First checks if the document node specified by the view’s selector property exists. If the node does not exist, it unregisters the view from the application.
- Checks the isTransient property of the view. If it is set to true, the component sets a timer and calls itself until the application timeout value is reached.
-
-
a7.console
- init( options )
- addMessage ( message (""), date (new Date()), source (“local|websocket”), level (ERROR,FATAL,INFO,TRACE,WARN) )
- Sends a message to the console. This method is called by a7.log when logging is enabled and the console is enabled. All logged messages are posted to the console.
-
a7.error
- init()
- captureError (msg, url, lineNo, columnNo, error)
- This method is called when there are runtime errors in the application.
-
a7.events
- init()
- publish ( topic, info )
- This method calls an event and passes the info object to the event.
- subscribe( topic, listener )
- Creates an event listener in the application for the topic, and specifies the listener object used to handle the event when an event is published.
-
a7.log
-
init()
-
error( message )
- Logs an error-level message.
-
fatal( message )
- Logs a fatal-level message.
-
info( message )
- Logs an info-level message.
-
trace( message )
- Logs a trace-level message.
-
warn( message )
-
Logs a warn-level message.
-
All of these methods log the passed message according to the level of the logged message.
-
-
-
a7.model
- This component implements the model funcitonality of the framework, which is used to store instantiated views and other arbitrary data by the application. By default, the framework uses the a7.components.model object to implement this functionality, but the application may specify any JavaScript object as the model for the applicatiion as long as it implements the spcified methods of the a7.model component.
methods
- init( options )
- destroy( key )
- Deletes the key from the model.
- get( key )
- Retreives the value in the model by key.
- set( key, value )
- Sets the value in the model by key,
- exists( key )
- Checks whether the key existing in the model.
-
a7.remote
methods
-
init( modules )
-
fetch( uri, params, secure)
- Handles a remote HTTP call to the specified uri. Returns a promise.
-
invoke( moduleAction, params)
- Calls the specified action in the specified modules, passing params as an argument, in the format invoke( module.action, params ).
-
getToken
- Returns the session token for the current user.
-
invalidateToken
- Removes the session token for the current user.
-
getSessionTimer
- Returns the timer object set by the SetTimeout() function that tracks the current user session.
-
webSocket( wsServer, messageHandler, isJSON )
- Creates a websocket connection to the specified wsServer and passes messages to the messageHandler function.
auth - login(params) - Calls a server-side authentication endpoint specified in the application config. - logout(params) - Calls a server-side logout endpoint specified in the application config. - refresh(params) - Calls a server-side endpoint specified in the application config to keep the current user session alive.
-
-
a7.router
- init(options)
- Called by the framework to initialize the router if enabled.
- open(path, params)
- Opens the specified path and publishes the mapped event with the params.
- add(path, handler)
- Creates a new route path and maps the handler to it.
- find(path)
- Returns a route map by path.
- match(path)
- Checks whether the specified path is mapped in the routes.
- init(options)
-
a7.security
- init()
- Called by the framework to initialize the security module.
- invalidateSession()
- Ends the current session and sets a blank User object in the model as the current system user.
- isAuthenticated()
- Checks whether the current user is authenticated.
- init()
-
a7.ui properties
- selectors
- The collection of document selectors set by the application.
- views
- The collection of View objects set by the application. methods
- init()
- Called by the framework to initialize the ui module.
- getEvents()
- Gets all of the browser events listed in the UI module.
- getSelector(name)
- Returns a specified selector by name.
- setSelector(name, selector)
- Sets a specified selector by name.
- getNode(selector)
- Gets a node in the DOM by selector.
- register(view)
- Registers the specified view in the application.
- unregister(id)
- Unregisters the view.
- getView(id)
- Returns a view by its ID.
- enqueueForRender(id)
- Adds the view to the render queue by ID.
- removeView(id)
- Removes the view from the application by ID.
- selectors
-
a7.util
- split (val)
- Split the val by commas
- extractLast(term)
- Get the last term from a comma-separated list
- encode64(input)
- decode64(input)
- leadingZero(n)
- dynamicSort( property )
- yesNo( val )
- isValidDate( d )
- id()
- tryCatch(fn,ctx,args)
- getNumberValue(value)
- isNumeric(num)
- getOffset(selector)
- split (val)
7 - Contribution Guidelines
8 - Examples
Some examples of alt-seven in action.
LacesIDE is an open source JavaScript editor and sandbox environment that you can install and run locally or on your own public server. It was built using a slightly older version of alt-seven, but it demonstrates the features of the framework quite well. The whole thing is less than five thousand line of code, small enough to review the whole thing, but big enough to give you a good idea of how you can organize an alt-seven application.