Learning from mistakes

This post is about my experience of learning jQuery. I’m developing some JavaScript for use with MathTran, and from past experience I know that I need a library. Elsewhere I explain why I’ve chosen jQuery. On Friday I started learning jQuery, mostly from the two Packt books, and yesterday and today (Saturday and Sunday) I’ve started with some coding.

I’m fairly new to JavaScript programming, and it’s easy for me to trip up on some of the language features. For example, it’s my Python habit to write ‘self’ when I really should be saying ‘this’. I addition, I’m not used to the widespread dynamic creation of functions, to be attached to DOM elements to handle events. So in addition to learning how to think jQuery, I’ve also been learning how to think JavaScript and DOM.

My first mistake: changing the DOM

Each formula can usefully be displayed in one of three ways

  • TeX notation only
  • Image only
  • Both TeX and image

I wanted a way to toggle all the math objects between TeX-only and image-only. And I had not even thought that one might want to see both at the same time.

The solution that first came to my mind, and which I started to code, was keep a list of all math-content nodes, and to change each of them in the DOM to achieve the toggle. In other words, the JavaScript would traverse the math nodes, replacing certain image nodes with TeX notation spans, and vice versa. And to achieve performance I would keep a list of all math-content nodes. I even managed to half-persuade myself that this might be a good idea.

Well, I was wrong. Reading the Learning jQuery book, I came to appreciate the value of changing the class of an object (such as the document body) in order to change the appearance of the content of the object. So I came to realise that I could keep both the TeX-notation spans and the rendered images in the DOM, and switch the display on and off by changing some classes on the document body (and some fairly trivial CSS also). From here it’s pretty easy to see that I could also display both at once if I want to.

Summary Try to avoid making changes to the DOM. If something is temporarily not needed, leave it in the DOM, but hide it. Changing a few classes (which is a small change to the DOM) is better than changing lots of nodes in the DOM. Yes, the work of finding and changing the display of all the mathematics nodes has to be done when the user preference changes, but why not let the browser do that work. Simply change a class or two and let the browser do the work.

My second mistake: not being ‘HTML creative’

One of the things I know I want to do is to transform certain documents. I wanted the author of the HTML page to supply only the ALT text for certain images, and the JavaScript would provide the image SRC, which would be a URL pointing to the public MathTran server.

I was thinking of this as being a matter of changing the DOM. Something like

  1. Compute and add a SRC attribute to the image node.
  2. Wrap the node in a span.
  3. Add a child to the span (a sibling of the image) for the TeX source.
  4. Set some classes.

I wrote code that did this as a sequence of DOM manipulations. Later, I realised I would need the same code when I was adding completely new mathematical images to the document. I’m also coming round to realising that using the browser to create DOM nodes from a string can be an efficient route, both in terms of programmer effort and browser resources.

So I found myself writing a function that would take a template such as

<span class=mathtran>
<span class=mathtran-tex></span>
<img class=mathtran-img />
</span>

and then add the TeX-related objects to the resulting object. In other words, instead of doing a sequence of DOM manipulations, simply create the DOM node from an HTML template.

Summary Use HTML as a template when creating DOM nodes, rather than doing everything with DOM manipulators. Use the manipulators only to change attributes and simple text content.

My third mistake: being different

Users of jQuery, after time, build up expectations about how to do things. The library provides standard tools for doing common tasks, and they have a consistent API. There’s a jQuery way of doing things, that I am beginning to learn.

With jQuery one writes $('.simple') to select all nodes in the document that have class ‘simple’. The plugin architecture of jQuery is one of its strengths, and so it makes sens for me to write a MathTran plugin for jQuery. Once one has this, one would expect to write $('.mathtran') to pick up all the MathTran nodes in the document. In other words, the standard thought patterns of jQuery, which seem to embody a great deal of wisdom and experience of JavaScript manipulation of the DOM, lead one to introduce and use a mathtran class in the CSS.

Put another way, much development follows the route

  1. Set up some CSS (to control the display)
  2. Use some selectors (to find suitable objects in the DOM)
  3. Use jQuery to make minor changes to these objects

If I tried to follow this route, then it’s most likely that I would have avoided mistake one (making large changes in the DOM, rather than using the CSS to leverage some small changes).

Summary This is not a new mistake. It is another way of looking at the first mistake. But it points to the benefits of knowing and understanding why things are done and they are in jQuery, and then trying to do the same.

My first success: the .tex() method

Every MathTran node — selected by, of course, $('.mathtran') — will contain a TeX string. It’s fairly obvious that we want a method to get this string, and another to set it. Setting it, of course, should change both the content of the span that contains the TeX and also the SRC attribute of the image.

There’s already a similar method in jQuery, which is the html() method. You can read documentation for it here. Giving the tex() method a similar API makes life so much easier, both for the programmer of the MathTran plugin for jQuery and for the user.

My second success: the .mathtran() method

If only out of vanity, we’d like the mathtran plugin to provide a mathtran() method. It’s fairly clear that it should construct mathtran nodes, that can be placed in the document tree. A little thought tells us that is should be what in some languages is called a class method. Mathematics exists in two forms, inline and display. The typography is different in the two cases. For example, compare with . The first is good for paragraph text (where it is important that formulas not be too high) and the second works well in displays (which is used for important formulas, and where the width should not be too great). So it’s clear that the typographic style should be a parameter to the mathtran() method.

I’ve not sorted out the API for this method yet, but it’s beginning to take shape.

How to ‘toggle’ with three choices

This post started with the three ways of displaying mathematics — TeX notation only, image only, or both. I’d like to put a button on the page that ‘toggles’ between the three possibilities. Writing this in a way that works well with jQuery is my current challenge, and part of my JavaScript, DOM and jQuery learning curve. You can see my currrent attempt here.

Conclusion

It’s important to make mistakes, and it’s important to learn from them. This is an example of the dialog between theory and practice (and my habit is to favour theory). As for jQuery, it has a well thought out API (that’s theory) which I should use as templates and examples when coding the MathTran plugin for jQuery. I should learn to rely more on CSS, particuarly when it can leverage minor changes to the DOM.

One final point. I’ve found that jQuery favours a sort of declarative approach to programming (make a series of statements about the situation and leave the browser to follow the resulting rules) rather than the procedural approach (tell the browser, step by step) what it should do. This is another aspect of the CSS example I’ve discussed in this post.

Advertisements