0

I have some problems with displaying an AJAX loader inside a table cell.

I want it to be displayed over the cell to underline that there is data being loaded into it. However, I am experiencing problems with properly positioning it.

My base solution:

CSS:

.loader {
    z-index: 30;
    text-align: center;
    background-color: #f00; /* Red, so I could see it properly */
    opacity:0.5;
    filter:alpha(opacity=50); /* For IE8 and earlier */
    position: relative;
}

JS:

displayCellLoader: function (cell) {
  var loader = $("<div>").addClass("loader").css({
    width: cell.width(),
    height: cell.height(),
    left: 0,
    top: 0
  });
  cell.append(loader);
}

However, this design has some flaws:

  1. If the table cells have padding (and they have) the loader won't cover it
  2. The loader will be displayed below any content the cell contains, not over it (as exppected)

A screenshot of the problem: Loaders without padding

I thought the best way to eliminate these flaws would be to position the loader absolutely but it caused a different problem:

The loader's left and right CSS properties are taken from the results of the offset() method, however for an unknown reason the loaders are displayed somewhat moved to the right (and a little to big).

Here is my modified JS:

displayCellLoader: function (cell) {
    var offset = cell.offset();
    var loader = $("<div>").addClass("loader").css({
        width: cell.innerWidth(),
        height: cell.innerHeight(),
        left: offset.left,
        top: offset.top
    });
    body.append(loader); /* body is $("body") */
}

And this is how it looks like now: Loaders moved to the right

Does anyone know why does it happen?

And, more importantly, is there a better way to do it?

EDIT: There was a solution posted, about a way I didn't mention here - appending absolutely positioned div into a td, which has position: relative. At first I thought "How on Earth could I forget about such obvious method?", however after testing it, I noticed that it doesn't work. The divs became positioned relatively to the table container, not to the cell itself.

I googled the issue and found this question. Quoting the best answer,

This is because according to CSS 2.1, the effect of position: relative on table elements is undefined.

So this solution doesn't apply to my case. The way to go would be to modify the template so all my table cells contain a div with position:relative which I could use to position the loaders. This solution is kind of painful for me, because it involves a lot of modifications in my code, so I'll use it as a last resort.

I also don't know why did the poster delete his answer - it could prove useful to others.

Community
  • 1
  • 1
Przemek
  • 6,300
  • 12
  • 44
  • 61
  • Well, I have "found" a way to solve it with wrapping the contents of the td with a relative div and then absolutely positioning the loader inside it. If noone finds a better way, I'll post and accept my own answer. – Przemek Dec 02 '11 at 08:13

2 Answers2

0

I tried it in a slightly different way - with absolute positioning, outerWidht/height & offset:

http://jsfiddle.net/tdSDY/

ptriek
  • 9,040
  • 5
  • 31
  • 29
  • Thak you for your answer but it does not work properly in my case, probably because of some style and html differences. – Przemek Dec 02 '11 at 08:10
0

Well, I ended up embedding cell contents into a div, like this:

displayCellLoader: function (cell) {
    var paddingTop = parseInt(cell.css("padding-top"));
    var paddingLeft = parseInt(cell.css("padding-left"));
    var tempDiv = $("<div>").css({
        position: "relative",
        height: cell.height()
    }).html(cell.html());
    cell.empty().append(tempDiv);
    var loader = $("<div>").addClass("loader").css({
        width: cell.width(),
        height: cell.outerHeight(),
        top: -paddingTop,
        left: -paddingLeft
    }).append($("<img>").attr("src", "images/loader-cell.gif"));
    tempDiv.append(loader);
}
Przemek
  • 6,300
  • 12
  • 44
  • 61