Tuesday, December 13, 2011

Modify DOM using jQuery contextMenu and dialog

Introduction
Recently we got a requirement to modify document object model with jQuery context menu  plugin. We could achieve this very easily with jQuery context menu plugin and jQuery dialog.

Details goes here-
For ease let us take a list of divs with some margin, padding and background color. The HTML for this goes here-
    <style>
        div.enableCtx
        {
            width:200px;
            background-color: Gray;
            margin: 5px 5px 5px 5px;
            padding: 5px 5px 5px 5px;
            color:White;
            font-size:15px;
        }
    </style>
    <div class="enableCtx"> data 1</div>
    <div class="enableCtx"> data 2</div>
    <div class="enableCtx"> data 3</div>
    <div class="enableCtx"> data 4</div>
    <div class="enableCtx"> data 5</div>
    <div class="enableCtx"> data 6</div>
    <div class="enableCtx"> data 7</div>
    <div class="enableCtx"> data 8</div>
    <div class="enableCtx"> data 9</div>
The requirement that we are going to implement here is as follows-
  • Use context menu jQuery plugin for this
  • The context menu should have options for add, edit and delete.
  • For adding and editing the data in each div we are going to use jQuery dialog.
  • The add functionality will add a similar div with with the added content next to the current div. 
Now to use contextMenu, we need the necessary JavaScript and CSS files. In this case we can use the following references-
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.js" type="text/javascript"></script>

    <script src="http://labs.abeautifulsite.net/archived/jquery-contextMenu/demo/jquery.contextMenu.js"
        type="text/javascript"></script>

    <link href="http://labs.abeautifulsite.net/archived/jquery-contextMenu/demo/jquery.contextMenu.css"
        rel="stylesheet" type="text/css" />
Next we need to create UI for context menu. And it goes like below-
    <ul id="myMenu" class="contextMenu">
        <li class="copy"><a href="#Add">Add</a></li>
        <li class="edit"><a href="#Edit">Edit</a></li>
        <li class="delete"><a href="#Delete">Delete</a></li>
        <li class="quit separator"><a href="#Cancel">Cancel</a></li>
    </ul>
Now we can enable context menu by calling the following JavaScript-
        $(document).ready(function() {
            EnableContext();
        });
        function EnableContext() {
            $("div.enableCtx").contextMenu({
                menu: 'myMenu'
            },
            function(action, el, pos) {
            });
        }
If we notice we can check that the contextMenu takes a function as a second parameter with three attributes called action, el and pos. action stands for what option we have selected from the menu potion. In this case these can be Add, Edit, Delete and Cancel. The value of this is taken from the href value except #. el stands for target element, in our case its one of the div we are right clicking. And the last parameter pos is the coordinate position of the mouse click.

Now what we can do is write a function for each of the operation with exactly the same name as in action and use eval for evaluating the function call. The code goes here-
     <script type="text/javascript">
        $(document).ready(function() {
            EnableContext();
        });
        function EnableContext() {
            $("div.enableCtx").contextMenu({
                menu: 'myMenu'
            },
            function(action, el, pos) {
                eval(action + "(el)");
            });
        }

        function Add(el) {
            //add implementation
        }
        function Edit(el) {
            //edit implementation
        }
        function Delete(el) {
            //delete implementation
        }
        function Cancel(el) {
            //cancel implementation
        }
     </script>
Here is the beauty of eval function. Suppose we have selected Add option from the context menu then it will evaluate the statement Add(el). That means its going to call the add function. Similarly for others.

Next comes the actual implementation of the functions. As we have decided to use jQuery dialog for add and edit purpose. So, we need to setup dialog. Here we are going to take dialog as a div with a text box for editing the content of the selected div. The dialog references and HTML goes here-
     <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/jquery-ui.js" type="text/javascript"></script>
     <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
    <div style="display:none" id="dialog" title="Add content">
        Enter Text: <nput type="text" id="text" />
   </div>
Add function-
   
        function Add(el) {
            $("#text").val("");
            $("#dialog").dialog({
                model: true,
                buttons: {
                    add: function() {
                        el.after($("<div>").addClass("enableCtx").html($("#text").val()));
                        EnableContext();
                        $(this).dialog("close");
                    }
                }
            });
        }
What we are doing in the add function is setting the textbox inside the dialog to empty, opening the dialog with a button called add. And in the add button click handler we are creating a dynamic div with class enableCtx and adding the content of the div as the textbox value. We are then adding the dynamic div next to the current div(el). We are recalling the EnableContext() function to add the same context behavior to the added div. And finally closing the dialog.

Edit, delete and cancel functions-
 
        function Edit(el) {
            $("#text").val(el.html());
            $("#dialog").dialog({
                model: true,
                buttons: {
                    Edit: function() {
                        el.html($("#text").val());
                        $(this).dialog("close");
                    }
                }
            });
        }
        function Delete(el) {
            el.remove();
        }
        function Cancel(el) {
        }
Edit function is simple, we are first copying the div HTML to textbox inside dialog, replacing the current div(el) HTML with textbox changed value. and closing the dialog.

Delete function is simply removing the current div. And in case of cancel function we need to to implement anything as it will automatically close the context menu.

Source code is here.