How do I get Bootstrap Tour to work with a jQuery dialog?
Asked Answered
B

3

3

Basically I can get Bootstrap Tour working with the most basic example, but when targeting an element in a jQuery dialog the highlight covers up the element.

var t = new Tour({
    backdrop: true
});

t.addStep({
    element: "#content",
    title: "Title",
    content: "Content"
});

t.start();

Here is a jsFiddle example of what I mean.

Bootstrap Tour with a jQuery Dialog

The highlight element should be behind the targeted element so that the text is still visible.

I think the issue is the z-index of the elements. It should be dialog -> highlight -> element, but instead it looks like it's dialog -> element -> highlight.

The z-index of the dialog is 100, the highlight is 1010 and the element is 1011, which I believe should be correct.

I can make it work by explicitly removing the z-index on the .ui-front jQuery UI class, but that doesn't seem like the best solution.

Any ideas why the default styling doesn't work if the z-index's are correct?

Bridgers answered 7/11, 2013 at 17:36 Comment(0)
S
11

The problem rests in the fact that the jQuery-UI Dialog has created a new stacking context and so changes to the z-index of the #content element will only show up relative to it's current stacking context.

For proof, add the following css, and you'll still see the #content div display above the dialog, which has a z-index of 100. --> i.e. Z-indexes are not absolute! ... jsFiddle

#content { z-index: 0 !important; }

From What No One Told You About Z-Index:

Every stacking context has a single HTML element as its root element. When a new stacking context is formed on an element, that stacking context confines all of its child elements to a particular place in the stacking order. That means that if an element is contained in a stacking context at the bottom of the stacking order, there is no way to get it to appear in front of another element in a different stacking context that is higher in the stacking order, even with a z-index of a billion!

New stacking contexts can be formed on an element in one of three ways:

  • When an element is the root element of a document (the element)
  • When an element has a position value other than static and a z-index value other than auto
  • When an element has an opacity value less than 1

The problem is Bootstrap Tour doesn't really have a good way of identifying this. When they start a tour on an element, they apply:

  • A full screen black tour-backdrop with a z-index of 1009,
  • A white tour-step-background behind the object with a z-index of 1010
  • and apply a z-index to the current tour element of 1011

...but the last z-index has no effect since our object is already in a stacking context. It is just positioned higher than any of the other elements within that stack (which it already was). Incidentally, that's why removing the z-index from ui-front results in the proper appearance because it frees the element from its current stack.


Here's what Bootstrap Tours should be doing, and we'll do manually with DOM manipulation.

The problem is that they are trying to position the elements relative to one another with z-indexes, but anytime the tour object is in a stacking context different from the .tour-step-background and .tour-backdrop, this will fail.

Solution? Place the elements you're generating inside the same stacking context!

Here's a simplified markup tree

  • Body
    • Tour background (normally goes here)
    • New stacking context
      • Tour object
      • Tour background (should go here)

To override this, we'll plugin to the tours onShown method and move the backdrops ourselves:

In JavaScript, when creating a tour, we'll do the following:

var t = new Tour({
    backdrop: true,
    onShown: function(tour) {
        var stepElement = getTourElement(tour);
        $(stepElement).after($('.tour-step-background'));
        $(stepElement).after($('.tour-backdrop'));
    }
});
 
function getTourElement(tour){
    return tour._steps[tour._current].element
}

This uses jQuery's .after() DOM manipulation to move the backdrop to the same stacking context as our tour object.

Also, we'll need to position both our tour backdrop elements as fixed instead of absolute, so they don't try to squeeze inside of our dialog. We can do that with the following CSS:

.tour-step-background, 
.tour-backdrop {
    position: fixed;
}

Working Demo in Fiddle

Which should look like this:

demo

Stargell answered 7/11, 2013 at 21:19 Comment(5)
Thanks for the research and very thorough explanation. I created an issue in GitHub (github.com/sorich87/bootstrap-tour/issues/166) in case someone else has come across this problem, but if no solution is found over the next few days I'll accept your answer.Bridgers
updated answer should work much better than originalStargell
this is great, thank you! Unfortunately this causes some display issues in IE, as well as scrolling issues in all browsers due to the position: fixed, but it's a push in the right direction. Thanks again.Bridgers
Confirmed this works with bootstrap-tour 0.9.3, but not 0.10.2. We tried several things with 0.10.2 and just could not get it working as shown in this jsfiddle.Nariko
@Pete, see the github issue above for a longer history of versioning issues. Here's a working demo in 10.1 which introduced some breaking changes. 10.2 isn't on cdnjs yet, but I'm guessing that it will at least need some of the old fixes.Stargell
C
1

I had the problem and I cheated by setting the opacity of tour-step-background to 0.4

Catenane answered 14/3, 2014 at 6:33 Comment(0)
G
-2

The right jsfiddle working with the last version of bootstrap tour

[http://jsfiddle.net/KyleMit/DYNbj/82/][1]
Globoid answered 19/4, 2015 at 4:18 Comment(1)
Hi Harold, while this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. Please take a look here: Why and how are some answers deleted?Piss

© 2022 - 2024 — McMap. All rights reserved.