Friday, May 01, 2009

Been a bit quiet here for the last few months. I’ve been particularly busy at work but also I’ve been working on a few other projects on the side.

One of these is ThumbWhere. http://thumbwhere.com (try the blog for more info).

ThumbWhere allows you to post text, images, video or audio to the web and to Twitter. Support for other social media and social networking sites will be enabled in the near future.

Here is a post on my Twitter stream sent in from ThumbWhere.

image 

If you use Twitter on your mobile phone you will find it’s very very fast. I have no ads – I just link you directly to the media if you click on a http://tny.tw shortlink using a phone.

If you just want to post something anonymously – send images, photos or video to +61-447-100-293 and it will be added to the public feed. Anyone can send via MMS and your content will be added anonymously to the public timeline. If you later on create an account, that content will be added to your account and will no longer be anonymous, so don’t post anything embarrassing if you intend to join up in the future :)

I’m keeping out the email spammers for now but I’ll be enabling submissions via email in the next few weeks – at the moment you need a phone that can MMS to the submission number, so if you have an iPhone you will need version 3.0.

image

image

The main web site is a very plain lightweight AJAX driven ‘white-site. It does not look like much, but it’s doing some wonderful magic under the hood as it’s all driven by my state machine language. The back end is running my own custom pipeline processing engine – it’s kind of a multi-dimensional-tree lazy evaluation version of map-reduce. This architecture means that it’s trivial for me to integrate job endpoints from on demand computer systems such as Azure and EC2.

image

I’ve set up a site to allow people to request features. First off the rank will be submission via email.

I’m also working on an iPhone app and an Azure endpoint for much of my processing and transcoding pipeline.

Its keeping me off the streets :)

Friday, May 01, 2009 4:17:08 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Thursday, September 25, 2008

In my last post I described the basic State Machine/Theorem Prover developed in JavaScript – here is a recap, update and continuation of that post based on the latest development.

And BTW - This is my presentation for WebJam 08 Sydney Australia so if this post seems a little scattered its because its kind of half blog, half crib sheet for a 3 minute presentation.

JavaScript Finite State-Machine Engine

What is a Finite State Machine?

244px-Finite_state_machine_example_with_comments.svg 

 finite state machine (FSM) or finite state automaton (plural: automata) or simply a state machine, is a model of behavior composed of a finite number of states, transitions between those states, and actions. A finite state machine is an abstract model of a machine with a primitive internal memory. Source: Wikipedia

 

The state-machine is a formalised description of the possible states of a system. States are either 'active' or 'inactive'.  My state-machine is multi-dimensional (states have sub-states) and multi-state (more than one state can active).

The state-machine description consists of an XML file that describes a list of states and a legal ways for transitioning between those states.

The state-machine description consists of a list of states.  

Each state has a collection of sub-states which can only be active if their parent is active.

image

Each state has...

A list of passive rules for validating states which allow for a degree of asserting contracts between states.

A state can 'exclude' another state. Which is a way of saying that if this state is active then the other state should be inactive. If not, a fault will be indicated by an exception.

A state can 'include' another state. Which is a way of saying that if this state is active then the other state should also be active. If not, a fault will be indicated by an exception.

A list of passive rules that describe how a state is affected by the activation of other states or the return from JavaScript calls.

A state can require that a state is active or inactive.

image

And require that a JavaScript function returns true. Any sub-state automatically requires its parent state. If you find a state requires only one or more states to be active then it should probably be a child of one of those states.

state can only be active if isInviteSent() returns true

A list of active rules that describe how a states can control that activation of other states.

A state can 'negate' a specified state in which case when the state becomes active it will try and make the specified state inactive.

A state can 'affirm' a specified state in which case when the state becomes active it will try and make the specified state active.

When x has won, the game is over.

A list of triggers that are fired when the pattern of active states changes. The trigger is the call to a JavaScript function.

A trigger can fire when a states 'enter' (become active).

A trigger can fire when a states 'exit' (become inactive).

A trigger can fire when two specified states transitions 'from' or 'to' active/inactive between determining states.

When we transition to 'off' from 'on' then call some javascript.

A state can have a lock which forces it into its current state until the state machine is reset.

When an O is placed at position 1,2 - we ensure that X can't be placed there and that this state can't change by locking it.

The state machine has the following public accessible JavaScript functions

MetaWrap.State.testState(stateName) - Returns true if the named state is active

MetaWrap.State.negateState(stateName) - Tries to set the named state to inactive then determines the new state and fires transitions. Returns true if state is 'inactive'

MetaWrap.State.affirmState(stateName) - Tries to set the named state to active then determines the new state and fires transitions. Returns true if state is 'active'

MetaWrap.State.flipState(stateName) - Flips the named the named state from active to inactive or visa versa. Returns true if state is was flipped.

MetaWrap.State.determineState()  - Calculates the current state. Called after changes to the model are made that may require the state machine to re-evaluate.'

 

JavaScript State Machine Examples

Toaster Example

NOTE – This won’t work in Safari or Opera.. yet. Neither of these browsers support client side XSLT. I’m working on a simple solution for this.

http://test.metawrap.com/javascript/tests/state/test_10_state.html

My first serious example was to model a simple toaster in a way that used most of the functionality of the state machine.

I wanted to model two classes of behavior.

The first are based on the explicit physical properties of the toaster (power on/off, bread in/out, lever up/down). I added the typical toaster behavior that you can’t push the lever down if the toaster is not on.

The second are based on the higher level states build up on the physical states, for instance if the power is on, the bread is in and the lever down, then the toast is cooking. I have also added the state where if you put the lever down after the toast has cooked, it will burn the toast.

image

 

image

image

Tic Tac Toe Example

I think it was Lela who suggested that I try and model Tic Tac Toe. So I sat down and defined the finite state machine.

NOTE – This won’t work in Safari or Opera.. yet. Neither of these browsers support client side XSLT. Two Simple solutions soon.

http://test.metawrap.com/javascript/tests/state/test_13_state.html

image

One pleasant surprise is that formally describing the states as a whole makes you think about them as a….. whole :) . And the formal description can make some things obvious. For example. In the way I modeled Tic Tac Toe, it could be X’s turn or O’s turn.

image

And I set it up for one to deny the other (note that x_turn defaults to true, so X goes first).  This means in the JavaScript my code is nice and simple.

image

Once the game is over, who’s turn is it? There is a fault in my current model that became obvious after examination. I thought I was being clever by inversely relating x_turn and o_turn because it gave me a way of tracking the turn inside of the state machine which would then flip the current state.

However at the end of the game when I want to make it nobody's turn, if I negate x_turn, o_turn becomes true and then when I negate o_turn, x_turn becomes true. I solved the issue by locking the turns.

I’m probably going to modify lock so that you can specify a value to lock it on and get it to suspend all further affirmations and negations down the chain, but I need to work out what the implications for that could be.

 image

image 

 

So you say that’s really…. neat and BTW how is the Asperger’s treating you?… …but how can we use this in web development?

My thesis is, in a nutshell that as developers we often end up dealing with complex logical situations in a user interface that are best explained by this sketch from Monty Python's The Meaning Of Life.

MR HUMPHREY: I begin the lesson, will those of you who are playing in the match this afternoon move your clothes down onto the lower peg immediately after lunch, before you write your letter home, if you're not getting your hair cut, unless you've got a younger brother who is going out this weekend as the guest of another boy, in which case, collect his note before lunch, put it in your letter after you've had your hair cut, and make sure he moves your clothes down onto the lower peg for you. Now,--
WYMER: Sir?
MR HUMPHREY: Yes, Wymer?
WYMER: My younger brother's going out with Dibble this weekend, sir, but I'm not having my hair cut today, sir. So, do I move my clothes down, or--
MR HUMPHREY: I do wish you'd listen, Wymer. It's perfectly simple. If you're not getting your hair cut, you don't have to move your brother's clothes down to the lower peg. You simply collect his note before lunch, after you've done your scripture prep, when you've written your letter home, before rest, move your own clothes onto the lower peg, greet the visitors, and report to Mr. Viney that you've had your chit signed.


Monty Python Sex Education Sketch From “The Meaning Of Life” 0:15 to (0:40 short) - (1:12 full)

Now, like me your probably written an application with a user interface that ends up after a few rounds of maintenance and changes with complex logic all over the place and a single change results in unpredictably strange consequences. As you make changes to this the code complexity grows. As developers, the best we have been able to come up with is MVC, which puts all that logic in the controller, however this is distributed throughout the source code files of the controller and there is no guarantee that you won't end up dabbling in the Kafkaesque.

 

 

Two random images from the web describing Model View Controller

 

Ideally I want some way of

  1. Describing a set of integrated rules in one location in a domain specific language.
  2. Decoupling this description as much as possible from the the Views.
  3. Allows those rules to be provable and enforced via contracts.
  4. Allow the system to be intelligent enough that it exhibits emergent behavior via its logical roots, this emergent behavior can then be leaned upon and provide complex yet intuitive behaviors to users for free.

My aim was to break the controller up into a state machine based rules system and a layer that could mediate between the state and view.  The states could be mathematically provable with contracts ensuring that no illegal state combination could be entered.  Combining this with a direct mapping layer between states and views, could result in a lot of code being abstracted away into the state machine and result in a more compact code-base.

 

 Drawing3

A state machine interrogates a model via user defined JavaScript functions.The state view map defines what views and aspects of the view should be visible and triggers their display. 

 

Aspect Orientated Views In JavaScript

Lets start with a simple HTML based template system which exposes something I can control with the state machine.

The basic thing we need to control is a View – so I recycled a JavaScript template engine system I built in late 2005.

I desired a system that enabled me to edit and compose the CSS and HTML without special tool chain or publishing or ingestion process slowing me down. Ideally wanted to allow people to use WYSIWYG editors or preview a template browser. Quick feedback for developing CSS.

I use a <span> inside of a <div>. Working on making this more compact. Can have multiple spans inside of a div to provide alternative view. At the moment the templating system prototype works on server side as well so I can strip out elements and send fragments back up from the server.

I built this about a year before AJAX.NET came out – but was thrilled that it did the same kind of fragment update. Obviously on the right track.

May end up with span only notation. At the moment this gives me more flexibility at the cost of forcing the developer to add <div>s at logical locations – which may or may not be a bad thing.

image

image

So I can see everything in the base view in activated state. If I want to edit in a particular state I play with CSS  to show hide what I want.

I want this aspect based and I want the aspects to cross multiple parts of a page and across views so I added aspects.

Eg  the Logged in aspect.

image

image

So if I turn on the aspect ‘loggedin’ these will show unless they are inside an aspect that is off. Aspects are hierarchical. Visibility obeys the laws of physics.

So consider this statemachine and in particular the part for managing the classical Web 2.0 Invite system.

image

So now we need to map between the states and the views

The State View Map

The state view map is a formalised description of mappings from a state to a view and a set of aspects of that view.

A state view map description consists of a list of states and the pages and aspects that should be visible.

A state can be mapped to a particular page – so if that state is true then it switches to that page/view.

A state can be mapped to an aspect. For this example check out the invite mappings. This is a very simple example – I only have three minutes! :)

image

Bringing it all together in an application. Template for the view. If you include the history iframe it will do the classic AJAX history tracking.

image

The function that starts it all.

image 

Every time there is a key hit in the invite email input, we re-determine the current state.

image

When we re-determine the state the state machine definition knows that for the send invite button to be ready we need to return true from isInviteReady()

image 

And that function simply returns true if there is a regex match on an the content of the invite email field.

image

And here is a Demo of it in action.

The End

James Mc Parlane http://blog.metawrap.com/

http://twitter.com/DrMiaow

Next Presentation At WebJam – Adding a dynamic Layout / Skinning engine to State/View engine.

Oh and BTW…

Massive Are Hiring HTML/JS/CSS Front End developers

Knowing XML/XSLT Is a bonus!

Mail work@massive.com.au

image

Thursday, September 25, 2008 5:34:41 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, September 03, 2008

I Like it. Its fast. The tab page is genius. Its my default browser for everything bar web development. Webkit developers console is outclassed by FireBug on FireFox.

Flash works. Flash player install required a few goes.

Java Works.. but need latest Java 6 Update 10 plugin http://java.sun.com/developer/technicalArticles/javase/java6u10/

My JavaScript library works with no modification required. So happy I could cry.

Silverlight does not work. Hope this is resolved soon.

Sadly my Blog editor does not work so this post will be short. Using LiveWriter mostly now anyway, but its not installed on this machine :)

Some interesting points from PPK http://www.quirksmode.org/blog/archives/2008/09/google_chrome.html

Wednesday, September 03, 2008 12:11:45 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Monday, July 21, 2008

I started witing this two years ago and never really got around to blogging about it. In a nutshell this is a module that runs within the MetaWrap JavaScript library that allows you to define a finite state machine in XML. The finite state machine can call out to JavaScript to check values and notify the application of state transitions.

This development is a follow on from my previous research into Parsing Theory and part of an ongoing interest in streamlining web development. I've recently started using the state machine for its intended purpose so after 18 months I’ve finally decided to dust it off and blog it :)

My thesis is, in a nutshell that as developers we often end up dealing with complex logical situations in a user interface that are best explained by this sketch from Monty Python's The Meaning Of Life.

MR HUMPHREY: I begin the lesson, will those of you who are playing in the match this afternoon move your clothes down onto the lower peg immediately after lunch, before you write your letter home, if you're not getting your hair cut, unless you've got a younger brother who is going out this weekend as the guest of another boy, in which case, collect his note before lunch, put it in your letter after you've had your hair cut, and make sure he moves your clothes down onto the lower peg for you. Now,--
WYMER: Sir?
MR HUMPHREY: Yes, Wymer?
WYMER: My younger brother's going out with Dibble this weekend, sir, but I'm not having my hair cut today, sir. So, do I move my clothes down, or--
MR HUMPHREY: I do wish you'd listen, Wymer. It's perfectly simple. If you're not getting your hair cut, you don't have to move your brother's clothes down to the lower peg. You simply collect his note before lunch, after you've done your scripture prep, when you've written your letter home, before rest, move your own clothes onto the lower peg, greet the visitors, and report to Mr. Viney that you've had your chit signed.

Now, like me your probably written an application with a user interface that ends up with complex logic all over the place and a single change results in unpredictably strange consequences. As you make changes to this the code complexity grows. As developers, the best we have been able to come up with is MVC, which puts all that logic is all in the controller, however this is distributed throughout the code of the controller and there is no guarantee that you won't end up dabbling in the Kafkaesque.

 

 

 

Ideally I want some way of

  1. Describing a set of integrated rules in one location in a domain specific language.
  2. Decoupling this description as much as possible from the the Views.
  3. Allows those rules to be provable and enforced via contracts.
  4. Allow the system to be intelligent enough that it exhibits emergent behavior via its logical roots, this emergent behavior can then be leaned upon and provide complex yet intuitive behaviors to users for free.

My aim was to break the controller up into a state machine based rules system and a layer that could mediate between the state and view.  The states could be mathematically provable with contracts ensuring that no illegal state combination could be entered.  Combining this with a direct mapping layer between states and views, could result in a lot of code being abstracted away into the state machine and result in a more compact code-base.

 

JS_StateMachine_MVC_Comparison

A state machine interrogates a model via user defined JavaScript functions.The state view map defines what views and aspects of the view should be visible and triggers their display. 

 

JavaScript Finite State-Machine

The state-machine is a formalised description of the possible states of a system. States are either 'active' or 'inactive'.  The state-machine is multi-dimensional (states have sub-states) and multi-state (more than one state can active). 

The state-machine description consists of an XML file that describes a list of states.

The state-machine description consists of a list of states.  

Each state has a collection of sub-states which can only be active if their parent is active.

image

Each state has...

A list of rules for validating states which allow for a degree of asserting contracts between states.

A state can 'exclude' another state. Which is a way of saying that if this state is active then the other state should be inactive. If not, a fault will be indicated by an exception.

A state can 'include' another state. Which is a way of saying that if this state is active then the other state should also be active. If not, a fault will be indicated by an exception.

A list of rules that describe how a state is affected by the activation of other states or the return from JavaScript calls.

A state can 'require' some conditions to be met that another state is active or that a JavaScript function returns true. Any sub-state automatically requires its parent state. If you find a state requires only one or more states to be active then it should probably be a child of one of those states.

state can only be active if isInviteSent() returns true

state wino2s (win by O on diagonal 2) is only true if states op13 op22 and op31 are active. 

The reverse of ‘require’ is ‘unrequire’ such that the state will require a state to be inactive and expect called JavaScript functions to return false.

If we are going to be in a draw state in tic tac toe, then we can't have anone winning

Can anyone think of an alternative to ‘require’ and ‘unrequire’. I’m seriously considering ‘canhas’ and ‘doesnotwant’ as they make as much sense as any other alternatives so far.

A list of rules that describe how a states can control that activation of other states.

A state can 'negate' a specified state in which case when the state becomes active it will try and make the specified state inactive.

A state can 'affirm' a specified state in which case when the state becomes active it will try and make the specified state active.

When x has won, the game is over.

A list of triggers that are fired when the pattern of active states changes. The trigger is the call to a JavaScript function.

A trigger can fire when a states 'enter' (become active).

A trigger can fire when a states 'exit' (become inactive).

A trigger can fire when two specified states transitions 'from' or 'to' active/inactive between determining states.

When we transition to 'off' from 'on' then call some javascript.

A state can have a lock which forces it into its current state until the state machine is reset.

When an O is placed at position 1,2 - we ensure that X can't be placed there and that this state can't change by locking it.

The state machine has the following public accessible JavaScript functions

MetaWrap.State.testState(stateName) - Returns true if the named state is active

MetaWrap.State.negateState(stateName) - Tries to set the named state to inactive then determines the new state and fires transitions. Returns true if state is 'inactive'

MetaWrap.State.affirmState(stateName) - Tries to set the named state to active then determines the new state and fires transitions. Returns true if state is 'active'

MetaWrap.State.flipState(stateName) - Flips the named the named state from active to inactive or visa versa. Returns true if state is was flipped.

MetaWrap.State.determineState()  - Calculates the current state. Called after changes to the model are made that may require the state machine to re-evaluate.'

 

JavaScript State Machine Examples

  1. Toaster Example

NOTE – This won’t work in Safari or Opera.. yet. Neither of these browsers support client side XSLT. I’m working on a simple solution for this.

http://test.metawrap.com/javascript/tests/state/test_10_state.html

My first serious example was to model a simple toaster in a way that used most of the functionality of the state machine.

I wanted to model two classes of behavior.

The first are based on the explicit physical properties of the toaster (power on/off, bread in/out, lever up/down). I added the typical toaster behavior that you can’t push the lever down if the toaster is not on.

The second are based on the higher level states build up on the physical states, for instance if the power is on, the bread is in and the lever down, then the toast is cooking. I have also added the state where if you put the lever down after the toast has cooked, it will burn the toast.

image

 

image

image

  1. Tic Tac Toe Example

I think it was Lela who suggested that I try and model Tic Tac Toe. So I sat down and defined the finite state machine.

NOTE – This won’t work in Safari or Opera.. yet. Neither of these browsers support client side XSLT. I’m working on a simple solution for this.

http://test.metawrap.com/javascript/tests/state/test_13_state.html

image

One pleasant surprise is that formally describing the states as a whole makes you think about them as a….. whole :) . And the formal description can make some things obvious. For example. In the way I modeled Tic Tac Toe, it could be X’s turn or O’s turn.

image

And I set it up for one to deny the other (note that x_turn defaults to true, so X goes first).  This means in the JavaScript my code is nice and simple.

image

Once the game is over, who’s turn is it? There is a fault in my current model that became obvious after examination. I thought I was being clever by inversely relating x_turn and o_turn because it gave me a way of tracking the turn inside of the state machine which would then flip the current state.

However at the end of the game when I want to make it nobody's turn, if I negate x_turn, o_turn becomes true and then when I negate o_turn, x_turn becomes true. I solved the issue by locking the turns.

I’m probably going to modify lock so that you can specify a value to lock it on and get it to suspend all further affirmations and negations down the chain, but I need to work out what the implications for that could be.

 image

image 

State View Map

The state view map is a formalised description of mappings from a state to a view and a set of aspects of that view.

A state view map  description consists of a list of states and the pages and aspects that should be visible.

This will be the topic of my next post.

Monday, July 21, 2008 11:43:58 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Friday, March 14, 2008

The cool thing about being able to work at Massive is that you straddle the extreme technical end of making things scale, in the web 'C10k problem' sense, combined with the demands of the general public TV audience.

It combines both of my passions for the hard core Computer Science of making machines work at optimum capacity, providing developers with a simple and sensible API while also involving my eternal pathological psychological passion for the creation of an intuitive interface that combines the essential ingredients of a compelling first impression and the fugue that comes with immersion.

At Massive we are fortunate enough to get to combine web technology with the world of mass entertainment which puts us a little bit closer to Hollywood.

Or in this case Cannes.

Yes. We have been nominated for another Emmy, which makes that two Emmy nominations in a row.

emmy1.png

http://www.iemmys.tv/awards_nominees.aspx

emmy2.png

Check out the V8 Supercars Showreel if you want to get an feel for what the site is all about and what it delivers to viewers.

Anyone who knows me personally knows that the V8 project has been one of my focal projects for the last 3 years. Many a person has been denied my weekend company because I have been devoted to making such an awesome system and concept work. I've blogged about algorithmic success and the trepidation of designing a new version. Sometimes its all for Science!

The BigPond V8 broadband site combines live streaming, PVR time-shifting and the synchronisation of disparate data sources to bring together a coherent behind the scenes in the car narrative to the end consumer. I have loved working on this project so very much and I'm really chuffed to get this recognition.

Of course this was a team effort, with many other people involved in the project at Massive working in Design, Flash and Project management. Without many others at Massive and some of the brilliant people at BigPond and Chief Entertainment this project would not have been possible.

Check out the Massive Showreel as well if you want to get a feel for the kind of projects we work on at Massive.

Friday, March 14, 2008 9:25:25 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, March 12, 2008

Adobe is planning to release a security update for Flash Player 9 in April 2008 to strengthen the security of Adobe Flash Player.

This security update will make the optional socket policy file changes introduced in Flash Player 9,0,115,0 mandatory.

  • A socket policy file will always be required for all socket connections
  • A policy file will be required to send headers across domains.
  • The allowScriptAccess default will always be "sameDomain"
  • javascript:" URLs will be prohibited in networking APIs, except getURL(), navigateToURL(), and HTML-enabled text fields

This is probably a good thing, but I am expecting a lot innocent flash applications to get stuck in the crossfire if their developers are not prepared  or are not aware that their application will be nobbled by this update.

Wednesday, March 12, 2008 3:27:13 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, September 26, 2007

There was a bad cable when we moved the servers around. All is good now.

Thanks to the people who pointed this out, unfortunately I was was so busy I didn't get to attend to this for a week.

Now the bad news. Everything is going down again this weekend due to a major change to the power in the building - the good news is that this is the last of the major infrastructure changes and things should then settle back down again.

After that should have some really cool stuff to start demoing.

Wednesday, September 26, 2007 6:04:08 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, July 25, 2007

This solved the issue I was having with MSXML not parsing XHTML as XML without an xml-declaration - which is the only format that Microsoft Expression Web will auto-detect as XHTML without forcing it to fail over to it. ([menu] Tools > Page Editor Options > Authoring > Secondary Schema = XHTML 1.0 Strict).

I coded up a simple test case

Normally for all things XML in Javascript I have a handy lib that normally abstracts this away for me but for a test-case I'm staying close to the metal.

var l_xml_document = new ActiveXObject("Msxml2.DOMDocument.3.0");
l_xml_document.async = false;
l_xml_document.validateOnParse = false;
l_xml_document.resolveExternals = false;
l_xml_document.load(p_file);

I'll run through each line

var l_xml_document = new ActiveXObject("Msxml2.DOMDocument.3.0");

This creates an Object which is IE's version of the W3C standard DOM Document. I ask for the MSXML 3.0 DOM Document by name because its the default for "Msxml2.DOMDocument" . This means I'm not going to get any surprises if the default goes to v6.0 and it changes behavior. V3 seems to be installed on all Windows machines by default. From memory it came as part of IE5.5

l_xml_document.async = false;

This disables asynchronous mode - in this case I'm happy to wait for the file to arrive

l_xml_document.validateOnParse = false;

This was the clincher - without setting validateOnParse to false I was unable to parse XHTML in the following format (which is valid XML - the xml-declaration is optional according to the w3c spec)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml" lang="en"><head></head><body></body></html>

I needed to add the xml-declaration at the start.

<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "
http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml" lang="en"><head></head><body></body></html>

When I did add the xml-declaration I had to force Microsoft Expression Web to fail-over this as XHTML, it would not detect it.

Using either the 'xml-declaration' or 'validateOnparse set to false' workarounds, DOMDocument was very slow to load the XML, which brings us to the next line

l_xml_document.resolveExternals = false;

This prevents Msxml2.DOMDocument from trying to load and DTD's and validate your code. This can take 5 seconds per request - so you really don't want this unless there is a real danger that the XML you get back will be not conform to XHTML.

l_xml_document.load(p_file);

Load it. Not explaining this.

Hope this helps someone. Special thanks to John-Daniel Trask and Chris Bentley who commented on my original post.

Wednesday, July 25, 2007 11:10:29 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Thursday, May 31, 2007
Thursday, May 31, 2007 10:25:38 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [2]
 Saturday, March 24, 2007

The BigPond V8 Supercars 2007 application that has kept me away from regular sleep/blogosphere/fun for the last few months is rapidly shedding its "Beta" status.

Here is a video WMV, QuickTime, QuickTime HUGE. The App runs at 25fps, so this 10fps screen capture does not really do it justice.

The application is written in JavaScript and uses Flash elements as a 'dumb' display terminal. This provides a simple and highly reactive coding environment coupled to lovely anti-aliasing and scaling via Flash. Each of the panels are detachable (and soon drag/swap-able) and can be made to detach, re-size and go full screen, so if you have multiple monitors, you can really have a good time :)

V8_2007.png

 

Saturday, March 24, 2007 4:32:56 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Friday, February 09, 2007

I've been waiting for Emerson Clarke to GPL this library since he started sending me code samples via IM a few years ago.

If you really want to squeeze every last nanoflop of performance out of your hardware then you need to turn to languages like C and C++, or if you have a lot of time on your hands, and a large beard, assembler.

There is a reason that these languages are the mainstay of the games development industry.

If you want to generate the fastest Ruby extension possible without having to worry about how you are going to install libraries for HTTP, XML, XPath, SQL, multithreading and file system access (to name a few) then I suggest you check this framework out.

If you want to take on Google and build the greatest number crunching data analysis farm in the world, then its perfect for that too.

Reason is a wonderfully easy to understand cross platform C++ framework. The code is very readable and amazingly well commented.  

Disclaimer: I used to work with Emerson at Massive before he joined Thoughtworks and then went on to storm the world developing industral scale C++ applications.

C++ | JavaScript | Massive | Web2.0 | XML | XPath
Friday, February 09, 2007 2:46:34 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [2]
 Wednesday, December 20, 2006

Great post on what a good JavaScript Library should have/not have.

"After spending about three weeks finishing a chapter of the upcoming book introducing JavaScript libraries to non-developers I was quite amazed how tough it is at times to use different libraries.

It was frustrating putting together a set of example scripts for several effects for the oddest reasons, which is why I am now publishing my wishlist for any JavaScript library developers or maintainers. Before you start a new library or expect people to be able to use yours immediately you might want to give these points some thought. For library users this list might be a good “heads up” to see how much work has to go into using a library or how to pick the right library for the job at hand.

Here’s what drove me nuts:"

http://www.wait-till-i.com/index.php?p=366

 

And here is an interesting referring post.

http://domscripting.com/blog/display/92

 

 

Wednesday, December 20, 2006 10:05:00 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, December 13, 2006

For those who have suffered through my detailed answer to the question "so what have you been working on lately?", here is a simple progress report in pictures. No doubt it makes as much sense as my addled answer, but I assure you its a Very Good ThingTM.

editor_test_cursor_firefox.png

editor_test_cursor_ie.png

Tuesday, December 12, 2006 11:24:57 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Tuesday, September 26, 2006

There Is A New Version Available - Click Here

 

Update: I just fixed 2 bugs - one handle leak and a bug that could stop it from scanning serial ports. Seems I left in some debug code on both counts.  If you downloaded this in September, then download it again - its been updated.


Here (Download) is the latest version (Build 8) of the MetaWrap time converter which replaces the previous version (Build 7)

timeconverterv8-green.png

This build fixes some reported bugs in the timezone data and adds a major new feature - GPS integration and a GPS API accessible via AJAX, JSON, CSV and UDP.

gps.png

If you enable the GPS menu option the application will lock onto an authoritative GPS source. Either a standard serial port/USB style NMEA 0183 gadget attached to your computer or a device that broadcasts NMEA 0183 over UDP that is plugged into your local network. The application will auto hunt for the hardware, no configuration is required.

If it finds an authoritative GPS source it will rebroadcast it for other time-converters to receive. These other time-converters don't need to have GPS enabled - they will simply pick it up off the local Ethernet segment.  You will be UDB broadcasting your location and IP address if you enable GPS, for most cases this should not be a problem as it will only be broadcast to your local area network. If you are on a cable network that enables UDP broadcasts then you may want to firewall UDP port 7305.

Your location will be tracked on the time-converter world map (above) with a small dot. If its salmon colored then its receiving GPS data, but the GPS quality is 0. If its green it has a quality or 1 or higher.

Three APIs are provided.

1) A Windows COM service is provided, so once the time-converter is installed, if a web-page in IE tries to access the "MetaWrap.TimeConverter" Object, the executable will be automatically launched.

com-api.png

2) For web-browsers such as Firefox and Opera, an HTTP service is provided via localhost which can be accessed via AJAX or JSON. This is designed to be backwardly compatible with the MeHere API.

Comma Delimited- http://localhost:7305/csv

JavaScript - http://localhost:7305/js

XML - http://localhost:7305/netlink

Google Earth - http://localhost:7305/kml

I'll add more of these formats on request.

3) The third API isavailable on UDP port 7305 . The application will broadcast its current known GPS location as a string.

This test page will test the values being put out by the time-converter via the COM interface.

simple-gps.png

This test page will integrate with Google maps and track you as you move about.

Mike Cornelius was able to use a fast 3G data modem and this example code/testcase to track himself driving from Sydney to Wollongong.

gps-tracker.png

 

Test pages for the AJAX and JSON code are under construction - but most JavaScript coders should be able to figure it out for themselves.


To upgrade you can either,

Choose Uninstall on the tool-tip menu on your current version and run the new one

uninstall.png

or

Select Exit via the tool-tip menu and replace your current mwtimeconverter.exe executable and add the new dlls, and then run it by double clicking on it.

exit.png

 

 

Tuesday, September 26, 2006 1:21:15 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, September 13, 2006

In short - externalInterface is the work of the devil.

There are others that have a low opinion of it.

So far the issue I have found seems to affect the interaction between Windows Media Center, FlashPlayer 9.16.0  (FlashPlayer 8 does not have the issue) and Flash SWFs that use externalInterface.

But there is a solution.

externalInterface is much nicer than fsCommand but suffers from some of the same problems when it comes to adding Flash to a page dynamically. In a previous post I have outlined a workaround.

The issue with externalInterface is very different which seems to center on that fact that it injects its own JavaScript code into window.parent

If you have seen the movie Terminator, there is a scene where Arnie walks up to biker and punches him in a chest and pulls out his still beating heart. Imagine that played back in reverse and you have a fair idea of what FlashPlayer 9 does to the browser.

eg

  // Look for the 'standard' functions that flash adds to window.parent
  if (window.parent.__flash__toXML != null)
  {
   alert("window.parent.__flash__toXML exists");
  }
  else
  {
   alert("window.parent.__flash__toXML not there");
  }

Windows Media Center runs HTML applications in a shell of IE.  It's IE plus a series of objects that you can script against to do MCE specific operations. It also behaves differently to IE in one critical aspect.

In WMC, when running an application, if you play a movie full screen or use one of the hot keys to browse forward, including the magic green button and then at a later time browse back to the application by hitting the "BACK" button, the BODY.onload event fires again.

In an application that has no embedded Flash SWFs this can be handled in JavaScript by setting a simple flag - but if your application embeds SWFs that use externalInterface and you have FlashPlayer 9 installed - your SWF dies. You get a white screen of "not really there". The SWF is still running. It's still able to call into JavaScript, but you can't call it and there is no way to make it start displaying again.

This does not happen with the FlashPlayer 8. Something has changed. Either the window.parent fisting is broken, or FlashPlayer 9 listens to BODY.onload and is doing something extra that is just not kosher for WMC.

I suspect that in WMC, window.parent may be something other than what FlashPlayer9 is expecting. I'm still exploring the specifics of this.

The solution is to give Arnie a cardboard cutout to insert its giblets into and that can be achieved by embedding your SWF or even your whole application in an IFRAME. This guarantees that window.parent, if called from within the IFRAME is the document that embedded the IFRAME.

Arnie shoves his fist from the IFRAME into your parent document, and not somewhere unexpected.


I'm working on an addition to the MetaWrap JavaScript libraries that will include a lot of WMC support, in particular for remoting applications and dealing with flash. Will post and update when its released.

Wednesday, September 13, 2006 12:09:01 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [5]
 Tuesday, August 08, 2006
Tuesday, August 08, 2006 2:03:38 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Tuesday, August 01, 2006

Looks great and looks like it will run as an Eclipse plug-in! What more could you ask for. Not sure how it compares to the latest Eclipse 3.2 (Callisto) Web tools platform - which I use and love.  

"Aptana is a robust, JavaScript-focused IDE for building dynamic web applications. Highlights include the following features:
  • Code Assist on JavaScript, HTML, and CSS languages, including your own JavaScript functions
  • Outliner that gives a snapshot view of your JavaScript, HTML, and CSS code structure
  • Error and warning notification for your code
  • Support for Aptana UI customization and extensions
  • Cross-platform support
  • Free and open source. (Source available soon)"

http://www.aptana.com/

 

Tuesday, August 01, 2006 2:26:59 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]

"Timeline is a DHTML-based AJAXy widget for visualizing time-based events. It is like Google Maps for time-based information. Below is a live example that you can play with. Pan the timeline by dragging it horizontally."

http://simile.mit.edu/timeline/


"Slightly ThickerBox is a modification of Cody Lindley's Thickbox script. I modified it for use on my Jason's Toolbox Redesign. The modifications allow the script to generate "Previous Image" and "Next Image" links. The result is that you can use Slightly ThickerBox to create image galleries. In addition, you can create groups of galleries by setting a "rel" attribute on the links. (I also moved the Caption and Close link to the top and made the script case insensitive.)"

http://www.jasons-toolbox.com/SlightlyThickerBox/


Cool Google IG style JavaScript widget.

http://ajaxian.com/archives/echo2-widget-panel


"The World Wide Web consortium’s (W3C) CSS working group recently released a draft of a new multi column layout module--to be included (with possible modifications) into the CSS 3  specs.  For those web developers that have been lamenting the lack of adequate multi column support in current supported versions of the CSS specs, this is an exciting and welcome addition."

http://blogs.pathf.com/uxd/2006/07/multi_column_la_1.html


"Ever wanted to match the look of your HTML forms with the rest of your website? This article demonstrates how to apply customized backgrounds to HTML forms, while preserving stucturally clean markup and accesibility."

http://www.picment.com/articles/css/funwithforms/


"The use of embed has gone on too long. Wishing for it to become part of the official specs is like wishing your partner would start putting the cap on the toothpaste. It’s not going to happen. It’s time to move on. If you want to validate your website, you have to get rid of embed. In this article, I’ll show you how."

http://www.alistapart.com/articles/byebyeembed


'Every once in a long while, I read about an idea that is a stroke of brilliance, and I think to myself, "I wish I had thought of that, it's genius!" Microformats are just that kind of idea. You see, for a while now, people have tried to extract structured data from the unstructured Web. You hear glimmers of these when people talk about the "semantic Web," a Web in which data is separated from formatting. But for whatever reason, the semantic Web hasn't taken off, and the problem of finding structured data in an unstructured world remains.'

http://www-128.ibm.com/developerworks/library/x-microformats/?ca=dgr-lnxw01Microformats


"JavaScript is hip again; there’s no doubt about it. But if you’re starting to get down and dirty with it, there’s no excuse not to keep it clean."

http://www.thinkvitamin.com/features/dev/the-importance-of-maintainable-javascript


"A little bit JavaScript, a little bit CSS and a little bit clairvoyance, Link Thumbnail shows users that are about to leave your site exactly where they're going. When that curious mouse pointer hovers over a link pointing to somewhere outside of your site, the script displays a small image of the destination page. It's a nice visual cue that serves a very real purpose: providing a clearer picture (no pun intended) of what's ahead."

http://lab.arc90.com/2006/07/link_thumbnail.php


"The Javascript Sound Kit is a wrapper around the ActionScript Sound Object, it makes it possible to use the Sound Object in Javascript the same way you do it in ActionScript."

http://jssoundkit.sourceforge.net/


"Rails must be spoiling me. Every time I have to write ugly code, I wonder: could the language be different?

I wondered just that about CSS while making some Backpack Calendar styles work across browsers. Hacks are ugly. What if I could just type a special selector, based on the name of the current browser?"

http://37signals.com/svn/archives2/browser_selectors_in_css.php


"One drawback of working with AJAX is that an AJAX-based client cannot make calls to URLs outside of its domain, which means that it cannot access services located on another server. A technique such as JSONP can help in this regard, but it has some limitations.  One limitation is that including third-party JavaScript inside script elements exposes your application to potential security risks because you are allowing external parties to interact with your client.

To overcome these problems, you need a generic proxy that can communicate with external services on your client's behalf. The proxy passes a call from your client application to the service, receives the content in response from the service, and returns the content to your client. You can then use this content in your AJAX-based application."

http://weblogs.java.net/blog/gmurray71/archive/2006/07/the_xmlhttpprox_1.html


"Which New Browser Is Best: Firefox 2, Internet Explorer 7, or Opera 9? "

http://www.extremetech.com/article2/0,1558,1990850,00.asp


"Web applications are becoming more and more like “normal” desktop applications. Of course, they are more and more functional, but smooth user interface acts the primary role. So we have drag and drop, autocompletition, and much more. Many of those nice features got possible only with help of AJAX.

This page, however, is not about AJAX (or any other buzzword). It is about rather simple user input method -- mouse wheel. I believe it would now be difficult to find a mouse without wheel. Vast majority of users are used to the wheel as a control for scrolling in lists, zooming etc. Rather few web applications, however, make smart use of mouse wheel. This page is to provide you with general information about handling mouse wheel-generated events in JavaScript programming language"

http://adomas.org/javascript-mouse-wheel/


"JavaScript malware is opening the door for hackers to attack internal networks."

http://it.slashdot.org/article.pl?sid=06/07/30/0547227&from=rss

Tuesday, August 01, 2006 12:02:28 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Friday, July 28, 2006

ClickTale shows you the full story: every mouse movement, every click and every scrolling action. By using ClickTale you will gain insights that will improve your website's usability, enhance navigation, and increase effectiveness.

http://www.clicktale.com/

Something that looks scarily like my Open Source JavaScript Macro Recorder but with a snazzy front and back end.

Something like this would probably make a good proof of concept application for my XML Storage server so I may build a white screen version of this in the near future as a test application.

Friday, July 28, 2006 12:20:00 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, July 26, 2006

I was in the middle of building something like this as a demo for my XML storage server, looks like several people beat me to it. Looks like they applied for a patent only to find that there is lots of prior-art.

"A little while back I had an idea about how it might be possible to build a massive grid computer harnessing the power of the transient Internet user population. In essence the idea was to use the almost universally deployed JavaScript runtime embedded in modern web-browsers to perform small processing tasks which are part of a larger distributed processing algorithm (I can just hear those bozo bits flipping)."

http://www.gridenvy.com/

Wednesday, July 26, 2006 12:01:37 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, July 19, 2006

"Apollo is the code name for a cross-operating system runtime being developed by Adobe that allows developers to leverage their existing web development skills (Flash, Flex, HTML, JavaScript, Ajax) to build and deploy Rich Internet Applications (RIAs) to the desktop.

While a number of more traditional desktop applications can be built and targeted at the Apollo runtime, Apollo is targeted at making it easy to develop and deploy Rich Internet Applications to the desktop.

It is this use case, deploying RIAs to the desktop, which is driving the feature set for Apollo 1.0. "

http://labs.adobe.com/wiki/index.php/Apollo:developerfaq

Wednesday, July 19, 2006 2:32:50 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Sunday, July 02, 2006

AJAX done well can reduce server load and bandwidth, but I've seen a lot of people jumping on the AJAX bandwagon who don't really consider what the impact is on the back-end.

Done badly, AJAX can bring a server to its knees.

If you are writing an AJAX application and you have never heard of  "/dev/poll" or the "thundering herd problem" then you really ought to smarten yourself up by reading this, and if you don't understand that post then read the rest of this one..

The issue in a nutshell relates to one of the great dirty secrets of the Internet and the operating system wars.

When the Internet burst forward, every man and his operating system provider built a web-server on top of the file IO handling of their current OS kernels. These kernels having being optimised generally for word-processing, volume, speed, but not lots of tiny little requests in parallel.

"Lots of tiny little requests in parallel" - sound like anything you know?

Only one company got it right the first time, and that was Sun, because Solaris 2.7+ had poll() and /dev/poll. This is one of the reasons people used to rave about the performance of Sun and Solaris.

Windows let you handle a whole maximum of 64 connections in one go, to do anything better, you had to perform your own magic.

The majority of the operating systems were awful at handling the one thing that web-servers need to perform well, and that is reading and writing data from a lot of simultaneous connections, or more specifically, knowing when to read and write.

Every time you use a XMLHttpRequest object in your AJAX code, you can, if you don't know what you are doing, create a new TCP/IP connection on the remote server.

The remote server may still have the previous connections in a wait state of some kind. These can build up over time and all of a sudden your server gets sluggish or starts rejecting connections. This can be less of a /dev/poll issue and more of a lack of system resources - but the cause is the same.

bad_ajax_scaleability.png

Oh The Humanity!

As a general rule, naively configured servers start to have a hard time at a few hundred connections - after that you start to degrade rapidly, the scalability curve can be brutal.

poll.png

Here We Go Again!

If the above makes no sense to you because all you do is front-end and want to AJAXify a site - then here are some general rules.

#1) Don't try heavy AJAX on a server that does not support HTTP1.1.

The killer feature of HTTP1.1 is that it implicitly uses one socket connection for multiple http requests. So your entire impact on a server can be one connection per user. This behavior is explicit in HTTP1.0 via specifying the KeepAlive header.

Almost all modern servers use HTTP1.1, but its nice to make sure.

#2) request.setRequestHeader("Connection", "close");

Don't use it unless you know what you are doing. This will force a close of the connection. This is fine if you just make one request. But if you have a large number of requests per user session (auto completion for example) then your service can fall over after a few minutes of just one user typing away.

On modern browsers, XMLHttpRequest  is clever and even if you create and destroy your XMLHttpRequest connection object, it will still keep and reuse your current connection to the server.

#3) Hire someone who knows what they are doing

Humans suffer permanent damage when accelerated above 20G... stay with me on this one..

If you want to stick the AJAX rocket onto your server, maybe you need a rocket scientist?

Get someone who knows how to make a server sing, especially if you are about to increase the number of requests its going to get. If you can find someone who installed the /dev/epoll linux kernel patch when it first came out, then you may be onto a winner.

If you don't know what you are really doing, at least use an AJAX library that is written by someone who does.

 

Sunday, July 02, 2006 3:38:12 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [13]

"I decided to make a list of the top libraries that I have come across or that I personally use. Libraries can be a web developers best friend. They are great resources to learn from and can save hours and hours of time. These libraries include JavaScript, Ajax, Colors, PHP, and CSS. These should be in any web developers bookmarks, so go ahead and look through these libraries and bookmark your favorite ones. The list is in no particular order."

http://www.cameronolthuis.com/2006/06/top-10-web-developer-libraries/


"The major web browsers are getting facelifts as they increasingly become the focal point for handling business transactions and running programs over the internet rather than simply displaying websites."

http://www.wired.com/news/technology/0,71204-0.html?tw=rss.index


Cross browser "window.onload" solution - now supports Safari.

http://dean.edwards.name/weblog/2006/06/again/


"iBox is a lightweight script that lets you overlay images, divs, and HTML on your current page. It is damn easy to install and setup."

http://www.ibegin.com/blog/p_ibox.html


http://www.subdevide.com/portfolio/drop-shadows-with-css/


http://www.designdetector.com/link/to/ten-common-css-mistakes/


Sudden publicity for using flash as an XML data-source connector to replace XMLHttpRequest. Should I mention that the MetaWrap project introduced this into its Xml action library over a month ago? :) (testcase)

http://www.fjax.net/

http://incito.lt/index.php#/gateways/go.php?to=products/swfjax


Google AJAX API for search

http://code.google.com/apis/ajaxsearch/


"JavaScript Libraries: Friend or Foe?"

http://simon.incutio.com/archive/2006/06/26/libraries


Safari JavaScript Debugger

http://webkit.opendarwin.org/blog/?p=61


"AJAX is a great tool for creating rich internet applications, however, when improperly implemented it can cause huge accessibility issues. The good news is that most of these issues can be fixed so your websites are viewable by a much wider audience. "

http://www.maxkiesler.com/index.php/weblog/comments/how_to_make_your_ajax_applications_accessible/


An oldie but a goodie - CSS text size zooming with working example.

http://www.deltatangobravo.com/archives/2004/september/zoomzoomzoom


 

   
Sunday, July 02, 2006 12:28:17 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Friday, June 02, 2006

Nothing could stop me from putting this off a moment longer.

Here is a screen recording of my JavaScript Macro Recorder in action.

Here is a test URL for a page that has the JavaScript code embedded. Works under IE and Firefox. Safari "Real Soon Now" :)

Add these two lines of code into your pages <HEAD> element and your page will be recordable.

<script src="http://js.metawrap.com/mw_lib.js"></script>
<script src="http://js.metawrap.com/mw_pkg_macrorecorder.js"></script>

Post a comment and tell me how long it takes to load please :)

Latest thing to hold me back from recording this was of all things a broken finger and on top of that two days ago I got the flu.

5 days after my sons birthday party which was jam chocked with rug-rats, I come down with something. Why am I amazed?

Next year every adult gets a complimentary hazmat suit.

Every time I bump into Rachel I seem to have the flu. So far this has been a good year. I've gone so well and been lucky enough to only have a few days off work. I would like to be at home in bed at the moment but work is too busy.

I've not really had a chance to do any fun coding in the last month in the volume I would like, but I have this Monday off to relax and noodle away. I have some fun wireless gear to play with :)

Friday, June 02, 2006 1:30:43 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Tuesday, May 30, 2006

I want my children to grow up in a world when coding in JavaScript does not result in a fistfight.

Brendan Eich may have intended Arrays to be only numeric, but the reality is they do more, and people have explored and used them to the fullest extent.

It is arguable that people pushing the JavaScript envelope in this way have made Web 2.0 viable.

I won't blame people for being creative.

But now we have libraries that can't co-exist, libraries that come embedded with insoluble philosophies. 134 Ajax libraries and counting. Oh the huge manatee!

We have to lay down some ground rules or JavaScript is going bring some serious issues to the next generation of 'Internet Applications'.

Its a little like driving and everyone agreeing on the rules of the road. If we all do this, things will get easier. Its a form of best practice. Its not arbitrary. Its a realpolitik compromise that allows everyone to get most of what they want. Some people want to extend objects for reasons of syntax and performance, others want to keep them pristine to allow libraries to inter-operate.

I propose the following rules to allow us to move forward.

#1 - Don't use Object.prototype to extend the base 'Object'.

Feel free to play with any other builtin type. 'Array', 'Number', 'Boolean', 'Date', 'Regex',....  but leave 'Object' alone.

Dean Edwards sums it up best.

"Extending native objects is a good way to provide backward compatibility for older browsers (e.g. providing push/pop for IE5.0). If we can’t do this then we are stuck with only the basic features of the language.

Extending Object.prototype is another matter as then we are left with no object that we can use as a hash."

#2 - Don't use 'Array' for an Associative Array

Use 'Object' or people will come and take your Arrays away from you.

Anything that extends Array via Array.prototype will break for(in) loops. Because we are leaving 'Object' alone, we can use it as an Associative Object.

var x = new Object(); // var x = {}; will work too
x["a"] = "A";
x["b"] = "B";
x["c"] = "C";

It works. Try it. Now.

Now, I have seen lots of code in the wild that does use for(in) to iterate an 'Array'. It does seem to be a natural and forgivable thing for a programmer to do seeing the term is normally taught is "Associative Array", not "Associative Object".

Good reference sites give examples that use 'Array'.

We are choosing to stop this practice.

#3 - There are two types of Library 'Primary' or 'Secondary'

We are still going to have issues if two libraries choose to extend Array and add the same named method (eg. Array.prototype.sortbyname). The more likely pattern is that you are going to use a 'primary library' (prototype, dojo, yahoo etc...) with a group of other smaller scripts. (secondary libraries) that just do one thing well.

If you are developing a secondary library, avoid extending the base types. The primary library will enforce its philosophy via its extensions to the base types. A 'secondary library' should just do one thing well without having to change the fundamentals.

With the above guidelines we should be able to mix as main secondary libraries together as we want with at most one primary library.

Mixing primary libraries together is going to be hit and miss.

#4 - Port code that uses 'Array' for Associative Arrays

Port it to use 'Object', Send it back to the author with a link to this blog post.

Try using the new iterators that are built into JS1.5 and above.

The sooner that we fix these libraries, the better.

#5 - Write JavaScript Tools That Warn Of Rule Violations

Anyone writing JavaScript debuggers or JavaScript/HTML editors should add functionality to warn users if they see Arrays being used as Associative Arrays, or Object.prototype being used to extend Object.


Can anyone think of anything else or improve on the above please?

Tuesday, May 30, 2006 12:40:06 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [3]
 Sunday, May 28, 2006

Thanks to Damian for pointing out this site.

Now that Google maps works properly in Australia, someone has built http://www.bikely.com/ a very nice Google Maps mashup that allows you to share your favorite bike route. 

The behind the scenes story is that it was the result of a 4 day marathon coding effort that started right after Google switched on street maps for Australia.

I love it. Simple, sweet, Does one thing very well.

Sunday, May 28, 2006 10:46:02 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, May 24, 2006

Here is a screen recording of my JavaScript Macro Recorder in action.

Here is a test URL for a page that has the JavaScript code embedded. Works under IE and Firefox. Safari "Real Soon Now" :)

Add these two lines of code into your pages <HEAD> element and your page will be recordable.

<script src="http://js.metawrap.com/mw_lib.js"></script>
<script src="http://js.metawrap.com/mw_pkg_macrorecorder.js"></script>

Post a comment and tell me how long it takes to load please :)

I started writing this last year, finished it a few months ago and have spent the last few months tweaking and testing.

It is entirely written in JavaScript and does not need a proxy server of any kind.

You simply need to add a few lines of JavaScript to your page and a small text control panel is added to the page.

macro_recorder_cpanel.png

  • [record] will start recording.
  • [stop] will stop recording or playback
  • [play] will playback the current macro.
  • [fast] will play the macro back at faster than recorded speed
  • [loop] will loop the macro
  • [hide] will hide the control panel during playback

The control panel and the macro recorder itself is based around a simple plugin architecture. I have plugins close to completion that will load and save macros and record a suite of testcases of multiple macros across a whole site. 

I've also started on plugins that will transcode a recorded macro into Watir and Selenium formats.

Does not work under Safari, but there is no reason why it can't. Any Safari guns willing to help? More on that in the screen recording tonight.

Enjoy!

 

Wednesday, May 24, 2006 12:28:06 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [9]
 Tuesday, May 23, 2006

Simple and effective comic sketch (video) in which your browser plays a role.

http://www.circoripopolo.be/comicduo/

Tuesday, May 23, 2006 11:13:36 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, May 17, 2006

I wrote about this a while ago, but.. long story short... I'm getting ready to record an epic screen-recording of my Macro-Recorder developed in JavaScript.

It was clear that I needed the practice after the first test run.

So here is a screen recording of me demonstrating the MetaWrap logging class.

Short and sweet.

Wednesday, May 17, 2006 12:28:45 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Monday, May 01, 2006

It was a long time coming, but on Feb 28 2006, Microsoft released a patch (KB912945) for the Eolas patent dispute that "breaks" Active X in Internet Explorer, which includes Flash on Windows XP and Windows Server 2003.

This only affects IE.

Firefox, Mozilla, Opera and the rest are not affected.

[Update 28/7/2006] - The new Opera 9 IS affected by this.

eolas_opera.png

Opera Asking for Activation

Windows 2000 derivatives are not affected (yet) as a final decision on browser revisions for Windows 2000 is still pending. Luckily there is a simple JavaScript workaround for this patch. See my previous posting and workaround.

Because this first patch "broke" so many websites, Microsoft have also issued a "Compatibility Patch" (KB917425) that negates the Eolas patch until some time in June. "This Compatibility Patch will function until an Internet Explorer update is released as part of the June update cycle, at which time the changes to the way Internet Explorer handles Active X controls will be permanent."

This compatibility patch can prevent you from seeing the full effect of the Eolas patch. So, if you are a web developer and you want to know what the effect the Eolas Patch is going to have on the behavior of your site in IE, Make sure you don't have the Compatibility Patch installed!

It seems that it is possible to install the Eolas Update via an Automatic Update (KB912812) in such a way that the 'workaround' that Microsoft and Macromedia suggests does not function. I have encountered a small but worrying (given the sample size) number of machines with this issue.

I was able to install and then un-install the compatibility patch and all problems (see "The Whole Story" below) were resolved, for no apparent reason. See "Conclusions" at the end of this document.

How To Tell If You Have The Eolas Patch Installed

If you are running Windows XP, Open the "Control Panel" and then click on "Add Or Remove Programs" and make sure 'Show Updates' is ticked.

If you have the Eolas Patch, One of the following will be installed.

KB912812.png

The KB912812 Security Update which contains the Eolas patch (KB912945)

KB912945.png

Just The KB912945 Eolas Patch

The Whole Story

Now I previously blogged about the Eolas Patch and provided a detailed description of the workaround provided by both Microsoft and Macromedia. I was able to test this workaround by directly downloading the patch from MSDN.

Here is the time-line for the Eolas related patches (As accurate as I have been able to determine).

Jan 9, 2006 - Microsoft releases non-security update for Internet Explorer 6 for Windows XP Service Pack 2 to MSDN subscribers

Feb 9, 2006 - Update became publicly available on MSDN

Feb 10, 2006 - Update for Internet Explorer for Windows XP Service Pack 2 (KB912945) Via KB912812

"After you install this update, you cannot interact with Active X controls from certain Web pages until these controls are enabled. To enable an Active X control, manually click the control. There are also techniques that Web developers can use to update their Web pages. For more information about these techniques, visit the following MSDN Web site"

Feb 28, 2006 - Patch distributed as a “recommended update” on Windows Update for Windows XP Service Pack 2

April 11, 2006 - Published in Cumulative Update for Internet Explorer for Windows XP Service Pack 2 (KB912812)

Also in : Cumulative Update for Internet Explorer 6 SP1 (KB912812)

Also contains "Update for Internet Explorer for Windows XP Service Pack 2" (KB912945) which in the first description is...

"This update includes minor changes to how Internet Explorer handles some web pages that use Microsoft Active X controls. Certain webpages will require users to manually activate Active X controls by clicking on it or using the TAB key and ENTER key. This update contains all previously released security updates. After you install this item, you may have to restart your computer."

But in another location...

"After you deploy update 912945 for Internet Explorer, the behavior of the Internet Explorer Active X update that is contained in security update 912812 is disabled. The security fixes that are contained in security update 912812 are still present and will still function. Only the Internet Explorer Active X update behavior is disabled."

One of these is incorrect.

April 11, 2006 - "Compatibility Patch" - "Update for Internet Explorer for Windows XP Service Pack 2" ( KB917425)

"The IE Compatibility Patch reverts the IE Active X update behavior contained in the April Security update (KB912812). This patch should be used by customers who have experienced compatibility issues and who require more time to test/update websites and programs that are impacted by the IE Active X update. This patch is temporary, and will only apply to KB912812. This IE compatibility patch will not be available for future security updates. After you install this item, you may have to restart your computer. "

April 20, 2006 - Re-Release of "Compatibility Patch" "Update for Internet Explorer for Windows XP Service Pack 2" ( KB917425)

?? June 2006 - Compatibility Patch Expires

"This Compatibility Patch will function until an Internet Explorer update is released as part of the June update cycle, at which time the changes to the way Internet Explorer handles Active X controls will be permanent."

So "officially", this patch came through with "Cumulative Security Update for Internet Explorer (912812)" which was released on April 11th 2006.

But on machines with this patch I was still getting prompts for activation on sites with the workaround in place. This has been verified with sites that use custom JavaScript and the very good flashObject/swfObject JavaScript library.

eolas.png

I have also received feedback from clients with 'dodgy' install of windows with the Eolas patch that are still getting prompted for Active X "activation" despite the web-site having the workaround in place.

Removing KB912812 and KB912945, rebooting then re-installing KB912812 again seems to resolve the issue.

Also installing the compatibility patch and then uninstalling it seems to solve the problem

Conclusions

It is possible for the original Eolas patch to be installed in such a way that JavaScript workaround does not function. Installing the compatibility patch and then uninstalling it seems to solve the problem

If you are a web developer, beware - the "Compatibility Patch" may be masking the problems your site has with Flash and Active X when viewed in IE with Eolas patch..

Monday, May 01, 2006 5:14:08 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [5]
 Wednesday, April 19, 2006

Dear Google,

Your Firefox start page ( http://www.google.com.au/firefox?client=firefox-a&rls=org.mozilla:en-US:official ) may or may not have a CSS error.

I know I'm being picky, the page functions fine, but you see every time I open Firefox (1.5.0.2) and test some JavaScript code, I open the Firefox JavaScript Console to see if my code did anything bad, and I am presented with this.

google_please_fix.png

And my poor little heart skips a beat.

Until I realise that its not me. Its you. I think.

Maybe its a Firefox Bug?

I'm sure you can get to the bottom of it, you are so big, strong and clever.

Thank-you.

Wednesday, April 19, 2006 6:17:36 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Thursday, April 13, 2006

As you now probably know, Microsoft has released a patch to IE6 because they have failed on appeal to overturn the Eolas patent on browser plug-ins, despite much back and forth and valiant efforts from the W3C.

The effects of this patch are replicated in the latest IE7 browser  which is part of Windows Vista.

This is going to primarily affect Flash, Windows Media Player and Java Applets.

AJAX is not affected (You can go back to reading "Getting Real" now :) ).

The symptom of this patch is that a user is unable to interact with an embedded object without first acknowledging a tool-tip prompt with a mouse click or key press anywhere to the embedded object.

So, your embedded object (Flash/Windows Media Player etc..) will play and animate, but a user will not be able to click any buttons, enter any text, or activate any rollovers until that first acknowledgement occurs.

Perhaps every time you click, someone at Eolas gets a penny :)

The prompt for acknowledgement is a small and subtle tool-tip and a highlighted border around the embedded object, both of which are easily missed. You may just notice that you need to click a flash button twice instead of once before you realise what is going on.

Guidance has been provided by Microsoft and Macromedia on how to bypass this problem.

Here is my summary.

Luckily the patent is so specific on how an embedded object is added to a HTML page and activated, it can be easily coded around.

The patch will only affect plug-ins that are

1) Embedded via explicit <embed, <object or <applet elements in a HTML page
2) Written into the page via JavaScript declared in the HTML page

flash_embedding_bad.png


If your elements are written into the page by an external function (a function declared in an included JavaScript file eg. "my_functions.js") and the function writes this content into the page via a document.write() or some DOM manipulation, then you won’t trigger the patch.

If you have pages that are affected by this patch then the solution is as follows..

1) Any explicitly embedded <embed <object or <applet elements should be moved into a function in a .js file that gets included by the main page.
2) Any JavaScript in the page that is adding <embed <object or <applet should be wrapped in a function and moved to a .js file that gets included by the main page.

flash_embedding_good.png


As long as the document.write() is performed in an external function, then your embedded elements will work.

You can generate a string containing the elements in the main page and pass it into an external function that simply does the document.write() for you..

function write_string(p_string)
{
  document.write(p_string);
}

And it will not trigger the prompt.

In the future..

  1. If you are using Flash, it is best practice to use flashObject , if you are not already.
  2. It is considered A Good ThingTM to have just content markup in your HTML and move all functions and style onto external .css and .js to avoid the dreaded Tag Soup. If you do this already then pat yourself on the back and relax, this patch won't affect you.
Thursday, April 13, 2006 3:32:39 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Thursday, March 30, 2006

Or-Assignment

In many languages a boolean expression eg "good OR bad OR ugly" will return a boolean object with one of two values, true or false. In the case of "good OR bad OR ugly" it will return true if any one of good, bad or ugly evaluates to true.

In JavaScript 

  1. A boolean OR expression will return that actual value that was evaluated to be true. These are executed in order and the first one to be true is returned, the rest are not evaluated.
  2. A reference that is null or undefined will be false, and a valid reference will be true.

This can make cross browser code rather compact, because very often you are checking for a value or reference that may be undefined in one browser, but defined in another.

so instead of

if (this.defaultView)

{

l_window = this.defaultView;

}

else

if (this.parentWindow)

{

l_window = this.parentWindow;

}

else

{

l_window = null;

}

you can write simply, which will assign a value to l_window of either this.defaultView or this.parentWindow, depending on which is non null.

l_window = this.defaultView||this.parentWindow; 

These are executed in order and the first one to be true is returned so you can mix this up and get some rather complicated behaviors by ordering them on order of desirability and you can optomise these by placing the most common first.

Here are some testcases that probe the behavior of 'Or-Assignment'.

Multiple Returns

Suppose you want to return more than one object from a function. In most structured languages this is a matter of have defined a structure/class to return your multiple values in.

function multiple_out(a,b) { return {x:a , y:b}; } var l_result = multiple_out(1,2);

In JavaScript you can simply roll an object dynamically and add some named objects and return them.

I just went through some JavaScript code and managed to get a speed increase with minimal change to the code using this method.

See this testcase for some examples.

 

Thursday, March 30, 2006 1:54:50 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Tuesday, February 21, 2006

arguments

The arguments object provides access to the arguments that are passed into a function.

You can refer to a function's arguments within the function by using the arguments array. This array contains an entry for each argument passed to the function.

The arguments array is available only within a function body. Attempting to access the arguments array outside a function declaration results in an error.

eg.

function Average() 
{ 
   var sum = 0 
   for(var i=0; i < arguments.length; i++) 
   {
      sum = sum + arguments[i] 
   }
   return (sum/arguments.length); 
}

You can use the arguments array if you call a function with more arguments than it is formally declared to accept. This technique is useful for functions that can be passed a variable number of arguments.

You can use arguments.length to determine the number of arguments passed to the function, and then process each argument by using the arguments array. (To determine the number of arguments declared when a function was defined, use the Function.length property.)

Example.

function listItems() 
{
   var items = arguments.length
   document.write("<UL>\n")
   for (i = 0;i < items;i++)
   {
      document.write("<LI>" + arguments[i] + "\n")
   }
   document.write("</UL>\n")
}

The function may be called as follows:

listItems("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Happyday");

 

The arguments object has some very handy members.

arguments.length

The number of arguments passed into the function.

arguments.callee

This property is a reference to the function that you are in. Which is very handy if you want to get a reference to an anonymous function from inside itself. One good reason for doing this would be in a recursive anonymous function.

function makeFactorialFunc() 
{
   return function(x) 
   {
      if (x <= 1)
       {
         return 1;
       }
       return x * arguments.callee(x - 1);
   };
}

var result = makeFactorialFunc()(5); // returns 120 (5 * 4 * 3 * 2 * 1)

arguments.caller

This property is a reference to the function that called the function you are in. This allows you to get access to the entire current callstack which is very handy for debugging.

function myFunc() 
{
  if (arguments.caller == null) 
  {
    return ("The function was called from the top!");
  }
  else
  {
    return ("This function's caller was " + arguments.caller);
  }
}

 

There are two other things you can do with the arguments object if you combine it with the fn.apply function.

Pass arguments from function to function.

function Called(a,b)
{
	return (a + " certainly " +  b);
}

function Caller(a,b)
{
	return(Called.apply(this,arguments));
}
Fake arguments by creating an array
function Called(a,b)
{
	return (a + " certainly " +  b);
}

function FakeCaller(a,b)
{
	var l_arguments = new Array();

	l_arguments[l_arguments.length] = a;
	l_arguments[l_arguments.length] = nb;

	return(Called.apply(this,l_arguments));
}

See this test-case for an example of both of these cases.

Tuesday, February 21, 2006 9:59:20 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [5]
 Friday, January 27, 2006

Its a few vowels short of a buzzword, but don't hold that against it.

There is a strong trend at the moment towards dynamic resolution dependent layout via JavaScript, that is the page rearranges the layout of its content via element-wise x,y positioning or changes to some of it's fundamental CSS properties in response to changes in the browser window size.

We have used this rather effectively in the V8 Supercars Media Center Application.

Here are some examples (Load the pages and re-size the windows).

Example 1

Example 2

Here are some good posts

Latest post of interest by The Man In Blue.

Keven Hale discusses it here.

PPK had something to say about it.

Friday, January 27, 2006 12:07:33 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Tuesday, January 24, 2006

Article by Simon Willison on escaping in regular expressions in JavaScript.

"JavaScript's support for regular expressions is generally pretty good, but there is one notable omission: an escaping mechanism for literal strings. Say for example you need to create a regular expression that removes a specific string from the end of a string."

Updated cursor position script from Beau Hartshorne

"I discovered that IE’s clientX and clientY measurements were sometimes a couple pixels out. It turns out this is because IE’s clientX and clientY measurements start from (2,2) in standards mode, and (0,0) in quirks mode.

IE stores this offset in its document.documentElement.clientLeft and document.documentElement.clientTop properties. This code should calculate the correct cursor position in all current browsers:"

Tuesday, January 24, 2006 11:06:47 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Monday, January 09, 2006

Great post by Dave Johnson that replicates and surpasses some of the benchmarking I have already into the practicality of using XSLT.

This is why XSLT is at the heart of the MetaWrap JavaScript Rending Pipeline.

The rendering pipeline and macro recorder are my current primary research interests - should have an interesting announcement in the next few months..

Monday, January 09, 2006 1:47:19 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Saturday, January 07, 2006

I was not prepared for the amount of responses I got to my last article. There really are two camps - and they sit around fires making pointy sticks.

The most constructive was from Rob Sanheim with this post, which got me rather excited.

Now before I code anything, I write a set of testcases. Testcases let you play with your API and sort out the semantics and 'feel' before you get too far into the project to change it. Testcases - Just Do It. (You know who you are).

So within 10 seconds of reading Rob's post I popped the latest prototype.js into my test system and had my result.

I used to have 1 extra dangleberry named 'extend' in every JavaScript Object. At least with that I had a fighting chance.

With prototype.js version 1.4.0 I have 33.

Here they are in all their tentacled glory.

each 
all
any
collect
detect
findAll
grep
include
inject
invoke
max
min
partition
pluck
reject
sortBy
toArray
zip
inspect
map
find
select
member
entries
_reverse
_each
clear
first
last
compact
flatten
without
indexOf

Now, I'm not complaining but, oh hang on - I am.

My previous fix for my rendering pipeline is completely out the window.

Now on top of my previous complaint, I'm wondering what the performance hit is for always having 33 objects to check against on every object slot access? In theory if the slot manager uses a good hashtable this won't be more significant than having just one object.

I have a library that can measure this, but prototype.js breaks it.

Its 3 o'clock and on the dark side of breakfast - for now I will sleep on this.

Saturday, January 07, 2006 2:30:55 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [10]
 Thursday, December 29, 2005

When it comes to JavaScript there is one issue for which there seems to be two polarised camps, and that is the question of extending the inbuilt JavaScript Array and Object types via the prototype object. There are those who do, and those who don't.

I am most definitely one of those in the "Don't, because it 'would be bad'" camp.

Now, thanks to the Web2.0/Ruby On Rails/Nuevo Bubble phenomena there is a widely used library that makes great use of the prototype object and that is Sam Stephenson's prototype.js library.

I ran into an issue 6 months ago and decided I would never ever use prototype.js, despite the fact, and I don't say this often, that after an examination of the code, prototype.js is an inspired work of art.

What I and many many others have discovered is that using the prototype object on the Array and Object inbuilt types increases the chances that your code will conflict with existing or external code. It makes your code not play well with others, so once you start using prototype.js, you have to keep using prototype's paradigm because by extending Array and Object via the prototype object it secretly modifies some of JavaScripts default behavior.

It's the crack cocaine of JavaScript.

This can be a good thing. If you don't want to waste time writing your own JavaScript libraries and learning how everything really works, then using prototype.js and the libraries that extend it (e.g. Open Rico) is a very good way of developing. You will save time and money and all you need to learn is "the way of prototype.js".

Now the entire tasty raisin for the MetaWrap JavaScript libraries is to allow others to easily remix MetaWrap applications via a client side API that can be invoked via XML. The result is that CSS, HTML and JavaScript can be injected into the application, or XML and HTML at any point in the rendering pipeline of the application.

So I simply had to reject prototype.js because, out of the box, the very first time I tried to use it – it snuck out and cut the throat of the JavaScript I was using that relied on performing a for(x in object) on the contents of an Array.

In JavaScript, value types are subdivided into primitives and objects. Objects are entities that have an identity (they are only equal to themselves) and that map primitive properties to other value types, ("slots" in prototype-based programming terminology) - see these testcase #5 - #7. Because of this behavior JavaScript objects are often mistakenly described as associative arrays or hash tables, while functionally they behave like an associative array/hash table, technically this is not their true nature.

Despite this the JavaScript programming world has come to rely on these objects behaving as predictable associative array/hash tables - and prototype.js breaks this.

There is no object more galactically useful than a good associative array/hashtable. There is no problem that can't be solved with a large enough hash table. In highly granular interpreted languages like JavaScript it provides a way to dip into pure native brute force computing power mostly unhindered by the language interpreter.

It is because this has been tampered with that I have to turn my back on prototype.js and say Nyet!

Now lets look the issue in some detail and in particular at the way that JavaScript uses arrays and the way that we create and access data in those arrays.

Although in reality there is one method to access data in an array array[value] = object;, there are two defacto methods. The first is numerical indexing, whereby you access each element in the array by a single number - this is supported by the inline constructor, shorthand and the array.push functions that add items to an array automatically via a numerical index.

The following three approaches will create an identical numerically indexable array.

E.g.,

"Specified numerical index"

var array = new Array();
array[0] = "Apple";
array[1] = "Orange";
array[2] = "Banana";

"Push"

var array = new Array();
array.push("Apple");
array.push("Orange");
array.push("Banana");

"Inline Constructor"

var array =new Array("Apple","Orange","Banana");

"Inline Constructor Shorthand"

var array = ["Apple","Orange","Banana"];

The elements of this numerically indexable array can be accessed via the following methods...

By directly indexing into the array with a number using for(;;)

var i; 
for(i = 0;i >array.length;i++) 
{ 
  alert(array[i];)
} 

or via the for(in) iterator

for(var i in array) 
{ 
   alert(array[i]);
}

But I mentioned there were two methods to store and access data in arrays..

The second is as an 'associative array/hash table', where in the index is not an number, but one of the other primitive value types (String or Float for example).

var array = new Array();
array["A"] = "Apple";
array["O"] = "Orange";
array["B"] = "Banana";

In this case array.length will be 0. There are three items in the array - but is length property will return 0.

This array is only useful if you know what the primitive value index is for a particular object. Array look-up performed natively within the interpreter so is very fast, which makes for a perfect hash table structure, but if you want to iterate all items in the array, you have to use the for(in) iterator method.

Sadly – protoype.js breaks this by adding 'extend' object that appears in every array.

So you have to be very careful about how you introduce external JavaScript that is not based on prototype.js. Prototype uses the JavaScript prototype level expando trick (via the prototype. keyword) to add extra objects to the inbuilt function and Array, Object and Function types.

After you include prototype, every array gets an extra element.

See these testcases.

When you execute testcase #1 this it will result in "extend A B C " instead of "A B C" - so it fails.

Now this can be remedied by the next testcase #2 that does not use for(in) but instead uses a numeric index into the array via an old style incremented for(i = 0;i<array.length;i++).

For associative arrays, there is no hope. Prototype makes associative arrays unreliable when it comes to using the for(x in array) loop.

The only way I can protect my code is to not use for(in) for an array that is not associative, and for associative arrays, treat 'extend' as a sentinel that gets skipped.

// Guard against prototype
if (l_node == "extend") continue;

The problem I am describing here is the result of one of the extensions made by prototype.js (version 1.3.1)

Object.prototype.extend

There are 5 others..

Array.prototype.push

On browsers that don't already implement push (IE5) then this will appear in an enumerated version of the array via for(x in object).

Function.prototype.bind

Function.prototype.bindAsEventListener

Number.prototype.toColorPart

Function.prototype.apply

String.prototype.extend


Thursday, December 29, 2005 12:55:14 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [26]
 Wednesday, December 14, 2005

Great article by Gez Lemon on the Minimal HTML document and the difference between required tags and required elements.

Wednesday, December 14, 2005 10:40:22 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Friday, December 02, 2005

A list ofg Common CSS Bugs in Safari, Firefox and Opera by Andy Budd.

An article by Ryan Campbell on the good bits in Sam Stephenson's Prototype library.

A further article by Justin Palmer on prototype.

I've been busy in low level C land in the last few weeks - nothing much to blog about .. yet :)

Friday, December 02, 2005 2:32:04 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Monday, November 21, 2005

Cool article that takes the concept of design patterns and applies it to web development.

"....In short, we lack a pattern language for the web.

But is our discipline mature enough to develop this vocabulary and language? Only trying to do just that will tell. "

http://westciv.typepad.com/dog_or_higher/2005/11/webpatterns_and.html

I need to read and digest this before I take another step in my MetaWrap development. I was sick most of last week and have been busy working on the back-end and tinkering with the rendering pipeline.

It used to be that JavaScript frameworks would just abstract away the inconsistencies between browsers. They were essentially experience in a bottle.

Traditional programing frameworks are useful if they implement common design patterns that result in efficiency in execution and program flow. These are ‘best-practice’ in a bottle.

I feel that the best possible framework is one that provides an ultra-light scaffolding for the application as a whole, and then lots of small, intuitively named and useful design patterns that a programmer can wire together into an application

My girlfriend pointed out some obvious flaws in my pipeline philosophy and raison dêtre, that being that it makes not a lot of sense in its current form. It should fit into the light scafolding category, and in a way it is mostly invisible to the user, but it is a major concept to understand how your data, styles and behavior get into your application in the first place.

I need to explain it better. I think it may be one of those complex things that people will make the effort to understand it, once its seems to be worth learning.

Monday, November 21, 2005 11:01:30 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, November 09, 2005

Another company working with automatically generated JavaScript.

Morfik offers ground-breaking Javascript Synthesis Technology (‘JST’) that allows developers to use a visual design environment and a high-level language of their choice to create applications comprising only of HTML and Javascript. This revolutionary technology combined with its tight integration of the browser, a database and web server, uniquely offers developers the opportunity to create web applications that run on the desktop after being unplugged from the web.

http://www.morfik.com/

Wednesday, November 09, 2005 10:01:13 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Tuesday, November 01, 2005

"The update also makes Safari the first major browser to pass the Acid2 test. The probe verifies a browser's compliance with several current internet standards. A quick probe by vnunet.com found that neither of the current versions of Firefox, Internet Explorer or Opera passed the test."

http://www.vnunet.com/vnunet/news/2145215/apple-sharpens-tiger-teeth

http://docs.info.apple.com/article.html?artnum=301984

Tuesday, November 01, 2005 2:42:30 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Sunday, October 23, 2005

My addEvent replacement now supports the full emulation of W3C standard cancelBubble and stopPropagation in event capture and bubbling mode in browsers that don't support W3C events (IE, Opera).

Here is a test case. If someone can break this and help me find any bugs I'd be very grateful.

Seems to work in Opera, IE5, IE5.5. IE6, Firefox 1.5, Mozilla, NS6.2, NS7.2, NS8

Will test it in Safari later, should work fine in but that browser has bitten me in the past.

/*!
    @fn         MetaWrap.Page.Element.stopPropagation = function(p_event)
    @param      p_event Reference to the event we want to cancel
    @return     void
    @brief      Cancels an event. 
    @author     James Mc Parlane
    @date       23 October 2005
    
    Allows events listeners on the current element to fire, 
    but prevents any listeners on any other events from firing.
*/ 
MetaWrap.Page.Event.stopPropagation = function(p_event)
{
    // If we have a native version
    if (p_event.stopPropagation)
    {
        // Then use it
        p_event.stopPropagation();
    }
    else
    {
        // Simulate it - the rest of the simulation code 
        // will interpret cancelBubble correctly
        p_event.cancelBubble = true;
    }
}
Sunday, October 23, 2005 6:11:36 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Saturday, October 22, 2005

[UPDATE] I have updated this with information gleaned from http://jibbering.com/faq/faq_notes/closures.html on the true nature of closures and performed an experiment. Its worse than I thought. The 'shotgun' nature of scope closure in JavaScript means that its very easy to write leaky code. One of the problems with JavaScript is that you can make an effective closure over objects that are not explicitly obvious if you look at the code within the closure itself.

The very general rule of thumb seems to be The deeper you are in scope when you create your closures, the more likely you are to have leakage.

Updates are in italics.[/UPDATE]

Why does IE leak when closures are used in event listeners?

  1. When a closure causes a circular reference. 
  2. A blind spot in the IE garbage collector for circular references involving DOM elements. IE uses uses "mark and sweep" for JavaScript objects, but it has a blind spot in that it uses COM "reference counting" for DOM objects.

Now, when I say closure, I don't just mean an anonymous function. I mean a real closure, although the way that JavaScript handles scope closure this becomes effectively a moot point.

The following is not a closure, because it does not reference any variable out of scope of the function.

function(){var x = 0; return x;}

The following is a closure in the traditional sense, because the function references l_a, which is declared outside the scope of the function.

var l_a = 1;
var l_f = function(){var x = l_a; return x;}

In JavaScript the following is effectively a closure too, because when you declare a function in JavaScript it gets a reference to the scope that it was declared in, and that scope contains references to all the objects that are declared in that scope. Even if you didn't intend to maintain a reference to l_a from the closure, you effectively are.

var l_a = 1;
var l_f = function(){var x = 0; return x;}

Now here is an important bit, every closure that contains an intended or unintended out of scope reference to the same variable in the same scope will be referencing the same object. And any change to that referenced object will be visible to all closures.

So...

var l_a = 1;
var l_f1 = function(){return l_a;}

l_a = 2;
var l_f2 = function(){return l_a;}

alert(l_f1());
alert(l_f2());

Both l_f1() and l_f2() will return 2 [TEST] because they both reference l_a in the same scope.

 

closure_scope_simple.png

Closures declared in the same scope referencing the same variable.

 

This is because all closures declared in the same scope maintain a reference to the same scope, so any changes you make to any variables declared in that scope or any other sub-scope are visible to the closure.

In the case of a memory leak pattern, if these closures were event handlers, then your leak would include l_a and because of scope closure l_f1 and l_f2

But a benign looking improvement to this code can cause many more leaks and change the behavior of the code.

function MakeClosure(p_a)
{
    return function(){return p_a;}
}

var l_a = 1;
var l_f1 = MakeClosure(l_a);

l_a = 2;
var l_f2 = MakeClosure(l_a);

l_a = 3;

alert(l_f1());
alert(l_f2());

In this case, l_f1() will return 1.. but l_f2() will return 2 [TEST]

Why?

l_a is a scalar value, it is being copied onto the stack in each scope that is created when you call MakeClosure, so p_a is not a reference to the original l_a, it is a copy of the value of l_a at the point of which MakeClosure() is called in two different scopes.

   closure_scope_2level.png

Closures declared in different scopes referencing different copies of a variable

Now here is another important bit..

If the above pattern was involved in a leak pattern, you would leak one copy of p_a for every time MakeClosure() is called because the scope of MakeClosure(), which includes the declaration of p_a is referenced by the closure.

This does not apply to object references. See the following.

function MakeClosure(p_o)
{
 return function(){return p_o.m_a;}
}

var l_o = new Object();
l_o.m_a = 1;
var l_f1 = MakeClosure(l_o);

l_o.m_a = 2;
var l_f2 = MakeClosure(l_o);
l_o.m_a = 3;

alert(l_f1());
alert(l_f2());

In this case both l_f1 and l_f2 return 3 - because p_o is a reference pointer to the original l_o. [TEST]

closure_scope_2level_object.png

Closures declared in different scopes using different references to the same variable

So if the above pattern was involved in a leak pattern you would leak three objects, l_o, l_f1 and l_f1 no matter how many times you call MakeClosure();

So why does the following code leak so badly? [TEST]

window.onload = init;

function init()
{
 // Start timing
 var T1 = (new Date()).getTime();

 createLinks();

 var x = document.getElementsByTagName('a');

 for (var i=0;i<x.length;i++)
 {
  assignListener(x[i]);
 }

 // How long did that take?
 alert("it took " + ((new Date()).getTime() - T1) / 1000 + 
 "seconds to render this\r\nHit F5 and see "+
 "what happens to the render time.");

}

function assignListener(p_e)
{
 p_e.onclick = function ()
 {
  this.firstChild.nodeValue = 'CLICK';
 }
}

Every time we call assignListener(p_e) we are creating a new scope that contains a new and unique reference, so we are leaking multiple scopes and because each p_e is a references to a different DOM object, it comes under the garbage collectors blind spot.

The following leak pattern is established for every element reference passed as a parameter to assignedListener.

IE_leak_closure_1.png

Every time we call assignListener() we create a new scope that contains a reference to a DOM element.

If we were to be sensible and use 'this' instead of p_e, then we would avoid the issue all together.

The deeper you are in scope when you create your closures, the more likely you are to have leakage.

But - these leaks are very subtle. Its not always obvious that they are going to occur, even when we do something innocent looking. One of the problems with JavaScript is that you can make an effective closure over objects that are not implicitly obvious if you look at the code in the closure itself.

There are four possible solutions.

  1. Ban closures as event listeners - but they are very useful and they are just one part of the IE leakage issue.
  2. Force programmers to go through a complicated framework that has no leak patterns. Lets face it, You can't force a programmer to do anything and its not going to stop them from accidentally writing leaky code.
  3. Wait for IE7 and hope it does not leak.
  4. Write your own garbage collector. This is what I did in my solution, but a very focused one. Any element that gets a listener assigned gets very carefully scrubbed after I am finished with it. Any element that is attached to a structure but is not part of the DOM is 'garbage collected'

Full points to anyone who gets the twisted 'Cabs' reference in the name of this topic. :)

[UPDATE]

Here is my updated element scrubber.

/*!
    @fn         MetaWrap.Page.Element.scrub = function(p_element)
    @param      p_element A reference to the element we want to scrub
    @return     void
    @brief      Nulls element references that commonly cause circular references.
    @author     James Mc Parlane
    @date       23 October 2005

    Called for every Element that is garbage collected by 
    MetaWrap.Page.garbageCollectListeners() or by the teardown code
    MetaWrap.Page.deleteListeners()
    
    As a generic leak pattern cleanup, this solution is only    
    effective for elements have had a listener added via
    MetaWrap.Page.Element.addEventListener
    
    Works by nulling event listeners and custom expanded members.
    
    This will only work if you use the following naming standard 
    for your custom expansions of the element object.
    
    m_XXX eg. m_flipover    
    $XXX eg. $flipover
*/ 
MetaWrap.Page.Element.scrub = function(p_element)
{
    // For each member of the element
    for(var l_member in p_element)    
    {        
        // If its an event listener or one of my user assigned 
        // members m_XXX, $XXX (self imposed naming standard)
        if ((l_member.indexOf("on") == 0) || 
            (l_member.indexOf("m_") == 0) || 
            (l_member.indexOf("$") == 0))
        {
            // Break the potential circular reference
            p_element[l_member] = null;
        }        
    }
}
Saturday, October 22, 2005 3:26:17 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Thursday, October 20, 2005

Good documentation is a battle between telling a memorable fable and overloading people with detail.

I've sat down and drawn another diagram (see below) of the MetaWrap rendering pipeline as I'm still in the process of mulling over the design.

I was inspired by the drawing style in this article to have tried and re-describe the pipeline in terms of traditional layers but relate in another axis the logical elements of the pipeline.

I'm looking for the perfect diagram that captures the concept accurately without being overly detailed. What I have now is still flawed, but I think I am getting there.

First a brain-dump of where I was, where I am now and where I am going.

The purpose of the MetaWrap rendering pipeline is to provide a client side framework for web application development in the MetaWrap platform. I built a working prototype 5 years ago, and this is a refinement of that prototype. A lot more processing power is available now and I can and will take the original idea much further.

  • Applications developed within MetaWrap framework can be easily remixed (see GreaseMonkey ). The rendering pipeline provides access to raw XML data as well as the final HTML output, so you can remix the data, the UI or both at the same time.
  • Applications can be easily re-skinned.
  • Applications can be easily transcoded into other platforms. eg. XHTML, CHTML, WAP

All of this can be done at the whim of the consumer of the application.

Thats the aim anyway :)

The input of the rendering pipeline is XSLT and XML which all originate from a MetaWrap server.

The output of the rendering pipeline is CSS, HTML, JS and XML.

A web browser gets the XSLT and XML out of the MetaWrap server via a HTTP request to an Apache web server running a module that implements the MetaWrap HTTP Gateway. The MetaWrap Apache module connects to a MetaWrap server. The XML and XSLT is obtained by fetching and translating objects from the MetaWrap server.

metawrap_pipeline_all.png

The rendering pipeline excutes within the MetaWrap Apache module and JavaScript libraries. I have a mostly working prototype of the pipeline in the following test case here.

If the browser is not capable or fails during any stage of the rendering pipeline, that stage can be substituted by the Apache module.

When a browser makes a request against the MetaWrap Apache module, the URL is translated and mapped into an object of focus. A focus can be anything from a single string to a full application. Via the focus, appropriate XML and XSLT can be generated. Via the consumers user context, customised behaviors can be loaded.

In the best case scenario, the browser simply takes XML and XSLT and execute the whole pipeline in JavaScript.

In the worst case scenario, a braindead or buggy browser simply takes XML, HTML, CSS and JS from the Apache Module.

Why do it this way?

XML data, XML behaviors and XSLT can be cached, saving a large proportion of the traffic from the web server for most applications.

The processing associated with rendering layout can be moved from the server to the client which prevents your server from burning a hole through the floor.

An application server essentially becomes an API that is accessed via XML over HTTP and a database of styles and behaviors to associate with and application and user.

Thursday, October 20, 2005 11:00:24 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]

At last a resource that describes exactly how memory leaks occur in IE, written by the only people qualified to know, Microsoft.

"In the past, memory leaks haven't posed huge problems for Web developers. Pages were kept relatively simple and navigation between different locations within a site was a great way to clean up any loose memory. If there was a leak, it was most likely small enough to go unnoticed.

New Web applications live up to higher standards. A page might run for hours without being navigated and retrieve updated information dynamically through Web services. Language features are pushed to the breaking point by combining complex event schemes, object-oriented JScript, and closures to produce entire applications. With these and other changes, certain memory leak patterns are becoming more prominent, especially those previously hidden by navigation."

Glad to see that my own mental model of the issue was spot on for the first two patterns so all my current cleanup code seems correct. The last two patterns are new to me; I have never encountered them, but are worth good hard study.

Rather shocked to find out that IE uses COM "reference counting" instead of the modern "mark and sweep" method which is immune to circular references.

I used to believe that the issue was simply a blind-spot in IEs garbage collector with event listeners, but from this article it seems that all circular references that include DOM elements are potentially harmful and the only antidote is effective cleanup code.

Also.. a handy dandy IE leak detector

http://www.outofhanwell.com/ieleak/

Try the detector against these testcases

test_19_ie_leak.html
test_20_ie_leak_noclosure.html
test_21_ie_leak_fix.html

Thursday, October 20, 2005 2:32:11 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, October 19, 2005

Not me - and there is a slight twang of disappointment, but its hardly so very surprising - the competition was simply to recode addEvent, and my solution was for the entire class of event registration problems that plague all the current browsers and the associated memory leakage issues in IE.

The competition drove me to make my solution as thorough as it could be, and its happily powering the MetaWrap WireWrap behavior library and providing a reliable rock solid base. No matter what browser, no matter what event propagation mode I use, even when I mix them, its consistent across all the browsers I'm targeting.

And that makes me a very happy camper :)

Wednesday, October 19, 2005 1:31:27 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [2]

Someone else who is on the same wavelength but can make much better diagrams :)

http://particletree.com/features/4-layers-of-separation/

 

Wednesday, October 19, 2005 11:35:00 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]

Glad that someone has gone off and done this.

http://h3h.net/2005/04/faulty-firing/

This is part of the knowledge that I need to acquire if I am ever to get the JavaScript macro recorder to work consistently. The next stage of development is to complete the  event simulation and translation functions. A macro recorded on one browser needs to be translated into the language of another browser or it won't work.

Wednesday, October 19, 2005 11:10:24 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Thursday, October 13, 2005

This is one of my current little research projects.

MetaWrap WireWrap is an XML format for defining behaviors that can be dynamically applied to HTML. It can be used stand-alone but is designed to be the client end for application objects served out of a MetaWrap server cluster.

The MetaWrap Apache module runs on one or more Apache servers and acts as the HTTP serving platform. Any stage of the WireWrap pipeline can be performed inside the Apache module or the browser, depending on the capabilities of the browser.

I have a working prototype of the client side of the process.

Been doodling and designing the final rendering pipeline.

The concept is that a user can have an application and then apply their own styles and behaviors to the application via chosen defaults or customised behavior XML. In effect the UI of each MetaWrap application is open and can be manipulated in a similar manner to the way GreaseMonkey lets existing web applications be modified by the user.

In its simplest form...

PublishingFlow_Summary.png

 

But this is a more accurate representation of the possible data paths.

 

PublishingFlow.png

Click For Larger version

Thursday, October 13, 2005 12:30:20 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Tuesday, October 11, 2005

I have come across an interesting bug in IE.

In a web page I dynamically create 8 flash <embed> elements using document.createElement.

If I stop using document.createElement. The bug goes away.

If I clear the cache and load the web page, the flash takes a minute to load. See the following load trace from HttpWatch.

flash_load_1.png

WTF?

The first two requests happen right away, every other request takes 10 seconds up to the last one but none of the requests complete until the last one is finished.

CPU usage is 0. IE just seems to sit there and wait.

If I leave the files in the cache I get the following.

flash_load_2.png

Every time I clear the cache, the pattern is the same. 10 seconds. The first 2 files take the same time to load. Everyone after that takes 10 seconds. All seem to finish at the same time. The last one loads 'normally'.

If I remove any one or more of the flash elements - I get the same pattern.

6 Flash elements

flash_load_3.png

3 Flash elements

flash_load_4.png

The problem goes away when I get to 2 Flash elements.

Note that the first two files have a result of 206. This is an artifact of streaming in flash. If I remove the first two. The next two have this result. So the first two stream. The next do not. Maybe only two can stream at once and that causes an issue?

flash_load_5.png

It could be that the default behavior of flash to stream is part of the issue.

If I stop using document.createElement and emit the <embed> elements using innerHTML. The problem goes away.

So what could be happening? I have tried rebooting. A different machine. Turning off hyper-threading. No joy.

Astoundingly, If I put a JavaScript 

alert("meep"); 

...between each of the flash element creation calls. The problem goes away. So it seems that allowing the windows message pump to process has something to do with the issue.

All I can come up with is the following 'theory'.

When the elements are added with document.createElement, they are not individually processed. At some point the IE document renderer goes through the added <embed> elements and processes their setup code all at once. If the flash file is not in the cache, a http GET request is made for each one. So we get 8 rapid requests for flash files.

Two GETs good.. three GETs bad.

I believe that more than three requests causes a deadlock in IE, and that somewhere there is some code that can deal with the deadlock that fires off every 10 seconds to process then next request.

If I add an alert between each creation the windows message pump is activated and is able to either IE process the setup code or the http request of the <embed> element, and the deadlock never has a chance to trigger.

The issue may be restricted to flash which streams by default.

I'm wondering if this affects just flash or other resources using <embed> as well?

Has anyone else encountered this or have a possible explanation?

I have my solution - that is to stop using document.createElement and instead use innerHTML and pray I never have to use xhtml.

Tuesday, October 11, 2005 6:46:00 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]

I have a requirement to dynamically add flash elements into a page and have FSCommand function properly.

FSCommand is the primary method that Flash gives a programmer to execute scripts within the parent browser.

This requires some shim code to be added as a listener. This listens for script calls from Flash.

According to the Macromedia examples the listener shim must be created using VBScript. So if my flash object has an id of "flashBufferingPlayer" I would require the following VBScript code that could then do a 'call' out to JavaScript.

<script language='vbscript'>

Sub flashBufferingPlayer_FSCommand(ByVal command, ByVal args)

   call flashBufferingPlayer_DoFSCommand(command, args)

end sub

</script>

Even though Macromedia have examples that use pure JavaScript they don't seem to work.

So at first glance it seems that the listener must be VBScript.

But there is a serious issue with adding both JavaScript and VBScript dynamically after document.onload is triggered

  • Adding script via innerHTML does not work. Testcase.
  • Using document.createElement appendChild does not work.
  • Using document.write creates a new document.

Luckily Macromedia is wrong - the following Pure JavaScript will work.

<SCRIPT event=FSCommand(command,args) for=flashBufferingPlayer>

   flashBufferingPlayer_DoFSCommand(command, args);

</SCRIPT>

And doubly lucky, a script event listener will work when dynamically added using innerHTML.

Sadly it seems that nothing like

flashBufferingPlayer.onfscommand = flashBufferingPlayer_DoFSCommand;

is available.

Tuesday, October 11, 2005 4:42:37 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [7]
 Wednesday, September 28, 2005

If you add an onclick listener to an anchor with addEventListener, the return value is ignored and whatever is in the href is activated.

I come across this issue every day and have written about it before, but its only after coming out the other end of writing my addEventListener wrapper/replacement that I really appreciate just how mind bogglingly out of place this behavior is.

If this was a natural phenomena, creationists would simply have to throw their hands in the air and acknowledege that there was obviously nobody at the wheel.

Wednesday, September 28, 2005 10:48:38 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Tuesday, September 27, 2005

I'm experimenting with describing all my CSS and JavaScript behaviors in XML. Currently working on allowing the optional nesting of CSS selectors which results in rules generated with normalised versions.

for example..

<selector css="pre">        
    <style>        
        font-size: 1.1em;
        background: #f0f0f0;
        -moz-border-radius: 10px;
        padding: 1em;
    </style>              
    <selector css="span">        
        <style>       
            font-weight: bold;
        </style>              
    </selector>
</selector>

I'm hoping this will make my life a little easier.

Need a way to specify the kind of selection being made. child, descendant etc. This is very very important for usability and for generating something that create a CSS that will render without boiling the ocean.

Read a post by Simon Willison today about taming the CSS monster, the comments pointed to some interesting resources, I added my 2c. I think what I am building in WireWrap will go part of the way towards solving the problem for me and improve the system that I am building as a whole - but as a general solution what I think we really need is good support in the IDE for CSS introspection and management.

All the rest is self discipline, good planning and knowing how CSS actually works.

 

Tuesday, September 27, 2005 1:21:17 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]

Found an issue with Safari (tested against version 1.3.1)

With the following code....

var l_a5 = document.getElementById("a5");

l_a5.onclick = f1;

l_a5.onclick = null;

l_a5.addEventListener("click",f2,true);

.. when clicking on the element referenced by l_a5 will result in both events triggering in the order f2,f1

Every other browser that supports addEventListener only triggers the single event f2

If you think about f1 should never fire, because the reference to it has been set to null - somehow, Safari remembers.

Here is a testcase  (see the last test) for browsers that support addEventListener which are off the top of my head Netscape,Firefox,Mozilla and Safari.

The testcase is used to show how different browsers handle a mixture of event listeners added by addEventListener  and inline or assigned eg. element.onevent = function.  Here is another testcase for my addEventListener replacement where you can see that I have made an attempt to normalise all the different quirks and emulate the way that the latest Mozilla engine handles some of these situations for all other browsers.

I've made a note in more detail on this problem here.

Tuesday, September 27, 2005 12:02:49 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Monday, September 26, 2005

Just added a feature to my JavaScript libraries so that they can work out what other JavaScript libraries need to be included and then includes them in the correct order. Most of the work is done by the foloowing three functions: MwUse , MwRequire and MwInclude .

Not working under all browsers yet - but shows lots of promise!

For example, in one of my test cases I specify the following script includes

<script language="JavaScript" type="text/javascript" src="mw_lib.js" ></script>
<script language="JavaScript" type="text/javascript" src="mw_lib_page.js" ></script>

mw_lib.js is the core library and depends on no external libraries so it does not trigger the load of any dependencies.

mw_lib_page.js however has the following two dependencies decared with the following statements.

// Ensure we have the namespace we need before we load this page
MwUse("MetaWrap","mw_lib.js");

// Ensure we have the namespaces/objects we need before we start executing
MwRequire("MetaWrap.Page.Element.addEventListener","mw_lib_page_element_addhandler.js");

MwUse checks to see if the specified object exist, if not it loads the corresponding JavaScript file (in a future feature it will work out the file name from the object name if the filename is not provided, hence my strict naming standard).

So mw_lib_page.js is declaring that it needs the namespace MetaWrap which can be found in mw_lib.js and that if you want to even load and parse this library, you better have it. But we already have that namespace loaded so nothing happens. if this was another namespace and file pair, such as

MwUse("MetaWrap.Test","mw_lib_test.js");

Then mw_lib_test.js would be downloaded and included by MwInclude before mw_lib_page.js loaded any further.

MwRequire checks to see if the object exists and loads the corresponding javascript file only at the point of initialising the library, so its a kind of defered MwUse. Any files that calls, MwRequire is declaring that the file can continue to parse but before you execute any of the methods in the file, you need to include the specified library or it Would Be Bad.

To initialise the library we call MwInit() (looking into automating this - stay posted)

At this point all the namespaces/objects that have been specified by MwRequire are loaded and in this case its mw_lib_page_element_addhandler.js, which contains the following lines of code in its header.

// Ensure we have the namespaces we need

MwUse("MetaWrap","mw_lib.js");

MwUse("MetaWrap.Page","mw_lib_page.js");

MwUse("MetaWrap.Page.Element","mw_lib_page_element.js");

So it checks for MetaWrap, which it has, and then MetaWrap.Page, that it already has, but it does not have MetaWrap.Page.Element so it loads mw_lib_page_element.js, which contains the following

// Ensure we have the namespaces we need

MwUse("MetaWrap","mw_lib.js");

MwUse("MetaWrap.Page","mw_lib_page.js");

And all of these namespaces are loaded - so no more loads are triggered.

It solves some nagging problems for me and counters human error so I'm really liking this new feature.

 

Monday, September 26, 2005 12:19:43 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Thursday, September 22, 2005

Cool Application, sure its a clone of Google Homepage, but I'm looking forward to the day when all websites are this malleable. Can't justify why, hell I like the idea.. maybe I'm just a control freak.....

Netvibes.com is a customizable web 2.0 homepage solution

This service is free and gives you the user the ability:

  • to create a personalized page with the content you like.
  • to put together data feeds and services from web 2.0 applications with a very simple interface
  • to access your page anytime and from any computer .

Key features of Netvibes:

  • Browse, modify, and import your RSS feeds with our integrated RSS/ATOM feedreader. You can easily import an OPML file as well.
  • Import, download and listen to podcasts without any additional software
  • Check your e-mail on one or many Gmail accounts; stick web notes and weather updates; and many more features to come!

http://www.netvibes.com/

Thursday, September 22, 2005 11:31:08 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]

Here is my entry for the QuirksMode addEvent() recoding contest.

Its not the smallest or simplest, but this was a project that I started before the competition was announced and its main purpose is to solve a much larger problem.

My solution provides an implementation of addEventListener and removeEventListener that is consistent across today's most popular browsers, supporting event bubbling and event capture (both the strict and non strict variants).

It..

  • Implements full W3C emulation layer for browsers that don't have a native addEventListener.
  • Emulates both event capture and event bubbling and provides a way to emulate the strict W3C and 'consensual' modes by dealing with some quirks in current browsers.
  • Plays well with other code and the mixing of pre-existing inline and assigned event listeners.
  • Allows event cancelling.
  • Does not leak in itself but is aware of the IE leak patterns and implements a focused scrubbing garbage collector to deal with the common and not so common leakage issues. The GC can be set to to agressive or lazy.

Read the full blog entry if you want to get the whole story.

I have tested this under IE5 (thanks Emanuele Aina) , IE5.5, IE6, Safari1.3.1, Firefox1.0.5, Firefox1.5beta, Opera8.5, Netscape 6.2.3, Netscape 7.2, Netscape 8, Mozilla 1.7.12.

I have not tested it under v4 browsers, but I see no reason why it would not work in emulation mode with some minor tweaks.

It won't work under IE5.0 unless I can somehow implement call or apply and splice in JavaScript for IE5 :)

You can view the actual implementation in mw_lib_page_element_addhandler.js and there is some supporting code in mw_lib_page_element.js 

And if you just want the js files, here they are.

mw_lib_page_element_addhandler.js
mw_lib_page_element.js
mw_lib_page.js
mw_lib.js

How To Use

Download the JavaScript library files

Then include them using the following script includes

<script language="JavaScript" src="mw_lib.js"></script>
<script language="JavaScript" src="mw_lib_page.js"></script>
<script language="JavaScript" src="mw_lib_page_element.js"></script>
<script language="JavaScript" src="mw_lib_page_element_addhandler.js"></script>

Four functions are provided

addEventListener

MetaWrap.Page.Element.addEventListener(p_element,p_event_type,p_function,p_capture);

This is a complete replacement for W3C element.addEventListener. The parameters are the same as the W3C version of the function with the same name

removeEventListener

MetaWrap.Page.Element.removeEventListener(p_element,p_event_type,p_function,p_capture);

This is a complete replacement for W3C element.removeEventListener.The parameters are the same as the W3C version of the function with the same name

Here is a testcase that tests both addEventListener and removeEventListener.

deleteListeners

MetaWrap.Page.deleteListeners();

This function implements the classic IE memory leak fix and should only be executed at window.onunload

garbageCollectListeners

MetaWrap.Page.garbageCollectListeners();

This function will garbage collect any dangling element references. There is a global variable MetaWrap.Page.m_listeners_auto_garbage that if set to true will force a garbage collect after every event. Its default value is false.

Here is a testcase for garbageCollectListeners and here is another.

If requested by enough people, I will release a 'compact' stand alone version of the code. I have an explanation for why my code is so flowery at the end of this post with the heading "My Strange Coding Style". :)

How It Works And Why

Hot on the heels of my last JavaScript project, I decided to get back into my JavaScript behavior library and found myself needing an implementation of addEventListener and removeEventListener that was consistent across all browsers. I researched the current state of the art and found an article on how you should not do it.

Taking this on board I decided to write own implementation, my aim being to fully support in IE everything that the W3C specification defines, so I ended up developing a solution that supports event bubbling and both the strict and non strict variants of event capture.

Now its debatable whether or not event capture is of any use, but in the past I have found it very useful in writing clean minimal code and I personally have a requirement for it.

The rules for how addEventListener (and the listeners themselves) should behave are very clearly defined, but perhaps not perfectly clear as it seems that only one of the major browsers (Opera) has followed the spec to the letter, and the rest seem to have either emulated each other, forming a de facto standard (Mozilla / Firefox / Netscape and Safari) and last but not least the browser with the most market share simply does not implement it at all (IE). Here is previous post about this issue that also points to a testcase.

The 6 Golden Rules Of W3C Events

I distilled the essential requirements from the W3C spec into the following 6 rules.

Rule 1

After initiating capture, all events of the specified type will be dispatched to the registered EventListener before being dispatched to any EventTargets beneath them in the tree. Events which are  bubbling upward through the tree will not trigger an EventListener designated to use capture.

Rule 2

If an EventListener is added to an EventTarget  while it is processing an event, it will *not* be triggered by the current actions but may be triggered during a later stage  of event flow, such as the bubbling phase.

Rule 3

If multiple identical EventListeners are registered on the same EventTarget with the same parameters the duplicate  instances are discarded. They do not cause the EventListener  to be called twice and since they are discarded they do not  need to be removed with the removeEventListener method.

Rule 4

If a listener was registered twice, one with capture and one without,  each must be removed separately. Removal of a capturing listener does not affect a non-capturing version of the same listener, and vice versa.

Rule 5

Even if an event is captured or bubbles up, the target/srcElement  always remains the element the event took place on.

Rule 6

A capturing EventListener will not be triggered by events dispatched directly to the EventTarget upon which it is registered.

 

Capture vs Bubble

Rule 1 describes the order in which the listeners are triggered and Rule 5 describes what should be passed to the listener. I try to think of the top level of a document, the <HTML> element for example, as the surface of a pond with all the other elements being below the surface at depths determined by parent/child relationships. Imagine you throw a rock into the pool at a particular element, the water captures the rock and down it falls till it hits that element. The element then bubbles and the bubbles rise to the surface. 

That is essentially what is happening during the capture and bubbling phases.

The added step is that as the rock passes each element, in the capture phase, if the element has events listening on capture, those events are triggered, and in the bubbling phase, only those listeners not registered to capture are triggered. The most shallow capture event fires first, and the most shallow bubbling event fires last.

JavaScript_Event_Bubbling.png

Down And Up

I wrote a series of test cases and then I implemented MetaWrap.Page.Element.addEventListenerWhen I completed the first version, I went looking for some critical test cases, I came across this competition.

"Hence I'd like to take the opportunity to launch an addEvent() recoding contest. Write your own version of addEvent() and removeEvent(), submit it by adding a comment to this page, and win JavaScript fame."

When I first saw it, there were no comments and thus no entries submitted, so I thought to myself.. hmmm.. "First Post?" :) It was 11pm, and approaching the dark side of breakfast, but I decided to go for it.

I downloaded the test page and substituted my code. I was disappointed, It kind of worked in IE, but didn't have the same behavior in the sub menu elements as it did under W3C browsers, do I decided that there must be something wrong with my implementation, which was odd given the number of test-cases that I threw at it.

I decided to give first post a miss because I had to get some sleep and another project deadline was looming and I needed my wits about me.

A week later I audited my code and found something that was in theory, an issue, but it did not look like it would affect the competition code. The issue was so do with what happened when you registered event listeners during an event (see Rule 2). Eg. on element X, onclick is fired and then then modifies the onclick for element X and Y.

My interpretation of Rule 2 is that, if during an event of a given event type, you modify the listeners for that event type on the current element, you won't see the new listeners executed till the next time that event is triggered. If you modify listeners of that event type on other elements that the event will be visiting as part of the bubbling or capture flow for this event, these listeners will be executed.

My code was violating this, you could in theory add a new handler on the event which would get fired and then add a new but different handler that removed the first and so on, so it was possible to throw the browser into an infinite loop of event handlers that leap-frogged each other into oblivion, which in retrospect makes Rule 2 a Good Thing.

Here is is a set of tests case for Rule 2. one, two, three, four.

Rule 3 describes what should happen when a listener is registered and how to deal with duplicates my implemenation obeys this, so no problem there. 

So that was a dead end. So still no joy. So I decided to see if a solution to the competition actually existed, maybe I was missing something fundamental. I recoded the competition page with the added events in-lined in the correct order and it behaved exactly the same as my code.

So something else was obviously up.

I wrote a test case so that I could log exactly which event was being fired and in what order and compared results for IE6 and Firefox when from above the elements dragging the mouse down over "Item 1" then up off it again.

node event type target this/currentTarget
LI showSubNav mouseover A1 li1
LI showBorder mouseover A1 li1
LI hideSubNav mouseout A1 li1
LI hideBorder mouseout A1 li1

IE6

 

node event type target this/currentTarget
LI showSubNav mouseover li1 li1
LI showBorder mouseover li1 li1
LI hideSubNav mouseout li1 li1
LI hideBorder mouseout li1 li1

Firefox

Looks like the issue was the mouseover/mouseout was targeted on the UL in Firefox, but on the A element in IE6.

Now the events are only listening on the LI elements but in IE the bubbled event is targeted by the A. So the mouseover/mouseouts are bubbling down to the parent LI and are being executed, but they are only reacting to movement on the A element. The trick was to make the LI wider.

To clarify this, from the point of view of the events, in IE, you are rolling the mouse over the A, but in Firefox, you are rolling the mouse over the LI which has plenty of area to roll around and activate the sub menu items.

So the competition has a sting, its not a simple case of sorting out addEvent, the competition example itself suffers from a CSS compatibility error which is going to mean its always a little flaky under IE even if you restyle the LI to be wider.

After making this width adjustment, my solution worked perfectly!

Later on after re-reading the competition page It dawned on me that I had been warned about this but had mis-interpreted the warning.

  1. Your entry should exhibit the same behaviour as this example page, which uses Scott Andrew's old functions. The example page doesn't work in Explorer, but your entry should. The mouseout functions on the example page don't work perfectly, but for the contest that doesn't matter.
  2.  

Browser Quirks

Mixed Mode Events

The following code results in different behavior in IE6 and Firefox 1.5

MetaWrap.Page.Element.addEventListener(l_a1,"click",f1,true);
MetaWrap.Page.Element.addEventListener(l_a1,"click",f2,true);       
l_a1.onclick = f3;
l_a1.onclick = f4;

In IE or Opera if you click on the element, just the f4 listener is executed.

In Firefox and Safari if you click on the element, just the f1,f2 and f4 listener are executed, in that order.

I have created a test case that tests mixed mode event listener assignment in various orders.

It looks like Firefox treats the assignment

element.onevent = listener;

as the following sequence

removeEventListener(element,event,element.onevent,false);

addEventListener(element,event,listener,false); 

It would be 'possible' to emulate this behavior, but it would be computationally expensive, not 100% reliable and probably not very practical. A possible method would be to, on each event, walk the list of all elements event types and check for consistency eg. event with listener stacks with a different master event handler than MetaWrap.Page.Element.listenerShimFunction.

[UPDATE....

With very little change I have emulated two issues which were naging at me.

The first is an issue when listeners were added with the following code.

l_a1.onclick = f1;

MetaWrap.Page.Element.addEventListener(l_a1,"click",f2,true);

Under IE emulation mode and Opera, f1 will never fire because it is overwritten by f2.  In Safari, they fire in the orfer f1,f2. In Mozilla based browsers f1 is preserved so both fire in the order f1,f2. This is because the Mozilla based browsers do something extra in addEventListener, they preserve the existing inline/assigned listeners as a captured event. Here is a testcase that shows the default behavior using the standard addEventListener reacting with different mixed mode events.

In the latest version of my library I emulate the default behavior of modern Mozilla based browsers for all browsers. 

I am only trialing this emulation, but it seems to make a lot of sense. It could however be effort for very little gain - my only justification for this is.

  1. It is low cost and standardises behaviors (and yes I choose Mozilla as the default behavior because of point 2)
  2. Its going to make more robust code. When using the library in existing code I don't want to inadvertently clobber the existing inline listeners so I have decided to (hopefuly) 'do no harm'.

In Safari, they fire in the order f1,f2 - from what I can tell Safari events are rather broken.

The following code in Safari (tested against version 1.3.1)

var l_a5 = document.getElementById("a5");

l_a5.onclick = f1;

l_a5.onclick = null;

l_a5.addEventListener("click",f2,true);

Clicking on the element referenced by l_a5 will result in both events triggering in the order f2,f1

On every other browser that supports element.addEventListener, only f2 triggers.

Here is a testcase - try the last test and you will see what I mean.

The second is for the following sequence

  MetaWrap.Page.Element.addEventListener(l_a3,"click",f1,true);
  l_a3.onclick = f3;
  l_a3.onclick = f4;
  MetaWrap.Page.Element.addEventListener(l_a3,"click",f2,true);

Which now works consistently across all browsers, even in emulation mode.

I'm not sure if I will keep these patches (they are clearly labeled in the source code). They make the code ugly, and they are little more then a token effort to fix a whole family of problems that occur if you start mixing the way you add event listeners. See this testcase.

They do however fix some obvious collisions that occur when adding this library to pre-existing code. The majority of the remaining problems would be an issue in the existing code anyway.

so..

I am of two minds on this one.

...]

Deleted Elements

Rule 4 covers listener removal. When an element is removed, what happens to its registered events? At the moment these are going to stick around in memory. Until the DOM mutation notification event becomes widely available and all other browsers are long dead (5 years?) we can't really deal with this efficiently, so the best we can do is have a simple garbage collect phase. To this effect the following method is made available.

MetaWrap.Page.garbageCollectListeners();

This will perform a garbage collect pass and remove all listeners for elements that are no longer part of the document.

There are two testcases for this method.. one tests elements removed by overwriting using innerHTML and the other tests elements that have been removed surgically with removeNode. The resulting element states are different in each case which garbage collector has to deal with cleanly.

Browser Compliance To W3 Spec

Opera seems to be the only browser that follows Rule 6, which complicates things. I can emulate the right way, or I can emulate the way that everyone else has implemented it. I have decided to do both, to which end the following global variable exists.

MetaWrap.Page.m_listeners_strict_w3c = false;

Its default behavior (false) is to force all browsers to behave like Netscape/Mozilla/Firefox and Safari. If we are running Opera, we execute the same emulation mode that we use for IE.

If you set its value to true however, it will emulate for all other browsers the way that Opera handles its event propagation.

The logic behind this decision is rational yet complicated but it comes down to providing a choice for the developer who can choose performance vs compliance but still maintain consistency across all browsers.

Here is previous post about this issue about the Rest Of The world vs Opera.

Here is a testcase that demonstrates the library with MetaWrap.Page.m_listeners_strict_w3c set to false.

Here is a testcase that demonstrates the library with MetaWrap.Page.m_listeners_strict_w3c set to true.

My Strange Coding Style

I work at a web development company called Massive Interactive in Sydney Australia where part of my role is to be a technology storm-trooper and develop code and libraries that can be passed on to others for use or further development.

I too can code strange JavaScript built with nothing but single character variables, ternary statements, object hash tricks and K&R styling but I choose not to because much of what I develop needs to be maintained by other people. I code to be understandable and maintainable. I am painfully aware of the cost of name spacing, the cost of the size of variable names and even the load time cost of comments , luckily the run time cost for comments and formatting is close to zero. But I choose to code in this way because I would rather have the performance hit than have code that is hard to maintain. 

I'm a firm believer in keeping the primary JavaScript code base neat and tidy, when it comes to rationalising the code for production - that is where the automatic composition and compression utilities come in.

If enough people want a 'compressed' version of the functions, I will happily provide some, but I'm sure there is going to be some bugfixes as soon as people start playing with this.

Thursday, September 22, 2005 12:40:35 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [2]
 Tuesday, September 20, 2005

Just lodged my first bug for Opera, only to figure out 5 mins after I hit submit that its not a bug with Opera, Its a bug with every other browser.

Seems that in Opera 8.5 when you use addEventListener with capture set to true, it behaves differently to the other common browsers that use addEventListener which are Safari and Mozilla.

On further examination (see below) its conceivable that Opera is the only one to follow the spec.

Here is my testcase for it

Try the CAPTURE example (the second test from the top)  First run it in Firefox or Safari, then Opera.

Try any of the 'MIXED' tests that capture on more than one element MIXED4, MIXED5, MIXED6, MIXED7 or MIXED8 and compare behavior with Safari and Firefox which follow the w3 spec.

Now From the spec, note the bit in bold...

Event capture is the process by which an EventListener registered on an ancestor of the event's target can intercept events of a given type before they are received by the event's target. Capture operates from the top of the tree, generally the Document, downward, making it the symmetrical opposite of bubbling which is described below. The chain of EventTargets from the top of the tree to the event's target is determined before the initial dispatch of the event. If modifications occur to the tree during event processing, event flow will proceed based on the initial state of the tree.

An EventListener being registered on an EventTarget may choose to have that EventListener capture events by specifying the useCapture parameter of the addEventListener method to be true. Thereafter, when an event of the given type is dispatched toward a descendant of the capturing object, the event will trigger any capturing event listeners of the appropriate type which exist in the direct line between the top of the document and the event's target. This downward propagation continues until the event's target is reached. A capturing EventListener will not be triggered by events dispatched directly to the EventTarget upon which it is registered.

If the capturing EventListener wishes to prevent further processing of the event from occurring it may call the stopProgagation method of the Event interface. This will prevent further dispatch of the event, although additional EventListeners registered at the same hierarchy level will still receive the event. Once an event's stopPropagation method has been called, further calls to that method have no additional effect. If no additional capturers exist and stopPropagation has not been called, the event triggers the appropriate EventListeners on the target itself.

Although event capture is similar to the delegation based event model in which all interested parties register their listeners directly on the target about which they wish to receive notifications, it is different in two important respects. First, event capture only allows interception of events which are targeted at descendants of the capturing EventTarget. It does not allow interception of events targeted to the capturer's ancestors, its siblings, or its sibling's descendants. Secondly, event capture is not specified for a single EventTarget, it is specified for a specific type of event. Once specified, event capture intercepts all events of the specified type targeted toward any of the capturer's descendants.

The bit in bold disturbs me, because I don't think Safari or Firefox obeys this and if I am right then I suspect that Opera may in fact be the only one to obey the spec properly.

Going back and looking at the test case, if you click on an element that has a listener added with capture, it is not triggered- as per the spec.

Compare MIXED2 and MIXED3. Its spot on as the spec describes

Tuesday, September 20, 2005 11:03:27 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Monday, September 19, 2005

// Declare Error Handler
function oops()
{
  alert ('Error!');
  return true;
}

// Assign to global error handler
window.onerror = oops;

// Trigger an error
x.y.z();

This does not work, and it makes me sad.

Updated - removed syntax error from example

Monday, September 19, 2005 6:16:30 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [3]
 Wednesday, September 14, 2005

Adds cool logging widget to your pages. Something else I was thinking about building, but now someone has done it for me.. w00t - Looks great!

jslogger.png

http://alistapart.textdrive.com/articles/jslogging#fvlogger

[Update]

Decided to write my own after all. Needed some good logging for my event handler code, so I started integrating fvlogger, but by the time I was finished I had a completely different creature that was well integrated with the MetaWrap JavaScript library.

The style is inspired by the old Amiga error popup.

Used to really get my attention.

Once you had added some errors, try clicking on the messages (more then once). Everything has a use. Its a subtle interface - but very usable.

Wednesday, September 14, 2005 1:07:00 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Saturday, September 10, 2005

If you are wondering why I have been not posting much to the blog recently, or if you met me in person lately, why I have been so tired and not really in the mood to talk, its because I have been busily working on this fantastic new creation which launched this weekend! w00t!

Click on the images for more detail..

 

spotlight.png

Its icon in "Online Spotlight"..

more_programs.png

Which adds it to "More Programs"

home_screen.png

"Home"

schedule.png

"Schedule"

setup.bmp

"Setup"

hotlap.png

Hotlap Broadcast

interview.png

Interviews

race_mode.png

The Race!

 

And here is a video of it in action

 

 

Saturday, September 10, 2005 3:46:20 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [2]
 Monday, September 05, 2005

Ruby's ActiveRecord Implementation is a very cool part of the very cool Ruby on Rails (RoR) project. RoR is a great way to build a database driven web page. It has weaknesses if you're trying to build something that's truly Javascript heavy though, because it offers no easy way for the Javascript in the page to get ahold of the database directly.

http://www.kiko.com/jsactiverecord/

Monday, September 05, 2005 4:14:01 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Friday, September 02, 2005

You learn something new every day, which is why I love being alive.

Its an astounding coincidence that just when I needed to implement a cross browser method of stacking event handlers (for MetaWrap WireWrap), this blog post came out describing exactly how you should not do it.

The issue seemed to be the difference between browsers that implement the W3C spec vs Microsoft's spec for dynamically adding an event handler.

The key difference is that the this keyword does not work properly in Microsoft's attachEvent. Instead of referring to the element the event handler is defined on, as it does in the W3C model, it refers to the window object.

There is also a memory leak in IE which for which the only solution is to garbage collect ever event handler you ever created, for example - on body.onunload() killing all references to event handlers. This leak is probably based on circular references.

So I'm going to write an event registration class in JavaScript that deals with both of these problems.


Related to WireWrap, it was pointed out to me that yet another CSS query/select JavaScript class has been released in this blog post which seems to implement the full set of CSS selectors.

Damned if I'm going to write my own now.

cssQuery() is a powerful cross-browser JavaScript function that enables querying of a DOM document using CSS selectors. All CSS1 and CSS2 selectors are allowed plus quite a few CSS3 selectors.

Friday, September 02, 2005 1:21:51 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Friday, August 26, 2005

This Is Not The JavaScript Our Parents Would Know

In the bad old days JavaScript was not compatible across browsers. JavaScript development was painful, frustrating and costly. More recently JavaScript has become the poster-child for effective web programing and the next wave of Web 2.0 applications. Why is this so? I investigate this quandary in the following essay.

Lets start by looking at the brief history of JavaScript which turned 10 years old last month.

History

1995 - JavaScript 1.0 / aka "LiveScript" Early ECMAscript + DOM level 0 without images  / Netscape2,IE2

1996 - JavaScript 1.1 / (JScript1.0) Early ECMAscript + DOM level 0 / Netscape 3, IE3

1997 - JavaScript 1.2 / (JScript2.0) ECMAscript + DOM level 0 + layers or proprietary DOM   /  Netscape 4, IE4

1998 - JavaScript 1.3 / (JScript3.0) ECMA-262  DOM level 0 + layers or proprietary DOM / Netscape 4.05-4.76*, IE4

1998 - JavaScript 1.4 / (only by Netscape's server side JavaScript)

1999 - JavaScript 1.5 / (JScript5.6) ECMA-262 Edition 3 + DOM level 0 + W3C DOM / Netscape 6, IE5,IE6

200? - JavaScript 2.0 / ECMA-262 Edition 4 /

Compatibility

Different versions and indicates where IE and Navigator versions of JavaScript are roughly compatible:

Browser

NN3.0

NN4.0 - 4.05

NN4.06 - 4.76

NN6.0+

IE3.0

JavaScript 1.1

JScript 1.0

     

IE4.0

 

JavaScript 1.2

JScript 3.0

JavaScript 1.3

JScript 3.0

 

IE 5.0

     

JavaScript 1.5

JScript 5.0

IE 5.5

     

JavaScript 1.5

JScript 5.5

IE6.0

     

JavaScript 1.5

JScript 5.6

The table only gives a very rough approximation, and in those terms JavaScript IE3 = NN3, IE4 = NN4 and IE5+ = NN6. An example of the small differences is the try..catch clause, which is supported in JavaScript by IE5+ and NN6+, but not in IE4 or NN4. Source

What Happened To Netscape 5?

Netscape 5.0 was based on the 4.x code base that Netscape released in 1998. Netscape also released the beginnings of Netscape Gecko -- a new code base -- at about the same time. Soon the Web was clamoring for Gecko's superior performance and standards support. So, [in 1999], Netscape switched code bases and rewrote the new software based on Gecko, canceling 5.0 (Mozilla classic) in favour of Netscape 6.


Why Is JavaScript So Damn Usable Now?

The answer is features, persistence and hype.

People have been working hard to make JavaScript work. JavaScript is the one true common platform. It is in every modern browser. With the correct arrangement of certain features, the kinds of problems that used to make people want to take a stiff drink at the mention of JavaScript of Dynamic HTML have gone away. Because of the hype of Web 2.0, mostly driven by the success of Google, blogger and flickr - JavaScript is very very hot at the moment.

Freeze The Clock at 1998

The developer community has essentially drawn a line under JavaScript1.3 and is using the JavaScript syntax and features of 1.3 and scaling up to the DOM/CSS and library support given the executing browser. (But that is a topic unto its own)

With the currently available libraries, It is possible with reasonable effort to create JavaScript that will run predictably on the following browsers.

Opera 7+ , Safari 1.3Mozilla/Firefox 1.0.X , Explorer 5.2 on Mac OS X , Explorer 5+ on Windows

Classes

To help in code re-use and to create code with a better structure, a heavy use of Object Orientated JavaScript has been under way for the last 4 years. Constructors, Typing, Namespaces Inheritance and Polymorphism. This has promoted code re-usability, to the point that the JSAN project has been able to take off and provide a library of JavaScript classes and a standard by which libraries can be easily installed and at run-time dynamical loaded and imported. See line 00118 of this file.

 

function Cat(p_name)
{
    this.m_name = p_name;
    this.talk = function()
    {
        alert( this.m_name + " say meeow!" )
    }
}

l_cat1 = new Cat("Felix");
l_cat1.talk();
 //alerts "Felix says meeow!"

l_cat2 = new Cat("Ginger")
l_cat2.talk();  
//alerts "Ginger says meeow!"

 
.Prototype Object Member

Introduced with JavaScript 1.1 and is not to be confused with, but is the reason that the excellent prototype JavaScript library has that name.

In JavaScript, you're allowed to add custom properties to both prebuilt and custom objects. Here's an example of each:



//Adding a custom property to a prebuilt object - can't do this to all prebuilt objects!

var l_image=new Image();
l_image.size="26k;



//Adding a custom property to a custom object

function Circle(p_radius)
{
    this.m_radius = p_radius;
}

function Area()
{
    return this.m_pi*this.m_radius*this.m_radius
}

var l_smallcircle = new Circle(2.0

l_smallcircle.m_pi = 3.14159;
l_smallcircle.area = Area;

var l_bigcircle = new Circle(20.0);

A custom property added this way only exists for that instance of the object. If I were to instantiate another instance of Circle(), called "l_bigcircle", for example, l_bigcircle.m_pi would by default return "undefined" and the area function would not be one one its members until I go over the process again of first defining m_pi and area, as with l_smallcircle.

JavaScript_Class_Diagrams.png

There are times when you'll want to add a custom property that's only reflected on a particular instance of an object, and other times, when you require all instances of the object to have the custom property.

The prototype object is here to help when you wish to quickly add a custom property to an object that is reflected on all instances of it.

Circle.prototype.m_pi = 3.14159;

All instances of Circle() now has the m_pi property prebuilt into them.

Circle.prototype.area = Area;

var l_smallcircle = new Circle(2.0);

var l_bigcircle = new Circle(20.0);

Now, all instances of the circle object contain an area() method!

JavaScript_Class_Diagrams_prototype.png

Tests To Prove It

 
Apply/Call

JavaScript1.3 defines two new methods. apply() and call(). These can be used to manipulate the 'this' reference in JavaScript which means that you can in effect emulate object method composition.

You can project any given object and make it 'this' within a function call.

These features make it easy to re-use code and stitch functions and objects together into a classical Object Orientated structure.

 
Arguments

You can refer to a function's arguments within the function by using the arguments array. This array contains an entry for each argument passed to the function.

The arguments array is available only within a function body. Attempting to access the arguments array outside a function declaration results in an error.

You can use the arguments array if you call a function with more arguments than it is formally declared to accept. This technique is useful for functions that can be passed a variable number of arguments. You can use arguments.length to determine the number of arguments passed to the function, and then process each argument by using the arguments array. (To determine the number of arguments declared when a function was defined, use the Function.length property.)

Example.

function listItems() 
{
   var items = listItems.arguments.length
   document.write("<UL>\n")
   for (i = 0;i < items;i++)
   {
      document.write("<LI>" + listItems.arguments[i] + "\n")
   }
   document.write("</UL>\n")
}

The function may be called as follows:

listItems("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Happyday");

Try/Catch/Finally

Added as part of JavaScript 1.4 (So Beware) - Server Side JavaScript

Used to catch any errors, as soon as the error event occurs, the program switched flow to the catch statement with an exception object that describes the error.

No more JavaScript Error Alerts.

With try/catch you can aggressively test for browser features that may cause an error, but you can test for try and catch. :)

try
{
  var i = 0
  if(i != 1)
  {
    throw "ThrowError"
  }
}
catch(e)
{
  if(e == "ThrowError")
  {
    document.write("This is a thrown error message: i is not one.<br/>")
  }
}
finally
{
  document.write("This is the finally message.")
}

One of my future tests will work out the cost of try/catch

 

Namespacing

Taking two or more random scripts and putting them on one page can often result in clashes and confusing behaviour as each script interferes with the other variables and functions simply because one scripts variable names and/or function names happen to be the same as another script.

To solve this the current trend is for every script developer to create a namespace.

In JavaScript a namespace is a normal JavaScript with a name that contains all the methods and variables for a given related set of code.

Object Literals are neater then the original old school, method of declaring the object to be used as a namespace.

var MyNamespace =
{
check_my_box :
   function(element_name)
   {
     var my_element = document.getElementById(element_name);
     my_element.checked = true;
    }
  ,
  uncheck_my_box :
   function(element_name)
   {
     var my_element = document.getElementById(element_name);
     my_element.checked = false;
    }

};

MyNamespace.check_my_box("mycheckbox");

Because a namespace is simply an named object, its existence can be tested for. This allows all sorts of wonderful probing for required namespaces and makes it possible to guard against multiply including the same namespace multiple times.

Tests To Prove It

There is a 3% performance hit on function calls for each level of the namespace.

 

Web 2.0 Hype

Web 2.0 is a term often applied to a perceived ongoing transition of the World Wide Web from a collection of websites to a full-fledged computing platform serving web applications to end users. The proponents of this thinking expect that ultimately Web 2.0 services will replace desktop computing applications for many purposes.

DoubleClick was Web 1.0; Google AdSense is Web 2.0.

Ofoto is Web 1.0; Flickr is Web 2.0.

O'Reilly Media, Battelle, and MediaLive launched the first Web 2.0 Conference in October 2004. The second annual conference will be held in October 2005.

Web 2.0 is intimately linked to the new buzzword SOA, Services Oriented Architectures, the poster-child for this is the Salesforce product. http://www.salesforce.com

At a deeper psychological level, the term "Web 2.0" has attracted much wishful positive thinking, possibly because the term infers that the great gravy-train of Web 1.0 could return. Calmer minds who remember the train-wreck are concentrating on the meat of the movement, which is is the emergence of JavaScript as the long promised "write once deploy anywhere" platform, AJAX and the emergence of SOA (Services Oriented Architectures).

   

AJAX

First described in this blog post and most recently in this post.

WTF? We have been doing this with flash for years? Hell we have been doing this in our own applications for years as well (See Demonstrations Below), what gives?.

Lots of AJAX is hype. Buts a good Meme and it serves as a rallying point for a the HTML developer community to catch up and start doing applications properly.

Ajax or Asynchronous JavaScript and XML is a term describing a web development technique for creating interactive web applications using a combination of:

  • HTML (or XHTML) and CSS for presenting information
  • The Document Object Model manipulated through JavaScript to dynamically display and interact with the information presented
  • The XMLHttpRequest object to exchange data asynchronously with the web server. (XML is commonly used, although any text format will work, including preformatted HTML, plain text, and JSON)

AJAX suffers from the same problems as Macromedia Flash - bookmarking and tracking. http://alexbosworth.backpackit.com/pub/67688


And With These Features You Can?

Develop!

  • ..readable and maintainable code.
  • ..testable code. With a class structure unit tests can be easily built into the libraries.
  • ..applications that make less round trips to the server.
  • ..applications in which the behavior, style and content are cleanly separated. (See The MetaWrap WireWrap library)


The Need For Speed

JavaScript engines are highly optimised and very efficient, but still very slow compared to C or Java. "JavaScript is about 5,000 times slower than C, 100 times slower than interpreted Java, and 10 times slower than Perl" 

Given Moore's law - "Computing power doubles every 18 to 24 months", JavaScript is now as fast as interpreted Java was in 1998 and as fast as C was in 1993. And there were some decent Java applications in 1998.

JavaScript is actually faster, because it is highly granular.

Many modern JavaScript interpreters feature just-in-time compilers that can run code very efficiently.

Google got Google Maps working on Safari, by creating an entire Xpath, XSLT and DOM library in JavaScript which runs well because of a good algorithm and effective use of regular expresions.

 


The Future - JavaScript 2.0

http://www.mozilla.org/js/language/js20/

 http://www.mozilla.org/js/language/es4/index.html


Best Practice For Cross Browser Development

Read this site. All of it.

Never Use Browser Detection - use Feature detection.


Demonstrations

   2001 - MetaWrap JavaScript Library

   2002 - Liberate VOD

   2003 - V8 Media Center Edition

   2004 - V8 Broadband Schema Editor

   2005 -  

JsUnit - Simple JavaScript Unit Testing System

Macro - Simple Macro Recorder and Playback

Page - Example Event Manipulation

Wirewrap - How to cleanly separate Behavior Style and Content using.

XSLT -  Driven Page rendering


Testing

http://www.edwardh.com/jsunit/

http://mir.aculo.us/articles/2005/08/03/more-automatic-testing-with-javascript

http://www.hanselman.com/blog/IntroducingWatirMakerRecordingForRubybasedWatir.aspx


Libraries Worth Looking At

There are so many, but here is an interesting example of a series of libraries, each relying on the previous.

http://www.openjsan.org/doc/c/cw/cwest/JSAN/0.10/lib/JSAN.html

http://prototype.conio.net/

http://openrico.org/rico/demos.page


 
Friday, August 26, 2005 12:09:34 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, August 24, 2005

Continuing my analysis of JavaScript performance. For this test I'm testing the impact of the current trend of JavaScript namespaces.

Namespaces

In this test 500000 iterations of the main function are performed.

The depth of the namespace varies from 1 to 15 in increments of 1. Each namespace is 5 characters long

 

namespaces_5_ie.png

 

In this test 500000 iterations of the main function are performed.

The depth of the namespace varies from 1 to 15 in increments of 1. Each namespace is 10 characters long

 

namespaves_10_ie.png

 

In this test 500000 iterations of the main function are performed.

The depth of the namespace varies from 1 to 150 in increments of 10. Each namespace is 10 characters long

namespaces_10_extreme_ie.png

 

The scaling curve is not that good for stupidly high depth of namespaces, this performance curve is reflected in normal usage as you lose approximately 3% of your performance with each namespace level.

Wednesday, August 24, 2005 11:00:52 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Monday, August 22, 2005

"Dare Obesanjo recently enumerated some key points that Ajax application architects have to contend with and a few of them are particularly worthy of note including how to deal with the need for permalinks, the Back button, and others. Please check it out. He also notes that MSN will be talking about their best practice Ajax techniques at Microsoft's PDC developer's conference next month, which it looks like I will attend. Since a prerelease version of Atlas will be available there as well, expect some updates here on this blog on the latest."

http://hinchcliffe.org/archive/2005/08/18/1675.aspx

Monday, August 22, 2005 12:41:23 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Thursday, August 18, 2005

Comment Tests - Parsing

In this test the test code is parsed 100 times for each measurement.

The number of comments varies from 1 to 10000 in increments of 666. Each of the comments is 64 characters long

 

comments_ie_parsetime.png

 

Looks fairly linear - even for a large number of individual comments. Pretty much as expected. No severe penalty for making lots of comments other than the cost of loading and parsing.
Thursday, August 18, 2005 12:28:22 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Wednesday, August 10, 2005

Jasm - perl script

http://www.anvilon.com/software/jsjam/

The Crunchinator  - web form

http://www.brainjar.com/js/crunch/

Code Trim

http://www.twinhelix.com/javascript/codetrim/demo/

Packer - WebForm and .NET Application

http://dean.edwards.name/packer/

Customised Rhino - Java application

java -jar js_with_compress.jar -c in.js > out.js 2>&1

Source for the tool is available in the same directory as the Jar file.

http://dojotoolkit.org/~alex/js_with_compress.jar

Creativyst® JavaScript Compressor Compress CSS Too! (Commercial)

http://www.creativyst.com/Prod/3/

Sample .NET Tool With Source  Code

http://www.codeproject.com/csharp/JSCodeCompressor.asp

Safe Compress - Commercial Product

http://www.codehouse.com/products/safe_compress/

JSCompactor

http://www.milonic.com/jscompactor.php

Wednesday, August 10, 2005 10:58:41 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [2]

This is a continuation from yesterdays post.

Now what is the impact of comments on the speed of JavaScript execution, beyond the obvious overhead at download and parse time?

Comment Tests

In this test 500000 iterations of the main function are performed. The number of comments varies from 1 to 200 in increments of 13. Each of the comments is 64 characters long

comments_ie.png

 

In this test 500000 iterations of the main function are performed. The number of comments varies from 1 to 3000 in increments of 200. Each of the comments is 64 characters long

comments_ie_extreme.png

 

Looks like comments have absolutely no effects at run-time. Looks like they must be removed at parse time.

Whitespace Tests

In this test 500000 iterations of the main function are performed. The number of whitespace characters varies from 1 to 15000 in increments of 1000.

whitespace_ie.png

Looks like whitespace is irrelevant as well.

Conclusions

You can comment and pad your code with whitespace as much as you like, all you are going to affect is the load and parse time. Execution time will not be effected. When it comes down to it, there are lots of tools that will 'compress' your JavaScript and remove comments and excess whitespace.

 

Wednesday, August 10, 2005 10:40:14 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]

My programming style always errs on the side of readability. A good algorithm and optimiser goes a long way to making pretty code run like tightly optimised assembler.

But does that apply to JavaScript?

This may sound like silly question. JavaScript is interpreted, not compiled, but the question is begged - what is the performance hit of all the nifty little JavaScript tricks we have developed over the years?

Does it matter if you go

if(condition)x++;

vs

if (condition)
{
  x++;
}

Do comments slow down the code?

Is the length of function names a consideration?

What is the overhead of X.Y.Z style namespacing?

How about the "prototype" object and the call and apply functions?

Over the next week I'm going to be building some tests and publishing some results. I'm in the middle of a large JavaScript project and I've decided to work out if I'm committing any cardinal sins before I reach the point of no return.

The tests below were run under IE6 on an AMD1.4GHz with 1G RAM, Windows XP

BaseLine Test

In this test 200000 iterations of the main function are performed.

From the results below we seem to have a good baseline of ~ 250.

baseline_largescale.png

 

Varying Length Of Function Name

This tests a simple root level non anonymous function call.

eg.

function FFFFFF()
{
   x = 1;
   y = 2;
}

The function name is increased in length for each test (listed on X axis)

In this test 200000 iterations of the main function are performed

The length of the function name varies from 1 to 150 in increments of 10 characters.

From the results below you can see that there is some degradation, but its not a harsh curve. ~ 1% performance hit per 8 characters in the function name.

 

functionlength_ie.png

This second graph shows a more normal range of use for function names.

In this test 500000 itterations of the main function are performed. The length of the function name varies from 1 to 32 in increments of 2 characters.

The 1% performance drop per 8 characters is still observed.

functionlength_normal_ie.png

This third graph in the series tests the function length to an extreme where you can see the scaling curve clearly.  In this test 200000 itterations of the main function are performed. The length of the function name varies from 1 to 15000 in increments of 1000 characters.


functionlength_extreeme_ie.png

Its pretty clear that in JavaScript the length of the function name matters. In compiled languages, every function call is compiled down to a memory address. In interpreted systems the function name is important. So if you have lots of long and descriptive function names, you are probably taking a performance hit of a few percent, which makes for a hard decision or readability over ultimate performance. For me, 1% is worth it if my function names can be easy to read and bear some resemblance to the actions they perform.

Now this may seem rather obvious, and to me these results are not unexpected, but you never know for sure till you really measure it.

More JavaScript drag racing tomorrow night :)

Wednesday, August 10, 2005 12:15:32 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [1]
 Monday, August 08, 2005
Monday, August 08, 2005 9:41:21 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Tuesday, August 02, 2005

I'm building an event logger for my JavaScript based macro recorder. One of the issues I have is browser differences with the way events are handled.

I would like that a macro recorded in IE can be played back in Mozilla.

Mozilla supports w3 standard events.

IE supports some w3 standard events + extra events.

Of particular bother are the onfocus,onblur events which do not bubble under IE.

I have two methods by which I can capture events. The first is to register a global document.event handler. The second is to register against every single event in the DOM. Without a working 'mutate' event this can only be done by brute force (a fast timer and a registration array). For now the global event handler is enough for a proof of concept. The second method is to use the addEventListener or attachEvent element methods.

The next most bothersome issue is event bubbling vs event capture and the ability of the JavaScript coder to turn off event bubbling.

http://www.quirksmode.org/js/events_order.html

The solution so far is to kill two birds with one stone and to support all the standard messages and simulate the non standard ones. Even onfocus,onblur can be simulated with only access to a global event handler. By logging everything, taking these events as supported and unsupported events, I should be able to build up a good database of what supported events spawn what unsupported events and end up with a nice family tree.

Thus with a minimal amount of event logging, I should be able to get the maximum amount of playback accuracy.

Tuesday, August 02, 2005 11:48:02 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]

Looks like a very nice wrapper of prototype, with great documentation and a really effective website.

http://openrico.org/rico/demos.page

 

Tuesday, August 02, 2005 10:44:19 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Monday, July 25, 2005

apply

Syntax

functionreference.apply(thisArg, argArray)

Parameters

thisArg (parameter for the calling object)

argArray (an optional parameter of an argument array for the object)

Description

apply allows you to apply a method of another object in the context of a different object (the calling object). You can assign a different this object when calling an existing function. this refers to the current object, the calling object. With apply, you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.

 

call

Syntax

functionreference.call(thisArg, arg1, arg2, ...)

Parameters

thisArg (parameter for the calling object)

arg1, arg2, ... (an optional parameters of arguments for the object)

Description

call allows you to call (executes) a method of another object in the context of a different object (the calling object). You can assign a different this object when calling an existing function. this refers to the current object, the calling object. With call, you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.

Monday, July 25, 2005 8:35:05 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Saturday, July 02, 2005

This is by far the most useful site ever. In the last month I have visited it every day. Its a pleasure to read, is full of accurate information for JavaScript programmers. When I say "most useful site ever" I really really mean it. If you are writing cross browser JavaScript, this site has all the differences laid out in easy to read tables, code examples and workarounds.

"QuirksMode.org is the personal and professional site of Peter-Paul Koch, freelance web developer in Amsterdam, the Netherlands. It contains more than 150 pages with CSS and JavaScript tips and tricks, and is one of the best sources on the WWW for studying and defeating browser incompatibilities.
It is free of charge and ads, and
largely free of copyrights."

http://www.quirksmode.org/

Saturday, July 02, 2005 4:10:45 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]
 Wednesday, June 29, 2005

http://www.ripcord.co.nz/behaviour/

I really really like this. It uses the CSS selector syntax to style elements with javascript code. You only need to keep one mapping paradigm in your head and its consistent for appearance and behavior.

I was considering using XPath for the same task by applying css classes and code to HTML and XHTML based on XPath - may still take this route, but I think this approach warrants some examination because more web developers understand CSS selectors than Xpath - but it may be slower and less efficent than my approach.

I'm going to play with this - if it does the job I willl integrate this into the MetaWrap JavaScript library, otherwise I'll have to write my own from scratch. The hardest part is the interpretaion of the selector to map into a set of elements. Not sure if I like thepackaging they use. Will look into it.

If you need s refresher in how CSS Selectors work.

http://css.maxdesign.com.au/selectutorial/

In particular

http://css.maxdesign.com.au/selectutorial/selectors_type.htm

CSS Javascript!

http://www.unix.org.ua/orelly/web/html/ch13_04.html

http://www.quirksmode.org/css/javascript.html

Edit In Place

http://tool-man.org/examples/edit-in-place.html

[Update]

An Even Better Edit In Place (Thanks to Damian for poining this out)

http://demo.wikiwyg.net/wikiwyg/demo/standalone/

 

Wednesday, June 29, 2005 11:40:11 AM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [3]
 Friday, June 24, 2005

You see both of these methods being used so often that you have to wonder - which is correct?

href="javascript:f()"

vs

href="#" onclick="javascript:f()"

The classic ill side-effect that can occur when using the javascript: within a href attribute is when the function returns a value. Eg when opening a new window using window.open() - it returns an object reference to the new windows. In some browsers this will redirect to an otherwise blank page except for the word "[object]" (IE) or "[object Window]" (Netscape 4.x). However, assigning the window.open method to a variable avoids this. So:

href="javascript:window.open();" will redirect the opener to [object] or [object Window]

href="javascript:var newWin = window.open();"  will pop the window without an opener redirect

Another trick is to wrap the function call in void as follows. href="javascript:void(window.open());"

However, I believe that best practice is placing the target URI in the href attribute (like a normal link) or some descriptive text and placing the javascript in an onclick event handler (with the addition of "return false" at the end to cancel the link's default behavior).

When you use "return false" on onclick eg. onclick="functionName();return false" the browser doesn't try to go to whatever is specified in the href when the link is clicked. If the onclick calls a submit function then you have effectively asked the browser to go to the href and the action of whatever form you are submitting.

So this is probably the best of both worlds.

href="javascript://Open A New Window" onclick="window.open();return false;"

Other possibilities for the href are

javascript:void()

javascript:

#

javascript://This Is Safer

 


Friday, June 24, 2005 8:06:43 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [3]
 Friday, April 01, 2005

This is not an April Fools post - although when you get to the end of it you may wonder.

As a proof of concept of the MetaWrap Apache_mod interface I'm going to write something that distributes grid tasks to web browsers as JavaScript transcoded from the MetaWrap VM.

Whenever someone visits a particular web page, either by included .js script file or an IFRAME I'll run some code that performs some small part of batch task that's been registered on a MetaWrap server.

Maybe not really a practical test unless I get some force multiplier from JavaScript being the only real "Run Anywhere" language out there and get a really huge number of users.

This is really a test of the MetaWrap server and the ability to create and coordinate a distributed computing task and display the results.

Aiming for something that will run on IE, Mozilla and as many mobile phone browsers that I can find that can run JavaScript of some kind. I figure there are so many 200Mhz + phones out there that it may be worthwhile.

Plan is to build a database of jobs that will render an ultra high resolution Mandelbrot set.

Or maybe ray trace a scene.

Need some way to allow people to navigate the completed Mandelbrot set online - which is a task in itself.

[Update 7/8/2005]

Google maps style interface would go nicely!

Using Action XML format to encode jobs. At this rate though not going to be finished for another year.. :(

[update 13/11/2005]

Javascript Mandelbrot set generator

http://jepstone.net/blog/?p=128

JavaScript Ray Tracer

http://www.slimeland.com/raytrace/

 

Friday, April 01, 2005 5:56:05 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [0]