Page 1

tn btn-default”>Add</button> </form> main.addContestant = function () { ContestantsService.addContestant(angular.copy(main.newContestant)); main.newContesta ’, name: ‘’, score: ‘’}; }; service.addContestant = function (contestant) { contestant.id = new Date().getTime(); contestants.push(contestant); }; <td>{{contestant.lane}} <input type=”text” ng-model=”contestant.lane” ng-blur=”main.updateContestant(contestant)”/></td> main.updateContestant = function (contestant) { ContestantsServic ontestant(contestant); }; service.updateContestant = function (contestant) { // Already in memory }; <button type=”button” class=”btn btn-link” ng-click=”mai Contestant(contestant)”>Remove</button> main.removeContestant = function (contestant) { ContestantsService.removeContestant(contestant); }; servic Contestant = function (contestant) {contestants.remove(function(c) { // Sugar.js method call return c.id === contestant.id; }); }; <script src=”//cdn.firebase.com/j 4.2/firebase.js”></script> <script src=”//cdn.firebase.com/libs/angularfire/1.2.0/angularfire.min.js”></script> var app = angular.module(‘leaderboard’, [‘firebase’]); ap (‘FIREBASE_URI’, ‘PUT_YOUR_FIREBASE_HERE’); app.factory(‘ContestantsService’, function ($firebase, FIREBASE_URI) var ref = new Firebase(FIREBASE ar contestants = $firebase(ref).$asArray(); service.getContestants = function () { return contestants; }; service.addContestant = function (contestant) nts.$add(contestant); }; service.updateContestant = function (contestant) { contestants.$save(contestant); }; service.removeContestant = function (contestant) nts.$remove(contestant); }; app.service(‘ContestantsService’, function () { var service = this; var contestants = [ {id: 1, lane: 1, name: ‘Contestant 01’, score: ‘10’}, {i 2, name: ‘Contestant 02’, score: ‘15’}, {id: 3, lane: 3, name: ‘Contestant 03’, score: ‘20’} ]; service.getContestants = function () { return contestants; }; }); // We are usin rollerAs syntax app.controller(‘MainCtrl’, function (ContestantsService) { var main = this; main.newContestant = {lane: ‘’, name: ‘’, score: ‘’}; main.contestants antsService.getContestants(); }); <tr ng-repeat=”contestant in main.contestants”> <td>{{contestant.lane}}</td> <td>{{contestant.name}}</td> <td>{{contestant.score}} > <form class=”form-inline” role=”form” novalidate ng-submit=”main.addContestant()”> <div class=”form-group”> <input type=”text” class=”form-contro el=”main.newContestant.lane” placeholder=”Enter lane”> </div> <!-- The rest of the form --> <button type=”submit” class=”btn btn-default”>Add</button> </form dContestant = function () { ContestantsService.addContestant(angular.copy(main.newContestant)); main.newContestant = {lane: ‘’, name: ‘’, score: ‘’}; }; servic estant = function (contestant) { contestant.id = new Date().getTime(); contestants.push(contestant); }; <td>{{contestant.lane}}</td> <td><input type=”tex el=”contestant.lane” ng-blur=”main.updateContestant(contestant)”/></td> main.updateContestant = function (contestant) { ContestantsServic ontestant(contestant); }; service.updateContestant = function (contestant) { // Already in memory }; <button type=”button” class=”btn btn-link”ng-click=”mai Contestant(contestant)”>Remove</button>main.removeContestant = function (contestant) {ContestantsService.removeContestant(contestant); }; servic Contestant = function (contestant) { contestants.remove(function(c) { // Sugar.js method call return c.id === contestant.id; }); }; <script src=”//cdn.firebase.com/j 4.2/firebase.js”></script> <script src=”//cdn.firebase.com/libs/angularfire/1.2.0/angularfire.min.js”></script> var app = angular.module(‘leaderboard’, [‘firebase’]); ap (‘FIREBASE_URI’, ‘PUT_YOUR_FIREBASE_HERE’); app.factory(‘ContestantsService’, function ($firebase, FIREBASE_URI) var ref = new Firebase(FIREBASE ar contestants = $firebase(ref).$asArray(); service.getContestants = function () {return contestants; }; service.addContestant = function (contestant) nts.$add(contestant); }; service.updateContestant = function (contestant) { contestants.$save(contestant); }; service.removeContestant = function (contestant) nts.$remove(contestant); }; app.service(‘ContestantsService’, function () { var service = this; var contestants = [ {id: 1, lane: 1, name: ‘Contestant 01’, score: ‘10’}, {id: name: ‘Contestant 02’, score: ‘15’}, {id: 3, lane: 3, name: ‘Contestant 03’, score: ‘20’} ]; service.getContestants = function () { return contestants; }; }); // We are using th rAs syntax app.controller(‘MainCtrl’, function (ContestantsService) { var main = this; main.newContestant = {lane: ‘’, name: ‘’, score: ‘’}; main.contestants antsService.getContestants(); }); <tr ng-repeat=”contestant in main.contestants”> <td>{{contestant.lane}}</td> <td>{{contestant.name}}</td> <td>{{contestant.score}} > <form class=”form-inline” role=”form” novalidate ng-submit=”main.addContestant()”> <div class=”form-group”> <input type=”text” class=”form-contro el=”main.newContestant.lane” placeholder=”Enter lane”> </div> <!-- The rest of the form --> <button type=”submit” class=”btn btn-default”>Add</button> </form dContestant = function () { ContestantsService.addContestant(angular.copy(main.newContestant)); main.newContestant = {lane: ‘’, name: ‘’, score: ‘’}; }; servic estant = function (contestant) { contestant.id = new Date().getTime(); contestants.push(contestant); }; <td>{{contestant.lane}}</td> <td><input type=”tex el=”contestant.lane”ng-blur=”main.updateContestant(contestant)”/></td> main.updateContestant = function (contestant) { ContestantsServic ontestant(contestant); }; service.updateContestant = function (contestant) { // Already in memory }; <button type=”button” class=”btn btn-link”ng-click=”mai Contestant(contestant)”>Remove</button> main.removeContestant = function (contestant) { ContestantsService.removeContestant(contestant); }; servic Contestant = function (contestant) { contestants.remove(function(c) { // Sugar.js method call return c.id === contestant.id; }); }; <script src=”//cdn.firebase.com/j 4.2/firebase.js”></script> <script src=”//cdn.firebase.com/libs/angularfire/1.2.0/angularfire.min.js”></script> var app = angular.module(‘leaderboard’, [‘firebase’]); ap (‘FIREBASE_URI’, ‘PUT_YOUR_FIREBASE_HERE’); app.factory(‘ContestantsService’, function ($firebase, FIREBASE_URI) var ref = new Firebase(FIREBASE ar contestants = $firebase(ref).$asArray(); service.getContestants = function () { return contestants; }; service.addContestant = function (contestant) nts.$add(contestant); }; service.updateContestant = function (contestant) { contestants.$save(contestant); }; service.removeContestant = function (contestant) nts.$remove(contestant); }; app.service(‘ContestantsService’, function () {var service = this; var contestants = [ {id: 1, lane: 1, name: ‘Contestant 01’, score: ‘10’}, {i 2, name: ‘Contestant 02’, score: ‘15’}, {id: 3, lane: 3, name: ‘Contestant 03’, score: ‘20’} ]; service.getContestants = function () { return contestants; }; }); // We are usin rollerAs syntax app.controller(‘MainCtrl’, function (ContestantsService) { var main = this; main.newContestant = {lane: ‘’, name: ‘’, score: ‘’}; main.contestants antsService.getContestants(); }); <tr ng-repeat=”contestant in main.contestants”> <td>{{contestant.lane}}</td> <td>{{contestant.name}}</td> <td>{{contestan td> </tr> <form class=”form-inline” role=”form” novalidate ng-submit=”main.addContestant()”> <div class=”form-group”> <input type=”text” class=”form-contro el=”main.newContestant.lane” placeholder=”Enter lane”> </div> <!-- The rest of the form --> <button type=”submit” class=”btn btn-default”>Add</button> </form dContestant = function () { ContestantsService.addContestant(angular.copy(main.newContestant)); main.newContestant = {lane: ‘’, name: ‘’, score: ‘’}; }; servic estant = function (contestant) { contestant.id = new Date().getTime(); contestants.push(contestant); }; <td>{{contestant.lane}}</td> <td><input type=”tex el=”contestant.lane” ng-blur=”main.updateContestant(contestant)”/></td> main.updateContestant = function (contestant) { ContestantsServic ontestant(contestant); }; service.updateContestant = function (contestant) { // Already in memory }; <button type=”button” class=”btn btn-link” ng-click=”mai Contestant(contestant)”>Remove</button> main.removeContestant = function (contestant) { ContestantsService.removeContestant(contestant); }; servic Contestant = function (contestant) { contestants.remove(function(c) { // Sugar.js method call return c.id === contestant.id; }); }; <script src=”//cdn.firebase.com/j 4.2/firebase.js”></script> <script src=”//cdn.firebase.com/libs/angularfire/1.2.0/angularfire.min.js”></script> var app = angular.module(‘leaderboard’, [‘firebase’]); ap (‘FIREBASE_URI’, ‘PUT_YOUR_FIREBASE_HERE’); app.factory(‘ContestantsService’, function ($firebase, FIREBASE_URI) var ref = new Firebase(FIREBASE ar contestants = $firebase(ref).$asArray(); service.getContestants = function () { return contestants; }; service.addContestant = function (contestant) nts.$add(contestant); }; service.updateContestant = function (contestant) { contestants.$save(contestant); }; service.removeContestant = function (contestant) nts.$remove(contestant); };group”> <input type=”text” class=”form-control” ng-model=”main.newContestant.lane” placeholder=”Enter lane”> </div> <!-- The rest --> <button type=”submit” class=”btn btn-default”>Add</button> </form> main.addContestant = function () { ContestantsService.addContestant(angular.copy(mai testant)); main.newContestant = {lane: ‘’, name: ‘’, score: ‘’}; }; service.addContestant = function (contestant) { contestant.id = new Date().getTime(); contestant ntestant); }; <td>{{contestant.lane}}</td> <td><input type=”text” ng-model=”contestant.lane” ng-blur=”main.updateContestant(contestant)”/></td> mai ontestant = function (contestant) { ContestantsService.updateContestant(contestant); }; service.updateContestant = function (contestant) { // Already in memory type=”button” class=”btn btn-link” ng-click=”main.removeContestant(contestant)”>Remove</button> main.removeContestant = function (contestant) antsService.removeContestant(contestant); }; service.removeContestant = function (contestant) {contestants.remove(function(c) { // Sugar.js method call return c.id == nt.id; }); }; <script src=”//cdn.firebase.com/js/client/2.4.2/firebase.js”></script> <script src=”//cdn.firebase.com/libs/angularfire/1.2.0/angularfire.min.js”></script> v ngular.module(‘leaderboard’, [‘firebase’]); app.constant(‘FIREBASE_URI’, ‘PUT_YOUR_FIREBASE_HERE’); app.factory(‘ContestantsService’, function ($firebas SE_URI) var ref = new Firebase(FIREBASE_URI); var contestants = $firebase(ref).$asArray(); service.getContestants = function () { return contestants; }; servic estant = function (contestant) { contestants.$add(contestant); }; service.updateContestant = function (contestant) { contestants.$save(contestant); }; servic

25 practical tutorials! master the world’s most important programming language

• Explore JS frameworks • Dive into VR • Create cutting-edge layouts


contents

JavaScript Guru Guide 4


Contents

Features

Animation

20 JavaScript tips to blow your mind 6

Site animations with scrollmagic

114

Essential Javascript

14

Create Micro-animations

120

Big question

22

Animate a character with CreateJS 126

Introduction to frontend testing

26

integrate photos into video

130

Fighting ebola with JavaScript

32

explore creative code with p5.js

134

Gallery

36

Frameworks

Performance Stop JS files slowing your sites

140

The 5 react mind shifts

46

Explore lazy loading

144

Build a music player with react

50

improve your grunt setup

150

Material Design with Angular 2

54

Head to head: Vue vs React

59

Data Visualisation with Angular

60

Live mockups with Angular

64

Essay: Progressive frameworks

68

Mix Web and native with Astro

70

Real time apps with firebase

76

Native mobile apps

80

VR & Iot 3D scenes with A-frame and vue.js

156

Virtual reality web apps

160

Apps that collect sensor data

166

Immersive Iot experiences

170

Exchange Advice from industry experts

UI & RWD layouts with postCss-flexbox

86

Web apps with container queries 

90

Create a custom user interface

96

D3.js charts with SVG gradients

100

Make your site work on touch

106

JavaScript Guru Guide 5

174


Author

Jack Franklin Jack is a developer at GoCardless, based in London. He writes regularly for the JavaScript Playground (javascriptplayground. com) and is often found playing with the latest library or tool

Illustrator

Linzie Hunter

Linzie is a Scottish illustrator and handlettering artist based in London. Clients include Time magazine, the Guardian, Hallmark, Nike and the BBC linziehunter.co.uk


The top 23 JavaScript libraries every designer and developer needs to know

The ecosystem of JavaScript libraries and tools is growing all the time, and getting to grips with what’s available and what will work for your project can be difficult. In this article I’ve tried to list some of the best tools out there for different use cases and categories to give you a head start. Remember, there’s no real substitute for sitting down and trying out a tool,

and I highly recommend doing that before committing to using a library on a project. Over time you’ll come to establish your favourites and that’s what you should aim for – a selection of libraries you trust and rely on. New toys to play with are great, but there’s nothing better than going back to the ones you are comfortable with.


Big question

JavaScript

Is it ok to build sites that rely on JavaScript? Progressive enhancement raises a lot of strong opinions. We asked the experts if it’s acceptable to build sites that don’t work without JavaScript

H a rr y Rober t s

Nol a n L aw s on

www.csswizardry.com

www.nolanlawson.com

Consultant frontend architect

In a word: No. In many words: Full JS apps are fine provided that a) They have their first render on the server, and b) They give me some content if that JS fails to load. It’s less about availability of JS, and more about not entrusting flaky network connections with delivering our entire app in one render-blocking package. That’s the problem. Don’t make JS your app’s single point of failure.

Eric Me y er

Web design consultant and author www.meyerweb.com

As long as you’re fine with the site completely failing because the browser is too old, or too new, or the user’s bandwidth is too constrained, or the server hiccups, or a firewall’s security policy blocks it, or a dependency goes sideways, or you accidentally drop a semicolon somewhere, then sure, it’s OK. What you build won’t be a part of the web continuum, and it will be needlessly fragile, but that’s a choice you can make.

Performance PM, Microsoft Edge

The question we should be asking ourselves is not how well our sites work without JS, but how well they work under poor or nonexistent network conditions. These concerns are often conflated, but they’re not the same. Every year smartphones represent an increasing share of web traffic, but mobile networks have not caught up. So offline-first – treating the network as an enhancement with JS tools like Service Worker and IndexedDB – has become the new standard for building fast, resilient websites. It is possible to do both traditional progressive enhancement and offline-first, but it’s not easy. We should prioritise offline-first over works-without-JS. JavaScript Guru Guide 22


Big question

L e a V erou

Chris t ia n Heil m a nn Developer evangelist

Computer scientist, web designer and developer

www.christianheilmann.com

lea.verou.me

For web apps (e.g. Google Docs), it’s a loud ‘Yes’, since their functionality cannot be replicated without JavaScript. For content-based websites, it gets a bit trickier. Sure, except for a few weirdos nobody disables JS anymore, and it is technically possible to make an accessible, lightweight site that depends on JS. Also, if there is a JS error anywhere, the content breaks, which is a terrible experience (not concatenating all JS files helps alleviate this a bit). So, I guess my answer is, yes if done really well; no otherwise. Jerem y K ei t h

Web developer and author www.adactio.com

The core functionality of any service on the web should be available to the widest number of people. The best way to ensure this is to use the simplest possible technology for that core functionality. But once you’ve got that in place, you can go absolutely crazy with JavaScript ... including adding more functionality that requires JavaScript to work. I’m reminded of what Mat Marquis said when working on the Boston Globe site: “Lots of cool features on the site don’t work when JavaScript breaks; ‘reading the news’ is not one of them.”

Probably. The question isn’t about JavaScript, the question is about responsibility and power. You can create a solution delivering the most important use case using HTML and CSS and enhance with JavaScript. This could, however, be very basic and not what people expect nowadays. If you rely on JavaScript you have full control, but also full responsibility over the delivery and the error handling. Problems like flaky connections can’t be solved without JavaScript. Our job on the web is to create experiences that are available and great to use. We do this by using all of our tools responsibly.

A a ron Gus ta f s on

Author of Adaptive Web Design www.aaron-gustafson.com

Your project may require client-side JavaScript; I’d argue most don’t. Most can benefit from client-side JavaScript to improve the user experience (including by providing a good offline experience), but creating an experience that benefits from client-side JavaScript is not the same as creating one that requires it. It’s an important distinction that is often overlooked.

Resources Fronteers conf

This Big Question was inspired by a slide in Nolan Lawson’s presentation at Fronteers conference (netm.ag/lawson-288), which caused some controversy around JavaScript usage. In it, Lawson challenged the idea that developers should start with HTML, then add CSS, and finally JavaScript.

Fix the web

In this post (netm.ag/heilmann-288), Christian Heilmann explains why JS isn’t the problem – in fact it’s part of the solution to the web’s ills. We need it to build accessible, easy-to-use and flexible websites; HTML and CSS alone aren’t enough. However, that doesn’t mean caution isn’t required.

JavaScript Guru Guide 23

Goodbye JavaScript

These days it’s possible to do so much with HTML and CSS that you can create all kinds of functional UI components without giving yourself an extra dependency in the form of JavaScript. This site (youmightnotneedjs.com) looks at smart, JavaScript-free ways to make forms, image sliders, file uploaders and more.


The future of JavaScript Essay

The JavaScript JavaScript Guru Handbook Guide 32 32


The future of JavaScript Essay

Offline-First

Fighting Ebola with Javascript Illustration by Ben Mounsey

Patricia Garcia explains how shrewd use of technology helped tackle an emergency situation in a developing country

In September 2014 I joined the software team of an NGO working at the intersection of tech and public health. By then the Ebola outbreak in West Africa had reached epidemic proportions, with thousands of cases reported. One month before, the outbreak had reached Nigeria, where the NGO had provided phones and a custom Android application that helped reduce the reporting time for suspected cases from 12 hours to almost nothing. Now it was the time to bring that expertise and those tools to the most affected countries: Guinea, Sierra Leone and Liberia.

The challenges The Ebola virus is non-airborne and contagion requires direct contact with the bodily fluids of an infected individual. To control the outbreak, infected persons must be isolated and everybody who has come into contact with them must be kept under observation for the 21 day-long incubation period. This requires the collection of an enormous amount of data, and it is critical that the information collected is reported promptly so sick persons can be treated and proper quarantine implemented. This is a scenario where technology shines. As well as speeding up the transfer of data considerably, even a simple application based on web forms can have a positive impact. For example, things like making certain fields mandatory, or letting users choose from a set of options in a drop-down can greatly improve the quality of the data collected.

However, while the technology solutions required are simple, implementing them in the context of a critical emergency situation in a developing country makes things much more challenging. Shipping early is not a nice-to-have but a must – there is no excuse for taking a long time to deliver a feature or not fixing a bug when human lives depend on it. More important than that, internet connectivity is a scarce resource that can’t be counted on. Even when broadband internet is available, it is not unusual for it to stop working for hours or days. Designing the applications to be offline-first is a necessity. Because of these constraints, we chose CouchDB as our central piece of software. CouchDB has been designed with distributed systems in mind, making it perfect to use in an offline context, where a local database is contained in each device. Offering an HTTP REST API, it became not only our database but our backend, too. In the frontend, PouchDB offers a JavaScript database that can store data locally while offline, then synchronise with the CouchDB backend when back online.

Scaling offline applications With the combination of CouchDB and PouchDB we were able to move from zero to production in a week in two of our most important applications, and with a relative simple and clean codebase. This worked very well in Nigeria, where the scale of the outbreak was relatively small. However, the complexity got higher as the amount of data and number of users grew.

The JavaScript JavaScript Guru Handbook Guide 33


React View source files here! All the files you need for this tutorial can be found at netm.ag/reactgit-286

A b o u t t he a u t h o r

Ray Vil l a l obos w: www.raybo.org

t: @planetoftheweb job: Senior staff instructor, LinkedIn areas of expertise: Frontend and fullstack web design and development

react

The 5 React mind shifts Ray Villalobos reveals the five most important things to get

your head around in order to master and fall in love with React Learning React, the JavaScript library for creating user interfaces from Facebook and Instagram, is just crazy. Rather, it seems nuts until you give it a chance. Things get much easier when you understand five key concepts. I call these the five mind shifts. They are: Components, JSX, state, lifecycle methods and one-way data flow. In this article I’ll take a closer look at each of them.

1 Components

Video Ray Villalobos has created an exclusive screencast to go with this tutorial. Watch along at netm.ag/ reactvid-286

Components are chunks of code that can be combined to provide more complex functionality. When you divide your application into components it makes it easier to update and maintain. In React, components are even more important: you don’t just program them, you design your app by thinking of how these components fit together. Let’s use the interface opposite as an example. You can see how it can be divided into three pieces: a box for booking a new appointment, a list view that lets you view the existing appointments, and a search box for looking through them.

JavaScript Guru Guide 46

In HTML, you might think of this application as a series of elements, like this: <div id="petAppointments"> <div class="addAppointments"></div> <div class="searchAppointments"></div> <div class="listAppointments"></div> </div> And that’s also what you’d do in React. You create a single tag ( <div id="petAppointments"> ) that calls a petAppointments component, which then calls the other sub-components as needed. To pass along a configuration object like this, you use the createClass method of the React object. var MainInterface = React.createClass({ render: function() { return ( <div className="interface"> <AddAppointment /> <SearchAppointments />


React

<ListAppointments /> </div> ) } //render }); //MainInterface ReactDOM.render( <MainInterface />, document.getElementById('petAppointments') ); //render There are two render methods. In the MainInterface class we declare the items that will be sent to the browser, and the ReactDOM.render method replaces the <div id="petAppointments"></div> element in your HTML with React’s code. We would then write the code that handles each of our three sub-components. Components make code easy to write and maintain. Once you learn to think of and organise your apps as a series of composable components, building complex applications becomes simpler.

JSX is an extension to JavaScript that allows you to combine XML code with JavaScript 2 JSX JSX (facebook.github.io/jsx) is probably one of the biggest mind shifts and one of the reasons why the library seems so weird. JSX is an extension to JavaScript that allows you to combine XML code with JavaScript. This is sort of what happens with templating languages like Mustache, which let you include JavaScript within HTML. But JSX gets translated (transpiled) into JavaScript. So you are not just building a template, but a structure that gets converted into a series of JavaScript statements. Unlike templating languages, it doesn’t have to be interpreted at runtime. Let’s look at an example. <li className="pet-item media" key={index}> <div className="pet-info media-body"> <div className="pet-head"> <span className="pet-name">{this.state.data[index]. petName}</span> <span className="apt-date pull-right">{this.state. data[index].aptDate}</span> </div> <div className="owner-name"><span className="labelitem">Owner:</span>

In-depth

What is a Virtual DOM? If there’s one thing about React that will win you over it’s the way it manages the DOM using something called the Virtual DOM. Managing the DOM means worrying about inconsistencies between the way browsers handle events and nodes, which is one of the reasons jQuery became so popular. But ask yourself: Why are you mucking with the DOM in the first place? It’s because the state of your application has changed and you need to update your views to match the changes. This is the type of task that would be better managed by a machine, and that’s exactly what React does. React automates the process, so a change in state will render views for you. React’s Virtual DOM is an independent copy of the regular DOM. Why is this faster? When you manage the DOM manually, you trigger a re-rendering process for each modification of the DOM, so if you make 10 changes to the DOM, your browser has to potentially recalculate the DOM 10 times. Borrowing a technique from video games, where the changes to state are cached ‘off-world’ and then pushed to the screen all at once, the Virtual DOM makes rendering happen less often. Another advantage is that you don’t have to worry about browser inconsistencies. The Virtual DOM’s representation is independent of the actual DOM and React will tackle each browser’s rendering independently, so you don’t have to worry about dealing with different methods for different browsers. The best thing about the Virtual DOM is that in most applications, you don’t have to worry about it at all. You worry about your interface, manage the state of your app, and let React do the rest. It’s a refreshing way to work within a modern application.

Example app You can easily see how to structure this app into reusable components

JavaScript Guru Guide 47


Astro

Web Hybrid

Thin Native Wrapper

HTML

JS

CSS

Native Hybrid PhoneGap Bridge

Device Access via plugins: camera, contacts gpd, file system etc

Native Header

My App Thin Native Wrapper JS

HTML

CSS

Thin Native Wrapper JS

HTML

CSS

Thin Native Wrapper

WebView

HTML

JS

Multiple Webviews for content with device access via PhoneGap

CSS

WebView

Assets

Assets

Native Tab Bar and Navigation

App blend Native hybrid

mobile apps blend native controls with one or more webviews (Image: Holly Schinsky, netm.ag/ strategy-286)

Astro vs phonegap a corresponding JavaScript plugin in order to expose so it can be added to the view hierarchy in app.js . It’s up to you to decide how much or how little business logic from the native view controller you’d like to expose in JavaScript. For a tutorial on building native views, check out netm.ag/native-286. Of course, creating native views is important, but it’s also very time consuming, since you have to build them multiple times for each platform (iOS, Android and browser). Let’s explore how to leverage your existing web content in an app.

App-aware sites Astro takes the concept of progressive enhancement to the next level. It doesn’t prescribe any particular way to build your web interfaces – you can use React, Angular or jQuery, it’s up to you. You just need to insert the astro-client.js library into your site, and this will allow you to send and receive messages to app.js . For instance, if you overrode an ‘Add to Cart’ button because you wanted to display a native modal view, the code in your web view would look as follows:

Resource This tutorial guides you through how to build an ecommerce app step-by-step. You can follow along by copying and pasting code snippets. Check it out at netm.ag/tut-286

Once you have the astro-client.js library in your site, you’ll be able to detect the app context in order to progressively enhance the web content for the app. This approach is very similar to how you’d use Modernizr to progressively enhance based on what features are available to the user’s browser. We recommend you have the ability to detect the app context in three places: CSS, JavaScript, and the server side. For detecting in JS, you can run the Astro.isRunningInApp method, which will return a Boolean. We suggest you add an app class to the HTML tag of the site in order to detect the app context in CSS. As for the server, Astro automatically appends Astro App to the user agent header of every request, which enables you to write conditional logic based on that user agent.

document.addEventListener(function(e) { e.preventDefault(); Astro.trigger('addToCartClicked', {item: 'foo'}); }, false); Then, inside your app.js file, you would listen and act on that event like so: webView.on('addToCartClicked', function(payload) { cartModalView.open(payload.item); });

JavaScript Guru Guide 74

In an article on the PhoneGap blog (netm.ag/ strategy-286), Holly Schinsky outlines two different ways of building hybrid apps. Take a look at the image above. The diagram on the left describes the most common use of PhoneGap: the framework gives you access to native APIs, but the UI is meant

Astro leverages PhoneGap, meaning all Cordova plugins are available to Astro to be entirely built with the web. The diagram on the right describes the Astro framework very well. Astro allows you to use JavaScript to render content either as web or as native, and does not care whether you use more of one or the other. Astro actually leverages Cordova, meaning all plugins available to this ecosystem are available in Astro. Learn more about how to add a Cordova plugin to an Astro app at netm.ag/cordova-286.

Conclusion When it comes to building apps, I believe we should be pragmatic about our tech choices instead of sticking to one strategy or the other. There are plenty of great reasons to render content in either web or native, and which one you use depends on the requirements of the feature you’re building. For that reason I believe that almost all apps should be built as progressive apps, which leverage the best of native and web. If you have any feedback or questions, join us in our Slack community at astrocommunity.herokuapp.com.


New York 27-28 April 2017

San Francisco 9 June 2017

London 20-22 september 2017 Tickets on Sale now

www.generateconf.com


D3.js View source files here! All the files you need for this tutorial can be found at netm.ag/D3git-280

A b o u t t he a u t h o r

Na dieh Bremer w: www.visualcinnamon.com t: @NadiehBremer job: Data visualisation designer, Adyen areas of expertise: Data visualisation, D3.js

SVG

Boost D3.js charts with SVG gradients

Nadieh Bremer walks through four different ways you can use SVG gradients to brighten up your D3.js data visualisations

Res ource One of the best books for learning D3 is Scott Murray’s Interactive Data Visualization for the Web, and it’s available online for free! netm.ag/scott-244

D3.js has taken over the world of interactive data visualisation. An enormous number of examples can be found, each showcasing its own fun and useful twist on the library. You see, D3 is not a charting library, but something much better. It gives you only the basic tools to create data visualisations, and in doing so enables you to create practically anything you can think of. Even though some ideas might take more time than others, you’ll get there eventually. And this freedom is exactly what I love about D3. At its core, every D3 visual is built out of SVG elements. For example, <circle> for each datapoint

JavaScript Guru Guide 100

in a scatterplot chart, <rect> to create a bar chart, <line> as an axis, parallel coordinates or slope graph, <text> as labels, and the extremely useful <path> for practically everything else. Furthermore, SVGs are resolution-independent, thus look great on any display or zoom level. Even if you’re just using SVGs for their shapes, you can create wonderful visualisations. However, they can do much more – think of SVG filters for example. In this tutorial, we’ll take a deep dive into one specific aspect and look at a few different ways it can be applied to brighten up a visualisation. Let me introduce you to SVG gradients!


D3.js

Linear gradients Sometimes when I create a line chart with a single line it just feels a bit too empty and can get lost on the white background. To make it stand out more, I place a light gradient below it using D3’s d3.svg.area function, filled with an SVG gradient (see fig 1). I want the gradient to run vertically from the top (where it is the same colour as the line but a lighter shade) to the bottom (where it should become white, or transparent). This is what is known as a linear gradient; something that changes colour along a straight line. We start with an SVG. This is the canvas on which our line chart will be drawn. We then create a defs element onto which we can append a linearGradient element. It’s very important to give the gradient a unique ID – we will use this later when we need to give the area below the line its fill.

At its core, every D3 visual is built out of SVG elements – but they can do much more var areaGradient = svg.append("defs") .append("linearGradient") .attr("id","areaGradient") .attr("x1", "0%").attr("y1", "0%") .attr("x2", "0%").attr("y2", "100%"); The last two lines of the code above define how the gradient should run. Think of it as a invisible line: x1 and y1 are the starting positions of the invisible line and the x2 and y2 indicate its end point, to give the direction of the gradient. It’s often easiest to define these as percentages, although it is possible to use exact pixel locations. By default the locations refer to the bounding box of the element onto which the gradient is applied. We want the gradient to run vertically, so x1 and x2 should be the same ( 0% is fine), y1 has to be 0% and y2 100% . Now we can define the colours of the gradient. At least two colours are needed for a gradient, but you can use as many as you like. For each colour in the gradient you add a stop element. Within this you specify the shade with stop-color , and the location (along the invisible line) where you want this colour to be pure (the exact colour) with offset . Optionally, we can also set the opacity of each colour with stop-opacity . Here I’m making the shade slightly lighter at the top and completely transparent at the bottom.

Focus on

Block Builder If you’ve ever looked up anything about D3.js before, it’s very likely you’ll have come across a D3 example hosted on bl.ocks.org. This page by D3’s creator Mike Bostock has become the prime location for the D3 community to share (small) visualisations or code samples. The diversity of charts and useful functions found on this page is mind-boggling, and it’s an extremely useful resource for those creating visualisations with D3. However, it used to be quite a hassle to get your code into a block (and even more so if you wanted to start or fork from another block), because you had to create and adjust your code on a local server and then upload and commit it to GitHub’s gists. But those days are over, thanks to the introduction of Block Builder (blockbuilder.org). Created in 2015 as a Kickstarter project by Ian Johnson, it is especially useful for those starting with D3 who are not used to working in a terminal. You can start with a blank slate or copy/fork over someone else’s example and edit the code directly in the browser. The results of your changes will be displayed immediately in the frame at the top of the screen, so there’s no need to continually switch between code editor and browser while you try and find a result you’re happy with. You can also add new files, and even upload a small thumbnail of the block’s result. Everything you save will become part of your own block gallery. Check out the 3-minute video on blockbuilder.org/ about to learn how easy it is to use!

D3 in the browser A screenshot of the Block Builder website showing the interactive visualisation at the top and the code below

JavaScript Guru Guide 101


Performance

In-Depth

Preload When someone visits your web page, which resources load first? The order in which files are referenced in the HTML matters, but browsers also have their own ideas about what kinds of resource should have priority. Preloading is one way to take some of the control back. It can be useful on pages that reference large numbers of JavaScript files. Even if they’re placed towards the end of the document, they can tie up connections that you might prefer to use for lower-priority resources, such as images. Preload allows you to tell the browser about files you know will be needed but that tend to be discovered late – font files and CSS background images are good examples. However, it can also be used to get images referenced in the HTML to leapfrog scripts by giving them higher priority. Using preload is as simple as adding <link> elements to the top of the page. For example:

Figure 3 Waterfall chart extract showing how images can be made to load ahead of scripts with preload

object, rather than leaving it to the browser to guess at what’s most important. We started to see something similar with the nowabandoned Resource Priorities specification. What could be helpful is something like the pr attribute in the Resource Hints specification, which indicates the likelihood that a given resource will be used.

HTTP/2

<link rel="preload" href="images/mypic.jpg"> Below you can see what happened when we tested this idea in Chrome. The first waterfall extract shows how scripts referenced at the bottom of the page can be loaded ahead of images referenced above them. The second shows how this changed when we preloaded the images.

In HTTP/2 some of these problems go away, since requests and responses are multiplexed in streams over a single connection. However, the concept of resource priorities remains, with bandwidth apportioned accordingly, taking various dependencies into account. Another important concept in HTTP/2 is server push. This involves a server sending a resource to the client before the client has asked for it, making it especially useful for delivering the CSS required to start rendering a page. Preloading and server push can be used together by adding a response header to the root object: Link: </ images/mypic.jpg>; rel=preload; Add nopush if you want to use preloading but not server push: Link: </ images/mypic.jpg>; rel=preload; nopush Server push is probably more relevant to critical CSS files than it is to imagery, but it’s worth mentioning here because it is possible to adjust the priority given to pushed resources (see Apache’s H2PushPriority directive: netm.ag/push-287).

The point to take away

Figure 4 A connection view waterfall chart showing images with higher priority than scripts

JavaScript Guru Guide 142

When building any page, it’s important to consider what visitors are most likely to want from it. Nonessential scripts can get in the way of key content, and loading them asynchronously doesn’t guarantee they won’t negatively impact the experience.


The source for tech buying advice techradar.com


Tech Guru Guide Bookazine 17 (Sampler)  

You can subscribe to this magazine @ www.myfavouritemagazines.co.uk

Tech Guru Guide Bookazine 17 (Sampler)  

You can subscribe to this magazine @ www.myfavouritemagazines.co.uk