Posts Tagged ‘JavaScript’

Failed half-hour project

Thursday, June 25th, 2009

My attempt at a half-hour project before going to sleep failed. It took a little more than a half-hour, and my input of the following:

      version proto

      character paul
        image paul.png
      end

      character angie
        image angie.png
      end

      angie says I thought you were going to bed!
      paul say But I really wanted to try and write a comic markup language prototype.
      angie says What? What the heck is wrong with you? Go to sleep.
      paul says Just give me a half hour.
      angie says Ok, fine, but only a half hour. Crazy person.

only resulted in the following output:

Unrecognized command at line 3: "character"

Ah well, there’s always tomorrow…

Python DOM HTML functional

Sunday, January 13th, 2008

DOM HTML Progress

Well, I’ve made some progress on the HTML layout engine, but it still isn’t complete enough to run yet.

When I got to the point where I needed to call ViewCSS.getComputedStyle from the DOM, I stopped to actually implement it, and decided that it was a good time to actually see if the DOM HTML code I had written would run.

It didn’t, of course.

So I spent some time fixing all the little bugs here and there, and set up some test code to pull a page from the internet and parse it into a full HTML DOM tree.

Since I’m using pxdom’s parsing functions and pxdom only knows how to parse proper XML, I also run the HTML through the python tidy lib first to ensure that it’s proper XHTML. Without doing that I couldn’t even parse the Google home page.

Here it is if you’d like to check it out. It needs pxdom to work. The parseString function will take a string containing HTML and return an HTMLDocument.

Right now it’s usable for manipulating and traversing the DOM with all the attributes you are used to being able to access from Javascript, and if you combine it together with this simpleget module (requires domhtml and utidy from above), you can use it for some basic web scraping purposes.

Remember, it is basically pre-alpha code, since I haven’t tested everything yet. I might get around to writing up some unit tests at some point, but until then I can’t guarantee that there are no errors.

JavaScript update

I didn’t spend all my time in the last couple of days just fixing up my DOM HTML implementation. I also did some research on JavaScript interpreters, and I think I’ve decided that I’m going to wrap SEE, a JavaScript interpreter written in C, with a Python module and use it for the scripting engine for my browser.

I considered using Spidermonkey, but after looking through the documentation for each, SEE seems like it will be much easier to wrap, and as far as I can tell, it supports JavaScript exceptions in an easier-to-use (and easier-to-integrate-with-Python-exceptions) way than Spidermonkey does.

SEE also handles memory management for you and you can fully separate interpreter instances so you don’t have to worry about thread safety, which is two less things to have to worry about.

Quick Python Browser update

Friday, January 11th, 2008

A quick update since I’ve not posted anything for over a week now.

I’ve written some, and outlined a bunch more, of the code for the browser layout engine.

I don’t have a name for the browser yet, but there are a few ideas floating around.

I’m considering my options for a JavaScript Engine. There are several implementations in C or some such similar language. There’s also the possibility of a translator into Python, which could then be bytecode compiled and run inside a sandbox environment. Or a pure Python implementation..but I think that would be too much work.

I’m going to be sure to keep the layout engine separate from the rendering engine (or as much as possible, at least), so that I can change my mind later about what I want to use if I need to.

I will probably have more to talk about tomorrow or Saturday, but I needed to break the silence.

As an added bonus, and to make this post longer, here’s the output of the really crappy, incomplete HTML rendering engine that I hacked together in a single night for a class project (click the image for the full page render):

Old Renderer Test Thumbnail

Notice the lack of padding and the failure of most lines to wrap properly. Hey, I wrote it in a very short period of time. The point was to write a program which was object-oriented, not one that did anything useful :)

In case you were wondering, that’s a render of my old blog, which was hosted on the Oregon State servers (still is, actually, but they should be taking it down any day now…)

So hopefully by tomorrow night I should have a similar, but better rendered picture to post. Does anyone have suggestions for the best font engine for Python? I know there are some FreeType wrappers written, but is there anything which adds more Python-y functionality as well?

return false; it’s good for you.

Sunday, November 25th, 2007

Today I was looking around for blogs about JavaScript when I stumbled upon The Strange Zen of JavaScript by Scott Andrew LePera (Hacker/Singer/Songwriter), which looks to be quite informative, though sadly it seems as though it has been in hibernation since July.

I was relieved to see in reading The Mark Of The n00b that I’m not a n00b (at least according to that particular metric). Though I suppose I should point it out to others so they can avoid being n00bs as well:

use href=”#” and return false from your onclick event handlers to avoid jumping! (Ironically there were comments asking how to avoid the jumping scrollbars in the Mark of the n00b post, which was posted immediately after the return false post. Whoops.) Hopefully adding yet another post about this will help people googling for solutions to this frustrating problem to be more likely to find it.

More about returning false

I hate to just link to a post without adding something to the discussion, so I’ll throw in a bit of extra information about JavaScript event handler return values.

Return values are handy in most any event handler, not just onclick. Returning false prevents the event from “bubbling” up to the browser

Here are some suggestions for ways in which to use event handler return values:

  • onsubmit

    Add an onsubmit handler to a form using onsubmit=”return validate_form()”, if the form input is valid, return true, allowing the form to be submitted. If it is not valid, return false, preventing it from being submitted, then let the user know why.

  • onmousemove

    When using onmousedown and onmousemove to make an element drag-n-drop-able, then you will probably want to return false from the onmousemove handler to prevent any text on the page from being selected.

  • onmousedown, onmouseup

    Say you want to respond to a right click on a link, but you want to leave alone regular left clicks. Register an onmouseup event handler (which takes a parameter e) for that link, check the value of e.button. If it is 0, return true and the link is followed. If it is 2, do your thing (pop up a context menu, perhaps?), then return false so that the browser doesn’t pop up its own context menu. This is the technique used by those annoying scripts that “prevent” you from downloading images from their sites.

For an enormous amount of more information, check out the DOM Event Compatibility Tables over at Quirksmode

Fun With Bookmarklets

Saturday, November 24th, 2007

I’ve got a project planned for the near future which will require some sort of interaction with webpages other than my own. There are two ways I’m considering doing this: browser plugin, or bookmarklet(s). The problem with doing a browser plugin is that I’d have to write a separate plugin for each browser or, worse, only support a single browser. So I’m leaning toward bookmarklets to begin with. As with most things, I figured I’d get a bit of experience with bookmarklets before trying to do anything too complicated.

My first bookmarklet

According to this page on bookmarklets, the longest I can make a bookmarklet and have it still run in every browser (read: IE6) is 488 characters. That’s hardly enough to do any sort of cool Web2.0 stuff, so I need to load in an external script. Despite what the previously linked site says, it is indeed possible to insert script tags into the header of more than just IE, so that’s what I’ll do:

(function() {
    var head = document.getElementsByTagName('head')[0];
    var newscript = document.createElement('script');
    newscript.type='text/javascript';
    newscript.src='http://probablyprogramming.com/files/bm/js/google.js';
    head.appendChild(newscript);
})()

There, only 250 characters when I take out all the whitespace and add “javascript:” to the beginning. Notice that everything is wrapped in anonymous functions; this avoids putting unnecessary stuff into global namespace, which should prevent this code from conflicting with any code already on the page it’s being inserted into. The one thing that I do put into the global namespace is the blogpaulbonsercomclosegoogle_box() function, which I named to avoid conflicts.

google.js:

function blog_paulbonser_com_close_google_box() {
    var gb = document.getElementById('blog_paulbonser_com_google_box');
    gb.parentNode.removeChild(gb);    
}
 
(function() {
    var body = document.getElementsByTagName('body')[0];
    var head = document.getElementsByTagName('head')[0];
 
    var newstyle = document.createElement('link');
    newstyle.href = "http://probablyprogramming.com/files/bm/css/google.css";
    newstyle.rel="stylesheet";
    head.appendChild(newstyle);
 
    body.innerHTML += '<div id="blog_paulbonser_com_google_box"><div><a href="#" onclick="blog_paulbonser_com_close_google_box(); return false;">Close</a></div><iframe src="http://google.com"></iframe></div>';
})();

Go ahead, give it a try.

Example Bookmarklet: open an iframe

There you go, google popping up in the middle of my page. The real power of this, however, is that it should work on any page (except for pages with frames, since they don’t have a top-level body element). If you drag the link up to your bookmark toolbar, or rightclick and select “Bookmark this link”, etc, you will then be able to go to any page, click on that bookmark, and have a google search page pop up right in the middle.

My first “useful” bookmarklet

That’s a good start, but how about something that might actually be useful? Here’s an attempt at just that.

Lightboxify Bookmarklet: lightboxify page

This bookmarklet, plus a slightly modified version of the wonderful Lightbox plugin by Lokesh Dhakar, will take any links to images on the current page and “lightboxify” them. Give it a try on this page with the links below (some random images pulled from my computer). Before running the bookmarklet, it will navigate away from this page to the image. After running it: instant fancy image gallery. (Okay, there are still no thumbnails, but that would require a bit of extra work.)

If you feel so inclined, you can also drag this bookmarklet to your bookmarks toolbar, go to the Apache-generated directory listing, and give it a whirl there, as well.

1 2 3 4 5 6 7 8

Extending Javascript: Tail Recursion

Sunday, November 18th, 2007

Javascript is a very powerful, yet underrated, programming language. Despite its name, it is neither Java-like nor “just a scripting language.” It uses a generally unfamiliar concept known as Prototype-based Programming, which is object-oriented, but without classes. A couple of common questions about Javascript are “How can I run multiple threads?” and “How do I pause execution of my program for X seconds?”

The common answer is “You can’t, but you can do something similar with setTimeout.”

If you want to wait for X milliseconds before doing something, you simply setup a callback with

    setTimeout('something', X);

However, any callbacks will have to wait until the current function finished executing before executing, because Javascript is single threaded, and setTimeout simply puts its function call on a queue of things to be done later. After each function is finished running, the queue is checked for scheduled tasks, and any task whose timeout has expired will be run. Firefox even seems to defer updating of page content until after the currently running Javascript function returns. This is why on some pages with poorly crafted Javascript browsers will give warnings aboout scripts running for too long or consuming too much processor time.

So what do you do if you want to do large amounts of calculations, perhaps in loops that will run for many seconds or minutes? Once again, setTimeout is the way to go. As long as each function only runs for a very short period of time, you can run several different tasks “simultaneously” without killing your browser.

There is one thing, however, that bothers me about using setTimeout: It makes for some ugly code, and usually requires you to either wrap a string or anonymous function around your callbacks. Worse, it requires you to think about callbacks at all. So something as simple as running a loop that won’t hijack your browser becomes a pain. For example, here’s a simple function to count between two numbers within an element on the page:

(more…)