Harshdeep
Harshdeep

Reputation: 5824

Jquery event getting triggered as a side-effect. How to stop that

I have a specific requirement of having a toggling table. By toggling I mean a table which will expand and collapse on event click of a hyperlink.

snippet of how I have made table is:

     <table class=".table" border="1">
     <tr id="1">
        <td><a href="#" class="action" id="a-1">+</a></td>
        <td>Superman</td>
     </tr>
     <tr id="version" class="child 1">
        <td></td>
        <td>Weight</td>
     </tr>
     <tr id="type" class="child 1">
        <td></td>
        <td>Height</td>
     </tr>
     <tr id="pl-id" class="child 1">
        <td><a href="#" class="action" id="a-1-101">+</a></td>
        <td>Planet</td>
     </tr>
     <tr id="KP" class="child 1-101">
        <td></td>
        <td>KP</td>
     </tr>
     <tr id="MN" class="child 1-101">
        <td></td>
        <td>MN</td>
     </tr>
     ..
     ..

Table can be imagined to have a structure of sort

1)  - Superman
        Weight
        Height
        - Planet
            KP
            MN


2)  + Superman


3)   - Superman
          - Planet
              KP
              MN

On clicking - against Superman in 1st state should take to 2nd state and not to 3rd state.

JQuery I have written to do this:

$().ready(function() {
            $('.child').hide();
            $('.action').click(function(){

                var id = $(this).attr('id');
                var idarray=id.split("-");
                var len = idarray.length;

                if(len==2)
                    {
                        id = id.substring(2);

                        if($(this).parent().parent().next().attr('style')=="display: none; "){
                            $('tr[class^=child '+id+'-1]').hide();
                            $('tr[class=child '+id+']').show();
                        }
                        if($(this).parent().parent().next().attr('style')=="display: table-row; "){
                            $('tr[class^=child '+id+'-1]').hide();
                            $('tr[class=child '+id+']').hide();
                        }

                    }
                else if(len==3)
                    {
                        //HAVEN'T REACHED TILL RESOLVING FOR 3 :(
                        /*id = id.substring(2);
                        alert(id);
                        $("."+id).toggle();
                        $('tr[class^=child '+id+']').hide();
                        $('tr[class=child '+id+']').show();*/

                    }
            });
        });

Using this JQuery on clicking the hyperlink with id=a-1 display:none block is executed but it triggers display:table-row block on its own due to show/hide functions inside it. Re-clicking is not happening then why does click event is simulated again. I don't want display:table-row block getting executed. Currently table is at 2nd state when html page loads and even after clicking + against Superman it remains in the same state because both if and else condition are getting evaluated which brings it back to original state.

How can this requirement be achieved in an easy way. I am new to JQuery and have tried so many things to do that I am totally confused. Can someone please tell me a way in which this can be done. Please give a working or close to working solution. Please don't give a link to documentation.

Thanks.

Upvotes: 2

Views: 231

Answers (2)

Harshdeep
Harshdeep

Reputation: 5824

Modified my script as

    $('.action').click(function(){

            var id = $(this).attr('id');    
            var idarray=id.split("-");
            var len = idarray.length;
            id = id.substring(2);

    if($(this).parent().parent().next().attr('style')=="display: none; "){
            $('tr[class=child '+id+']').show();
            $('tr[class^=child '+id+'-]').show();
            return false;
    }
    if($(this).parent().parent().next().attr('style')=="display: table-row; "){
            $('tr[class=child '+id+']').hide();
            $('tr[class^=child '+id+'-]').hide();
            return false;
    }

Now this works fine. The line which solved my problem was return false;. It stopped the side effect JQuery events.

After inputs from John Green gave more thought into it and made it work and less clumsy as well.

Upvotes: 0

John Green
John Green

Reputation: 13435

The issue is in your referencing. Note that JQuery uses the Sizzle selector, which basically gives you CSS-style referencing of elements.

This kind of referencing won't work:

$('tr[class=child '+id+']').show();

You'd need to use the attribute list selector:

$('tr[class~=child][class~='+id+']').show();

Or, even better since you're dealing with CSS classes (don't use attribute selectors for ID or class unless you need fuzzy matches):

$('tr.child.'+id).show();

All of that being said... I highly recommend you look at your implementation. Instead of utilizing tables with semi-hidden rows, use container objects. It will dramatically simplify your code and make updates easier. As you have it... well, I pity the next guy who has to step in and try to maintain it.

Upvotes: 2

Related Questions