Tag Archiv: tutorials

Top Fireworks Tutorials for Web Design


Even though Adobe has officially discontinued Fireworks it still remains a very popular tool for UI design. Creative Cloud includes Fireworks CS6 as part of the bundle and it should be supported for a least a couple more years. Thus learning Fireworks can be one of the best decisions you make when it comes to mockup design and wireframing. These tutorials are aimed at complete beginners who want to bring Fireworks into their typical web design workflow.

Fireworks UI

intro to fireworks ui

Wireframing

fireworks wireframing how to

Mood Boards

moodboards web design fireworks

Vectorize Elements

howto vector design fireworks

Design Tools

video design tools fireworks

Fireworks for Web Design

basics of fireworks webdesign tutorial

jQuery Mobile in FW

fireworks for jquery mobile ui

Fireworks Design Workflow

fireworks workflow for web design

Brushed Metal Effect

brushed metal icloud icon fireworks

3D Text

3d text effect fireworks

Complex Vector Shapes

complex vector shapes fireworks

SVG with Fireworks

svg graphics in fireworks

Interactive Prototypes

interactive prototypes fireworks

Rocketship Icon

rocket ship icon fireworks

Fireworks Style Guide

fireworks howto design style guide

Advertisements:
ioDeck, a self-hosted and awesome PHP form generator.
Professional XHTML Admin Template ($15 Discount With The Code: WRD.)
SSLmatic – Cheap SSL Certificates (from $19.99/year)

The post Top Fireworks Tutorials for Web Design appeared first on Web Resources Depot.

Tutorials for Learning Google Material Design


Android Lollipop has become the standard method of design for smartphones powered by Google’s OS. This design follows the popular flat techniques to a T with slight drop shadows, but almost no gradients or bevels. It’s an easy technique to master but difficult to gain momentum.

These tutorials can teach even a complete novice how to design Android interfaces in Photoshop, Sketch, and Illustrator.

Tuts+ Material Intro

google material design introduction

Getting Started

getting started android material

Android Toolbar

material design toolbar

Floating Button

floating button ui design

Flat Tabs

flat android tabs tutorial

Sliding Nav

sliding drawer nav ui

Materialize CSS Framework

css materialize framework

Polymer Chat App

material polymer chat app

Lollipop Resources

free material lollipop resources

Free Swatches & Palettes

free swatches color palettes material design

Material Shadows

material design shadows tutorial

Material Design in Sketch

material design sketch tutorial

Sketch Android App Design

android apps in sketch howto

PS & AI Material Design

photoshop illustrator material design

Advertisements:
ioDeck, a self-hosted and awesome PHP form generator.
Professional XHTML Admin Template ($15 Discount With The Code: WRD.)
SSLmatic – Cheap SSL Certificates (from $19.99/year)

The post Tutorials for Learning Google Material Design appeared first on Web Resources Depot.

Making Your First HTML5 Game With Phaser

html5-game-phaser

Everybody loves classic games. How many of you remember the retro snake game from old Nokia phones? We sure do. This is why for this lesson we decided to recreate it using HTML5. There is a great open source game development framework called Phaser that we will use.

You will learn about sprites, game states and how to use the preload, create and update methods. Here’s what the final version of the game we’re building looks like:

Finished Game

Setup

Download a zip archive with the file structure of the game here. It contains all the image assets needed for the game but no code. We will be writing this next.

Now open index.html, add a title for your page and create links to all the JS files. Later, to play the game, just open this file in your browser.

<!doctype html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Snake</title>
    <script src="assets/js/phaser.min.js"></script>
    <script src="assets/js/menu.js"></script>
    <script src="assets/js/game.js"></script>
    <script src="assets/js/game_over.js"></script>
    <script src="assets/js/main.js"></script>
</head>
<body>

</body>
</html>

Your directory should look like this:

Directory Tree

Directory Tree

How the game is organized

Phaser games are organized around states. Think of states in Phaser as the different parts of a game. Here are the states of our game:

  • The Menu state. It is handled by menu.js, and only displays the start image. When it is clicked, the game transitions to the Game state.
  • Game state. It is handled by game.js. This is the actual play area of the game. You control the snake, eat apples and have lots of fun. When you die, you transition to the Game_Over state.
  • Game_Over state. It shows gameover.png and displays your last score. When it is clicked you transition to the Game state.

main.js is our main JavaScript file. This is the place where we will create a new game instance and add a menu state.

1. Loading an image

Right now, our game doesn’t do anything. Let’s code the Menu state, and make it display the title screen.

During the setup we included the Phaser library in our HTML file. This gives us a global object called Phaser. Through it, we can access the library’s methods and functions for building games.

Now we will use the global Phaser object, and create a new game instance. This is an object which represents our entire game. We will add the states to it.

main.js

var game;

// Create a new game instance 600px wide and 450px tall:
game = new Phaser.Game(600, 450, Phaser.AUTO, '');

// First parameter is how our state will be called.
// Second parameter is an object containing the needed methods for state functionality
game.state.add('Menu', Menu);

game.state.start('Menu');

Now we need to initialize our Menu state object. In menu.js define a new object and add the functions below. When the state is started, the preload function will be called first, loading all the needed assets for our game. Once preloading finishes, create gets called, initializing the playing field and everything we want on it:

menu.js

var Menu = {

    preload : function() {
        // Loading images is required so that later on we can create sprites based on the them.
        // The first argument is how our image will be refered to, 
        // the second one is the path to our file.
        game.load.image('menu', './assets/images/menu.png');
    },

    create: function () {
        // Add a sprite to your game, here the sprite will be the game's logo
        // Parameters are : X , Y , image name (see above) 
        this.add.sprite(0, 0, 'menu');
    }

};

Because of browser security restrictions, to start the game you’ll need a locally running web server. This page from the Phaser guidelines has plenty of options for all operating systems – here. In other words, it won’t work if you simply double click your index.html.

If everything has been done right, a page with the the start screen should appear in your browser.

Rendering an image

2. Drawing the snake

As we mentioned earlier, the Game state is where the actual game play happens. This is also the place where we will draw the snake. Like we did with the Menu state, we need to register the Game state with the global game object in main.js. Here is how your code should look like:

main.js

var game;

game = new Phaser.Game(600, 450, Phaser.AUTO, '');

game.state.add('Menu', Menu);

// Adding the Game state.
game.state.add('Game', Game);

game.state.start('Menu');

We’ll also want to add some code in menu.js to let us start the Game state when it is clicked. For this purpose, we will replace the sprite with a button. Adding a button is basically the same as adding a sprite, you only need to provide a function to be called when it is clicked. Here is the final menu.js code:

menu.js

var Menu = {

    preload : function() {
        // Load all the needed resources for the menu.
        game.load.image('menu', './assets/images/menu.png');
    },

    create: function () {

        // Add menu screen.
        // It will act as a button to start the game.
        this.add.button(0, 0, 'menu', this.startGame, this);

    },

    startGame: function () {

        // Change the state to the actual game.
        this.state.start('Game');

    }

};

We can now proceed with coding the Game state and drawing the snake. The structure is similar to the one of the Menu state.

game.js

var snake, apple, squareSize, score, speed,
    updateDelay, direction, new_direction,
    addNew, cursors, scoreTextValue, speedTextValue, 
    textStyle_Key, textStyle_Value;

var Game = {

    preload : function() {
        // Here we load all the needed resources for the level.
        // In our case, that's just two squares - one for the snake body and one for the apple.
        game.load.image('snake', './assets/images/snake.png');
        game.load.image('apple', './assets/images/apple.png');
    },

    create : function() {

        // By setting up global variables in the create function, we initialise them on game start.
        // We need them to be globally available so that the update function can alter them.

        snake = [];                     // This will work as a stack, containing the parts of our snake
        apple = {};                     // An object for the apple;
        squareSize = 15;                // The length of a side of the squares. Our image is 15x15 pixels.
        score = 0;                      // Game score.
        speed = 0;                      // Game speed.
        updateDelay = 0;                // A variable for control over update rates.
        direction = 'right';            // The direction of our snake.
        new_direction = null;           // A buffer to store the new direction into.
        addNew = false;                 // A variable used when an apple has been eaten.

        // Set up a Phaser controller for keyboard input.
        cursors = game.input.keyboard.createCursorKeys();

        game.stage.backgroundColor = '#061f27';

        // Generate the initial snake stack. Our snake will be 10 elements long.
        // Beginning at X=150 Y=150 and increasing the X on every iteration.
        for(var i = 0; i < 10; i++){
            snake[i] = game.add.sprite(150+i*squareSize, 150, 'snake');  // Parameters are (X coordinate, Y coordinate, image)
        }


        // Genereate the first apple.
        this.generateApple();


        // Add Text to top of game.
        textStyle_Key = { font: "bold 14px sans-serif", fill: "#46c0f9", align: "center" };
        textStyle_Value = { font: "bold 18px sans-serif", fill: "#fff", align: "center" };

        // Score.
        game.add.text(30, 20, "SCORE", textStyle_Key);
        scoreTextValue = game.add.text(90, 18, score.toString(), textStyle_Value);
        // Speed.
        game.add.text(500, 20, "SPEED", textStyle_Key);
        speedTextValue = game.add.text(558, 18, speed.toString(), textStyle_Value);

    },



    update: function() {
        // The update function is called constantly at a high rate (somewhere around 60fps),
        // updating the game field every time.
        // We are going to leave that one empty for now.
    },


    generateApple: function(){

        // Chose a random place on the grid.
        // X is between 0 and 585 (39*15)
        // Y is between 0 and 435 (29*15)

        var randomX = Math.floor(Math.random() * 40 ) * squareSize,
            randomY = Math.floor(Math.random() * 30 ) * squareSize;

        // Add a new apple.
        apple = game.add.sprite(randomX, randomY, 'apple');
    }

};

Here is how the snake and apple should look like:

Drawing the snake

3. Movement and control

To make the snake move we’ll be working in the update function of game.js.

First of all, we create event listeners for controlling the direction of the snake with the arrow keys.

The actual movement is a bit complex, since update is triggered at a very quick rate, and if we move the snake every time it’s called we would end up with one uncontrollably speedy reptile. To change this, we’ve set up an if statement that checks weather this is the 10th consecutive call of update() using a counter variable called updateDelay. 

If it really is the 10th call, we remove the last square of our snake (first element in the stack), give it new coordinates according to the current direction and place it in front of the head of the snake (top of the stack). Here’s how the code looks like:

update: function() {

    // Handle arrow key presses, while not allowing illegal direction changes that will kill the player.

    if (cursors.right.isDown && direction!='left')
    {
        new_direction = 'right';
    }
    else if (cursors.left.isDown && direction!='right')
    {
        new_direction = 'left';
    }
    else if (cursors.up.isDown && direction!='down')
    {
        new_direction = 'up';
    }
    else if (cursors.down.isDown && direction!='up')
    {
        new_direction = 'down';
    }


    // A formula to calculate game speed based on the score.
    // The higher the score, the higher the game speed, with a maximum of 10;
    speed = Math.min(10, Math.floor(score/5));
    // Update speed value on game screen.
    speedTextValue.text = '' + speed;

    // Since the update function of Phaser has an update rate of around 60 FPS,
    // we need to slow that down make the game playable.

    // Increase a counter on every update call.
    updateDelay++;

    // Do game stuff only if the counter is aliquot to (10 - the game speed).
    // The higher the speed, the more frequently this is fulfilled,
    // making the snake move faster.
    if (updateDelay % (10 - speed) == 0) {


        // Snake movement

        var firstCell = snake[snake.length - 1],
            lastCell = snake.shift(),
            oldLastCellx = lastCell.x,
            oldLastCelly = lastCell.y;

        // If a new direction has been chosen from the keyboard, make it the direction of the snake now.
        if(new_direction){
            direction = new_direction;
            new_direction = null;
        }


        // Change the last cell's coordinates relative to the head of the snake, according to the direction.

        if(direction == 'right'){

            lastCell.x = firstCell.x + 15;
            lastCell.y = firstCell.y;
        }
        else if(direction == 'left'){
            lastCell.x = firstCell.x - 15;
            lastCell.y = firstCell.y;
        }
        else if(direction == 'up'){
            lastCell.x = firstCell.x;
            lastCell.y = firstCell.y - 15;
        }
        else if(direction == 'down'){
            lastCell.x = firstCell.x;
            lastCell.y = firstCell.y + 15;
        }


        // Place the last cell in the front of the stack.
        // Mark it the first cell.

        snake.push(lastCell);
        firstCell = lastCell;

    }
    
}

Try and control the snake via the arrow keys on your keyboard.

Movement and control

 4. Collision detection

A game in which the snake is roaming freely in the playing field is not much fun. We need to detect when the snake comes in contact with a wall, an apple or itself. This is called collision detection.

This is usually done by using a physics engine, of which the Phaser framework supports a few. But they are too complex for a simple game like this. We will instead do our own collision detection by comparing coordinates.

In the update function, after the code for moving the snake, we call a number of methods. They will compare coordinates to tell us if a collision has occurred.

update: function() {

        // Snake movement
        // ...
        // End of snake movement

        // Increase length of snake if an apple had been eaten.
        // Create a block in the back of the snake with the old position of the previous last block
        // (it has moved now along with the rest of the snake).

        if(addNew){
            snake.unshift(game.add.sprite(oldLastCellx, oldLastCelly, 'snake'));
            addNew = false;
        }

        // Check for apple collision.
        this.appleCollision();

        // Check for collision with self. Parameter is the head of the snake.
        this.selfCollision(firstCell);

        // Check with collision with wall. Parameter is the head of the snake.
        this.wallCollision(firstCell);
    }


},

appleCollision: function() {

    // Check if any part of the snake is overlapping the apple.
    // This is needed if the apple spawns inside of the snake.
    for(var i = 0; i < snake.length; i++){
        if(snake[i].x == apple.x && snake[i].y == apple.y){

            // Next time the snake moves, a new block will be added to its length.
            addNew = true;

            // Destroy the old apple.
            apple.destroy();

            // Make a new one.
            this.generateApple();

            // Increase score.
            score++;

            // Refresh scoreboard.
            scoreTextValue.text = score.toString();

        }
    }

},

selfCollision: function(head) {

    // Check if the head of the snake overlaps with any part of the snake.
    for(var i = 0; i < snake.length - 1; i++){
        if(head.x == snake[i].x && head.y == snake[i].y){

            // If so, go to game over screen.
            game.state.start('Game_Over');
        }
    }

},

wallCollision: function(head) {

    // Check if the head of the snake is in the boundaries of the game field.

    if(head.x >= 600 || head.x < 0 || head.y >= 450 || head.y < 0){


        // If it's not in, we've hit a wall. Go to game over screen.
        game.state.start('Game_Over');
    }

}

When the snake collides with the apple we increase the score and the length of the snake. But when a collision with the wall or the snake body occurs, we should end the game. To do this, we need to make the Game_Over state. Again, we need to register it with main.js. Add this line near the bottom of that file:

main.js

game.state.add('Game_Over', Game_Over);

And the state itself:

game_over.js

var Game_Over = {

    preload : function() {
        // Load the needed image for this game screen.
        game.load.image('gameover', './assets/images/gameover.png');
    },

    create : function() {

        // Create button to start game like in Menu.
        this.add.button(0, 0, 'gameover', this.startGame, this);

        // Add text with information about the score from last game.
        game.add.text(235, 350, "LAST SCORE", { font: "bold 16px sans-serif", fill: "#46c0f9", align: "center"});
        game.add.text(350, 348, score.toString(), { font: "bold 20px sans-serif", fill: "#fff", align: "center" });

    },

    startGame: function () {

        // Change the state back to Game.
        this.state.start('Game');

    }

};

Collision detection

That’s it! Our game is ready!

Further reading

We hope that you liked our simple game and learned a lot while following our tutorial. There is much more to learn about Phaser:

Making Your First Webapp with React

creating-your-first-web-app-with-react

React has gained a lot of popularity recently and has attracted a large and active community. This results in a vast wealth of reusable components for it that will save you time when coding. The library itself encourages writing loosely coupled code that is modular and composable.

In this tutorial, I will show you how to create a small application and how to split it into discrete components that talk to each other. As a base, we will take the npm-driven website example from last month, but we’ll do it the React way. It is interesting to compare the results – the React version has a few more lines of code than the jQuery version, but we can both agree that it is much better organized.

What you need to know about React

  • It is a popular client-side library/framework for building user interfaces, which is developed and used by Facebook.
  • With it, you organize your application around discrete components, with each handling its own rendering and state. Components can be nested within each other.
  • React is fast because it minimizes the number of writes to the DOM (the slowest part of any client-side application).
  • The recommended way to write React code is by using JSX – an extension to JavaScript which presents components as HTML elements. JSX needs to be compiled to JS in order to work in browsers.
  • It hasn’t hit version 1.0 as of this writing, so there might be changes in the future.
  • We have a nice article with examples for learning react which you can check out. Also there is the official getting started guide here.

What we will be building

We will create a simple web app, which invites people to search for locations and to store them in their browsers’ localStorage. The locations will be presented on a Google Map with the help of the GMaps plugin. We will use Bootstrap with the Flatly theme for the interface. In the process, we will break the application down into logical components and make them talk to each other.

Running the demo

If you don’t want to read the entire tutorial, you can go ahead and download the source code from the download button above. To run it, you need to have Node.js and npm installed. Assuming that you have, here is what you need to do:

  1. Download the zip with the source code from the button above.
  2. Extract it to a folder somewhere on your computer.
  3. Open a new terminal (command prompt), and navigate to that folder.
  4. Execute npm install. This will download and install all dependencies that are needed.
  5. Execute npm run build. This will compile the react components down to a regular JavaScript file named compiled.js.
  6. Open index.html in your browser. You should see the app.

There is one more npm command that I’ve prepared for you to make your development easier:

npm run watch

This will compile the JSX code down to JavaScript and will continue to monitor it for changes. If you change a file, the code will be recompiled automatically for you. You can see these commands in the package.json file.

The source code is easy to follow and has plenty of comments, so for those of you who prefer to read the source, you can skip the rest of the article.

Setting things up

As I mentioned, the recommended way to write React code is by using a JavaScript extension called JSX, which needs to be transformed to JavaScript. There are a few tools that can do this but the one I recommend is reactify – a browserify transform. So in addition to compiling JSX down to JavaScript, you get access to the require() node.js call and with it the ability to install and use libraries from npm.

To set up reactify, browserify and the rest, run this command:

npm install browserify reactify watchify uglify-js react

To create a production ready and minified JavaScript file, which you can put online, run this command in your terminal:

NODE_ENV=production browserify -t [ reactify --es6 ] main.js | uglifyjs > compiled.min.js

Reactify supports a limited set of the new ES6 features with the --es6 flag, which I’ve used in the source code (you will see it in a moment).

While developing, use the following command:

watchify -v -d -t [ reactify --es6 ] main.js -o compiled.js

Watchify will monitor your files for changes and recompile your source code if it is needed. It also enables source maps, so you can use the Chrome Debugger to step through your code.

Great! You can now write React modules, require() npm libraries and even use some ES6 features. You are ready for writing some code!

The code

Here are the components that we will be writing:

  • App is the main component. It contains methods for the actions that can be performed by the user like searching, adding a location to favorites and more. The other components are nested inside it.
  • CurrentLocation presents the currently visited address in the map. Addresses can be added or removed from favorites by clicking the star icon.
  • LocationList renders all favorite locations. It creates a LocationItem for each.
  • LocationItem is an individual location. When it is clicked, its corresponding address is searched for and highlighted in the map.
  • Map integrates with the GMaps library, and renders a map from Google Maps.
  • Search is a component that wraps around the search form. When it is submitted, a search for the location is triggered.
Components Breakdown

Components Breakdown

App.js

First up is App. In addition to the lifecycle methods that React requires, it has a few additional ones that reflect the main actions that can be performed by the user like adding and removing an address from favorites and searching. Notice that I am using the shorter ES6 syntax for defining functions in objects.

var React = require('react');

var Search = require('./Search');
var Map = require('./Map');
var CurrentLocation = require('./CurrentLocation');
var LocationList = require('./LocationList');


var App = React.createClass({

	getInitialState(){

		// Extract the favorite locations from local storage

		var favorites = [];

		if(localStorage.favorites){
			favorites = JSON.parse(localStorage.favorites);
		}

		// Nobody would get mad if we center it on Paris by default

		return {
			favorites: favorites,
			currentAddress: 'Paris, France',
			mapCoordinates: {
				lat: 48.856614,
				lng: 2.3522219
			}
		};
	},

	toggleFavorite(address){

		if(this.isAddressInFavorites(address)){
			this.removeFromFavorites(address);
		}
		else{
			this.addToFavorites(address);
		}

	},

	addToFavorites(address){

		var favorites = this.state.favorites;

		favorites.push({
			address: address,
			timestamp: Date.now()
		});

		this.setState({
			favorites: favorites
		});

		localStorage.favorites = JSON.stringify(favorites);
	},

	removeFromFavorites(address){

		var favorites = this.state.favorites;
		var index = -1;

		for(var i = 0; i < favorites.length; i++){

			if(favorites[i].address == address){
				index = i;
				break;
			}

		}

		// If it was found, remove it from the favorites array

		if(index !== -1){
			
			favorites.splice(index, 1);

			this.setState({
				favorites: favorites
			});

			localStorage.favorites = JSON.stringify(favorites);
		}

	},

	isAddressInFavorites(address){

		var favorites = this.state.favorites;

		for(var i = 0; i < favorites.length; i++){

			if(favorites[i].address == address){
				return true;
			}

		}

		return false;
	},

	searchForAddress(address){
		
		var self = this;

		// We will use GMaps' geocode functionality,
		// which is built on top of the Google Maps API

		GMaps.geocode({
			address: address,
			callback: function(results, status) {

				if (status !== 'OK') return;

				var latlng = results[0].geometry.location;

				self.setState({
					currentAddress: results[0].formatted_address,
					mapCoordinates: {
						lat: latlng.lat(),
						lng: latlng.lng()
					}
				});

			}
		});

	},

	render(){

		return (

			<div>
				<h1>Your Google Maps Locations</h1>

				<Search onSearch={this.searchForAddress} />

				<Map lat={this.state.mapCoordinates.lat} lng={this.state.mapCoordinates.lng} />

				<CurrentLocation address={this.state.currentAddress} 
					favorite={this.isAddressInFavorites(this.state.currentAddress)} 
					onFavoriteToggle={this.toggleFavorite} />

				<LocationList locations={this.state.favorites} activeLocationAddress={this.state.currentAddress} 
					onClick={this.searchForAddress} />

			</div>

		);
	}

});

module.exports = App;

In the render method, we initialize the other components. Each component receives only the data that it needs to get its job done, as attributes. In some places, we also pass methods which the child components will call, which is a good way for components to communicate while keeping them isolated from one another.

CurrentLocation.js

Next is CurrentLocation. This component presents the address of the currently displayed location in an H4 tag, and a clickable star icon. When the icon is clicked, the App’s toggleFavorite method is called.

var React = require('react');

var CurrentLocation = React.createClass({

	toggleFavorite(){
		this.props.onFavoriteToggle(this.props.address);
	},

	render(){

		var starClassName = "glyphicon glyphicon-star-empty";

		if(this.props.favorite){
			starClassName = "glyphicon glyphicon-star";
		}

		return (
			<div className="col-xs-12 col-md-6 col-md-offset-3 current-location">
				<h4 id="save-location">{this.props.address}</h4>
				<span className={starClassName} onClick={this.toggleFavorite} aria-hidden="true"></span>
			</div>
		);
	}

});

module.exports = CurrentLocation;

LocationList.js

LocationList takes the array with favorite locations that was passed to it, creates a LocationItem object for each and presents it in a Bootstrap list group.

var React = require('react');
var LocationItem = require('./LocationItem');

var LocationList = React.createClass({

	render(){

		var self = this;

		var locations = this.props.locations.map(function(l){

			var active = self.props.activeLocationAddress == l.address;

			// Notice that we are passing the onClick callback of this
			// LocationList to each LocationItem.

			return <LocationItem address={l.address} timestamp={l.timestamp} 
					active={active} onClick={self.props.onClick} />
		});

		if(!locations.length){
			return null;
		}

		return (
			<div className="list-group col-xs-12 col-md-6 col-md-offset-3">
				<span className="list-group-item active">Saved Locations</span>
				{locations}
			</div>
		)

	}

});

module.exports = LocationList;

LocationItem.js

LocationItem represents an individual favorite location. It uses the moment library to calculate the relative time since the location was added as a favorite.

var React = require('react');
var LocationItem = require('./LocationItem');
var moment = require('moment');

var LocationItem = React.createClass({

	handleClick(){
		this.props.onClick(this.props.address);
	},

	render(){

		var cn = "list-group-item";

		if(this.props.active){
			cn += " active-location";
		}

		return (
			<a className={cn} onClick={this.handleClick}>
				{this.props.address}
				<span className="createdAt">{ moment(this.props.timestamp).fromNow() }</span>
				<span className="glyphicon glyphicon-menu-right"></span>
			</a>
		)

	}

});

module.exports = LocationItem;

Map.js

Map is a special component. It wraps the Gmaps plugin, which is not a React component by itself. By hooking to the Map’s componentDidUpdate method, we can initialize a real map inside the #map div whenever the displayed location is changed.

var React = require('react');

var Map = React.createClass({

	componentDidMount(){

		// Only componentDidMount is called when the component is first added to
		// the page. This is why we are calling the following method manually. 
		// This makes sure that our map initialization code is run the first time.

		this.componentDidUpdate();
	},

	componentDidUpdate(){

		if(this.lastLat == this.props.lat && this.lastLng == this.props.lng){

			// The map has already been initialized at this address.
			// Return from this method so that we don't reinitialize it
			// (and cause it to flicker).

			return;
		}

		this.lastLat = this.props.lat;
		this.lastLng = this.props.lng

		var map = new GMaps({
			el: '#map',
			lat: this.props.lat,
			lng: this.props.lng
		});

		// Adding a marker to the location we are showing
		
		map.addMarker({
			lat: this.props.lat,
			lng: this.props.lng
		});
	},

	render(){

		return (
			<div className="map-holder">
				<p>Loading...</p>
				<div id="map"></div>
			</div>
		);
	}

});

module.exports = Map;

Search.js

The Search component consists of a Bootstrap form with an input group. When the form is submitted the App’s searchForAddress method is called.

var React = require('react');

var Search = React.createClass({

	getInitialState() {
		return { value: '' };
	},

	handleChange(event) {
		this.setState({value: event.target.value});
	},

	handleSubmit(event){
		
		event.preventDefault();
		
		// When the form is submitted, call the onSearch callback that is passed to the component

		this.props.onSearch(this.state.value);

		// Unfocus the text input field
		this.getDOMNode().querySelector('input').blur();
	},

	render() {

		return (
			<form id="geocoding_form" className="form-horizontal" onSubmit={this.handleSubmit}>
				<div className="form-group">
					<div className="col-xs-12 col-md-6 col-md-offset-3">
						<div className="input-group">
							<input type="text" className="form-control" id="address" placeholder="Find a location..." 
							value={this.state.value} onChange={this.handleChange} />
							<span className="input-group-btn">
								<span className="glyphicon glyphicon-search" aria-hidden="true"></span>
							</span>
						</div>
					</div>
				</div>
			</form>
		);

	}
});

module.exports = Search;

main.js

All that is left is to add the App component to the page. I am adding it to a container div with the #main id (you can see this element in index.html in the downloadable zip file).

var React = require('react');
var App = require('./components/App');

React.render(
  <App />,
  document.getElementById('main')
);

In addition to these files, I have included the GMaps library and the Google Maps JavaScript API on which it depends, as <script> tags in index.html.

We’re done!

I hope that this tutorial gave you a better understanding of how to structure React applications. There is much more you can do with the library, including server-side rendering, which we hope to cover in the future.

Smartphone Remote Control with Node.js and Socket.io

smartphone-remote-control-for-your-presentation

Wouldn’t it be cool to use your smartphone as a remote control? It turns out it is not difficult at all! You don’t even need to know how to write native mobile apps – your phone has a fully capable web browser with support for web sockets, which opens a lot of possibilities. In this short tutorial, we are going to use Node.js and Socket.io to remotely control a presentation that is running on your laptop with your phone.

There are a lot of cool HTML5 presentation libraries out there and it would be a waste of effort to create this functionality from scratch. This is why we will be using Reveal.js – it will handle animations and transitions between slides, as well as support for keyboard and touch events.

We won’t be making a dedicated remote control interface. Instead, we will synchronize the presentation that is opened on your phone with that on your computer using websockets. This will allow you not only to control the presentation, but see its mobile version on your phone, which will help you keep track of the current slide.

The Idea

The technique we are going to use is very simple. Reveal.js puts the current slide number in the URL as a hash (e.g. http://example.com/#/1). We will send this hash to all other connected devices, which will transition them to the new slide automatically. This will make it possible for people to just open the URL in a browser and sabotaging your presentation, so we will require all devices to enter a pass code before connecting.

It is worth mentioning that Reveal.js already has an API, so we could have used that to synchronize the two presentations. But the hash change technique is simpler and will work with any presentation library, so we chose to go with it instead.

Our slideshow

Our slideshow

Running our Example

You can run this example locally, or by deploying it to a hosting provider with node.js support like Heroku. Running it locally is easier, but you must have node.js and npm installed. Running it on Heroku requires you to have the heroku toolbelt installed and signing up for an account.

To run our code locally:

  1. Download the code from the button near the beginning of the article.
  2. Make sure you have node.js installed. If needed, install it.
  3. Unzip the archive you downloaded to a folder.
  4. Open a terminal and cd to the folder.
  5. Run npm install to install the required libraries
  6. Run node app.js to start the presentation
  7. Open http://localhost:8080 on your computer and enter your pass key (by default it is “kittens“).
  8. Open http://<your computer’s local ip address> on your phone and enter the same pass key.
  9. Have fun!

To run the code on Heroku:

  1. Download the code from the button near the beginning of the article.
  2. Unzip it to a folder.
  3. Open a terminal and cd to the folder.
  4. Create a git repository, and commit.
  5. Create a new Heroku App
  6. Run git push heroku master.
  7. Visit the URL of the app on every device you want to connect. The default pass key is “kittens”.

Read more about deploying node.js apps to heroku here. If you use a different cloud hosting provider, the last three steps will be different.

The Code

But enough talk, let’s see the code! There are only two JavaScript files – app.js for the server side, and script.js for the browser. You can run the app in Node.js 0.10+ or in io.js.

For the backend, we use express and socket.io. It’s main responsibility is listening for and responding to socket.io events. With express.static, we serve the files in the public folder to the world. We have a public/index.html file which contains the code for the presentation. It is served automatically by express.static, so we don’t need a “/” route.

app.js

// This is the server-side file of our mobile remote controller app.
// It initializes socket.io and a new express instance.
// Start it by running 'node app.js' from your terminal.


// Creating an express server

var express = require('express'),
	app = express();

// This is needed if the app is run on heroku and other cloud providers:

var port = process.env.PORT || 8080;

// Initialize a new socket.io object. It is bound to 
// the express app, which allows them to coexist.

var io = require('socket.io').listen(app.listen(port));


// App Configuration

// Make the files in the public folder available to the world
app.use(express.static(__dirname + '/public'));


// This is a secret key that prevents others from opening your presentation
// and controlling it. Change it to something that only you know.

var secret = 'kittens';

// Initialize a new socket.io application

var presentation = io.on('connection', function (socket) {

	// A new client has come online. Check the secret key and 
	// emit a "granted" or "denied" message.

	socket.on('load', function(data){

		socket.emit('access', {
			access: (data.key === secret ? "granted" : "denied")
		});

	});

	// Clients send the 'slide-changed' message whenever they navigate to a new slide.

	socket.on('slide-changed', function(data){

		// Check the secret key again

		if(data.key === secret) {

			// Tell all connected clients to navigate to the new slide
			
			presentation.emit('navigate', {
				hash: data.hash
			});
		}
	});
});

console.log('Your presentation is running on http://localhost:' + port);

And here is our JavaScript for the front-end, which listens for hashchange events and sends socket.io messages to the server.

public/assets/js/script.js

$(function() {

	// Apply a CSS filter with our blur class (see our assets/css/styles.css)
	
	var blurredElements = $('.homebanner, div.reveal').addClass('blur');

	// Initialize the Reveal.js library with the default config options
	// See more here https://github.com/hakimel/reveal.js#configuration

	Reveal.initialize({
		history: true		// Every slide will change the URL
	});

	// Connect to the socket

	var socket = io();

	// Variable initialization

	var form = $('form.login'),
		secretTextBox = form.find('input[type=text]');

	var key = "", animationTimeout;

	// When the page is loaded it asks you for a key and sends it to the server

	form.submit(function(e){

		e.preventDefault();

		key = secretTextBox.val().trim();

		// If there is a key, send it to the server-side
		// through the socket.io channel with a 'load' event.

		if(key.length) {
			socket.emit('load', {
				key: key
			});
		}

	});

	// The server will either grant or deny access, depending on the secret key

	socket.on('access', function(data){

		// Check if we have "granted" access.
		// If we do, we can continue with the presentation.

		if(data.access === "granted") {

			// Unblur everything
			blurredElements.removeClass('blurred');

			form.hide();

			var ignore = false;

			$(window).on('hashchange', function(){

				// Notify other clients that we have navigated to a new slide
				// by sending the "slide-changed" message to socket.io

				if(ignore){
					// You will learn more about "ignore" in a bit
					return;
				}

				var hash = window.location.hash;

				socket.emit('slide-changed', {
					hash: hash,
					key: key
				});
			});

			socket.on('navigate', function(data){
	
				// Another device has changed its slide. Change it in this browser, too:

				window.location.hash = data.hash;

				// The "ignore" variable stops the hash change from
				// triggering our hashchange handler above and sending
				// us into a never-ending cycle.

				ignore = true;

				setInterval(function () {
					ignore = false;
				},100);

			});

		}
		else {

			// Wrong secret key

			clearTimeout(animationTimeout);

			// Addding the "animation" class triggers the CSS keyframe
			// animation that shakes the text input.

			secretTextBox.addClass('denied animation');
			
			animationTimeout = setTimeout(function(){
				secretTextBox.removeClass('animation');
			}, 1000);

			form.show();
		}

	});

});

It’s Slideshow Time!

With this our smartphone remote control is ready! We hope that you find our experiment useful and have fun playing with it.

Quick Tip: Add Keyboard Shortcuts To Your Web App

quick-tip-add-keyboard-shortcuts-to-your-web-app

We power users love our keyboard shortcuts. We use them everywhere – in our code editor, in Photoshop, in gmail. And we hate it when we hit Ctrl+S in a web app, only to see our browser offering to download it. Adding shortcuts to your application is not hard at all. In this quick tip, we will show you how to do it, by using Mousetrap.js.

1. Single Keys

Single keys are easy. You can do it with a simple event listener for keypress on the document object. But with Mousetrap, it is even better.

After hitting the run button, focus the editor by clicking on it. Otherwise, it won’t register your key presses and the demo won’t work.

(Play with our code editor on Tutorialzine.com)

2. Alternative Symbols

Mousetrap shines when listening for more complex key combinations like capital letters and special symbols.

(Play with our code editor on Tutorialzine.com)

3. Key combinations

Combinations that involve the Control key are equally easy (see the next example for how to listen for both Control and the OS X Command key).

(Play with our code editor on Tutorialzine.com)

4. Multiple Combinations

Passing an array instead of a string lets you listen for multiple key combinations at once. This is useful when you have to listen for combinations which involve the Control (for Windows and Linux) and Command (for Mac) keys.

(Play with our code editor on Tutorialzine.com)

5. Sequences

This type of shortcuts are very powerful, and are used in apps like gmail. Works with array keys as well!

(Play with our code editor on Tutorialzine.com)

Conclusion

This was our quick tip on keyboard shortcuts. If you’ve used keyboard hotkeys before, or are brave enough to experiment with them in your next project, do share the results with us in the comments below.

Making a Single Page App Without a Framework

making-a-simple-page-app-without-a-framework

The idea behind single page applications (SPA) is to create a smooth browsing experience like the one found in native desktop apps. All of the necessary code for the page is loaded only once and its content gets changed dynamically through JavaScript. If everything is done right the page shouldn’t ever reload, unless the user refreshes it manually.

There are many frameworks for single page applications out there. First we had Backbone, then Angular, now React. It takes a lot of work to constantly learn and re-learn things (not to mention having to support old code you’ve written in a long forgotten framework). In some situations, like when your app idea isn’t too complex, it is actually not that hard to create a single page app without using any external frameworks. Here is how to do it.

Note: To run this example after downloading it, you need a locally running webserver like Apache. Our demo uses AJAX so it will not work if you simply double-click index.html for security reasons.

The Idea

We will not be using a framework, but we will be using two libraries – jQuery for DOM manipulation and event handling, and Handlebars for templates. You can easily omit these if you wish to be even more minimal, but we will use them for the productivity gains they provide. They will be here long after the hip client-side framework of the day is forgotten.

The app that we will be building fetches product data from a JSON file, and displays it by rendering a grid of products with Handlebars. After the initial load, our app will stay on the same URL and listen for changes to the hash part with the hashchange event. To navigate around the app, we will simply change the hash. This has the added benefit that browser history will just work without extra effort on our part.

The Setup

Our project's folder

Our project’s folder

As you can see there isn’t much in our project folder. We have the regular web app setup – HTML, JavaScript and CSS files, accompanied by a products.json containing data about the products in our shop and a folder with images of the products.

The Products JSON

The .json file is used to store data about each product for our SPA. This file can easily be replaced by a server-side script to fetch data from a real database.

products.json

[
  {
    "id": 1,
    "name": "Sony Xperia Z3",
    "price": 899,
    "specs": {
      "manufacturer": "Sony",
      "storage": 16,
      "os": "Android",
      "camera": 15
    },
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique ipsum in efficitur pharetra. Maecenas luctus ante in neque maximus, sed viverra sem posuere. Vestibulum lectus nisi, laoreet vel suscipit nec, feugiat at odio. Etiam eget tellus arcu.",
    "rating": 4,
    "image": {
      "small": "/images/sony-xperia-z3.jpg",
      "large": "/images/sony-xperia-z3-large.jpg"
    }
  },
  {
    "id": 2,
    "name": "Iphone 6",
    "price": 899,
    "specs": {
      "manufacturer": "Apple",
      "storage": 16,
      "os": "iOS",
      "camera": 8
    },
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique ipsum in efficitur pharetra. Maecenas luctus ante in neque maximus, sed viverra sem posuere. Vestibulum lectus nisi, laoreet vel suscipit nec, feugiat at odio. Etiam eget tellus arcu.",
    "rating": 4,
    "image": {
      "small": "/images/iphone6.jpg",
      "large": "/images/iphone6-large.jpg"
    }
  }
]

The HTML

In our html file we have several divs sharing the same class “page”. Those are the different pages (or as they are called in SPA – states) our app can show. However, on page load all of these are hidden via CSS and need the JavaScript to show them. The idea is that only one page can be visible at a time and our script is the one to decide which one it is.

index.html

<div class="main-content">

	<div class="all-products page">

		<h3>Our products</h3>

		<div class="filters">
			<form>
				Checkboxes here
			</form>
		</div>

    <ul class="products-list">
      <script id="products-template" type="x-handlebars-template">​
        {{#each this}}
          <li data-index="{{id}}">
            <a href="#" class="product-photo"><img src="{{image.small}}" height="130" alt="{{name}}"/></a>
            <h2><a href="#"> {{name}} </a></h2>
            <ul class="product-description">
              <li><span>Manufacturer: </span>{{specs.manufacturer}}</li>
              <li><span>Storage: </span>{{specs.storage}} GB</li>
              <li><span>OS: </span>{{specs.os}}</li>
              <li><span>Camera: </span>{{specs.camera}} Mpx</li>
            </ul>
            <button>Buy Now!</button>
            <p class="product-price">{{price}}$</p>
            <div class="highlight"></div>
          </li>
        {{/each}}
      </script>

    </ul>

	</div>


	<div class="single-product page">

		<div class="overlay"></div>

		<div class="preview-large">
			<h3>Single product view</h3>
			<img src=""/>
			<p></p>

			<span class="close">&times;</span>
		</div>

	</div>

	<div class="error page">
		<h3>Sorry, something went wrong :(</h3>
	</div>

</div>

We have three pages: all-products (the product listing), single-product (the individual product page) and error.

The all-products page consists of a title, a form containing checkboxes for filtering and a <ul> tag with the class “products-list”. This list is generated with handlebars using the data stored in products.json, creating a <li> for each entry in the json. Here is the result:

The Products

The Products

Single-product is used to show information about only one product. It is empty and hidden on page load. When the appropriate hash address is reached, it is populated with product data and shown.

The error page consist of only an error message to let you know when you’ve reached a faulty address.

The JavaScript Code

First, lets make a quick preview of the functions and what they do.

script.js

$(function () {

	checkboxes.click(function () {
		// The checkboxes in our app serve the purpose of filters.
		// Here on every click we add or remove filtering criteria from a filters object.

		// Then we call this function which writes the filtering criteria in the url hash.
		createQueryHash(filters);
	});



	$.getJSON( "products.json", function( data ) {
		// Get data about our products from products.json.

		// Call a function that will turn that data into HTML.
		generateAllProductsHTML(data);

		// Manually trigger a hashchange to start the app.
		$(window).trigger('hashchange');
	});


	$(window).on('hashchange', function(){
		// On every hash change the render function is called with the new hash.
		// This is how the navigation of our app happens.
		render(window.location.hash);
	});


	function render(url) {
		// This function decides what type of page to show 
		// depending on the current url hash value.
	}


	function generateAllProductsHTML(data){
		// Uses Handlebars to create a list of products using the provided data.
		// This function is called only once on page load.
	}


	function renderProductsPage(data){
		// Hides and shows products in the All Products Page depending on the data it recieves.
	}


	function renderSingleProductPage(index, data){
		// Shows the Single Product Page with appropriate data.
	}

	function renderFilterResults(filters, products){
		// Crates an object with filtered products and passes it to renderProductsPage.
		renderProductsPage(results);
	}

	function renderErrorPage(){
		// Shows the error page.
	}

	
	function createQueryHash(filters){
		// Get the filters object, turn it into a string and write it into the hash.
	}

});

Remember that the concept of SPA is to not have any loads going on while the app is running. That’s why after the initial page load we want to stay on the same page, where everything we need has already been fetched by the server.

However, we still want to be able to go somewhere in the app and, for example, copy the url and send it to a friend. If we never change the app’s address they will just get the app the way it looks in the beginning, not what you wanted to share with them. To solve this problem we write information about the state of the app in the url as #hash. Hashes don’t cause the page to reload and are easily accessible and manipulated.

On every hashchange we call this:

function render(url) {

		// Get the keyword from the url.
		var temp = url.split('/')[0];

		// Hide whatever page is currently shown.
		$('.main-content .page').removeClass('visible');


		var map = {

			// The Homepage.
			'': function() {

				// Clear the filters object, uncheck all checkboxes, show all the products
				filters = {};
				checkboxes.prop('checked',false);

				renderProductsPage(products);
			},

			// Single Products page.
			'#product': function() {

				// Get the index of which product we want to show and call the appropriate function.
				var index = url.split('#product/')[1].trim();

				renderSingleProductPage(index, products);
			},

			// Page with filtered products
			'#filter': function() {

				// Grab the string after the '#filter/' keyword. Call the filtering function.
				url = url.split('#filter/')[1].trim();

				// Try and parse the filters object from the query string.
				try {
					filters = JSON.parse(url);
				}
				// If it isn't a valid json, go back to homepage ( the rest of the code won't be executed ).
				catch(err) {
					window.location.hash = '#';
				}

				renderFilterResults(filters, products);
			}

		};

		// Execute the needed function depending on the url keyword (stored in temp).
		if(map[temp]){
			map[temp]();
		}
		// If the keyword isn't listed in the above - render the error page.
		else {
			renderErrorPage();
		}

	}

This function takes into consideration the beginning string of our hash, decides what page needs to be shown and calls the according functions.

For example if the hash is ‘#filter/{“storage”:[“16″],”camera”:[“5″]}’, our codeword is ‘#filter’. Now the render function knows we want to see a page with the filtered products list and will navigate us to it. The rest of the hash will be parsed into an object and a page with the filtered products will be shown, changing the state of the app.

This is called only once on start up and turns our JSON into actual HTML5 content via handlebars.

function generateAllProductsHTML(data){

    var list = $('.all-products .products-list');

    var theTemplateScript = $("#products-template").html();
    //Compile the template​
    var theTemplate = Handlebars.compile (theTemplateScript);
    list.append (theTemplate(data));


    // Each products has a data-index attribute.
    // On click change the url hash to open up a preview for this product only.
    // Remember: every hashchange triggers the render function.
    list.find('li').on('click', function (e) {
      e.preventDefault();

      var productIndex = $(this).data('index');

      window.location.hash = 'product/' + productIndex;
    })
  }

This function receives an object containing only those products we want to show and displays them.

function renderProductsPage(data){

    var page = $('.all-products'),
      allProducts = $('.all-products .products-list > li');

    // Hide all the products in the products list.
    allProducts.addClass('hidden');

    // Iterate over all of the products.
    // If their ID is somewhere in the data object remove the hidden class to reveal them.
    allProducts.each(function () {

      var that = $(this);

      data.forEach(function (item) {
        if(that.data('index') == item.id){
          that.removeClass('hidden');
        }
      });
    });

    // Show the page itself.
    // (the render function hides all pages so we need to show the one we want).
    page.addClass('visible');

  }

Shows the single product preview page:

function renderSingleProductPage(index, data){

    var page = $('.single-product'),
      container = $('.preview-large');

    // Find the wanted product by iterating the data object and searching for the chosen index.
    if(data.length){
      data.forEach(function (item) {
        if(item.id == index){
          // Populate '.preview-large' with the chosen product's data.
          container.find('h3').text(item.name);
          container.find('img').attr('src', item.image.large);
          container.find('p').text(item.description);
        }
      });
    }

    // Show the page.
    page.addClass('visible');

  }

Takes all the products, filters them based on our query and returns an object with the results.

function renderFilterResults(filters, products){

      // This array contains all the possible filter criteria.
    var criteria = ['manufacturer','storage','os','camera'],
      results = [],
      isFiltered = false;

    // Uncheck all the checkboxes.
    // We will be checking them again one by one.
    checkboxes.prop('checked', false);


    criteria.forEach(function (c) {

      // Check if each of the possible filter criteria is actually in the filters object.
      if(filters[c] && filters[c].length){


        // After we've filtered the products once, we want to keep filtering them.
        // That's why we make the object we search in (products) to equal the one with the results.
        // Then the results array is cleared, so it can be filled with the newly filtered data.
        if(isFiltered){
          products = results;
          results = [];
        }


        // In these nested 'for loops' we will iterate over the filters and the products
        // and check if they contain the same values (the ones we are filtering by).

        // Iterate over the entries inside filters.criteria (remember each criteria contains an array).
        filters[c].forEach(function (filter) {

          // Iterate over the products.
          products.forEach(function (item){

            // If the product has the same specification value as the one in the filter
            // push it inside the results array and mark the isFiltered flag true.

            if(typeof item.specs[c] == 'number'){
              if(item.specs[c] == filter){
                results.push(item);
                isFiltered = true;
              }
            }

            if(typeof item.specs[c] == 'string'){
              if(item.specs[c].toLowerCase().indexOf(filter) != -1){
                results.push(item);
                isFiltered = true;
              }
            }

          });

          // Here we can make the checkboxes representing the filters true,
          // keeping the app up to date.
          if(c && filter){
            $('input[name='+c+'][value='+filter+']').prop('checked',true);
          }
        });
      }

    });

    // Call the renderProductsPage.
    // As it's argument give the object with filtered products.
    renderProductsPage(results);
  }

Shows the error state:

function renderErrorPage(){
    var page = $('.error');
    page.addClass('visible');
  }

Stringifies the filters object and writes it into the hash.

function createQueryHash(filters){

    // Here we check if filters isn't empty.
    if(!$.isEmptyObject(filters)){
      // Stringify the object via JSON.stringify and write it after the '#filter' keyword.
      window.location.hash = '#filter/' + JSON.stringify(filters);
    }
    else{
      // If it's empty change the hash to '#' (the homepage).
      window.location.hash = '#';
    }

  }

Conclusion

Single page applications are perfect when you want give your project a more dynamic and fluid feel, and with the help of some clever design choices you can offer your visitors a polished, pleasant experience.

Tutorial: Making a Shoutbox with PHP and jQuery

shoutbox-php-jquery

In this tutorial, we are going to build a shout box with PHP and jQuery, which allows visitors of your website to leave short comments to one another. Shouts will be stored on the server as files, no database like MySQL will be required. We are going to use two PHP libraries to make things easier – Flywheel for storing the shouts as json files and RelativeTime for creating human readable relative time stamps. We will be using Composer to install these libraries.

On the client side, we are using plain jQuery code, and the Emoji One library, which is a free project and library for adding pretty emojis to web apps. Let’s begin!

Running the shoutbox

You can grab the source code from the download button above. It has plenty of comments and is easy to follow. To run it, simply upload it to your web hosting space or add it to the apache htdocs folder if you run something like XAMPP or MAMP. Then, open http://localhost in your browser (or your website, if you uploaded it to your hosting space). Here are a few things to look for:

  • The zip files already contains the dependencies, so you don’t need to install Composer. This makes it easy to get started with the code – simply upload it and use it!
  • Make sure that the data/shouts directory exists and is writable. Otherwise you will see errors in your log file and no shouts will be stored. You might need to chmod it to 777 if you keep seeing errors.

The HTML

Let’s start with index.html. It is a regular HTML5 document, which includes our JavaScript libraries, scripts and stylesheets. Here are the parts relevant to the shoutbox:

index.html

<div class="shoutbox">
    
    <h1>Shout box <img src='./assets/img/refresh.png'/></h1>
    
    <ul class="shoutbox-content"></ul>
    
    <div class="shoutbox-form">
        <h2>Write a message <span>×</span></h2>
        
        <form action="./publish.php" method="post">
            <label for="shoutbox-name">nickname </label> <input type="text" id="shoutbox-name" name="name"/>
            <label class="shoutbox-comment-label" for="shoutbox-comment">message </label> <textarea id="shoutbox-comment" name="comment" maxlength='240'></textarea>
            <input type="submit" value="Shout!"/>
        </form>
    </div>
    
</div>

With JavaScript we will insert the published shouts into the <ul> element. The form is hidden by default, and only revealed when the “Write a message” header is clicked.

Shoutbox with PHP and jQuery

Shoutbox with PHP and jQuery

The JavaScript Code

And here is our script.js, which makes the above HTML work:

assets/js/script.js

$(function(){

    // Storing some elements in variables for a cleaner code base

    var refreshButton = $('h1 img'),
        shoutboxForm = $('.shoutbox-form'),
        form = shoutboxForm.find('form'),
        closeForm = shoutboxForm.find('h2 span'),
        nameElement = form.find('#shoutbox-name'),
        commentElement = form.find('#shoutbox-comment'),
        ul = $('ul.shoutbox-content');

    // Replace :) with emoji icons:
    emojione.ascii = true;

    // Load the comments.
    load();
    
    // On form submit, if everything is filled in, publish the shout to the database
    
    var canPostComment = true;

    form.submit(function(e){
        e.preventDefault();

        if(!canPostComment) return;
        
        var name = nameElement.val().trim();
        var comment = commentElement.val().trim();

        if(name.length && comment.length && comment.length < 240) {
        
            publish(name, comment);

            // Prevent new shouts from being published

            canPostComment = false;

            // Allow a new comment to be posted after 5 seconds

            setTimeout(function(){
                canPostComment = true;
            }, 5000);

        }

    });
    
    // Toggle the visibility of the form.
    
    shoutboxForm.on('click', 'h2', function(e){
        
        if(form.is(':visible')) {
            formClose();
        }
        else {
            formOpen();
        }
        
    });
    
    // Clicking on the REPLY button writes the name of the person you want to reply to into the textbox.
    
    ul.on('click', '.shoutbox-comment-reply', function(e){
        
        var replyName = $(this).data('name');
        
        formOpen();
        commentElement.val('@'+replyName+' ').focus();

    });
    
    // Clicking the refresh button will force the load function
    
    var canReload = true;

    refreshButton.click(function(){

        if(!canReload) return false;
        
        load();
        canReload = false;

        // Allow additional reloads after 2 seconds
        setTimeout(function(){
            canReload = true;
        }, 2000);
    });

    // Automatically refresh the shouts every 20 seconds
    setInterval(load,20000);


    function formOpen(){
        
        if(form.is(':visible')) return;

        form.slideDown();
        closeForm.fadeIn();
    }

    function formClose(){

        if(!form.is(':visible')) return;

        form.slideUp();
        closeForm.fadeOut();
    }

    // Store the shout in the database
    
    function publish(name,comment){
    
        $.post('publish.php', {name: name, comment: comment}, function(){
            nameElement.val("");
            commentElement.val("");
            load();
        });

    }
    
    // Fetch the latest shouts
    
    function load(){
        $.getJSON('./load.php', function(data) {
            appendComments(data);
        });
    }
    
    // Render an array of shouts as HTML
    
    function appendComments(data) {

        ul.empty();

        data.forEach(function(d){
            ul.append('<li>'+
                '<span class="shoutbox-username">' + d.name + '</span>'+
                '<p class="shoutbox-comment">' + emojione.toImage(d.text) + '</p>'+
                '<div class="shoutbox-comment-details"><span class="shoutbox-comment-reply" data-name="' + d.name + '">REPLY</span>'+
                '<span class="shoutbox-comment-ago">' + d.timeAgo + '</span></div>'+
            '</li>');
        });

    }

});

The Emoji One library has version for both JavaScript and PHP. In the appendComments method, we use the emojione.toImage() function to convert all typed-out smileys into emoji. See all functions that are supported, and check out this handy emoji code website. Now that the frontend is ready, let’s move on to the backend.

The PHP Code

We have two files – publish.php and load.php. The first accepts a POST request for storing shouts in the data store, and the second returns the 20 latest shouts. These files are not opened directly by visitors – they only handle AJAX requests.

publish.php

<?php

// Include our composer libraries
require 'vendor/autoload.php';

// Configure the data store

$dir = __DIR__.'/data';

$config = new JamesMossFlywheelConfig($dir, array(
    'formatter' => new JamesMossFlywheelFormatterJSON,
));

$repo = new JamesMossFlywheelRepository('shouts', $config);
    
// Store the posted shout data to the data store

if(isset($_POST["name"]) && isset($_POST["comment"])) {
    
    $name = htmlspecialchars($_POST["name"]);
    $name = str_replace(array("n", "r"), '', $name);

    $comment = htmlspecialchars($_POST["comment"]);
    $comment = str_replace(array("n", "r"), '', $comment);
    
    // Storing a new shout

    $shout = new JamesMossFlywheelDocument(array(
        'text' => $comment,
        'name' => $name,
        'createdAt' => time()
    ));
    
    $repo->store($shout);
    
}

Here we directly use the Flywheel library we mentioned in the beginning. Once it is configured, you can store any type of data, which will be written as a JSON file in the data/shouts folder. Reading these shouts is done in load.php:

load.php

<?php

require 'vendor/autoload.php';

// If you want to delete old comments, make this true. We use it to clean up the demo.
$deleteOldComments = false;

// Setting up the data store

$dir = __DIR__.'/data';

$config = new JamesMossFlywheelConfig($dir, array(
    'formatter' => new JamesMossFlywheelFormatterJSON,
));

$repo = new JamesMossFlywheelRepository('shouts', $config);

// Delete comments which are more than 1 hour old if the variable is set to be true.

if($deleteOldComments) {
    
    $oldShouts = $repo->query()
                ->where('createdAt', '<', strtotime('-1 hour'))
                ->execute();

    foreach($oldShouts as $old) {
        $repo->delete($old->id);
    }
    
}

// Send the 20 latest shouts as json

$shouts = $repo->query()
        ->orderBy('createdAt ASC')
        ->limit(20,0)
        ->execute();

$results = array();

$config = array(
    'language' => 'RelativeTimeLanguagesEnglish',
    'separator' => ', ',
    'suffix' => true,
    'truncate' => 1,
);

$relativeTime = new RelativeTimeRelativeTime($config);
        
foreach($shouts as $shout) {
    $shout->timeAgo = $relativeTime->timeAgo($shout->createdAt);
    $results[] = $shout;
}

header('Content-type: application/json');
echo json_encode($results);

We’ve included code which deletes shouts older than an hour. We use this feature to keep the demo clean. You can enable it if you wish. After selecting the shouts, we are also calculating the human-readable relative time stamp with the RelativeTime library.

With this our shoutbox is ready! You can embed it in your website, customize it and change the code any way you please. We hope you like it!

Creating Your First Desktop App With HTML, JS and Node-WebKit

first-nodewebkit-app

These days you can do pretty much anything with JavaScript and HTML. Thanks to Node-WebKit, we can even create desktop applications that feel native, and have full access to every part of the operating system. In this short tutorial, we will show you how to create a simple desktop application using Node-WebKit, which combines jQuery and a few Node.js modules.

Node-WebKit is a combination of Node.js and an embedded WebKit browser. The JavaScript code that you write is executed in a special environment and has access to both standard browser APIs and Node.js. Sounds interesting? Keep reading!

Update (15th Jan 2015) – Just after a week of publishing this tutorial, node-webkit was renamed to NW.js. For now, this tutorial is perfectly compatible with it. In the future we might update it if there are any changes.

Installing Node-WebKit

For developing applications, you will need to download the node-webkit executable, and call it from your terminal when you want to run your code. (Later you can package everything in a single program so your users can only click an icon to start it).

Head over to the project page and download the executable that is built for your operating system. Extract the archive somewhere on your computer. To start it, you need to do this in your terminal:

# If you are on linux/osx

/path/to/node-webkit/nw /your/project/folder

# If you are on windows

C:pathtonode-webkitnw.exe C:yourprojectfolder

# (the paths are only for illustrative purposes, any folder will do)

This will open a new node-webkit window and print a bunch of debug messages in your terminal.

You can optionally add the extracted node-webkit folder to your PATH, so that it is available as the nw command from your terminal.

Your First Application

There is a Download button near the top of this article. Click it and get a zip with a sample app that we prepared for you. It fetches the most recent articles on Tutorialzine from our RSS feed and turns them into a cool looking 3D carousel using jQuery Flipster.

Directory Structure

Directory Structure

Once you extract it, you will see the files above. From here this looks like a standard static website. However, it won’t work if you simply double click index.html – it requires Node.js modules, which is invalid in a web browser. To run it, CD into this folder, and try running the app with this command:

/path/to/node-webkit/nw .

This will show our glorious desktop app.

Our node-webkit app

Our node-webkit app

How it was made

It all starts with the package.json file, which node-webkit looks up when starting. It describes what node-webkit should load and various parameters of the window.

package.json

{
  "name": "nw-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.html",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "window": {
    "toolbar": false,
    "width": 800,
    "height": 500
  },
  "license": "ISC",
  "dependencies": {
    "pretty-bytes": "^1.0.2"
  }
}

The window property in this file tells node-webkit to open a new window 800 by 500px and hide the toolbar. The file pointed to by the main property will be loaded. In our case this is index.html:

index.html

<!DOCTYPE html>
<html>
<head>

	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">

	<title>Tutorialzine Node-Webkit Experiment</title>

	<link rel="stylesheet" href="./css/jquery.flipster.min.css">
	<link rel="stylesheet" href="./css/styles.css">

</head>
<body>

	<div class="flipster">
		<ul>
			<!-- Tutorialzine's latest articles will show here -->
		</ul>
	</div>

	<p class="stats"></p>

	<script src="./js/jquery.min.js"></script>
	<script src="./js/jquery.flipster.min.js"></script>
	<script src="./js/script.js"></script>
</body>
</html>

And finally, here is our JavaScript file. This is where it gets interesting!

js/script.js

// Mixing jQuery and Node.js code in the same file? Yes please!

$(function(){


	// Display some statistic about this computer, using node's os module.

	var os = require('os');
	var prettyBytes = require('pretty-bytes');

	$('.stats').append('Number of cpu cores: <span>' + os.cpus().length + '</span>');
	$('.stats').append('Free memory: <span>' + prettyBytes(os.freemem())+ '</span>');

	// Node webkit's native UI library. We will need it for later
	var gui = require('nw.gui');


	// Fetch the recent posts on Tutorialzine

	var ul = $('.flipster ul');

	// The same-origin security policy doesn't apply to node-webkit, so we can
	// send ajax request to other sites. Let's fetch Tutorialzine's rss feed:

	$.get('http://feeds.feedburner.com/Tutorialzine', function(response){

		var rss = $(response);

		// Find all articles in the RSS feed:

		rss.find('item').each(function(){
			var item = $(this);
			
			var content = item.find('encoded').html().split('</a></div>')[0]+'</a></div>';
			var urlRegex = /(http|ftp|https)://[w-_]+(.[w-_]+)+([w-.,@?^=%&amp;:/~+#]*[w-@?^=%&amp;/~+#])?/g;

			// Fetch the first image of the article
			var imageSource = content.match(urlRegex)[1];


			// Create a li item for every article, and append it to the unordered list

			var li = $('<li><img /><a target="_blank"></a></li>');

			li.find('a')
				.attr('href', item.find('link').text())
				.text(item.find("title").text());

			li.find('img').attr('src', imageSource);

			li.appendTo(ul);

		});

		// Initialize the flipster plugin

		$('.flipster').flipster({
			style: 'carousel'
		});

		// When an article is clicked, open the page in the system default browser.
		// Otherwise it would open it in the node-webkit window which is not what we want.

		$('.flipster').on('click', 'a', function (e) {

			e.preventDefault();
			
			// Open URL with default browser.
			gui.Shell.openExternal(e.target.href);

		});

	});

});

Notice that we are accessing Tutorialzine’s RSS feed directly with jQuery, even though it is on a different domain. This is not possible in a browser, but Node-WebKit removes this limitation to make development of desktop applications easier.

Here are the node modules we’ve used:

  • Shell – A node webkit module that provides a collection of APIs that do desktop related jobs.
  • OS – The built-in Node.js OS module, which has a method that returns the amount of free system memory in bytes.
  • Pretty Bytes – Convert bytes to a human readable string: 1337 → 1.34 kB.

Our project also includes jQuery and the jQuery-flipster plugin, and that’s pretty much it!

Packaging and Distribution

You most certainly don’t want your users to go through the same steps in order to run you application. You wan’t to package it in a standalone program, and open it by simply double clicking it.

Packaging node-webkit apps for multiple operating systems takes a lot of work to do manually. But there are libraries that do this for you. We tried this npm module – https://github.com/mllrsohn/node-webkit-builder, and it worked pretty well.

The only disadvantage is that the executable files have a large size (they can easily hit 40-50mb) , because they pack a stripped down webkit browser and node.js together with your code and assets. This makes it rather impractical for small desktop apps (such as ours), but for larger apps it is worth a look.

Conclusion

Node-webkit is a powerful tool that opens a lot of doors to web developers. With it, you can easily create companion apps for your web services and build desktop clients which have full access to the users’s computer.

You can read more about node-webkit on their wiki.

Quick Tip: Easy form validation with HTML5

easy-form-validation-html5

When you collect information from people through a form, applying some kind of validation is a must. Failing to do so could lead to lost customers, junk data in your database or even security exploits of your website. Historically, building form validation has been a pain. On the server side, this is made easier by full stack frameworks which handle it for you, but on the client you often end up with JavaScript libraries that take a lot of effort to integrate.

Thankfully, HTML5 gives us a number of features that can handle most of your validation needs. Forms in HTML5 now have built-in support for validation through the use of special attributes and new input types, and give you a lot of control over styling with CSS.

See an online demo here and read a quick overview of the basics behind HTML5 form validation below.

1. Specialized Input Types

HTML5 introduced several new input types. They can be used to create input boxes, which will accept only a specified kind of data.

The new input types are as follows:

  • color
  • date
  • datetime
  • datetime-local
  • email
  • month
  • number
  • range
  • search
  • tel
  • time
  • url
  • week

To use one of the new types, include them as the value of the type attribute:

<input type="email"/>

If the browser does not support the given input type, the field will behave as a regular text input. Also, it’s helpful to know that some of the input fields (such as “email” and “tel”) will cause a mobile devices to open specialized keyboards with a limited set of keys, and not the full QUERTY layout.

For more details on all the input types, head out to this MDN wiki – here.

2. Required Fields

By simply adding the “required” attribute to a <input>, <select> or <textarea>, you tell the browser that a value must be provided in this field. Think of this as the red asterisk* we see in most registration forms.

<input type="checkbox" name="terms" required >

The problem here is that nearly any data will fulfill this requirement – for example you can bypass it with an empty space (we’ll show you how to prevent this in a moment).

When you set the required attribute on email or url fields, the browser expects a certain pattern to be followed, but it’s very permissive and emails such as “z@zz” are considered valid (read on to see how to work around this).

3. Limits

We can set some basic limitations like max length and minimum and maximum values for number fields. To limit the length of input fields and textareas, use the “maxlength” attribute. What this does is to forbid any string longer than the field’s “maxlength” value to be entered at all. If you try and paste a string witch exceeds this limit, the form will simply clip it.

<input type="text" name="name" required  maxlength="15">

The <input type=”number”> fields use “max” and “min” attributes to create a range of possible values – in our example we’ve made the minimum allowed age to be 18 (too bad you can be whatever age you want on the internet).

<input type="number" name="age" min="18" required>

4. Styling

CSS3 pseudo classes let us style any form field depending on its state. They are:

  • :valid
  • :invalid
  • :required
  • :optional
  • :in-range
  • :out-of-range
  • :read-only
  • :read-write

This means that you can have required fields look one way, optional ones another and so on.

In our demo we’ve combined the “valid” and “invalid” selectors with the “focus” pseudo class to color form fields red or green when the user selects them and starts typing.

input:focus:invalid,
textarea:focus:invalid{
	border:solid 2px #F5192F;
}

input:focus:valid,
textarea:focus:valid{
	border:solid 2px #18E109;
	background-color:#fff;
}

5. Tooltips

As you’ve probably noticed, when you try to submit a form that’s not correctly filled, a pop-up appears. By setting the “title” attribute of our fields, we can add additional hints on what values our rules validation expects.

Note that different browsers display the pop-ups in differently. In Chrome, the title attribute value will appear under the main error-message text in smaller font. In Firefox it doesn’t show your custom tooltip text at all, unless you’ve used the “pattern” attribute as well, which then is taken as a pattern info.

<input type="text" name="name" title="Please enter your user name.">

The error boxes or their default content can’t be changed that simply and require the help of JavaScript, but that’s a whole other tutorial.

6. Patterns

The “pattern” attribute lets developers set a Regular Expression, which the browser will match against the user supplied input, before allowing the form to be submitted. This gives us great control over the data entries, since RegEx patterns can be quite complex and precise. To learn more about Regular Expressions, check out our article – Learn Regular Expressions in 20 Minutes.

Now, with the ability to filter out input values, our example form accepts only full email addresses and a password with a minimum length of 8 characters, including at least one number.

Here’s how to use it:

<input type="email" name="email" required pattern="^S+@S+.S+$" title="example@mail.com">

We hope that this quick tip helped you get up to speed with HTML5’s validation features. Thanks for reading!

Powered by Gewgley