Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cancelling the tour when clicking outside the element #141

Closed
paulocheque opened this issue Oct 31, 2016 · 2 comments
Closed

cancelling the tour when clicking outside the element #141

paulocheque opened this issue Oct 31, 2016 · 2 comments

Comments

@paulocheque
Copy link

paulocheque commented Oct 31, 2016

Do we have any native option for that? Using Shepherd or tetherOptions?

What about typing the Esc key for that?

Thanks in advance

@paulocheque paulocheque changed the title cancel when clicking outside the element cancelling the tour when clicking outside the element Oct 31, 2016
@catherineomega
Copy link

This is what I did to allow:

  • arrow key navigation to handle next/back steps on the tour
  • using escape key to cancel the tour
  • clicking outside the tour step popup to close the tour
  • highlighting the currently targeted tour step to isolate it from the rest of the page

First, I add a div to the page, the same size as the window:

function addTourOverlay() {
    if ($('#tour-overlay').length === 0) {
      $('body').prepend('<div id="tour-overlay"></div>');
    }
    resizeOverlay();
  }

  function resizeOverlay() {
    var window_height = $(window).height;
    var window_width = $(window).width;
    $('#tour-overlay').height(window_height).width(window_width);
  }

I style it like this:

.shepherd-step {
  z-index: 1000; }

#tour-overlay {
  opacity: 0;
  width: 100%;
  height: 100%;
  z-index: -9999;
  position: fixed;
  overflow: hidden;
  left: 0;
  top: 0; }
  .shepherd-active #tour-overlay {
    z-index: 998; }
  .shepherd-active.shepherd-element-attached-middle #tour-overlay, .shepherd-active.shepherd-target-attached-middle #tour-overlay {
    background-color: #1aa3dd;
    opacity: 0.4; }

.shepherd-target.shepherd-enabled {
  box-shadow: 0px 0px 0px 10000px rgba(26, 163, 221, 0.4), inset 0px 0px 2px rgba(26, 163, 221, 0.4);
  position: relative;
  z-index: 10; }

This uses the CSS box-shadow property to draw what appears to be a translucent overlay "over" everything, leaving a "hole" for the element currently targeted by the current step. In actual fact, the "hole" is just the object, and it's been relatively positioned using z-index to be "above" everything else.

This is the elements' z-index order, sorted, from top to bottom:

  1. Tour popup
  2. #tour-overlay div
  3. Currently-targeted element in the page
  4. Everything else

This lets clicks outside the current tour step popup hit the targeted area (unfortunately, depending on your use case, this includes the currently-targeted element, so we can't just use it to isolate the current target).

If nothing is being targeted, we make the overlay visible, so it functions as the translucent background.

And then, to let clicks on the overlay with the overlay AND with the div, I do this:

// Cancel the tour when users click outside the tour area.
    $('body').on('click', '#tour-overlay', function() {
      tour.cancel();
    });

    // Keyboard commands for interacting with the tour:
    // cancel the tour when users hit escape.
    // move to next item in tour when users hit right arrow.
    // go back on left arrow.
    document.onkeydown = function(evt) {
      evt = evt || window.event;
      var isEscape = false;
      if ("key" in evt) {
        isEscape = (evt.key == "Escape" || evt.key == "Esc");
      } else {
        isEscape = (evt.keyCode == 27);
      }
      if (isEscape) {
        tour.cancel();
      }

      // this is not the escape key.
      else {
        // we only interact with the tour if the tour is active.
        if ($('body.shepherd-active').length !== 0) {
          // left arrow
          if (evt.keyCode == '37') {
            tour.back();
          }
          // right arrow
          else if (evt.keyCode == '39') {
            tour.next();
          }
          // // up arrow
          // else if (evt.keyCode == '38') {
          //
          // }
          // // down arrow
          // else if (evt.keyCode == '40') {
          //
          // }
        }
      }

@RobbieTheWagner
Copy link
Member

I think this functionality is potentially outside the scope of Shepherd, and would be something you would want to implement in your app, as needed. If someone has a small idea and wants to try a PR we would definitely consider it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants