JavaScript Recipe: Adding Paragraph-level Permalinks

Posted Friday, February 12, 2010 at 5:24 p.m. by Chris Amico in Projects about code, JavaScript and recipes

Paragraph-level permalinks are hot, right? Let's do this in JavaScript, just for fun.

Remember from my last post that all you need is a block of HTML and something to parse it with? This is pretty much what JavaScript was made to do.

var entry = document.getElementById('entry-text');
var paras = entry.getElementsByTagName('p')

Assuming you have a div with id="entry-text", we've just grabbed every paragraph below it and created an array called paras. Simple enough.

Now, like we did with Python and Beautiful Soup, we're just going to loop through that list of paragraph elements, add and id attribute to each one, then create a link to that paragraph as a child element.

for (var i=0; i<paras.length; i++) {
    var p = paras[i];
    p.id = 'p' + i;

    // Create an <a> tag
    var a = document.createElement('a');
    a.href = '#p' + i;
    a.title = 'Link to this paragraph';

    // add link text
    a.appendChild(document.createTextNode(' #'));

    // append it to our <p> tag
    p.appendChild(a);

That's mostly it. Nothing terribly complicated. Except we should do two more things here:

  • Make it reusable, since you might not call your blog text div "entry-text"
  • Trigger it when the page loads

So, let's wrap this in a function and add it to an event callback on window:

function permalinks(id) {
    var entry = document.getElementById(id);
    var paras = entry.getElementsByTagName('p');
    for (var i=0; i < paras.length; i++) {
        var p = paras[i];
        p.id = 'p' + i;
        var a = document.createElement('a');
        a.href = '#p' + i;
        a.title = 'Link to this paragraph';
        a.appendChild(document.createTextNode(' #'));
        p.appendChild(a);
    };
};

window.addEventListener('load', function() {
    permalinks('entry-text');
}, false);

Simple enough. Like most things JavaScript, though, this gets shorter and easier with JQuery:

$(document).ready(function() {
    $('#entry-text > p').each(function(i) {
        var p = $(this);
        p.attr('id', 'p' + i);
        var a = $('<a/>').attr('href', '#p' + i)
        a.attr('title', 'Link to this paragraph');
        a.text(' #');
        p.append(a);
    });
});

OK, that's really it. Any of these methods will add a link to each paragraph in your chunk of HTML. If you want to see it in action, I added permalinked paragraphs to a couple of my recent posts, using each of the three methods described:

If there's something I missed, let me know in the comments.



Comments:

apr 7, 2010 at 1:17 p.m. // Ryan said:

Neat.

I think it gets a bit messy, visually, having the anchors after each paragraph. I'd probably add a CSS style to the links like the following:

p a.permalink { visibility:hidden }
p:hover a.permalink { visibility:visible }

That way you only see it when you're hovering over the paragraph.

Please use Markdown format, your real name and common decency. Remember that Google can always find the dumbest thing you've ever said.

Say it: