Web application R&D notes, from the world of Java, Flex, CSS, XHTML, Flash, .NET, cross-browser compatibility, JavaScript, AJAX, ADA compliance, Photoshop, and any and all things related to Web development!
Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts
06 August 2015
Nice jQuery plugin for "Read more" text truncating
Spent some time researching options to do "Read more" functionality for text on a web page. Many were based on a preset height in pixel, which cut the text in mid-sentence, without adding any ellipsis. In addition, those which did truncate with ellipsis lacked a flexible animation. Then I found jTruncate from jMar's blog. It does the trick on any number of elements on the page via jQuery; it also includes options for animation and more/less link text.
07 April 2015
19 October 2011
IE7 and "Error: Expected identifier, string or number"
IE7 (and earlier versions) have trouble with errant commas in array declarations. Take this code, provided by James Messinger on Stack Overflow:
<script type="text/javascript">
// Replace the normal jQuery getScript function with one that supports
// debugging and which references the script files as external resources
// rather than inline.
jQuery.extend({
getScript: function(url, callback) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = url;
// Handle Script loading
{
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true;
if (callback)
callback();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
}
};
}
head.appendChild(script);
// We handle everything using the script element injection
return undefined;
}, // <-- Unneeded comma which blows up IE7.
});
</script>
IE7 blows up with this error:Error: Expected identifier, string or numberIt took quite a bit of debugging and Google searches to finally understand where the problem was. Note the last comma, after the next-to-last closing curly brace "}," -- this is unnecessary. Modern browsers can handle this, but IE7 chokes. Simply remove the comma and you're good to go. More on this problem on Stack Exchange.
02 October 2011
SharePoint: Create an easy "Share page with friend" button
In SharePoint, it's useful to have an email icon that allows users to email the page to friends. Though we could build a popup box, we can also go with a simpler solution that uses the person's email client to do the heavy lifting. In another post, I covered how to fetch some of the server-side variables into a JavaScript array needed for generating this email. Now, let's use the variables and see how we send the email.
One key to this feature is to keep it simple; this means, we'll leave the To field of the email blank and use the commonplace "mailto:" HREF attribute. So, let's get to the code:
Once we've concatenated the various elements, we pass the anchor variable to the jQuery wrap() function, called on the email icon img tag (with ID of send-email). We call the above generateEmailTo() in the document.ready function. When you click the link, it produces something like this in the generated email (Outlook, Thunderbird, etc.):
Hope you find this useful.
Update: Here's the IMG tag that is being referenced in the code above:
function generateEmailTo(){
var body = currentElements.currentUserName + ' has shared a page with you on the intranet.%0A%0APage Title: %22' +
currentElements.currentTitle + '%22%0A' + $(location).attr('href').replace('#','');
var subject = currentElements.currentUserName + ' has shared an intranet page with you';
var mailto = 'mailto: ?body=' + body + '&subject=' + subject;
var anchor = '<a href="' + mailto + '"></a>';
$("#send-email").wrap(anchor);
}
We can pass the body, subject, and mailto for the mail message. The ?body= and the &subject= allow the main message and the subject to be passed in the querystring. To provide line breaks, we use %0A hex values; so for two line breaks, we use %0A%0A in the querystring value. To pass quotes, we use %22. To pass a blank mailto:, we leave a space in front of it, before the ?body=. More notes on mailto, setting its cc, bcc, and special characters can be found here.Once we've concatenated the various elements, we pass the anchor variable to the jQuery wrap() function, called on the email icon img tag (with ID of send-email). We call the above generateEmailTo() in the document.ready function. When you click the link, it produces something like this in the generated email (Outlook, Thunderbird, etc.):
Alex C has shared a page with you on the intranet. Page Title: "My Page Title" http://mysite.org/Pages/mypage.aspxThe subject, not shown, will be "Alex C has shared an intranet page with you". Note that the URL will appear as a clickable link in most email clients. Also note that we can't pass HTML to the body of the message, only plain text.
Hope you find this useful.
Update: Here's the IMG tag that is being referenced in the code above:
<img id="infoweb-email" title="Send this page to a friend." src="<%= baseUrl %>/SiteAssets/media/icons/email-icon.gif"/>The baseUrl server-side variable is set in the page layout's OnLoad event handler:
<script type="text/c#" runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e); // Required for the SharePoint ribbon bar, etc., to work correctly.
Microsoft.SharePoint.SPContext context = Microsoft.SharePoint.SPContext.GetContext(HttpContext.Current);
baseUrl = context.Site.Url;
// Other code...
}
</script>
For the page layout to allow code blocks, we must make the following change to the Web.config file:
<PageParserPaths> <PageParserPath VirtualPath="/_catalogs/masterpage/*" CompilationMode="Always" AllowServerSideScript="true" IncludeSubFolders="true"/> </PageParserPaths>Note that this allows all files in the masterpage folder to contain code blocks. If we use Firebug to examine the element in Firefox, we'll see this is the HTML generated by our server- and client-side code:
<a href="mailto: ?body=Alex%20C has shared a page with you on the intranet.%0A%0APage Title: %22My%20Page%20Title%22%http://mysite.org/Pages/mypage.aspx&subject=Alex%20C has shared a page with you on the intranet."> <img id="send-email" src="http://mysite.org/SiteAssets/media/icons/email-icon.gif" title="Send this page to a friend."> </a>So the IMG element has been wrapped by an anchor tag which has the properties we set in JavaScript.
SharePoint: Fetch environment variables and store in JavaScript
For a header text, we needed the current site's name. In addition, to generate a "Share this page with a friend" button, we needed the current user's login name and full name. We could use SharePoint's Client Object Model, which does an asynchronous call from JavaScript to get the information.
However, we needed the site's name to be available with the DOM, not when the page loads; we tried the AJAX call and it took a second or two to fetch the data. During this time, the page had no header text saying which site the user was on.
What to do? We could use jQuery to get the site name from the breadcrumbs generated via the asp:SiteMapPath control, but there could be times when we wouldn't be using this control. Else we could fetch it from the top-left navigation tree dropdown; even that was clunky. So we decided to put the following code in the Page Layout's PlaceHolderAdditionalPageHead control; it can also be placed in the master page:
Once we have the values, we plug them into a JavaScript array that we build server-side. When the page loads in the browser, the array will be instantiated with the values we set using C#. We use a StringBuilder object for optimal performance because of the string concatenations.
So what does it look like when the page loads? Here it is:
A final note: If any of the values will have a single quote in them, just escape the value using a .Replace("'","\'")on the string in C#.
However, we needed the site's name to be available with the DOM, not when the page loads; we tried the AJAX call and it took a second or two to fetch the data. During this time, the page had no header text saying which site the user was on.
What to do? We could use jQuery to get the site name from the breadcrumbs generated via the asp:SiteMapPath control, but there could be times when we wouldn't be using this control. Else we could fetch it from the top-left navigation tree dropdown; even that was clunky. So we decided to put the following code in the Page Layout's PlaceHolderAdditionalPageHead control; it can also be placed in the master page:
<asp:Content ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server">
<%
String currentUserName = Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.Name.ToString();
String currentUserEmail = Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.LoginName.ToString().Replace("MYDOMAIN\\","");
String currentSite = Microsoft.SharePoint.SPContext.Current.Web.ToString();
String currentTitle = (Microsoft.SharePoint.SPContext.Current.Item["Title"] == null) ?
"" : Microsoft.SharePoint.SPContext.Current.Item["Title"].ToString();
StringBuilder sb = new StringBuilder();
sb.Append("<script type='text/javascript'>var currentElements = { currentUserName: '");
sb.Append(currentUserName);
sb.Append("', currentUserEmail: '");
sb.Append(currentUserEmail);
sb.Append("', currentSite: '");
sb.Append(currentSite);
sb.Append("', currentTitle: '");
sb.Append(currentTitle);
sb.Append("'}</script>");
Response.Write(sb.ToString());
%>
....
</asp:Content>
We fetch the current user's name using the SPContext.Current property, which gives us a handle to the current HTTP request in SharePoint. Then we get the various items we need, such as the user's name, login name, web (current site name), and the publishing page's title.Once we have the values, we plug them into a JavaScript array that we build server-side. When the page loads in the browser, the array will be instantiated with the values we set using C#. We use a StringBuilder object for optimal performance because of the string concatenations.
So what does it look like when the page loads? Here it is:
<script type='text/javascript'>var currentElements = { currentUserName: 'Alex C', currentUserEmail: 'myemailid', currentSite: 'My Site Name', currentTitle: 'Page Title'}</script>
To use any of the array elements in jQuery or elsewhere, just call it via something like this: currentElements.currentSiteA final note: If any of the values will have a single quote in them, just escape the value using a .Replace("'","\'")on the string in C#.
14 September 2011
SharePoint tabs UI for web parts
Christophe Humbert's beautiful Easy Tabs for SharePoint works wonderfully well; it automatically generates tabs for the web parts on the page. You simply drop the code Christophe provides into a content editor web part (CEWP) and off you go.
In a current project, we needed the ability to have all pages show tabs without dropping a CEWP on every page. The code needed to be on a page layout for a publishing site. The challenge? Christophe's code traverses up the DOM from the current CEWP to find the parent container of the web parts; unless you use a CEWP, it won't work.
Some serious trial-and-error, as well as posting to the SharePoint group on StackExchange.com, provided the clues; we need to provide a direct reference to the parent container of the web parts. Here's the part of the code that was moving up the DOM tree:
In a current project, we needed the ability to have all pages show tabs without dropping a CEWP on every page. The code needed to be on a page layout for a publishing site. The challenge? Christophe's code traverses up the DOM from the current CEWP to find the parent container of the web parts; unless you use a CEWP, it won't work.
Some serious trial-and-error, as well as posting to the SharePoint group on StackExchange.com, provided the clues; we need to provide a direct reference to the parent container of the web parts. Here's the part of the code that was moving up the DOM tree:
var el=document.getElementsByTagName("SCRIPT"),p=el[el.length-1],sT,a,sep,tabRow;
do {p=p.parentNode;sT=p.innerHTML.split("MSOZoneCell_WebPart");}while (sT.length<4 && p.parentNode.id!="MSO_ContentTable")In the page layout, the web parts are in a Page Content control (PublishingWebControls:richhtmlfield), so here's the change to the JavaScript to reference that parent container:var p,a,sep,tabRow;Note that there's no need for the el variable or the do-while loop. You probably need to do some trial-and-error, using alert() statements to view the p.innerHtml and/or p.parentNode.innerHtml; this helped me discover what p was pointing to after the do-while and simply reference it directly.
p = document.getElementById('ctl00_PlaceHolderMain_ctl01__ControlWrapper_RichHtmlField');
11 August 2011
12 April 2011
08 April 2011
01 April 2011
Create a new window using custom jQuery function
For my current project, I needed to pop up a new window from specific anchor tags on the page. This provided the perfect opportunity to write some custom jQuery to handle this. I started with some research into creating jQuery function; Jeremy Martin's blog post got me started. Next, I got some inspiration from this popup window generator, though I could never get it working for my site.
So the jQuery function looks like this:
So the jQuery function looks like this:
/*Note the helper function isEmpty() which serves to check for null, undefined, or blank variables. The folks on StackOverflow.com helped with that function. To use the popWindow() function, ensure you've included the latest jQuery library on your page; add the above code in a script tag; then set the style class on your anchor tag or add an ID so you can reference the object; finally, call it on your page like this:
* Add a function to jQuery to automate popup windows.
*/
(function($){
$.fn.popWindow = function(options) {
// Declare some default values.
var defaults = {
width: 729,
height: 529,
left: 19,
top: 19,
location: 0,
directories: 0,
status: 0,
toolbar: 0,
menubar: 0,
resizable: 1,
scrollbars: 1,
url: '',
name: 'cms_win',
center: 0
};
// Merge the defaults with the options parameter.
var options = $.extend(defaults, options);
// For each of these objects...
return this.each(function(){
// Get a handle to this HTML object.
obj = $(this);
// Set the left and top if we're centering.
if (options.center){
options.left = (screen.width - options.width)/2;
options.top = (screen.height - options.height)/2;
}
// If user provided a URL, use that; otherwise use the HREF.
var url = (!jQuery(options.url).isEmpty()) ?
options.url : obj.attr("href");
// Concatenate the window.open() function's options.
var features = "width="+options.width+",height="+
options.height+",left="+options.left+",top="+
options.top+",location="+options.location+
",directories="+options.directories+",status="+
options.status+",toolbar="+options.toolbar+
",menubar="+options.menubar+",scrollbars="+
options.scrollbars+",resizable="+
options.resizable;
// Add an onClick() handler to this object.
obj.click(function(){
// On click, open a new window with these arguments.
window.open(url,options.name,features);
return false;
});
});
}
})(jQuery);
/*
* Add a function to jQuery to check null/undefined/blank
* status of object.
*/
(function($){
$.fn.isEmpty = function(){
return (typeof $(this) === "undefined" ||
$(this) === null ||
$(this) === "") ? true : false;
}
})(jQuery);
jQuery(document).ready(function(){
// Set all the objects with pop class to open in new window.
jQuery(".pop").popWindow({
center: 1
});
});In this case, I'm also taking advantage of the built-in center functionality to center the new window.
02 February 2011
Dynamically replace HTML5 video with Flash in Fancybox
For my current project, I needed to dynamically (based on whether the device supported HTML5 or not) replace HTML5 video tags with a Flash player. What made this more challenging was that the video player needed to be in a Fancybox.
A day's worth of coding resulted in the following JavaScript function. It's heavily commented so it should be self-explanatory. Drop me a comment if something doesn't make sense. You need to include the latest jQuery library for this to work.
Update: A few requests have come in for a version of the code to allow HTML5 videos on a page to be placed into a Fancybox. Here's the demo, with a very special thanks to Pipsqueak.
Here's the HTML code, with the JavaScript followed a little further down:
Update: The good folks at Long Tail Video provide a great HTML5 video tag reference.
A day's worth of coding resulted in the following JavaScript function. It's heavily commented so it should be self-explanatory. Drop me a comment if something doesn't make sense. You need to include the latest jQuery library for this to work.
function flashPopup(){
// Declare some variables.
var el = "";
var vidFileName = "";
var posterPath = "";
var placeHolderPosterPath = "";
var replacement = "";
var imgTitle = "";
var videoTag = "";
var boxId = "";
var flashId = "";
var dotPosition = "";
var swf = ""
// Loop over each video tag.
$("video").each(function(){
// Reset the variables to empty.
el = "";
vidFileName = "";
posterPath = "";
imgTitle = "";
placeHolderPosterPath = "";
replacement = "";
videoTag = "";
flashId = "";
swf = "";
// Get a reference to the current object.
el = $(this);
// Set some values we'll use shortly.
boxId = this.id + "_flashBox";
flashId = this.id + "_flashPlayer";
/*
Set the ID attribute of the first DIV in this element's parent's
parent. This "box" will have the Fancybox attached to it.
*/
el.parent().parent().find("div:first").attr("id",boxId);
/*
Fetch the MP4/M4V video from the <source> tags. Need to go to the
parent of the current tag to find them.
*/
el.parent().find("source").each(function(){
if ($(this).attr("src").indexOf("m4v") != -1 ||
$(this).attr("src").indexOf("mp4") != -1){
vidFileName = $(this).attr("src").substring($(this).attr("src").lastIndexOf("/")+1);
}
});
/*
IE (< 9) and older browsers use the Flash player, which overlays a 'Play' button
on the poster image by default; so we use a poster image that doesn't have
a play button. Otherwise we'd end up with a play button on top of a play
button.
We have an img tag inside the <video> tag which we'll use (by adding "-ie" to the
filename) for the Flash player's image attribute. The next two lines find the file
and its path.
*/
dotPosition = el.parent().find("img").attr("src").lastIndexOf(".");
posterPath = el.parent().find("img").attr("src").substring(0,dotPosition) + "-ie" + el.parent().find("img").attr("src").substring(dotPosition);
/*
Use the same image but this time don't add "-ie" to its name. This will be for the
main placeholder linked image; when the user clicks it, the Fancybox pops up with
the Flash player.
*/
placeHolderPosterPath = el.parent().find("img").attr("src");
/*
Fetch the image's title attribute, which we'll use for the linked image's title.
This will appear as the title on the Fancybox.
*/
imgTitle = el.parent().find("img").attr("title");
/*
Concatenate the linked image that will take the place of the <video> tag.
*/
replacement = "<a title='" + imgTitle + "' id='" + boxId + "' href='javascript:;'><img src='" +
placeHolderPosterPath + "' style='float:left; padding-left:5px; '/></a>"
// Replace the parent of the current element with the linked image HTML.
el.parent().replaceWith(replacement);
/*
The swfobject library can't be used with Fancybox (as far as I know). but
we can pass a Flash player of our own design into the Fancybox as its content.
Here, we concatenate the Flash player and point to the swfobject player.swf
file. We'll still use that player, but build our own OBJECT and EMBED tags.
*/
swf = "<object id='" + flashId + "' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' width='372' height='209'>" +
"<param name='movie' value='global/vid/player.swf' />" +
"<param name='quality' value='high' />" +
"<param name='wmode' value='opaque' />" +
"<param name='swfversion' value='6.0.65.0' />" +
"<param name='expressinstall' value='global/vid/expressInstall.swf' />" +
"<!--[if !IE]>--> " +
"<object type='application/x-shockwave-flash' data='global/vid/player.swf' width='372' height='209'> " +
"<!--<![endif]--> " +
"<param name='quality' value='high' /> " +
"<param name='wmode' value='opaque' /> " +
"<param name='swfversion' value='6.0.65.0' /> " +
"<param name=flashvars value='file=" + vidFileName + "&autostart=false&image=" + posterPath + "'>" +
"<param name='expressinstall' value='global/vid/expressInstall.swf' />" +
"<div>" +
"<h4>Content on this page requires a newer version of Adobe Flash Player.</h4>" +
"<p><a href='http://www.adobe.com/go/getflashplayer'><img src='http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' width='112' height='33' /></a></p>" +
"</div>" +
" <!--[if !IE]>--> " +
" </object> " +
" <!--<![endif]--> " +
" </object> ";
/*
Now attach a Fancybox to this item and set its attributes. Note that
we need to disable the autoDimensions for SWF files or you'll get a
long, narrow box showing. We then set the width and height (which
usually requires some trial-and-error).
The two functions for onComplete and onClosed are custom code that
stop/start the AnythingSlider when the user opens the Fancybox and
closes it, respectively.
This entire function acts as an onClick handler for the object to
which it's attached (hence the "end click function" comment).
*/
$("[id="+boxId+"]").fancybox(
{
'content' : swf,
'autoDimensions' :false,
'height' :236,
'width' :375,
'padding' : 5,
'showCloseButton' : true,
'enableEscapeButton': true ,
'titlePosition' : 'outside',
'onComplete' : function() {stopSlider()},
'onClosed' : function() {startSlider()}
}
); // end click function
});
}Update: A few requests have come in for a version of the code to allow HTML5 videos on a page to be placed into a Fancybox. Here's the demo, with a very special thanks to Pipsqueak.
Here's the HTML code, with the JavaScript followed a little further down:
<!doctype html>Replace the line above in the HTML that says "Add inline script code here." with this JavaScript:
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Fancybox HTML5 Video</title>
<meta name="description" content="">
<meta name="author" content="alex cougarman">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="js/jquery.fancybox-1.3.4/fancybox/jquery.fancybox-1.3.4.css" type="text/css" />
<!--
In addition to the stylesheet for the Fancybox
component, the following styles control the
look of the page and the linked image.
-->
<style type="text/css">
body {
margin:50px 0px; padding:0px;
text-align:center;
font:11px verdana, arial, helvetica, sans-serif;
}
#main {
width:500px;
margin:0px auto;
text-align:left;
padding:15px;
border:1px dashed #333;
background-color:#eee;
}
.img-link
{
border:1px solid #999;
padding:5px
}
</style>
<!--
Include the jQuery library, followed by the
Fancybox and the Easing libraries.
-->
<script type="text/javascript" src="js/jquery.fancybox-1.3.4/jquery-1.4.3.min.js"></script>
<script type="text/javascript" src="js/jquery.fancybox-1.3.4/fancybox/jquery.fancybox-1.3.4.pack.js"></script>
<script type="text/javascript" src="js/jquery.fancybox-1.3.4/fancybox/jquery.easing-1.3.pack.js"></script>
<!-- Add inline script code here. -->
</head>
<body>
<div id="main">
<h3>HTML5 Video in a Fancybox</h3>
<div>
<video id="vid-1" width="480" height="360" poster="btf.jpg" controls preload>
<source src="btf.mp4" type="video/mp4">
<source src="btf.ogv" type='video/ogg; codecs="theora, vorbis"'>
</video>
</div>
</div>
</body>
</html>
<script type="text/javascript">Replace the two videos (btf.mp4 and btf.ogv) with your own HTML5-compatible videos and try it. Demo, with a very special thanks to Pipsqueak.
$(document).ready(function(){
fancyPopup(); // Replace the video tags.
});
/*
Function finds the video tags on the page. For each,
it fetches the video tag's HTML and replaces it with
a linked image that, when clicked, pops up a Fancybox
containing the HTML5 video.
*/
function fancyPopup() {
// Declare some variables.
var el = "";
var posterPath = "";
var replacement = "";
var videoTag = "";
var fancyBoxId = "";
var posterPath = "";
var videoTitle = "";
// Loop over each video tag.
$("video").each(function () {
// Reset the variables to empty.
el = "";
posterPath = "";
replacement = "";
videoTag = "";
fancyBoxId = "";
posterPath = "";
videoTitle = "";
// Get a reference to the current object.
el = $(this);
// Set some values we'll use shortly.
fancyBoxId = this.id + "_fancyBox";
videoTag = el.parent().html(); // This gets the current video tag and stores it.
posterPath = el.attr("poster");
videoTitle = "Play Video " + this.id;
// Concatenate the linked image that will take the place of the <video> tag.
replacement = "<a title='" + videoTitle + "' id='" + fancyBoxId + "' href='javascript:;'><img src='" +
posterPath + "' class='img-link'/></a>"
// Replace the parent of the current element with the linked image HTML.
el.parent().replaceWith(replacement);
/*
Now attach a Fancybox to this item and set its attributes.
This entire function acts as an onClick handler for the object to
which it's attached (hence the "end click function" comment).
*/
$("[id=" + fancyBoxId + "]").fancybox(
{
'content': videoTag,
'title': videoTitle,
'autoDimensions': true,
'padding': 5,
'showCloseButton': true,
'enableEscapeButton': true,
'titlePosition': 'outside',
}); // end click function
});
}
</script>
Update: The good folks at Long Tail Video provide a great HTML5 video tag reference.
09 September 2010
Watch out Java, here comes JavaScript
http://www.infoworld.com/d/developer-world/watch-out-java-here-comes-javascript-799
The benefits of JavaScript as a server-side language are clear and striking. It allows Web application developers to implement their entire code base using a single syntax, reducing the clutter and confusion of typical Web apps. JavaScript's performance is increasing at a breakneck pace, which has built-in benefits for developers. Its event-driven programming model makes building parallel applications easy and logical. And JavaScript itself has matured into a fine language, with features that support both the object-oriented and functional programming styles.
27 August 2010
15 July 2010
12 July 2010
Explaining JavaScript scope and closures
Closures are a critical part of JavaScript libraries; this tutorial explains scope and closures: http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/
Another great article on the same subject from the always impressive SmashingMagazine.com: http://www.smashingmagazine.com/2009/08/01/what-you-need-to-know-about-javascript-scope/
And more here: http://blog.morrisjohns.com/javascript_closures_for_dummies.html
Another great article on the same subject from the always impressive SmashingMagazine.com: http://www.smashingmagazine.com/2009/08/01/what-you-need-to-know-about-javascript-scope/
And more here: http://blog.morrisjohns.com/javascript_closures_for_dummies.html
22 June 2010
Subscribe to:
Posts (Atom)