JasonWyatt

This blog is full of stuff, and things.

Find my resume.

permalink

Make alert() behave like console.log(), when possible..

The other day, @mrspeaker tweeted this:

c’mon alert() - just magically be a _bit_ more like console.log and you’d save me a lot of time

This got the creative juices flowing a little and I coded up a small script to overwrite how alert() operates and, if available, it will choose to behave exactly like console.log() by writing to the console instead of popping up the dialog (if it’s available). It still needs some work to support formatted strings in alert() dialogs, for when console.log() isn’t available.

var oldAlert = alert;
alert = function(){
    if(window.console != null){
        console.log.apply(null, arguments);
    } else {
        oldAlert.apply(null, arguments);
    }
};

What this means now is that you can exclusively use alert() in your code and not have to use console.log() and worry about your JavaScript breaking in browsers that don’t have Firebug or a console.

Find it on GitHub, here.

permalink

Use jQuery to Make Your DOM Editable!

I was playing around with jQuery a bit last night on my flight from Raleigh to Tampa and put together a pretty cool little piece of code that will let you click any paragraph on the page and edit it in place. I’d say it needs some more work before it could be a plugin (for example, adding functionality to support updates to the server), but it’s not too bad:

<script type="text/javascript" src="./jquery-1.3.2.js" charset="UTF-8"></script>
<script type="text/javascript">
    // <!--
    $(document).ready(function(){
        $("p").live("click", function(){
            var node = $(this);
            var html = node.html();
            
            var editNode = $('<textarea/>');
            editNode.text(html);
            editNode.css('display', node.css('display'));
            editNode.width(node.width());
            editNode.height(node.height());
            editNode.blur(function(){
                node.html($(this).attr("value"));
                $(this).before(node);
                $(this).remove();
            });
            
            node.before(editNode);
            editNode.focus();
            node.remove();
        });
    });
    // -->
</script>

You can see it in action on the demo page.

permalink

Dynamically Instantiate a Dojo Class At Runtime

Need to create an instance of a class in Dojo without knowing what that class is ahead of time? Will you only have the name of the class that you want to instantiate? Check this out:

/**
 * Create a new instance of a Dojo class.
 *
 * @param className
 *    (String) A fully-qualified name for class, such as 
 *    "my.pack.age.Class"
 * @param constructorSettings
 *    (object) An object that will be passed on to the 
 *    class's constructor.
 */
function instantiateDojoClass(className, constructorSettings){
    try {
        dojo.require(className);
        
        /*
         * Eval the class name to get a reference to the 
         * function, then call it as a constructor using the 
         * constructorSettings object as an argument.
         */
        var obj = new (eval(className))(constructorSettings);
    } catch (e){
        /*
         * Handle any errors that might happen.
         */
        if(console){
            console.error("Could not instantiate %s: %s", classsName, e.message);
        } else {
            alert("Could not instantiate "+className+": "+e.message);
        }
        throw e;
    }
}

The real trickery here is in the line:

var obj = new (eval(className))(constructorSettings);

This evaluates the string className to retrieve a reference to the dojo function that was ‘created’ by the call to dojo.require(..), then calls that function as a constructor by using the new keyword. It passes the constructorSettings object on to the constructor, just like you’d do with any normal dojo instantiation.

permalink

HTML 5 Canvas - Mandelbrot Fractal

I’ve been really interested in HTML 5’s new <canvas> feature and have been trying to think of excuses to use it (like on Friday when I made jQReflect). Today I felt it’d be fun to do an old classic: a mandelbrot fractal renderer.

It turns out that JavaScript is still pretty slow, even after all the advances lately in browsers’ JS engine technology. Drawing to the canvas was not my performance bottleneck, however. The sheer number of calculations I had to perform is what slows it down.

Check out the demo.

permalink

Getting computed style

nonowarn:

When the computed style of arbitrary element is needed,

var computedStyle = document.defaultView.getComputedStyle(element, null);

should work. But in IE, it doesn’t. But non-tested “cross-browser” version is here:

function getComputedStyle(el) {
   var dview = document.defaultView;
   return dview ? dview.getComputedStyle(el, "") : el.currentStyle;
}

References:

Nicely done! I’ll have to play with this tonight after work..

permalink

Footnotes.js - Automatic Footnote Creator

This is another project I worked on a few months ago. It’s a script that will automatically scan your document for footnote anchors and generate links to the footnotes you specify in an ordered list anywhere on the page. It requires jQuery to operate.

Tutorial

  1. Download the zip and extract it into a folder within your site somewhere. For the sake of this tutorial we’ll say you unzipped it into the directory /httpdocs/footnotes, where /httpdocs is the root of your web site and is where the HTML file we’re going to use footnotes with resides.
  2. In your HTML document’s <head> section add the following lines:

    <link ref="stylesheet" href="./footnotes/footnotes.css" type="text/css" charset="UTF-8" />
    <script type="text/javascript" src="./footnotes/footnotes.js" charset="UTF-8"></script>
  3. There are two main areas to think about when you want to reference a footnote:

    • the text that is referring to the footnote,
    • and the footnote itself.

    With footnotes.js, you refer to a footnote by using an anchor tag and you store your footnotes in a list.

    Depending on the settings you specify within footnotes.js, what you need to do can vary, but we’ll assume you stuck with the default values.

    Assume you have the following paragraph in your HTML (from Jules Verne’s Around the World in Eighty Days):

    <p>
      Mr. Phileas Fogg lived, in 1872, at No.7, Saville Row, Burlington Gardens, the house in which Sheridan died in 1814. He was one of the most noticeable members of the Reform Club, though he seemed always to avoid attracting attention; an enigmatical personage, about whom little was known, except that he was a polished man of the world.  People said that he resembled Byron - at least that his head was Byronic; but he was a bearded, tranquil Byron, who might live on a thousand years without growing old.
    </p>

    And assume we want to add a link to a footnote after the first sentence that says this:

    At least we think it was the house where Sheridan died, but we're not 100% sure.

    As well as another footnote referenced after each mention of Byron that has a link to the Wikipedia article about Byron:

    See the article at <a href="http://en.wikipedia.org/wiki/George_Gordon_Byron,_6th_Baron_Byron">Wikipedia</a> to learn who George Gordon Byron was.

    We would introduce three anchor tags into the paragraph which would look like so:

    <p>
      Mr. Phileas Fogg lived, in 1872, at No.7, Saville Row, Burlington Gardens, the house in which Sheridan died in 1814.<a class="footnote"></a> He was one of the most noticeable members of the Reform Club, though he seemed always to avoid attracting attention; an enigmatical personage, about whom little was known, except that he was a polished man of the world.  People said that he resembled Byron<a class="footnote"></a> - at least that his head was Byronic; but he was a bearded, tranquil Byron<a class="footnote" name="2"></a>, who might live on a thousand years without growing old.
    </p>

    If you notice, you’ll see two different kinds of anchor tags we added there:

    • One with only a class attribute “footnote” - These will get auto-numbered by the script in the order in which they appear. This is useful if you know your references will be in the same order as the footnote list you’re using.
    • One with two attributes: class and name - The class attribute is still set to “footnote”, but the name attribute is identifying the “target” footnote to reference (I would’ve loved to make the attribute be the “target” HTML attribute, but in XHTML Strict there is no such thing).

    Of course we also need to add a list containing the content of our actual footnotes (you can put it anywhere):

    <ol id="footnotes">
      <li class="footnote">
        At least we think it was the house where Sheridan died, but we're not 100% 
        sure.
      </li>
    
      <li class="footnote">
        See the article at 
        <a href="http://en.wikipedia.org/wiki/George_Gordon_Byron,_6th_Baron_Byron">Wikipedia</a>
        to learn who George Gordon Byron was.
      </li>
    <ol>
  4. There we go, you’re done!

permalink

Bookmarklet which loads external script

nonowarn:

Demo

javascript:void((function(D) {
  var s = D.createElement('script');
  s.src = "http://where.script/is";
  D.body.appendChild(s);
})(document))
permalink

JavaScript escapeHTML String Function

Modify the prototype of all string objects in the JavaScript runtime to introduce a new function called escapeHTML() which will replace all ampersands with &amp; and all <’s and >’s with &lt; and &gt;, respectively:

String.prototype.escapeHTML = function(){
    var result = "";
    for(var i = 0; i < this.length; i++){
        if(this.charAt(i) == "&" 
              && this.length-i-1 >= 4 
              && this.substr(i, 4) != "&amp;"){
            result = result + "&amp;";
        } else if(this.charAt(i)== "<"){
            result = result + "&lt;";
        } else if(this.charAt(i)== ">"){
            result = result + "&gt;";
        } else {
            result = result + this.charAt(i);
        }
    }
    return result;
};

I ran into a gotcha with IE while developing this, make sure you never try to reference characters in a string object with myString[charIndex] - it will always end up undefined. Instead, use the string function myString.charAt(charIndex) for cross-browser application.

Edit: I just did a quick google search for “javascript escapeHTML” and learned that the Prototype Framework already has something like this. I guess I re-invented the wheel a little here. Oh well, it was still fun.

permalink

Built-in Logging Capability for Strings in JavaScript

I really like playing around in JavaScript a lot, and sometimes this involves hacking with the built-in prototypes.

Today I found myself wanting an easy to use way to log messages, errors, warnings and fire off alerts directly from a string object. (mostly just to make things look prettier, I’ll admit) I decided to tweak String’s prototype directly and add five new functions: log(), warn(), debug(), error(), and alert():

String.prototype.log = function(){
    console.log(this+"");
};
String.prototype.error = function(){
    console.error(this+"");
};
String.prototype.debug = function(){
    console.debug(this+"");
};
String.prototype.warn = function(){
    console.warn(this+"");
};
String.prototype.alert = function(){
    alert(this+"");
};

Now you can print text out to the console simply by calling log() on any string:

"This is the text I want to log".log();

Keep in mind you can always tweak the internals of these functions so that they’ll do whatever you want. (e.g. have them append to the innerHTML of a particular DOM node)