Page 1

.html { render action: “edit” } format.json { render json: @task.errors, status: :unprocessable_entity } $ bundle exec rails generate migration add_priority_to_tas y:integer $ bundle exec rake db:migrate $ bundle exec rake db:migrate $ bundle exec rails server validate :due_at_is_in_the_past def due_at_is_in_the_past erro ue_at, ‘is in the past!’) if due_at < Time.zone.now #!/usr/bin/en python import pygame from random import randrange MAX_STARS = 100 pygame.init() screen me.display.set_mode((640, 480)) clock = pygame.time.Clock() stars = for i in range(MAX_STARS): star = [randrange(0, 639), randrange(0, 479), randrange(1, 16)] sta d(star) while True: clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: exit(0) #!/usr/bin/perl $numstars = 100; use Time::HiRes qw(uslee urses; $screen = new Curses; noecho; curs_set(0); for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] = rand(80); $star_y[$i] = rand(24); $star_s[$i] = rand(4) + 1; } while (1 n->clear; for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] -= $star_s[$i]; if ($star_x[$i] < 0) { $star_x[$i] = 80; } $screen->addch($star_y[$i], $star_x[$i], “.”); } $screen->refres 50000; gem “therubyracer”, “~> 0.11.4” group :development, :test do gem “rspec-rails”, “~> 2.13.0” $ gem install bundler $ gem install rails --version=3.2.12 $ rbe h $ rails new todolist --skip-test-unit respond_to do |format| if @task.update_attributes(params[:task]) format.html { redirect_to @task, notice: ‘...’ } format.json { he ntent } else format.html { render action: “edit” } format.json { render json: @task.errors, status: :unprocessable_entity } $ bundle exec rails generate migration ad y_to_tasks priority:integer $ bundle exec rake db:migrate $ bundle exec rake db:migrate $ bundle exec rails server validate :due_at_is_in_the_past def due_at_is_i ast errors.add(:due_at, ‘is in the past!’) if due_at < Time.zone.now #!/usr/bin/en python import pygame from random import randrange MAX_STARS = 100 pygam creen = pygame.display.set_mode((640, 480)) clock = pygame.time.Clock() stars = for i in range(MAX_STARS): star = [randrange(0, 639), randrange(0, 479), randrange ars.append(star) while True: clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: exit(0) #!/usr/bin/perl $numstars = 100; use Time::HiR leep); use Curses; $screen = new Curses; noecho; curs_set(0); for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] = rand(80); $star_y[$i] = rand(24); $star_s[$i] = rand(4) + e (1) { $screen->clear; for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] -= $star_s[$i]; if ($star_x[$i] < 0) { $star_x[$i] = 80; } $screen->addch($star_y[$i], $star_x[$i], “.” n->refresh; usleep 50000; gem “therubyracer”, “~> 0.11.4” group :development, :test do gem “rspec-rails”, “~> 2.13.0” $ gem install bundler $ gem install ra on=3.2.12 $ rbenv rehash $ rails new todolist --skip-test-unit respond_to do |format| if @task.update_attributes(params[:task]) format.html { redirect_to @task, noti ormat.json { head :no_content } else format.html { render action: “edit” } format.json { render json: @task.errors, status: :unprocessable_entity } $ bundle exec ra ate migration add_priority_to_tasks priority:integer $ bundle exec rake db:migrate $ bundle exec rake db:migrate $ bundle exec rails server validate :due_at_is_in_th ef due_at_is_in_the_past errors.add(:due_at, ‘is in the past!’) if due_at < Time.zone.now #!/usr/bin/en python import pygame from random import randrange MA S = 100 pygame.init() screen = pygame.display.set_mode((640, 480)) clock = pygame.time.Clock() stars = for i in range(MAX_STARS): star = [randrange(0, 63 nge(0, 479), randrange(1, 16)] stars.append(star) while True: clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: exit(0) #!/usr/bin/p stars = 100; use Time::HiRes qw(usleep); use Curses; $screen = new Curses; noecho; curs_set(0); for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] = rand(80); $star_y[ (24); $star_s[$i] = rand(4) + 1; } while (1) { $screen->clear; for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] -= $star_s[$i]; if ($star_x[$i] < 0) { $star_x[$i] = 80; } $scree h($star_y[$i], $star_x[$i], “.”); } $screen->refresh; usleep 50000; gem “therubyracer”, “~> 0.11.4” group :development, :test do gem “rspec-rails”, “~> 2.13.0” $ gem inst er $ gem install rails --version=3.2.12 $ rbenv rehash $ rails new todolist --skip-test-unit respond_to do |format| if @task.update_attributes(params[:task]) format.htm ct_to @task, notice: ‘...’ } format.json { head :no_content } else format.html { render action: “edit” } format.json { render json: @task.errors, status: :unprocessable_ent ndle exec rails generate migration add_priority_to_tasks priority:integer $ bundle exec rake db:migrate $ bundle exec rake db:migrate $ bundle exec rails server valida t_is_in_the_past def due_at_is_in_the_past errors.add(:due_at, ‘is in the past!’) if due_at < Time.zone.now #!/usr/bin/en python import pygame from random imp nge MAX_STARS = 100 pygame.init() screen = pygame.display.set_mode((640, 480)) clock = pygame.time.Clock() stars = for i in range(MAX_STARS): star ange(0, 639), randrange(0, 479), randrange(1, 16)] stars.append(star) while True: clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: exit bin/perl $numstars = 100; use Time::HiRes qw(usleep); use Curses; $screen = new Curses; noecho; curs_set(0); for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] = rand(8 y[$i] = rand(24); $star_s[$i] = rand(4) + 1; } while (1) { $screen->clear; for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] -= $star_s[$i]; if ($star_x[$i] < 0) { $star_x[$i] = 80 n->addch($star_y[$i], $star_x[$i], “.”); } $screen->refresh; usleep 50000; gem “therubyracer”, “~> 0.11.4” group :development, :test do gem “rspec-rails”, “~> 2.13.0” nstall bundler $ gem install rails --version=3.2.12 $ rbenv rehash $ rails new todolist --skip-test-unit respond_to do |format| if @task.update_attributes(params[:tas .html { redirect_to @task, notice: ‘...’ } format.json { head :no_content } else format.html { render action: “edit” } format.json { render json: @task.errors, statu cessable_entity } $ bundle exec rails generate migration add_priority_to_tasks priority:integer $ bundle exec rake db:migrate $ bundle exec rake db:migrate $ bund ails server validate :due_at_is_in_the_past def due_at_is_in_the_past errors.add(:due_at, ‘is in the past!’) if due_at < Time.zone.now #!/usr/bin/en python imp me from random import randrange MAX_STARS = 100 pygame.init() screen = pygame.display.set_mode((640, 480)) clock = pygame.time.Clock() stars = for i MAX_STARS): star = [randrange(0, 639), randrange(0, 479), randrange(1, 16)] stars.append(star) while True: clock.tick(30) for event in pygame.event.get(): if event.ty game.QUIT: exit(0) #!/usr/bin/perl $numstars = 100; use Time::HiRes qw(usleep); use Curses; $screen = new Curses; noecho; curs_set(0); for ($i = 0; $i < $numstar $star_x[$i] = rand(80); $star_y[$i] = rand(24); $star_s[$i] = rand(4) + 1; } while (1) { $screen->clear; for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] -= $star_s[$i] _x[$i] < 0) { $star_x[$i] = 80; } $screen->addch($star_y[$i], $star_x[$i], “.”); } $screen->refresh; usleep 50000; gem “therubyracer”, “~> 0.11.4” group :development, :te m “rspec-rails”, “~> 2.13.0” $ gem install bundler $ gem install rails --version=3.2.12 $ rbenv rehash $ rails new todolist --skip-test-unit respond_to do |format| if @tas e_attributes(params[:task]) format.html { redirect_to @task, notice: ‘...’ } format.json { head :no_content } else format.html { render action: “edit” } format.json { rend @task.errors, status: :unprocessable_entity } $ bundle exec rails generate migration add_priority_to_tasks priority:integer $ bundle exec rake db:migrate $ bundle ex b:migrate $ bundle exec rails server validate :due_at_is_in_the_past def due_at_is_in_the_past errors.add(:due_at, ‘is in the past!’) if due_at < Time.zone.now #!/u python import pygame from random import randrange MAX_STARS = 100 pygame.init() screen = pygame.display.set_mode((640, 480)) clock = pygame.time.Cloc = for i in range(MAX_STARS): star = [randrange(0, 639), randrange(0, 479), randrange(1, 16)] stars.append(star) while True: clock.tick(30) for event in pygame.eve f event.type == pygame.QUIT: exit(0) #!/usr/bin/perl $numstars = 100; use Time::HiRes qw(usleep); use Curses; $screen = new Curses; noecho; curs_set(0); for ($i = numstars ; $i++) { $star_x[$i] = rand(80); $star_y[$i] = rand(24); $star_s[$i] = rand(4) + 1; } while (1) { $screen->clear; for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] s[$i]; if ($star_x[$i] < 0) { $star_x[$i] = 80; } $screen->addch($star_y[$i], $star_x[$i], “.”); } $screen->refresh; usleep 50000; gem “therubyracer”, “~> 0.11.4” gro opment, :test do gem “rspec-rails”, “~> 2.13.0” $ gem install bundler $ gem install rails --version=3.2.12 $ rbenv rehash $ rails new todolist --skip-test-unit respond_ mat| if @task.update_attributes(params[:task]) format.html { redirect_to @task, notice: ‘...’ } format.json { head :no_content } else format.html { render action: “edit .json { render json: @task.errors, status: :unprocessable_entity } $ bundle exec rails generate migration add_priority_to_tasks priority:integer $ bundle exec ra grate $ bundle exec rake db:migrate $ bundle exec rails server validate :due_at_is_in_the_past def due_at_is_in_the_past errors.add(:due_at, ‘is in the past!’) if due_ e.zone.now #!/usr/bin/en python import pygame from random import randrange MAX_STARS = 100 pygame.init() screen = pygame.display.set_mode((640, 480)) clo ame.time.Clock() stars = for i in range(MAX_STARS): star = [randrange(0, 639), randrange(0, 479), randrange(1, 16)] stars.append(star) while True: clock.tick(30) n pygame.event.get(): if event.type == pygame.QUIT: exit(0) #!/usr/bin/perl $numstars = 100; use Time::HiRes qw(usleep); use Curses; $screen = new Curses; noech et(0); for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] = rand(80); $star_y[$i] = rand(24); $star_s[$i] = rand(4) + 1; } while (1) { $screen->clear; for ($i = 0; $i < $numstar $star_x[$i] -= $star_s[$i]; if ($star_x[$i] < 0) { $star_x[$i] = 80; } $screen->addch($star_y[$i], $star_x[$i], “.”); } $screen->refresh; usleep 50000; gem “therubyracer”, “ ” group :development, :test do gem “rspec-rails”, “~> 2.13.0” $ gem install bundler $ gem install rails --version=3.2.12 $ rbenv rehash $ rails new todolist --skip-test-u nd_to do |format| if @task.update_attributes(params[:task]) format.html { redirect_to @task, notice: ‘...’ } format.json { head :no_content } else format.html { render actio } format.json { render json: @task.errors, status: :unprocessable_entity } $ bundle exec rails generate migration add_priority_to_tasks priority:integer $ bundle ex b:migrate $ bundle exec rake db:migrate $ bundle exec rails server validate :due_at_is_in_the_past def due_at_is_in_the_past errors.add(:due_at, ‘is in the past!’ t < Time.zone.now #!/usr/bin/en python import pygame from random import randrange MAX_STARS = 100 pygame.init() screen = pygame.display.set_mode((640, 48 = pygame.time.Clock() stars = for i in range(MAX_STARS): star = [randrange(0, 639), randrange(0, 479), randrange(1, 16)] stars.append(star) while True: clock.tick(3 ent in pygame.event.get(): if event.type == pygame.QUIT: exit(0) #!/usr/bin/perl $numstars = 100; use Time::HiRes qw(usleep); use Curses; $screen = new Curs o; curs_set(0); for ($i = 0; $i < $numstars ; $i++) { $star_x[$i] = rand(80); $star_y[$i] = rand(24); $star_s[$i] = rand(4) + 1; } while (1) { $screen->clear; for ($i = 0; $ stars ; $i++) { $star_x[$i] -= $star_s[$i]; if ($star_x[$i] < 0) { $star_x[$i] = 80; } $screen->addch($star_y[$i], $star_x[$i], “.”); } $screen->refresh; usleep 50000; ge

the ultimate

javascript manual 2019 20+ practical tutorials! master the world’s most important programming language

THIRD edition

Digital Edition

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

180 pages of expert advice enhance your knowledge with in-depth projects and guides


contents

JavaScript Guru Guide 6


Contents

Animation

Features 20 JavaScript tips to blow your mind 8

Site animations with scrollmagic

106

Essential Javascript

16

Build a split-screen landing page

112

Big question

24

Create Micro-animations

118

Introduction to frontend testing

26

Wireframe Rendering in WebGL

124

Gallery

32

integrate photos into video

130

explore creative code with p5.js

134

Frameworks

Performance

The 5 react mind shifts

40

Build a music player with react

44

Stop JS files slowing your sites

140

Material Design with Angular

48

Explore lazy loading

144

Head to head: Vue vs React

53

improve your grunt setup

150

Data Visualisation with Angular

54

Live mockups with Angular

58

Mix Web and native with Astro

62

3D scenes with A-frame and vue.js

156

Real time apps with firebase

68

Virtual reality web apps

160

add push notifications

72

Apps that collect sensor data

166

Immersive Iot experiences

170

UI & RWD layouts with postCss-flexbox

78

Web apps with container queries 

82

Create a custom user interface

88

D3.js charts with SVG gradients

92

Make your site work on touch

98

VR & Iot

Exchange Advice from industry experts

JavaScript Guru Guide 7

174


Essential JavaScript

When to use jQuery In 2013 Remy Sharp spoke at jQuery UK and wrote an accompanying blog post titled ‘I know jQuery. Now what?’ (netm.ag/nowwhat-261). In the post he spoke about how he went from relying on jQuery for all his projects, to using it on more of a case-by-case basis. Tom Maslen, a developer at the BBC, spoke at Responsive Day Out (besquare.me/session/cutting-themustard) about ‘Cutting the mustard’, the technique the BBC use to decide if a browser is ‘up to scratch’ or not: if ('querySelector' in document && 'localStorage' in window && 'addEventListener' in window) { // bootstrap the JavaScript application } Any browsers that don’t support the above get the core experience, but without the extra functionality added by the JavaScript. If you need to fully support those older browsers, jQuery is still the best option. If you find yourself only supporting the newer browsers but still wanting an easier interface than JavaScript offers by default, Remy Sharp’s min.js (github.com/remy/min.js) might be the thing for you. It’s a small library that offers simple DOM querying and event listener functionality.

GruntJS One of the frst and most popular projects for running command line tasks

Command line tools

Node.js

Grunt

nodejs.org

gruntjs.com

Node.js lets us write JavaScript on the server, but it also lets us run arbitrary JavaScript on the command line. This has led to a number of tools designed to automate tasks that we otherwise would have to complete manually. The easyto-use Node Package Manager (npm) has really helped the community and ecosystem grow at a rapid rate. It not only makes it very easy to install tools, but also makes it nice and straightforward for people to publish their own.

Grunt has been around for quite a while now, and is the most popular task runner for JavaScript. Created by Ben Alman, its vast plugin ecosystem allows you to configure it to compile your Sass, run your tests, minify your JavaScript and much more. When using Grunt, you install the plugins for the functionality you desire, and then create a Gruntfile.js file which will contain all the configuration for the plugins – such as the location of files to use, or settings for how you would like your code to be minified. You don’t write code to perform your tasks, but configure the plugins you’d like to use.

gulp.js gulpjs.com gulp.js uses file streams and lets you define tasks by writing the code, rather than the configuration approach favoured by Grunt. This means you can get a bit more hands-on with your build system. In your Gulpfile.js file, tasks are defined as functions, in which you can write any JavaScript you’d like. There is still a huge amount of plugins for common tasks, but you have to include and call them yourself. It’s harder to pick up, but once you’re used to it you’re able to wield a huge amount of power.

JavaScript Guru Guide 18

Serve github.com/visionmedia/serve Serve is something I use every day and has become a key part of my workflow. Once installed, it allows me to run serve in any directory and visit the site on localhost:3000 . This is fantastic if you’re working with a website that you would quickly like to run, and view in a browser.


Essential JavaScript

gulp This system focuses on streams, which are abstract representations of files

ESLint Keep code quality high across teams

Yeoman You can save time by using Yeoman to generate files for you

Moment.js This provides a fantastic API for editing and formatting dates

Yeoman yeoman.io Yeoman is a tool for building websites. It will generate a project structure and configure any build tools used to run your project. Once you’re familiar with the tools, you can save a lot of time by using Yeoman to generate files for you. For example, running yo webapp will generate an entire project set-up for writing HTML, CSS (or if you prefer, Sass) and JavaScript, complete with a fully featured Gulpfile with tasks configured for you. You can also create custom generators to suit your project’s particular needs.

ESLint eslint.org As JavaScript is a loosely typed language, perfectly valid code can start causing unexpected problems down the line. ESLint is a tool that can check through

your files for common issues that may not be what you intended. Each project can have its own set of rules to check against. By running eslint . it will check all JavaScript files in the project directory. All that is required is a .eslintrc configuration file that details the rules to follow. Preset collections of rules by the likes of Google and Airbnb are readily available.

http-server github.com/indexzero/http-server Every project will need a server. While these can be tricky to get up and running, http-server can do all the heavy lifting behind the scenes. By default, running http-server will serve from the current directory. But there are a multitude of different options to customise this. For example, --ssl will enable HTTPS or --gzip will serve gzipped assets. It is flexible enough to install locally for development

JavaScript Guru Guide 19

and reliable enough to deploy for production sites.

Utility libraries

Lo-Dash

lodash.com Although newer features in ECMAScript 5 and 6 have a lot of added functionality, often you’ll find yourself wanting to perform a fairly simple task on some data that you’d rather not implement yourself. That’s where Lo-Dash comes in. It provides a vast amount of utility functions to perform common operations on objects, arrays or functions.

Moment.js momentjs.com Working with dates is usually pretty painful, regardless of language, but in JavaScript it’s even worse. The provided APIs simply don’t provide the features required. Thankfully for us, Moment.js


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 40

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 41


AngularJS Download the files here! Download all the files you need for this tutorial at netm.ag/firebasegit-265

AngularJS

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

L uk as Ruebbel k e t: @simpulton w: onehungrymind.com Job: Senior developer advocate, Udacity Areas of expertise: JavaScript, HTML, CSS, shenanigans

Build a real-time app with Firebase

Lukas Ruebbelke shows you how to take an AngularJS application and give it real-time capabilities using AngularFire Imagine connecting an AngularJS application to a fully functional backend in a matter of minutes. Now imagine every client connected to your app would reflect changes to your data in real time. We are going to do exactly that, by taking an existing AngularJS leaderboard application, which only stores data in memory on the frontend, and converting it into a real-time web app using Firebase (firebase.com).

The leaderboard First, let’s look at how the static version of the leaderboard works. Our leaderboard consists of two main parts: the admin dashboard (where we manage contestant data) and the leaderboard (where we display contestant data in real time). The leaderboard application consists of an AngularJS service called ContestantsService and a controller named MainCtrl . The MainCtrl delegates all operations that manipulate the contestants collection to the ContestantsService . This means when we add Firebase functionality to our application, all our changes will be contained in the service and nothing else needs to change.

Displaying contestants

Video Lukas Ruebbelke has created an exclusive screencast to go with this tutorial. Watch along at netm.ag/ firebasevid-265

We’ll start with displaying contestants’ data. In our ContestantsService we have created a contestants collection that we are making available via the service.getContestants method. app.service('ContestantsService', function () { var service = this; var contestants = [

JavaScript Guru Guide 68

{id: 1, lane: 1, name: 'Contestant 01', score: '10'}, {id: 2, lane: 2, name: 'Contestant 02', score: '15'}, {id: 3, lane: 3, name: 'Contestant 03', score: '20'} ]; service.getContestants = function () { return contestants; }; }); Now we have access to the contestants collection, we will inject ContestantsService into the MainCtrl and assign the return value of ContestantsService. getContestants to main.contestants . We are also initialising an empty contestant object to main.newContestant , which we will use to bind the new contestant form to. // We are using the controllerAs syntax app.controller('MainCtrl', function (ContestantsService) { var main = this; main.newContestant = {lane: '', name: '', score: ''}; main.contestants = ContestantsService.getContestants(); }); With contestants available on our controller, we can use ngRepeat to display our contestants in a table. <tr ng-repeat="contestant in main.contestants"> <td>{{contestant.lane}}</td> <td>{{contestant.name}}</td> <td>{{contestant.score}}</td> </tr>


AngularJS

The leaderboard page is actually a subset of the admin dashboard, which allows us to use the same controller for both views.

Adding a contestant In our dashboard, we will add a form that will allow us to add a new contestant. We are showing one input – to update the contestant’s lane – but the format is the same for the contestant’s name and score. Here, we have a text input field that uses ngModel to bind to a property of main.newContestant.lane . We have also added ngSubmit , which calls main. addContestant when the form is submitted: <form class="form-inline" role="form" novalidate ng-submit="main.addContestant()"> <div class="form-group"> <input type="text" class="form-control" ng-model="main.newContestant.lane" placeholder="Enter lane"> </div> <!-- The rest of the form --> <button type="submit" class="btn btn-default">Add</ button> </form> When main.addContestant is called, a copy of main. newContestant is passed on to ContestantsService. addContestant and main.newContestant is reset.

The leaderboard page is a subset of the admin dashboard, so we can use the same controller main.addContestant = function () { ContestantsService.addContestant(angular.copy(main. newContestant)); main.newContestant = {lane: '', name: '', score: ''}; }; In the static version of the leaderboard, service. addContestant creates a fake id based on the current time and uses that id to add the new contestant to the contestants collection. I would not recommend using this method in a real application, but it will serve its purpose until it gets hooked up to Firebase.

service.addContestant = function (contestant) { contestant.id = new Date().getTime(); contestants.push(contestant); };

Updating a contestant Updating a contestant is slightly simpler in the static version of the leaderboard, as updates to the contestant object are immediately stored in memory. In the dashboard, we will replace the simple binding in the table cell to a text field that we will bind to that property on the contestant . For instance, the markup below: <td>{{contestant.lane}}</td> ... will become:

<td><input type="text" ng-model="contestant.lane" ng-blur="main.updateContestant(contestant)"/></td> We are using ngBlur to call main.updateContestant with the contestant we are updating, which then gets passed on to ContestantsService.updateContestant . main.updateContestant = function (contestant) { ContestantsService.updateContestant(contestant); }; We are not actually going to do anything in service. updateContestant yet, but it will come in handy in just a moment.

JavaScript Guru Guide 69

Leaderboard When a user updates a contestant in the dashboard view, that change is immediately sent to everyone connected to the leaderboard view


HTML, Sass & Javascript

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

Neil P e arce w: neilpearcedesigns.co.uk t: @  neilpearce job: Front-end developer and designer areas of expertise: All-round front-end developer, style guides, pattern libraries, architecture, team work, speaking, workshops

HTML, SasS & JavaScript

Build a split-screen landing page

Using HTML, Sass and JavaScript, develop an animated split screen landing page, ideal for a fashion brand website

Your website landing page is a crucial element in web design. Its effectiveness can translate to increased conversions and when it involves an ecommerce website, this can be very important. Landing pages are designed with a single focused objective – known as a Call to Action (CTA). This CTA needs to be simple and obvious enough to work – simplicity is key here as your landing page is the first real opportunity you have to introduce your business, or the product or products you sell. So the use of nice colours and images to compliment the calls to action and the user experience is a must. So, in this tutorial, we will look at how we can build a simple landing page for a fashion brand for both men and women. We will be giving the user a nice pleasant design with nice large images and animated transitions that happen on hover. This page will have two clear calls to action buttons and

JavaScript Guru Guide 112

we’ll be using HTML, Sass (.scss) for styling and a touch of vanilla JavaScript that uses the ES6 syntax. To make things easier for us, we will develop this project within Codepen (https://codepen.io). You can use your own local set up but we will be using Sass, so if you want to follow along with everything I’ll be doing without using Codepen, then you’ll need Sass installed and running before we can begin.

Getting set up If you’re using Codepen, make sure the CSS is set to ‘SCSS’ in the Pen settings. You can make this change by clicking on the settings tab, choose ‘CSS’ and change the CSS Preprocessor to SCSS in the dropdown options. Then we can begin adding in our HTML. We’re going to wrap a section called ‘left’ and a section called ‘right’ within a container class, with both sections given a class of ‘screen’.


HTML, Sass & Javascript

<div class="container"> <section class="screen left"> </section> <section class="screen right"> </section> </div>

Finishing up the HTML To finalize our HTML, we will add in a title for each section using an ‘h1’ tag. Underneath that we will need to add in a button, which would link to another page if this was a real-world project. We will give this a class of ‘button’ to keep things nice and simple. <div class="container"> <section class="screen left"> <h1>Mens Fashion</h1> <button> <a href="#" class="button">Learn More</a> </button> </section> <section class="screen right"> <h1>Womens Fashion</h1> <button> <a href="#" class="button">Learn More</a> </button> </section>

Sass Variables The one thing we all love about Sass is the use of variables. Even though native CSS variables are getting more support, we will keep things safe by using Sass. We will put these at the top of our ‘.scss’ , and you can choose whatever colours you want, but using the ‘rgba’ values will give us more flexibility. /** Variables **/ $container-BgColor: #444; $left-bgColor: rgba(136, 226, 247, 0.7); $left-button-hover: rgba(94, 226, 247, 0.7); $right-bgColor: rgba(227, 140, 219, 0.8); $right-button-hover: rgba(255, 140, 219, 0.7); $hover-width: 75%; $small-width: 25%; $animateSpeed: 1000ms;

Body Styling Firstly, we will clear all default padding and margin to the body and then set the font family to ‘Open Sans’. This will only effect the button, so it doesn’t matter too much on what font we use. Then we will

set the width and height to 100% and make sure that anything that overflows on the X axis gets hidden. html, body { padding:0; margin:0; font-family: 'Open Sans', sans-serif; width: 100%; height: 100%; overflow-x: hidden; }

Styling the Section Titles In print, fashion magazines use specific fonts. The most common is ‘Didot’. However, this font isn’t a Google font so we will use one called ‘Playfair Display’ – which is close enough. Then using ‘translateX’ we can make sure the section titles are always centred on the x axis.

JavaScript Guru Guide 113

Top In the CSS section in Codepen, set the preprocessor to SCSS using the drop down options, before continuing on Above With our HTML now completed, we can start to add in some CSS by giving the body some styling


A-Frame View source files here! All the files you need for this tutorial can be found at netm.ag/VRgit-287

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

P e t er O’Shaughness y w: peteroshaughnessy.com t: @poshaughnessy job: Developer advocate, Samsung

Original photograph: Stuart Chapman

areas of expertise: Web APIs, mobile, VR/AR

A-Frame

Create a virtual reality web app

Peter O’Shaughnessy introduces WebVR and shows you how to develop your first virtual reality web app using A-Frame

Video Samsung developer advocate Diego González has created an exclusive screencast to go with this tutorial. Watch along at netm.ag/vrvid-287

For decades technology fans have dreamed of the ‘Metaverse’: a shared, inhabitable, virtual universe, limited only by our imagination. It sounds like science fiction, but the virtual reality internet is now starting to become a reality. Imagine a chat app that could launch an instant virtual meeting, transporting yourself and your colleagues into a scene from the other side of the world. Or imagine reading a web page about Mars that – at the press of a button – transforms into a virtual reality tour of the planet. These kind of experiences (and much more) are possible with

JavaScript Guru Guide 160

WebVR, a new JavaScript API that lets you create VR applications powered by your web browser.

Introducing webvr WebVR provides the tools to take a scene from a canvas element and display it on a virtual reality head-mounted display (HMD), in a way that gives the user a sense of seeing and inhabiting a threedimensional scene. The API provides the user’s orientation and the necessary parameters required to render the scene appropriately for the particular VR device.


9000

A-Frame

Focus on

X, Y and Z values Our position , rotation and scale values consist of three numbers, representing (in order) X, Y and Z. A-Frame, like three.js upon which it is based, uses a ‘right-handed’ coordinate system. This means that X increases to the right, Y increases upwards, and Z increases coming out from the screen. Right-handed refers to the ‘right hand rule’ whereby, if your thumb represents X, your forefinger represents Y and your middle finger represents Z, then the axes increase in the direction that your fingers point, when you hold your hand up as shown in the image below. Lift off Virtual reality can transport us anywhere we can imagine, including to other planets

WebVR currently has support from Google, Mozilla, Samsung and Microsoft. The specification is an early draft, but there is a W3C community group actively working on it. It is already possible

WebVR enables us to take a scene from a canvas element and display it on a HMD to start developing web apps for Oculus Rift, Samsung Gear VR and OpenVR headsets including the HTC Vive. Using a polyfill, it can be used for simple smartphone enclosures such as Google Cardboard too. As web developers, WebVR is bestowing us with the power to create our own virtual worlds, immersive games and 3D interfaces. Let’s use it to develop our first virtual reality web app.

Hand rules Left-handed and right-handed coordinate systems (Image by Primalshell, CC BY-SA 3.0)

If you do not define your own camera element, A-Frame will define one for you by default and position it at 0, 0, 0 . Therefore, to place an object so that it is in front of the user when the scene first loads, you would need to give it a negative Z position. For angles of rotation, A-Frame uses degrees (it converts them to radians for us, to pass into three.js). A rotation value of 0 45 0 means the object will be rotated 45 degrees around the Y-axis.

How to enable WebVR WebVR is not yet enabled in browsers by default. In the meantime, we can download a suitable browser and switch WebVR on: ●C  hrome (supports Oculus Rift and OpenVR): download the experimental WebVR build from webvr.info/get-chrome, visit chrome://flags and select Enable WebVR ● Firefox Nightly (supports Oculus Rift and OpenVR): follow the instructions at mozvr. com/#start

JavaScript Guru Guide 161

Profile for Future PLC

Technology Bookazine 2290 (Sampler)  

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

Technology Bookazine 2290 (Sampler)  

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