Posts Tagged ‘javascript’

Timeout your XHR requests

Client-side timeouts on XHR requests isn’t something I’ve ever thought a whole lot about. The default is no timeout and in most cases, where you’re kicking off an XHR request in response to a user interaction, you probably won’t ever notice an issue. That said, I ran into a case with ScratchGraph on Chrome where not having a timeout specified, along with some client-side network errors, left the application in a state where it was unable to send any more XHR requests.

ScratchGraph continuously polls its server for new data and every so often I would notice that the XHR calls would stop, with the application left in a broken state, unable to make any AJAX calls. This typically (but not always) occurred when the machine woke up from being put to sleep and in the console there would be a few error messages, typically a number of ERR_NETWORK_IO_SUSPENDED and ERR_INTERNET_DISCONNECTED errors. Testing within my development environment, it was impossible to reproduce. Finally, I came across this StackOverflow post that pointed out that not having a timeout specified on the XHR calls would result in these errors.

I’m still not exactly sure of the interplay between Chrome, the XHR requests, and the network state that results in this situation, but since adding a timeout, I’ve yet to notice this behavior again. It’s also worth noting that it’s very simple to add a timeout on an XHR request:

var xhr = new XMLHttpRequest();
xhr.open(
'GET', '/hello', true);
xhr.timeout = 500;
// time in milliseconds

Real-time image processing on the web

A while ago I began playing around with grabbing a video stream from a webcam and seeing what I could do with the captured data. Capturing the video stream using the navigator.getUserMedia() method was straightforward, but directly reading and writing the image data of the video stream isn’t possible. That said, the stream data can be put onto a canvas using CanvasRenderingContext2D.drawImage(), giving you to ability to read the pixel data. When it comes to writing visual data, a few options are available.

var videoElem = document.querySelector('video');

// Request video stream
navigator.getUserMedia({video: true, audio: false},

function(_localMediaStream) {
videoStream = _localMediaStream;
videoElem.src = window.URL.createObjectURL(_localMediaStream);
},

function(err) {
console.log(
'navigator.getUserMedia error' + err);
}

);
var videoElem = document.querySelector('video');
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

...

// put snapshot from video stream into canvas
ctx.drawImage(videoElem, 0, 0);

You can read and write to the <canvas> element, so hiding the <video> element with the source data and just showing the <canvas> element is an option, but the CanvasRenderingContext2D.drawImage() call is expensive; looking at the copied stream on the <canvas> element there is, very noticeable, visual lag. Another reason to avoid this option is that the frequency at which you render (e.g. 30 FPS), isn’t necessarily the frequency at which you’d want to grab and process image data (e.g. 10 FPS). The disassociation allow you to keep the video playback smooth, for a better user experience, but more effectively utilize CPU cycles for the image processing. At least in my experiences so far, a small delay in the visual feedback from the image processing is acceptable and looks perfectly fine intermixed with the higher-frequency video stream.

Throwing aside reading and writing to just the <canvas> element, alternative options all involve showing the <video> element with the webcam stream and placing visual feedback on top of the video pixels. A few ideas:

  • Write pixel data to another canvas and render it on top of the <video> element
  • Render SVG elements on top of the <video> element
  • Render DOM elements (absolutely positioned) on top of the <video> element

The third option is an ugly solution, but it’s fast to code and thus allows for quick prototyping. The demo and code below shows a quick demo I slapped together using <div> elements as markers for hot spots, in this case bright spots, within the video.

<!DOCTYPE html>
<
html>
<
head>
<
title>Webcam Cap</title>
<
meta charset="UTF-8">
<
meta name="viewport" content="width=device-width, initial-scale=1.0">

<
style type="text/css">
* { margin:0; padding:0; border:none; }
</style>

</
head>

<
body>
<
div>
<
video style="width:640px; height:480px;" width="640" height="480" autoplay></video>
<
canvas style="display:none; width:640px; height:480px;" width="640" height="480"></canvas>
</
div>

<
div class="ia-markers"></div>

<
script type="text/javascript">

navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);

if ( typeof navigator.getUserMedia !== 'undefined' ) {

var videoElem = document.querySelector('video');
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var videoStream = null;
var snapshotIntv = null;

var width = 640;
var height = 480;

// Request video stream
navigator.getUserMedia({video: true, audio: false},

function(_localMediaStream) {
videoStream = _localMediaStream;
videoElem.src = window.URL.createObjectURL(_localMediaStream);

// Take a snapshot of the video stream 10ms
snapshotIntv = setInterval(function() {
processSnapshot(videoStream);
}, 100);

},

function(err) {
console.log(
'navigator.getUserMedia error' + err);
}

);


// Take a snapshot from the video stream
function processSnapshot() {

// put snapshot from video stream into canvas
ctx.drawImage(videoElem, 0, 0);

// Clear old snapshot markers
var markerSetParent = (document.getElementsByClassName('ia-markers'))[0];
markerSetParent.innerHTML =
'';

// Array to store hotzone points
var hotzones = [];

// Process pixels
var imageData = ctx.getImageData(0, 0, width, height);
for (var y = 0; y < height; y+=16) {
for (var x = 0; x < width; x+=16) {
var index = (x + y * imageData.width) << 2;

var r = imageData.data[index + 0];
var g = imageData.data[index + 1];
var b = imageData.data[index + 2];

if(r > 200 && g > 200 && b > 200) {
hotzones.push([x,y]);
}
}
}

// Add new hotzone elements to DOM
for(var i=0; i<hotzones.length; i++) {
var x = hotzones[i][0];
var y = hotzones[i][1];

var markerDivElem = document.createElement("div");
markerDivElem.setAttribute(
'style', 'position:absolute; width:16px; height:16px; border-radius:8px; background:#0f0; opacity:0.25; left:' + x + 'px; top:' + y + 'px');
markerDivElem.className =
'ia-hotzone-marker';

markerSetParent.appendChild(markerDivElem);
}
}

}
else {
console.log(
'getUserMedia() is not supported in your browser');
}

</script>

</
body>
</
html>

Function argument tricks

I came across this “trick” on coderwall for avoiding an if statement when you have a a function argument that is allowed to be either an array or a scalar value (something that seems oddly common in loosely typed languages).

function example(ids) {
;[].concat(ids).forEach(
function (id) {
// ...
})
}

The trick in question is just concatenating the argument with an empty array so that, within the function, you’re always dealing with an array and elements of the array.

Taking a step back, the bigger question is why do this?
In my experience, it’s almost always better to keep the code within the function straightforward and force the caller to adapt and give the function what it needs. In this case, that means simply forcing the caller to always pass an array.

Where we live

Using a number of technologies I’ve been playing around with recently, I began working on a 3D visualization of the Earth, plotting every city, creating a pointillism-styled representation of the planet. Below is the result along with an overview of how I produced the rendering.

Getting the data

I extracted all cities with a population of at least 100,000 people from the MySQL GeoNames database using the following query:

SELECT `id`,`name`,`latitude`,`longitude`,`population`,`timezone`
FROM geonames.cities
WHERE population >= 100000 AND feature_class = 'P';

… and put the results into a JS array.

Creating a 3D model to represent each city

I created this hexagonal model in Blender, exported it to a Wavefront OBJ file, and ran the OBJ file through the Wavefront OBJ to JSON converter I wrote. Note that the model is facing the z-axis to match WebGL’s (and OpenGL’s) default camera orientation: facing down the negative z-axis.

Convert longitude and latitude to a 3D position

Converting a geodetic longitude, latitude pair to a 3D position involves doing a LLA (Longitude Latitude Altitude) to ECEF (Earth-Centered, Earth-Fixed) transformation. The code below implements this transform, converting the longitude and latitude of every city pulled from the GeoNames database into a 3D coordinate where we can render the hexagonal representation of the city.

function llarToWorld(lat, lon, alt, rad)
{            
    lat = lat * (Math.PI/180.0);
    lon = lon * (Math.PI/180.0);

    
var f = 0; //flattening
    
var ls = Math.atan( Math.pow((1.0 - f),2) * Math.tan(lat) ); // lambda

    
var x = rad * Math.cos(ls) * Math.cos(lon) + alt * Math.cos(lat) * Math.cos(lon)
    
var y = rad * Math.cos(ls) * Math.sin(lon) + alt * Math.cos(lat) * Math.sin(lon)
    
var z = rad * Math.sin(ls) + alt * Math.sin(lat)
    
    
return [x,z,-y];            
}

There are 2 items worth noting:

  • The transformation (and function above) involve a 4th parameter, radius which is the radius of the ellipsoid (or sphere, in this case, as flattening=0) into which the transformation is done. I have it set as a fixed constant, as I’m primary concerned with an approximate visual representation, but the MathWorks page describes the actual computation.
  • The ECEF (Earth-Centered, Earth-Fixed) coordinate system has the z-axis pointing north, not the y-axis, so the z and y values need to be swapped to produce a coordinate corresponding to WebGL’s default camera orientation. In addition, as WebGL has a right-handed coordinate system (so the default camera orientation is one where it’s pointing down the negative z-axis), the z coordinate is negated so the point doesn’t wind up behind the camera.

Orient all cities to face the origin

Getting each of the hexagonal models to face the origin involved a bit of math:

  • Calculating the axis about which the rotation should occur by, first, computing a vector from the origin to the 3D position of the model (lookAt), and taking the cross product between lookAt and the z-axis (as we’re rotating toward the z-axis).
  • Calculating the angle of rotation (the angle between the z-axis and lookAt) by computing the dot product between lookAt and the z-axis, then taking the acos of the dot product.

There’s some additional code to handle cases where points lie on the on the z-axis (where the cross product gives the zero vector) and also to return a matrix representation of the rotation.

function lookAtOrigin(v)
{
// compute vector from origin
var lookAt = vec3.create([v[0], v[1], -v[2]]);
vec3.normalize(lookAt);

// reference axis
var refAxis = vec3.create([0,0,-1]);

// computate axis of rotation
var rotAxis = vec3.create(lookAt);
vec3.cross(rotAxis, refAxis);

// compute angle of rotation
var rotAngRad = Math.acos(vec3.dot(lookAt, refAxis));

// special cases...
if(rotAxis[0] == 0 && rotAxis[1] == 0 && rotAxis[2] == 0) {
if(lookAt[2] > 0) {
rotAxis = vec3.create([1,0,0]);
rotAngRad = Math.PI;
}
else {
rotAxis = vec3.create([1,0,0]);
rotAngRad = 0;
}
}

// compute and return a matrix with the rotation
var ret = mat4.identity();
mat4.rotate(ret, rotAngRad, rotAxis);

return ret;
}

Render the scene

Using glfx, I pulled everything together, also adding a bit of code to rotate the camera and do some pseudo-lighting in the pixel shader by alpha blending colors based on depth. All the code can be found in the webgl-globe repository on bitbucket.

Double-tap interactions

While click events are seamlessly supported on touch devices, double-click events are not and there is no equivalent double-tap event available. However, double-tap interactions can be captured by listening for multiple, subsequent touchend events. The code below shows how to do this, with the basis for a double-tap being:

  • Two touchend events, on a certain element, both occurring within a certain time interval (300ms)
  • Two touchend events, on a certain element, both occurring within a certain distance from each other (24px)

I’ve come across a lot of code that addresses the first point (see double tap on mobile safari), but the second point is just as important because almost all touchscreens are multitouch and a two-handed posture with a phone or tablet is not uncommon. With a two-handed posture, and an element large enough to span the screen, it’s easy to hit two different areas of the element (on opposite ends of the screen) in rapid succession – a double-tap would be detected, even though two distant points on the element were touched, unless the distance between the points is taken into account.

Ideally, both the interval and distance should be user-defined settings at the device/operating-system level, similar to the way setting the double-click speed is, but lacking such support, hacking it in at the application-level is the only viable option.


// Handler for when a double-tap (on a touchscreen) or double-click (with a mouse) is detected
var dblTapHandler = function (x, y) {

// Do stuff...

}

$(document).ready(
function() {


// Listen for double-click events for desktop/mouse-based interactions
$('.ia-dbltap-area').on('dblclick', function (e) {
// Call handler
dblTapHandler(e.pageX, e.pageY);
});


// Listen for touchend events for touch-based interactions
$('.ia-dbltap-area').on('touchend', function(e) {

var dblTapRadius = 24; // radius (in pixels) of the area in which we expect the 2 taps for a double-tap
var dblTapSpeed = 300; // interval (in milliseconds) in which we expect the 2 taps for a double-tap

if(e.originalEvent.changedTouches.length <= 0) {
return false; // we have nothing to work with
}

var dblTapDetected = false; // flag specifying if we detected a double-tap
var areaElem = $(this); // element in which this touchend event has occured

// Position of the touch
var x = e.originalEvent.changedTouches[0].pageX;
var y = e.originalEvent.changedTouches[0].pageY;

var now = new Date().getTime();

// Check if we have stored data for a previous touch (indicating we should test for a double-tap)
if(areaElem.data('last-touch-time')) {

lastTouchTime = areaElem.data(
'last-touch-time');

// Compute time since the previous touch
var timeSinceLastTouch = now - lastTouchTime;

// Get the position of the last touch on the element
var lastX = areaElem.data('last-touch-x');
var lastY = areaElem.data('last-touch-y');

// Compute the distance from the last touch on the element
var distFromLastTouch = Math.sqrt( Math.pow(x-lastX,2) + Math.pow(y-lastY,2) );

// Check if:
// 1. If the time since the last touch is within the specified double-tap interval (dblTapSpeed)
// 2. The distance from the last touch is within the specified double-tap radius (tapRadius)
if(timeSinceLastTouch <= dblTapSpeed && distFromLastTouch <= dblTapRadius) {

// Flag that we detected a double tap
dblTapDetected = true;

// Call handler
dblTapHandler(x, y);

// Remove last touch info from element
areaElem.data('last-touch-time', '');
areaElem.data(
'last-touch-x', '');
areaElem.data(
'last-touch-y', '');
}

}


if(!dblTapDetected) { // A double-tap wasn't detected

// Store time and position of this touch on the element
// (Next touch may be a double-tap, we can use this info to determine if it is)
areaElem.data('last-touch-time', now);
areaElem.data(
'last-touch-x', x);
areaElem.data(
'last-touch-y', y);
}

});

});

The demo below shows the code in actions along with a bit of SVG to render where the user double-clicked or double-touched div.ia-dbltap-area:

Moving the caret to the end of text in an <input> element

Very simple, and the following will work in all modern browsers.

HTML

<input name="url" type="text" value="http://" />

Javascript

var inputElem = document.getElementsByName("url")[0];
                
var valLen = inputElem.value.length;

inputElem.selectionStart = valLen;
inputElem.selectionEnd = valLen;

inputElem.focus();

The same technique will work for <textarea> elements as well.

Manipulating text relative to the caret in a contenteditable div

I wanted to play around a bit with dynamically modifying text as you type. The following is a simple auto-correct demo that makes use of the Selection and Range interfaces to replace text (read: text preceding to the caret) within a contenteditable div.

$(document).on('keydown', '.ia-txt', function (e) {
            
    
// check if space bar was hit
    
if(e.keyCode == 32) {
                    
        
// we'll check for the string "hwat"; incorrect form of "what"
        
var incorrectTxt = "hwat";
    
        
// Get selection and range based on position of caret
        // (we assume nothing is selected, and range points to the position of the caret)
        
var sel = window.getSelection();
        
var range = sel.getRangeAt(0);
                            
        
// check that we have at least incorrectTxt.length characters in our container
        
if(range.startOffset - incorrectTxt.length >= 0) {
        
            
// clone the range, so we can alter the start and end
            
var clone = range.cloneRange();
            
            
// alter start and end of cloned ranged, so it selects incorrectTxt.length characters
            
clone.setStart(range.startContainer, range.startOffset - incorrectTxt.length);
            clone.setEnd(range.startContainer, range.startOffset);

            
// get contents of cloned range
            
var contents = clone.toString();                    
                                    
            
// check if the contents of the cloned range is equal to our incorrectTxt string
            
if(contents == incorrectTxt) {
                                        
                
// delete the contents of the range ("hwat")
                
clone.deleteContents();    
                
                
// create a text node with the corrected text ("what") and insert it where we deleted the incorrect text
                
var txtNode = document.createTextNode("what");
                range.insertNode(txtNode);
                
                
// set the start of the range after the inserted node, so we have the caret after the inserted text
                
range.setStartAfter(txtNode);
                                    
                
// Chrome fix
                
sel.removeAllRanges();
                sel.addRange(range);             

            }                
        }
    }
    

});

You can see the code in action in the frame below. Every time you press the space-bar and the string “hwat” is detected, preceding the position of the caret, it is removed and replaced with the string “what”:

This is an incredibly trivial example (note that it doesn’t even check that the string “hwat” is surrounded by whitespace on both sides), but it does serve as a template for more advanced functionality. That said, be very aware of minor differences in the behavior of Range methods when working across browsers, I stumbled across a few:

  • The code above breaks under certain conditions in Internet Explorer. If you move the caret to a position between 2 works, type “hwat” + space (the string is auto-corrected to “what”), then type “hwat” + space again, the auto-correct doesn’t work. The range.startOffset variable seems incorrect (too small) and subtracting incorrectTxt.length (4) yields a negative start offset.
  • Using a keyup event instead of a keydown event, and checking for the string “hwat ” instead yields different behaviors in Firefox and Chrome. Firefox preserves the space after the corrected string, and the caret is at the position after the space. However, Chrome strips the space and the caret is after the corrected string.
  • After the selection’s range is altered after auto-correcting, Chrome requires the removeAllRanges(), addRange() calls to replace the selection’s range, but Firefox does not.

Interaction classes – seperating CSS styles from Javascript interactions

Something I’ve been doing for a while in my web development work is applying separate classes, interaction classes, to DOM elements that interact with Javascript. Basically, an interaction class is applied to any DOM element touched by Javascript code – an element bound to an event handler, an input element with it’s value being read or written, an element selected for animation, etc. The goal being to de-couple styling from interaction, allowing style changes to not interfere with JS code, and vice-versa.

Below is a bit of code to demonstrate what I’m talking about. As a convention, I apply a “ia-” prefix to my interaction classes.

<a href="#" class="btn-primary ia-begin-testing">Begin Testing</a>
  • btn-primary has the CSS rules for styling the anchor as a button
  • ia-begin-testing is bound to a JS event that triggers some arbitrary “begin testing” action

If the future, if I want to change the button to a link (remove the btn-primary class), change it to a secondary button (btn-primary to btn-secondary), or change styling in any other way, the Javscript code is unaffected and requires no changes.

In addition, the ia-begin-testing class can also be applied to other elements (another button, a link, an anchor wrapping an image, etc.) and is automatically bound to the same interaction functions, without writing additional JS DOM selection code. The ia-begin-testing class can also be removed, or changed to another interaction class, and the styling on the button remains the same.

While IDs and data attributes are also good choices for architecting this sort of style/interaction separation, I like classes for 2 reasons:

  • Selection via class is relatively fast across all browsers compared to selection via data attributes
  • Compared to IDs, classes can be re-used allowing the same interactions to be shared by multiple elements (e.g. a button and a link can both trigger the same function)

One of the reasons I wrote this post is as an alternative to the the “grouping of selectors” approach presented in Chris Coyier’s Can You “Over Organize” JavaScript? article. With interaction classes, there’s little need for grouping selectors. Aside from the benefit of de-coupling styling and interaction, you get the advantage of a single class (ia-whatever), on whatever and however many elements, mapping all said elements to their necessary JS functions. With grouping of selectors, some sanity is brought to the scattered DOM selection code, but you’re left with the burden of maintaining a pool of different element IDs, classes, etc.; a chore that only gets harder as the codebase grows and changes.

Notes on web workers

Recently I’ve been working on parallelizing some HTML5 canvas image processing code with web workers and hit a few stumbling blocks, mostly due to some unexpected limits and misunderstandings about workers. Below are some notes I’ve jotted down while working.

  • There’s a limit on the number of web workers being executed, with Firefox I hit a limit of 20.
  • With Firefox, there’s no warning when you hit the limit, your worker simply doesn’t run. There’s no queuing with workers either, so you can’t fire off a worker and expect the browser to schedule it to run when you have less than the maximum number of workers executing.
  • I attempted to implement my own queuing mechanism, but this was a waste of time. You can’t precisely predict when the browser will delete the worker. I tried posting a message from the worker thread to the caller (via postMessage) at the end of the worker onmessage processing function, but this only accurately signals that the processing is done, not that the worker is terminated, and you therefore can’t predict when it’s possible to spawn off another worker.
    EDIT: Experimenting a bit more, I’ve discovered this to be incorrect. To actually terminate the worker, you can use the close method from within the worker, or the terminate method from the caller, so a queuing mechanism is a feasible solution to deal with browser limits on the number of executing web workers.
  • When posting a message from worker to caller (via postMessage), the handler function within the caller seems to be executed within the worker thread.
  • You can’t pass a function to a worker. You pass data between worker and caller by copying the data (serializing/de-serializing an object by structured cloning) or giving ownership of the object to the worker (transferable objects). This allows for a great deal of thread-safety, but in a language like Javascript where functions are first-class citizens, it’s hard not to see the elegance of being able to simply spawn off a worker from a function.
  • Given an upper limit on the number of executing web workers, a spawn-and-forget (or spawn-and-wait) model for concurrency is not practical. A thread pool pattern may be appropriate. In general, each worker should be thought of as a heavy-weight processing engine.
    EDIT:This is perhaps more true not because of browser limits on the number of workers, but the fact that workers were designed with the expectation of them being long-lived, with high performance and memory costs.

All my work was in Firefox, so the points above may not necessarily be true for other browsers.

A better toggle button, with jQuery and CSS3

One of my more popular articles on this blog has been my jQuery toggle button article. However, my thinking has changed a lot since writing that post and, approaching the problem now, I’d likely do things differently. There were a few key flaws in my approach:

  • Using an additional image for the border. border-radius was still new at the time, but even so I think it would have been better to develop for the bleeding edge, and then deal with fallback for older tech.
  • Using jQuery animate. While I like Javascript as a control mechanism for animations, Javascript-based animations are another matter entirely. CSS3 transitions and transformations are a much better solution, they’re easier to handle and performance is, almost always, much better. Again, this was because I was avoiding the bleeding edge and focusing too much on backward compatibility, as transition and transform were still very new at the time.
  • Not making it a jQuery plugin. There was so much of a dependency on jQuery for selection, modifying the DOM, etc. that wrapping everything in a jQuery plugin made sense. My thinking was always that by not being bound too closely to jQuery, you can always just rip-out the jQuery bits and have a slim, pure JS component. However, there are 2 problems with this idea:
    • it’s not always that easy to rip-out jQuery, and doing so usually means re-creating much of the abstraction and utility functions offered by jQuery
    • plugin or not, you can still end up coupling heavily with jQuery
  • Widgetizing the HTML/CSS. The flaw here is writing out HTML and inline CSS from a Javascript string to create the button, which is usually not a good idea. It’s usually better to leave markup and styling in the document, where they can be readily manipulated or re-style. This is in line with my rant about Enyo (and widget frameworks in general), where I mentioned that widgets lead to a significant loss of flexibility. There is a case to be made for a toggle button widget, as it enables you to automatically replace checkboxes with toggle buttons without modifying any HTML but, in the general, I don’t think it’s worth it.

Below is an updated toggle button accompanied by the code that creates it. As in my previous post, the button itself is a single image, applied as a background-image to an anchor tag, and state transitions are done by shifting the background-position of the element.

Live Demo

HTML

<!-- toggle button markup -->
<a id="btn-toggle" class="btn-toggle" href="#">
    <
input name="yesno" type="checkbox" checked="checked" />
</
a>

CSS

/* toggle button style, styled for initial state (off) */
a.btn-toggle { margin:0; padding:0; display:block; border-radius:32px; background:url(base.png) -57px 0px no-repeat transparent; width:98px; height:64px; }

/* toggle button active state (on) */
a.btn-toggle.active { background-position:-7px 0px; border-color:#40A1EC; }

/* hide the underlying input checkbox of the toggle button */
a.btn-toggle input { display:none; }

Javascript

// jQuery plugin for toggle button
(function( $ ){

    $.fn.makeToggleButton =
function() {
        
    
this.each(function() {
            
            
var elem = $(this);
                    
            
// get the state of the underlying input checkbox
            
elem.val = function() {
                
return elem.find('input').is(':checked');
            }
                    
            
// function to toggle button state
            
elem.toggle = function() {
                    
                
var chkbx = elem.find('input');                    
                
if (!chkbx.is(':checked')) { // not check, switch on
                        
                    
elem.addClass('active');
                    chkbx.attr(
'checked', true);
                }
                
else {

                    elem.removeClass(
'active');
                    chkbx.attr(
'checked', false);
                }
            }
                    
            
// click handler
            
elem.click(function(e) {                    
                elem.toggle();
                e.preventDefault();                    
            });
                    
            
// adjust state to initial value of input checkbox
            
if(elem.find('input').is(':checked'))
            {
                elem.addClass(
'active');
            }
                    
            
// setTimeout to prevent transition upon setting initial state to active
            
setTimeout(function() {
                elem.css(
'transition', 'background-position 0.4s');
                elem.css(
'-webkit-transition', 'background-position 0.4s');
                elem.css(
'-moz-transition', 'background-position 0.4s');
                elem.css(
'-o-transition', 'background-position 0.4s');
                elem.css(
'-ms-transition', 'background-position 0.4s');
            }, 50 );
                
        });


    
return this;
            
    };
})( jQuery );        


// make toggle button when document is ready
$(document).ready(function() {
    $(
'#btn-toggle').makeToggleButton();
});