I use yii2 as a backend framework, I want to make tour for my app, but bootstrap tour popover not shown on the second page, I create an asset bundle for bootstrap tour and register it in the layout, bootstrap tour work correctly on the first page but when going to another page it make problem and in debug on the next page show:
Bootstrap Tour 'tour' | Redirect to paper/upload
Bootstrap Tour 'tour' | Error redirection loop to paper/upload
I already check window local storage in the developer tool of the chrome and see it is on the correct step when going to second-page window local storage was shown: tour_current_step value 2,
and another question, how I should set value for path option in the bootstrap tour for yii2 router, is my paths correct? for example first step is on the main page of the site is: "", is it correct, I would like if someone clicks on the previous button of popover return back to the previous step.
here is my javascript code, I register this javascript code in the layout file:
$(function() {
var $demo, duration, remaining, tour;
$demo = $("#demo");
duration = 5000;
remaining = duration;
tour = new Tour({
onStart: function() {
return $demo.addClass("disabled", true);
},
onEnd: function() {
return $demo.removeClass("disabled", true);
},
debug: true,
steps: [
{
path: "",
element: "#demo",
placement: "bottom",
title: "Welcome to Bootstrap Tour!",
content: "Introduce new users to your product by walking them through it step by step."
}, {
path: "",
element: "#Wordcounter",
placement: "bottom",
title: "Step One",
content: "For translation click on word counter menu item"
}, {
path: "paper/upload",
element: "#myDropzone",
placement: "top",
title: "Step two",
content: "Drag and Drop your file here or click to upload plz wate to complete upload"
}
,
{
path: "paper/upload",
element: "#next",
placement: "bottom",
title: "Step three",
content: "then Click on the Next Bottom",
reflex: true
}, {
path: "paper/show",
element: "#save",
placement: "top",
title: "Step four",
content: "click on save and continue and choose language plan",
duration: 5000
}
]
}).init();
if (tour.ended()) {
$('<div class="alert alert-info alert-dismissable"><button class="close" data-dismiss="alert" aria-hidden="true">×</button>You ended the demo tour. <a href="#" data-demo>Restart the demo tour.</a></div>').prependTo(".content").alert();
}
$(document).on("click", "[data-demo]", function(e) {
e.preventDefault();
if ($(this).hasClass("disabled")) {
return;
}
tour.restart();
return $(".alert").alert("close");
});
});
I make a lot of work on the code and finally find an answer, the problem was on the paths, I used pretty URL in the URL manager, and the bootstrap tour need relation paths, if path in the current page not same as the path in the step of bootstrap tour, it's going to on redirect loop, and this is because there is no way the bootstrap tour can find, does it need to redirect or no, this is the short code of bootstrap tour where go to redirect loop
if (step.redirect && this._isRedirect(step.host, path, document.location)) {
this._redirect(step, i, path);
if (!this._isJustPathHashDifferent(step.host, path, document.location)) {
return;
}
}
for solving this issue when paths should get from the router (for example in frameworks like Yii, Laravel, Symfony and ...) the bootstrap tour suggest to use the onNext attribute in the step and redirect to an address.
but in my case, I change the source code of bootstrap tour to find my answer in better form and replace the above code with this code:
var current_url = document.URL;
var result = current_url.includes(path);
if(!result){
this._redirect(step, i, path);
if (!this._isJustPathHashDifferent(step.host, path, document.location)) {
return;
}
}
and change the redirect code to this:
Tour.prototype._redirect = function(step, i, path) {
var href;
if ($.isFunction(step.redirect)) {
return step.redirect.call(this, path);
} else {
href = this._options.domainAddress + path;
// href = {}.toString.call(step.host) === '[object String]' ? "" + step.host + path : path;
this._debug("Redirect to: " + href);
if (this._getState('redirect_to') === ("" + i)) {
this._debug("Error redirection loop to " + path);
this._removeState('redirect_to');
if (step.onRedirectError != null) {
return step.onRedirectError(this);
}
} else {
this._setState('redirect_to', "" + i);
return document.location.href = href;
}
}
};
and define a global variable in options, domainAddress, but i think it is not a good way to change the source code of bootstrap tour, but it is work for my case.