Fancy Drop Cap - Part 2
In Fancy Drop Cap - Part 1, I showed how I used jQuery to insert a drop cap on my personal weblog. But there is still some unfinished business to take care of:
- Accounting for cases in which the first paragraph (where I want my drop cap to go) starts with another tag of some sort (
<a href="...">, <em>, etc.) - Adding a little CSS to the drop cap
So let's begin with item 1. As you may recall, we defined three variables, first_paragraph, first_letter, and text. The variables allowed us to get the value of the textNode of the first letter of the first paragraph, so we could replace it with the image. Here is what that part looked like:
The only problem with that code is that line 3 assumes that the first child node of the first paragraph is actually a text node. But what if it's a span tag (<span>) or a link (<a href="...">)? Well, in that case we'll need to keep drilling down through the nodes until we can't go any farther.
Loop the Loop
To do that, we'll set an intermediate variable, called node, initially making it the same as first_paragraph:
-
var node = first_paragraph;
Next, we change our node variable to be defined as the first child of that node (node = node.firstChild), and we keep doing that until there are no more child nodes left, by using a "while" loop:
-
node = node.firstChild;
-
}
So, in other words, as long as there is a child node, our variable will be reset as that child node.
The First Letter — and Only a Letter
When that's all done, we set our text variable, this time as the value of our node variable:
Now all we have to do is get the first letter of the text so that we can replace it with the drop-cap image: var first_letter = text.substr(0,1).
There is just one more thing that we should account for — the possibility that the first character is either the beginning of a self-closing tag such as <img /> or some other character for which we have no image. In my case, I only want a letter "a" through "z" to be replaced. Here is a simple regular expression for that, followed by a "if" condition that wraps the image-replacement code:
-
var match = /[a-zA-Z]/.test(first_letter);
-
if ( match ) {
-
// image-replacement code goes here
-
}
Line 2 tests if first_letter is a lower-case or upper-case letter. If it is, "match" will return true; if it isn't, "match" will return false. Thanks to Fil for posting a comment about that on Part 1.
The full code
Here is what all of the code looks like.
-
swap_letter();
-
});
-
function swap_letter() {
-
var first_paragraph = $('#main-content p')[0];
-
if (!first_paragraph) return false;
-
var node = first_paragraph;
-
node = node.firstChild;
-
}
-
-
var match = /[a-zA-Z]/.test(first_letter);
-
if ( match ) {
-
$('<img />')
-
}
-
}
For an explanation of the parts of this code not discussed in this entry, see my previous entry, Fancy Drop Cap - Part 1.
Adding Some Style
If we leave the fancy letter the way that it is, it will stick up above the rest of the first line in the paragraph. But we want it to drop. Fortunately, we've given our image a class called "fancy-letter," so we can just attach the style to that class. Let's float the image left and give it some padding on the top, right, and bottom:
-
img.fancy-letter {
-
float: left;
-
margin: 2px 2px 2px 0;
-
}
That's all there is to it! If you'd like to try this on your own site, you can download the script here. You'll also need the jQuery source code, of course. And here is a zip file of the fancy letters that I use. (20KB zip)
Update: To see how you can add fancy drop caps to every paragraph within a certain DIV, see my other entry: Multiple Fancy Drop Caps.



May 28th, 2007 at 9:52 am
[...] Google search turned up a tutorial on Learn jQuery which fit my needs. However, being a perfectionist, I felt I could improve on the code and tailor [...]
February 4th, 2008 at 8:43 am
From accessibility point of view, much better is don't put an img tag with alt attribute, but surround the first letter by span tag and add look via CSS.
How manage these images? Simple by add class related to letter, like this:
<span class="fancy-letter letter-t">T</span>hat's all there is to it!
May 14th, 2008 at 7:07 pm
Yeah... what Wojciech Bednarski said. I want to wrap the first letter of a specific tag in a span and add a class with a name that has that letter. Does anyone know how to do that in jQuery?
May 16th, 2008 at 3:15 pm
Wojciech and Craig,
Based on your feedback, I created a Fancy Letter Plugin that wraps a span tag around the first character of all elements matched by the jQuery selector.
May 17th, 2008 at 9:31 am
Thank you Karl!!!