A harmonica is a user interface (UI) element that allows a user to choose which part of a text they wish to see. The other parts then fold up. In this article: algorithm, examples, javascript code.
A.E.Veltstra
Saturday, August 23, 2008
So... you implemented a CMS (content management system) that allows for BBCode in an article text... and you want to employ a Harmonica effect to make your article better readable? But since your article contains BBCode you can't set ID's nor Classes... can we still do it?
Yes, we can!
Harmonica Example
It takes a small bit of unobtrusive javascript, primarily manipulating the DOM, to ensure the original text is available unharmed to visitors who can't use javascript. Let's break down what the script does:
1. It finds the container for the Harmonica. Luckily, that part is a div with an ID... it's the container of the BBCode article. The page is generated using PHP, which picks up the BBCode article, parses the BBCode to HTML and spits it out over the net.
2. It walks through the container's DOM tree, looking for HTMLElements. Because I created the BBCode article, I can predict in what order those elements will appear: a B element followed by text, and that several times in a row.
3. It starts converting the elements into Harmonica elements... B elements will become the Harmonica titles, and the texts in between will be the Harmonica bodies.
Unfortunately the texts themselves aren't elements... they're text nodes: blocks of text without elements, thrown into the container div. So we can't collect all P elements, for instance.
Instead, we have to walk the DOM tree and look for any node, then figure out whether it's an element or a text node, and react accordingly. The text nodes are converted into P elements, after which we can traverse them the normal way, and we can apply CSS.
4. My BBCode parser turns empty lines into BR elements. They look good outside of a Harmonica, but inside it they only confuse. So they have to go.
5. Because I want to have some kind of animation, collapsing and expanding the Harmonica bodies, I need each P element to hold several bits of information. This is stored in a special, custom object, added to each P element.
Since the B elements and the new P elements are all siblings, owner identifications are applied to the P elements as well, in the same custom object. That way, when someone clicks the Harmonica titles to expand its body, we can recognise the correct P elements to expand.
6. To make the animation run smoothly, window.setInterval() is used. That way, the animation shouldn't lock up the browser window nor the visitor's entire computer.
To make the animation stop, that interval handle has to be removed. That requires saving the interval handle in a place from where it can be retrieved.
Initially I tried saving it in the same custom object as before... I could save it, but not retrieve it. So I had to make a global array to hold all the separate intervals.
7. A bit of CSS and image application creates a different look for the Harmonica, helping the seeing visitors recognise it. I applied separate styles for screen, mobile and print media.
To see what a similar script can do when applying a different bit of CSS, take a look at this Tab Page Example.
Yes, we can!
Harmonica Example
It takes a small bit of unobtrusive javascript, primarily manipulating the DOM, to ensure the original text is available unharmed to visitors who can't use javascript. Let's break down what the script does:
1. It finds the container for the Harmonica. Luckily, that part is a div with an ID... it's the container of the BBCode article. The page is generated using PHP, which picks up the BBCode article, parses the BBCode to HTML and spits it out over the net.
2. It walks through the container's DOM tree, looking for HTMLElements. Because I created the BBCode article, I can predict in what order those elements will appear: a B element followed by text, and that several times in a row.
3. It starts converting the elements into Harmonica elements... B elements will become the Harmonica titles, and the texts in between will be the Harmonica bodies.
Unfortunately the texts themselves aren't elements... they're text nodes: blocks of text without elements, thrown into the container div. So we can't collect all P elements, for instance.
Instead, we have to walk the DOM tree and look for any node, then figure out whether it's an element or a text node, and react accordingly. The text nodes are converted into P elements, after which we can traverse them the normal way, and we can apply CSS.
4. My BBCode parser turns empty lines into BR elements. They look good outside of a Harmonica, but inside it they only confuse. So they have to go.
5. Because I want to have some kind of animation, collapsing and expanding the Harmonica bodies, I need each P element to hold several bits of information. This is stored in a special, custom object, added to each P element.
Since the B elements and the new P elements are all siblings, owner identifications are applied to the P elements as well, in the same custom object. That way, when someone clicks the Harmonica titles to expand its body, we can recognise the correct P elements to expand.
6. To make the animation run smoothly, window.setInterval() is used. That way, the animation shouldn't lock up the browser window nor the visitor's entire computer.
To make the animation stop, that interval handle has to be removed. That requires saving the interval handle in a place from where it can be retrieved.
Initially I tried saving it in the same custom object as before... I could save it, but not retrieve it. So I had to make a global array to hold all the separate intervals.
7. A bit of CSS and image application creates a different look for the Harmonica, helping the seeing visitors recognise it. I applied separate styles for screen, mobile and print media.
To see what a similar script can do when applying a different bit of CSS, take a look at this Tab Page Example.
Need problem solving?
Talk to me. Let's meet for coffee or over lunch. Mail me at “omegajunior at protonmail dot com”.