This is featured post 1 title
Replace these every slider sentences with your featured post descriptions.Go to Blogger edit html and find these sentences.Now replace these with your own descriptions.This theme is Bloggerized by Lasantha - Premiumbloggertemplates.com.
This is featured post 2 title
Replace these every slider sentences with your featured post descriptions.Go to Blogger edit html and find these sentences.Now replace these with your own descriptions.This theme is Bloggerized by Lasantha - Premiumbloggertemplates.com.
This is featured post 3 title
Replace these every slider sentences with your featured post descriptions.Go to Blogger edit html and find these sentences.Now replace these with your own descriptions.This theme is Bloggerized by Lasantha - Premiumbloggertemplates.com.
Wednesday, October 5, 2011
Wednesday, September 21, 2011
Adding Syntax Highlighting to Blogger
(Note: This article is somewhat dated because SyntaxHighlighter 2.0
was released in February 2009. However, this article is still valid
for those who prefer the older 1.5.x version or who don't want to
upgrade)
As we all know, any self-respecting blogger needs some kind of syntax-highlighting plug-in before posting source code on a blog. I've been amiss in this regard, but decided it was high time to correct this particular deficiency.
From doing a little web searching, it looks like the favorite choice is a Java script tool called syntaxhighlighter. As of this writing, syntaxhighlighter hasn't been updated since version 1.5.1 was release in August 2007. It's been surprisingly robust all this time, except that it appears to have some trouble with scrollbars in the more recent Firefox versions, and Safari can be pegged at 100% CPU utilization. Also, the documentation is a little sparse.
That said, here are the steps I followed to make syntax highlighting work with Blogger (the host for this blog) using the syntaxhighlighter suite of javascript and css code.
In the blogger back end (reachable by logging into your blog and clicking "New Post" or "Customize", or other methods), click the"Layout" tab, then the "Edit HTML" sub-tab. Within the textbox within the "Edit Template" section, do the following:
1. Go to http://syntaxhighlighter.googlecode.com/svn/trunk/Styles/SyntaxHighlighter.css, then perform a "select all" and "copy". The css information is now in the clipboard.
2. Paste the css information at the end of the css section of your blogger html template (i.e., after
3. [Updated March 25, 2009 to include closing script tags] Before the
Feel free to remove lines for languages you'll never use (for example, Delphi) -- it will save some loading time.
4. [Updated to add final /script] Before the
5. Use the "Preview" button to make sure your website is correct, then click "Save Template".
6. When composing a blog entry that contains source code, click the "Edit Html" tab and put your source code (with html-escaped characters) between these tags:
Substitute "cpp" with whatever language you're using (full list). (Choices: cpp, c, c++, c#, c-sharp, csharp, css, delphi, pascal, java, js, jscript, javascript, php, py, python, rb, ruby, rails, ror, sql, vb, vb.net, xml, html, xhtml, xslt)
For performing the HTML escaping, you can get a good list of tools by searching for 'html esaper' or a similar term. Here's the one I used while writing this post.
Let me know how it works!
As we all know, any self-respecting blogger needs some kind of syntax-highlighting plug-in before posting source code on a blog. I've been amiss in this regard, but decided it was high time to correct this particular deficiency.
From doing a little web searching, it looks like the favorite choice is a Java script tool called syntaxhighlighter. As of this writing, syntaxhighlighter hasn't been updated since version 1.5.1 was release in August 2007. It's been surprisingly robust all this time, except that it appears to have some trouble with scrollbars in the more recent Firefox versions, and Safari can be pegged at 100% CPU utilization. Also, the documentation is a little sparse.
That said, here are the steps I followed to make syntax highlighting work with Blogger (the host for this blog) using the syntaxhighlighter suite of javascript and css code.
In the blogger back end (reachable by logging into your blog and clicking "New Post" or "Customize", or other methods), click the"Layout" tab, then the "Edit HTML" sub-tab. Within the textbox within the "Edit Template" section, do the following:
1. Go to http://syntaxhighlighter.googlecode.com/svn/trunk/Styles/SyntaxHighlighter.css, then perform a "select all" and "copy". The css information is now in the clipboard.
2. Paste the css information at the end of the css section of your blogger html template (i.e., after
<b:skin><!--[CDATA[/* and before ]]--></b:skin>).3. [Updated March 25, 2009 to include closing script tags] Before the
</head> tag, paste the following:- <!-- Add-in CSS for syntax highlighting -->
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shCore.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCpp.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCSharp.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCss.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushDelphi.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJava.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJScript.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPhp.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPython.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushRuby.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushSql.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushVb.js' type='text/javascript'></script>
- <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushXml.js' type='text/javascript'></script>
4. [Updated to add final /script] Before the
</body> tag, insert the following:- <!-- Add-in Script for syntax highlighting -->
- <script language='javascript'>
- dp.SyntaxHighlighter.BloggerMode();
- dp.SyntaxHighlighter.HighlightAll('code');
- </script>
5. Use the "Preview" button to make sure your website is correct, then click "Save Template".
6. When composing a blog entry that contains source code, click the "Edit Html" tab and put your source code (with html-escaped characters) between these tags:
- <pre name="code" class="cpp">
- ...Your html-escaped code goes here...
- </pre>
Substitute "cpp" with whatever language you're using (full list). (Choices: cpp, c, c++, c#, c-sharp, csharp, css, delphi, pascal, java, js, jscript, javascript, php, py, python, rb, ruby, rails, ror, sql, vb, vb.net, xml, html, xhtml, xslt)
For performing the HTML escaping, you can get a good list of tools by searching for 'html esaper' or a similar term. Here's the one I used while writing this post.
Let me know how it works!
Jquery plugin IBM
Introduction
In a previous article in this series, Working with jQuery, Part 2: Intermediate JQuery: The UI project, I discussed using plug-ins in your own jQuery code to increase the effectiveness of your Web applications. However, these plug-ins don't write themselves. They are written and tested by developers like you and me, donating their free time to the jQuery community to make it better. And we do this all for free, living only for the love of our own code. This article focuses on how you can give something back to this great community, by writing your own plug-in and checking it into the plug-in pages hosted by jQuery. This lets everyone use the plug-in you create, bettering the entire jQuery development community. Consider this my charity work for the year.
While writing the plug-in for this article, I found that the plug-in creation, and the framework for creating it, is extremely straightforward and easy. The hard work is actually thinking of something that hasn't already been done by someone else, and writing the "grunt work" JavaScript code that actually does things. Because of the straightforward plug-in structure, which is easy for beginners and flexible for advanced coders, the number of plug-ins has grown rapidly.
Of course, in doing the research for this article, I also found that every author has their own style for writing a plug-in and that jQuery allows several different styles for writing them. I will concentrate on the easiest one here, and the one recommended by jQuery itself, but will point out any differences or options as they pop up.
Describing your plug-in
Step 1 in creating a plug-in is, of course, thinking of a good idea. Chances are, like most good ideas, someone else has already beaten you to it. For the plug-in I'll be developing here, it's not a novel concept, but at the time of this article I couldn't find it anywhere in the jQuery plug-in community. I know I would personally get a lot of use out of it.
My plug-in is a NumberFormatter plug-in. Number formatting is likely familiar to anyone who's worked with server-side code like Java™ or PHP and internationalization. It's common knowledge that not everyone in the world formats their numbers in the same way. For example, not everyone uses miles for distance. A number that we would write in the U.S. as "1,250,500.75" (I just grabbed this number from my tax form), would be written differently in different countries: "1.250.500,75" in Germany, "1 250 500,75" in France, "1'250'500.75" in Switzerland, and "125,0500.75" in Japan. The number is exactly the same, but it's just written using a different format when presented to users of the Web application.
So, the question emerges, when you're writing an international application, how would you present these numbers to people in different countries? The solution, of course, is to use server-side formatting, which is pretty common. Java has a robust formatting library to make formatting numbers easy. When the page is set up on the server with numbers, the server can take care of formatting these numbers. However, many times you might not be on the server, so you need a way to format numbers on the client, without ever talking to the server.
Here's a typical use case for what I'm describing. You have an input field in your Web application that asks a person for their salary. In the U.S., the user can type in varied forms of input - "$65000", "65,000", "65000", "65,000.00". All these numbers are exactly the same, but you want to control how these numbers look on the screen, in order to create a better user experience. You could call the server after the number is entered, but this could get annoying if you have a lot of number fields with different formats. Plus, if you can take care of this problem on the client, and offer instantaneous feedback to the user, why wouldn't you do that?
So, I've established the gap in JavaScript/jQuery functionality I am trying to fill. My plug-in is going to offer number formatting on the client, giving others a way to offer internationalization for their Web applications without having to talk to the server. As an added bonus, my plug-in will also do the opposite function; the plug-in will allow developers to parse numbers, getting a number out of a formatted text string. This can be used for mathematical operations on the client. Additionally, I will mimic the functionality in the Java
Step 1 result: I've established a need for a plug-in, and have defined the specs that I will use in filling the need.
Plug-in rules
The jQuery team has established a number of general rules that they want plug-in authors to follow to create a common and expected environment for the plug-in users. Because I consider the jQuery team to be much smarter than me, who am I to disagree with any of the rules, right? For that reason, I'll outline the rules here, and will also strive to follow them in every step of my own plug-in.
Step 2 result: I will follow all the rules of creating a jQuery plug-in
Writing the plug-in
Now it's time to start writing the code! The first step in starting your plug-in is to decide how you want to structure your plug-in. There are two choices to start off with: do you want it to be a method or a function? "What's the difference?" you might ask.
A method, as I said above, needs to be attached to the jQuery.fn object, and a function needs to be attached to the jQuery object. Oh, that clears everything up, right? Well, probably not if you're relatively new to jQuery. Instead, think of it this way. A method gives your code the ability to loop through all the selected elements that are passed into the plug-in. As a result, your plug-in can accept any type of HTML element, and it's up to your plug-in to define how to work with each element. Thus, your plug-in method can accept any jQuery selector, anything from "p" to "#mySpecificPageElement". This would be desirable if you want to have some flexibility in your plug-in, allowing users to pass in any type of page element. The burden is on you, the plug-in developer, to deal with everything properly. Contrast that with a function, which doesn't take any selected elements as arguments. It's simply a function that will be applied to the entire page. The burden shifts to the plug-in developer, who has to define which page elements they want the plug-in to interact with, and ignore the others. Let's take a look at the difference in some code.
Listing 1. jQuery plug-in method/function
So, judging from these descriptions, it looks like your plug-in should use a method, because you want to allow its users to tell you what page elements they want formatted. Listing 2 shows how your plug-in code looks now.
Listing 2. Your method definition
Of course, your function can't simply be a one-size-fits-all plug-in, because you're dealing with internationalization and you can't automatically figure out what country you want the text formatted for or the format you want. So, you must modify your plug-in slightly to accept some options. You will need two options in your formatting method: the format the number should use (for example, #,### vs. #,###.00) and the locale (the locale being a simple 2-letter country code to determine which international number formatting to use).
You also want to make your plug-in as easy to use as possible, because you want to increase your plug-in's chances of success. This means you should also go ahead and define some default options so the user doesn't have to pass in the options if they don't want to. Because I'm writing this from the U.S., and that also happens to be the most common number formatting in the world, I'll default to the "us" locale, and I'll default to the "#,###.00" format, for no other reason other that it can be used for currency with this default.
Listing 3. Allowing options in your plug-in
The final step to creating your plug-in framework is to work properly with the selected elements that were passed into the method. If you'll recall from the examples above, the selected elements could be 1 page element, or it could be many page elements. You have to deal with them all equally well. Also, recall from the jQuery plug-in commandments, the
Listing 4. Working with the jQuery object
Because the actual plug-in code itself isn't the point of this article, I won't spend any time on it, but you can see it all in the plug-in code attached to this article (see Download). I'd also like to show you an example of how you'd set up your plug-in architecture if you decided to write a function, as opposed to a method.
Listing 5. Example plug-in using a function
Fine tuning the plug-in
Most beginner plug-in articles you find around the Web will stop there, letting you take the basic plug-in format and run with it. However, this basic framework is just that, basic. There are other important things that you must consider when writing your own plug-in, things that will give your plug-in the polish it needs to be more than a beginner plug-in. With these two added steps, you can turn your beginner plug-in into an intermediate-level plug-in.
Fine tune #1 - Make internal methods private
In any object-oriented programming language, you will find it handy to create external functions that can run repetitious code. In the NumberFormatter plug-in that I've created, there is an example of this code — the code that decides which locale got passed into the function and which characters to use as the decimal points and the group separator. This code is needed in the both the
The solution for this private method problem is something called a Closure, and it essentially closes the entire plug-in code from outside calls, except those you attach to the jQuery object (which is public). Using this design, you can put any code you want within your plug-in and not worry about it being called by outside scripts. By attaching your plug-in methods to the jQuery object, you are essentially making them public methods, with all the rest of the functions/classes becoming private. Listing 6 gives you a look at the code required to do this.
Listing 6. Make a function private
Fine tune #2 - Make your plug-in's defaults overridable
The last step to fine-tuning this plug-in is to give it the ability to have its defaults overridden. After all, if a developer in Germany downloaded this plug-in, and knew that all of his Web application's users would want to see the German locale, you should give him the ability to change the default locale in one line of code, rather than requiring him to write it in every method call. This is particularly handy in your plug-in because it is highly unlikely that a Web application will present numbers in different international formats to its users. Chances are, if you're on a Web page, all the numbers are going to be formatted using the same locale.
This step will require you to modify your code somewhat, so what you've seen so far has been updated to reflect this latest polishing step.
Listing 7. Overridable defaults
That is the last step to creating your plug-in! What you should have now at this point is a polished plug-in that's ready for the final steps of testing. Listing 8 shows the completed plug-in that you've put together in this article so you can see how all the pieces fit together. Also, included is the
Listing 8. The NumberFormatter plug-in
Testing the plug-in
The final step in creating my plug-in is to test it—thoroughly. Nothing angers a plug-in user more than seeing a bug in your plug-in. Rather than fix it, they will quickly dump your plug-in and move on. Getting a few of these types of users as well as some bad reviews can quickly sink your plug-in. Besides, it's a good reciprocal behavior—you want the plug-ins you use in your code to be well tested, so you should return the favor in your own plug-in code.
I created a quick test structure to test my plug-in (no need for a unit testing library), which creates dozens of spans with various numbers and the correct format right after the number. The JavaScript test calls format on the numbers and then compares the formatted number with the desired result, showing them as red if it fails. With this quick test, I can set up dozens of different test cases, testing every possible format, which I've done. I've attached my test page to the examples download so you can see one possible solution to testing your plug-in, utilizing jQuery to do the testing for you.
Looking at the finished plug-in
Let's take a look at the new NumberFormatter in action. I've created a simple Web application that you can look at to see how the NumberFormatter plug-in can fit in your applications.
Figure 1. NumberFormatter in action
The Web application is simple and straightforward enough. When the user leaves the textfield, after typing in their salary, house, and child information, the NumberFormatter plug-in will format their answers appropriately. The plug-in allows the Web app to consistently format numbers to the user. Also, note that this Web application is formatted for a user in Germany, as the decimal and group characters are different than it would be for a user in the U.S. (this lets me show how to change defaults).
Listing 9. NumberFormatter in action
Some remaining things to point out about the NumberFormatter plug-in before I close things up. First of all, this is the first 1.0.0 release of the plug-in, so I'm hoping to expand it in the future to include more formatting features that are included in the Java DecimalFormatter. This includes support for currency, scientific notation, and percentages. It will also include separate formatting rules for positive and negative numbers, beyond the simple "-" for a negative (for example, using (5,000) for negative numbers, which is done in accounting). Finally, a good formatter will allow any character in the format, it just ignores any that aren't part of the reserved characters. These are all features I hope to add in the near term to make this a robust plug-in.
Getting the locale of a user
One last question that's not specific to jQuery plug-ins, but one that might arise from using this plug-in—how do you get the user's locale? This is a good question, because there's currently no way to get this information using JavaScript. You'll need to create a JavaScript Bridge to do it. What's a JavaScript Bridge? I just mean you can set up a simple design pattern to get values into the JavaScript code from the server-side code. Listing 10 shows you could use Java; how you could do this on a JSP page.
Listing 10. Getting a user's locale
In a previous article in this series, Working with jQuery, Part 2: Intermediate JQuery: The UI project, I discussed using plug-ins in your own jQuery code to increase the effectiveness of your Web applications. However, these plug-ins don't write themselves. They are written and tested by developers like you and me, donating their free time to the jQuery community to make it better. And we do this all for free, living only for the love of our own code. This article focuses on how you can give something back to this great community, by writing your own plug-in and checking it into the plug-in pages hosted by jQuery. This lets everyone use the plug-in you create, bettering the entire jQuery development community. Consider this my charity work for the year.
While writing the plug-in for this article, I found that the plug-in creation, and the framework for creating it, is extremely straightforward and easy. The hard work is actually thinking of something that hasn't already been done by someone else, and writing the "grunt work" JavaScript code that actually does things. Because of the straightforward plug-in structure, which is easy for beginners and flexible for advanced coders, the number of plug-ins has grown rapidly.
Of course, in doing the research for this article, I also found that every author has their own style for writing a plug-in and that jQuery allows several different styles for writing them. I will concentrate on the easiest one here, and the one recommended by jQuery itself, but will point out any differences or options as they pop up.
Describing your plug-in
Step 1 in creating a plug-in is, of course, thinking of a good idea. Chances are, like most good ideas, someone else has already beaten you to it. For the plug-in I'll be developing here, it's not a novel concept, but at the time of this article I couldn't find it anywhere in the jQuery plug-in community. I know I would personally get a lot of use out of it.
My plug-in is a NumberFormatter plug-in. Number formatting is likely familiar to anyone who's worked with server-side code like Java™ or PHP and internationalization. It's common knowledge that not everyone in the world formats their numbers in the same way. For example, not everyone uses miles for distance. A number that we would write in the U.S. as "1,250,500.75" (I just grabbed this number from my tax form), would be written differently in different countries: "1.250.500,75" in Germany, "1 250 500,75" in France, "1'250'500.75" in Switzerland, and "125,0500.75" in Japan. The number is exactly the same, but it's just written using a different format when presented to users of the Web application.
So, the question emerges, when you're writing an international application, how would you present these numbers to people in different countries? The solution, of course, is to use server-side formatting, which is pretty common. Java has a robust formatting library to make formatting numbers easy. When the page is set up on the server with numbers, the server can take care of formatting these numbers. However, many times you might not be on the server, so you need a way to format numbers on the client, without ever talking to the server.
Here's a typical use case for what I'm describing. You have an input field in your Web application that asks a person for their salary. In the U.S., the user can type in varied forms of input - "$65000", "65,000", "65000", "65,000.00". All these numbers are exactly the same, but you want to control how these numbers look on the screen, in order to create a better user experience. You could call the server after the number is entered, but this could get annoying if you have a lot of number fields with different formats. Plus, if you can take care of this problem on the client, and offer instantaneous feedback to the user, why wouldn't you do that?
So, I've established the gap in JavaScript/jQuery functionality I am trying to fill. My plug-in is going to offer number formatting on the client, giving others a way to offer internationalization for their Web applications without having to talk to the server. As an added bonus, my plug-in will also do the opposite function; the plug-in will allow developers to parse numbers, getting a number out of a formatted text string. This can be used for mathematical operations on the client. Additionally, I will mimic the functionality in the Java
DecimalFormatter class, to maintain a
commonality between the client code and the standard server-side method of
doing number formatting. Step 1 result: I've established a need for a plug-in, and have defined the specs that I will use in filling the need.
Plug-in rules
The jQuery team has established a number of general rules that they want plug-in authors to follow to create a common and expected environment for the plug-in users. Because I consider the jQuery team to be much smarter than me, who am I to disagree with any of the rules, right? For that reason, I'll outline the rules here, and will also strive to follow them in every step of my own plug-in.
- Name your file "
jquery.<your plug-in name>.js"
Well, this makes sense, because you want someone to look at the file and know right away that it's a jQuery plug-in, and which plug-in it is. Check. I will call my plug-in "jquery.numberformatter.js." - All new methods are attached to the jQuery.fn object, all new functions
to the jQuery object
This may be confusing at this stage, and I will discuss this more in the next section because this is the most important rule for actual coding. Check. I will only attach methods/functions to those two objects. - "
this" is a reference to the jQuery object
This is to facilitate plug-in writing by letting all plug-in authors know what object they will receive from jQuery when they reference "this." Check. I will use "this" only as a reference to the jQuery object. - All methods/functions defined in the plug-in must have a ";"
(semicolon) at the end
or code minimizers will break.
Because it is a best practice to minimize JavaScript files, breaking the minimizer would be bad, and chances are your plug-in would get dumped quickly Check. All of the methods/functions will have a ";" at the end. - All methods must return the jQuery object, unless otherwise noted
The daisy-chaining of jQuery methods is quite popular, and if you write a plug-in that breaks this chain, it literally "breaks the chain" Check. Myformat()method will return the jQuery object, and even though theparse()method will not return the jQuery object, I have documented it in many places that this function breaks the chain. (After all, it would be difficult/impossible to return a Number object and not break the chain.) - You should always use
this.each()to iterate over the matched elements, as this is a reliable and efficient way to loop through objects
For performance and stability reasons, they recommend all methods use this means to loop through matched elements. Check. My methods will only loop through matched elements in this manner. - Always use "jQuery" instead of "$" in your plug-in code
This is important because it allows users who have a conflict with "$" (those who may be using another JavaScript library) the ability to change their pseudonym for jQuery in one place using the "var JQ = jQuery.noConflict();" function. However, as I have looked through many plug-ins, I have found that this rule is broken quite often, which is unfortunate. If the developer ever needs to change the jQuery pseudonym, it likely means that the broken plug-ins will get dumped. Check. In my plug-in, I will only use the jQuery and not its "$" pseudonym.
Step 2 result: I will follow all the rules of creating a jQuery plug-in
Writing the plug-in
Now it's time to start writing the code! The first step in starting your plug-in is to decide how you want to structure your plug-in. There are two choices to start off with: do you want it to be a method or a function? "What's the difference?" you might ask.
A method, as I said above, needs to be attached to the jQuery.fn object, and a function needs to be attached to the jQuery object. Oh, that clears everything up, right? Well, probably not if you're relatively new to jQuery. Instead, think of it this way. A method gives your code the ability to loop through all the selected elements that are passed into the plug-in. As a result, your plug-in can accept any type of HTML element, and it's up to your plug-in to define how to work with each element. Thus, your plug-in method can accept any jQuery selector, anything from "p" to "#mySpecificPageElement". This would be desirable if you want to have some flexibility in your plug-in, allowing users to pass in any type of page element. The burden is on you, the plug-in developer, to deal with everything properly. Contrast that with a function, which doesn't take any selected elements as arguments. It's simply a function that will be applied to the entire page. The burden shifts to the plug-in developer, who has to define which page elements they want the plug-in to interact with, and ignore the others. Let's take a look at the difference in some code.
Listing 1. jQuery plug-in method/function
// This is a method because you can pass any type of selector to the method and it
// will take some action on the results of the selector. In this case, it will
// doSomething() on the page element with an ID of myExample
$("#myExample").doSomething();
// This is also a method, even though you are passing the entire page body to
// the method, because you are still passing a selector
$("body").doSomethingElse();
// This is a function, because you are NOT passing any selector to the function
// The plug-in developer must determine what page elements they want to take action on.
// This is usually accomplished by the plug-in developer requiring the page elements
// to contain a certain class name.
<div class="anotherThing">
// This hypothetical plug-in developer would document that his plug-in only works
// on elements with the class "anotherThing"
$.anotherThing();
|
So, judging from these descriptions, it looks like your plug-in should use a method, because you want to allow its users to tell you what page elements they want formatted. Listing 2 shows how your plug-in code looks now.
Listing 2. Your method definition
jQuery.fn.format = function();
// You would call your plug-in like this (at this point)
$("#myText").format();
|
Of course, your function can't simply be a one-size-fits-all plug-in, because you're dealing with internationalization and you can't automatically figure out what country you want the text formatted for or the format you want. So, you must modify your plug-in slightly to accept some options. You will need two options in your formatting method: the format the number should use (for example, #,### vs. #,###.00) and the locale (the locale being a simple 2-letter country code to determine which international number formatting to use).
You also want to make your plug-in as easy to use as possible, because you want to increase your plug-in's chances of success. This means you should also go ahead and define some default options so the user doesn't have to pass in the options if they don't want to. Because I'm writing this from the U.S., and that also happens to be the most common number formatting in the world, I'll default to the "us" locale, and I'll default to the "#,###.00" format, for no other reason other that it can be used for currency with this default.
Listing 3. Allowing options in your plug-in
jQuery.fn.format = function(options) {
// the jQuery.extend function takes an unlimited number of arguments, and each
// successive argument can overwrite the values of the previous ones.
// This setup is beneficial for defining default values, because you define
// them first, and then use the options passed into the method as the
// second argument. This allows the user to override any default values with their
// own in an easy-to-use setup.
var options = jQuery.extend( {
format: "#,###.00",
locale: "us"
}, options);
|
The final step to creating your plug-in framework is to work properly with the selected elements that were passed into the method. If you'll recall from the examples above, the selected elements could be 1 page element, or it could be many page elements. You have to deal with them all equally well. Also, recall from the jQuery plug-in commandments, the
"this" object is a reference to
the jQuery object. So, you have a reference to the jQuery-selected elements
that were passed into the method, and now you just need to iterate through them.
Also, looking back at the Commandments, each plug-in method should return the
jQuery object. You know, of course, the jQuery object is "this", so you can
simply return this in your method and be all good. Let's take a look at how
you can accomplish both in a code snippet, iterating through each selected element
and return the jQuery object.
Listing 4. Working with the jQuery object
jQuery.fn.format = function(options) {
var options = jQuery.extend( {
format: "#,###.00",
locale: "us"
}, options);
// this code snippet will loop through the selected elements and return the jQuery object
// when complete
return this.each(function(){
// inside each iteration, you can reference the current element by using the standard
// jQuery(this) notation
// the rest of the plug-in code goes here
});
|
Because the actual plug-in code itself isn't the point of this article, I won't spend any time on it, but you can see it all in the plug-in code attached to this article (see Download). I'd also like to show you an example of how you'd set up your plug-in architecture if you decided to write a function, as opposed to a method.
Listing 5. Example plug-in using a function
jQuery.exampleFunction = function(options) {
var options = jQuery.extend( {
// your defaults
}, options);
jQuery(".exampleSelector").each(function(){
});
});
|
Fine tuning the plug-in
Most beginner plug-in articles you find around the Web will stop there, letting you take the basic plug-in format and run with it. However, this basic framework is just that, basic. There are other important things that you must consider when writing your own plug-in, things that will give your plug-in the polish it needs to be more than a beginner plug-in. With these two added steps, you can turn your beginner plug-in into an intermediate-level plug-in.
Fine tune #1 - Make internal methods private
In any object-oriented programming language, you will find it handy to create external functions that can run repetitious code. In the NumberFormatter plug-in that I've created, there is an example of this code — the code that decides which locale got passed into the function and which characters to use as the decimal points and the group separator. This code is needed in the both the
format() method and the parse() method,
and any beginning programmer can tell you this belongs in its own method.
However, one problem arises from this decision because you are working with a
jQuery plug-in: if you simply make it its own function, defined in JavaScript,
then the method can be called by anyone who uses the script, for any purpose.
This isn't what the function is intended for, and I would like to prevent
outsiders from calling it, because it is intended only for my internal work. So,
let's see how you can make this function a private one. The solution for this private method problem is something called a Closure, and it essentially closes the entire plug-in code from outside calls, except those you attach to the jQuery object (which is public). Using this design, you can put any code you want within your plug-in and not worry about it being called by outside scripts. By attaching your plug-in methods to the jQuery object, you are essentially making them public methods, with all the rest of the functions/classes becoming private. Listing 6 gives you a look at the code required to do this.
Listing 6. Make a function private
// this code creates the Closure structure
(function(jQuery) {
// this function is "private"
function formatCodes(locale) {
// plug-in specific code here
}; // don't forget the semi-colon
// this method is "public" because it's attached to the jQuery object
jQuery.fn.format = function(options) {
var options = jQuery.extend( {
format: "#,###.00",
locale: "us"
},options);
return this.each(function(){
var text = new String(jQuery(this).text());
if (jQuery(this).is(":input"))
text = new String(jQuery(this).val());
// you can call the private function like any other function
var formatData = formatCodes(options.locale.toLowerCase());
// plug-in-specific code here
});
}; // don't forget the semi-colon to close the method
// this code ends the Closure structure
})(jQuery);
|
Fine tune #2 - Make your plug-in's defaults overridable
The last step to fine-tuning this plug-in is to give it the ability to have its defaults overridden. After all, if a developer in Germany downloaded this plug-in, and knew that all of his Web application's users would want to see the German locale, you should give him the ability to change the default locale in one line of code, rather than requiring him to write it in every method call. This is particularly handy in your plug-in because it is highly unlikely that a Web application will present numbers in different international formats to its users. Chances are, if you're on a Web page, all the numbers are going to be formatted using the same locale.
This step will require you to modify your code somewhat, so what you've seen so far has been updated to reflect this latest polishing step.
Listing 7. Overridable defaults
jQuery.fn.format = function(options) {
// Change how you load your options in to take advantage of your overridable defaults
// You change how your extend() function works, because the defaults
// are globally defined, rather than within the method. If you didn't use the
// {} as the first argument, you'd copy the options passed in over the defaults, which is
// undesirable. This {} creates a new temporary object to store the options
// You can simply call the defaults as an object within your plug-in
var options = jQuery.extend({},jQuery.fn.format.defaults, options);
return this.each(function(){
// rest of the plug-in code here
// define the defaults here as an object in the plug-in
jQuery.fn.format.defaults = {
format: "#,###.00",
locale: "us"
}; // don't forget the semi-colon
|
That is the last step to creating your plug-in! What you should have now at this point is a polished plug-in that's ready for the final steps of testing. Listing 8 shows the completed plug-in that you've put together in this article so you can see how all the pieces fit together. Also, included is the
parse() function, which I haven't talked about up until this point,
but which is included in the plug-in. (I've excluded the grunt work of the
plug-in, the parts that deal with formatting, because they are outside the scope
of the article. They are included in the examples, and are of course in the
plug-in itself).
Listing 8. The NumberFormatter plug-in
(function(jQuery) {
function FormatData(valid, dec, group, neg) {
this.valid = valid;
this.dec = dec;
this.group = group;
this.neg = neg;
};
function formatCodes(locale) {
// format logic goes here
return new FormatData(valid, dec, group, neg);
};
jQuery.fn.parse = function(options) {
var options = jQuery.extend({},jQuery.fn.parse.defaults, options);
var formatData = formatCodes(options.locale.toLowerCase());
var valid = formatData.valid;
var dec = formatData.dec;
var group = formatData.group;
var neg = formatData.neg;
var array = [];
this.each(function(){
var text = new String(jQuery(this).text());
if (jQuery(this).is(":input"))
text = new String(jQuery(this).val());
// now we need to convert it into a number
var number = new Number(text.replace(group,'').replace(dec,".").replace(neg,"-"));
array.push(number);
});
return array;
};
jQuery.fn.format = function(options) {
var options = jQuery.extend({},jQuery.fn.format.defaults, options);
var formatData = formatCodes(options.locale.toLowerCase());
var valid = formatData.valid;
var dec = formatData.dec;
var group = formatData.group;
var neg = formatData.neg;
return this.each(function(){
var text = new String(jQuery(this).text());
if (jQuery(this).is(":input"))
text = new String(jQuery(this).val());
// formatting logic goes here
if (jQuery(this).is(":input"))
jQuery(this).val(returnString);
else
jQuery(this).text(returnString);
});
};
jQuery.fn.parse.defaults = {
locale: "us"
};
jQuery.fn.format.defaults = {
format: "#,###.00",
locale: "us"
};
})(jQuery);
|
Testing the plug-in
The final step in creating my plug-in is to test it—thoroughly. Nothing angers a plug-in user more than seeing a bug in your plug-in. Rather than fix it, they will quickly dump your plug-in and move on. Getting a few of these types of users as well as some bad reviews can quickly sink your plug-in. Besides, it's a good reciprocal behavior—you want the plug-ins you use in your code to be well tested, so you should return the favor in your own plug-in code.
I created a quick test structure to test my plug-in (no need for a unit testing library), which creates dozens of spans with various numbers and the correct format right after the number. The JavaScript test calls format on the numbers and then compares the formatted number with the desired result, showing them as red if it fails. With this quick test, I can set up dozens of different test cases, testing every possible format, which I've done. I've attached my test page to the examples download so you can see one possible solution to testing your plug-in, utilizing jQuery to do the testing for you.
Looking at the finished plug-in
Let's take a look at the new NumberFormatter in action. I've created a simple Web application that you can look at to see how the NumberFormatter plug-in can fit in your applications.
Figure 1. NumberFormatter in action
The Web application is simple and straightforward enough. When the user leaves the textfield, after typing in their salary, house, and child information, the NumberFormatter plug-in will format their answers appropriately. The plug-in allows the Web app to consistently format numbers to the user. Also, note that this Web application is formatted for a user in Germany, as the decimal and group characters are different than it would be for a user in the U.S. (this lets me show how to change defaults).
Listing 9. NumberFormatter in action
$(document).ready(function() {
// use the AlphaNumeric plug-in to limit the input
$(".decimal").decimal();
$(".numeric").numeric();
// you want to change the defaults to use the German locale
// this will change the default for every method call on the
// entire page, so you won't have to pass in the "locale"
// argument to any function
$.fn.format.defaults.locale = "de";
$.fn.parse.defaults.locale = "de";
// when the salary field loses focus, format it properly
$("#salary").blur(function(){
$(this).format({format:"#,###.00"});
});
// when the house field loses focus, format it properly
$("#houseWorth").blur(function(){
$(this).format({format:"#,###"});
});
// when the kids field loses focus, format it properly
$("#kids").blur(function(){
$(this).format({format:"#"});
});
// calculate the tax
$("#calculate").click(function(){
// parse all the numbers from the fields
var salary = $("#salary").parse();
var house = $("#houseWorth").parse();
var kids = $("#kids").parse();
// make some imaginary tax formula
var tax = Math.max(0,(0.22*salary) + (0.03*house) - (4000*kids));
// place the result in the tax field, and then format the resulting number
// you need one intermediate step though, and that's the "formatNumber" function
// because all numbers in JavaScript use a US locale when made into a String
// you need to convert this Number into a German locale String before
// calling format on it.
// So, the steps are:
// 1) the tax is a Number that looks like 9200.54 (US locale)
// 2) formatNumber converts this to a String of 9200,54 (German locale)
// 3) put this String in the #tax field
// 4) Call format() on this field
$("#tax").text($.formatNumber(tax)).format({format:"#,###"});
});
});
|
Some remaining things to point out about the NumberFormatter plug-in before I close things up. First of all, this is the first 1.0.0 release of the plug-in, so I'm hoping to expand it in the future to include more formatting features that are included in the Java DecimalFormatter. This includes support for currency, scientific notation, and percentages. It will also include separate formatting rules for positive and negative numbers, beyond the simple "-" for a negative (for example, using (5,000) for negative numbers, which is done in accounting). Finally, a good formatter will allow any character in the format, it just ignores any that aren't part of the reserved characters. These are all features I hope to add in the near term to make this a robust plug-in.
Getting the locale of a user
One last question that's not specific to jQuery plug-ins, but one that might arise from using this plug-in—how do you get the user's locale? This is a good question, because there's currently no way to get this information using JavaScript. You'll need to create a JavaScript Bridge to do it. What's a JavaScript Bridge? I just mean you can set up a simple design pattern to get values into the JavaScript code from the server-side code. Listing 10 shows you could use Java; how you could do this on a JSP page.
Listing 10. Getting a user's locale
<%
// the request object is built into JSPs
// unfortunately, it's not any easier
// tested on FF, IE, Safari, Chrome
String locale = "us"; // or your default locale
String accLang = request.getHeader("Accept-Language");
if (accLang.length() > 5)
{
accLang = accLang.substring(0,5);
locale = accLang.substring(accLang.indexOf("-")+1);
}
%>
$(document).ready(function() {
// take advantage of the ability to override defaults by using the JavaScript
// Bridge here. Then your page can use the format() and parse() functions
// elsewhere in the page without modifying them for a user's locale.
$.fn.format.defaults.locale = "<%=locale%>";
$.fn.parse.defaults.locale = "<%=locale%>";
});
Wednesday, August 17, 2011
jQuery Plugin Design Patterns: Part I
jQuery plugins come in all shapes and sizes. They perform very simple
or very complex tasks depending on their intended use. When it comes
time for you to design your own plugin, its really important to
understand what patterns other developers use and what will best suits
your needs.
As a side note, I have built a number of plugins for my own projects and client work that will never be released. The jQuery community needs to stop thinking of plugins only as releasable, open-source projects, and start thinking of them instead as a reusable pieces of code that can help optimize and DRY up a complex website. Take this little plugin as an example:
It simply abstracts the animation for displaying a notice (using
jQuery 1.4). Would I ever release this on an open source site? Of course
not! But it is still a fully functioning jQuery plugin that can be used
over and over throughout a website.
Released plugins often also have a version number:
If you end up building a lot of plugins for your website, consider
also including a namespace to keep all your files together (And of
course you would combine and minify them for production, right?):
This gives your plugin a private scope to work in, and also allows your plugin to be used with
You should use this this structure when you are
writing a simple plugin that acts once upon the jQuery result set on
each execution. For complex plugins that need to maintain an adjustable
state, you should consider the “Class and Function” structure.
You should use this structure if you need to be able
to access the object later that is associated with a DOM element. It is
far easier to attach a single object vs several key/value pairs using
the data() method. In this approach, you can access the object by calling $('selector').data('MyClass').
This functions more like a widget and is a plugin that maintains state
and can adjust its state on the fly (Learn how in the next article.).
Note: Widget Factory: The next release of jQuery UI is going to see the addition of a Widget Factory that will be designed to specially assist in developing widget-like plugins.
You will find this structure helpful if you need to add a large number
of plugin methods to jQuery. I would contend, however, that if your
plugin needs to add that many methods, there may be a better way to
structure its implementation.
I feel the extend method is used more by programmers transitioning from other JS libraries. I personally find the simple $.fn.pluginName = structure to be easier to read, and more in line with what you will normally see in jQuery plugins.
As a side note, I have built a number of plugins for my own projects and client work that will never be released. The jQuery community needs to stop thinking of plugins only as releasable, open-source projects, and start thinking of them instead as a reusable pieces of code that can help optimize and DRY up a complex website. Take this little plugin as an example:
$.fn.notice = function(){ |
return this.slideDown(500).delay(4000).slideUp(500); |
} |
Design Pattern Series Overview
- Basics & Structure (this article)
- Options & Updating
- Callbacks & Custom Events
- Misc. General Practices
Basics
Filename
Every jQuery plugin sits in its own JS file, and is normally named using the following pattern:jquery.pluginname.js |
jquery.pluginname.min.js |
jquery.pluginname-1.3.js |
jquery.pluginname-1.3.min.js |
jquery.mysite.pluginname.js |
jquery.mysite.pluginname.js |
Basic File Layout
After any comments you choose to put at the top of your file, the very next thing you should have is a self executing anonymous function that will actually wrap your entire plugin. Say what!? Don’t worry, you have seen it before, and it looks like this:(function($){ |
... code here ... |
})(jQuery); |
$.noConflict mode without creating a problem. By passing jQuery into the function, the $ will equal jQuery inside the function even if $ means something different outside your plugin.Structure
There are three basic structures you will see when you look at released plugins:Contained Function
In this structure, (almost) all the code to run your plugin is contained within the function used to call your plugin. This is the most common format:(function($){ |
$.fn.myPlugin = function(){ |
return this.each(function(){ |
// do something |
}); |
} |
})(jQuery); |
Class and Function
In this structure, a class is used and an instance is created for each DOM element in the result set. You may see these objects attached in some way to the DOM elements they modify:(function($){ |
var MyClass = function(el){ |
var $el = $(el); |
// Attach the instance of this object |
// to the jQuery wrapped DOM node |
$el.data('MyClass', this); |
} |
$.fn.myPlugin = function(){ |
return this.each(function(){ |
(new MyClass(this)); |
}); |
} |
})(jQuery); |
Note: Widget Factory: The next release of jQuery UI is going to see the addition of a Widget Factory that will be designed to specially assist in developing widget-like plugins.
Extend
In my opinion, this is the least idiomatic way to create a jQuery plugin. It uses the jQuery.fn.extend method instead of jQuery.fn.pluginName:(function($){ |
$.fn.extend({ |
myPlugin: function(){ |
return this.each(function(){ |
// do something |
}, |
myOtherPlugin: function(){ |
return this.each(function(){ |
// do something |
} |
}); |
})(jQuery); |
I feel the extend method is used more by programmers transitioning from other JS libraries. I personally find the simple $.fn.pluginName = structure to be easier to read, and more in line with what you will normally see in jQuery plugins.
Up Next
In the next part of this series, we will look at passing options and providing methods for updating settings and functionality after a plugin has been called.Jquery Plugin
For some jQuery plugins
it would be useful if we could expose one or more functions, so that we
can interact with it from Javascript outside the plugin. If we follow
the standard mechanism of plugin authoring, we can only interact with
the it at the moment of initialisation. This post will look at two
mechanisms that can be used to expose and access plugin functions.
This post will be based around the following mediaPlayer fictional plugin:
This mediaPlayer plugin would work by being attached to a selected DIV element in the DOM, like this:
Now suppose we now want to interact with our mediaPlayer from
outside. For example, we may want to trigger the media player to play a
certain file. It would be useful if we could have a play() function on
our plugin so we can trigger this action. So, how can we do this?
There is another approach to building jQuery plugins, called the class and function approach (see this
excellent article of jQuery design patterns). Instead of returning the
current context, the jQuery plugin creates and then returns a new
instance of a JavaScript class. So, our mediaPlayer plugin could be
created in the following way:
If the Javascript that creates the plugin stores a reference to
returned instance it can continue accessing it’s public API. For
example:
However, there is a bit of a problem with this approach. Because it
returns the instance of the class rather than the current context, it
breaks the chaining of plugins in jQuery. We can no longer do this…
…we would have to do this instead:
The example below shows how we might use this mechanism to build our mediaPlayer plugin.
When the plugin function is called the first argument is examined to
see what type it is. If this is NOT a string it is a call to initialise
a mediaPlayer and so the createMediaPlayer() method is executed by
using the apply() command. It uses apply as it 1) ensures that the
context is correct (this is passed as the context); and 2) allows us to pass the argument(s) without caring about how many there are.
If the first argument is a string, then this must be the name of the function that is required to be executed. A new arguments array is prepared by stripping off the first argument (see this blog post about splice), as the called method won’t need this. Then the named function is executed by calling apply() and passing the current context and our new list of arguments. You might notice that when this named function is executed it has to retrieved from the commands object by using the bracket notation. This is required for the apply() function to be able to execute functions dynamically from string values.
This is how we would initialise this plugin and call the play() function:
As the context is always returned from the plugin function we can still chain calls to our selected DIV:
The Execution Through apply() Mechanism still allows jQuery chaining as the current context is still returned from the plugin initialisation function. This mechanism allows access to functions by effectively overloading the initialisation function to allow the name of the function that is to be executed to be passed in. This function can then be executed by using the JavaScript apply() command.
This post will be based around the following mediaPlayer fictional plugin:
- (function($) {
- $.fn.mediaPlayer = function(options){
- .........
- }
- })(jQuery);
- $('.myDiv').mediaPlayer(options);
Class and Function Mechanism
With the standard mechanism of building a jQuery plugin we always ensure that the plugin function returns this (the current context of the plugin). The reason for returning the current context is that it allows the plugin call to be chained onto another plugin call. For example:- $('.myDiv')
- .mediaPlayer(options)
- .otherPlugin();
- (function($) {
- //the class
- var player = function(options){
- return createApi();
- function createApi(){
- return {
- play : play
- }
- }
- function play(url) {
- //our play code
- }
- }
- //the function
- $.fn.mediaPlayer = function(options){
- //create an instance of the class and return from the plugin
- return new player(options);
- }
- })(jQuery);
- var myMediaPlayer = $('.myDiv').mediaPlayer(options);
- myMediaPlayer.play(url1);
- myMediaPlayer.play(url2);
- $('.myDiv')
- .mediaPlayer(options)
- .otherPlugin();
- $('.myDiv')
- .mediaPlayer(options);
- $('.myDiv')
- .otherPlugin();
Execution Through apply() Mechanism
An alternative, and my preferred approach, is to execute the ‘public’ functions in the main plugin function by use of the apply() command. For this approach to work the plugin function has to be effectively overloaded, so that it can be used in two ways. It needs to retain it’s constructive form which in out case takes one argument of options, but it also needs to be able to accept an alternative call that takes a string argument (function name) and any additional arguments that this function requires.The example below shows how we might use this mechanism to build our mediaPlayer plugin.
- (function($) {
- //define the commands that can be used
- var commands = {
- play: play,
- stop: stop
- };
- $.fn.mediaPlayer = function() {
- if (typeof arguments[0] === 'string') {
- //execute string comand on mediaPlayer
- var property = arguments[1];
- //remove the command name from the arguments
- var args = Array.prototype.slice.call(arguments);
- args.splice(0, 1);
- commands[arguments[0]].apply(this, args);
- }
- else {
- //create mediaPlayer
- createMediaPlayer.apply(this, arguments);
- }
- return this;
- };
- function createMediaPlayer(options){
- //mediaPlayer initialisation code
- }
- //Exposed functions
- function play(url) {
- //code to play media
- }
- function stop() {
- //code to stop media
- }
- })(jQuery);
If the first argument is a string, then this must be the name of the function that is required to be executed. A new arguments array is prepared by stripping off the first argument (see this blog post about splice), as the called method won’t need this. Then the named function is executed by calling apply() and passing the current context and our new list of arguments. You might notice that when this named function is executed it has to retrieved from the commands object by using the bracket notation. This is required for the apply() function to be able to execute functions dynamically from string values.
This is how we would initialise this plugin and call the play() function:
- $('.myDiv')
- .mediaPlayer(options);
- $('.myDiv')
- .mediaPlayer('play', url1);
- $('.myDiv')
- .mediaPlayer(options)
- .otherPlugin();
- //chain calls to our play method...
- $('.myDiv')
- .mediaPlayer('play', url1)
- .mediaPlayer('play', url2);
Conclusion
In this post I’ve looked at two mechanisms that can be used to expose functions on jQuery plugins. The first of these is the Class and Function Mechanism that exposes ‘public’ functions by returning an instance of a class from the plugin initialisation function. Although this does allow functions to be exposed, it does break jQuery chaining and so is not ideal.The Execution Through apply() Mechanism still allows jQuery chaining as the current context is still returned from the plugin initialisation function. This mechanism allows access to functions by effectively overloading the initialisation function to allow the name of the function that is to be executed to be passed in. This function can then be executed by using the JavaScript apply() command.
Tuesday, May 31, 2011
Jquery mistake you 're probaly making
- Selector Perfomance :
- Event binding : What is different between live method and delegate method?
$('li',ul).live('click',function(){});$(ul).delegate('li','click',function(){});Initialization performance!
.live() will execute the selector at init,.delegate() will not


6:06 PM
Unknown



