Expand table rows with jQuery - jExpand plugin

jExpand is ultra lightweight jQuery plugin that will make your tables expandable. Typical for line of business applications, this feature can help you organize tables better. This way, tables can hold more information such as images, lists, diagrams and other elements.

Download jExpand with samples View demo

How does it work?

To have such expandable table we have to reserve two rows for each entity, one that will be master row and another that will show details. Details rows are toggled by clicking on master row.

Master row can contain as many columns as it is needed. The important thing is that details row have to span (using colspan attribute) all the columns that master row contains (if you want to have full details row area, of course). In the example below, table contains 4 columns and details rows spans exactly 4 columns.

<table id="report">
    <tr>
        <th>Lorem ipsum</th>
        <th>Lorem ipsum</th>
        <th>Lorem ipsum</th>
        <th>Lorem ipsum</th>
    </tr>
    <tr>
        <td>Lorem ipsum</td>
        <td>Lorem ipsum</td>
        <td>Lorem ipsum</td>
        <td>Lorem ipsum</td>
    </tr>
    <tr>
        <td colspan="4">
            <!-- Details here -->  
        </td>
    </tr>
    <tr>
        <td>Lorem ipsum</td>
        <td>Lorem ipsum</td>
        <td>Lorem ipsum</td>
        <td>Lorem ipsum</td>
    </tr>
    <tr>
        <td colspan="4">
            <!-- Details here -->  
        </td>
    </tr>
</table>

The code that turns this into expandable table is quite simple. First, it will add .master class to each odd row in the table and hide all rows that don't have .master class (those are details rows). It will then "unhide" table header that is first in the array of table rows. The second step is to add click handler to all rows that have .master class. By clicking on any master row, jQuery will toggle the visibility of related details row. Couldn't be simpler, I think.

$("#report tr:odd").addClass("master");
$("#report tr:not(.master)").hide();
$("#report tr:first-child").show();
$("#report tr.master").click(function(){
    $(this).next("tr").toggle();
    $(this).find(".arrow").toggleClass("up");
}); 

There is one more line of code here which adds "odd" CSS class to each odd table row. The code is fully functional even without this line, but I added it to make table styling simpler. This way it is easy to style each master row.

At first I tried with $("td[colspan]") and $("td:not([colspan])") selectors to do the same, but that didn't work in IE. The code was simpler and additional classes wasn't needed. Shame. I tested this version in FF, IE (all versions), Chrome, Safari and Opera and it works fine in all browsers. Except IE8 - details rows aren't shown. It seems as if IE8 have some problems with .toggle() function. To make it work in this browser as well you'll have to check for visibility and then use show() or hide() functions. Shame, again.

At the end, to use plugin that is located in source files just do this:

$(#sometable").jExpand(); 

How do you deal with cases like this? Do you use tables or you have some other approach?  

More articles in Blog archive or elsewhere
Advertisement

66 Comment(s)

Ivan

Ivan 20 Jul 2009 #

Very useful, especially I like small footprint, HTML code is clean and jQuery is very lightweight...

Thx, Janko and keep up with the good work!

Marco

Marco 20 Jul 2009 #

Simple, yet effective - great work once again Janko! Really like to see the UI Exp. increase when people use these kinds of effects.

Thanks for sharing this beautiful and simple piece of code!

Davide Espertini

Davide Espertini 20 Jul 2009 #

Great Janko! Simple, useful and lightweight jQuery code Laughing

Thx for sharing your great knowledge!

Neil

Neil 20 Jul 2009 #

Very nice!

Josip

Josip 20 Jul 2009 #

Genius, reusable code at it's best Smile

Steven

Steven 21 Jul 2009 #

Very clean and quite simple. Will definitely add this to my arsenal.

Bill

Bill 21 Jul 2009 #

Doesn't seem to work in IE8...if you care.  But it does work in compatiblity mode.

Langel

Langel 21 Jul 2009 #

I bet this would conflict with a plugin like tablesorter.  I've been thinking about trying to do a hybrid of  that and something like this using <div>'s but it's just a thought!  Laughing

Janko

Janko 21 Jul 2009 #

Thanks everyone for the comments!

Bill: Yep, I know it doesn't work in IE8, unfortunately. I provided possible solution for this and that is to replace .toggle() with show() and hide() methods.

Langel: Yes it would probably conflict with tablesorter. Perhaps tablesorter can be modified to sort odd/even rows only? I guess it won't be that tricky.

Chris

Chris 21 Jul 2009 #

This works great, but is there a way to dynamically populate the table?  I've tried using php/mysql, but every time I add the Table ID the page loads blank.

Thanks

Janko

Janko 21 Jul 2009 #

Chris: You have to find a way to populate table with some data, the plugin only styles it and adds necessary effects. Basically, try to populate the table before you apply this plugin, this way you can make sure everything is loaded properly.

Indie

Indie 22 Jul 2009 #

Simple, yet effective - great work once again Janko!

SergioSuperstar

SergioSuperstar 23 Jul 2009 #

IE8 behaves so bad that I sometimes think, that group of amateurs built it :-(
However your example is once again very interesting UI solution. Keep up the good work Wink

Janko

Janko 23 Jul 2009 #

SergioSuperstar: Yes, I cant believe that after so many years of criticism they didn't create stable and standards compliant browser Frown

AV4TAr

AV4TAr 23 Jul 2009 #

Cool, i've modified it to use ajax to load the content.

dise&#241;o comunicacion visual

diseño comunicacion visual 23 Jul 2009 #

Muy buen blog de diseño! great blog! thanks from Argentina.

Jedwab

Jedwab 24 Jul 2009 #

well it wasn't as hard as I'd expect it to be. Pretty straightforward tutorial, thanks a lot.

Jono

Jono 27 Jul 2009 #

Could someone please post code that works with IE 8 and other browsers, i can make IE8 show the detail row when clicked but i can't or dont know how to work out the code to hide it again.

Thanks

Bony

Bony 28 Jul 2009 #

Clear, straightforward and useful! Exactly what I need in my project 8) Thanks!

Cormac

Cormac 28 Jul 2009 #

Nice bit of code. I'm no js expert but i've been trying to add a class to the expanded row, and remove it when it's clicked again. So far I have the class being added on the click, but i'm not sure how to remove it again.

(functionMoney{
    $.fn.jExpand = function(){
        var element = this;

        $(element).find("tr:odd").addClass("odd");
        $(element).find("tr:not(.odd)").hide();
        $(element).find("tr:first-child").show();
        

        $(element).find("tr.odd").click(function() {
            $(this).next("tr").toggle();
            $(this).addClass("highlight");
            
        });
        
    }    
})(jQuery);


I'd also second Jono's request for IE8 compatible code.

Thanks a million, any tips appreciated!

Janko

Janko 11 Aug 2009 #

Jono: to make it work in IE8, use show() and hide() methods instead of using toggle()

Cormac: you can heck if row has class "highlight" and then show/hide based on that value

Steve Daly

Steve Daly 12 Aug 2009 #

Thanks for the code! Exactly what I needed!  I tried the JQuery UI accordian, but it was just "too much" for what I needed.

A quick question from a JQuery novice.  How can I open a particular row based on a query string variable?  I have a landing page with several options in collapsible rows.  When a user clicks a link from another page to this landing page I would like the appropriate row to open up.

Andy B

Andy B 25 Aug 2009 #

Hi great bit of code this thanks, but could you explain to the layman copy and paste coder how to make it IE8 compliant, is it as simple as this? And would it still work in IE7, 6 etc.

<script type="text/javascript">  
        $(document).ready(function(){
            $("#report tr:odd").addClass("odd");
            $("#report tr:not(.odd)").hide();
            $("#report tr:first-child").show();
            
            $("#report tr.odd").click(function(){
                $(this).next("tr").show();
                $(this).find(".arrow").toggleClass("up");
            });
            //$("#report").jExpand();
        });
    </script>  

Joonas Manninen

Joonas Manninen 04 Sep 2009 #

Hi,

Can you please paste the code for ie8, I have excatly the same problem as someone aboe, that in IE8 show() works, but hide() doesnt.

Thanks!

jock

jock 09 Sep 2009 #

Not sure about toggle() function not working in ie8

I've found other examples which use toggle and work fine in ie8. (andylangton.co.uk/.../)

I wish I could tell you what was wrong with yours but I don't know jQuery.

If you can find a fix or post the show/hide method that would be great.

Regards

Zidane

Zidane 10 Sep 2009 #

This works for me

$(document).ready(function(){
  $("#transactioncategories tr:odd").addClass("odd");
  $("#transactioncategories tr:not(.odd)").hide();
  $("#transactioncategories tr:first-child").show();
  
  $("#transactioncategories tr.odd").click(function(){
    if($(this).next("tr").is(":visible"))
    {
      $(this).next("tr").hide();
    }
    else $(this).next("tr").show();
    $(this).find(".arrow").toggleClass("up");
  });

jock

jock 11 Sep 2009 #

mmm, doesn't work at all now.

Can you post a link to the page where it's working?

The hidden info just shows permanently now.

jock

jock 11 Sep 2009 #

I think this is what you were trying to achieve but it still fails in ie8. I wish I knew jQuery!


        $(document).ready(function(){
            $("#report tr:odd").addClass("odd");
            $("#report tr:not(.odd)").hide();
            $("#report tr:first-child").show();
            
            $("#report tr.odd").click(function(){
        if($(this).next("tr").is(":visible"))
        {
        $(this).next("tr").hide();
        }
        else $(this).next("tr").show();
        $(this).find(".arrow").toggleClass("up");
            });
            //$("#report").jExpand();
        });

jock

jock 11 Sep 2009 #

UPDATE:

I think the original code using toggle is good but ie8 is having a problem with the latest version of jQuery 1.3.2. I tried this using a slightly older version of jQuery library 1.2.3 and it works fine!

One more question though: How can I restrict the onclick to just the arrow? At the moment you can click anywhere in the row and the hidden row appears. That's fine until you want to put links into other cells on that row and then the link works but the onclick activates as well (which you don't want!)

Any ideas?

Janko

Janko 11 Sep 2009 #

Jock: yes it's the problem with IE8. I behaves really strange - at some point it worked with show() and hide() Frown

For making arrow clickable, use something like this: $("#report tr.master img.arrow")

mikan

mikan 15 Sep 2009 #

Thank you for the great code Smile
me too, it didn't move with IE8. so I also changed the version from 1.3.2 to 1.2.3 and then moved with IE8.

I hope I can understand...

Thanks a lot!!

Steve

Steve 15 Sep 2009 #

JQuery 1.2.6 works on IE8 for this script as well... not checked against anything else. IE 8, guaranteed to spoil your day... no change there, then!

sourabh

sourabh 05 Oct 2009 #

not working in ie8

MkePQ

MkePQ 20 Oct 2009 #

I have developed a similar widget and IE 8 was killing me.
I have found out that IE works if I change the document declaration to:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

or change toggle () with show and hide as was suggested above.

Paul

Paul 29 Oct 2009 #

Great piece of code! Thank you for sharing.

Is there anyway I can add a button that closes all the expanded rows?

Janko

Janko 29 Oct 2009 #

Steve, MkePQ: thanks for the tips!

Paul: You can try with $("tr:odd).next().hide(); Maybe not the best solution but it should work.

Paul

Paul 30 Oct 2009 #

Hi again Janko. Thanks for the tip. Unfortunately I couldn´t get it to work. Where should I place that line of code?

Janko

Janko 30 Oct 2009 #

Paul: I guess the easiest way is to add some HTML anchor and bind onclick event to it. Then, when you click on that link it can expand/collapse rows

aab

aab 04 Nov 2009 #

Hi Janko
  Your code is so enjoyable and usefull, it  was a question in my mind how can do it,but I don't know how can I use it in my solution,may I ask you send me an email ? (complete code ( souce code ) as one simple asp solution )  or  a link  for download complete source code ?. I will be thankful .
Best regards

aab

aab 04 Nov 2009 #

Hi Janko and Hello to everyone, I have another question and I will be so thankful if somebody can help me. How can I  set  the table row ( move ) as the first row when cilck on it ( using jquery )?
best regards.

Janko

Janko 04 Nov 2009 #

aab: Thanks! Unfortunately I don't have any backend code. I don't provide tutorials and articles about backend development. It's about UI only Smile It is up to you to implement your own logic for rendering a such table.

aab

aab 04 Nov 2009 #

Hi Janko,thank you about your reply,may I ask you lead me how can I set a table row as first table row ( show it  at  the first index) using jquery ? , I will be so thankful
best regards.

Olivier

Olivier 18 Nov 2009 #

Hello,
good code but someone would be able to make it works with tablesorter jquery plugin ?
Thank you!

Chandler

Chandler 19 Nov 2009 #

Thanks, Janko !!!
I've found the solution for jquery 1.3.2 foe IE 8
You just need to edit the jquery script:
replace this

Sizzle.selectors.filters.hidden = function(elem){
    return elem.offsetWidth === 0 || elem.offsetHeight === 0;
};

Sizzle.selectors.filters.visible = function(elem){
    return elem.offsetWidth > 0 || elem.offsetHeight > 0;
};

by this

Sizzle.selectors.filters.hidden = function(elem){
    var width = elem.offsetWidth, height = elem.offsetHeight,
         force = /^tr$/i.test( elem.tagName );
    return ( width === 0 && height === 0 && !force ) ?
        true :
            ( width !== 0 && height !== 0 && !force ) ?
                false :
                    !!( jQuery.curCSS(elem, "display") === "none" );
};

Sizzle.selectors.filters.visible = function(elem){
    return !Sizzle.selectors.filters.hidden(elem);
};


Chandler

Chandler 19 Nov 2009 #

Thanks, Janko!!!)))
I've found the solution for jquery 1.3.2 for IE 8
You just need to edit jquery source:

replace this

Sizzle.selectors.filters.hidden = function(elem){
    return elem.offsetWidth === 0 || elem.offsetHeight === 0;
};

Sizzle.selectors.filters.visible = function(elem){
    return elem.offsetWidth > 0 || elem.offsetHeight > 0;
};

by this

Sizzle.selectors.filters.hidden = function(elem){
    var width = elem.offsetWidth, height = elem.offsetHeight,
         force = /^tr$/i.test( elem.tagName );
    return ( width === 0 && height === 0 && !force ) ?
        true :
            ( width !== 0 && height !== 0 && !force ) ?
                false :
                    !!( jQuery.curCSS(elem, "display") === "none" );
};

Sizzle.selectors.filters.visible = function(elem){
    return !Sizzle.selectors.filters.hidden(elem);
};

Lehlogonlo

Lehlogonlo 19 Nov 2009 #

great stuff, it works fine in Ie7 , IE8 and firefox

CodeReaper

CodeReaper 27 Nov 2009 #

Chandler's fix may have other unwanted effects on.... I use this instead :

(functionMoney{
    $.fn.jExpand = function(){
    var element = this;
    
        $(element).find("tr:odd").addClass("odd");
        $(element).find("tr:not(.odd)").hide();
        $(element).find("tr:first-child").show();
    
        $(element).find("tr.odd").click(function() {
            var tr = $(this).next("tr");
      
      if(tr.css("display") == "none")
        tr.css("display", "table-row");
      else
        tr.css("display", "none");
      
      $(this).find(".arrow").toggleClass("up");
        });
        
    }    
})(jQuery);

Sanjeev

Sanjeev 01 Dec 2009 #

Great... this is what i was searching.. Can i add the class or id for the <tr> and display/hide them.
in my case i may not want odd rows to be hide/show. i may want depending on conditions.

Matt Aumann

Matt Aumann 06 Dec 2009 #

I got this code to work is ie8 and Firefox, Chrome
Checks the class of the Arrow, rather than if tr is visible.

$("#report tr.odd").click(function(){
     if($(this).find(".arrow").hasClass("up"))
     {
         $(this).next("tr").hide();
     }
    else $(this).next("tr").show();
    $(this).find(".arrow").toggleClass("up");
});

John

John 06 Dec 2009 #

Did anyone figure out how to combine tablesorter with this cool plugin? Is that logically impossible due to the way the two plugins were coded?

Geert

Geert 08 Dec 2009 #

Cool code!

When I use a nested table in my “details row” its rows toggle too. How do I prevent this in my nested table?

WebGrid

WebGrid 11 Dec 2009 #

Hi,

Thanks! It gave me an idea for my datagrid Smile

Norbert

Norbert 18 Dec 2009 #

Great,  pls. check with IE8.  Thanks in advance!

Norbert

Nick

Nick 25 Dec 2009 #


(functionMoney{
$.fn.jExpand = function(){
var element = this;

$(element).find("tr:odd").addClass("odd");
$(element).find("tr:not(.odd)").hide();
$(element).find("tr:first-child").show();

$(element).find("tr.odd").click(function() {
var tr = $(this).next("tr");

if(tr.css("display") == "none")
tr.css("display", "table-row");
else
tr.css("display", "none");

$(this).find(".arrow").toggleClass("up");
});

}
})(jQuery);



CodeReaper's alternate code for IE8 worked great for me, but it didn't work in IE 6 or IE 7.  I found out that it's because IE 6 and IE 7 don't recognize the "table-row" value as a valid css attribute for "display".

To fix, I changed the line:

tr.css("display", "table-row");

to:

tr.css("display", "t");

and it worked great in IE 6, IE 7, and IE 8 (in addition to FF 3, Chrome 4, etc)

Nick

Nick 25 Dec 2009 #

The code change should read

"tr.css("display", "");"  

instead of

"tr.css("display", "t");"  

Typo on my part.

TNk

TNk 28 Dec 2009 #

@Geert
I wish to know that too, i tried with #id > tr:odd and ("#id").children("tr:odd")  . ..i couln't make it to work Frown  . Could someone with a better knowledge of JQ help us please! Smile

..and to make it work with tablesorter too would definitely be a plus Laughing

p.s: thx for the articles as always very useful! ^^

Gabriel

Gabriel 07 Jan 2010 #

no work in ie8

Hidayat Sagita

Hidayat Sagita 07 Jan 2010 #

Hi Janko,
Great work as always Smile
I added slideToggle for the toggle but not pretty smooth enough. Here's the code :

$("#report tr.odd").click(function(){
                
                $(this).next("tr").slideToggle('slow', function() {
                
                  if($(this).css('display') == 'block')
                    $(this).css('display', 'table-row');
                });
                
                $(this).find(".arrow").toggleClass("up");
            });

alex

alex 09 Jan 2010 #

Its`s a cool plugin. Thank you.

Together with tableSorter woulkt be nice!

alex

alex 10 Jan 2010 #

is it possible to open the next tr by clicking only the arrow div?

I added checkboxes to the tr`s. but if i click the checkbox the next tr opens.

Thank you

Janko

Janko 10 Jan 2010 #

Thanks everyone for the comments and solutions for IE8. I've tested it in IE Tester and it worked in IE6, 7 & 8, so I wasn't aware of any issues. Damn IE, what can I say.

To be able to make it work with tablesorter you will have to change that plugn. It includes each row, so you might want to change it to sort only odd or even rows.

Porcopus

Porcopus 15 Jan 2010 #

It seems that i cant get it to work with ajax-loaded table. It works with static table, but when i try to assign it to a table, which has tr's loaded by ajax call, it will not work. It just shows those additional info rows. No interaction whatsoever. What am i doing wrong?

My rows are being loaded like this:

                success: function(data) {
      $('#loading').hide();
      $('#tblx> tbody:last').append(data);
      
    }


And after that i call this expand-func.

        $("#tblxtr:odd").addClass("master");
  $("#tblxtr:not(.master)").h.... etc.

Vladimir

Vladimir 16 Jan 2010 #

Shalom everybody!
After I spent 2 week on improving this code, I want to share with you how to make slideToggle.
DEMO is here: http://ayalon.ru/cms/primer/
This string should be added before HEAD tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "www.w3.org/.../xhtml1-strict.dtd">;
<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">

In HEAD shoul be these strings:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="jquery.js"></script>
<style type="text/css">
        body { font-family:Arial, Helvetica, Sans-Serif; font-size:0.8em;}
        #report { border-collapse:collapse;}
        #report h4 { margin:0px; padding:0px;}
        #report img { float:right;}
        #report ul { margin:10px 0 10px 40px; padding:0px;}
        #report th { background:#7CB8E2 url(header_bkg.png) repeat-x scroll center left; color:#fff; padding:7px 15px; text-align:left;}
        #report td { background:#C7DDEE none repeat-x scroll center left; color:#000; padding:0px 1px; }
        #report tr.odd td { background:#fff url(row_bkg.png) repeat-x scroll center left; cursor:pointer; }
        #report div.arrow { background:transparent url(arrows.png) no-repeat scroll 0px -16px; width:16px; height:16px; display:block;}
        #report div.up { background-position:0px 0px;}
    #report .message_body { display: none;}
#r { display: none;}
    </style>

Javascript I added after BODY tag:

<div id="txtHint"><b>Person info will be listed here.</b>
  
  <script type="text/javascript">           
            $("#report tr:odd").addClass("odd");
            $("#report tr:not(.odd)").hide();
            $("#report tr:first-child").show();
            
           $(document).ready(function(){
      $(".message_head").live("click",function(){
    $("." + this.id).slideToggle("slow");
  
      $(this).toggleClass("active");

    $(this).find(".arrow").toggleClass("up");

  });
            //$("#report").jExpand();
        });
    </script>

And the main code:
$con = mysql_connect('localhost', 'user', pass');
if (!$con)
  {
  die('Could not connect: ' . mysql_error());
  }
mysql_select_db("dbname", $con);
$sql="SELECT * FROM azaa ORDER BY id DESC limit 30";
$result = mysql_query($sql);

echo "<table id='report'>";
echo "<tr>
            <th>Country</th>
            <th>Population</th>
            <th>Area</th>
            <th>Official languages</th>
            <th>Another</th>
       <th></th>
        </tr>";
while($row=mysql_fetch_array($result))
{
echo "<tr class='message_head'  id='". $row['id'] ."'>";
echo "<td style='background:#fff url(row_bkg.png) repeat-x scroll center left; cursor:pointer;'>". $row['id'] ."</td>";
echo "<td style='background:#fff url(row_bkg.png) repeat-x scroll center left; cursor:pointer;'>". $row['name7'] ."</td>";
echo "<td style='background:#fff url(row_bkg.png) repeat-x scroll center left; cursor:pointer;'>". $row['name3'] ."</td>";
echo "<td style='background:#fff url(row_bkg.png) repeat-x scroll center left; cursor:pointer;'>". $row['name17'] ."</td>";
echo "<td style='background:#fff url(row_bkg.png) repeat-x scroll center left; cursor:pointer;'>". $row['name1'] ."</td>";
echo "<td style='background:#fff url(row_bkg.png) repeat-x scroll center left; cursor:pointer;'><div class='arrow'></div></td>";
echo "</tr>";

  echo "<tr>                                                                                        
      <td colspan='6'><div class='". $row['id'] ."'  id='r'>";
   echo "<div>". $row['id'] ."";    
     echo "". $row['teudatzeut'] . "";
                echo "". $row['miparishui'] . "";
                echo "". $row['name18'] . "";
    echo "". $row['teudatzeut'] . "";
                echo "". $row['miparishui'] . "";                  
  echo "</div>";    
  echo "</div></td>
  </tr>";

}
echo "</table>";

mysql_close($con);
unset($_SESSION['q']);
unset($_SESSION['a']);

?>

as you can see on my DEMO I added some AJAX code to do it sortable. On any question I'll give an explaination.

Vladimir

Vladimir 16 Jan 2010 #

Updated to jquery-1.4.min.jsWorks perfect in IE6 / 7 / 8 , FireFox, Google Chrome and Opera.

Craig Cooke

Craig Cooke 05 Feb 2010 #

Heres an example a small change I made to get it working in IE8 using show(), hide()

$(document).ready(function(){
            $("#report tr:odd").addClass("odd");
            $("#report tr:not(.odd)").hide();
            $("#report tr:first-child").show();
            
            $("#report tr.odd").click(function(){
        if(!$(this).next("tr").hasClass('shown'))
        {
                  $(this).next("tr").show()      
                  $(this).find(".arrow").toggleClass("up");
          $(this).next("tr").addClass("shown");
              }
        else
        {
          $(this).next("tr").hide()      
                  $(this).find(".arrow").toggleClass("up");
          $(this).next("tr").removeClass("shown");
        }
      });
            //$("#report").jExpand();
        });

Hope that helps!

Starting to really enjoy jQuery, saves so much time!

Jessica

Jessica 16 Feb 2010 #

Matt Aumann's worked for me in ie 8 THANK YOU SO MUCH!

Comments are closed
via Ad Packs
9292