jQuery Popups without jQuery UI – Part 2

In part 1, we went over the creation of a basic jQuery popup plugin. While this is very useful in itself, it is not that flexible yet. This time around we are going to add a few new features that will make our popup plugin way more flexible and useful. So come on and find out what cool things we will make our popup do.

Before we get started, I am just going to note that we are going to be starting with the code we created in part 1. If you have not read it, you should, because you may get a little bit lost otherwise. So keep in mind we are building on part 1.

Here is a quick example of our new and improved popup:

Show Popup

I am a popup…meow.

Now that you have part 1 in mind, let’s get started. The first thing we will be adding is a title bar/drag handle that will provide a limited area for the user to click on to initiate dragging. Basically, we will turn our popup in to a normal window, that has a draggable title bar. To begin, we have some new HTML and CSS to implement, which looks like so:

<html>
  <head>
    <title>THIS. IS. JQUERY!</title>
    <style type="text/css">
      #popup
      {
        width: 400px;
        height:400px;
        background-color: #009900;
        color: #000;
        position: absolute;
        top: 20px;
        left: 100px;
      }

      .no-select
      {
        -webkit-user-select: none;
        -khtml-user-select: none;
        -moz-user-select: none;
        -o-user-select: none;
        user-select: none;
      }
     
      #popup #handle
      {
        display: block;
        width: 100%;
        height: 30px;
        background-color: #006600;
      }
    </style>
  </head>
  <body>
   
    <div id="main">
      <div id="popup">
        <span id="handle"></span>
        This is a popup…
      </div>
    </div>
    <script type="text/javascript" src="jquery-1.5.min.js"></script>
    <script type="text/javascript" src="jquery.popup.js"></script>
    <script type="text/javascript">
      $(document).ready(function(){
        $(‘#popup’).popup({ handle: "handle" });
      });
    </script>
  </body>
</html>

AS you can see, we added three things here, all revolving around the “handle” we will be using. We added the HTML and CSS for the handle, and more importantly, we added our first parameter to our call to popup: handle: "handle". Now we have to use all this new stuff.

The parameter we pass into the function represents the ID of the element to use as the handle inside our popup. So what we have to do is search our popup for an element with that ID, then apply the mousedown event to the handle instead of the popup itself. Then we just add the close anchor to the handle as opposed to the popup. When it is all said and done, the changes will look like so:

(function($)
{
  $.fn.popup = function(params)
  {
    if(params == undefined)
      params = {handle: null};
   
    var handle = this;
    if(params.handle != null)
      handle = this.find("#" + params.handle);
   
    var popupElm = this;
    handle.mousedown(function(emd){
       
        /* Get the mouses offset when you click the popup. */
        var offset = popupElm.offset();
        var mxOff = emd.pageX offset.left;
        var myOff = emd.pageY offset.top;
         
        $("body").mousemove(function(emm){
         
          /* Gets the x and y to set the
           * popup to, taking into account
           * the offset of the mouse position. */

          var x = emm.pageX mxOff;
          var y = emm.pageY myOff;
         
          popupElm.css({
            ‘left’: x,
            ‘top’: y
          });
        })
        .addClass("no-select")
        .attr(‘unselectable’, ‘on’);
       
      })
      .mouseup(function(e){
        $(‘body’)
          .unbind(‘mousemove’)
          .removeClass("no-select")
          .attr(‘unselectable’, ‘off’);
      });
     
      /* Add a close anchor. */
      $(‘<a href="">close</a>’).click(function(e){
        e.preventDefault();
        popupElm.hide();
        $(this).remove();
      }).appendTo(handle);
     
      /* Move the popup to the bottom of the document. */
      popupElm.detach();
      $(‘body’).append(popupElm);
      popupElm.show();
  };
})(jQuery);

The first thing you may have noticed is the check on params. This check sets all our params (in this case just one) to null when the params object is not passed in. This is just a simple way to make sure we don’t try to access any params that don’t exist, since checking for null still requires the params object to be defined.

The next logic we added finds the handle element, if one is provided, and sets the clickable handle to that element. By default the handle is set to the popup itself. Once we have the handle, it is just a matter using it for the mousedown event, and adding the close anchor to it. The only other addition was to change our closing anchor to popup itself, rather than referring to a parent.

If you ran this, exactly the way presented, you would have a popup that is draggable only by the handle, or title bar if you will. However, it is missing something else we need…a way to position it where we want.

Generally you want to have a way to position your popup when it is shown, before the user moves it. Luckily this can be done with only a few additions. Lets take a look at the updated code:

(function($)
{
  $.fn.popup = function(params)
  {    
    if(params == undefined)
      params = {x: null, y: null, handle: null};
   
    /* Set the x position. */
    if(params.x != null)
      this.css(‘left’, params.x this.width() + "px");
    else
      this.css(‘left’, ($(window).width() / 2) – (this.width() / 2) + "px");
   
    /* Set the y position. */
    if(params.y != null)
      this.css(‘top’, params.y + "px");
    else
      this.css(‘top’, ($(window).height() / 2) – (this.height() / 2) + "px");
   
    var handle = this;
    if(params.handle != null)
      handle = this.find("#" + params.handle);
   
    var popupElm = this;
    handle.mousedown(function(emd){
       
        /* Get the mouses offset when you click the popup. */
        var offset = popupElm.offset();
        var mxOff = emd.pageX offset.left;
        var myOff = emd.pageY offset.top;
         
        $("body").mousemove(function(emm){
         
          /* Gets the x and y to set the
           * popup to, taking into account
           * the offset of the mouse position. */

          var x = emm.pageX mxOff;
          var y = emm.pageY myOff;
         
          popupElm.css({
            ‘left’: x,
            ‘top’: y
          });
        })
        .addClass("no-select")
        .attr(‘unselectable’, ‘on’);
                       
      })
      .mouseup(function(e){
        $(‘body’)
          .unbind(‘mousemove’)
          .removeClass("no-select")
          .attr(‘unselectable’, ‘off’);
      });
     
      /* Add a close anchor. */
      $(‘<a href="">close</a>’).click(function(e){
        e.preventDefault();
        popupElm.hide();
        $(this).remove();
      }).appendTo(handle);
     
      /* Move the popup to the bottom of the document. */
      popupElm.detach();
      $(‘body’).append(popupElm);
      popupElm.show();
  };
})(jQuery);

So the first thing you will notice is that we now set a x and a y property in our params object if it is undefined. This is how we get the initial position, through the params object.

Next we check the x and y params, and if they are null, we use the middle of the screen, horizontally and vertically accordingly. However, if either a x or a y is provided, we set the position to those coordinates. This allows you to maybe provide a y (say 10 pixels down), but leave the x alone, centering it horizontally.

Well,this is about all for this tutorial. Keep an eye out, because we may just have a part three coming soon. Just remember, when you need coding help, all you have to do is Switch On The Code.

Have suggestions for improvements for the jQuery Popup? Let us know! Comment or go over the forums and tell us what you would like to see!

Leave a Reply

Your email address will not be published. Required fields are marked *