giza: Giza White Mage (Default)
There are a number of folks out there who use the Firebug extension for FireFox so they can debug webpages. Firebug also includes a Javascript console so you can execute arbitrary Javascript code against the current page.

If you're a fan of the jQuery library, there's a way you can use that in Firebug (first documented here):

var j = document.createElement("script");
j.onload = jsCallback;
j.src = "http://code.jquery.com/jquery-latest.pack.js";
document.getElementsByTagName("head")[0].appendChild(j);


Note that line I have in bold? That fires a function called "jsCallback()" after jQuery is successfully loaded.

"Why a fancy callback?"

As I learned the hard way, if I were to just put Javascript code following the jQuery code, it might get executed before jQuery is successfully loaded, leading to errors. While I could just re-run the code (as jQuery would already be loaded), I was looking for a better solution to the problem, and this is what I came up with.

"So what can I do this callback?"

I'm glad you asked. One way using jQuery in Firebug comes in quite handy is if you want to dissect another web page. For example, let's say you want to run a Google search, and extract the URLs in the search results. Here's how to do it:

/**
* This is executed after jQuery is successfully loaded.
*/
function jsCallback() {

    var e = jQuery("a.l");

    var output = "";
    e.each(function() {
        output += jQuery(this).attr("href") + "\n";
    });

    alert(output);

}

var j = document.createElement("script");
j.onload = jsCallback;
j.src = "http://code.jquery.com/jquery-latest.pack.js";
document.getElementsByTagName("head")[0].appendChild(j);



"I could write $.get() calls to load Google's search results!"

Good luck with that. FireFox won't let you do that due to the same-origin policy.

"Well, how about if I get Google's search results in JSONP format?"

Um, good luck with that, too. You won't get very far without an HTTP referrer header, I'm afraid.

"So if I want to do this on an ad-hoc basis, I have to dissect the Google search results page?"

Yep, exactly.


Got any other tricks you find really useful to do with jQuery in Firebug? Let me know in the comments! 
 
giza: Giza White Mage (Default)
I spent about 2 hours tonight trying to figure out why my modal dialog box refused to work under Internet Explorer 6.0. The symptom was that in addition to the rest of the webpage being grayed out, the modal box was also being grayed out. Not good.

The culprit turned out to be this bit of CSS:

.jqmWindow {
   position: fixed;
}
Having the position set to "fixed" will screw you every single time. (Plus, the box displaces your page content, instead of appearing over top of it, like you would expect with a high z-index value.)

The fix is to change the position attribute from fixed to absolute. Once you do that, it behaves as expected in both MSIE 6 and FireFox.

Other than that little problem, the jqModal library is a nice little library which can create pop-up boxes within a webpage that are part of the same window. It can also "gray out" the current contents of the page and force the user to click in the box before continue. Very handy to have, if you want to make the user agree to the T&Cs of a particular website.
giza: Giza White Mage (Default)
Today's programmatic venting is brought to you by Internet Explorer's implementation of the setTimeout() function under Javascript.

What is setTimeout()?

setTimeout() schedules an arbitrary function call for some point in future. This is useful when you have functions that do repetitive tasks some milliseconds apartment, but not constantly.

The reason why this is used instead of a simply while (true) { ... } loop is because Javascript is a single-threaded language. So if you tie up the interpreter by executing one piece of code over and over, nothing else in the browser gets a chance to run. setTimeout() allows other pieces of Javascript (or browser events, such as clicking on a button) to run, while guaranteeing that your code will be executed at some point.

Sounds cool. How do I use setTimeout()?

Simple, like this:

setTimeout(function_name, msec);

This will cause a function called function_name to execute a certain number of milliseconds in the future.

For functions that don't need data passed into them, that works great. But what if you want to pass in parameters? In FireFox, you would do this:

setTimeout(function_name, msec, arg1);

And this works great. It will call the function called function_name again in the specified number of milliseconds. Except, MSIE doesn't like this. And rather than throw an error, it just ignores the additional arguments. So when function_name gets called again, its argument is now undefined, and choas ensues.

[Edit: It has since been pointed out to me that the most recent draft of the spec does not allow for additional parameters to setTimeout(). Okay then, but why isn't MSIE at least throwing an error? Silently accepting additional arguments and then just throwing them away is just plain stupid.]

So how do I work around this annoyance?

Closures. Up until now, I thought that closures were very geeky, and used only by CS people who were working on their PhDs. Then I saw this:

setTimeout(function() {function_name(arg1)}, msec);

Wait, what? What's going on there? Well, it might be a little easier to understand if I write it like this:

var f = function() {function_name(arg1); };
setTimeout(f, msec);


What's happening there is a variable called "f" is created, which is actually an anonymous function. That function in turn contains a single line of code: function_name(arg1); -- a call to the function we really want to call, with our specified argument. Note that all we have done so far is define a function that calls our target function. We have not executed either that function or the target function -- the target function is essentially "frozen in time". This is a very important concept, and if you've never done this before, you will have difficulty wrapping your brain around it. :-)

To get a better idea of what's going on, in this case, you could also execute the variable f as a function, since it now *is* a function for all intents and purposes:

f();

Bringing this all together, in the above example, the end result is that the function function_name will be executed after the specified interval, with the desired argument. And this will work in both MSIE and FireFox.

Just out of curiosity, what is a practical application of this function?

I'm glad you asked! As I mentioned above, Javascript is single-threaded. This means that a loop that takes a long time to run can cause the browser to appear to "freeze up" or become unresponsive, which detracts from the overall user experience. A perfect example of this would be populating a div with rows of data retrieved via AJAX. Writing 1,000 rows into that div takes about 3.2 seconds on my machine, during which the browser will not respond to commands.

What I did in my little test was instead of printing each row as it was retrieved, I instead stored them in an array. I then wrote a function which shift()ed and printed only 50 elements from that array. After 50 elements were printed, it then checked to see if there were any elements left in the array. If there were, it would call setTimeout() with itself and the array inside a closure, to be run again in 10 millseconds. The end result took a little longer, 3.5 seconds, but resulted in a much more responsive browser, and happier users.

Share and enjoy!

Source: Passing parameters to a function called with setTimeout, by Bryan Gullen
giza: Giza White Mage (Default)
Making form variables into arrays in PHP easy. One only needs to add "[]" to the name of the variable to make this happen. Example:
<input type="text" name="search[name]" id="search[name]" />
<input type="text" name="search[age]" id="search[age]" />
<input type="text" name="search[city]" id="search[city]" />
<input type="text" name="search[state]" id="search[state]" />
<input type="text" name="search[country]" id="search[country]" />
When the form is submitted and the PHP code on the processing page is run, there will be a handy little array called $search. This variable can then be passed into additional functions, looped through, etc. It's way easier than working with 5 separate variables.

Lately, I've been using jQuery in some of my web development. It lets me "do more with less", as they say. One very easy way to access specific HTML entities in a document is with pound-notation. Examples:
$("#foo").addClass("required");
$("#bar").hide();
$("#username").css("background-color", "blue");
If you just groaned, then you know what's coming. Sure enough, jQuery has issues with using square brackets in pound-notation. It seems that square brackets are used by jQuery itself as attribute selectors.

It took me some time, but I finally found a workaround, which was the real reason behind writing this journal entry -- so as to save myself and other folks time from having to find this solution again in the future. Examples:
$("[id='search[name]']").hide();
$("[id='search[address]']").show();
$("[id='search[country]']").css("color", "green");
That's about it. Happy jQuerying!
giza: Giza White Mage (Default)
Here's a little talk from the gentleman who created the jQuery javascript library. He talks about considerations in designing an API and gets into some of the stuff that jQuery went through as it evolved.



It's about an hour long, and worth a look. He has pretty good Powerpoint slides, and I just skipped through some of the talking to get to those. :-)

Profile

giza: Giza White Mage (Default)
Douglas Muth

April 2012

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930     

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags