g1
is a micro-framework collection that makes it easy to write front-end data
applications. It’s a humble alternative to Vue.js,
AngularJS and React.
It not a framework – more a collection of tools that work together. Sort of like UNIX.
If you need a library to build data applications without a learning curve and low overhead, g1 may be for you.
You can add g1 and its dependencies with a single script tag:
<script src="https://cdn.jsdelivr.net/combine/npm/jquery,npm/lodash,npm/g1"></script>
or install it using:
yarn install jquery lodash g1
# ... OR ...
npm install jquery lodash g1
… and add this to your HTML file:
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/lodash/lodash.min.js"></script>
<script src="node_modules/g1/dist/g1.min.js"></script>
You can create dynamic content from data using templates. To create a template:
<template>..</template>
.<% .. %>
in the templateThis renders your template with your data. For example:
<template class="sample">
<% list.forEach(function(item) { %>
<div>item <%= item %></div>
<% }) %>
</template>
<script>
$("template.sample").template({ list: [1, 2, 3] });
</script>
Templates use lodash, which is plain HTML and JavaScript. You don’t need to learn a new template language.
<% ... %>
is executed as Javascript.<%= ... %>
is evaluated and displayed..template()
again with different data.TODO: show a full-blown example of this.
Apps shows different content based on what the user requests. A good way to capture this is to store the requests in the URL. This lets the user bookmark the page and share the URL. This URL represents the state of the app.
For example, /view=sales&year=2019
may show the sales in year 2019.
To parse a URL, use g1.url.parse:
var url = g1.url.parse(location.href);
url.searchKey == { view: "sales", year: "2019" };
This can affect what template to render, and what data to render. For example:
<template class="sales">Sales was <%- data %> in <%- q.year %>.</template>
<template class="profit">Profit was <%- data %> in <%- q.year %>.</template>
<script>
var data = {
sales: { 2018: 250, 2019: 260 },
profit: { 2018: 50, 2019: 60 },
};
var q = g1.url.parse(location.href).searchKey;
$("template." + q.view).template({ data: data[q.view][q.year], q: q });
</script>
When the URL is ?view=sales&year=2019
, it renders “Sales was 260 in 2019.”
When the URL is ?view=profit&year=2018
, it renders “Profit was 50 in 2018.”
TODO: show a full-blown example of this.
To change the state, we change the query. For example:
?view=sales&year=2018
changes year to become…?view=sales&year=2019
We can do this using <a href="?view=sales&year=2019">
. But we usually change
only some of the keys at a time (e.g. change year to 2019 without changing
view
.)
$().urlfilter() makes this easier.
<a class="urlfilter" href="?year=2019">
changes just the year to 2019, and
keeps other keys constant.
<ul>
<li>
<a class="urlfilter" href="?view=sales">Set ?view=sales, keep the rest</a>
</li>
<li>
<a class="urlfilter" href="?view=profit">Set ?view=profit, keep the rest</a>
</li>
<li>
<a class="urlfilter" href="?year=2018">Set ?year=2018, keep the rest</a>
</li>
</ul>
<script>
$("body").urlfilter(); // activates URL filtering on the entire page
</script>
TODO: show a full-blown example of this.
Changing the URL reloads the page. To build single page apps that don’t reload,
you can store the state in the location hash, like /#?view=sales&year=2019
.
To make $().urlfilter() update the hash (instead of the query),
use $('body').urlfilter({target: '#'})
.
To listen to hash change events, use $(window).urlchange(). For example:
$(window)
.on("#?view", function (e, view) {
console.log("view is", view);
})
.on("#?year", function (e, year) {
console.log("year is", year);
})
.on("#", function (e, url) {
console.log("hash is", url);
});
TODO: show a full-blown example of this.
Normally, re-rendering a template deletes the content and re-creates the DOM
elements. But if you use <template data-engine="vdom">
, it only updates
changed elements. This has 3 advantages:
TODO: show a full-blown example of this.
You can import either g1.min.js – which has all of these functions – or one of the individual libraries below:
mapviewer.min.js is not part of g1.min.js.
For debugging, use dist/g1.js – an un-minified version.