Add a Pop Up Div to a Link Dynamically

Sometimes in life you have to ask “should I do this”, this is not one of those times. The idea is simple, click on a link and a div appears over the link with some kind of message in it. Kind of like being able to add a pop up note to a word. If you are absolutely amazed by that, don’t be afraid. Most likely you’ll die soon from forgetting to breathe. However, if you are just slightly curious as to why and how, keep reading.

So why did I do this? Well it started with the idea of having something simple for a blog that has multiple authors: What if other authors could add notes to someone’s post in the post. Well the idea of using some kind of text change (Like italics) sounded lame. I wanted something easy that could be replicated quickly and wouldn’t be visible unless needed. Thus the onClick idea. Now the next problem I had was the class needed for the style sheet. As you can see, when the div is shown, it doesn’t displace any of the items on the page. This is because I am using position:absolute and a high z-index. This allows for the div to lay on top of other things and not touch them. Problem with absolute is that it basicaly plants the div in relation to it’s parent container. Now that whole parent container thing seems to be up for interpretation when you are talking about browsers. Each seems to deal with it the way it sees fit.

Originally I had it as a div that would contain this new div. This was a pain in the -ss. In IE it showed up over the div, FireFox not so much. So the next thought was to create a div to hold the div that held the div. Something that isn’t exactly “user friendly” to be sure. Then it hit me, maybe I could put this in a link. After all, people who are viewing the blog would understand it’s something they can click on (Provided I don’t screw with the link styles too much) and it’s easy for non coders to copy and paste.

So on to the promised land. First I’ll just get the CSS out of the way since it’s absolutely needed but needs little explanation:

.hidePostComment
{
    visibility:hidden;
    position: absolute;
    z-index:-100;
}

.showPostComment
{
    background-color:Gray;
    border-color:Black;
    border-style:dotted;
    border-width:thin;
    color:White;
    margin-right:3px;
    padding:3px;
    position:absolute;
    text-decoration:none;
    visibility:visible;
    width:100px;
    z-index:10;
}

.hidePostComment

As you can see, I’ve screwed with the z-index, visibility, and position. Position I’ve already explained, and I think you can understand why visibility is hidden with this class. However, z-index might not be something you know about. Basically,z-index tells the browser where an item is in a vertical sense. When you look at a browser, there are actually a lot of layers regardless of the 2nd appearance. The z-index is used to bring something forward or backward. If I want the div to be behind say the text I am typing right now, it has to be at a z-index lower than the text. I used -100 in the example just to make sure it’s behind anything. It’s really an arbitrary number though. A positive number would make the div appear in front of the text (And in that case the text would not show up since it would be “behind” the div) which is what I did with the visibility class.

.showPostComment

Mostly just a bunch of visual changes like border and background color. However, you will also notice the the position is still absolute and that the z-index is now 10. (positive) The div will now effectively be “in front” of the link when it shows up giving it the pop up look. One Note: I had to add in text-decoration:none since the div is attached to the link and IE wants to drag the underline with the pop up causing the text to up with an underline. Kind of odd but no big deal.

Now for the code:

function BuildSelectableSpanForPost(spanName, parentElement, innerText)
{
    var divToAdd;
    var parentContainer;
    //check to see if the parentElement is actually an element or string.  If string, use it
    //to find the element.
    if (typeof parentElement == 'string')
    {
        parentContainer = document.getElementById(parentElement);
    }
    else
    {
        parentContainer = parentElement;
    }
    //Create the div
    //set the name (The name must unique since there could be a million "pop ups" per page
    //set the id
    //set the text for the div which is what we want to show up in the pop up
    divToAdd = document.createElement('span');
    divToAdd.setAttribute('name', spanName);
    divToAdd.id = spanName;
    divToAdd.innerHTML = innerText;

    //Add the div to whatever element that was found.  For this post it will be a link
    //but it doesn't really matter.
    parentContainer.appendChild(divToAdd);

    return divToAdd;
}

So there is the building of the pop up div. Here’s the method to be called by the onclick event:

function ShowCommentForPost(postName, parentElement, innerText)
{
    var divName;
    var createdDiv;
    var parentContainer;

    //Same as before
    if (typeof parentElement == 'string')
    {
        parentContainer = document.getElementById(parentElement);
    }
    else
    {
        parentContainer = parentElement;
    }
    //See if the pop up div  already exists.  If it does, then don't create again
    //I didn't have this before and it would create a new div everytime
    //That's what some might call a surprise feature
    divName = 'comment' + postName;
    createdDiv = document.getElementById(divName);
    //Ooops, the div didn't exist, create it and add the hide class
    if (createdDiv == null)
    {
        createdDiv = BuildSelectableSpanForPost(divName, parentContainer, innerText);
        //this is a method found on this post
        ClassHandler.AddClass(createdDiv, 'hidePostComment');
    }

    //this is a method based off this post
    //As you can guess it will show or hide depending on which class it already has.
    ShowHideElementBasedOnCss(createdDiv);

    return false;
}

To start, there is the code to create the actual div.

Now for the actual use:

<a onclick="return ShowCommentForPost('1', this, 'THIS IS SO STUPID!');" href="www.byatool.com">word.</a>

Pretty easy to actually use right? The actual location doesn’t really matter since it the method will always return false and therefore the link will never redirect. Also, you’ll see that I put 1 as the name sent in. The name sent in doesn’t matter what it is, but for every link it has to be different. If you are using this in a blog situation where there could be multiple blog posts in one page, I would suggest the name sent in would be the title and an increasing number.

If you got to this point and feel robbed of five minutes in your life, well just be happy this post robbed me of 15 minutes of mine.