11

进入第二页后,我无法在多页浏览中启动 Bootstrap Tour。

我的巡演从点击事件开始,并localStorage设置为false. 游览从单击事件开始正常,但是当我进入游览的第二步并加载新页面时,游览不会从中断的地方继续。

如何在这个新页面上从第二步恢复游览?我知道我需要重新初始化游览,但我显然没有正确执行此操作。

$(document).ready(function () {
    // Instance the tour
    var tour = new Tour({
        name: "CiteTour",
        steps: [{
            element: "",
            title: "#1",
            content: "You can find help with formatting citations on the Guide page. Click 'Next' to go there now.",
            placement: ""
        }, {
            element: "#CiteTour2",
            title: "#2 - Citation Resources",
            content: "There are several options for getting help with formatting citations. Once on the Guide page, look for the box labeled 'Citation Help.'",
            placement: "right",
            path: "/newpath",
            onNext: function (tour) {
                tour.init();
                tour.restart();
            }
        }, {
            element: "#CiteTour3",
            title: "#3",
            content: "This site can help format your research paper and references in APA, MLA, and the other major citation formats.",
            placement: "right",
        }, {
            element: "#AskTour1",
            title: "#4 - Ask-a-Librarian",
            content: "If you still have questions about citations or citation format, feel free to contact the librarians.  Good luck!",
            placement: "left",
        }],
        storage: false,
    });

    // Initialize the tour
    tour.init();
    $('#CiteTour-go').on('click', function () {
        // Start the tour
        tour.start();
    });
});
4

2 回答 2

31

问题及说明

首先,您必须确保您storage: window.localStorage使用的是Storage API。这是默认的游览选项,因此您所要做的就是不要像您所做的那样将其覆盖为 false。这样做是允许 Bootstrap Tour 将当前步骤信息保存在同一域内的多个页面中。

想要证明?- 打开您的开发工具并查看: 资源

其次,如果您path为任何步骤指定选项,则应为所有步骤指定它。当单页导览开始时,它不需要担心导航到不同的页面,但是一旦你移动到一个新的页面,如果你没有为前面的步骤指定路径,引导导览是没有办法的知道导航回哪里。

此外,您需要通过在 url 前加上一个斜杠来使用绝对路径引用,以便它相对于根目录。如果您使用相对路径,则路径将在您浏览页面/步骤时更改。 有关更多信息,请参阅我在无限页面刷新问题底部的部分

第三,只要你定义了tour对象并init初始化它,游览就会自动在一个新的页面上拾取。

让我们看一下做什么init()的简化版本:

Tour.prototype.init = function(force) {
  // other code omitted for brevity

  if (this._current !== null) {
    this.showStep(this._current);
  }
};

所以一旦你初始化了巡视,只要它注意到巡视已经开始并且还没有结束(即它有一个当前步骤),它就会自动启动那个步骤。因此,您无需通过onNext在第二步中点击事件来进行初始化。

多页游概念证明

可编辑的 Plunk | 可运行演示

脚本.js

$(function() {
  
  // define tour
  var tour = new Tour({
    steps: [{
      path: "/index.html",
      element: "#my-element",
      title: "Title of my step",
      content: "Content of my step"
    }, {
      path: "/newPage.html",
      element: "#my-other-element",
      title: "Title of my step",
      content: "Content of my step"
    }]
  });

  // init tour
  tour.init();

  // start tour
  $('#start-tour').click(function() {
    tour.restart();
  });
  
});

索引.html:

<!DOCTYPE html>
<html>
<head>
  <title>Multipage Bootstrap Tour - Page 1</title>
  <link rel="stylesheet" href="bootstrap.css" />
  <link rel="stylesheet" href="bootstrap-tour.min.css">
</head>
<body>
  <div class="container">
    <h1>First Page</h1>
    
    <button class="btn btn-lg btn-primary" id="start-tour">
      Start Tour
    </button><br/><br/>
  
    
    <span id="my-element">
      My First Element
    </span>
    
  </div>
  <script src="jquery.min.js"></script>
  <script src="bootstrap.js"></script>
  <script src="bootstrap-tour.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

新页面.html

<!DOCTYPE html>
<html>
<head>
  <title>Multipage Bootstrap Tour - Page 2</title>
  <link rel="stylesheet" href="bootstrap.css" />
  <link rel="stylesheet" href="bootstrap-tour.min.css">
</head>
<body>
  <div class="container">
    <h1>New Page</h1>
    
    <span id="my-other-element">
      My Second Elemennt
    </span>

  </div>
  <script src="jquery.min.js"></script>
  <script src="bootstrap.js"></script>
  <script src="bootstrap-tour.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

您在哪里引入了以下

无限页面刷新问题

在很多配置中,您会进入一个循环,页面无限刷新,不断尝试解析到当前步骤的路径。以下是为什么会出现此问题以及如何解决此问题。

Bootstrap Tour 如何进行下一步?

当您按下Next按钮时,游览将调用下一步showStep(i)

这是一个简化版本showStep

Tour.prototype.showStep = function (i) {
    // other code omitted for brevity

    // get step path
    path = tour._options.basePath + step.path;

    // get current path - join location and hash
    current_path = [document.location.pathname, document.location.hash].join('');

    // determine if we need to redirect and do so
    if (_this._isRedirect(path, current_path)) {
        _this._redirect(step, path);
        return;
    }
};

因此,如果文档中的当前路径与下一步的路径不同,则 tour 将自动重定向到下一步。

这是仅考虑字符串值的重定向的简化形式:
尽管 Bootstrap Tour 也支持它们,但我省略了基于正则表达式的路径

Tour.prototype._isRedirect = function(path, currentPath) {
    var checkPath = path.replace(/\?.*$/, '').replace(/\/?$/, '');
    var checkCurrent = currentPath.replace(/\/?$/, '');
    return (checkPath !== checkCurrent);
};

Tour.prototype._redirect = function(step, path) {
    this._debug("Redirect to " + path);
    return document.location.href = path;
};

注意:正则表达式只是用于删除查询参数 ( /\?.*$/) 和尾部正斜杠 ( //?$/` )

当任何页面加载时,不确定 Bootstrap Tour 是否已将其重定向,或者您只是回来并尝试从您离开的地方继续浏览。

因此,在您初始化游览时的任何页面上:

  1. 它将根据本地存储中的值启动当前步骤。
  2. 当前步骤加载时,将确认该步骤的路径与当前 url 相同
  3. 如果没有,它将重定向到步骤路径并从步骤 1 重新开始

换句话说,它知道如何到达下一个需要去的地方,但是一旦到达那里就无法确认是否是这种情况。以这种情况为例,其步骤如下所示:

var step = {
      path: "index.html",
      element: "#my-element",
      title: "Title of my step",
      content: "Content of my step"
    }

它可以很好地重定向到相对引用,但是当页面再次加载并检查它是否已加载到正确的地址时,会发生这种情况:

无限循环

“KyleMit”,你可能会抗议,“它就不能弄清楚我想要什么吗?

-不!

如果您依赖相对路径进行重定向,当它加载一个步骤时,它不能保证您实际上已经到达该步骤,它会尝试再次重定向您。

这是因为,在网址中,"index.html" !== "\index.html". 他们是两条不同的路!一个保证在域根,而另一个可以在任何地方。想象一下,你有一些这样的嵌套视图:

  • 意见
    • 共享
      • 索引.html
      • 新页面.html
      • 索引.html
      • 新页面.html

在页面之间导航时,如果您只告诉它正确的页面名称,引导程序如何知道它是否到达了正确的目的地。

这使我们解决了这个问题:

绝对使用绝对 URL

提示debug:true:通过在创建游览时传递来更好地了解正在发生的事情,这将记录每个重定向:
重定向

于 2014-11-25T01:44:56.470 回答
1

专门针对使用 Angular 构建的 SPA

@KyleMit 的精彩回答对我帮助很大:我遵循了所有三个建议,但旅行没有继续。我相信 bootstrap-tour 仍然存在单页应用程序的问题。

由于我在 SPA 上使用 Angular,它实际上是相同的“网页”,但不同的 Angular“视图”。巡演没有继续……</p>

直到我在 $(window).resize();固定导航栏的控制器中添加了一个。导航栏固定在屏幕顶部。因此,控制器被实例化一次。而且我已经有了一个位置更改处理程序:

$scope.$on("$locationChangeSuccess", $scope._handleLocationChange);

这个“解决方案”的一个提示是我碰巧按 F12 在(停靠的)Firebug 面板中查看控制台消息,你瞧,游览继续!我检查了一下,当我关闭或打开 Firebug 面板时它会继续。我仍然无法弄清楚为什么resize是必要的,但在我的应用程序的上下文中它是无害的,我需要继续前进,在这个问题上花了这么多时间之后。取消调用,resize重定向后游览将不会继续。将其添加回来,游览将按预期继续。

"basePath": "/app/#"在配置中进行了游览,它只跨越了两个视图。路径就像"path": "/"(对于“主页”视图)和"path": "/show/chair"(应用程序中的典型视图)。

我在这个应用程序上使用 Angular 1.4.8。

HTH。

于 2016-11-05T10:50:45.063 回答