jQuery: Slide Menu With Pop Up Divs. Yay!

So you may have seen this post about how I came to create such a wonderful menu with no real purpose as of yet. Well that menu has been improved and can be downloaded here.

Remember that question you never asked? Well once again I’ve answered it.

To take the normal sliding menu farther I thought I should have something happen when hovering over the menu items. Novel! Well as you can see if you clicked on the link above (Sorry, can’t repost the link. Links are expensive.) the menu items have large counter parts that show up when hovered over and don’t go away until the counter part or the main item is left. What does this all mean? I DON’T KNOW but I’ll find out eventually. It’s in the cards man, it’s in the cards…

Ok so additions… For the style sheet, I added a class:

.menuItemBig
{
  height:100px;
  margin-right:5px;
  position:absolute;
  width:100px;
  z-index:100;
}

And have included a child div to the menu item:

Before

  <div class="menuItem floatLeft blue">1</div>

Now

  <div class="menuItem floatLeft blue">
    1
    <div class="menuItemBig red">THIS IS THE BIG ITEM 1</div>
  </div>

I added two methods:

//
// mouseenter: Find any menuItemBig within the given element and show
//             Reset the position of the menuItemBig element to appear
//             to be in the middle of the parent element
// mouseleave: Hide the child menuItemBig
//
function setOnHoverForMenuItems(items)
{
  jQuery(items)
  .each
  (
    function ()
    {
      jQuery(this).mouseenter
      (
        function()
        {
          //Why the positioning?  I wanted the child div to show up in the
          // middle of the parent div which is done by putting the child's left side
          // to half of the width of the parent over from the parent's left side
          var parentPosition = jQuery(this).position();
          var bigItems = jQuery(this).children(".menuItemBig");
          bigItems.css({ left: parentPosition.left - (jQuery(this).width() /2), top: parentPosition.top + 10  });
          bigItems.show();
        }
      );

      jQuery(this).mouseleave
      (
        function()
        {
          jQuery(this).children(".menuItemBig").hide();
        }
      );
    }
  );
}

Why not hover? *EDIT* It should be hover. Turns out an issue I was having with hover was not actually an issue with it… *END EDIT*

The other method I added was a simple one:

//
// Used to find any element of menuItemBig
//
function hideAllBigItems(bigItemParentItems)
{
  jQuery(bigItemParentItems).children(".menuItemBig").hide();
}

And where did I use these? I appended them to the setChildrenDivs method:

function setChildrenDivs(mainHolder)
{
  var menuItems = getMenuItems(mainHolder);

  for (var loopCounter = 0; loopCounter < menuItems.length; loopCounter++)
  {
    if(loopCounter > maximumToShow - 1)
    {
      jQuery(menuItems[loopCounter]).hide();
    }
  }

  setPager(jQuery(mainHolder).children(".leftPager"), getLastVisible, getNextInLineBack);
  setPager(jQuery(mainHolder).children(".rightPager"),getFirstVisible, getNextInLineFront);
  setOnHoverForMenuItems(menuItems);
  hideAllBigItems(menuItems);
}

So in all, this didn’t take much at all, thanks to mouseleave. Next up… not sure. No idea if I will take this any further.

jQuery Slide Menu… Another Cause I Can Experiment

So for no real reason at all I had it in my mind that I wanted to make a horizontal menu with jQuery that would work like that weird scrolling menu thing that Macs have. No idea what it’s called. So basically I don’t need it, have no reason for it, but damnit I’m going to make it happen and I did it with only 3 things from jquery.com; 1.3.2, ui 1.7.2, and jquery.timer . Now this is still rough in the sense it has no real styling but it works tried and true functionality wise.

The main idea is that there are two scroll arrows, one on each side, and X amount of divs. Now at the start, a certain amount of divs are hidden (global variable). When hovering over the left pager, for example, it causes one on the right to hide while one on the left appears giving the feeling of the items sliding.

EXAMPLE HERE!!11

The markup is simple, a holder with x number of elements that are “menuitems” and two pager divs.

<div class="mainHolder">
  <div class="leftPager green floatLeft"><</div>
  <div class="menuItem floatLeft blue">1</div>
  <div class="menuItem floatLeft red">2</div>
  <div class="menuItem floatLeft yellow">3</div>
  <div class="menuItem floatLeft blue">4</div>
  <div class="menuItem floatLeft red">5</div>
  <div class="menuItem floatLeft yellow">6</div>
  <div class="menuItem floatLeft blue">7</div>
  <div class="rightPager green floatLeft">></div>
</div>

I think from the classes you can tell what you need to know about them.

First thing we need from jQuery is methods to find various elements in the container when paging.

//When using the left pager, it's important to find the first visible element
//then find the item before it so that it can be shown.
function getNextInLineBack(menuItems)
{
  var oneBefore = null;

  for (var loopCounter = 0; loopCounter < menuItems.length; loopCounter++)
  {
    if(jQuery(menuItems[loopCounter]).is(":visible") && loopCounter > 0)
    {
      oneBefore = jQuery(menuItems[loopCounter - 1 ]);
      break;
    }
  }

  return oneBefore;
}

//Find the first visible element from the beginning.
//This will be needed when paging right since it will have to be hidden
function getFirstVisible(menuItems)
{
  var firstVisible = null;

  for (var loopCounter = 0; loopCounter < menuItems.length; loopCounter++)
  {
    if(jQuery(menuItems[loopCounter]).is(":visible") && loopCounter < menuItems.length - maximumToShow)
    {
        firstVisible = menuItems[loopCounter];
        break;
    }
  }
  return firstVisible;
} 

//Get the last possible visible item
//If the item is in an index less than the maximum number to show, then null is returned since there has to be no more or less than the maximumToShow.
function getLastVisible(menuItems)
{
  var lastVisible = null;
  for (var loopCounter = menuItems.length - 1; loopCounter > maximumToShow - 1; loopCounter--)
  {
    if(jQuery(menuItems[loopCounter]).is(":visible"))
    {
      lastVisible = menuItems[loopCounter];
      break;
    }
  }

  return lastVisible;
}

//Find the first visible from the end
//Pretty simple, this will be important when paging left since this
//will be the next item to be hidden
function getNextInLineFront(menuItems)
{
  var lastOne = null;

  for (var loopCounter = menuItems.length-1; loopCounter > -1; loopCounter--)
  {
    if(jQuery(menuItems[loopCounter]).is(":visible"))
    {
      lastOne = menuItems[loopCounter + 1];
      break;
    }
  }

  return lastOne;
}

Next is a method that is just used to stop having to repeat the same thing over and over when needing a list of all the menu items.

function getMenuItems(mainHolder)
{
  return jQuery(mainHolder).children(".menuItem");
}

Next is the method to handle what item to show and what item to hide when the pager has the mouse over it. Instead of having methods for the right and left pager, I just ended up having the methods for finding the item to hide and show sent through as parameters.

function showHideOnHover(pager, timer, getHideMethod, getShowMethod)
{
  //This is just candy for changing the color of the pager when the mouse
  //is over it
  jQuery(pager).removeClass("green");
  jQuery(pager).addClass("orange");

  //Remember those methods I passed through, well here they
  //are in use.  I'm using them to get the item to hide and the item
  //to show along with the list of items.
  var menuItems = getMenuItems(jQuery(pager).parent());
  var hide = getHideMethod(menuItems);
  var show = getShowMethod(menuItems);

  //If neither is null, then go ahead and show/hide
  //If either one is null, something isn't right and the timer
  //needs to be stopped.... timer??  Well I'll get to that
  //next.
  if(show != null && hide != null)
  {
    jQuery(hide).hide( "slide", { direction: "right" } , 0);
    jQuery(show).show( "slide", { direction: "left" } , 100);
  }
  else
  {
    timer.stop();
  }
}

Now for the method above the last one, this one involves the timer passed in the last method. This method actually sets the mouseover/mouseout events (aka hover). When mouseover, the timer is created and the showHideOnHover method is called every 500 units, that’s we’ll call tools, (Not sure how much that is, seems like a half second) after the first time it’s called. On mouseout, the timer is stopped, nulled out, and the pager changes it’s color.

function setPager(pager, hideMethod, showMethod)
{
  //Making the timer variable "global" to the events so that I know
  //I have the same timer for both mouseover and mouseout.
  var newTimer;
  pager.hover
  (
    //Mouseover method
    function()
    {
      var first = true;
      //This sets the timer, consequently starting the method for the first time.
      //Why timer doesn't have a start method I don't know.  Ask jquery.com.
      //The first thing is just so that the first time around it runs right away,
      //then each call afterwards comes every 500 tools.
      newTimer = jQuery.timer
                      (
                         0, //First time through, runs after 0 tools.
                         function(timer)
                         {
                           showHideOnHover(pager, timer, hideMethod, showMethod);
                           //If this is the first time through, reset
                           //timer to run every 500 tools.
                           if(first)
                           {
                              timer.reset(500);
                              first = false;
                           }
                         }
                       );
    },

    //Mouseout method
    function()
    {
      //mouse is done, stop the timer
      newTimer.stop();
      newTimer = null;
      jQuery(pager).addClass("green");
      jQuery(pager).removeClass("orange")
    }
  );
}

Now for the method above the one… above. This is used to set the children of the passed in holder.

function setChildrenDivs(mainHolder)
{
  //Get the items for the holder
  var menuItems = getMenuItems(mainHolder);

  //Hide all the items after the first X items (maximumToShow)
  for (var loopCounter = 0; loopCounter < menuItems.length; loopCounter++)
  {
    if(loopCounter > maximumToShow - 1)
    {
      jQuery(menuItems[loopCounter]).hide();
    }
  }

  //set the pagers.
  setPager(jQuery(mainHolder).children(".leftPager"), getLastVisible, getNextInLineBack);
  setPager(jQuery(mainHolder).children(".rightPager"),getFirstVisible, getNextInLineFront);
}

FINALLY THE END! This is the document.ready method used to set this whole joke in motion. maximumToShow is just how many items to show at a time and is global.

var maximumToShow = 5;

jQuery(document).ready
(
  function()
  {
    //Find every holder on the page and set everything in motion.
    var mainHolders = jQuery(".mainHolder");
    for (var loopCounter = 0; loopCounter < mainHolders.length; loopCounter++)
    {
      setChildrenDivs(mainHolders[loopCounter]);
    }
  }
);

Why the timer? If you haven’t figured that out yet, well it’s because I had issues with how to get the menu to keep doing it’s thing as long as the user had his/her mouse over a pager. I didn’t want this to be a click menu because, let’s be honest, that would be much easier. So as is, the timer is started the moment the mouse is over a pager and hides/shows an item. Then every 500 tools the mouse is over the pager, it continues the hide/show until it runs out of items to show/hide. (End of the list)

Uhg that’s annoying to type out even with cut and paste so I will host it here.

I suppose the next part of this would have the items blow up or something when hovering over them but that should be much easier than this was.

jQuery Slide and Pairing a Div’s Hover With a Div’s Slide

So this could be filed under “I did it because I can” (which is a really good mantra in science…) and am not sure I’ll use it but it is useful in the concept.

LIVE EXAMPLE HERE

The idea is to set the hover on one div to show/hide another div WITHOUT having to use some kind of id/name trick (as in setting the id to “divHide1”) and to have it be completely self setting in the .ready method. Why would this be at all useful? Say you want to roll through a list of things and generate the divs, but want to defer the jQuery until the page has loaded. And you don’t want to have to resort to:

    <div id="someDiv<%= someId %>"></div>

like structure where you parse some identifier from the id property. Mostly because you have no idea how many someDiv1s there could be on the page. It could be a highly reused name (someDiv) and that could lead to a mess.

Also the reason ‘cuz. If you have any more questions of why after that answer, well you’re just being annoying.

Anywho, here’s the actual html for structure.

   <div class="mainDiv">
      <div class="showDiv" id="oneTop">
        Kaneda?
      </div>
      <div class="slideDiv" id="one">
        What do you see?!
      </div>
    </div>
    <div class="clear"></div>

Now I get that this isn’t off a foreach, but it doesn’t take much to figure out that it’s easily made into a loop if you just loop it over and over. Why? Because first there are no ids or names so that you can’t have two of the same name and also because that chunk is self contained.

So what is going on there? Simple, you have a parent container that holds a div to hold and a div to hover over and the other that will be shown/hidden.

Here’s the styles involved just incase you care:

    <style type="text/css">
        .clear
        {
        	clear:both;
        }

        .leftDiv
        {
        	float:left;
        }

        .mainDiv
        {
        	margin:5px;
        	height:200px;
        }

        .rightDiv
        {
        	float:left;
        }

        .showDiv
        {
        	float:left;
        	margin-right:5px;
        	height:200px;
        	background-color:Silver;
        }

        .slideDiv
        {
        	background-color:Teal;
        	height:200px;
        	position:absolute;
        	float:left;
        	z-index:100;
        }
    </style>

That doesn’t entirely matter, but it does to show the div “sliding” over another div. Kind of a little somethin’ somethin’ I threw in at no extra cost. Now for the jQuery:

First the method for setting the mouse over and out events for the show div, we turn to .hover:

    function setHover(currentSlideDiv, currentStableDiv)
    {
      currentStableDiv.hover
      (
        //first parameter is the method for showing the div on mouse over
        function()
        {
          if (currentSlideDiv.is(":hidden"))
          {
            currentSlideDiv.show("slide", { direction: "left" }, 100);
          }
        },
        //second parameter is the method for hiding the div on mouse out
        function()
        {
          if (currentSlideDiv.is(":visible"))
          {
            currentSlideDiv.hide("slide", { direction: "left" }, 100);
          }
        }
      );
    };

Now for the method that actually uses these:

    //This is used to take in one of the main divs and set all the
    //show and slide divs within.
    function setChildrenDivs(mainDiv)
    {
      //get all the show and slide dvis within the main div
      var mainChildrenStableDiv = jQuery(mainDiv).children(".showDiv");
      var mainChildrenSlide = jQuery(mainDiv).children(".slideDiv");

      //loop through the list of show divs
      for (var loopCounter = 0; loopCounter < mainChildrenStableDiv.length; loopCounter++)
      {
        //Get the show div and it's corresponding slide div using the
        //two lists and the current counter.
        var currentStableDiv = jQuery(mainChildrenStableDiv[loopCounter]);
        var currentSlideDiv = jQuery(mainChildrenSlide[loopCounter]);

         //This is to make sure the slide is where it should be.
         //to the right of the show div.
         var containerPosition = jQuery(currentStableDiv).position();
         jQuery(currentSlideDiv).css({ left: containerPosition.left + currentStableDiv.width() });
        //Set the mouse over and the mouse out on the show div
        setHover(currentSlideDiv, currentStableDiv);
      }
    }

Now the final touch, the .ready method:

    jQuery(document).ready
    (
      function()
      {
        //hide all the slide divs
        jQuery(".slideDiv").hide();

        //find all the parent divs
        var mainDivs = jQuery(".mainDiv");

        //set the children
        for (var loopCounter = 0; loopCounter < mainDivs.length; loopCounter++)
        {
          setChildrenDivs(mainDivs[loopCounter]);
        }
      }
    );

And boom, now you have multiple show/hide (Slide in this instance). Now if I could just find a use for it…

Oh yeah and you’ll need jQuery 1.3.2 and jQuery ui 1.7.2 to use this. At least those are the versions I know this works with.

Update: Due to popular demand… one person… Source can be found here.

ASP.Net MVC, jQuery, JSon, and paging… how’s that for a SOE title?

One of the things I’ve come to realize is how easy it easy to do a lot of things with these three buzzwords. In fact, I’m pretty convinced it’s so easy that it’s actually complex and I am a genius. Not buying it? Neither am I.

So for an experiement the other day I decided to try my hand at some sort of dynamic grid using jQuery’s ajax fun and JSon. Just so happens that this works really well with MVC’s REST like makeup. Don’t know what REST is? On a very tool level, it’s using a url and a command to tell the server what to do. So something like:

www.byatool.com/users/dostuff

Could mean either get all users (if using get) or create a user (If using post). And yes that is probably a ridiculously simplistic view so I’d suggest consulting the Wikitruth. In an MVC sense this would be:

Controller: Users
Action: dostuff

Now most likely your Get All Users action isn’t going to the same as your Add A User action, but it was just a stupid example ok?

However, with jQuery what this means is you have a simple url that it can call and get information from, making it incredibly easy to set up a dynamic grid.

So first off, lets say I have a Forum controller with an action of IndexJquery… yeah I know cheesy name, but it gets the job done. Basically the method IndexJquery would have to take in a page number and optionally (And for this example) how many items to show along with a sort. With that it should return a JSon “object” that will be in this example holds first page, last page, next page, previous page, sortBy, and some kind of list of stuff. (For the two people actually reading this, comment if you want the c# code. It’s really just basic MVC stuff.)

The markup for this is pretty simple. I have a div to hold the grid, four directional divs that work as buttons (First, Previous, Next, Last), and two div “butons” for how many items to show.

    <div>
        <div id="divHolder">
        </div>
    </div>
    <div>
        <div id="divFirstPage" class="divLink floatLeft">
            <<
        </div>
        <div id="divPreviousPage" class="divLink floatLeft">
            <
        </div>
        <div id="divNextPage" class="divLink floatLeft">
            >
        </div>
        <div id="divLastPage" class="divLink floatLeft">
            >>
        </div>
    </div>
    <div class="clear"></div>
    <div>
        <div id="divAmountToShowOne" class="divLink floatLeft">
            1
        </div>
        <div id="divAmountToShowFive" class="divLink floatLeft">
            5
        </div>
    </div>
    <div class="clear"></div>

As you can see exactly as advertised.

Ready for the call? It’s waaaaay hard:

        function getGrid(pageNumberIn, amountToShowIn, sortByIn)
        {
            jQuery.getJSON
            (
               //This is the url for the information I need
               "http://www.someurl.com/Forum/IndexJquery/",
               //this is the construction of the "object" to send... really this just
               //means that I have a method somewhere looking for pageNumber,
               //amountToShow, and sortBy
               {
                   pageNumber: pageNumberIn,
                   amountToShow: amountToShowIn,
                   sortBy: sortByIn
               },
               //This is the method to call once this ajax transaction has completed...
               //transaction may not be the best word.  Basically it has to be a method
               //that takes in the result from the getJSon call
               returned
            );
        }

Next would be the script to actually create the grid. Looks verbose, but most likely thats because I didn’t refactor much.

    function returned(jsonObject)
    {
        //Have to remove all the previous click event handlers since because
        //this is all client side, there's no "refresh" and therefore the object
        //is still in memory.  So even though I might call the method to get the
        //information, the "objects" are still in memory.
        jQuery("#divFirstPage").unbind("click");
        jQuery("#divLastPage").unbind("click");
        jQuery("#divNextPage").unbind("click");
        jQuery("#divPreviousPage").unbind("click");
        jQuery("#divAmountToShowOne").unbind("click");
        jQuery("#divAmountToShowFive").unbind("click");

        //Ok so now that the event is not being listened to, set up the listeners
        //The idea is to call that getGrid method and pass in the values straight
        //off the previously returned json object.  Using jQuery's easy .click method
        //makes this so simple.
        jQuery("#divFirstPage").click(function() { getGrid(jsonObject.FirstPage, jsonObject.AmountToShow, jsonObject.SortBy); })
        jQuery("#divPreviousPage").click(function() { getGrid(jsonObject.PreviousPage, jsonObject.AmountToShow, jsonObject.SortBy); })
        jQuery("#divNextPage").click(function() { getGrid(jsonObject.NextPage, jsonObject.AmountToShow, jsonObject.SortBy); })
        jQuery("#divLastPage").click(function() { getGrid(jsonObject.LastPage, jsonObject.AmountToShow, jsonObject.SortBy); })
        jQuery("#divAmountToShowOne").click(function() { getGrid(0, 1, jsonObject.SortBy); })
        jQuery("#divAmountToShowFive").click(function() { getGrid(0, 5, jsonObject.SortBy); })

        //Again since this is client side, the divHolder "object" still is holding
        //the previous results.  These have to be cleared.
        jQuery("#divHolder").children().remove();

        //Create the table and loop through the list.
        var mytable = document.createElement("table");
        var mytablebody = document.createElement("tbody");

        for (loopCounter = 0; loopCounter < jsonObject.ListForViewing.length; loopCounter++)
        {
           var currentItem = something.ListForViewing[loopCounter];
           var mycurrent_row = document.createElement("tr");

           var mycurrent_cell = document.createElement("td");
           var currentText = document.createTextNode(currentItem.ForumName);
           mycurrent_cell.appendChild(currentText);
           mycurrent_row.appendChild(mycurrent_cell);

           mytablebody.appendChild(mycurrent_row);
        }

        mytable.appendChild(mytablebody);
        //Don't forget to add the table to the div!!11
        jQuery("#divHolder").append(mytable);
        return false;
    }

And boom. So easy even a ca… tool can do it. Now if you want this grid to come preloaded, it’s pretty easy:

    jQuery(document).ready
    (
        function setPage()
        {
            getGrid(0, 10, null);
        }
    )

Stop the IPhone / Safari from Minimzing a Page

Real quick one, but I thought this was crazy useful.

If you’re developing a web based app that might be used by IPhone users, there is a simple way to stop the IPhone from shrinking the page onload. Thanks to Mark W on The Stack Hath Runith Over there is a simple solution.

  <head runat="server">
     <title>I LOVE TITLES!</title>
     <meta name="viewport" content="width=420" />

That one beautiful metatag makes life worth living again… until the next Street Fighter movie comes out. Then life is back in the forfeit container. Here’s a link to more options:
BYEBYE

jQuery: Add a Pop Up Div to a Link Dynamically

So as an exercise to learn more about jQuery, I decided to redo this little gem using jQuery. Have to say though only technically XHTML compliant, it worked out much better and with less code. So the idea is to have something really easy for non programmers (You know, lesser people) to be able to have a pop up comment added to some chunk of text on a web site. What I came up with before was ok but kind of annoying since it looked like this:

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

Kind of annoying since I would have to explain that ‘1’ is the name and it has to be unique for every one of these, this isn’t really understood by those people, and well it just seems more complicated then it needs to be. So what if I told you it could look like this?

<a href="http://www.byatool.com" class="showItLink" xmlns:comment="hihihi">HI</a>

Gorsh, that seems even better and it works in both IE and Firefox… which might be a first for this site and anything javascript. First let’s get the css out of the way, shall we?

    .showItLink
    {
    }

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

Most of the is just for looks, but like the older example I’ve called upon the power of position:absolute and z-index well that’s just pulling it in front of everything else.

Next part will be the actual code, and if you take the method from THE POSITION ABSOLUTE POST

    function SetTopAndLeft(parentContainer, elementToSet)
    {
        var containerPosition;

        containerPosition = $(parentContainer).position();
        $(elementToSet).css({ top: containerPosition.top + 10, left: containerPosition.left + 10 });
    }

and add in a simple span creation method:

    function CreateDiv(innerText, cssClass)
    {
        var spanToAdd;

        spanToAdd = document.createElement('span');
        spanToAdd.className = cssClass;
        spanToAdd.innerHTML = innerText;

        return spanToAdd;
    }

you’re ready for the actual fun part… making sure something pops up when the link is clicked.

jQuery(document).ready  //Everything inside this will load as soon as the DOM is loaded and before the page contents are loaded.*
(
    function()  //this is the start of an anonymous method
    {
        jQuery(".showItLink").click //find all things with the .showItLink class and assign the click event to the next anonymous method
        (
            function(event) //this is the start of an anonymous method for the click event
            {
                var containerPosition;
                var createdSpan;
                var comment;

                comment = jQuery(this).attr("xmlns:comment");  //Get the value from the comment attribute on the link.
                createdSpan = jQuery(this).children(".postComment"); //Find a possible span already attached to the link if it exists.  The span is of class 'postComment'

                if (createdSpan.length == 0)  //span doesn't exist
                {
                    createdSpan= CreateDiv(comment, "postComment");  //create the span
                    jQuery(this).append(createdSpan);  //Add the span to the link
                    jQuery(this).children(".postComment").hide();  //Make sure the new span is hidden
                }
                SetTopAndLeft(this, createdSpan);  //Set the position of the span
                jQuery(createdDiv).toggle();  //This will hide if it's showing, show if it's hidden... kind of nice huh?

                event.preventDefault();  //Equivalent to false.  Need this for Firefox.
            }
        );
    }
);

And boom you have something that works. Hooray.

Couple things of note:

.Hide – At first I though this would screw up my class for the span by removing the current class and adding display:none. Turns out it doesn’t harm the original class. Kind of nice.

.Toggle() – This is really nice. It will hide if it is showing and show if hidden. Stupid easy to use and is pretty effective. Just like .Hide, the class of the element is not harmed.

$ versus jQuery – Some people might notice that I am not using the short hand $ for my jQuery calls. Turns out that it might be safer this way. There are other javascript libraries that use the $ short hand like prototype. I ran into this with WordPress since it uses both jQuery and Prototype and blocks jQuery from using $ since it could conflict with other libraries. Weeeee!

JQuery, Position : Absolute, and How to Make It All Work

This is a really quick one but when I was taking my cheesy pop up and reworking it using JQuery (After Andre the Annoying wouldn’t shut up about it), I ran into a fun problem: position:absolute wasn’t working like it should. You know “absolute is positioned at the specified coordinates relative to its containing block.”. Meaning it should at worst show up within it’s container, where ever that is. Now IE is fine with that and the thing was showing up well:

absolutepositionie

Firefox? Not so much:

absolutepositionfirefox

Well… turns out JQuery pretty much does it for me. With a simple method, you can set one element’s position relative to a parent’s position:

    function SetTopAndLeft(parentContainer, elementToSet)
    {
        var containerPosition;

        containerPosition = $(parentContainer).position();
        $(elementToSet).css({ top: containerPosition.top + 10, left: containerPosition.left + 10 });
    }

Really simple, you get the position of the parent container and you set the child element’s top and left to it. Or in this case, I have it just off since hiding the parent container could be problematic. (Say if the parent container is a link AND NOW YOU CAN’T FIND IT TO CLICK ON IT AND THINGS HAPPEN BAD THINGS AND THE WORLD EXPLODES BECAUSE OF YOU!)

And boom, you can for once be a winner just like me.

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.

Add, Remove, or Replace a CSS Class Using Javascript

Now honestly, I think the all famous Prototype has something for this, but if you aren’t using the all famous Prototype… well you’re screwed. Until now.

This is the idea, you want show or hide something on a click of it.

    <div onclick="HideOrShowMe();">
      YAYAAYAYAY!
    </div>

Annoying thing is trying to keep up with whether it’s hidden or not. Now there are ways to do this for sure, but if you had them you wouldn’t be here… or you just love idiotic banter. Either way, you’re here.

To start, get a class going:

    if (typeof ClassHandler != 'object')
    {
      ClassHandler = new Object();
    }

Normal declaration. Yeehaw. Now we need a method to check for the class:

ClassHandler.CheckForClass = function(element, nameOfClass)
{
    var returnValue = false;

    //Check to see if the element variable is a string or (hopefully) a control.
    //If it is a string, get the control that belongs to that id.
    if (typeof element == 'string')
    {
        element = document.getElementById(element);
    }

    //next you use a regular expression to check the className property for
    //  the class you want.  If it finds a match, you're good to go.
    if (element.className != '')
    {
        returnValue = new RegExp('\\b' + nameOfClass + '\\b').test(element.className);
    }

    return returnValue;
}

Ok so now you have a method to check if it’s there… but what about if you want to replace the old one with a new one? Well that could be broken into two methods first (Both that are useful). First one is the removal of the old class:

ClassHandler.RemoveClass = function(element, nameOfClass)
{
    var returnValue = false;

    //You know the drill
    if (typeof element == 'string')
    {
        element = document.getElementById(element);
    }

    //Hey cool, I just used the CheckForClass method
    if (ClassHandler.CheckForClass(element, nameOfClass))
    {
        //Real simple, replace the old
        //But you have to check if the nameOfClass exists with a preceding space
        //If it does, then you replace that with a space, other wise just replace
        //the nameOfClass with a space.
        element.className = element.className.replace((element.className.indexOf(' ' + nameOfClass) >= 0 ? ' ' + nameOfClass : nameOfClass),'');
        returnValue = true;
    } 

    return returnValue;
}

And now you’ll have to add in the new one.

ClassHandler.AddClass = function(element, nameOfClass)
{
    var returnValue = false;
    //lalalala
    if (typeof element == 'string')
    {
        element = document.getElementById(element);
    }
    //If className already has a value, precede the nameOfClass with a space
    // otherwise just add it in.
    if (!ClassHandler.CheckForClass(element, nameOfClass))
    {
        element.className += (element.className ?  '  '  :  '') + nameOfClass;
        returnValue = true;
    } 

    return returnValue;
}

Now for the replace:

ClassHandler.ReplaceClass = function(element, classToRemove, classToAdd)
{
    var returnValue = false;

    //african elephants only have four teeth for chewing their food.
    if (typeof element == 'string')
    {
        element = document.getElementById(element);
    }

    //Remove the old one
    //Add the new one
    if(ClassHandler.CheckForClass(element, classToRemove))
    {
        ClassHandler.RemoveClass(element, classToRemove);
        ClassHandler.AddClass(element, classToAdd);
        returnValue = true;
    }

    return returnValue;
}

Now you might be thinking, “Tool, why don’t you just use the replace method in the replace method.” Well I suppose you could, but this way you have two other methods at your disposal for future use. Up to you really, part of this was because I actually needed those methods and the title says “Add, Remove, or Replace”. I can’t go against the title. I don’t have that kind of strength.

Usage? Well there are couple ways you can do this.

    if(ClassHandler.CheckForClass('someDiv', 'hide'))
    {
       ClassHandler.ReplaceClass('someDiv', 'hide', 'show');
    }
    else
    {
       ClassHandler.ReplaceClass('someDiv', 'show', 'hide');
    }

or this:

    if(!ClassHandler.ReplaceClass('someDiv', 'hide', 'show'))
    {
       ClassHandler.ReplaceClass('someDiv', 'show', 'hide'));
    }

And other ways to be sure. Now I’m not saying this is the best way to do it, just a decent way… although looking back on this I wonder if I could clean up the regex stuff.

Quick Hit: Hiding Horizontal or Vertical scroll using CSS

If nothing else the motto for this site is, “Why was this written?” but sometimes it can also be, “I bypass the middle man and pass the savings on to you.” In this case, it has to do with a really simple way to show only on scroll bar on a section be it a div, span, pre tag, ect. In fact, I actually used it to for this site.

Here’s the problem, you have a section that you want to only show the horizontal scroll bar. Now the scroll bar is usually set with the overflow keyword in css:

  overflow:auto;

But what does this do? Well if the section you have is larger than its parent (Say a pre section in a set width div), both scroll bars come up. Sometimes that’s not a bad thing but sometimes it looks really annoying if you only have two lines in it like:
bat_scroll1
Since it will automatically force both scroll bars. And on top of that, the scroll bars themselves now take up space and essentially cover up some of that second line. Well there’s two ways you can go about this in order to at least allow for everything to be seen without a verticle scroll.

1)

You can use the overflow-x and overflow-y keywords:

  {
    overflow-y:hidden;
    overflow-x:auto;
  }

What this does is completely hides the verticle scroll bar. Now this will work very well if you have sections that are of a specific height. Problem is if the height isn’t set specifically, it will just not show the parts that would normally need the verticle scroll for. (Happens sometimes)

bat_scroll2

This brings us to the second solution:

B)

Padding.

  padding:8px 0px 40px 0px;
  overflow-x:auto;
  overflow-y:hidden;

Really simple addition that will basically push the bottom of the container down so that the writing that was being hidden before (Because the scroll bar didn’t exist) is now pushed upwards causing no loss of stuff.

bat_scroll3

As you can see, now everything can be… eh seen. Sure you get that annoying bit of space, but the 40px I’m using could be a bit of overkill. You really just have to shoot for a number that allows the bottom to be shown. But hey, life is tough.