Monday, December 28, 2009

Embedding HTML from jQuery AJAX Call Into Your Page

I got an interesting Twitter question the other day and thought I would blog about it to help anyone who has a similar situation.

Question

Hey buddy! How can I do a simple thing as loading a page into a div using Ajax and on the loaded page, execute a simple task as executing a javascript with an alert box?!? The page is loaded but the javascript just doesn't run! If I access the page direct directly, the alert pops out ok! --@montedesucata

 

Scenario 1

My initial thoughts were that he was trying to put an entire HTML document (pulled back from an AJAX call) inside another HTML document (the document that made the AJAX call). You can't do that because then you’d have two html elements, two head elements, two body elements, etc... in one document. So, my first example was to put the contents into an iFrame.

Note: You can also, strip out the body content of the returned full HTML document and inject that into your current document, but then you might not have the correct scripts or css files that were included in the head element (or wherever you put those).

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Load Full HTML Document via AJAX into iFrame</title>
   <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   <style>
      .dynamicIframe { 
         display: none; width: 100%; border: none 1px black; 
      }
   </style>   
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
   <script type="text/javascript">
   $(function() {
      $('#load').click(function() {
         $.ajax({
            type: "GET",
            url: "FullTestHtmlWithAlert.html", 
            dataType: "html",
            success: function(html) {
               $("#dynamicContent")
                  .contents().find("body")
                  .html(html).end().end()
                  .fadeIn('slow');               
            }
         });
         return false;
      });
   });
   </script>   
</head>
<body>
   <h3>Load Full HTML Document via AJAX into iFrame</h3>
   <button id="load">Load</button><br/>
   <iframe id="dynamicContent" class="dynamicIframe"></iframe><br/>
</body>
</html>

The contents of the FullTestHtmlWithAlert.html are below…

<!-- FullTestPageWithAlert.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Load Full HTML Document via AJAX into iFrame</title>
   <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   <script type="text/javascript">
      alert('Hello World!');
   </script>
</head>
<body>
   <h3>Hello World From Full Html Document</h3>
</body>
</html>

The following is a screenshot of the results after clicking the Load button.

LoadFullHtmlDocumentViaAjaxIntoIframe

Feel free to Demo the above code below...

cooltext439924698

Scenario 2

The other scenario is that the HTML from the AJAX call is a partial document, meaning that it doesn’t include html, head, body, etc… tags and is just content that might be found in a body tag. This is a simpler case and the results can easily be injected into another DOM element in the document.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Load Full HTML Document via AJAX into iFrame</title>
   <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
   <script type="text/javascript">
   $(function() {
      $('#load').click(function() {
         $.ajax({
            type: "GET",
            url: "PartialTestHtmlWithAlert.html", 
            dataType: "html",
            success: function(html) {
               $('#dynamicContent').html(html)
                  .fadeIn('slow');
            }
         });
         return false;
      });      
   });
   </script>   
</head>
<body>
   <h3>Load Parital HTML Document via AJAX into Div</h3>
   <button id="load">Load</button><br/>
   <div id="dynamicContent" style="display: none;"></div>
</body>
</html>

The contents of the PartialTestHtmlWithAlert.html are below…

<!-- PartialTestPageWithAlert.html -->
<script type="text/javascript">
alert('Hello World!');
</script>
<table>
    <tr>
        <td>1</td>
        <td>2</td>
    </tr>
    <tr>
        <td>a</td>
        <td>b</td>
    </tr>
</table>

The following is a screenshot of the results after clicking the Load button.

LoadPartialHtmlDocumentViaAjaxIntoDiv

Feel free to Demo the above code below...

cooltext439924698

Tuesday, December 22, 2009

Performance of JavaScript Looping Techniques

I was reading Paul Irish’s (@paul_irish) recent blog post entitled Updates from all around – Dec 2009 and I saw an interesting for loop syntax that he referenced…

for (var i = -1, len = arr.length; ++i < len; ) // the cool guy loop

He went on further to show some performance results of the above syntax compared to the old for loop style most of us are used to.

I thought this was interesting, so I decided to put my own suite of tests together to exercise various looping techniques and determine their average performance. 

Note: In my test methods I wanted to simulate a semi-real world scenario where an array would be used and in the loop an item from the array would be referenced.

The test runner accepts the size of the array to be looped and the number of times you want the test to be ran. The end result will print the average time (in milliseconds) the test took to the console.

Here are the functions that I am profiling…

function oldAndBusted() {
   for (var i = 0; i < arr.length; ++i) { arr[i]; }
}

function oldAndBustedCached() {
   var arrLength = arr.length;
   for (var i = 0; i < arrLength; ++i) { arr[i]; }
}

function coolGuyLoop() {
   for (var i = -1, len = arr.length; ++i < len; ) { arr[i]; } 
}

function coolGuyLoopCached() {
   var arrLength = arr.length;
   for (var i = -1, len = arrLength; ++i < len; ) { arr[i]; } 
}

function whileLoopCached() {
   var i = 0, arrLength = arr.length;
   while (i < arrLength) { arr[i]; i++; }
}

function reverseWhileLoop() {
   var i = arr.length; 
   while (i--) { arr[i]; }
}

Here are the results of my testing...

JavaScriptLoopPerformance2

You can view, run, and edit the tests for yourself on JS Bin (jsbin.com/uvoye/edit)

From a speed perspective here is how the various looping techniques ranked against each other (#1 being fastest & #6 being slowest)

  1. Reverse While Loop
  2. The Cool Guy Loop
  3. Old and Busted Cached
  4. While Loop Cached
  5. The Cool Guy Loop Cached
  6. Old and Busted
    I was actually surprised that ‘the cool guy loop cached’ was slower than ‘the cool guy loop’. I was thinking if I saved off the array length into a variable that it would speed up the loop instead of accessing the length every time.
    Note: If you have any variations of a loop you would like to see in my test cases, please provide a comment with your suggestion.

cooltext439924698 cooltext439925164

Note: The above performance times were ran using FireFox 3.6 Beta 4 using FireBug 1.5X.0b8 on an Intel Quad Core 2.00GHz Laptop running Win7.

Twitter Killed the jQuery Star

As many of you are aware, I am a frequent Tweeter and regularly distribute Web Developer technology related links for .NET and jQuery via my Tech Tweets.

Historically, my main concern was to just gather the latest web dev news and Tech Tweet those out to the public.

However, more and more many of these posts are just round-ups of other posts with little or no commentary. These posts tend to clutter the interwebs with noise that makes it difficult to find the real gems of web development. 

A combination of a recently article entitled Smashing Magazine Killed The Community (Or Maybe It Was Me) and the input of several individuals that I respect inspired me to change how I am Tech Tweeting.

I put out an informal poll on Twitter and here were the results…

TopjQueryPluginPoll

The funny thing is that most of the responses were either in total support of the posts or in total opposition to the posts.

So what now? That is a good question. I’m not sure if you have noticed, but I have dramatically decreased the amount of round-up posts that I tweet.

If a blog post matches one or more of the following criteria it is most likely not going to be tech tweeted anymore…

  1. The title of the blog post starts with a number (example: “Top 10 jQuery Plug-in…”)
  2. If the blog post contains a series of screenshots from other websites without any original content
    Over the past couple of weeks I have been saving jQuery posts that I’ve not tweeted matching the above criteria. Thus far I have 22 rejected blog posts!

For those of you who voted that you liked the round-up posts, I still plan to post those blog posts, but only those that are of the highest quality and hopefully provide some sort of original content such as sample code, pros & cons, personal thoughts, etc…

My goal is to aid the jQuery community, not work against it ;)

Note: If you have any feedback about the above post or how I can improve Tech Tweets, please let me know.

Now for listening enjoyment...

Monday, December 21, 2009

Year End Twitter Cloud

TwitterCloud2009Small3

To end off the year, I thought I’d generate a quick Tweet Cloud that represents my top word usage on Twitter.

I think the above image pretty much sums up my presence on Twitter ;) As if you didn’t know before, I mostly tweet about ASP.NET MVC, jQuery, and general Web Dev related topics.

The above graph was generated by TweetStats and then passed through a service called Wordle.

Note: You can also generate Twitter Clouds using the TweetCloud service, but I found that it wasn’t as accurate at the TweetStats service that I used above. For example, TweetCloud didn’t list ASP.NET MVC as one of my top Twitter words, whereas TweetStats did. Maybe TweetCloud doesn’t account for hashtags?

I hope you have a great Christmas and a New Year!

Friday, December 18, 2009

Tools of the Tech Tweet Trade

TechTweetBird I get a lot of questions about how I go about finding and distributing my Tech Tweets on a day to day basis. Some people even have the notion that I just sit at my computer and tweet all day.

I thought I’d put together some of these questions and answer them for you. The process is ongoing and regular changes, but the following will capture what I am doing today.

Before we start going into the logistics of what I use and how I use it, I thought I’d first give you a quick overview of why I started tech tweets and why I continue to provide them.

So, without further ado, here are the questions…

1. Why did you start doing Tech Tweets?

I’ve always been a sucker for the latest and greatest technologies. Not only do I enjoy finding out about the latest news and tools, but I also enjoy learning more about my current craft and becoming a better programmer. For these reasons, I regularly sorted through a wide variety of RSS feeds looking for what’s new.

At first, I just kept those links to myself and tried to build my craft. As time progressed I thought my teammates at work might benefit from the links I’ve found as well.

Shortly after, I became aware of Twitter where I was able to take a peak into the minds of those that I admire (in the programming world). Then I figured maybe someone outside of my team might benefit from the links, so I started tweeting them. At first I thought it would also be helpful for me to search for my old tweets, but I later found out that the Twitter search doesn’t go back all that far (in my case like 3 weeks).

2. How do you find all the information for you Tech Tweets?

Tweetie2_320 reader twitter_256x256 194beddda84293e00a3a25b0989

I use a variety of tools to help round up the latest Tech Tweets. One of my main tools happens to by my iPhone. While I am out, I often get on Tweetie and search Twitter for jQuery and ASP.NET MVC related information. When I find an interesting article, I will post the tweet to Instapaper. A long time ago I used to favorite tweets, but I like the concept of marking Instapaper entries as read (kind of like you do in e-mail). So, Tweetie is one of the iPhone Twitter apps that has integration with Instapaper.

Once I get access to my main computer, then I move on to Google Reader to check my daily RSS feeds (of which I currently have 227 subscriptions even after removing quite a few of them last week). If you don’t have it already, there is an awesome extension for Google Reader (Google Reader Plus for Google Chrome or Google Reader Filter for Firefox’s GreaseMonkey) that will allow you to filter your feeds via Regular Expressions. You can list RegEx patterns that you like and RegEx patterns that you don’t like. The one you like will be highlighted in yellow and the ones you don’t like will be grayed out. You can also set some other options like remove duplicates!

3. What tools do you use to distribute your Tech Tweets?

BigTweetLogo
windows-live-writer
delicious_256x256 hootsuite-icon

I would say that this area is the one that I change most frequently, but as of now I start by using a bookmarklet called BigTweet to capture my Tech Tweets. The bookmarklet overlays an inline modal onto the webpage you are on and captures the title of the page, auto shortens the URL using j.mp (formerly bit.ly), and it even can auto post to delicious if you want. There are many other features as well so I recommend you check it out.

So, instead of posting directly from BigTweet to Twitter, I copy/paste the results into HootSuite where I schedule the tech tweet to send out at a future time. I have used many scheduling Twitter clients in the past such as Twuffer, TwitterMatic!, FutureTweets, TwtMstr, Social Oomph (formerly known as Tweet Later), but I’ve found that HootSuite has given me the nicest UI, the richest features, with consistent results. And now recently they have released an iPhone version that uses the same settings you have in the browser version! The one thing that I resist from HootSuite is their URL shortener. I used it for a little while, but soon found out that people didn’t like the digg like bar at the top of each tech tweet I sent out ;)

After the tech tweets have gone out for the day, I use Window Live Writer (WLW) to post a daily Tech Tweet round-up. I wrote a plug-in for WLW to gather my Tweets from today, group them into categories, parse them with a Regular Expression, expand the URLs, submit the Tech Tweets to my delicious account for future searching, and then generate the HTML for the Tech Tweet blog post.

Conclusion

You might have noticed that I have slightly changed my approval process over the last week or two. I am trying to refine my process to keep the highest quality links as possible and cut out the noise. I plan to do a separate post on my thoughts about this later.

I hope you have enjoyed the Tech Tweets and I plan to continue to provide helpful, timely, and high quality links on a day to day basis.

If you have any suggestions on how I can better contribute to the community through Tech Tweets please let me know. I value your input!

Thursday, December 17, 2009

Where Did @elijahmanor’s Tech Tweets Go?

TechTweetBird You might be wondering “Where Did @elijahmanor’s Tech Tweets Go?”. I actually wasn’t aware of this issue until I had several people asking where my tech tweets went. It seems that there is an issue with my account on Twitter today starting around 9AM CST.

In order to see my tweets there is a workaround of unfollowing and then refollowing me (@elijahmanor). This seems strange, but it has worked for those that have tried it.

You may have not noticed that this was a problem. If that is the case then maybe you were seeing my tweets as part of a Twitter search (which still works) or maybe I was part of a custom Twitter List that you are watching.

I hope that this is just a temporary glitch in Twitter that will resolve itself soon. I have created a Twitter Ticket explaining the issue just in case.

I will do my regular Tech Tweets blog post round-up as usual. So, if you didn’t see any of my tech tweets you can enjoy them there :)

Update: On my way home today I noticed an update to the Twitter Status Blog stated that

We are aware of and investigating the causes of timeline delays and missing tweets. Retweet is back up and fully functional.

So, I hope that means this will not last for long ;)

Friday, November 20, 2009

Visualize your Twitter Timeline with jQuery and SIMILE

Since my last post I wondering if there was a better way to visualize my tweets. The Word Cloud was a nice feature, but I wanted more. I thought about using the Google Annotated Time Line chart, but it didn’t quite give me what I was looking for. Well, it turns out there is a really cool JavaScript plug-in called Simile Timeline that provides the functionality I was looking for.

So, I threw the following together to display my tweets. After completing it, I realized how much I actually tweet! A lot of exciting stuff was going on after being on vacation, having PDC 2009 going on, and watching the jQuery Summit.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
   <title>Visualize your Twitter Timiline with jQuery and SIMILE</title>
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>  
   <script src="http://simile.mit.edu/timeline/api/timeline-api.js" type="text/javascript"></script>      
   <style type="text/css" media="screen">
   body { background-color: #000; font: 14px Helvetica, Arial; color: #fff; }
   #my-timeline, #source { margin-top: 15px; }
   #criteria, #my-timeline, #source { margin-bottom: 15px; }

   .timeline-band-layer-inner { font-size: 10px; }
   .timeline-event-bubble-title, .timeline-event-bubble-body { color: black; }
   .timeline-event-bubble-time { padding-top: 5px; color: #ccccc; font-size: 9px; }
   </style>   
   <script type="text/javascript">   
   $(function() {
      $("#my-timeline").hide();
      $('#getTwitterTimeline').click(function() {
         getTwitterTimeline($('#userName').val());
      });
   });   
      
   var timeLine;
   function getTwitterTimeline(userName) {
      var eventSource = new Timeline.DefaultEventSource();
      var url = 'http://twitter.com/status/user_timeline/' + userName + '.json?count=200&callback=?';       
      $.getJSON(url, function(data) { 
         $("#my-timeline").fadeIn('slow');
         var mostRecentTweetDate = new Date(1);
         $.each(data, function(i, item) {   
            var dateEvent = Date.parse(item.created_at); 
            mostRecentTweetDate = (dateEvent > mostRecentTweetDate) ? dateEvent : mostRecentTweetDate;
            var html = replaceUrlWithHtmlLinks(item.text);
            var evt = new Timeline.DefaultEventSource.Event(
               new Date(dateEvent), //start
               null, //end
               null, //latestStart
               null, //earliestEnd
               true, //instant
               item.text.substr(0, 47) + '...', //text
               html //description
            );
            eventSource.add(evt);            
         });
         
         var bandInfos = [
            Timeline.createBandInfo({
               trackGap: 0.2,
               width: "80%", 
               intervalUnit: Timeline.DateTime.HOUR, 
               intervalPixels: 500,
               eventSource: eventSource,
               timeZone: new Date().getTimezoneOffset() / 60,
               date: new Date(mostRecentTweetDate).toGMTString()
            }),
            Timeline.createBandInfo({
               showEventText:  false,
               trackHeight: 0.5,
               trackGap: 0.2,
               width: "20%", 
               intervalUnit: Timeline.DateTime.DAY, 
               intervalPixels: 300,
               eventSource: eventSource,
               timeZone: new Date().getTimezoneOffset() / 60,
               date: new Date(mostRecentTweetDate).toGMTString()
            })
         ];
         
         bandInfos[1].syncWith = 0;
         bandInfos[1].highlight = true;
         timeLine = Timeline.create($("#my-timeline")[0], bandInfos);                  
      });
   }

   var resizeTimerID = null;   
   $('body').resize(function() {
      if (resizeTimerID == null) {
         resizeTimerID = window.setTimeout(function() {
            resizeTimerID = null;
            timeLine.layout();
         }, 500);
      }
   });
      
   function replaceUrlWithHtmlLinks(text) {    
      var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;    
      return text.replace(exp,"<a href='$1'>$1</a>"); 
   }   
   </script>
   </head>
   <body>
      <h3>Visualize your Twitter Timeline with jQuery and SIMILE</h3>
      <div id="criteria">
         <span>Twitter Username: </span>
         <input id="userName" type="text" value="elijahmanor" /> 
         <button id="getTwitterTimeline">Twitter Timeline</button>
      </div>
      <div id="my-timeline" style="height: 200px;"></div>
      <a id="source" href="http://jsbin.com/ekimi3/edit" target="_blank">View, Run, & Edit Source Code</a>      
   </body>
</html>

cooltext439924738 cooltext439924698

 

Tuesday, November 17, 2009

Twitter Word Cloud Visualization with Google API

With all the Google Closure news recently, I thought I would play around a little more with what Google has to offer. I’ve been impressed with their charting options that have been available in Google Docs and noticed that they are also available to use outside of Google Docs.

After looking through the Google Visualization API Gadget Gallery I decided upon playing around with the WordCloud chart.

I thought I would use jQuery AJAX to pull the recentl 20 tweets from a user name and then create a Word Cloud using Google’s API.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
   <title>Sandbox</title>      
   <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   <link rel="stylesheet" type="text/css" href="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.css"/>
   <script type='text/javascript' src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
   <script type="text/javascript">
   firebug.env.debug = false;   // open minimized
   firebug.env.detectFirebug = true; // do not initialize if Firebug is active
   </script>   
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
   <script type="text/javascript" src="http://visapi-gadgets.googlecode.com/svn/trunk/wordcloud/wc.js"></script>
   <script type="text/javascript" src="http://www.google.com/jsapi"></script>
   <script type="text/javascript">
   $(function() {
      $('#twitterCloud').click(function() {
         draw($('#userName').val());
      });
   });
   
   google.load("visualization", "1"); 
   function draw(userName) { 
      var url = 'http://twitter.com/status/user_timeline/' + userName + '.json?count=20&callback=?'; 
      $.getJSON(url, function(data) { 
         console.log('data: %o', data);
         var dataTable = new google.visualization.DataTable(); 
         dataTable.addColumn('string', 'Tweet'); 
         dataTable.addRows(20); 
         $.each(data, function(i, item) {   
            console.log('i: ' + i);
            console.log('item.Text: ' + item.text);           
            dataTable.setCell(i, 0, item.text); 
         }); 
         var outputDiv = $('#wordCloud').css({
            'border-width': '1px',
            'border-color': '#cccccc',
            'border-style': 'solid',
            'margin': '10px',
            'padding': '10px'
         }); 
         var wc = new WordCloud(outputDiv.get(0)); 
         wc.draw(dataTable, null); 
      });   
   }
   </script>
</head>
<body>   
   <div>Twitter Username: <input id="userName" type="text" /> <button id="twitterCloud">Twitter Cloud</button></div>
   <div id="wordCloud"></div>
   <a href="http://jsbin.com/alubi/edit" target="_blank">View, Run, & Edit Source Code</a>
</body>
</html>

 

cooltext439925164 cooltext439925034

Saturday, November 14, 2009

DevExpress CodeRush with Refactor Pro Giveaway

DevExpressThis time Devexpress has offered to giveaway 3 separate licenses of their CodeRush with Refactor Pro Visual Studio add-on each with a value of $249.99!

CodeRush with Refactor Pro is a productivity tool that can assist you in your programming efforts. There are many features that can catapult your productivity to the next level. There are more details later in this post covering the detail of this Visual Studio add-on.

Giveaway Rules

The contest will start today, November 5th, 2009, and last 7 days concluding on November 11th, 2009 11:59PM. At that point I will pick the winner and announce the results on the following day.

In order to signup for the giveaway you need to do 4 things…

  1. Follow @elijahmanor on Twitter
  2. Tweet the following…
  3. Add a comment to this blog including your Twitter username
  4. And in honor of our sponsor follow @DevExpress on Twitter and become a fan of DevExpress on Facebook

At the end of the contest I will pick a random comment from this blog entry and then make sure the comment author also completed the other 3 steps. At that point I will Direct Message the winner (which is why you need to follow @elijahmanor) with further instructions to receive the CodeRush with Refactor Pro license.

Note: You can add multiple comments to this blog post, but only one per day per person. This increases you chances of winning. So please, come by once a day during the contest and leave a comment below.

Learn More About CodeRush with Refactor Pro

1. The online screencasts will teach you quickly how to get started with CodeRush

2. Download the fully-functioning trial and test drive in your Visual Studio

3. Check out their blogs, they've got some great content up there

4. DevExpress has a big developer fan base and their Facebook Page shows this enthusiasm and excitement. Become a fan by going to this page

You can also check out a great blog post by Rory Becker (@RoryBecker) explaining the top features that he likes about CodeRush with Refactor Pro.

Winners Announced…

Congratulations to Al Gonzalez (@algonzalex), Simon Green (@lumbarius), and John Nystrom (@johnnystrom) for winning the CodeRush with Refactor Pro Giveaways. Someone from DevExpress will be contacting you shortly with instructions.

Thanks to everyone for participating. I have other prizes to giveaway in the near future. So stayed tuned ;)

Wednesday, November 11, 2009

AJAXified jQuery Flip Plugin

I was talking to a friend a couple of weeks ago and he was looking for some plugin that would visually flip over a section of the screen (like flipping an index card). He had a master/detail layout and wanted to be able to click on a link from the master, the content would flip, and then the detail content would be displayed on the flipped side.

I recommended the Flip! jQuery Plugin since it was the closet thing I was aware that would do this effect without WPF, Flash, or Silverlight. Since the plugin supports several custom events (onBefore, onAnimation, onEnd) I figured that on the onBefore event an AJAX call could be initiated and the callback content can be inserted onto the reverse side of the master.

Here is a sample application that I put together last night. The app requests your twitter username, flips, retrieves the latest tweet using JSONP from Twitter for that username, and then displays it on the flip side.

AJAXified jQuery Flip! Plugin

I have hosted it on JsBin so that you can view the code, run the code, and edit the code to your heart’s content ;) I have also listed the code here below.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head> 
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<script src="http://lab.smashup.it/flip/js/jquery-ui-1.7.2.custom.min.js"></script> 
<script src="http://lab.smashup.it/flip/js/jquery.flip.min.js"></script> 
<script type='text/javascript' src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script> 
<script type="text/javascript"> 
firebug.env.debug = false;   // open minimized 
firebug.env.detectFirebug = true; // do not initialize if Firebug is active 
</script> 
<title>AJAXified jQuery Flip! Plugin</title> 
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 
<style type="text/css" media="screen"> 
.flipBox { 
  width: 500px; 
  height: 200px; 
  background-color: #F6EECA; 
  font-family: Helvetica; 
  color: #000000; 
  text-align: left; 
  padding: 15px; 
}  
</style> 
<script type="text/javascript"> 
$(function() { 
   $('#flip').live('click', function() { 
      console.log('flip click'); 
      $("#front").flip({ 
         direction: 'tb', 
         content: $('#back'), 
         color: '#C8E3DC', 
         onBefore: function(){ 
            console.log('before starting the animation'); 
            var twitterUsername = $('#twitterUsername').val(); 
            var url = 'http://twitter.com/status/user_timeline/' + twitterUsername + '.json?count=1&callback=?'; 
            $.getJSON(url, function(data) { 
               console.log('data: %o', data); 
               var twitterList = '<ul>'; 
               $.each(data, function(i, item) { 
                  console.log(item.text); 
                  twitterList += '<li>' + item.text + '</li>'; 
               }); 
               twitterList += '</ul>'; 
               $('#backAjax').html(twitterList); 
               $('#backTitle').text("Here is " + twitterUsername + "'s Lastest Tweet..."); 
            });             
         }, 
         onAnimation: function(){ 
            console.log('in the middle of the animation'); 
         }, 
         onEnd: function(){ 
            console.log('when the animation has already ended'); 
            $('.revert').live('click', function() { 
              $('#front').revertFlip(); 
            });             
         } 
      }); 
   }); 
}); 
</script> 
</head> 
<body> 
   <div id="front" class="flipBox"> 
      <span id="frontStatic">Enter Twitter Username</span> 
      <input id='twitterUsername' type='text'/> 
      <button id="flip">Submit</button> 
   </div> 
   <div id="back" class="flipBox" style="display: none"> 
      <span id="backTitle">Here is Your Latest Tweet...</span> 
      <span id="backAjax">Back AJAX</span> 
      <button class="revert">Return</button> 
   </div> 
   <a href="http://jsbin.com/ifoga/edit" target="_blank">View Source Code &amp; Edit</a> 
</body> 
</html>

I hope you found this plugin interesting. I had a fun time putting it together ;)

 cooltext439925164 cooltext439925034

Wednesday, November 04, 2009

Whiskerino 2009: A Beard Growing Contest

WhiskerinoLogo
For those of you who don’t know I recently started a beard growing contest called Whiskerino!
Whiskerino is a 4 month beard growing contest starting November 1st, 2009 and proceeding through Feburary 28th, 2010.
The basic idea behind Whiskerino is…
Shave completely clean, post images regularly, interact, participate in themes, be nice. Grow a massive beard.
So, if you want to know where I am in my beard growing process, feel free to visit my Whiskerino Profile Page. You can also subscribe to my RSS Feed to make sure you don’t miss a thing ;)
2009-11-01-T
You might have noticed that I’ve been updating my Twitter Profile image frequently (like the one of the left). That is because when I upload a new Whiskerino picture I’m also updating my Twitter Profile as well. In addition, I will also be tweeting when I have updated my Whiskerino profile ;)
Several of my friends have joined me during this manly adventure. The following men are from Nashville, TN:
Note: I will be shaving my neck ;) I refuse to grow a Neck Beard… yuck!

Tuesday, November 03, 2009

jQuery Enlightenment eBook Review

Introduction

I just finished reading the jQuery Enlightenment eBook by Cody Lindley (@codylindley) and let me tell you it was definitely worth my time ;)

You may be already familiar with Cody Lindley as the author of the modal jQuery plug-in Thickbox.

As stated by the author, this eBook is intended for 3 types of people

  1. A beginner jQuery developer looking to learn more
  2. Someone that already knows another JavaScript library
  3. Someone looking for an awesome set of reference material for jQuery

Review

The contents of this eBook range from basic to complex themes such as core library features, selectors, traversing, manipulation, forms, events, performance, animation, ajax, etc…

One of the great things about this eBook is that each section self-contained and could be understood apart from the other sections. So you could conceivably skip around in the book and still understand what is necessary fore that section.

The feature that I was most impressed upon was the JsBin integration with all of the 100+ code samples. JsBin is a service that allows you to share, execute, and modify code snippets to aid in the learning process. For example, you can take of the code snippets (example code snippet) from the jQuery Enlightenment eBook and click the Output tab for the results of the jQuery. Then you can double-click the HTML to experiment with your own examples.

A feature that you should definitely not skip over is the notes portion of each section. On numerous occasions I found very useful tips and insights clues into the jQuery framework.

Note: I found some minor typos and code snippets issues during my detailed reading of the eBook. You can review my comments and issues in a Google Document I put together…

Summary

I highly recommend this eBook to anyone hoping to not only understand how to write jQuery, but also to understand the why behind the how. If you have any JavaScript experience at all and would like to bring your jQuery game to the next level… then, this eBook is for you!

The eBook is very affordable coming in at only $15. You can also purchased printed version from lulu.com for $30 (black & white) or $45 (color). If the price is a factor, might I suggest you asking your work to buy it on your behalf ;)

Ohh, and 10% of the price goes back to the jQuery project… so you’ll be supporting open source software too ;)

Other jQuery Enlightenment Reviews

Thursday, October 29, 2009

New Official jQuery Podcast Announced

jquerypodcast In case you  hadn’t heard yet, the Official jQuery Podcast (@jQueryPodcast) has officially been announced.

It was first announced at the StackOverflow DevDays event in Toronto, ON, Canada on Friday Oct 23rd, 2009 and then it was tweeted yesterday by the @jQueryPodcast account and retweeted by myself and others.

Ralph Whitbeck (@redwolves), member of the jQuery Evangelism Team, and I (@elijahmanor) will be hosting a weekly jQuery podcast starting in mid-November.

Our first guest will be non-other than Mr. jQuery himself, John Resig (@jeresig).

The format of the show will loosely be interviewing a jQuery related guest and then jumping into a review of jQuery happenings from the previous week.

We already have a great line-up of guests scheduled. I hope you are as excited as I am about this new opportunity.

So, keep your eyes out for the 1st podcast coming to you mid-November ;)

You can follow @jQueryPodcast for up-to-date news and information.

Wednesday, October 14, 2009

qTip Tooltip with jQuery UI ThemeRoller Support

Recently as I develop with jQuery, I’ve been trying to either use jQuery UI ThemeRoller supported plugins or somehow tweak existing jQuery plugins to support the ThemeRoller classes.

Note: There are many plugins out there that already support ThemeRoller (and you can find a list I’ve compiled in my previous Quickly Testing Various jQuery UI Themes on Your Website post).

Out of all the jQuery tooltip plugins I’ve seen, I prefer the qTip implementation. The tooltips look good and it is easy to use. There are several themes that are supported out of the box and you can also tweak the styles if you don’t like the baked in ones.

$('a[title]').qtip({ 
   position: { 
      corner: { 
         target: 'rightTop', 
         tooltip: 'leftBottom' 
      } 
   }, 
   style: { 
      name: 'cream', 
      tip: true 
   } 
});

That is all well and good, but what I really wanted was to control the theme a little more. The documentation on the website got me a little further. You can tweak out the style settings and instead of using one of the default themes you can specify the border and color values manually.

$('a[title]').qtip({ 
   position: { 
      corner: { 
         target: 'rightTop', 
         tooltip: 'leftBottom' 
      } 
   }, 
   style: { 
      border: { 
         width: 5, 
         radius: 10, 
         color: '#017DC3' 
      }, 
      background: '#ffffff', 
      color: '#000000', 
      padding: 10, 
      textAlign: 'left', 
      tip: true 
   } 
});

Well, that almost gets me to where I wanted to be. Instead of defining the styles, I wanted qTip to use the ThemeRoller classes so when/if I changed my jQuery UI theme all the styles would be applied auto-magically.

So, I thought about submitting a new feature request, but before I did I noticed there was already a feature request listed for for ThemeRoller Support. That is exactly what I was looking for! Then I noticed that it was already developed. It was then that I ran across a forum entry authored by David (dfeeney) showing how to use the ThemeRoller classes with qTip.

$.fn.qtip.styles.themeroller = { 
   background: null, 
   color: null, 
   tip: { 
      corner: true, 
      background: null 
   }, 
   border: { 
      width: 5, 
      radius: 3 
   }, 
   title: { 
      'background': null, 
      'fontWeight': null 
   }, 
   classes: { 
      tooltip: 'ui-widget', 
      tip: 'ui-widget', 
      title: 'ui-widget-header', 
      content: 'ui-widget-content' 
   } 
}; 

$('a[title]').qtip({ 
   position: { 
      corner: { 
         target: 'rightTop', 
         tooltip: 'leftBottom' 
      } 
   }, 
   style: { 
      name: 'themeroller', 
      tip: true 
   } 
});

There is a concept of creating your own theme (or in qTip’s nomenclature that is ‘style’) and this is documented well in their online help. The above code create a new theme and uses the ThemeRoller classes to define the tooltip, tip, title, and content section of the qTip tooltip!

I imagine at some point the classes attribute will be highlighted on the online help, but as for now the only place I saw it used on in the forums or if you dig through the source code. Anyway, that is how you get the qTip to use the ThemeRoller.

Download Example Code

Demonstrate Example Code

Friday, October 09, 2009

ASP.NET MVC Cheat Sheets

Most of you have seen many jQuery Cheat Sheets out in the wild, but as of recently there are now also many ASP.NET MVC Cheat Sheets to chose from.

If you know of any other ASP.NET MVC Cheat Sheets, please let me know and I’ll add it to the above list. I hope these prove to be helpful for you. You might consider printing them out and posting them on your cubical walls ;)

Note: Instead of hosting the PDF’s on my server, I am pointing to the source website for you to download the Cheat Sheets from there.

Getting Started with ASP.NET MVC 1.0


DZone

You'll learn how to setup your environment and how to create a web application. Then, you'll get to go deeper into detail and learn about components of the framework along with the structure of the main API.

ASP.NET MVC: The Request-Handling Pipeline


RequestHandling

Illustrates which parts of the ASP.NET MVC Framework get called when a request is made. Check out the purpose and features of routing, controllers, actions, and views.

ASP.NET MVC: View Cheat Sheet


ViewCheatSheet
The View Cheat Sheets focuses on the HTML Helpers, URL Helpers and so on that you would use within your views.

ASP.NET MVC: Controller Cheat Sheet


Controllers

The Controller Cheat Sheet focuses on what you return from your controller and how to use them and it also includes a lot of information on the MVC specific attributes.

ASP.NET MVC: Framework Cheat Sheet

Framework

Framework Cheat Sheet focuses on the rest of MVC like routing, folder structure, execution pipeline etc.

ASP.NET MVC: Proven Practices Cheat Sheet

ProvenPractices

Proven Practices Cheat Sheet contains ten KEY learnings that every ASP.NET MVC developer should know - it also includes links to the experts in this field where you can get a ton more information on those key learning's. 

ASP.NET MVC 101 Sheet

aspnetmvcCheatSheet

This sheet contains some snippets and information about ASP.NET MVC 1.0, C├ęsar Intriago compiled most of this information from the ASP.NET MVC official site and from the free chapter of ASP.NET MVC 1.0 eBook:

Thursday, October 08, 2009

Using MvcContrib ScriptInclude, Stylesheet, And T4MVC

I am always looking for more ways I can integrate features of MVC Contrib into my ASP.NET MVC projects. I also have started using David Ebbo’s T4MVC Template that generates strongly typed helpers for ASP.NET MVC (download).

Before I integrated these tools my script and style includes looked like…

<script src="../../Content/Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="../../Content/Scripts/jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>

<link href="../../Content/Styles/Site.css" rel="stylesheet" type="text/css" />
<link href="../../Content/Styles/start/jquery-ui-1.7.2.custom.css" rel="stylesheet" type="text/css" />

I remembered hearing about ScriptInclude and StyleInclude Html Helpers in the MVC Contrib so I updated the above references to the following…

<%= Html.ScriptInclude("~/Content/Scripts/jquery-1.3.2.min.js")%>
<%= Html.ScriptInclude("~/Content/Scripts/jquery-ui-1.7.2.custom.min.js")%>
    
<%= Html.Stylesheet("~/Content/Styles/Site.css")%>
<%= Html.Stylesheet("~/Content/Styles/start/jquery-ui-1.7.2.custom.css")%>

I was please about using the MVC Contrib Helpers, but I wasn’t thrilled with having hard-coded strings laying around which is where the T4MVC Template comes into play.

There are many features of the T4MVC Template (many more than I planned on covering today), but one of them is interrogating your project structure and generating static classes with read-only references to your Scripts, Styles, and Images.

So, after running the T4MVC Template, I updated my references to the following…

<%= Html.ScriptInclude(Links.Content.Scripts.jquery_1_3_2_min_js)%>
<%= Html.ScriptInclude(Links.Content.Scripts.jquery_ui_1_7_2_custom_min_js)%>
    
<%= Html.Stylesheet(Links.Content.Styles.Site_css)%>
<%= Html.Stylesheet(Links.Content.Styles.start.jquery_ui_1_7_2_custom_css)%>

Looks pretty good, doesn't it? Well, there is only one problem… it doesn’t work! Why? Well, the output of the T4MVC Links are relative paths that have been resolved (meaning they no longer have the “~”). The MVC Contrib Helpers assume that if the URL passed it it doesn’t have the “~”, then it will prepend either “~/Scripts/” for scripts or “~/content/css/'” for styles.

Seeing that I have moved my scripts, styles, and images under the “~/Content” folder, there are a couple of changes to the MVC Contrib Html Helpers that could make this work…

    1. Provide some sort of mechanism to define the paths prepended to the Scripts and Styles if there is no “~”
    2. Override the Html Helpers with another option to not prepend any path information
    3. Possibly search for the “/” instead of the “~” when determining if a path should be prepended to the URL
    Can you think of any other solutions to get these to play well together?

Monday, October 05, 2009

SubMain CodeIt.Right Giveaway

submain-logo-250x76 Well, its time for another great giveaway. This time SubMain has offered to giveaway 2 of their CodeIt.Right Enterprise Edition licenses that are valued at $600.00 each!

For those of you don’t know, CodeIt.Right is a Visual Studio plugin that assists in their development process. Here are some of the features that it offers…

  • Automatic Code Refactoring
  • Team Features
  • Code Metrics
  • Reporting
  • Microsoft Guidelines and Best Practices
  • Follow Your Own Standards
  • Automate Code Reviews
  • Continuous Integration
  • And Many More…

CodeIt.Right's biggest benefit is the automatic code refactoring
-- Scott Mitchell, MSDN Magazine Toobox

Giveaway Rules

CodeIt.Right-Logo_250x57The contest will start today, October 5th, 2009, and last 7 days concluding on October 11th, 2009 11:59PM CST. At that point I will pick the winner and announce the results on the following day.

In order to signup for the giveaway you need to do 3 things…

  1. Follow @elijahmanor on Twitter (if you haven’t already)
  2. Tweet the following…
  3. Add a comment to this blog including your Twitter username.

Note: To increase your chances of winning you can add one comment to this blog each day of the contest.

At the end of the contest I will pick a 2 random comments from this blog entry and then make sure the comment authors tweeted the above RT. At that point I will Direct Message the winners (which is why you need to follow @elijahmanor) with further instructions to receive the CodeIt.Right license.

More About the SubMain CodeIt.Right

Want to learn more about the awesome prize? I highly recommend you check out the following:

1. Visit CodeIt.Right product page to learn about the product you might win.

2. Download the full-featured trial and see how it can help you be a better developer, find some interesting, and real, code problems right away!

Winners Announced…

Congratulations to Sal DiStefano and Mark A. Wilson for winning the SubMain CodeIt.Right Giveaway. Someone from SubMain will be contacting you shortly with instructions.

Thanks to everyone for participating. It looks as if I will be getting some other prizes to giveaway in the near future. So stayed tuned ;)

Thursday, October 01, 2009

I’ve Been MVP’ed

MVP_08Banner_EN

As I woke up this morning I checked my Twitter feed on my iPhone and saw the following tweet…

RT @Zannabanana: Welcome back MVPs! @robzelt @plitwin @DanWahlin @anthony808 @chadcampbell & Welcome new MVPs @SaraJChipps and @elijahmanor

Wow, what a way to wake up in the morning! As you might imagine, I’ve been beaming inside ever since ;) What an honor to be accepted into the Microsoft Most Valuable Professional (MVP) Award!

Shortly later  that morning I received the official email welcoming me to the program…

Congratulations, you are one of only a few thousand people around the world who have been recognized with a Microsoft MVP Award.

I want to thank everyone who has supported & encouraged me… and of course all the tweet love you’ve shown :)

aspnetinsidersEarlier this year I was also accepted into the ASPInsiders program which has enabled me to converse with the developers of ASP.NET MVC, provide feedback, and play with the newest bits of software before they are released.

I look forward to growing more as a developer and will attempt to continue and provide helpful and timely resources, tips, and tricks for web developers (ASP.NET, ASP.NET MVC, jQuery, HTML, CSS, etc…)

twitter8 As I’m sure you know I am quite active on Twitter and provide daily tech tweets that are also posted on my blog in a daily tech tweet roundup and also archived to delicious.

Thanks for all the tweetulations today by the following band of twitter folk…

@Zannabanana @AndyLeonard @johnnystock @lazycoder @mjlefevre @SaraJChipps @johnnystock @rob_james @D_Guidi @mstum @TheCodeJunkie @Frozzare @unclebiguns @DeveloperInfra @SteveAndrews @foreachdev @ChrisLove @arcanecode @AlanBarber @wendy_dance @DavidGiard @wbm @julielermanvt @alvinashcraft @RachelAppel @ddurose @sergeb @jgaylord @kyleNash @SuprotimAgarwal @wpstudios @JeremySkinner @JMBucknall @EduBergantini @GavinOsborn @maartenballiauw @MrTyzik @PrintsCharming @JRGarcia @Raycast @omarq @omarq @ronnycarreras @jglozano @christianaspnet @KathleenOrland @sergeb @donniefitz2 @tommynorman @geekedout @thegeekyouneed @tasid @shuraCL @karlprosser @davepurdon @taurafigueiredo @DouglasAguiar @novogeek @vimpyboy @dmohl @A_Robson @jcoehoorn @ifandelse @schmehi @vitaminjeff @jthomp @ehexter @snahider @ssathya @DeanWeber @navin_l @tobint @rrubin @toncijukic @darthobiwan @_Neville @Raycast @stimms @funcakes @neilcamm @D_Guidi @ivaylovasilev @eddiespooner @jbasilio @tekchic @stevenabanks @JavaScript1x @CoderDennis @kirstinj

Tuesday, September 29, 2009

Increase Your Website Performance by Hosting jQuery with a CDN

In the following screencast I will demonstrate how to speed up your website by using a Content Delivery Network (CDN). Specifically, I will be swamping out a local copy of jQuery with one hosted by Google. You can host a variety of files (example: jQuery, jQuery UI, Prototype, script.aculo.us, MooTools, Dojo, SWFObject, YUI, etc...) with a CDN as well, but the following screencast only shows jQuery being hosted.

First of all, you might be wondering "What is a CDN and why do I need to use one?". If so, you are in luck because Encosia wrote a great blog post concerning this question and here is what he came up with. A CDN provides...

  1. Decreased Latency
  2. Increased Parallelism
  3. Better Caching

For a detailed explanation of the above 3 concept please read his detailed blog post. Now without further ado, here is the screencast.

In the above screencast, I showed how you can replace your local reference of jQuery (see line 4 below) with a version of jQuery that is hosted on a CDN (such as line 5 from Google or line 6 from Microsoft).

<head id="Head1" runat="server">
    <title>Test Page</title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
    <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function() {
            console.log('jQuery has been loaded & document is ready!');
        });
    </script>
</head>

It is worth to not that even after updating your update to use Google or Microsoft as your CDN, YSlow will still not recognize those files as being hosted on a CDN. YSlow only recognizes itself, Yahoo, as a known CDN. The good news is that you can register other CDNs (such as Google &| Microsoft) deep inside of Firefox's configuration. In order to update this setting you can follow these instructions…

  1. Type in 'about:config' into the Firefox's navigation TextBox
  2. Filter for the 'extensions.yslow.cdnHostnames' Preference Name
  3. Double-Click & enter 'ajax.googleapis.com,ajax.microsoft.com' into the dialog box
  4. Restart Firefox and re-run YSlow
    As I mentioned above, there are many files on CDNs that are available for you to reference in your project. The two CDNs that I highlighted in the above screencast are…

Quickly Testing Various jQuery UI Themes on Your Website

The following short screencast shows how you can use the jQuery UI ThemeRoller Firefox Bookmarklet to quickly switch the theme on your webpage in order to compare and tweak out the colors that is just right for your website.

 

Not only do the jQuery UI Plugins support the jQuery UI Themes, but there are several other jQuery Plugins that also utilize the themes as well such as

    If I am missing some others, please leave a comment and I will add it to the above list.

Tuesday, September 22, 2009

Jumpstarting Your Next jQuery Plugin with an Online Tool

The following screencast focuses on how to quickly make a jQuery plugin. The intent is not to dig deep into the ins and outs of a jQuery Plugin’s wiring. If that is what you are looking for there are many other good tutorials out there for that such as…

This screencast’s focus is to build off of your current knowledge of how to build a jQuery Plugin (although it doesn’t have to be too deep), and allow you to quickly focus on the building your plugin, rather than worrying about how all the little pieces are wired together.

The tool we will be using is called Starter: jumptstart Your jQuery Plugins and you just provide the new jQuery Plugin name, optional namespace, parameters, options, etc… and then you are on your way focusing on the guts of your Plugin.

 

Update: This screencast has been posted on Nettuts+ for voting. If you like it, then please consider voting for the 3rd entry on the Nettuts+ blog post…

The plugin that we will be creating is an ImageTextOverlay that will allow you to provide a list of message and overlay them over a message. The message will fade in and out in succession and you will be able to change the properties of each message (such as it’s location, size, color, etc…). I was inspired to write this small plugin after hearing someone on Twitter wanting something similar to this.

Sometimes it is easiest if we look at how we want to use our Plugin before actually creating it. So, here is a simple page that is selecting an image and calling our imageTextOverlay plugin. You can see how there is a default top & left positions provided and then a list of messages. Each message only needs to have a text property provided, but you can also provide many other properties to override the default values.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    <script src="jquery.imagetextoverlay.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function() {
            $('#ctlImage').imageTextOverlay({
                top: "10px",
                left: "10px",
                messages: [{
                        text: "Message 1"
                    }, {
                        text: "Message 2",
                        top: "50px",
                        left: "50px",
                        fontSize: "22px"
                    }, {
                        text: "Message 3",
                        top: "100px",
                        left: "100px",
                        color: "black",
                        fontSize: "48px",
                        backgroundColor: "#CCCCCC"
                    }, {
                        text: "Message 4",
                        top: "200px",
                        left: "200px",
                        letterSpacing: "-1px",
                        color: "red",
                        fontSize: "24px",
                        backgroundColor: "white"
                    }
                ]
            });
        });    
    </script>
</head>
<body>
    <img id="ctlImage" src="curtains.jpg" />
</body>
</html>

The next step is to starting entering our plugin Class Name and Default Options into the Starter: jumptstart Your jQuery Plugins online tool. Then we just click the Create button to prototype out our plugin! We can either copy/paste the results into our own file or there is even a Download button so you don’t have to copy/paste :)

StarterInput

Now we can focus on writing the core logic of our jQuery plugin and not have to worry about all the nuts and bolts of how a plugin should be structured. So, here is what I put together for the ImageTextOverlay plugin. I will highlight only the lines of code that I actually wrote… everything else was generated by the online tool!

(function($){
    
    $.ImageTextOverlay = function(el, options){
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;
        
        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el; 
        
        // Add a reverse reference to the DOM object
        base.$el.data("ImageTextOverlay", base);
        
        base.init = function(){
            
            base.options = $.extend({},$.ImageTextOverlay.defaultOptions, options);
            
            // Put your initialization code here
            base.createAndUpdateImageText(base.$el, base.options);
        }
        
        // Sample Function, Uncomment to use
        // base.functionName = function(paramaters){
        //     
        // }

        base.createAndUpdateImageText = function($ctlImage, options) {
            var $ctlText = base.createImageText();
            base.updateImageText($ctlImage, $ctlText, options, function() {
               base.createAndUpdateImageText($ctlImage, options);
            });
        }        
        
        base.createImageText = function() {
            var $imageText = $('#ctlImageText');

            if ($imageText.length == 0) {
                $('<div id="ctlImageText" />')
                    .css({
                        position: "absolute"
                    })
                    .appendTo('body')
                    .hide();
                $imageText = $('#ctlImageText');
            }

            return $imageText;
        }    

        base.messageIndex = 0;
        base.updateImageText = function($ctlImage, $ctlText, options, onComplete) {
            var message = options.messages[base.messageIndex++ % options.messages.length];
            var messageOptions = $.extend({}, options, message);
            $ctlText.html(message.text).css({
                fontSize: messageOptions.fontSize
            });
            
            $ctlText.css({
                top: messageOptions.top,
                left: messageOptions.left,
                color: messageOptions.color,
                letterSpacing: messageOptions.letterSpacing,
                backgroundColor: messageOptions.backgroundColor,
            }).fadeIn('slow').animate({ opacity: 1.0 }, 3000).fadeOut('slow', function() {
                onComplete();
            });
        }
        
        base.init();
    }
    
    $.ImageTextOverlay.defaultOptions = {
        fontSize: "24px",
        letterSpacing: "normal",
        color: "white",
        backgroundColor: "transparent"
    }

    $.fn.imageTextOverlay = function(options){
        return this.each(function(){
            (new $.ImageTextOverlay(this, options));
        });
    }

    // This function breaks the chain, but returns
    // the ImageTextOverlay if it has been attached to the object.
    $.fn.getImageTextOverlay = function(){
        return this.data("ImageTextOverlay");
    }
    
})(jQuery);

As I mentioned above, I only wrote the lines that are highlighted. The rest of the plugin was written by the Starter: jumptstart Your jQuery Plugins online tool!

If you are interested in other screencasts, I have made several others that you may be interested in as well…