These are code snippets and rambling musings about Javascript.
I wrote this before I practiced with the module pattern and with adding methods to prototypes. So this article doesn't explain a best practice. Still, it's a pretty good pattern. See also the Javascript Patterns book.
JS has closures, and with closures, you can create functions that return functions as values. Erm. So what? Well, the closure is not just a function, but also its "environment". I think the term in JS is "local variables". So the function carries with it, a bunch of its local variables.
This means you can create a function that "remembers" some values you've passed to it. Here's an example:
foo = function (x) { return function (y) { return x + y; } }
To use it, you do this:
addone = foo(1); addten = foo(10);
Now, addone(5) returns 6. addten(6) returns 16.
If that doesn't make sense, look at the code again. The body of foo is "return function (y) { return x + y; }".
Well, x, in this case, is a local variable that you passed into foo().
So the code of addone is really something like this: "function addone(y) { var x = 1; return x + y; }".
You may need to re-read the above.
The point here is that the function creates another function, and that function is slightly tailored to do something. Now, that might seem pointless, but it's not. It's a lot like objects and methods, except instead of creating a lot of objects, you now can create a lot of functions that contain some data.
If you think about it, the jQuery and current JS style of programming involves creating a lot of anonymous functions and attaching them as handlers onto the DOM objects. A function-making function is really handy, because you can go through a DOM and attach a unique handler function to each object.
Here's part of a function I'm working on. It might not work:
SW.map.listFormatterMaker = function (prefix) {
return function (d) {
$.template('MainInjectList',
' ${name} ${city}, ${address}');
document.getElementById( prefix+'-list' ).innerHTML = '';
document.getElementById( prefix+'-list2' ).innerHTML = '';
a = d.slice(0,5);
b = d.slice(5,10);
a.forEach(SW.listInserter( prefix+'-list')); // this is another function-making function
b.forEach(SW.listInserter( prefix+'-list2')); // ditto
}
}
It's a little long, but it's a function that returns a "listFormatter". A "listFormatter" is a function that formats some data that's passed do it.
It takes a 'prefix' parameter. The HTML includes two UL elements that have IDs of 'map-list' and 'map-list2'. I'm using a naming convention, and the prefix is "map".
When SW.map.listFormatterMaker('map') is called, it returns a function. That function, when passed some data, d, it'll format and insert the data into my page.
Before inserting the data, it splits the array into two (for two columns), and then inserts into -list and -list2, separately. To do the insertion, it uses forEach and another function-making function called listInserter().
So, if I want to re-use this code, I could create some HTML with IDs of 'map2-list' and 'map2-list2' and pass 'map2' as the prefix. Then, calling SW.map.listFormatterMaker('map2'), will make a different function that will do the same thing for a different area of my page.
It's used like this:
$.getJSON('foo.php',{arg:1},SW.map.listFormatterMaker('map'));
$.getJSON('bar.php',{arg:1},SW.map.listFormatterMaker('map2'));
So that's 2 function calls that are visible to the user, but the result is that four different areas of the page get updated with data. Each area is updated by anonymous functions.
You might be wondering if this can be done without this function-making-function business. I think it can, but it would be a lot more code. You would have to write a customized data handler for each call. With this style of programming, you avoid that.
Also, it's not just useful for specifying a selector. You can also pass it functions, so it's possible to create functions that have different behaviors depending on the functions passed into the function-maker.
The attached HTML page is a password generator that creates a page of random 10-character passwords. It helps you manage one password per website, so a password leaked for one site doesn't get used on other sites. To use it, click and view the file.
You can also download it and use it - it's all done with Javascript so there's nothing that requires the server.
To use it, just keep the printed page in a safe place. Make a copy and store it in a fireproof safe or safe deposit box. As you use each password, make a note of the site. You may not want to use the full site URL. It doesn't matter. You might even try to obfuscate the site name or use an abbreviation. You have three blank columns so you can put in some fake data in there to add chaff, which is junk data meant to mislead someone who gets this paper.
You can also do tricks, like ignore one letter in the password. So you have 9 character passwords instead of 10 character passwords. If the password list is lost or stolen, the guesser would have to guess which character is being dropped from the actual password.
You can transform: perhaps the first character is reduced by 1, so B becomes A, 8 becomes 7, etc. You can transpose - the first two characters can be swapped, so 1} becomes }1.
Every year or so, you can change your passwords and clean up your lists (doing things like alphabetizing them. You might keep the old lists as "decoys". Repeated failed logons will cause some sites to lock out the account. This is another kind of chaffing, where you "fluff up the haystack" and hide your needle in it.
The real password and url is discoverable, but it should be hard for someone to figure out.
See also: http://en.wikipedia.org/wiki/Password_strength#Creating_and_handling_passwords.
| Attachment | Size |
|---|---|
| randompasslist.html | 1.22 KB |
Here's a bit of PHP code that emits javascript. The javascript emits an email link, but coded in Javascript, so that most spiders won't be able to get your email address for spamming.
<?php
function printEmailAddress( $email )
{
$parts = explode( '@', $email );
echo ' var d = document;';
echo 'd.write("");';
echo 'd.write("'.$parts[0].'");';
echo 'd.write("@");';
echo 'd.write("'.$parts[1].'");';
echo 'd.write("");';
}
printEmailAddress("fake@mail.com");
?>
Normally, you should use canned Javascript or canned PHP modules to implement web features, but sometimes, that can suck. Typically, these products, if they're popular, start to suffer from feature bloat. Such was the case with some code for "interstitials", which are those ads that pop up on some web pages, interrupting your reading. Popups have been around a long time, and the drop-in code is just really huge.
Nowadays, you can assume that you'll have at least one JS library installed on the site. I started with Dojo, and now use jQuery. There's also Scriptaculous on top of Prototype (I'm kinda iffy about those), and Mootools.
So you can immediately cut code size by using the library, which is large, but can be cached -- if you link to it from one of the CDNs like Google -- and is reused for other things. Then, you can start looking at libraries.
The best interstitial library seems to be Shadowbox.js. It just looks nice.
Of course, sometimes, you just want to make your own, and you need special behaviors. In my case, I needed a form that integrates with an external site, not a thumbnail that expands, so Shadowbox wasn't a great fit. I just coded it by hand, and learned some more jQuery and CSS. To top it off, the code is a little smaller.
The interstitial ad feature is attached. If you need more explanation, please ask in a comment, and I'll do my best to accomodate.
May-Jun 2012: 80, pagerank 1 for interstitial jquery ad
| Attachment | Size |
|---|---|
| inter.zip | 30.05 KB |
So I'm working on a small "speech bubble" library, and needed to delay hiding of the bubble. It's not that it was required, but it was a pain in the butt figuring out how to arrange the event handlers on the different elements so that you don't end up with a situation where you get a flickering bubble because you hide the bubble, and that fires a mouseover event that, in turn, displays the bubble again. That fires a mouseout event that causes the bubble to be hidden.
The usual right way to fix this is to detect the mouse moving into the area around the hotspot, and when it does that, hide it. My cheap fix is to just delay the hiding, and if the mouse happens to enter another element that requires the bubble to be displayed, the handler for this other element can cancel the hide.
A delay is also "nice" because it also gives the user a chance to roll back if they overshoot a target a little bit.
Here's the code fragment to implement a delay:
var hide = function () {
this.bubble.style.display = 'none';
}
var delayedHide = function() {
(function (x) {
x.hideInProgress = setTimeout(function () {x.hide()},250);
})(this);
}
var cancelHide = function() {
clearTimeout(this.hideInProgress);
}
The one really weird part is in delayedHide. What this does is construct a function that will call setTimeout(), then immediately call it. That calls setTimeout(), which registers the timeout handler to fire off in 1/4 second. Why not just call it like this?
this.hideInProgress = setTimeout(function () {this.hide()}, 250);
Well, the problem is that "this" changes between the two calls. When it's called from the bubble object (i.e. b.delayedHide() ), "this" is set to the object. When the timeout happens and the function's called by the system, I think "this" is set to window. Anyway, it's a different "this". "this" may not even exist. We're screwed.
So what we do, instead, is use a function to create a closure. A closure holds is local variables. So, what's happening is that (function(x) { ... })(this) is setting the local variable x to = this. Then, when function(){x.hide()} is created, it also carries the local variable x within the closure. That's because the closure contains the local variables in the scope in which is was defined.
After the call, the outer function wrapper is thrown away, but the inner one is stored away in window, ready to be called in 250 milliseconds.
A JavaScript Module Pattern is a fantastic example of how to use closures.
Javascript Closures has more detailed information.
Douglas Crockford brought the style over to JS, and his site has a lot of important articles about Javascript hacking (as a functional language).
A good description of closures is part of Blocks and Closures in Ruby an interview with Matz.
This video, Advanced Topics In Programming Languages: Closures For Java with Neal Gafter has a pretty detailed explanation about implementing closures in Java.
Last but not least, PHP 5.3 will have closures. What's new in PHP by John Mertic at IBM developerworks details the feature. The PHP RFC also has good examples.
| Attachment | Size |
|---|---|
| closure.png | 12.65 KB |
Joel on Software has a good article that explains functors, the purpose of passing functions as paramters, and leads into an explanation of map/reduce and parallel computing. These ideas are explained in Javascript, but also apply to Lisp, Scheme, and Perl (see the Mark Jason Dominus book). All these languages are functional programming languages, where functions are objects (or objects are functions).
(Add examples of functional programming here.)
Unfortunately, PHP, the other language covered here, has only half-baked functional programming. See the Function Handling Functions section of the manual.
Checkboxes work well if you're dealing with a few choices, but stop working so well when there are many options, and only a few are selected. SelectAdd is some code that will display a CSS/JS/DHTML widget that makes it look like you're adding selections to a list.
This is just a demo script. It doesn't include any integration with a database backend.
| Attachment | Size |
|---|---|
| selectadd.zip | 2.89 KB |
This page reads your timesheet, which you paste in below, and adds up your hours. It's designed to work with somewhat organized data, in a format that I've used for years.
Do not type your timesheet into this page. You will lose your data! Use something like "Stickies" or some other notetaker, or Notepad, instead. Copy your data into this page, and use it as a calculator and timesheet formatter.
It's written in Javascript, and requires a Netscape 4 or later browser that supports regular expressions. It's pretty much all about regular expressions. There's no PHP or Perl or anything like that involved. The script was written by John Kawakami and is in the public domain.
If you're interested in regexs, check out a refcard at Visibone. I used that page to make this page. (The cards are a good cheap gift for your local webhead.)