Total results: 24

Swipe.JS - Detect touch direction and distance

During development of recent project, I have had to realize a JavaScript solution that will detect when a visitor swipes the page and then perform an action based on the swipe direction and distance.

Of course this is not a new challenge and many solutions have already been found. jQuery mobile ships with a built in swipe event but I did not require such an extensive framework and decided to write the cleanest answer that solved the problem.

Below you will find the source code to a jQuery plugin I call "Swipe.JS", which provides the same swipe event to any DOM node.

Usage

First I will show how to use the plugin. Multiple swipe events can be bound to different nodes but for the sake of example, we will use the "body".

$("body").swipe(function( direction, offset ) {
  console.log( "Moving", direction.x, "and", direction.y );
  console.log( "Touch moved by", offset.x, "horizontally and", offset.y, "vertically" );    
});

Swipe.JS console output

Static file web servers

Testing a static website can be done simply by opening the HTML files in a web browser, but for some functionality to perform correctly, such as local AJAX calls, the files need to be served from a web server.

Alternatively, you may want to check out some static files on your mobile device. You can do this easily by starting a simple web server for the project and navigate to your computers IP address with the given server port.

Python Server

The easiest way to do this on UNIX based systems is to use the Python Simple HTTP Server, like so:

python -m SimpleHTTPServer 8080

Run this command in the same directory as your project from the terminal, then point your browser to http://localhost:8080.

This is a great way to get a server running in seconds, for basic testing, but I have found that as the number of files in the project increases, the stability of the server decreases. Often files will not be passed to the client and 404 errors are encountered. For these reasons I have investigated a stronger solution that is still simple to setup. This leads me to Node.JS.

Node Server

Node.JS is no stranger to web servers, in fact this is often the primary task of a Node application.

"Connect" is a Node.JS middleware application that makes the creation of simple web servers trivial.

To get Connect running, first install it via npm:

npm install -g connect

Here is a web server that can be used, simply paste the code into a file called "server.js" in your project's root directory.

var connect = require( 'connect' ),
  http = require( 'http' );

app = connect()
  .use( connect.logger( 'dev' ) )
  .use( connect.static( __dirname ) );

http.createServer( app ).listen( 8080 );

Finally run the server from the terminal like so:

node server.js

If no error was received, the server is running and files can be viewed by browsing http://localhost:8080, just like in the Python example.

I have not had any trouble with the Connect version of my server and it comes built with a nice development logger, showing what files were requested and with what status. This output can be viewed live in the terminal window as requests come in.

Connect Server Dev Log

Improve page performance with optimal CSS

There are certain CSS best practices that should be followed in order to increase CSS performance in the browser. These will help the browser to perform less DOM parsing and reduce the time of repaint events.

1. Browser reflow and repaint

If you are unfamiliar with the concepts of reflow and repaint, here are some articles that will get you up to speed:

2. Remove unused styles

Simply having styles that aren't used causes the browser to search the DOM for matches needlessly. This is wasted processor time. Additionally, the CSS file will have a higher page weight that is needlessly sent over the wire to the client.

It may not seem to make a huge difference but removing dead CSS code will greatly increase performance and additionally improve the project stability and maintainability.

Check size of localStorage usage in Chrome

localStorage is a great tool for JavaScript developers to persist information across multiple sessions. Due to its simple API, large browser support and and higher reliability than cookies, it can easily lead to the situation of overusing localStorage.

Since localStorage has a maximum size of 5MB the following snippet will help inspect what localStorage keys are being used and how much size is being allocated to each.

To give credit, I have taken the method here and added a total counter.

var total = 0;
for(var x in localStorage) {
  var amount = (localStorage[x].length * 2) / 1024 / 1024;
  total += amount;
  console.log( x + " = " + amount.toFixed(2) + " MB");
}
console.log( "Total: " + total.toFixed(2) + " MB");

Simply run this in the Chrome console or create a bookmarklet from the following code (Right click bookmark bar > Add Page > Copy the code as "URL")

javascript:var total = 0;for(var x in localStorage) {  var amount = (localStorage[x].length * 2) / 1024 / 1024;  total += amount;  console.log( x + "=" + amount.toFixed(2) + " MB");}console.log( "Total: " + total.toFixed(2) + " MB");

Which will give a similar output:

Matches = 0.40 MB
Matches_timestamp = 0.00 MB
Teams = 0.19 MB
Teams_timestamp = 0.00 MB
Total: 0.59 MB

Dynamically append LESS.js stylesheets

Here is a function that can be called to dynamically apply a LESS.js stylesheet to the DOM after the page has finished loading. The following code snippet uses jQuery for convenience.

 function loadLESS ( filename ) {
    // If LESS isn't available, do nothing
    if ( !window.less ) { return;}

    // Create LESS link and add to <head>
    var $link = $("<link type='text/css' rel='stylesheet/less' />");
    $link.attr("href", filename + ".less");
    $("head").append( $link );

    // Notify LESS that there is a new stylesheet
    less.sheets.push( $link[0] );
    less.refresh();
}

The important parts are after applying the new link tag to the head section, the raw DOM node $link[0] must be added to the less.sheets array and then refresh called to apply the changes to the web page.

Also remember that the rel attribute for the link tag must be set to "stylesheet/less" rather than just "stylesheet".

Append an HTML string to the DOM without a JavaScript Library

In the event where appending new nodes to the DOM via JavaScript is required but there is no access to a library such as jQuery or Prototype.JS, this handy snippet allows an easy librabry-like API with a tiny amount of code:

 function append ( elString, parent ) {
    var div = document.createElement( "div" );
    div.innerHTML = elString;
    document.querySelector( parent || "body" ).appendChild( div.firstChild );
 }

This snippet can be used easily:

// Append a link tag to the head
append( "<link rel='stylesheet' href='css/foo.css' />", "head" );

// Append a parapgraph to the body
append( "<p>My text</p>" );

// Append a new list item
append( "<li>Cheese</li>", "ul.shopping-list" );

Install Node.JS on Debian Wheezy

Official Method

The official Node.JS install guide recommends manually downloading and building the Node.JS package for Debian. This can be done using the following set of commands:

sudo apt-get install python g++ make checkinstall
mkdir ~/node_js_src && cd $_
wget -N http://nodejs.org/dist/node-latest.tar.gz
tar xzvf node-latest.tar.gz && cd node-v*
./configure
checkinstall
sudo dpkg -i node_*

This install method should work fine but will take a long time to complete on the Raspberry Pi's hardware. For this reason I experimented a little and found a quicker install method that doesn't require a manual compile, by using the Ubuntu package.

Ubuntu Method

This install method will be much faster than the official method but is not designed for Debian Wheezy, so use at your own risk! Personally I have not had any trouble with my node install yet but I cannot guarantee this will be the case for anyone else.

sudo apt-get update
sudo apt-get install -y python-software-properties python g++ make
sudo add-apt-repository ppa:chris-lea/node.js

At this point the file with the new repository details must be edited. Open the file: /etc/apt/sources.list.d/chris-lea-node_js-wheezy.list with a text editor like vim and change the word "wheezy" to "lucid". Thanks to Ken Yap for this hint.

Now, go on and finish installing Node.

sudo apt-get update
sudo apt-get install -y nodejs

A JavaScript Google Analytics event tracking plugin

In todays online world it is common for web developers to improve their websites by enabling a large amount of interactive functionality. Often this takes the form of JavaScript applications that no longer adhere to the simple page-by-page model but instead act more like a desktop program (Gmail, YouTube and Twitter for example).

If many interactions are happening in a single page without the URL changing, this experience is great for the user but can prove problematic when tracking for analytics. Traditionally analytics software such as Google Analytics is included in every web page of a site and each time a page is downloaded it is tracked back to Google. Obviously if the visitor never leaves that URL, this causes the aforementioned issue.

Google have a solution called "Events" that allow a developer to programmatically track an interaction via JavaScript. Events breakdown into the following components:

  • Category
  • Action
  • Label (optional)

For example, to track a customer checking out of an online store through a JavaScript form interface the following events may be used:

Format: Category / Action / Label

  1. Checkout / ViewCart
  2. Checkout / Country Selected / USA
  3. Checkout / Details Provided
  4. Checkout / Order Confirmed

From these tracked events, reports can be generated or funnels (called "Goals" by Google) setup to track conversion rates.

The method that Google provides to programmatically track an event looks as follows:

_gaq.push(['_trackEvent', 'Checkout', 'Country Selected', 'USA']);

This is simple enough, however, it is not wise to litter application code with calls to _gaq. If the Analytics script does not load due to a network issue this variable will be undefined and cause a potentially serious error. Also, if you someday remove Google Analytics it may be problematic to remove all occurrences of this throughout your code base.

For this reason I have created the following wrapper around the tracking code with a simple API and multiple advantages that can be plugged into any JavaScript application.

© Blake Simpson, 2012 – 2017