<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:series="http://organizeseries.com/"
> <channel><title>SitePoint &#187; jQuery</title> <atom:link href="http://www.sitepoint.com/category/javascript/jquery/feed/" rel="self" type="application/rss+xml" /><link>http://www.sitepoint.com</link> <description>Learn CSS &#124; HTML5 &#124; JavaScript &#124; Wordpress &#124; Tutorials-Web Development &#124; Reference &#124; Books and More</description> <lastBuildDate>Mon, 13 May 2013 13:12:07 +0000</lastBuildDate> <language>en-US</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.5.1</generator> <item><title>Unheap.com: a Better jQuery Plugin Repository?</title><link>http://www.sitepoint.com/unheap-jquery-plugin-repository/</link> <comments>http://www.sitepoint.com/unheap-jquery-plugin-repository/#comments</comments> <pubDate>Fri, 03 May 2013 16:36:48 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[Open source]]></category> <category><![CDATA[Tools and Libraries]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[plugins]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=65656</guid> <description><![CDATA[Do you need a jQuery plugin? Are you finding it difficult to locate one on the official repository? Craig suggests Unheap.com may be a better alternative...]]></description> <content:encoded><![CDATA[<p></p><p>I&#8217;ve never been <a
href="http://www.sitepoint.com/jquery-plugins-registry/">particularly complimentary</a> about the <a
href="http://plugins.jquery.com/">official jQuery Plugin Registry</a>. The team are working on it, but perhaps the kindest observation is that it&#8217;s <em>&#8220;ctional&#8221;</em> &#8212; functional with all the &#8220;fun&#8221; removed. The system lacks an easy interface, good search facilities, online demonstrations, developer ratings and reviews.</p><p>As an alternative, why not try <a
href="http://www.unheap.com/"><strong>unheap.com</strong></a> &#8212; a new independent jQuery plugin repository&hellip;</p><p><a
href="http://www.unheap.com/"><img
src="http://blogs.sitepointstatic.com/images/tech/821-unheap-jquery-plugins.jpg" alt="Unheap.com" class="center" /></a></p><p>The benefits of <a
href="http://www.unheap.com/"><strong>unheap.com</strong></a> become apparent the moment you use it:</p><ul><li>The site has a gorgeous dynamic and responsive interface &#8212; it&#8217;s a pleasure to use</li><li>Plugins are categorized in sections and sub-sections for interface, inputs, media, navigation and miscellaneous code.</li><li>The search facility works well.</li><li>Plugin lists have direct links to demonstration pages and videos.</li><li>Related plugins are listed.</li><li>User views, votes and bug reports are recorded.</li><li>Social media sharing facilities are provided.</li><li>An RSS feed of new and updated plugins is available for you to check in <a
href="http://www.sitepoint.com/goodbye-google-reader/"><s>Google Reader</s></a>, erm, a compatible RSS Reader.</li><li>The <a
href="http://www.unheap.com/submit">plugin submission process</a> is easy and straight-forward.</li><li>Almost 700 plugins are available at the time of writing.</li></ul><p>I&#8217;m impressed. Unless the jQuery team can produce a system as nice as <a
href="http://www.unheap.com/">unheap.com</a>, perhaps they should give up now and adopt it as the &#8220;official&#8221; repository?</p><p>Unless you&#8217;ve found something better?&hellip;</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/unheap-jquery-plugin-repository/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>How to Build an Instagram-like Photo Sharing App with HTML5: Part 2</title><link>http://www.sitepoint.com/how-to-build-an-instagram-like-photo-sharing-app-with-html5-part-2/</link> <comments>http://www.sitepoint.com/how-to-build-an-instagram-like-photo-sharing-app-with-html5-part-2/#comments</comments> <pubDate>Fri, 26 Apr 2013 15:55:52 +0000</pubDate> <dc:creator>Rajasekharan Vengalil</dc:creator> <category><![CDATA[CSS]]></category> <category><![CDATA[CSS3]]></category> <category><![CDATA[HTML]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=65642</guid> <description><![CDATA[In Part 1, Rajasekharan Vengalil laid out the implementation details of his InstaFuzz app built with HTML5, CSS and JS. Here, he shows how Drag/Drop, File API, Canvas and Web Workers can be used.]]></description> <content:encoded><![CDATA[<p></p><p>In <a
href="http://www.sitepoint.com/how-to-build-an-instagram-like-photo-sharing-app-with-html5/">part 1</a> we took a look at some of the UI layout implementation details of the <a
href="http://blogorama.nerdworks.in/arbit/InstaFuzz/" target="_blank">InstaFuzz</a> app.  You can get the source code for the app from <a
href="http://sdrv.ms/14B672O" target="_blank">here</a> if you wish to run it locally.  In this installment we’ll take a look at some of the other bits such as how drag/drop, File API, Canvas and Web Workers are used.</p><h2>Drag/Drop</h2><p>One of the things that <i>InstaFuzz</i> supports is the ability to drag and drop image files directly on to the big blackish/blue box.  Support for this is enabled by handling the “drop” event on the CANVAS element.  When a file is dropped onto an HTML element the browser fires the “drop” event on that element and passes in a <a
href="http://aka.ms/dataTransfer"><i>dataTransfer</i></a> object which contains a <a
href="http://aka.ms/filesproperty"><i>files</i> property</a> that contains a reference to the list of files that were dropped.  Here’s how this is handled in the app (“picture” is the ID of the CANVAS element on the page):<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><pre>var pic = $("#picture");
pic.bind("drop", function (e) {
    suppressEvent(e);
    var files = e.originalEvent.dataTransfer.files;
    // more code here to open the file
});
&nbsp;
pic.bind("dragover", suppressEvent).bind("dragenter", suppressEvent);
&nbsp;
function suppressEvent(e) {
    e.stopPropagation();
    e.preventDefault();
}</pre><p>The <i>files</i> property is a collection of <a
href="http://aka.ms/FileObject"><i>File</i> objects</a> that can then subsequently be used with the File API to access the file contents (covered in the next section).  We also handle the <i>dragover</i> and <i>dragenter</i> events and basically prevent those events from propagating to the browser thereby preventing the browser from handling the file drop.  IE for instance might unload the current page and attempt to open the file directly otherwise.</p><h2>File API</h2><p>Once the file has been dropped, the app attempts to open the image and render it in the canvas.  It does this by using the <a
href="http://aka.ms/FileAPI">File API</a>.  The File API is a W3C specification that allows web apps to programmatically access files from the local file system in a secure fashion.  In <i>InstaFuzz</i> we use the <a
href="http://aka.ms/FileReaderObject"><i>FileReader</i> object</a> to read the file contents as a <a
href="http://aka.ms/dataProtocol">data URL</a> string like so using the <a
href="http://aka.ms/readAsDataURLmethod"><i>readAsDataURL</i></a> method:</p><pre>var reader = new FileReader();
reader.onloadend = function (e2) {
    drawImageToCanvas(e2.target.result);
};
reader.readAsDataURL(files[0]);</pre><p>Here, <i>files</i> is the collection of <i>File</i> objects retrieved from the function handling the “drop” event on the CANVAS element. Since we are interested only in a single file we simply pick the first file from the collection and ignore the rest if there are any.  The actual file contents are loaded asynchronously and once the load completes, the <a
href="http://aka.ms/onloadend"><i>onloadend</i></a> event is fired where we get the file contents as a data URL which we then subsequently draw on to the canvas.</p><h2>Rendering the filters</h2><p>Now the core functionality here is of course the application of the filters.  In order to be able to apply the filter to the image we need a way to access the individual pixels from the image.  And before we can access the pixels we need to have actually rendered the image on to our canvas.  So let’s first take a look at the code that renders the image that the user picked on to the canvas element.</p><h3>Rendering images on to the canvas</h3><p>The canvas element supports the rendering of <i>Image</i> objects via the <a
href="http://aka.ms/drawImage"><i>drawImage</i></a> method.  To load up the image file in an <i>Image</i> instance, <i>InstaFuzz</i> uses the following utility routine:</p><pre>App.Namespace.define("InstaFuzz.Utils", {
    loadImage: function (url, complete) {
        var img = new Image();
        img.src = url;
        img.onload = function () {
            complete(img);
        };
    }
});</pre><p>This allows the app to load up image objects from a URL using code such as the following:</p><pre>function drawImageToCanvas(url) {
    InstaFuzz.Utils.loadImage(url, function (img) {
        // save reference to source image
        sourceImage = img;
&nbsp;
        mainRenderer.clearCanvas();
        mainRenderer.renderImage(img);
&nbsp;
        // load image filter previews
        loadPreviews(img);
    });
}</pre><p>Here, <i>mainRenderer</i> is an instance created from the <i>FilterRenderer</i> constructor function defined in <i>filter-renderer.js</i>.  The app uses <i>FilterRenderer</i> objects to manage canvas elements – both in the preview pane as well as the main canvas element on the right.  The <i>renderImage</i> method on the <i>FilterRenderer</i> has been defined like so:</p><pre>FilterRenderer.prototype.renderImage = function (img) {
    var imageWidth = img.width;
    var imageHeight = img.height;
    var canvasWidth = this.size.width;
    var canvasHeight = this.size.height;
    var width, height;
&nbsp;
    if ((imageWidth / imageHeight) &gt;= (canvasWidth / canvasHeight)) {
        width = canvasWidth;
        height = (imageHeight * canvasWidth / imageWidth);
    } else {
        width = (imageWidth * canvasHeight / imageHeight);
        height = canvasHeight;
    }
&nbsp;
    var x = (canvasWidth - width) / 2;
    var y = (canvasHeight - height) / 2;
    this.context.drawImage(img, x, y, width, height);
};</pre><p>That might seem like a lot of code but all it does ultimately is to figure out the best way to render the image in the available screen area considering the aspect ratio of the image.  The key piece of code that actually renders the image on the canvas occurs on the last line of the method.  The <i>context</i> member refers to the 2D context acquired from the canvas object by calling its<a
href="http://aka.ms/getContext"> <i>getContext</i></a> method.</p><h3>Fetching pixels from the canvas</h3><p>Now that the image has been rendered we will need access to the individual pixels in order to apply all the different filters that are available.  This is easily acquired by calling <a
href="http://aka.ms/getImageData"><i>getImageData</i></a> on the canvas’s context object.  Here’s how <i>InstaFuzz</i> calls this from <i>instafuzz.js</i>.</p><pre>var imageData = renderer.context.getImageData(
    0, 0,
    renderer.size.width,
    renderer.size.height);</pre><p>The object returned by <i>getImageData</i> provides access to the individual pixels via its <i>data</i> property which in turn is an array like object that contains a collection of byte values where each value represents the color rendered for a single channel of a single pixel.  Each pixel is represented using 4 bytes that specify values for the red, green, blue and alpha channels.  It also has a <a
href="http://aka.ms/lengthProperty"><i>length</i></a><i> </i>property that returns the length of the buffer.  If you have a 2D co-ordinate you can easily transform that into an index into this array using code such as the following.  The color intensity values of each channel ranges from 0 through 255.  Here’s the utility function from <i>filters.js</i> that accepts as input an image data object along with 2D coordinates for the pixel the caller is interested in and returns an object containing the color values:</p><pre>function getPixel(imageData, x, y) {
    var data = imageData.data, index = 0;
&nbsp;
    // normalize x and y and compute index
    x = (x &lt; 0) ? (imageData.width + x) : x;
    y = (y &lt; 0) ? (imageData.height + y) : y;
    index = (x + y * imageData.width) * 4;
&nbsp;
    return {
        r: data[index],
        g: data[index + 1],
        b: data[index + 2]
    };
}</pre><h3>Applying the filters</h3><p>Now that we have access to the individual pixels, applying the filter is fairly straightforward.  Here, for instance is the function that applies a weighted grayscale filter on the image.  It simply picks intensities from the red, green and blue channels and sums them up after applying a multiplication factor on each channel and then assigns the result for all 3 channels.</p><pre>// "Weighted Grayscale" filter
Filters.addFilter({
    name: "Weighted Grayscale",
    apply: function (imageData) {
        var w = imageData.width, h = imageData.height;
        var data = imageData.data;
        var index;
        for (var y = 0; y &lt; h; ++y) {
            for (var x = 0; x &lt; w; ++x) {
                index = (x + y * imageData.width) * 4;
                var luminance = parseInt((data[index + 0] * 0.3) +
                                         (data[index + 1] + 0.59) +
                                         (data[index + 2] * 0.11));
                data[index + 0] = data[index + 1] =
                    data[index + 2] = luminance;
            }
&nbsp;
            Filters.notifyProgress(imageData, x, y, this);
        }
&nbsp;
        Filters.notifyProgress(imageData, w, h, this);
    }
});</pre><p>Once the filter has been applied we can have that reflected on the canvas by calling the <a
href="http://aka.ms/putImageData"><i>putImageData</i></a> method passing in the modified image data object.  While the weighted grayscale filter is fairly simple most of the other filters use an image processing technique known as <i>convolution</i>.  The code for all the filters is available in <i>filters.js</i> and the convolution filters were ported from the C code available <a
href="http://lodev.org/cgtutor/filtering.html">here</a>.</p><h2>Web Workers</h2><p>As you might imagine doing all this number crunching to apply the filters can potentially take a long time to complete.  The <i>motion blur</i> filter for instance uses a 9&#215;9 filter matrix for computing the new value for every single pixel and is in fact the most CPU intensive filter among them all.  If we were to do all this computation on the UI thread of the browser then the app would essentially freeze every time a filter was being applied.  To provide a responsive user experience the app delegates the core image processing tasks to a background script using the support for W3C <a
href="http://aka.ms/WebWorkers">Web Workers</a> in modern browsers.</p><p>Web workers allow web applications to have scripts run in a background task that executes in parallel along with the UI thread.  Communication between the worker and the UI thread is accomplished by passing messages using the <a
href="http://aka.ms/postMessage"><i>postMessage</i></a> API.  On both ends (i.e. the UI thread and the worker) this manifests as an event notification that you can handle.  You can only pass “data” between workers and the UI thread, i.e., you cannot pass anything that has to do with the user interface  – you cannot for instance, pass DOM elements to the worker from the UI thread.</p><p>In <i>InstaFuzz</i> the worker is implemented in the file <i>filter-worker.js</i>.  All it does in the worker is handle the <a
href="http://aka.ms/onmessage"><i>onmessage</i></a> event and apply a filter and then pass the results back via <i>postMessage</i>.  As it turns out, even though we cannot pass DOM elements (which means we cannot just hand a CANVAS element to the worker to have the filter applied) we can in fact pass the image data object as returned by the <i>getImageData</i> method that we discussed earlier. Here’s the filter processing code from <i>filter-worker.js</i>:</p><pre>importScripts("ns.js", "filters.js");
&nbsp;
var tag = null;
onmessage = function (e) {
    var opt = e.data;
    var imageData = opt.imageData;
    var filter;
&nbsp;
    tag = opt.tag;
    filter = InstaFuzz.Filters.getFilter(opt.filterKey);
&nbsp;
    var start = Date.now();
    filter.apply(imageData);
    var end = Date.now();
&nbsp;
    postMessage({
        type: "image",
        imageData: imageData,
        filterId: filter.id,
        tag: tag,
        timeTaken: end - start
    });
}</pre><p>The first line pulls in some script files that the worker depends on by calling <a
href="http://aka.ms/importScripts"><i>importScripts</i></a>.  This is similar to including a JavaScript file in a HTML document using the SCRIPT tag.  Then we set up a handler for the <i>onmessage</i> event in response to which we simply apply the filter in question and pass the result back to the UI thread by calling <i>postMessage</i>.  Simple enough!</p><p>The code that initializes the worker is in <i>instafuzz.js</i> and looks like this:</p><pre>var worker = new Worker("js/filter-worker.js");</pre><p>Not much is it?  When a message is sent by the worker to the UI thread we handle it by specifying a handler for the <i>onmessage</i> event on the worker object.  Here’s how this is done in <i>InstaFuzz</i>:</p><pre>worker.onmessage = function (e) {
    var isPreview = e.data.tag;
    switch (e.data.type) {
        case "image":
            if (isPreview) {
                previewRenderers[e.data.filterId].
                    context.putImageData(
                        e.data.imageData, 0, 0);
            } else {
                mainRenderer.context.putImageData(
                    e.data.imageData, 0, 0);
            }
&nbsp;
            break;
        // more code here
    }
};</pre><p>The code should be fairly self-explanatory.  It simply picks the image data object sent by the worker and applies it to the relevant canvas’s context object causing the modified image to be rendered on screen.  Scheduling a filter for conversion with the worker is equally simple.  Here’s the routine that performs this function in <i>InstaFuzz</i>:</p><pre>function scheduleFilter(filterId,
                             renderer,
                             img, isPreview,
                             resetRender) {
    if (resetRender) {
        renderer.clearCanvas();
        renderer.renderImage(img);
    }
&nbsp;
    var imageData = renderer.context.getImageData(
        0, 0,
        renderer.size.width,
        renderer.size.height);
&nbsp;
    worker.postMessage({
        imageData: imageData,
        width: imageData.width,
        height: imageData.height,
        filterKey: filterId,
        tag: isPreview
});
}</pre><h2>Wrapping it up</h2><p>The source for <i>InstaFuzz</i> is available for download <a
href="http://sdrv.ms/11110mf">here</a>.  We saw that fairly intricate user experiences are possible today with HTML5 technologies such as Canvas, Drag/Drop, File API and Web Workers.  Support for all of these technologies is quite good in pretty much all modern browsers.  One thing that we did not address here is the question of making the app compatible with older browsers.  That, truth be told, is a non-trivial but necessary task that I will hopefully be able to talk about in a future article.</p><div><p><em>This article is part of the HTML5 tech series from the Internet Explorer team. <a
href="http://www.microsoft.com/click/services/Redirect2.ashx?CR_CC=200210648">Try-out</a> the concepts in this article with three months of free BrowserStack cross-browser testing @ <a
href="http://modern.ie/">http://modern.IE</a></em></div><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/how-to-build-an-instagram-like-photo-sharing-app-with-html5-part-2/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>How to Build an Instagram-like Photo Sharing App with HTML5</title><link>http://www.sitepoint.com/how-to-build-an-instagram-like-photo-sharing-app-with-html5/</link> <comments>http://www.sitepoint.com/how-to-build-an-instagram-like-photo-sharing-app-with-html5/#comments</comments> <pubDate>Thu, 25 Apr 2013 14:16:53 +0000</pubDate> <dc:creator>Rajasekharan Vengalil</dc:creator> <category><![CDATA[CSS]]></category> <category><![CDATA[CSS3]]></category> <category><![CDATA[HTML]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=65596</guid> <description><![CDATA[Rajaskharan Vengalil set out to see if an app like Instagram could be built using only HTML, CSS and JavaScript. Turns out it is (sorry, belated spoiler alert!).]]></description> <content:encoded><![CDATA[<p></p><p>When I started out on this app I was only really just interested in seeing if the web platform had really evolved to a point where an app like the hugely popular <a
href="http://aka.ms/Instragram">Instagram</a> app could be built using just HTML, JavaScript and CSS.</p><p>As it turns out we can in fact do exactly that.  This article walks you through the technologies that make this possible and shows how it is entirely feasible today to build interoperable web applications that provide a great user experience no matter what brand of browser the user is running.</p><p>If you happen to be one of the two or so people who have not heard about <i>Instagram</i> then you might be pleased to hear that it is a hugely popular photo sharing and social networking service that allows you to take pictures, apply interesting digital filters on them and share them with the world.  The service became so popular that it was <a
href="http://finance.fortune.cnn.com/2012/04/09/breaking-facebook-buying-instagram-for-1-billion/">acquired by Facebook</a> for a bag full of cash and stock in April of 2012.</p><p><a
href="http://aka.ms/InstaFuzz">InstaFuzz</a> is the name of the app I put together and while I don’t expect to be acquired by Facebook or anybody else for a billion green it does, however, make the case that an app such as this one can be built using only standards compliant web technologies such as Canvas, File API, Drag/Drop, Web Workers, ES5 and CSS3 and still manage to run well on modern browsers such as <a
href="http://www.microsoft.com/click/services/Redirect2.ashx?CR_CC=200210648">Internet Explorer 10</a>, Google Chrome and Firefox.  And you could easily use the code to <a
href="http://www.microsoft.com/click/services/Redirect2.ashx?CR_CC=200185226">build a Windows Store app</a> too.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><h2>About the app</h2><p>If you’d like to take a look at the app, then here’s where it is hosted:</p><p><a
href="http://aka.ms/InstaFuzz">http://blogorama.nerdworks.in/arbit/InstaFuzz/</a></p><p>As soon as you load it up, you’re presented with a screen that looks like this:</p><p><img
class="alignnone size-full wp-image-65597" alt="Instafuzz default" src="http://www.sitepoint.com/wp-content/uploads/1/files/2013/04/figure19.png" width="463" height="384" /></p><p>The idea is that you can load up a photograph into the app either by clicking on the big red “Add” button on the bottom left hand corner or drag and drop an image file into the blackish/blue area on the right. Once you do that you get something that looks like this:</p><p><img
class="alignnone size-full wp-image-65598" alt="Add an image" src="http://www.sitepoint.com/wp-content/uploads/1/files/2013/04/figure24.png" width="463" height="385" /></p><p>You’ll note that a list of digital filters listed on the left of the screen shows a preview of what the image would look like if you were to apply the said filter.  Applying a filter is a simple matter of clicking on one of the filter previews on the left.  Here’s what it looks like after applying the “Weighted Grayscale” filter followed by a “Motion Blur”.  As you can tell filters are <i>additive</i> – as you keep clicking on filters, they are applied on top of what was applied earlier:</p><p><img
class="alignnone size-full wp-image-65599" alt="filter applied" src="http://www.sitepoint.com/wp-content/uploads/1/files/2013/04/figure34.png" width="462" height="385" /></p><p>Let’s next take a look at how the UI layout has been put together.</p><h2>UI Layout</h2><p>The HTML markup is so little that I can actually reproduce the contents of the BODY tag in its entirety here (excluding the SCRIPT includes):</p><pre>&lt;header&gt;
    &lt;div id="title"&gt;InstaFuzz&lt;/div&gt;
&lt;/header&gt;
&lt;section id="container"&gt;
    &lt;canvas id="picture" width="650" height="565"&gt;&lt;/canvas&gt;
    &lt;div id="controls"&gt;
        &lt;div id="filters-list"&gt;&lt;/div&gt;
        &lt;button id="loadImage"&gt;Add&lt;/button&gt;
        &lt;input type="file" id="fileUpload"
           style="display: none;"
           accept="image/gif, image/jpeg, image/png" /&gt;
    &lt;/div&gt;
&lt;/section&gt;
&amp;nbsp;
&lt;!-- Handlebar template for a filter UI button --&gt;
&amp;nbsp;
&lt;script id="filter-template" type="text/x-handlebars-template"&gt;
    &lt;div data-filter-id="<b>{{</b>filterId<b>}}</b>"&gt;
        &lt;div&gt;<b>{{</b>filterName<b>}}</b>&lt;/div&gt;
        &lt;canvas width="128" height="128"&gt;&lt;/canvas&gt;
    &lt;/div&gt;
&lt;/script&gt;</pre><p>There’s nothing much going on here.  Pretty much everything should be standard fare.  I will however draw attention to the fact that I am using the <a
href="http://handlebarsjs.com/">Handlebars</a> JavaScript templating system here for rendering the markup for the list of filters on the left of the screen.  The template markup is declared in the HTML file (the SCRIPT tag in the snippet shown above) and then used from JavaScript.  The template markup is then bound to a JavaScript object that supplies the values for handlebars expressions such as <i>{{filterId}}</i> and <i>{{filterName}}.</i>  Here’s the relevant piece of JS from the app with a bit of DOM manipulation help from <a
href="http://jquery.com/">jQuery</a>:</p><pre>var templHtml = $("#filter-template").html(),
    template = Handlebars.compile(templHtml),
    filtersList = $("#filters-list");
&amp;nbsp;
var context = {
    filterName: filter.name,
    filterId: index
};
&amp;nbsp;
filtersList.append(template(context));</pre><p>As you can tell from the HTML markup, all the filter preview boxes feature a CANVAS tag, as does the big box on the right where the final output is rendered.  We’ll go into a bit more detail later on in the article as to how canvas technology is used to achieve these effects.</p><p>The app also uses<a
href="http://aka.ms/fontface"> CSS3 @font-face</a> fonts to render the text in the header and the “Add” button.  The fonts have been taken from the excellent <a
href="http://aka.ms/FontSquirrel">Font Squirrel</a> site and here’s what the declaration looks like:</p><pre>@font-face {
    font-family: 'TizaRegular';
    src: url('fonts/tiza/tiza-webfont.eot');
    src: url('fonts/tiza/tiza-webfont.eot?#iefix')
           format('embedded-opentype'),
         url('fonts/tiza/tiza-webfont.woff') format('woff'),
         url('fonts/tiza/tiza-webfont.ttf') format('truetype'),
         url('fonts/tiza/tiza-webfont.svg#TizaRegular') format('svg');
    font-weight: normal;
    font-style: normal;
}</pre><p>This directive causes the user agent to embed the font in the page and make it available under the name assigned to the <i>font-family</i> rule which in this case is “TizaRegular”.  After this we can assign this font to any CSS <i>font-family</i> rule like how we normally do.  In <i>InstaFuzz</i> I use the following rule to assign the font to the header element:</p><pre>font-family: TizaRegular, Cambria, Cochin, Georgia, Times,
    "Times New Roman", serif;</pre><p>You might also have noticed that there is a subtle shadow being dropped on the page by the container element.</p><p>This is made possible using the <a
href="http://aka.ms/boxshadowproperty">CSS3 box-shadow</a> rule and here’s how it’s used in <i>InstaFuzz</i>.</p><pre>-moz-box-shadow: 1px 0px 4px #000000, -1px -1px 4px #000000;
-webkit-box-shadow: 1px 0px 4px #000000, -1px -1px 4px #000000;
box-shadow: 1px 0px 4px #000000, -1px -1px 4px #000000;</pre><p>This causes the browser to render a shadow around the relevant element.  Each comma separated section in the value specifies the following attributes of the shadow:</p><ol><li>Horizontal offset</li><li>Vertical offset</li><li>Spread distance – positive values have the effect of softening the shadow</li><li>Shadow color</li></ol><p>One can specify multiple shadow values separated by comma as in fact has been done above.  Note that I’ve also specified the shadow using vendor prefix syntax for Firefox and Chrome/Safari using the <i>moz</i> and <i>webkit</i> prefixes.  This causes the shadow to continue to work in versions of those browsers where support for this capability was provided using the vendor prefixed version of the rule.  Note that the W3C version of the rule – <i>box-shadow</i> – is specified last.  This is done deliberately to ensure that in case the browser supports both the forms then only the W3C behavior is actually applied to the page.</p><p>One often finds that web developers either fail to include vendor prefixed version of a given CSS3 rule for all the browsers that support that rule and/or fail to include the W3C version as well.  Often developers just put the <i>webkit</i> version of the rule ignoring other browsers and the W3C standard version.  This causes two problems – [1] poor user experience for users who are using non-webkit browsers and [2] it ends up resulting in webkit becoming a de-facto standard for the web.  Ideally we want W3C to be driving the future of the web and not one specific browser implementation.  So here are some things to remember when playing with experimental implementations of CSS features:</p><ol><li>Use vendor prefixed versions of CSS rules by all means but remember to specify the rule for all supported browsers and not just the one that you happen to be testing the page in (if you’re using <a
href="http://www.microsoft.com/click/services/Redirect2.ashx?CR_CC=200117040" class="broken_link">Visual Studio</a> to edit your CSS then you might be interested in the supremely excellent extension for Visual Studio called <a
href="http://aka.ms/WebEssentials"><i>Web Essentials</i></a> that makes the job of managing vendor prefixes about as simple as it can possibly get).</li><li>Remember to specify the W3C version of the rule as well.</li><li>Remember to order the occurrence of the rules so that the W3C version shows up last.  This is to allow clients that support both the vendor prefixed version and the W3C version to use the W3C specified semantics for the rule.</li></ol><p>That’s all for now.  In the next and final article in this series, we’ll take a look at how the app supports drag/drop of files, the use of File API, how the filters themselves work and how we prevent the UI thread from freezing by delegating the core number crunching work to web workers.</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/how-to-build-an-instagram-like-photo-sharing-app-with-html5/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>What&#8217;s New in jQuery 2.0</title><link>http://www.sitepoint.com/whats-new-in-jquery-2-0/</link> <comments>http://www.sitepoint.com/whats-new-in-jquery-2-0/#comments</comments> <pubDate>Sat, 20 Apr 2013 08:30:51 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[Ajax]]></category> <category><![CDATA[HTML]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[Libraries]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <category><![CDATA[javascript]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=65533</guid> <description><![CDATA[jQuery 2.0 has been released. There is one new feature, but it's a big change. Craig provides the details...]]></description> <content:encoded><![CDATA[<p></p><p>The second branch of the web&#8217;s most popular JavaScript library was released on April 18, 2013. <a
href="http://jquery.com/download/">jQuery 2.0 is now available for download</a> but don&#8217;t rush off and install it just yet &#8212; there is one major change&hellip;</p><h2>No More Support for IE6/7/8</h2><p><em>(or IE9 and IE10 if they&#8217;re used in &#8220;Compatibility View&#8221; mode).</em></p><p>I still think it&#8217;s a little premature to abandon IE8 but the team couldn&#8217;t wait any longer. jQuery 2.0 removes all the legacy IE code for node selection, DOM manipulation, event handling and Ajax.</p><p>This has resulted in a 11% file size reduction from 32,819 bytes to 29,123 bytes. That&#8217;s 3.6Kb for the gzipped minified version &#8212; it&#8217;s unlikely to be noticeable even on a dial-up connection. Admittedly, the team hoped to save more but discovered that Android/Webkit 2.x browsers still required many workarounds.</p><p>If you need to support IE8 and below, stick with jQuery 1.9.x for now. You could conditionally load version 2.0 in all other browsers, but:</p><ol><li>conditional loading will offset any gains in file size reduction and processing, and</li><li>you may encounter differences between the two jQuery branches. The team has pledged to minimize API divergence but there will almost certainly be issues. jQuery 1.10 will address known compatibility problems.</li></ol><h2>Custom Builds</h2><p>The custom build feature has been refined in version 2.0 so you can exclude any of 12 unused modules and shrink jQuery below 10Kb. The modules which can be omitted are:</p><ul><li><strong>ajax</strong>: all Ajax functionality, transports, and event shorthands.</li><li><strong>ajax/xhr</strong>: XMLHTTPRequest Ajax transport only.</li><li><strong>ajax/script</strong>: <code>&lt;script&gt;</code> Ajax transport only.</li><li><strong>ajax/jsonp</strong>: JSONP Ajax transport only (depends on ajax/script).</li><li><strong>css</strong>: The <code>.css()</code> method plus non-animated <code>.show()</code>, <code>.hide()</code> and <code>.toggle()</code>.</li><li><strong>deprecated</strong>: deprecated methods (currently <code>.andSelf()</code> only).</li><li><strong>dimensions</strong>: <code>.width()</code> and <code>.height()</code> methods, including <code>inner-</code> and <code>outer-</code> variations.</li><li><strong>effects</strong>: the <code>.animate()</code> method and its shorthands such as <code>.slideUp()</code>.</li><li><strong>event-alias</strong>: event attaching/triggering shorthands such as <code>.click()</code>.</li><li><strong>offset</strong>: the <code>.offset()</code>, <code>.position()</code>, <code>.offsetParent()</code>, <code>.scrollLeft()</code>, and <code>.scrollTop()</code> methods.</li><li><strong>wrap</strong>: the <code>.wrap()</code>, <code>.wrapAll()</code>, <code>.wrapInner()</code>, and <code>.unwrap()</code> methods.</li><li><strong>sizzle</strong>: the Sizzle selector engine. When this module is excluded, it is replaced by a rudimentary selector engine based on the native <code>querySelectorAll</code> method which does not support some advanced jQuery selectors.</li></ul><p>For example, if you are using CSS3 animations rather than jQuery methods, you could omit the <strong>effects</strong> module and possibly <strong>dimensions</strong>, <strong>offset</strong>, <strong>wrap</strong> and <strong>sizzle</strong>.</p><p>Creating your own custom build is not for the faint-hearted and you&#8217;ll require some knowledge of Git, Node.js and Grunt. <a
href="https://github.com/jquery/jquery/#readme">Full instructions are available</a> but, longer term, I hope the team can implement an online build process similar to <a
href="http://modernizr.com/download/">Modernizr</a>.</p><h2>Should I Upgrade?</h2><p>It&#8217;s important to understand that jQuery 2.0 has API parity with jQuery 1.9. There are a small number of bug fixes but no new features.</p><p>However, if you&#8217;re one of those lucky developers who has dropped support for IE6/7/8, <a
href="http://jquery.com/download/">grab jQuery 2.0</a> and don&#8217;t look back.</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/whats-new-in-jquery-2-0/feed/</wfw:commentRss> <slash:comments>22</slash:comments> </item> <item><title>Selective Content Loading</title><link>http://www.sitepoint.com/selective-content-loading/</link> <comments>http://www.sitepoint.com/selective-content-loading/#comments</comments> <pubDate>Wed, 03 Apr 2013 13:32:22 +0000</pubDate> <dc:creator>Andrew Fisher</dc:creator> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[Programming]]></category> <category><![CDATA[Responsive Web Design]]></category> <category><![CDATA[Tools and Libraries]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=65082</guid> <description><![CDATA[Andrew Fisher, co-author of <em>Jump Start Responsive Web Design</em>, expands on the technique called selective content loading, referred to in the book.]]></description> <content:encoded><![CDATA[<p></p><p>One of the techniques we talk about in <a
href="http://www.sitepoint.com/books/responsive1/">Jump Start Responsive Web Design</a> is called Selective Content Loading (SCL). This technique is really useful in situations where you want to load small pieces of data into an already loaded page in a structured way. When would this be useful?</p><ul><li> When you have serious bandwidth issues between your server and the end user’s device (for example, on a mobile connection that is moving on a poor network with lots of errors and having to deal with cell handoff).</li><li> When your pages are largely the same structurally from page to page and simply reloading the content saves many requests.</li><li> If you have chunked your content nicely and want to simply load in the next piece in the sequence (for example, infinite scrolling on a Twitter feed)</li></ul><p>Some of these issues can be dealt with by good caching and using local storage and these should definitely be explored as good practices generally. However, even with smart asset caching you still require server round trips to retrieve a document, all the page HTML still has to be sent to the browser and then the browser still has to render the page.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>If your page has only added a couple of additional bits of data (for example, a tweet) or is only changing a small amount of content (for example, the details for a product) then SCL may be a good option for you. This doesn’t work in every circumstance and it also causes a number of possible issues with URLs, browser history and what content gets spidered on a “page” by search engines (if this important to you).</p><p>Recapping our approach from Jump Start RWD, this is what we’re going to do conceptually:</p><ul><li> On the first page request we’ll load up all of the page content including the site navigation, content layout, CSS and JS files as normal.</li><li> After the page has loaded we’ll override all of the links in our page to make them XHRs rather than a standard request for a document.</li><li> We’ll then process the response (the XHR response will only be the internal page content in JSON rather than the entire page) and overwrite the content that was in the page.</li><li> We can then use <code>pushState()</code> to modify our browser history (so the URL updates to something shareable and we can go backwards if needs be).</li></ul><p>Here’s an example that should illustrate the point simply. The content has been truncated purposefully in order to keep this concise.</p><p>We’re going to set up a page that can load content about books without having to reload the entire page, just the pertinent content. We’ll also use <code>pushState()</code> from the History API to ensure that if the user wants to share or come back to the URL they&#8217;ll be able to do so.</p><p>To make things simple to express, we’re going to use jQuery for the DOM manipulation and a JavaScript templating library called <a
href="http://handlebarsjs.com/">Handlebars.js</a>. If you haven’t checked out JavaScript templating options and what they can do, Handlebars is an excellent choice to get your feet wet.</p><p>The core of our solution relies on the fact that URLs can respond differently depending on whether they are an XHR or a normal HTTP request. If the server gets a normal request then the view will deliver the full HTTP response (containing all the document and then the JS, CSS etc). If the server gets an XHR, it will respond with JSON which only contains data about the book requested.</p><p>So, as an example, the standard HTTP response for the “Frankenstein” page looks like this:</p><pre>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;script type="text/javascript" src="<a href="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js</a>"&gt;&lt;/script&gt;
&nbsp;
var original = null;
var backtostart = true;
&nbsp;
  &lt;script type="text/javascript"&gt;
      ($(document).ready(function() {
          var source = $("#story-template").html();
          var template = Handlebars.compile(source);
&nbsp;
          var story_link_handler = (function(evt) {
              evt.preventDefault();
              $.get(this.href, function(data) {
                  $("#contentarea").html("");
                  $("#contentarea").html(template(data));
                  history.pushState({url:data.location}, data.title, data.location);
              }, "json");
          });
&nbsp;
          $("ul#storylist li a").bind("click", story_link_handler);
&nbsp;
          $(window).bind("popstate", function(evt) {
              if (event.state) {
                  url = event.state.url;
                  $.get(url, function(data) {
                      $("#contentarea").html("");
                      $("#contentarea").html(template(data));
                  }, "json");
               backtostart = false;
              } else {
               if (! backtostart) {
                  backtostart = true;
                      $("#contentarea").html("");
                      $("#contentarea").html(original);
               } else {
                 original = $("#contentarea").html();
                    backtostart = false;
               }
            }
          });
&nbsp;
      }));
  &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;ul id="storylist"&gt;
      &lt;li&gt;&lt;a href="mobydick"&gt;Moby Dick&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="gulliverstravels"&gt;Gulliver's Travels&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="frankenstein"&gt;Frankenstein&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;div id="contentarea"&gt;
      &lt;article id="story"&gt;
          &lt;h1&gt;Frankenstein&lt;/h1&gt;
              &lt;h2&gt;Mary Shelley&lt;/h2&gt;
              &lt;p&gt;Doctor creates artificial life&lt;/p&gt;
          &lt;/article&gt;
      &lt;/div&gt;
&lt;script type="text/javascript" src="handlebars.js"&gt;&lt;/script&gt;
      &lt;script id="story-template" type="text/x-handlebars-template"&gt;
      &lt;article&gt;
          &lt;h1&gt;{{title}}&lt;/h1&gt;
          &lt;h2&gt;{{author}}&lt;/h2&gt;
          &lt;p&gt;{{synopsis}}&lt;/p&gt;
      &lt;/article&gt;
      &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre><p><em>NB you can download code used in this article in a zip file linked at the end of this article</em></p><p>However, the equivalent JSON response for an XHR will look like this instead:</p><pre>{
  "location": "/frankenstein",
  "title": "Frankenstein",
  "author": "Mary Shelley",
  "synopsis": "Mad doctor creates artificial life"
}</pre><p>All the code required to make the selective loading work is requested and loaded in the first request. After that, we only get the data and then load it into the template. Let’s take a look at how the code works.</p><pre>  &lt;script id="story-template" type="text/x-handlebars-template"&gt;
      &lt;article&gt;
          &lt;h1&gt;{{title}}&lt;/h1&gt;
          &lt;h2&gt;{{author}}&lt;/h2&gt;
          &lt;p&gt;{{synopsis}}&lt;/p&gt;
      &lt;/article&gt;
  &lt;/script&gt;</pre><p><em>NB you can download code used in this article in a zip file linked at the end of this article</em></p><p>Handlebars uses a script element to create a template for what an article looks like (this content won’t be rendered by the browser as it won’t take an action on its type). Variable locations are defined using <code>{{variable}}</code> syntax. You can do a lot more with Handlebars (conditionals, loops, block execution etc) that we aren’t using in this instance though. Note the ID for the script, we need this so we can pass it into the Handlebars template compiler.</p><p>In our document ready function, we grab the HTML from the template script tag we defined above and then we compile it into a template object we can use with new data later.</p><pre>  var source = $("#story-template").html();
  var template = Handlebars.compile(source);</pre><p>Next, we define a function we can use for our link <code>onclick</code> event handler. Here we’re simply stopping the actual request to the file by preventing its default behaviour. From there we make a jQuery XHR that returns JSON to the URL that was defined in the link’s <code>HREF</code> attribute.</p><pre>  var story_link_handler = (function(evt) {
      evt.preventDefault();
      $.get(this.href, function(data) {
          $("#contentarea").html("");
          $("#contentarea").html(template(data));
          history.pushState({url:data.location}, data.title, data.location);
      }, "json");
  });</pre><p>When the response comes back, we simply overwrite the <code>div</code> content area that holds all our book data.</p><pre>$("#contentarea").html(template(data));</pre><p>We also use <code>pushState()</code> to push the URL we just requested onto the browser history so we can go backwards using the back button.</p><pre>history.pushState({url:data.location}, data.title, data.location);</pre><p>That’s not quite the whole picture with <code>pushState()</code>, though, in order for it to “just work” for the user. We next create a <code>popstate</code> event handler on the window so that when the user hits the back button we can update the content with the appropriate data for the book. In this case we’re going and getting the data again using an XHR. With pushstate, it’s possible to store data in a <code>state</code> object. In our case the amount of data is small and it’s bad practice to load up the user’s browser with additional data (especially on mobile) so only do it if you can guarantee it’s a tiny amount.</p><pre>  $(window).bind("popstate", function(evt) {
      if (event.state) {
          url = event.state.url;
          $.get(url, function(data) {
              $("#contentarea").html("");
              $("#contentarea").html(template(data));
          }, "json");
      }
  });</pre><p>One of the things we need to consider with this technique is what happens when the browser gets back to the start of the list. That is, you’ve popped all of your XHRs off the stack and you’re back to where you started.</p><p>To remedy this, we use a flag to determine if we’re back to the start or not and we save the content that was in <code>#contentarea</code> so we can replace it. You can use other techniques such as simply hiding the original content area or storing the original document’s JSON.</p><p>We then update the <code>popstate</code> event to check if there’s no <code>event.state</code>. If so, we revert to our original form.</p><pre>$(window).bind("popstate", function(evt) {
              if (event.state) {
                  url = event.state.url;
                  $.get(url, function(data) {
                      $("#contentarea").html("");
                      $("#contentarea").html(template(data));
                  }, "json");
               backtostart = false;
              } else {
               if (! backtostart) {
                  // revert the content to the original
                  backtostart = true;
                      $("#contentarea").html("");
                      $("#contentarea").html(original);
               } else {
                 // store original content to retrieve later
                 original = $("#contentarea").html();
                    backtostart = false;
               }
            }
          });</pre><p>Finally, we add our <code>click</code> event handler to all the relevant links. In our instance, we’re just using the links in the list, but in practice you could do this to a whole range of links based on <code>class</code> or <code>HREF</code> attributes.</p><pre>$("ul#storylist li a").bind("click", story_link_handler);</pre><p>The rest of the page is the page structure and the actual content that was requested &#8211; in this case the <code>/frankenstein</code> URL.</p><p>As can be seen, this approach gives us a nice, responsive setup. The initial page request is a little heavier (in this case about 1Kb) but provides all of the scaffolding needed to layout the page and provide the interactions. Subsequent requests get the benefit of only having to return very small snippets of data, which are then loaded into the template.</p><p>The URL is updated using <code>pushState()</code> which means the user can still share the URL using intents or copy and paste and that URL will work properly for whomever it is shared with. You also get the benefit that each document still exists properly &#8211; this means search engines can still correctly index your site, if that’s needed.</p><p>One of the things we need to be careful of with this technique is that if we have content that exists in many different templates, the benefits from only loading the snippets of data via XHR will be destroyed by having to load all of the different content templates into the first page request and masking it from the user until it&#8217;s used. Don’t forget, all of the HTML still has to be loaded, regardless of whether it’s used or not.</p><p>Where this technique works particularly well is in an “infinite scroll” scenario such as a stream of content or very long article. The content type doesn’t change almost at all (or only within a very defined way)—this technique does for “page content” as a whole what the lazy loading technique does for images within a page. If you’ve taken the time to chunk your content, this can be especially effective as it means you can avoid the user hitting “goto page 2” even though search engines will follow happily.</p><p><a
href="http://blogs.sitepointstatic.com/examples/selective-content-loading/scl_files.zip">Download code files used in this article</a></p><p><em>Delve further into the world of responsive web design in Andrew&#8217;s new book with Craig Sharkie: <a
href="http://www.sitepoint.com/books/responsive1/">Jump Start Responsive Web Design</a>.</em></p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/selective-content-loading/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>What&#8217;s New in NetBeans 7.3: HTML5!</title><link>http://www.sitepoint.com/netbeans-73-html5-support/</link> <comments>http://www.sitepoint.com/netbeans-73-html5-support/#comments</comments> <pubDate>Mon, 11 Mar 2013 18:58:35 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[Browsers]]></category> <category><![CDATA[CSS3]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[News]]></category> <category><![CDATA[Open source]]></category> <category><![CDATA[Software]]></category> <category><![CDATA[editor]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <category><![CDATA[HTML5 Tutorials & Articles]]></category> <category><![CDATA[IDE]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[software]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=63562</guid> <description><![CDATA[Craig looks at the new HTML5, CSS3 and JavaScript editing features in the latest edition of the ever-popular NetBeans IDE.]]></description> <content:encoded><![CDATA[<p></p><p>Owing to my rapidly increasing age I&#8217;ve used many, many IDEs and text editors over the years. Visual Studio, Aptana, Eclipse, HomeSite, CoffeeCup, Bluefish, Komodo, Vim, Crimson, jEdit, TextPad, PSPad, ConTEXT, PHPEdit, ScITE &#8212; I&#8217;ve probably forgotten more than I remember. Most annoy me. They often miss features I want or add bloat I don&#8217;t need. My current editor of choice is <a
href="http://www.notepad-plus-plus.org/">Notepad++</a>: it&#8217;s simple, lightweight and very configurable.</p><p>Historically, HTML editors have been fairly awful. Many IDEs forced you to create dumb projects, insisted on particular doctypes, or favored deprecated tags. JavaScript editing could be worse: the editor programmers didn&#8217;t understand the language so even basic features such as function lists could fail.</p><p>Fortunately, the situation has improved and <a
href="http://netbeans.org/">NetBeans 7.3 has been released</a> with full support for HTML5, CSS and JavaScript. The cross-platform IDE now includes an HTML project wizard which allows you to select popular boilerplate templates and JavaScript frameworks:</p><p><a
href="http://wiki.netbeans.org/wiki/images/9/9b/Html5project-a2.png"><img
src="http://wiki.netbeans.org/wiki/images/9/9b/Html5project-a2.png" alt="NetBeans HTML5 project" width="600" class="center" /></a><div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>There&#8217;s a lightweight internal server, embedded WebKit browser, Chrome integration and responsive web design facilities:</p><p><a
href="http://wiki.netbeans.org/wiki/images/6/6d/Chrome-ext-resize-01.png"><img
src="http://wiki.netbeans.org/wiki/images/6/6d/Chrome-ext-resize-01.png" alt="NetBeans Chrome integration" width="390" class="center" /></a></p><p>CSS styles can be edited directly or changed within the Inspector-like rule editor:</p><p><a
href="http://wiki.netbeans.org/wiki/images/f/f6/RuleEditor.png"><img
src="http://wiki.netbeans.org/wiki/images/f/f6/RuleEditor.png" alt="NetBeans CSS editing" width="287" class="center" /></a></p><p>The JavaScript editor has been rewritten to include better code completion, jQuery support and pattern recognition:</p><p><a
href="http://wiki.netbeans.org/wiki/images/2/2e/Nb72_JS_comment_generation_after.png"><img
src="http://wiki.netbeans.org/wiki/images/2/2e/Nb72_JS_comment_generation_after.png" alt="NetBeans JavaScript editing" width="434" class="center" /></a></p><p>There&#8217;s also a new debugger which can analyze code running in the internal browser or Chrome. You can apply breakpoints on lines, when a DOM element changes, when events are raised and when Ajax requests are called. Very useful:</p><p><a
href="http://wiki.netbeans.org/wiki/images/a/a0/LineBreakpoints.png"><img
src="http://wiki.netbeans.org/wiki/images/a/a0/LineBreakpoints.png" alt="NetBeans JavaScript debugger" width="600" class="center" /></a></p><p>Finally, there&#8217;s a great browser log which displays exceptions, errors and warnings as they occur:</p><p><a
href="http://wiki.netbeans.org/wiki/images/2/2e/Browserlog.png"><img
src="http://wiki.netbeans.org/wiki/images/2/2e/Browserlog.png" alt="NetBeans JavaScript log" width="600" class="center" /></a></p><p>Don&#8217;t forget that NetBeans also provides first-class development facilities for PHP, Java and C/C++. If you&#8217;re into that sort of thing.</p><p>It&#8217;s great to see client side browser technologies finally receiving the tools they deserve. I&#8217;m going to give NetBeans another look &hellip; <em>will you?</em></p><p>NetBeans is available for free from <a
href="http://netbeans.org/"><strong>netbeans.org</strong></a>.</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/netbeans-73-html5-support/feed/</wfw:commentRss> <slash:comments>11</slash:comments> </item> <item><title>A jQuery Plugin for Touch Swiping &#8211; Part 2 of 2</title><link>http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-2-of-2/</link> <comments>http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-2-of-2/#comments</comments> <pubDate>Thu, 07 Mar 2013 05:14:22 +0000</pubDate> <dc:creator>Chee How Chua</dc:creator> <category><![CDATA[Intermediate]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[plugins]]></category> <guid
isPermaLink="false">http://jspro.com/?p=2198</guid> <description><![CDATA[The second part of Chee How Chua's walkthrough of the steps to create a jQuery plugin that detects the horizontal swiping motion on touch devices such as the iPhone and Android-based devices.
]]></description> <content:encoded><![CDATA[<p></p><p>This is part two of two in the series describing how to create a jQuery plugin to detect and respond to swipe gestures.</p><p>In <a
href="http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-1-of-2/">the first part</a>, we saw how to create a plugin that changes a carousel&#8217;s pictures to correspond to the position of the finger on screen. In this part, we will extend that to detect a swipe gesture. This improves the carousel by creating fixed intervals so that a swipe changes the carousel to show the next/previous picture in its entirety.</p><pre class="brush: jscript; title: ; notranslate">var Swiper = function (el, callbacks, options) {
  ...
  this.opts = options;
  this.swipeDone = false;
  //perform binding
  this.el.addEventListener('touchend', function (evt) {
    tis.stop(evt);
  });
  ....
};
Swiper.LEFT = - 1;
Swiper.RIGHT = 1;
...
$.fn.swiper = function (callbacks, options) {
  var opts = $.extend({}, $.fn.swiper.defaults, options);
  if (typeof callbacks.swiping !== 'function') {
    throw '&amp;amp;amp;amp;quot;swiping&amp;amp;amp;amp;quot; callback must be defined.';
  }
  if (typeof callbacks.swiped !== 'function') {
    throw '&amp;amp;amp;amp;quot;swiped&amp;amp;amp;amp;quot; callback must be defined.';
  }
  if (typeof callbacks.swipeCancel !== 'function') {
    throw '&amp;amp;amp;amp;quot;swipeCancel&amp;amp;amp;amp;quot; callback must be defined.';
  }
  this.each(function () {
    ...
    if (!swiper) {
      tis.data('swiper', (swiper = new Swiper(this, callbacks, opts)));
    }
  });
};
$.fn.swiper.defaults = {
    tolerance: 100
};</pre><p>In the above listing, we see that the class constructor for <code>Swiper</code> is modified to accept a third parameter <code>options</code> that holds a single property <code>tolerance</code>. The parameter is assigned to an internal property <code>opts</code>. The <code>touchend</code> event is proxied to the <code>stop()</code> instance method of the <code>Swiper</code> class.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>Additionally, two callback functions have been added (<code>swiped</code> and <code>swipeCancel</code>) to handle the swiping. The default value for <code>tolerance</code> is set as 100 (pixels). Notice there are also two class properties <code>Swiper.LEFT </code> and <code>Swiper.RIGHT</code>. They represent a left swipe and a right swipe respectively and will be used in subsequent listings.</p><p>The plugin definition is also modified to accept a second, optional, parameter that provides the choice to override the default threshold of 100 pixels.</p><p>We need to extend the plugin to recognise when a swipe has occurred and modify the carousel correspondingly. There are several scenarios we need to consider. The first, and most straightforward, is when the user drags a finger across the screen and releases it. If the finger covers a distance that is more than or equal to the <code>tolerance</code> value, we consider that a swipe, and the carousel should advance to the next image when the finger is lifted off the screen. The figure below illustrates this scenario.</p><p><img
src="http://jspro.com/files/2013/02/swipe1.png" caption="Beyond threshold - swipe detected." /></p><p>On the other hand, if the finger covers a distance that is less than the <code>tolerance</code> value, the movement is <em>not</em> considered a swipe and the carousel should revert to its original position.</p><p><img
src="http://jspro.com/files/2013/02/swipe2.png" caption="Within threshold - No swipe detected." /></p><p>Remember that the plugin moves the carousel to mirror the movement of the finger for the duration of contact with the screen. The decision as to whether to advance or revert the carousel position is taken when the finger is lifted off the screen (binding for the <code>touchend</code> event).</p><pre class="brush: jscript; title: ; notranslate">Swiper.prototype.stop = function (evt) {
  if (!this.swipeDone) {
    this.cbs.swipeCancel();
  } else {
    this.cbs.swiped(this.getDirection());
  }
};</pre><p>If a swipe is detected, invoke the callback for advancing the carousel (<code>swiped()</code>), otherwise revert the carousel (<code>swipeCancel()</code>).</p><p>One thing to note is that we are returning the direction of the movement to the &#8220;advancing&#8221; callback as determined by the <code>getDirection</code> method. This is required as the callback needs to know which direction to advance the carousel to.</p><pre class="brush: jscript; title: ; notranslate">Swiper.prototype.getDirection = function () {
  var direction = this.diff();
  if (direction &amp;amp;amp;amp;lt; 0) {
    return Swiper.LEFT;
  }
  if (direction &amp;amp;amp;amp;gt; 0) {
    return Swiper.RIGHT;
  }
};</pre><p>This method uses the <code>diff()</code> method defined in Part 1 of this series to get the displacement of the finger. If the difference is negative, it is a left swipe, otherwise it is a right swipe.</p><p>We now need to know how to determine whether a swipe is generated i.e. setting of the <code>swipeDone</code> flag. Before we delve into that though, let&#8217;s consider the next scenario.</p><p>If the user brings a finger to the screen, drags it beyond the threshold value, and then brings it back to within the threshold value before removing the finger, we don&#8217;t want to advance the carousel as the user&#8217;s intention, by bringing the finger back, is that he/she does not want to advance the carousel.</p><p><img
src="http://jspro.com/files/2013/02/swipe3.png" caption="Pulls back to within tolerance - No swipe"/></p><p>Similarly if the user brings the finger back beyond the tolerance value before removing the finger, his/her intention is to advance the carousel.</p><p><img
src="http://jspro.com/files/2013/02/swipe4.png" caption="Pulls back to beyond tolerance - Swipe detected" /></p><p>As you can imagine, the determination of when the gesture is detected is done while the finger is dragging on the screen, and not when the finger is lifted. We therefore have to make some changes to the <code>move()</code> instance method of the <code>Swiper</code> class.</p><pre class="brush: jscript; title: ; notranslate">Swiper.prototype.move = function (evt) {
  if (Math.abs(this.diff()) &amp;amp;amp;amp;gt;= this.opts.tolerance) {
    this.swipeDone = true;
  } else {
    this.swipeDone = false;
  }
  if (evt.targetTouches &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; evt.targetTouches.length === 1) {
    if (evt.targetTouches[0].offsetX) {
      this.points[1] = evt.targetTouches[0].offsetX;
    } else if (evt.targetTouches[0].layerX) {
      this.points[1] = evt.targetTouches[0].layerX;
    } else {
      this.points[1] = evt.targetTouches[0].pageX;
    }
    this.cbs.swiping(this.diff());
  }
};</pre><p>At the beginning of the <code>move()</code> method, we check if the distance moved by the finger has exceeded the tolerance value. The difference is encompassed in a <code>Math.abs()</code> function because a left movement will always generate a negative value which is less than any positive value. By taking its absolute value, we can check the distance for both left and right movements. If it is determined that the distance is larger than or equals to the tolerance value, we consider it a swipe.</p><p>A key point about making this work is the removal of the line <code>this.points[0] = this.points[1];</code> from the <code>move()</code> method. This is absolutely critical because we want to take reference from the point where the finger came into contact with the screen (<code>touchstart</code>). If we retain this line of code, the reference point will keep changing with each movement of the finger and we will not be able to perform the calculation that we want. With the removal of this line of code though, the value that <code>diff()</code> returns will also be different from before. We then have to change the definition of the <code>swiping()</code> callback function.</p><p>One last change to make to the <code>Swiper</code> class is to its <code>start()</code> instance method. This change basically says that every time a finger is first placed on screen, the <code>swipeDone</code> flag to false, which is natural since a swipe cannot have been generated when the finger first touches the screen.</p><pre class="brush: jscript; title: ; notranslate">Swiper.prototype.start = function (evt) {
  if (evt.targetTouches &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; evt.targetTouches.length === 1) {
    this.swipeDone = false;
    ...
  }
};</pre><p>We are pretty much done with the plugin itself. Changing the application code to utilise the plugin requires a paradigm shift in how we manipulate the carousel&#8217;s position while the finger is still dragging on screen. Remember that the carousel is supposed to &#8220;snap&#8221; to positions that show any of the images in its entirety. As a result, the value of the position is always a multiple of the width of each image. Thus it is easiest to represent the position as a percentage. Note that since we are treating the <code>currPos</code> value as a percentage, the values of <code>MAX_LEFT</code> and <code>MAX_RIGHT</code> need to be converted into percentages too.</p><p>We still want to retain the mirroring effect of the carousel on the finger. To do that, a new variable <code>adhocPos</code> is introduced in the <code>swiping()</code> callback. This value holds the position of the carousel as the finger drags on the screen. It uses the <code>baseWidth</code> variable which is set to 330 pixels (the width of each image in the carousel). This value <strong>must</strong> be changed if the width of an image in the carousel changes.</p><pre class="brush: jscript; title: ; notranslate">...
MAX_LEFT = -300,
MAX_RIGHT = 0,
baseWidth = 330;
cb = {
  swiping: function (displacement) {
    var adhocPos = currPos / 100 * baseWidth;
    adhocPos += displacement;
    pictures.css('left', adhocPos + 'px');
  },
  ...
}</pre><p>The <code>currPos</code> value is treated as a percentage which is set in the <code>swiped</code> callback below:</p><pre class="brush: jscript; title: ; notranslate">swiped: function (direction) {
  currPos += (direction * 100);
  if (currPos &amp;amp;amp;amp;lt; MAX_LEFT || currPos &amp;amp;amp;amp;gt; MAX_RIGHT) {
    //i.e. exceeded limit
    currPos -= (direction * 100);
  }
  pictures.css('left', currPos + '%');
}</pre><p>The callback is passed a <code>direction</code> parameter which, as we saw earlier, is either <code>1</code> or <code>-1</code>. This is then multiplied with 100 to convert into a percentage value before summing up with <code>currPos</code>. The <code>if</code> statement checks to make sure that the value remains within the boundaries so that the carousel does not scroll into empty space. This was previously done in the <code>swiping()</code> callback. By placing this check in the <code>swiped()</code> callback, we get the effect that when the user drags the carousel beyond the last image, we see white space but as soon as the finger is lifted, the carousel jumps back, thereby creating a sort of &#8220;bouncing&#8221; effect.</p><p>Lastly, there is the <code>swipeCancel()</code> callback which sets the carousel back to its original position before the dragging started.</p><pre class="brush: jscript; title: ; notranslate">swipeCancel: function () {
  pictures.css('left', currPos + '%');
}</pre><p>With the modifications we made to the plugin in this article we have a decent swiping carousel that works almost like a native app in your browser. Similarly, the plugin has been tested in the same browsers as stated in the first article. You can see the <a
title="See working demo" href="http://jspro.rojakcoder.com/touchswipe2">demo</a> or download the <a
title="Download ZIP file" href="http://jspro.rojakcoder.com/touchswipe2/touchswipe2.zip">source code</a> and have fun with them!</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-2-of-2/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>A jQuery Plugin for Touch Swiping &#8211; Part 1 of 2</title><link>http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-1-of-2/</link> <comments>http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-1-of-2/#comments</comments> <pubDate>Fri, 01 Mar 2013 09:00:06 +0000</pubDate> <dc:creator>Chee How Chua</dc:creator> <category><![CDATA[Intermediate]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[plugins]]></category> <guid
isPermaLink="false">http://jspro.com/?p=2084</guid> <description><![CDATA[This article will explain the steps to create a jQuery plugin that detects the horizontal swiping motion on touch devices such as the iPhone and Android-based devices.]]></description> <content:encoded><![CDATA[<p></p><p>This article will explain the steps to create a jQuery plugin that detects the horizontal swiping motion on touch devices such as the iPhone and Android-based devices. This article is the first in a two-part series. In this article, we will be creating an image carousel that can respond to the user&#8217;s input and change the position of the carousel accordingly. <a
href="http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-2-of-2/">The second article</a> will extend the plugin by adding swipe detection.<br
/> <span
id="more-2084"></span></p><h3>HTML &amp; CSS</h3><p>Before we go on to the JavaScript, let&#8217;s take a look at the HTML and CSS for the image carousel which will be used to demonstrate the Swiper plugin. The HTML is shown below.</p><pre class="brush: xml; title: ; notranslate">
&lt;div style=&quot;width: 330px; height: 200px;&quot;&gt;
  &lt;div id=&quot;target&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;&lt;img alt=&quot;&quot; src=&quot;rexy.jpg&quot; /&gt;&lt;/div&gt;
      &lt;div&gt;&lt;img alt=&quot;&quot; src=&quot;xena.jpg&quot; /&gt;&lt;/div&gt;
      &lt;div&gt;&lt;img alt=&quot;&quot; src=&quot;xenaagain.jpg&quot; /&gt;&lt;/div&gt;
      &lt;div&gt;&lt;img alt=&quot;&quot; src=&quot;rexyagain.jpg&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</pre><p>Similarly, the carousel&#8217;s CSS is shown below.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><pre class="brush: css; title: ; notranslate">
img { /*100% width to scale the height proportionately*/
  width: 100%;
  margin: 0;
}
.frame {
  width: 100%;
  height: 100%;
  border: 1px solid #ccc;
  overflow: hidden;
  position: relative;
}
.pictures {
  position: absolute;
  width: 400%; /*change accordingly*/
  left: 0%;
}
.pictures:after {
  content: &quot;&#92;&#48;020&quot;;
  display: none;
  height: 0;
}
.pictures .pic {
  width: 25%; /*change with respect to .pictures*/
  float: left;
}
</pre><p>The inner container (<code>.pictures</code>) is set to 400% to contain four images. Each image&#8217;s container (<code>.pic</code>) is set to 25% so that the images end up at a width of 330 pixels. If you change the number of images or use absolute values instead of percentages, you&#8217;d want to change the width value of the <code>.pictures</code> and <code>.pic</code> elements accordingly.</p><p>The images are made to line up horizontally by floating to the left. The frame (<code>.frame</code>) is made to show only one image at a time. With this setup, we can then &#8220;slide&#8221; the carousel by changing the <code>left</code> property of the <code>.pictures</code> <code>&lt;div&gt;</code> element.</p><h3>JavaScript</h3><p>Here is the skeleton of the plugin:</p><pre class="brush: jscript; title: ; notranslate">
(function ($) {
  'use strict';
  var Swiper = function (el, callbacks) {
  }
  $.fn.swiper = function (callbacks) {
    if (typeof callbacks.swiping !== 'function') {
      throw '&quot;swiping&quot; callback must be defined.';
    }
    this.each(function () {
      var tis = $(this),
        swiper = tis.data('swiper');
      if (!swiper) { //i.e. plugin not invoked on the element yet
        tis.data('swiper', (swiper = new Swiper(this, callbacks)));
      }
    });
  };
}(jQuery));
</pre><p>This listing is boilerplate code for creating a jQuery plugin. The bulk of the complexity is handled by the internal class <code>Swiper</code>, whose methods are not yet defined. <code>Swiper</code> is responsible for reading the events produced by the browser and invoking the callback. The plugin is defined in a closure so that the <code>Swiper</code> class will not be mistakenly overridden by external code. The plugin is also prevented from binding to an element more than one time by associating the instantiated <code>Swiper</code> class with the <code>swiper</code> data attribute.</p><pre class="brush: jscript; title: ; notranslate">
var Swiper = function (el, callbacks) {
  var tis = this;
  this.el = el;
  this.cbs = callbacks;
  this.points = [0, 0];
  //perform binding
  this.el.addEventListener('touchstart', function (evt) {
    tis.start(evt);
  });
  this.el.addEventListener('touchmove', function (evt) {
    evt.preventDefault();
    tis.move(evt);
  });
};
</pre><p>In the above listing, the <code>Swiper</code> constructor instantiates the object&#8217;s properties and event handlers. The <code>points</code> property is a two-celled array that stores the starting position of the finger in the first cell, and the ending position in the second cell. We will see the usage of this array in subsequent listings. Its values are both initially zero.</p><p>The constructor binds the <code>touchstart</code> and <code>touchmove</code> events, and proxies the events to the corresponding methods in the <code>Swiper</code> class. The <code>touchstart</code> binding initializes the <code>points</code> array with the initial position of the finger. The <code>touchmove</code> binding gives us the movement of the finger, which we will pass to the callback function to offset the carousel accordingly.</p><pre class="brush: jscript; title: ; notranslate">
Swiper.prototype.start = function (evt) {
  if (evt.targetTouches &amp;&amp; evt.targetTouches.length === 1) {
    if (evt.targetTouches[0].offsetX) {
      this.points[0] = evt.targetTouches[0].offsetX;
    } else if (evt.targetTouches[0].layerX) {
      this.points[0] = evt.targetTouches[0].layerX;
    } else {
      this.points[0] = evt.targetTouches[0].pageX;
    }
    //make initial contact with 0 difference
    this.points[1] = this.points[0];
  }
};
</pre><p>The listing above shows the <code>start()</code> method, which takes the event and reads the set of touches generated on screen. In devices with multi-touch capability, which means nearly all modern smartphones and tablets, this property is an array storing the locations of all contact points with the screen. In this implementation, we are keeping track of one contact point as we are tracking a single swipe gesture which is done using one finger.</p><p>We are checking for the different properties of the touch event to accommodate the different implementations of the touch behaviour on different devices. This used to be required to make it <a
href="http://www.nogginbox.co.uk/blog/canvas-and-multi-touch">work for different devices</a>. Today, however, the devices that I have tested all generate the <code>pageX</code> property.</p><p>Since we are checking only for a horizontal swipe gesture, we ignore the <code>pageY</code> property. We also set the cells of the <code>points</code> property to the same value so that the initial difference between the starting and ending points is zero.</p><p>The function binding for the <code>touchmove</code> event and other helper methods are listed below.</p><pre class="brush: jscript; title: ; notranslate">
Swiper.prototype.diff = function () {
  return this.points[1] - this.points[0];
};
Swiper.prototype.move = function (evt) {
  if (evt.targetTouches &amp;&amp; evt.targetTouches.length === 1) {
    if (evt.targetTouches[0].offsetX) {
      this.points[1] = evt.targetTouches[0].offsetX;
    } else if (evt.targetTouches[0].layerX) {
      this.points[1] = evt.targetTouches[0].layerX;
    } else {
      this.points[1] = evt.targetTouches[0].pageX;
    }
    this.cbs.swiping(this.diff());
    this.points[0] = this.points[1];
  }
};
</pre><p>The <code>diff()</code> method simply calculates the difference between the last point (which changes as the user moves the finger) and the previous point. This is illustrated by the following figure.</p> <a
href="http://jspro.com/files/2013/02/image1.png"><img
class="size-full wp-image-2101 " alt="image1" src="http://jspro.com/files/2013/02/image1.png" width="239" height="166" /></a> Illustration of the Distance &#8220;Dragged&#8221; by a Finger.<p>The <code>move()</code> method also checks through the different properties to get the right one for storing into the second cell of the <code>points</code> property. After storing the value, the callback function is invoked with the difference between the previous position and the new position of the finger. The callback function is responsible for changing the position of the carousel. This is explained below.</p><p>After invoking the callback, the previous position&#8217;s value is replaced with the current position&#8217;s value. The next time the callback is invoked, the difference will be the displacement between the current position and the previous position instead of the starting position. This is required if we want the movement of the carousel to mirror that of the finger. Without this line, the carousel&#8217;s movement accumulates the difference and the result is a large displacement of images in response to a small movement of the finger, which is clearly undesirable for a smooth user experience.</p><p>The listing below invokes the plugin.</p><pre class="brush: jscript; title: ; notranslate">
var target = $('#target'),
  pictures = $('.pictures', target),
  MAX_LEFT = -990,
  MAX_RIGHT = 0,
  currPos = 0,
  cb = {
    swiping: function (displacement) {
      currPos += displacement;
      if (currPos &gt; MAX_RIGHT) {
        currPos = MAX_RIGHT;
      } else if (currPos &lt; MAX_LEFT) {
        currPos = MAX_LEFT;
      }
      pictures.css('left', currPos + 'px');
    }
  };
target.swiper(cb);
</pre><p>We get the element using its <code>id</code>. We also need a handle to the <code>.pictures</code> element within the target because the carousel&#8217;s positioning is changed by changing the <code>left</code> CSS property of this element.</p><p>We set the left and right limit of the carousel&#8217;s position with the <code>MAX_LEFT</code> and <code>MAX_RIGHT</code> variables. These values have to change in relation to the carousel&#8217;s size. They are used so that the user does not scroll the carousel to empty spaces. The <code>MAX_RIGHT</code> variable determines how far right the finger can drag the carousel to hit the left-most image. Naturally, this value is <code>0</code>. The <code>MAX_LEFT</code> variable limits how far left the finger can move the carousel. Since there are four images, to display the right-most one, the three images on the left have to be displaced. The values are derived like this:</p><p><code>330 (width of one image) * 3 = 990</code></p><p>We also have a variable, <code>currPos</code>, that stores the current position of the carousel. Alternatively, we can get the position of the carousel like so:</p><pre class="brush: jscript; title: ; notranslate">currPos = parseInt(pictures.css('left'));</pre><p>The preferred approach is to use the variable. The only reason is that of performance &#8211; retrieving the <code>left</code> property of the element and converting it into an integer definitely consumes more processing power than accessing a variable&#8217;s value. This is cognizant of the fact that we are adding behavior on top of a browser&#8217;s interface, so it is important that we keep the plugin lean.</p><p>The callback is specified as a property within a JSON literal. Why not simply pass it as a function? Well, this is to set the stage for part two of this series, where we will explain how to add swipe gesture detection to the plugin.</p><p>A final note: on iOS devices (iPhones and iPads), there is a bouncing effect on the browser window when you scroll the carousel. This is apparent if the carousel is near the bottom or the top (as is the case here) of the page. To prevent that from happening, we call the <code>preventDefault()</code> method on the <code>touchmove</code> event. Incidentally, by calling the <code>preventDefault()</code> method, it prevents the event from bubbling up the <abbr
title="Document Object Model">DOM</abbr> hierarchy, which in turn leads to better performance, especially apparent on slower devices such as the Nexus One. I&#8217;ve tested the plugin on the iPad 2 (iOS 6.0.1), Nexus One (Android 2.3.6), and Galaxy Note II (Android 4.1.2). If you have used any other devices/OS, feel free to let us know in the comments!</p><ul><li><a
href="http://jspro.rojakcoder.com/touchswipe1">Online Demo</a></li><li><a
href="https://github.com/jsprodotcom/source/blob/master/TouchSwipe.zip">Download Source Code</a></li></ul><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/jquery-plugin-for-touch-swiping-part-1-of-2/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>7 of the Best Code Playgrounds</title><link>http://www.sitepoint.com/7-code-playgrounds/</link> <comments>http://www.sitepoint.com/7-code-playgrounds/#comments</comments> <pubDate>Fri, 15 Feb 2013 13:22:40 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[CSS]]></category> <category><![CDATA[CSS3]]></category> <category><![CDATA[HTML]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[Libraries]]></category> <category><![CDATA[Programming]]></category> <category><![CDATA[Software]]></category> <category><![CDATA[Software debugging]]></category> <category><![CDATA[code]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <category><![CDATA[HTML5 Tutorials & Articles]]></category> <category><![CDATA[javascript]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=63469</guid> <description><![CDATA[Messing around with experimental code is easy thanks to several free online development playgrounds. Craig looks at seven of the best...]]></description> <content:encoded><![CDATA[<p></p><p>A variety of code playgrounds have appeared during the past couple of years. The majority offer a quick and dirty way to experiment with client-side code and share with others. Typical features include:</p><ul><li>color-coded HTML, CSS and JavaScript editors</li><li>a preview window &#8212; many update on the fly without a refresh</li><li>HTML pre-processors such as HAML</li><li>LESS, SASS and Stylus CSS pre-processing</li><li>inclusion of popular JavaScript libraries</li><li>developer consoles and code validation tools</li><li>sharing via a short URL</li><li>embedding demonstrations in other pages</li><li>code forking</li><li>zero cost (or payment for premium services only)</li><li>showing off your coding skills to the world!</li></ul><p>The best feature: they allow you to test and keep experimental snippets code without the rigmarole of creating files, firing up your IDE or setting up a local server. Here are seven of the best &hellip;</p><h2 style="clear:both"><a
href="http://jsfiddle.net/">JSFiddle</a></h2><p><a
href="http://jsfiddle.net/"><img
src="http://blogs.sitepointstatic.com/images/tech/789-code-playgrounds-jsfiddle.png" width="360" height="225" alt="JSFiddle" class="right" /></a><a
href="http://jsfiddle.net/">JSFiddle</a> was one of the earliest code playgrounds and a major influence for all which followed. Despite the name, it can be used for any combination of HTML, CSS and JavaScript testing. It&#8217;s looking a little basic today, but still offers advanced functionality such as Ajax simulation.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>&nbsp;<br
/> &nbsp;<br
/> &nbsp;</p><h2 style="clear:both"><a
href="http://codepen.io/">CodePen</a></h2><p><a
href="http://codepen.io/"><img
src="http://blogs.sitepointstatic.com/images/tech/789-code-playgrounds-codepen.png" width="360" height="225" alt="CodePen" class="right" /></a>The prize for the best-looking feature-packed playground goes to <a
href="http://codepen.io/">CodePen</a>. The service highlights popular demonstrations (&#8220;Pens&#8221;) and offers advanced functionality such as sharing and embedding. The PRO service provides cross-browser testing, pair-programming and teaching options for just $9 per month.</p><h2 style="clear:both"><a
href="http://cssdeck.com/">CSS Deck</a></h2><p><a
href="http://cssdeck.com/"><img
src="http://blogs.sitepointstatic.com/images/tech/789-code-playgrounds-cssdeck.png" width="360" height="225" alt="CSS Deck" class="right" /></a>This may be named <a
href="http://cssdeck.com/">CSS Deck</a>, but it&#8217;s a fully-fledged HTML, CSS and JavaScript playground with social and collaboration features. It&#8217;s similar to CodePen (I don&#8217;t know who influenced who!) but you might prefer it.</p><h2 style="clear:both"><a
href="http://jsbin.com/">JS Bin</a></h2><p><a
href="http://jsbin.com/"><img
src="http://blogs.sitepointstatic.com/images/tech/789-code-playgrounds-jsbin.png" width="360" height="225" alt="JS Bin" class="right" /></a><a
href="http://jsbin.com/">JS Bin</a> was started by JS guru <a
href="http://remysharp.com/">Remy Sharp</a>. It concentrates on the basics and handles them exceedingly well. As far as I&#8217;m aware, it&#8217;s also the only option which offers a JavaScript console. Recommended.</p><h2 style="clear:both"><a
href="http://dabblet.com/">Dabblet</a></h2><p><a
href="http://dabblet.com/"><img
src="http://blogs.sitepointstatic.com/images/tech/789-code-playgrounds-dabblet.png" width="360" height="225" alt="Dabblet" class="right" /></a>Another early playground, <a
href="http://dabblet.com/">Dabblet</a> started life as an HTML5/CSS3 demonstration system by <a
href="http://lea.verou.me/">Lea Verou</a> but it&#8217;s recently received JavaScript facilities. It looks gorgeous and has one killer feature &#8212; browser CSS prefixes are added automatically. There&#8217;s no need to enter that -webkit, -moz and -ms nonsense yourself.</p><h2 style="clear:both"><a
href="http://tinkerbin.com/">Tinkerbin</a></h2><p><a
href="http://tinkerbin.com/"><img
src="http://blogs.sitepointstatic.com/images/tech/789-code-playgrounds-tinkerbin.png" width="360" height="225" alt="Tinkerbin" class="right" /></a><a
href="http://tinkerbin.com/">Tinkerbin</a> is an alpha release and one of the simpler options here. It may not offer features above and beyond the alternatives but it&#8217;s attractive and functional.</p><h2 style="clear:both"><a
href="http://liveweave.com/">Liveweave</a></h2><p><a
href="http://liveweave.com/"><img
src="http://blogs.sitepointstatic.com/images/tech/789-code-playgrounds-liveweave.png" width="360" height="225" alt="Liveweave" class="right" /></a><a
href="http://liveweave.com/">Liveweave</a> is slightly unusual in that it places your HTML, CSS and JavaScript into a single file. It&#8217;s not possible to share your creation, but you can download the result and store or open it locally. It&#8217;s ideal for quick and dirty private experimentation.</p><p>I guess I missed your favorite?&hellip;</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/7-code-playgrounds/feed/</wfw:commentRss> <slash:comments>10</slash:comments> </item> <item><title>Web Prototyping for Touch Gestures</title><link>http://www.sitepoint.com/web-prototyping-for-touch-gestures/</link> <comments>http://www.sitepoint.com/web-prototyping-for-touch-gestures/#comments</comments> <pubDate>Thu, 14 Feb 2013 00:06:45 +0000</pubDate> <dc:creator>Sanjay Raval</dc:creator> <category><![CDATA[CSS]]></category> <category><![CDATA[HTML]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[Programming]]></category> <category><![CDATA[touch gestures]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=63425</guid> <description><![CDATA[Sanjay Raval explains how to construct a web prototype that will respond to touch gestures, using HTML, CSS and jQuery.]]></description> <content:encoded><![CDATA[<p></p><p>The working process of many web designers involves using a wireframe, a static outline of page layout that can be filled with design elements, perhaps drawn from a Photshop comp.</p><p>Developers, however, need to build functionality not available in a static wireframe. A web prototype is more like a working model that allows a developer to experiment with how things work on a web page.</p><p>In this article, you’ll learn how to create a web prototype with touch gestures using simple and easy HTML, CSS and jQuery.</p><h2>Prototyping for Touch</h2><p>For a recent project, I wanted to incorporate a facility to allow appropriate screens to respond to touch gestures.  I designed a static wireframe and then thought to build a rich web prototype to run on tablet devices to demo to the stakeholders.</p><p>Considering it was a just a prototype and wasn&#8217;t going to be used for actual development, and given that I have a limited knowledge of programming (a common problem for designers), I was looking for an easy JavaScript framework for allowing swipe gestures to work on mobile browsers, specifically tablets and iPads.</p><p>The main requirement would be to show the primary navigation bar with sliding animation when the user swipes their finger from left to right.  I started Googling, and tried various frameworks from jQuery mobile to hammer.js. All the frameworks I tried were either too complex to use or not very responsive on mobile browsers.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>Finally, I tried another framework called wipetouch.js, and it worked the way I wanted. It is very simple and easy to use and the swipe gesture is very responsive in platforms like iOS and Android.</p><p><b>Note:</b> the demo is primarily made for iPad and tablets but it runs well on desktop browsers, too. For desktop, in place of swipe, the user can slide the mouse pointer. To see the result, open the link on your iPad or Android tablet, then swipe the finger from left to right, right to left and top to bottom.</p><p><a
href="http://blogs.sitepointstatic.com/examples/web-prototyping-for-touch-gestures/index.html">View Demo</a></p><p><img
class="alignnone size-full wp-image-63427" alt="demo page screenshot" src="http://www.sitepoint.com/wp-content/uploads/1/files/2013/02/figure13.png" width="602" height="353" /></p><h3>Files used for this exercise</h3><ul><li>index.html for html</li><li>style.css for styling</li><li>common.js for JavaScript</li><li>jquery.wipetouch.js – a framework used for swipe gesture</li><li>and link to jQuery files</li></ul><h3>Images used in this exercise</h3><p><strong>Swipe from Left to right:</strong><br
/> Showing the left menu bar with sliding animation</p><p><img
class="alignnone size-full wp-image-63428" alt="left menu" src="http://www.sitepoint.com/wp-content/uploads/1/files/2013/02/figure23.png" width="131" height="300" /></p><p><strong>Swipe from right to left:</strong><br
/> Showing the right bar with sliding animation</p><p><img
class="alignnone size-full wp-image-63429" alt="right menu" src="http://www.sitepoint.com/wp-content/uploads/1/files/2013/02/figure34.png" width="131" height="300" /></p><p><strong>Swipe from top to bottom:</strong><br
/> In this example, I wanted to use a swipe down gesture to add the product without tapping on the + icon, because swiping is easier and quicker than tapping on a small icon.</p><p>But, as this touch gesture has a problem of discoverability, the icon to add the product is there in case the user is not aware of this gesture.</p><p><img
class="alignnone size-full wp-image-63430" alt="top menu" src="http://www.sitepoint.com/wp-content/uploads/1/files/2013/02/figure43.png" width="594" height="108" /></p><h2>Getting Started</h2><p><b>Note:</b> To make the article easy and clean, I will only explain the code used to slide the left menu on swipe from left to right. For right and top menu, the code is pretty much same (and is provided in the actual demo source files).</p><h3>Step 1 – Link JavaScript and jQuery files</h3><p>First we&#8217;ll link the required jQuery files and wipetouch.js framework for this prototype in the HTML page. We&#8217;ll use jQuery for showing the sliding animation and wipetouch.js for the swipe gestures. Common.js is the JavaScript file used for this assignment.</p><pre>&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"&gt;&lt;/script&gt;
&lt;script src="jquery.wipetouch.js"&gt;&lt;/script&gt;
&lt;script src="common.js"&gt;&lt;/script&gt;</pre><p>Filename – index.html</p><p>Download <a
href="http://wipetouch.codeplex.com/" target="_blank">wipetouch.js</a></p><h3>Step 2 – Add Images</h3><p>In HTML, we will add the <code>left_menu.png</code> image and give it an ID. We will use this ID in the CSS and JS files.</p><pre>&lt;img src="images/left_menu.png" width="262" height="600" id="menuLeft"&gt;</pre><p>Filename – index.html</p><h3>Step 3 – CSS Code</h3><p>In CSS, we will position the image on the page from where we want the sliding animation to start.</p><pre>/* Set Position of Left bar */
#menuLeft {
    position:absolute;
    left:0;
    top:0px;
    z-index:99;
}</pre><p>Filename – style.css</p><h3>Step 4 – Hide the #menuLeft when page loads</h3><pre>$("#menuLeft").hide();</pre><p>Filename – common.js</p><p>Here <code>menuLeft</code> is the ID applied to <code>left_menu.png</code>.</p><h3>Step 5 - Show the navigation bar with sliding animation when user swipes from left to right</h3><pre>wipeRight: function(result) {
    $("#menuLeft").show("slide", { direction: "left" }, 1000);
}</pre><p>Filename – common.js</p><p>Here <code>wipeRight</code> is the function from wipetouch.js that is triggered when the user swipes the finger from left to right.</p><p>On this swipe action, we show the menuLeft image with sliding animation from the left direction.</p><h3>Step 6 – Slide back the image on tap</h3><p>Now we need to slide same image back the when user taps on the image.</p><pre>$("#menuLeft").click(function () {
    $("#menuLeft").hide("slide", { direction: "left" }, 1000);
});</pre><p>On tapping on the image, it slides back to be hidden.</p><p><b>Note:</b> To make the article easy and clean, I have only explained the code used to slide the left menu on swipe from left to right. For swiping from right to left and swiping from top to bottom, the code is pretty much same and given in actual demo source files.</p><p><a
href="http://blogs.sitepointstatic.com/examples/web-prototyping-for-touch-gestures/WebPrototype_Using_TouchGestures.zip">Download Demo Source Files</a></p><h2>In Conclusion</h2><p>No doubt the available prototyping tools will soon cover touch gestures, but right now this solution does the trick. I hope this demo provides a good base for you to build a prototype to show touch gestures and basic animation on touch devices using easy simple code.</p><p>Please let me know if you have any suggestions for improvements. Please share your thoughts, opinions and ideas in the comments section below.</p><h2>Further Reading</h2><p><a
href="http://www.netcu.de/jquery-touchwipe-iphone-ipad-library">http://www.netcu.de/jquery-touchwipe-iphone-ipad-library</a><br
/> Another nice demo created using touchwipe.js to slide show on swipe</p><p><a
href="http://eightmedia.github.com/hammer.js/">http://eightmedia.github.com/hammer.js/</a><br
/> Another very popular JS framework for mobile devices</p><p><a
href="http://www.appliness.com/multitouch-with-hammer-js/">http://www.appliness.com/multitouch-with-hammer-js/</a><br
/> A nice demo created using hammer.js to show drag and drop</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/web-prototyping-for-touch-gestures/feed/</wfw:commentRss> <slash:comments>13</slash:comments> </item> <item><title>Event Delegation with jQuery</title><link>http://www.sitepoint.com/event-delegation-with-jquery/</link> <comments>http://www.sitepoint.com/event-delegation-with-jquery/#comments</comments> <pubDate>Fri, 08 Feb 2013 09:00:50 +0000</pubDate> <dc:creator>Ian Oxley</dc:creator> <category><![CDATA[Intermediate]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[events]]></category> <guid
isPermaLink="false">http://jspro.com/?p=2026</guid> <description><![CDATA[jQuery makes event handling in JavaScript easy. However, the more event handlers you define, the more memory you use, which can end up decreasing performance and making the UI sluggish. This article looks at how event delegation can help prevent this, and how you can apply event delegation with jQuery. Event delegation is an event [...]]]></description> <content:encoded><![CDATA[<p></p><p>jQuery makes event handling in JavaScript easy. However, the more event handlers you define, the more memory you use, which can end up decreasing performance and making the UI sluggish. This article looks at how event delegation can help prevent this, and how you can apply event delegation with jQuery.<br
/> <span
id="more-63976"></span></p><p>Event delegation is an event handling technique where, instead of attaching event handlers directly to every element you want to listen to events on, you attach a single event handler to a parent element of those elements to listen for events occurring on it&#8217;s descendant elements. When handling the event, you check which element fired the event, and respond accordingly. Event delegation relies on event bubbling in the DOM. This is the process whereby an event triggered on a child element propagates up the DOM tree to its parent element, and its parent&#8217;s parent element, etc., until the <code>document</code> is reached. Bubbling can also be stopped by the programmer using <a
href="http://api.jquery.com/event.stopPropagation/"><code>event.stopPropagation()</code></a>. Note that not all DOM events propagate &#8211; focus, blur, load, and unload don&#8217;t.</p><p>Event delegation uses less memory because you replace multiple event handlers with a single event handler. For example, if you attach event handlers to each link in a list of ten links, you&#8217;d have ten event handlers taking up space in memory. If, instead, you use event delegation and handle events at the parent <code>&lt;ul&gt;</code> element, you only create one event handler and use less memory than you would&#8217;ve attaching to each link individually. In addition to reduced memory consumption, event delegation also has the following benefits.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><ul><li>No need to manually manage events when elements are added or removed from the DOM. If we used traditional event handling, we&#8217;d have to attach event handlers to elements added to the DOM, and remove event handlers from elements removed from the DOM.</li><li>Less code to manage, through fewer event handling functions. This can leave us with simpler code, without any duplicated event handling logic, which can help keep our JavaScript nice and <a
href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>.</li></ul><h2>An Example of Event Delegation in jQuery</h2><p>Suppose you&#8217;re developing a single page application that sells pictures of kittens. When the page loads, the first 20 kittens are displayed. As the user scrolls down the page, more kittens are loaded. Our HTML is shown below.</p><pre class="brush: xml; title: ; notranslate">
&lt;section id=&quot;cats&quot;&gt;
  &lt;ul&gt;
    &lt;li&gt;
      &lt;img src=&quot;http://placekitten.com/200/200&quot; alt=&quot;&quot;/&gt;
      &lt;a href=&quot;/moreinfo&quot;&gt;More info&lt;/a&gt;
      &lt;button&gt;Add to cart&lt;/button&gt;
    &lt;/li&gt;
    ...
  &lt;/ul&gt;
&lt;/section&gt;
</pre><p>With traditional event handling, we&#8217;ll need to wire up event handlers to:</p><ol><li>Display a larger picture when the user clicks on a thumbnail.</li><li>Display more info when the user clicks on the &#8216;More info&#8217; link.</li><li>Add the picture to the shopping cart when the user clicks &#8216;Add to cart&#8217;.</li><li>Attach these three events to the new DOM elements that are added as the user scrolls down the page.</li></ol><p>This code will resemble the following example. Note that this is boilerplate code intended to show how attaching event handlers to individual elements differs from using event delegation, so no implementation is given for the <code>loadImage()</code>, <code>moreInfo()</code>, <code>addToCart()</code>, and <code>loadNewKittens()</code> functions.</p><pre class="brush: jscript; title: ; notranslate">
$(document).ready(function() {
  var cats = $('#cats');
  cats.find('img')
    .on('click', function() {
      loadImage();
    })
  cats.find('a')
    .on('click', function(event) {
      event.preventDefault();
      moreInfo();
    });
  cats.find('button')
    .on('click', function() {
      addToCart();
    });
  $(window).scroll(function() {
    var fragment = loadNewKittens();
    // attach event handlers for new DOM elements
    fragment.find('img')
      .on('click', function() {
        loadImage();
      });
    fragment.find('a')
      .on('click', function(event) {
        event.preventDefault();
        moreInfo();
      });
    fragment.find('button')
      .on('click', function() {
        addToCart();
      });
    fragment.appendTo('#cats ul');
  });
});
</pre><p>That&#8217;s quite a bit of code. Now let&#8217;s see how our code looks if instead we use event delegation:</p><pre class="brush: jscript; title: ; notranslate">
$(document).ready(function() {
  $('#cats')
    .on('click', 'img, a, button', function(event) {
      event.preventDefault();
      var target = event.target;
  switch(target.tagName.toLowerCase()) {
    case 'img':
      loadImage();
      break;
    case 'a':
      moreInfo();
      break;
    case 'button':
      addToCart();
      break;
    default:
      // do nothing
  }
});
  $(window).scroll(function() {
    var fragment = loadNewKittens();
    fragment.appendTo('#cats ul');
  });
});
</pre><p>The key is the optional second argument to <a
href="http://api.jquery.com/on/"><code>on()</code></a>. By passing a selector here, <code>on()</code> knows it&#8217;s dealing with a delegated event handler rather than a directly bound event handler.</p><p>Our event handling code is a lot simpler now too. By getting a hold of <a
href="http://api.jquery.com/event.target/"><code>event.target</code></a>, and switching on it&#8217;s <code>tagName</code>, we can tell which element fired the event and can respond appropriately. Plus, we no longer have to attach event handlers for elements loaded in <code>$(window).scroll</code>, as the events fired by these new elements are delegated to the parent element.</p><p>A potential &#8216;gotcha&#8217; to be aware of when using event delegation is that any event handlers attached to child elements are handled <em>before</em> the deletated event handler fires. Therefore, it&#8217;s possible for a child event handler to call <code>event.stopPropagation()</code> or <code>return false</code>, which will prevent the event from bubbling up to the delegated event handler, and leave you scratching your head as to why your event isn&#8217;t being delegated.</p><h2>Conclusion</h2><p>In this article we&#8217;ve looked at event delegation. We&#8217;ve seen how it can help improve the performance of your site by lessening the event handling load it has to bear. We&#8217;ve also seen how to implement event delegation in jQuery via the <code>on()</code> function.</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/event-delegation-with-jquery/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Why We Develop jQuery Plugins</title><link>http://www.sitepoint.com/why-we-develop-jquery-plugins/</link> <comments>http://www.sitepoint.com/why-we-develop-jquery-plugins/#comments</comments> <pubDate>Wed, 06 Feb 2013 09:00:26 +0000</pubDate> <dc:creator>Rakhitha Nimesh</dc:creator> <category><![CDATA[Intermediate]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[plugins]]></category> <guid
isPermaLink="false">http://jspro.com/?p=1997</guid> <description><![CDATA[jQuery is one of the most popular JavaScript libraries among web developers and designers. And, many new plugins with amazing effects are created every day. Developers and users tend to select jQuery plugins whenever possible. If you&#8217;re still on the fence about jQuery, this article will help you understand why they are so popular. A [...]]]></description> <content:encoded><![CDATA[<p></p><p>jQuery is one of the most popular JavaScript libraries among web developers and designers. And, many new plugins with amazing effects are created every day. Developers and users tend to select jQuery plugins whenever possible. If you&#8217;re still on the fence about jQuery, this article will help you understand why they are so popular.<br
/> <span
id="more-63975"></span></p><p>A plugin is an independent module that adds custom functionality to an application. Enabling or disabling a plugin does not affect the core system or other plugins. As developers, we tend to look for quick fixes rather than focusing on maintainable solutions. With experience we change our approach to consider maintainability and future enhancements. To understand why plugins are such an attractive option, we must first understand what life would be like without them.</p><h2>Developing Without Plugins</h2><p>Assume that we have been given the task of converting a menu comprised of unordered lists into a select box. This will be a very handy feature to have in our responsive web design toolkit. So, we are going to use it as our base example for understanding why we develop jQuery plugins. Let&#8217;s look at a basic jQuery implementation.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
$(document).ready(function(){
  var select = $('&lt;select&gt;');
  $('#menu li').each(function() {
    var link  = $(this).find('&gt; a');
    var level = $(this).parents('li').length;
    var indent = '';
    for(i=0;i&lt;level;i++){
      indent += '-';
    }
    var option = $('&lt;option&gt;').text(indent + ' ' + link.text())
       .val(link.attr('href'))
       .appendTo(select);
  });
  $('#menu').replaceWith(select);
});
&lt;/script&gt;
</pre><p>The code snippet above converts the unordered list items into options inside a select box. You can see that the unordered list ID is hard coded. If we wanted to convert another list to a select box, we would have to duplicate the existing code, which can be error prone. Instead, we convert the code into a function to make it reusable. The code should be similar to the following:</p><pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
function convertMenusToSelect(menu){
  // Previous code with dynamic item instead of hard coding #menu
}
&lt;/script&gt;
</pre><p>Now, we have a common function that we can reuse over and over again. But, suddenly a new customer requirement comes in with the following two tasks.</p><ul><li>Selected menu options should be highlighted in a given color.</li><li>The indentation sign used for the sub menus should be dynamic.</li></ul><p>The immediate solution would be to add another two parameters to the <strong>convertMenusToSelect()</strong> function to handle both color and indentation sign. However, as more requirements comes in, we will have to add additional parameters, making it hard to maintain. Instead, we can consider passing parameters as an object, as shown below.</p><pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
function convertMenusToSelect(params){
}
var params={menuID: '#menu', color:'#EEE', indentMark : '#' };
convertMenusToSelect(params);
&lt;/script&gt;
</pre><p>There can be both mandatory and optional parameters within the object, so we need to check for the parameters manually in order to extract the correct values. As new requirements comes in, our solution is becoming very hard to maintain. So, let&#8217;s look at a solution using a jQuery plugin and see how it handles the changing requirements.</p><h2>Developing With jQuery Plugins</h2><p>We started the list-to-select box converter with plain jQuery code, and converted it to a reusable function in the process. Now, let&#8217;s look at a jQuery plugin implementation using the following code.</p><pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
(function($){
  $.fn.extend({
    selectConvert: function(options) {
      var defaults = {
        color: '#EEE',
        indentMark: '-',
      }
      var options =  $.extend(defaults, options);
      this.each(function() {
        var o = options;
        var currentItem = $(this);
        var select = $('&lt;select&gt;');
        $(currentItem).find('li').each(function() {
          var link  = $(this).find('&gt; a');
          var level     = $(this).parents('li').length;
          var indent = '';
          for(i=0;i&lt;level;i++){
            indent += o.indentMark;
          }
          var option = $('&lt;option&gt;').text(indent + ' ' + link.text())
            .val(link.attr('href')).css('background',o.color)
            .appendTo(select);
        });
        $(currentItem).replaceWith(select);
        return select;
      });
    }
  });
})(jQuery);
&lt;/script&gt;
</pre><p>In the above code <code>selectConvert</code> will be our plugin name, and will be a separate namespace inside the jQuery.fn object. Each of the plugin methods will be placed inside the <code>selectConvert()</code> function. The plugin function uses a variable called <code>options</code> to handle the data passed on initialization. The <code>defaults</code> variable contains all of the allowed variables and their default values. We can also assign functions to the <code>defaults</code> section.</p><p>Then, we compare the <code>defaults</code> against the options passed to the plugin using the jQuery <code>extend()</code> function. The final output will contain the passed option values and default values which are not provided in the initialization. Hence, adding new parameters is not such a difficult task with jQuery plugins. Finally, we execute the conversion code with the provided options and returns the converted item.</p><h2>The Importance of jQuery Plugins</h2><p>We made the decision to implement a plugin due to the issues we had with the plain jQuery implementation. Now, let&#8217;s see why we prefer jQuery plugins over pure JavaScript implementations.</p><ul><li><strong>Prevents Function Conflicts</strong><p>We create all the plugin related functions inside a unique namespace. So, the possibility of name conflicts is reduced with plugins.</li><li><strong>Extendability</strong><p>jQuery plugins automate the process of extending parameters and functions within the plugin. We can define the default parameters and functions inside the plugin and override them at runtime using extended values and functions. This reduces the work of handling required and optional parameters.</li><li><strong>Chainability</strong><p>I would assume chainability is the most powerful factor in jQuery plugins. In pure JavaScript we have to call functions, assign the results to variables, and pass them to the next function. With jQuery, we can call another function or plugin on the same returned results in one line of code. Consider the following code, which combines a jQuery autocomplete select box plugin with our design. You can chain together any number of functions or plugins on the same result set, making it easy to add and remove functionality dynamically.</p><pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
$(document).ready(function() {
  $('#menu').selectConvert().combobox();
});
&lt;/script&gt;
</pre></li><li><strong>Reusability</strong><p>jQuery plugins allows us to use the same functionality over multiple elements without duplicating code. We used a single menu in our initialization code as shown below.</p><pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
$(document).ready(function() {
  $('#menu').selectConvert();
});
&lt;/script&gt;
</pre><p>Generally, we need to use two lines for converting two menus. But jQuery makes is possible to reuse the same line of initialization code for both menus as shown in the following code.</p><pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
$(document).ready(function() {
  $('#menu,#menu2').selectConvert();
});
&lt;script&gt;
</pre></li><li><strong>Encapsulation</strong><p>We can define both public and private functions inside a jQuery plugin. Therefore, we can encapsulate the logic inside the plugin and decide which components are publicly visible and which are private to the plugin. So, plugin developers and users will only be able to call features publicly available.</li><li><strong>Usability</strong><p>Most of the people who uses jQuery plugins are not very experienced with JavaScript or jQuery. As developers, we need to make it as simple as possible to use the plugins. jQuery plugins provides a common initialization technique, where you can call the plugin initialization function on any compatible element. Therefore, users can just copy the initialization code and everything will work.</li></ul><h2>Conclusion</h2><p>We have used one of the most basic patterns of jQuery plugins in this tutorial. There are also several advanced patterns which make it even easier to write highly maintainable and extendable code. As a developer, you might be wondering why we can&#8217;t do the same with plain JavaScript. jQuery is built using JavaScript, so JavaScript <em>is</em> capable of providing anything jQuery provides. However, we prefer to use jQuery since it abstracts many common tasks and allows us to focus on application logic.</p><p>It&#8217;s time to share your opinion on jQuery plugins vs pure JavaScript implementation. Do you prefer developing and using jQuery plugins? Let us know. You can also download the code used in this article from the <a
href="https://github.com/jsprodotcom/source/blob/master/Why-We-Develop-jQuery-Plugins.zip" title="Source Code" target="_blank">JSPro GitHub page</a>.</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/why-we-develop-jquery-plugins/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Introducing the jQuery Plugins Registry</title><link>http://www.sitepoint.com/jquery-plugins-registry/</link> <comments>http://www.sitepoint.com/jquery-plugins-registry/#comments</comments> <pubDate>Wed, 23 Jan 2013 18:07:33 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[Libraries]]></category> <category><![CDATA[News]]></category> <category><![CDATA[Open source]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[jQuery Tutorials & Articles]]></category> <category><![CDATA[library]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/?p=62623</guid> <description><![CDATA[The jQuery team have launched a new Plugin Registry; a facility which is long overdue. Craig takes a first look at the resource...]]></description> <content:encoded><![CDATA[<p></p><p>The popularity of <a
href="http://jquery.com/">jQuery</a> continues unabated. At the <a
href="http://w3techs.com/technologies/details/js-jquery/all/all">last count</a>, the JavaScript library has been adopted by 55% of all websites. More impressively, it&#8217;s loaded on more than 90% of sites which use a library.</p><p>However, not all is perfect in the jQuery world. Despite having a great plugin system, how do you locate a plugin for your needs? The original repository at <a
href="http://jquery.com/">jquery.com</a> was clunky at best; search results were poor, code was out of date and documentation was sparse. Googling was a better option but finding suitable code was a hit-and-miss affair. Ultimately, it was often easier to <a
href="http://www.sitepoint.com/how-to-develop-a-jquery-plugin/">develop your own jQuery plugin</a>.</p><p>Fortunately, the jQuery team are aware of the issue and have launched a new <a
href="http://plugins.jquery.com/"><strong>jQuery Plugin Repository</strong></a>. Their aim is to reduce the fragmentation and distribution problems that can be obstacles for plugin developers and consumers.</p><h2>How to Download jQuery Plugins</h2><p>You can search, browse or click tags to locate plugins in the <a
href="http://plugins.jquery.com/">jQuery Plugin Repository</a>. Each plugin page provides a brief description, compatibility information and links to the home page, documentation, demonstrations, issues and downloads.</p><h2>How to Register New jQuery Plugins</h2><p>If you&#8217;d like to share your amazing jQuery plugin, there are several steps required to publish code on the <a
href="http://plugins.jquery.com/">jQuery Plugin Repository</a>:</p><ol><li><a
href="http://plugins.jquery.com/docs/names/">Choose a unique name</a>. Keep it short, descriptive and don&#8217;t use a name which has already been taken. It&#8217;s first come, first served.</li><li><a
href="http://plugins.jquery.com/docs/package-manifest/">Create a package manifest</a>. This is a JSON file describing the plugin, version, dependencies, developer, license, links etc.</li><li><a
href="http://plugins.jquery.com/docs/publish/">Publish your plugin on GitHub</a>. You&#8217;ll need to <a
href="https://github.com/">sign-up for an account</a>, <a
href="https://help.github.com/articles/post-receive-hooks">create a post-receive hook</a> with the URL <code>http://plugins.jquery.com/postreceive-hook</code>, and push using your preferred <a
href="https://help.github.com/articles/set-up-git">Git tool</a>.</li></ol><h2>First Impressions</h2><p>The <a
href="http://plugins.jquery.com/">jQuery Plugin Repository</a> is new and has a limited selection of plugins available. The search isn&#8217;t the best, plugin descriptions are terse and you need to link out to various information pages which slows down browsing. For me, the most fundamental omission is an absence of user ratings and reviews.</p><p>That said, the aim must be to create a repository which is as useful as the <a
href="http://wordpress.org/extend/plugins/">WordPress Plugin Directory</a>; a definitive and easy-to-use resource with a thriving developer community. Let&#8217;s hope the jQuery team succeed.</p><p>Will you publish your code to jQuery Plugin Repository? If you need a plugin, would you head there first?</p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/jquery-plugins-registry/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>What&#039;s New in jQuery 1.9</title><link>http://www.sitepoint.com/jquery-19-whats-new-2/</link> <comments>http://www.sitepoint.com/jquery-19-whats-new-2/#comments</comments> <pubDate>Mon, 21 Jan 2013 19:30:32 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <guid
isPermaLink="false">http://jspro.com/?p=1893</guid> <description><![CDATA[jQuery 1.9 was released on January 15, 2013 and marks an important milestone on the road to world domination. The code has been streamlined in readiness for version 2.0 which drops IE6, 7 and 8 support. jQuery has been adopted by 55% of all websites and 90% of those loading a JavaScript library. It&#8217;s important [...]]]></description> <content:encoded><![CDATA[<p></p><p>jQuery 1.9 was released on January 15, 2013 and marks an important milestone on the road to world domination. The code has been streamlined in readiness for version 2.0 which drops IE6, 7 and 8 support.<br
/> <span
id="more-63969"></span></p><p>jQuery has been adopted by 55% of all websites and 90% of those loading a JavaScript library. It&#8217;s important to JavaScript coders and almost anyone creating a modern website or application.</p><p>Over at SitePoint.com, I discuss <a
href="http://www.sitepoint.com/jquery-19-whats-new/"><strong>What&#8217;s New in jQuery 1.9</strong></a>. There are a few new methods but it&#8217;s the removed features which will cause most concern for those using older plugins. The jQuery team have great solution, but is their decision to abandon legacy IE browsers a little premature? <a
href="http://www.sitepoint.com/jquery-19-whats-new/"><em>Read on&hellip;</em></a></p><div
class='after-content-widget-1'><div
id="sitepointcontextualcontentmanagerwidget-5" class="widget widget_sitepointcontextualcontentmanagerwidget"><div
class="dfp-ad show-desktop"><div
id="div-gpt-ad-1340873946991-4" style="width: 728px; height: 90px;"> <script type="text/javascript">googletag.cmd.push(function() { googletag.display("div-gpt-ad-1340873946991-4"); });</script> </div></div></div></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/jquery-19-whats-new-2/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 43/73 queries in 0.089 seconds using memcached
Object Caching 2041/2211 objects using memcached

Served from: www.sitepoint.com @ 2013-05-13 15:02:27 --