<?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/"
	>

<channel>
	<title>Stoat - Where? &#187; Javascript</title>
	<atom:link href="http://jamietalbot.com/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://jamietalbot.com</link>
	<description>Adventures in Engrish</description>
	<lastBuildDate>Sat, 29 Oct 2011 05:14:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Object Oriented jQuery Plugins Mk 2</title>
		<link>http://jamietalbot.com/2010/08/26/object-oriented-jquery-plugins-mk-2/</link>
		<comments>http://jamietalbot.com/2010/08/26/object-oriented-jquery-plugins-mk-2/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 23:02:40 +0000</pubDate>
		<dc:creator>Jamie Talbot</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[Object Oriented Design]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://jamietalbot.com/?p=98</guid>
		<description><![CDATA[Update: This code is now on GitHub and has had some substantial improvements made. You should look at the latest code here and submit a pull request if you make any improvements! In a recent post, I outlined a method to abstract away the complexity of creating an encapsulated jQuery plugin. However, as was pointed [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update:</strong> This code is now on GitHub and has had some substantial improvements made.  You should look at the latest code <a href="https://github.com/majelbstoat/Celsus/blob/master/js/plugins/encapsulatedPlugin.js">here</a> and submit a pull request if you make any improvements!</p>
<hr />
<p>In a <a href="http://jamietalbot.com/2010/08/22/object-oriented-jquery-plugins/">recent post</a>, I outlined a method to abstract away the complexity of creating an encapsulated jQuery plugin.  However, as was pointed out in the comments, there was a missing piece that didn&#8217;t allow for arguments to be passed through.  More seriously, there was an issue with the binding of the facade function, which meant that only the last defined public function in the class could be called.</p>
<p>As an aside, if you need to bind a variable at the time that it is defined, it isn&#8217;t enough to define an anonymous function with a reference to the closure, as that can change by the time the function is called.  The bug in my code was in the piece that bound the facade function to the set member functions.</p>
<pre class="brush: jscript; title: ; notranslate">
	for ( var i in template) {
		if (typeof (template[i]) == 'function') {
			result[i] = function() {
				this.each(function() {
					this[i]();
				});
			};
		}
	}
</pre>
<p>By the time the inner function is called, &#8220;i&#8221; has already been re-bound to the final function name in the template.  The solution is to bind the inner function name to the outer function name at the time of definition, which we can do by wrapping it in (yet another!) function.</p>
<pre class="brush: jscript; title: ; notranslate">
	// Iterates through the set calling the specified function.
 	function makeIteratorFunction(f, set) {
		return function() {
			for ( var i = 0; i &lt; set.length; i++) {
				set[i][f].apply(set[i][f], arguments);
			}
		};
	}
</pre>
<p>and then calling that function:</p>
<pre class="brush: jscript; title: ; notranslate">
	if (template) {
		for ( var i in template) {
			if (typeof (template[i]) == 'function') {
				result[i] = makeIteratorFunction(i, result);
			}
		}
	}
</pre>
<p>At this point, although &#8220;i&#8221; will continue to change as the loop continues, the function call is bound through the closure on &#8220;f&#8221; in the auxiliary function, which remains fixed.  Google Chrome&#8217;s developer tools certainly make following all that a lot simpler!  I&#8217;ve updated the plugin with these improvements, which also enables us to pass arguments through, finally allowing:</p>
<pre class="brush: jscript; title: ; notranslate">
$('#foo').myplugin().publicMethodWithArguments('hello');
</pre>
<p>You can get the updated plugin <a href="/projects/js/jquery/encapsulatedPlugin.js.txt" title="jQuery encapsulated plugin generating plugin">here</a>.  Feedback welcomed!</p>
]]></content:encoded>
			<wfw:commentRss>http://jamietalbot.com/2010/08/26/object-oriented-jquery-plugins-mk-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Object Oriented jQuery Plugins</title>
		<link>http://jamietalbot.com/2010/08/22/object-oriented-jquery-plugins/</link>
		<comments>http://jamietalbot.com/2010/08/22/object-oriented-jquery-plugins/#comments</comments>
		<pubDate>Sun, 22 Aug 2010 17:36:48 +0000</pubDate>
		<dc:creator>Jamie Talbot</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[Object Oriented Design]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://jamietalbot.com/?p=91</guid>
		<description><![CDATA[Object oriented jQuery plugins have typically been hard to create in an elegant way.  Here, we demonstrate how to design a clean jQuery plugin which allows for full encapsulation of data, and allows access to public methods without using the data object as a obvious proxy.]]></description>
			<content:encoded><![CDATA[<p><strong>Update 2:</strong> This code is now on GitHub and has had some substantial improvements made.  You should look at the latest code <a href="https://github.com/majelbstoat/Celsus/blob/master/js/plugins/encapsulatedPlugin.js">here</a> and submit a pull request if you make any improvements!</p>
<hr />
<p><strong>Update:</strong> As pointed out in the comments, the first version of this code didn&#8217;t allow for methods with parameters.  Although the code in the main post below is unchanged, the code linked at the bottom of the page and <a href="/projects/js/jquery/encapsulatedPlugin.js.txt" title="jQuery encapsulated plugin generating plugin">here</a> has been updated to reflect some improvements, that now allow this and some other niceties.  The main body of the post should still be worth reading for the derivation though!</p>
<hr />
<p>I&#8217;ve recently begun the process of porting some javascript library code from Prototype to jQuery, and on the whole it hasn&#8217;t been too problematic.  I really like the element-centric nature of jQuery, whereas Prototype is more like a excellent set of useful static methods.  There were only a couple of things I found myself really missing, and they were enumerables, and elegant plugin encapsulation.  The first problem was solved with Xavier Shay&#8217;s nice <a href="http://rhnh.net/2008/12/28/inject-and-collect-with-jquery" title="Enumerables for jQuery">enumerables plugin</a>.  The second one was more of a challenge.</p>
<p>The lack of encapsulation for jQuery plugins seems to be a common frustration, and there are lots of queries on the web along the lines of &#8220;how do I add public methods to a jQuery plugin&#8221;.  The best solution I found came from <a href="http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html">Hector Virgen</a>, which allows you to do something like this:</p>
<pre class="brush: jscript; title: ; notranslate">
var pluginInstance = $('#foo').data('myplugin');
pluginInstance.publicMethod();
</pre>
<p>That&#8217;s pretty neat, but I didn&#8217;t really like the idea of having to go through the data object each time.  A couple of other people in the comments felt the same way, but there didn&#8217;t seem to be any solutions forthcoming, so I had a crack.  What follows is largely based on Hector&#8217;s code, so you should go and read that first before you go through this.</p>
<p>We start off with a basic plugin shell, slightly modified from Hector&#8217;s, per my taste:</p>
<pre class="brush: jscript; title: ; notranslate">
(function($) {
	var Celsus = Celsus || {};
	Celsus.MyPlugin = function(element, options) {

		// Private members
		var elem = $(element);

		var settings = $.extend({}, options || {});

		// Private methods
		function _privateMethod() {
			console.log(&quot;This is a private method!&quot;);
		}

		return {
			publicMethod: function() {
				console.log(elem);
				_privateMethod();
				return true;
			}
		};
	};

	$.fn.myplugin = function(options) {
		return this.each(function() {
			var element = $(this);
			if (element.data('myplugin')) {
				return;
			}
			var myplugin = new Celsus.MyPlugin(this, options);

			// Store the new plugin definition in a data object.
			element.data('myplugin', myplugin);
		});
	};
})(jQuery);
</pre>
<p>This is a pretty good start.  However, as Hector points out, the main issue is that the plugin returns a jQuery object to enable chaining.  In many complex instances, chaining isn&#8217;t necessarily something you&#8217;re going to want to do, so we make a small sacrifice and forego that convenience.  Instead, we are going to return a set of plugin instance objects:</p>
<pre class="brush: jscript; title: ; notranslate">
$.fn.myplugin = function(options) {
	var result = [];
	this.each(function() {
		var element = $(this);

		if (!element.data('myplugin')) {
			// Initialise
			var myplugin = new Celsus.MyPlugin(this, options);

			// Store the new functions in a validation data object.
			element.data('myplugin', myplugin);
		}
		result.push(element.data('myplugin'));
	});
};
</pre>
<p>At this point, it&#8217;s not looking too great.  We&#8217;ve broken chaining because we no longer return a jQuery object, but if you try and call</p>
<pre class="brush: jscript; title: ; notranslate">
$('#foo').myplugin().publicMethod();
</pre>
<p>it still doesn&#8217;t work.  This is because, although each plugin instance has the publicMethod() function, they are contained inside a bare array.  At this point we could actually do:</p>
<pre class="brush: jscript; title: ; notranslate">
($('#foo').myplugin()[0]).publicMethod();
($('#foo').myplugin()[1]).publicMethod();
</pre>
<p>Or something similar with each(), but this is very messy.  We need a bit of syntactic sugar.  To achieve this, the next step is to take that array, turn it into something we can work with, and add a facade, so that every public function we&#8217;ve just mixed in is presented as an option on the plugin instance set.  We do that by adding the following to the plugin definition:</p>
<pre class="brush: jscript; title: ; notranslate">
result = $(result);
var template = result[0];
if (template) {
	for ( var i in template) {
		if (typeof (template[i]) == 'function') {
			result[i] = function() {
				this.each(function() {
					this[i]();
				});
			};
		}
	}
}
</pre>
<p>Firstly, we convert the array to a jQuery object.  Then, we look at the first instance in the set and use that as a template.  It should contain all the public functions we&#8217;ve defined in our definition class, and all the instances are of the same type, so we can safely use the first entry&#8217;s template for all of them.  We then enumerate through all the public functions and create a proxy or facade function on the set, which simply calls the closure of that function for each element in the set.  This ensures that when you call</p>
<pre class="brush: jscript; title: ; notranslate">
$('#foo').myplugin().publicMethod();
</pre>
<p>it is functionally equivalent to:</p>
<pre class="brush: jscript; title: ; notranslate">
$('#foo').myplugin().each(function(instance) {
	instance.publicMethod();
});
</pre>
<p>So that&#8217;s pretty cool.  We&#8217;ve avoided namespace pollution, we can mix in any number of public methods, and private members and methods behave as you&#8217;d expect them to.  It isn&#8217;t possible to access public variables in this manner of course, but that is easily remedied by using public getters and setters.  We can even add in a reference back to the jQuery object, so we can get chaining back in in some form:</p>
<pre class="brush: jscript; title: ; notranslate">
result.$ = this;
</pre>
<p>Which lets us do:</p>
<pre class="brush: jscript; title: ; notranslate">
$('#foo').myplugin().$.addClass('bar');
</pre>
<p>This is useful when you&#8217;re doing plugin initialisation, but thereafter it&#8217;s a bit redundant as the actual plugin call simply returns an object which you then ignore.  The only final point is that there&#8217;s quite a lot of boilerplate going on here just to get set up.  In actual fact, the actions are pretty generic, so we can extract all that code and put it in its own plugin.  A plugin to generate a plugin!</p>
<pre class="brush: jscript; title: ; notranslate">
(function($) {
	$.fn.encapsulatedPlugin = function(plugin, definition, objects, options) {
		var result = [];
		objects.each(function() {
			var element = $(this);

			if (!element.data(plugin)) {
				// Initialise
				var instance = new definition(this, options);

				// Store the new functions in a validation data object.
				element.data(plugin, instance);
			}
			result.push(element.data(plugin));
		});

		// We now have a set of plugin instances.
		result = $(result);

		// Take the public functions from the definition and make them available across the set.
		var template = result[0];
		if (template) {
			for ( var i in template) {
				if (typeof (template[i]) == 'function') {
					result[i] = function() {
						this.each(function() {
							this[i]();
						});
					};
				}
			}
		}

		// Finally mix-in a convenient reference back to the objects, to allow for chaining.
		result.$ = objects;

		return result;
	};

})(jQuery);
</pre>
<p>With this little plugin, our plugin initialisation code is a lot lighter:</p>
<pre class="brush: jscript; title: ; notranslate">
	$.fn.myplugin = function(options) {
		return $.fn.encapsulatedPlugin('myplugin', Celsus.MyPlugin, this, options);
	};
</pre>
<p>Not too bad!  The actual code that specialises a plugin is tucked away in a neatly encapsulated object, we have access to all the public methods defined on it and multiple instances can happily live side by side and be invoked separately without trampling on each other.    You can grab a copy of the plugin generating plugin from <a href="/projects/js/jquery/encapsulatedPlugin.js.txt" title="jQuery encapsulated plugin generating plugin">here</a>.  This is still new cod and there might be the odd glitch, so if you spot any, or have other ideas, be sure to leave a comment!</p>
]]></content:encoded>
			<wfw:commentRss>http://jamietalbot.com/2010/08/22/object-oriented-jquery-plugins/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>CSS Technique: Morning Sunset</title>
		<link>http://jamietalbot.com/2010/03/10/css-technique-morning-sunset/</link>
		<comments>http://jamietalbot.com/2010/03/10/css-technique-morning-sunset/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 22:39:31 +0000</pubDate>
		<dc:creator>Jamie Talbot</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Dojo]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[Morning Sunset]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://jamietalbot.com/?p=58</guid>
		<description><![CDATA[A novel CSS+Javascript effect that allows a site to blend from one full-page image to another as the visitor scrolls down the page.]]></description>
			<content:encoded><![CDATA[<p>After coming across <a href="http://css-tricks.com/perfect-full-page-background-image/">an excellent article</a> on generating full page images, I had the idea that it would be cool to blend between multiple images as a user scrolled down the page.  The somewhat artistic conceit that a user could scroll a similar scene from morning to sunset, ironically came to me at sunset on Saturday and was finished by morning!</p>
<p>The effect is pretty simple to set up, though does require a specific bit of markup.  We start with 2 images and set a z-index on them, such that the first one is in front of the second.  With the full page image CSS rules, the first image fills the screen and the second is completely obscured.  </p>
<pre class="brush: php; title: ; notranslate">
&lt;img id=&quot;morning&quot; class=&quot;bg&quot; style=&quot;z-index: 2;&quot; src=&quot;morning.jpg&quot; /&gt;
&lt;img id=&quot;sunset&quot; class=&quot;bg&quot; style=&quot;z-index: 1;&quot; src=&quot;sunset.jpg&quot; /
</pre>
<p>For the CSS, In addition to the standard full page image rules, I add an additional higher z-index, plus a little bit of transparency  This allows the content to sit on top of both of these images, and for the effect to be more pronounced.</p>
<pre class="brush: css; title: ; notranslate">
div#content {
	/* This is the only important rule */
	/* We need our content to show up on top of the background */
	position: relative;
	z-index: 10;

	/* Added some opacity to demonstrate the effect better */
	opacity: 0.8;
	filter: alpha(opacity=80);
}
</pre>
<p>So far, so what?  We&#8217;ve arranged for a user to download an image he can&#8217;t see &#8211; not so good.  The magic comes with a blending function tied to the scrollbar.  The idea is that the top layer becomes more and more transparent as the user scrolls through the content.</p>
<p>In working with the Zend Framework, I&#8217;ve been getting to grips with Dojo and its supporting classes, so I was happy to see that Dijit had tools for getting the dimensions of the viewport.  With this information, I was able to calculate the scroll ratio, which gave me a number ranging from 0 at the top of the page to 1 at the bottom.</p>
<p>Dojo also has a great style() function, which allows you to set opacity and have it &#8220;just work&#8221;, across all browsers, regardless of their non-standard filter() shennanigans.  At the outset, the top layer image has an opacity of 1.  Subtracting the scroll ratio from this allows it to be fully opaque at the top of the page, and fully transparent at the bottom.</p>
<pre class="brush: jscript; title: ; notranslate">
dojo.subscribe(&quot;/window/scrolled&quot;, function(e){
	// Calculate the scroll percentage, and adjust the opacity of the top layer, appropriately.
	var vp = dijit.getViewport();
	dojo.style(&quot;morning&quot;, {
		&quot;opacity&quot;: 1 - (vp.t / (document.documentElement.scrollHeight - vp.h))
	});
});
</pre>
<p>There is some rate-limiting code going on to prevent the event firing continuously and slowing down the page.  That came from a helpful <a href="http://dojocampus.org/content/2009/09/28/rate-limiting-with-javascript/">Dojo Cookie</a> by Peter Higgins over at Dojo Campus.  I haven&#8217;t played fully with the rate limiting yet, but 50ms seemed to give a reasonable balance of subtle movement without overloading the page.</p>
<p>Degradation is variable &#8211; without Javascript, the user just sees the top image and there&#8217;s some overhead of the second image that is never seen.  Without CSS, there&#8217;s more of a problem, as the images are inlined in the page, which pushes all the content down.  If there is a full page image solution using background images only, I&#8217;d love to hear about it.</p>
<p>There&#8217;s <a href="http://jamietalbot.com/projects/css/morning-sunset/">a working, self-describing example</a> of the effect so you can try it out for yourself.  It works best in Chrome, with its superior Javascript handling, but works in all modern browsers to a reasonable degree.</p>
<p>The next step is to generalise the code, so that I can pass it an array of image URLs and have it automatically build the markup necessary to generate the effect.  With more work on the blending function, I&#8217;ll be able to have it blend between multiple layers and potentially follow different rates &#8211; I might investigate Dojo curves for that.</p>
<p>I&#8217;m not aware of this technique being described anywhere else, but if there are other approaches to doing this, I&#8217;d be interested to see them.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamietalbot.com/2010/03/10/css-technique-morning-sunset/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

