3

I've this default responsive Bootstrap table:

<div class="table-responsive">
    <table class="table table-bordered">
      <thead>
        <tr>
          <th>#</th>
          <th>First Name</th>
          <th>Last Name</th>
          <th>Username</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">1</th>
          <td>Mark</td>
          <td>Otto</td>
          <td>@mdo</td>
        </tr>
        <tr>
          <th scope="row">2</th>
          <td>Jacob</td>
          <td>Thornton</td>
          <td>@fat</td>
        </tr>
        <tr>
          <th scope="row">3</th>
          <td>Larry</td>
          <td>the Bird</td>
          <td>@twitter</td>
        </tr>
      </tbody>
    </table>
</div>

How can I add a div or container to the right of each row showing some action buttons, like delete row, updating icon etc.? They should be hidden by default. When I mouse over a row, it should be displayed right to the row. Not inside the table, but the top and bottom should be aligned with the position and height of the given table row.

enter image description here

How can I solve this? If it cannot be done using CSS alone, a solution using jQuery/JavaScript or like could be okay.

dhrm
  • 14,335
  • 34
  • 117
  • 183
  • When you say "*not inside the table*", does that mean that it must visually *look* like it's not part of the table, or that it *must not* be a part of the table's DOM, so the HTML must be an entirely separate element? Because nesting is far easier to work with (both for presentation and for JavaScript interaction, since it's nested within the row you want the control(s) to affect). – David Thomas Mar 10 '15 at 21:08
  • Just visually, don't care about the DOM for that matter. :) – dhrm Mar 10 '15 at 21:11

8 Answers8

11

Try the following code

$('tbody tr').hover(function(){
 $(this).find('td:last').show();
},function(){
  $(this).find('td:last').hide();
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
  .table-bordered-custom{
    border:0px;
    border-top:initial;
  }
  
  .table-bordered-custom thead th {
    border-top:1px solid #ddd !important;
  }
  .table-bordered-custom tbody td:last-child {
    border:0 !important;
    display:none;
  }
  </style>
<table style="margin:10px" class="table table-bordered table-bordered-custom">
  
      <thead>
        <tr>
          <th width="10%">#</th>
          <th width="25%">First Name</th>
          <th width="25%">Last Name</th>
          <th width="25%">Username</th>
          <th style="border:0 !important" ></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">1</th>
          <td>Mark</td>
          <td>Otto</td>
          <td>@mdo</td>
          <td ><input type="button" value="X"> <input type="button" value="Edit"></td>
          
        </tr>
        <tr>
          <th scope="row">2</th>
          <td>Jacob</td>
          <td>Thornton</td>
          <td>@fat</td>
          <td ><input type="button" value="X"> <input type="button" value="Edit"></td>
        </tr>
        <tr>
          <th scope="row">3</th>
          <td>Larry</td>
          <td>the Bird</td>
          <td>@twitter</td>
          <td ><input type="button" value="X"> <input type="button" value="Edit"></td>
        </tr>
      </tbody>
    </table>
Puneet
  • 2,051
  • 9
  • 17
  • It should not be placed inside the table. See my screenshot. – dhrm Mar 09 '15 at 13:25
  • It will be placed in the Table. We can hide the border for these specific cells and it will look like it is outside the table. – Puneet Mar 09 '15 at 13:29
  • Please try to run your code snippet. The cell-border is hidden, but the buttons are inside the overall table border. – dhrm Mar 10 '15 at 06:46
  • @DennisMadsen - Please try the snippet now. – Puneet Mar 10 '15 at 09:39
  • See my JSFiddle: http://jsfiddle.net/dennismadsen/zg0yk3rj/1/. First of all, I need the button to appear, when I mouse over the row. I need my table to have full width, in this case 8 grid columns. And the buttons should then appear "outside" the table when mousing over the row. Right now, they are a part of the table. – dhrm Mar 10 '15 at 14:20
  • Giving only code is bot enough, give textual explanation too! – peterh Mar 11 '15 at 01:56
  • I've updated the question with further information. Is it more clear now? – dhrm Mar 11 '15 at 07:31
  • @DennisMadsen I have updated the Snippet. Now the buttons will be shown only on the hover of row. Please have a look. And If you need explanation on the code, let me know, I add the explanation too. – Puneet Mar 11 '15 at 09:20
  • I've updated the JSFiddle: http://jsfiddle.net/dennismadsen/mbaeczwb/. The table is not having full width inside the container, when the buttons are hidden. And a outside border is visible. What am I doing wrong? – dhrm Mar 16 '15 at 12:23
7

you may use hover and absolute to allow also tab crawling from a link to another :

td,th {
  border:1px solid;
}
table {
  margin:1em;
}
tr> :last-child {
  width:1em;
  vertical-align:top;
  border:none;
}
:last-child a { 
  text-align:center;  
  position:absolute;
  left:-9999px;
  display:inline-block;
  width:1em;
  color:white;
  text-decoration:none;  
  background:red;
}
tr:hover td:last-child a,td a:focus {
  left:auto;
}
<div class="table-responsive">
  <table class="table table-bordered">
    <thead>
      <tr>
        <th>#</th>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Username</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>Mark</td>
        <td>Otto</td>
        <td>@mdo</td>
        <td><a href>X</a></td>
      </tr>
      <tr>
        <th scope="row">2</th>
        <td>Jacob</td>
        <td>Thornton</td>
        <td>@fat</td>
        <td><a href>X</a></td>
      </tr>
      <tr>
        <th scope="row">3</th>
        <td>Larry</td>
        <td>the Bird</td>
        <td>@twitter</td>
        <td><a href>X</a></td>
      </tr>
    </tbody>
  </table>
</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • 1
    Your problem is going to be clicking that link (without adequate cursor momentum to get there)... – jcuenod Mar 11 '15 at 21:38
  • @jcuenod , good point, it is fixed, using basic drop down menu method to allow tabbing links to links – G-Cyrillus Mar 12 '15 at 13:16
  • I'm not convinced - it has that horrible flashy effect. – jcuenod Mar 12 '15 at 14:07
  • @jcuenod no reason to be any flashing effect here. i don't with any of the 6 different browsers i use. it is **free** and **free** to **use or not**. – G-Cyrillus Mar 12 '15 at 15:03
  • Your fix enables me to click the button but as I hover over the gap there is a flicker. Obviously your code is free to use or not use, I'm offering my opinion so you can continue to improve your solution (which at the beginning, I thought had a major flaw - now there's just something aesthetic that I don't like). – jcuenod Mar 12 '15 at 15:34
  • @jcuenod can you tell wich browser does this, i really do not experiment it myself and never saw that happen on drop down menu working on this very common method absolut+left – G-Cyrillus Mar 12 '15 at 18:58
  • I'm using chrome on Linux and have the flicker as I move between `td`s. If I add `border-collapse: collapse;` to the table the issue is sorted (you'll just want to space the cell contents a bit better). – jcuenod Mar 13 '15 at 07:08
  • @jcuenod Ok i see what you mean, with bootstrap style linked, it should be not a problem : http://codepen.io/anon/pen/zxmaXE – G-Cyrillus Mar 13 '15 at 08:25
  • Thanks for your answer. I've tried to implement your solution, but it introduce a scrollbar and a outside border: http://jsfiddle.net/dennismadsen/xt9boj15/1/ – dhrm Mar 16 '15 at 12:19
  • add table { margin:1em 0; } to see that your margin tells your table needs 100%width + 1em on each side – G-Cyrillus Mar 16 '15 at 12:31
  • IMHO this is the best answer simply for lack of js now. – jcuenod Mar 18 '15 at 07:35
6

Since you need complete width for the table and it should be responsive, you can keep the delete button inside last td(Username) and position it by getting few values from the hovered row using jQuery.

$('.table-bordered-custom tr')
    .on('mouseenter', function () {
        var offset = $(this).offset();
        var top = offset.top;
        var width = parseInt($('.table-responsive').css('width'),10);
        var elem = $(this).find('span.delete');
        var parent_padding_left = parseInt($('.table-responsive').parent().css('padding-left'),10)
        
        elem.css({
            "top": top + "px",
            "left": (width + parent_padding_left) - 1 + "px",
            "display": "inline"
        });
    })
    .on('mouseleave', function () {
        $('span.delete').css({
            "display": "none"
        })
    });
span.delete {
    display: none;
    position: absolute;
    background: crimson;
    color: #fff;
    cursor: pointer;
    padding: 9px 12px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
    <section id="content">
        <div class="col-xs-8 col-xs-offset-2">
            <div class="table-responsive">
                <table class="table table-bordered table-bordered-custom">
                    <thead>
                        <tr>
                            <th>#</th>
                            <th>First Name</th>
                            <th>Last Name</th>
                            <th>Username</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <th scope="row">1</th>
                            <td>Mark</td>
                            <td>Otto</td>
                            <td>@mdo<span class="delete">x</span>

                            </td>
                        </tr>
                        <tr>
                            <th scope="row">2</th>
                            <td>Jacob</td>
                            <td>Thornton</td>
                            <td>@fat<span class="delete">x</span>

                            </td>
                        </tr>
                        <tr>
                            <th scope="row">3</th>
                            <td>Larry</td>
                            <td>the Bird</td>
                            <td>@twitter<span class="delete">x</span>

                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </section>
</div>
anpsmn
  • 7,217
  • 2
  • 28
  • 44
  • 1
    Bonus point for making the button overlap with the border which makes sure the button can't vanish as you slowly move the cursor to it. – Domino Mar 17 '15 at 15:01
3

imho so many difficult answers, I would do it with an easy aproach.

In this JSFIDDLE I just add a display:none cell to each row with whatever buttom you want to show inside and with no borders so it won't look at all as inside the table, then :

  tr:hover .buttom {display:table-cell;}

may do the trick.

and no idea why I have the feeling this may not be what you want (bounty question so many javascript answers and such)... but as much as I reread the question this is it.

Excuse my poor english

Edited: Btw, if you really want the buttoms outside the "responsive" table so you have your border around, it's easily done with absolute positioned, but you shoudn't really do it. Once the table goes 100% of the window width, then those buttoms you want won't be visible for the user.

Edited: When the "buttom" cell is displayed as none, it won't take the fixed 40px width we need (or whatever future width you need once you have all buttoms inside) so I set the width to .X0 insteed becuase this element is there (but with no border, style or content) and will make all the column the same width.

Then I just overwrite some bootstrap styles that were messing with the table. (Please notice that something like:

.table-responsive {border:0; padding:2px;}
.table-bordered {border:0;} 

may affect all your project so be sure you just overwrite the styles in this table and non others. Use something like:

.container-of-the-table-with-buttoms .table-responsive {border:0; padding:2px;}

Fiddle has been updated

Alvaro Menéndez
  • 8,766
  • 3
  • 37
  • 57
  • Thanks for your answer, i've tried to implement your solution, but it is not working as expected. What am I missing? http://jsfiddle.net/dennismadsen/dpc0je5p/1/ – dhrm Mar 16 '15 at 12:17
  • The problem was that when the cell "buttom" has none display, it doesn't take the 40px width set. And when hover and the bottom becomes visible, it takes the right width movin the rest of cells to get the space needed. Anyway I've fixed it for you. Check this fiddle:http://jsfiddle.net/wg0mwo20/1/ and I will explain what I did editing the answer – Alvaro Menéndez Mar 16 '15 at 12:36
  • fixed some issues with bootstrap not playing the way we need: http://jsfiddle.net/wg0mwo20/3/ – Alvaro Menéndez Mar 16 '15 at 12:43
  • My table needs to align vertically with other elements on the website (right side of table). Therefore I need the four "always visible" columns to have full width inside the grid column. That's not the case in this example. Is there a way to solve that? – dhrm Mar 16 '15 at 12:54
  • It can be possible but your options are all the table cells moving when hover over the row (because they need to be somewhere) or positioned the buttoms cells as "absolute" but then they will be displayed (on hover) over your adjacents elements (not very nice also) – Alvaro Menéndez Mar 16 '15 at 13:09
0

I quickly wrote some code that might help you get started :

HTML

<div class="table-responsive">
    <table class="table table-bordered">
      <thead>
        <tr>
          <th>#</th>
          <th>First Name</th>
          <th>Last Name</th>
          <th>Username</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">1</th>
          <td>Mark</td>
          <td>Otto</td>
          <td>@mdo</td>
        </tr>
        <tr>
          <th scope="row">2</th>
          <td>Jacob</td>
          <td>Thornton</td>
          <td>@fat</td>
        </tr>
        <tr>
          <th scope="row">3</th>
          <td>Larry</td>
          <td>the Bird</td>
          <td>@twitter</td>
        </tr>
      </tbody>
    </table>
</div>
<div class="actionbuttons"></div>

CSS

.actionbuttons
{
    position:absolute;
    width: 150px;
    height: 30px;
    background: #f00;
    display:none;
}

jQuery code

$('tbody tr').on('mouseover',function(){
var rowPosition = $(this).position();
    var targetPosition = {
        top: rowPosition.top,
        left: rowPosition.left + $(this).width()
    }
    $('.actionbuttons').css(targetPosition);
    $('.actionbuttons').show();
});

$('tr').on('mouseout',function(){
    $('.actionbuttons').hide();
});

The fiddle

Laurent S.
  • 6,816
  • 2
  • 28
  • 40
0

try adding an onmouseover and an onmouseout attribute to each row of the table. Use each to make the button visible and invisible.

<tr onmouseover="
    *insert code to make button for this row visible*        
" onmouseout="
    *insert code to make button for this row invisible*
">
    *insert table data for this row*
</tr>
Nicholas Greene
  • 125
  • 2
  • 14
0

You can also play a little with CSS3 transform, transition and eventually FontAwesome to obtain a:

Pure CSS3 solution ( NO JavaScript, NO images )

td {
  background: white;
}
th.buttons {
  display: none;
}
td.buttons {
  border: none !important;
  padding: 0px !important;
  z-index: -1;
  transform: translateX(-100%);
  transition: transform .5s ease 0s, z-index .1s ease 0s;
}
tr:hover td.buttons {
  transform: translateX(0%);
  z-index: 1;
  transition: transform .5s ease 0s, z-index .01s ease .5s;
}
.buttons ul {
  text-align: left;
  margin: 0;
  padding: 0;
}
.buttons ul li {
  display: inline-block;
  min-height: 100%;
  text-align: center;
}
.buttons a {
  border-radius: 2px;
  color: red;
  display: block;
  font-size: 16px;
  line-height: 100%;
  min-width: 5em;
  text-decoration: none !important;
  transition: background 0.3s ease 0s;
}
.buttons i {
  display: block;
  font-size: 1.5em;
}
.buttons span {
  font-family: sans-serif;
  font-size: 0.625em;
  text-transform: uppercase;
}
li:hover a {
  background: red;
  color: white;
  z-index: 1;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="table-responsive">
  <table class="table table-bordered">
    <thead>
      <tr>
        <th>#</th>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Username</th>
        <th class="buttons"></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>Mark</td>
        <td>Otto</td>
        <td>@mdo</td>
        <td class="buttons">
          <ul>
            <li><a href="javascript:alert('update row...');"><i class="fa fa-pencil-square-o"></i><span>update</span></a>
            </li><!--
            --><li><a href="javascript:alert('delete row...');"><i class="fa fa-times"></i><span>delete</span></a>
            </li>
          </ul>
        </td>
      </tr>
      <tr>
        <th scope="row">2</th>
        <td>Jacob</td>
        <td>Thornton</td>
        <td>@fat</td>
        <td class="buttons">
          <ul>
            <li><a href="javascript:alert('update row...');"><i class="fa fa-pencil-square-o"></i><span>update</span></a>
            </li><!--
            --><li><a href="javascript:alert('delete row...');"><i class="fa fa-times"></i><span>delete</span></a>
            </li>
          </ul>
        </td>
      </tr>
      <tr>
        <th scope="row">3</th>
        <td>Larry</td>
        <td>the Bird</td>
        <td>@twitter</td>
        <td class="buttons">
          <ul>
            <li><a href="javascript:alert('update row...');"><i class="fa fa-pencil-square-o"></i><span>update</span></a>
            </li><!--
            --><li><a href="javascript:alert('delete row...');"><i class="fa fa-times"></i><span>delete</span></a>
            </li>
          </ul>
        </td>
      </tr>
    </tbody>
  </table>
</div>

Note: the <li> are connected by HTML comments (<!-- -->) to prevent the inline-block spacing problem.

Community
  • 1
  • 1
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • I've edited the code snippet to add Twitter's CSS from CDN, since I've noticed now that you're using Bootstrap. Now it should be exactly like in your question... – Andrea Ligios Mar 18 '15 at 16:05
0

Use this:

$('tr').hover(function(){
    $('div').removeClass('hide');
    $('div').addClass('open');
})

CSS:

.open {    
background: yellow;
height: 300px;    
position: absolute; 
top: 0;
left: -500px;    
width: 500px;
opacity: 1;    
-webkit-transition: all 0.7s ease-out;
   -moz-transition: all 0.7s ease-out;
    -ms-transition: all 0.7s ease-out;
     -o-transition: all 0.7s ease-out;
            transition: all 0.7s ease-out;
}
.close {
background: yellow;
    height: 300px;    
    position: absolute; 
    top: 0;
    left: -500px;    
    width: 500px;
    opacity: 1;    
    -webkit-transition: all 0.7s ease-in;
       -moz-transition: all 0.7s ease-in;
        -ms-transition: all 0.7s ease-in;
         -o-transition: all 0.7s ease-in;
                transition: all 0.7s ease-in;
}

Hope it Works!

Razetime
  • 216
  • 3
  • 19