Better handling of tour triggering
This commit is contained in:
parent
5917e0a6a9
commit
ae06540ea0
@ -6,7 +6,7 @@ _Guide your users in the one true path._
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Abraham makes it easy to show guided tours to users of your Rails application. Abraham keeps track of whether someone has seen a tour so it doesn't appear again and also lets a user skip until their next visit.
|
Abraham makes it easy to show guided tours to users of your Rails application. When Abraham shows a tour, it keeps track of whether the user has completed it (so it doesn't get shown again) or dismissed it for later (so it reappears in a future user session).
|
||||||
|
|
||||||
* Define tour content with simple YAML files, in any/many languages.
|
* Define tour content with simple YAML files, in any/many languages.
|
||||||
* Organize tours by controller and action.
|
* Organize tours by controller and action.
|
||||||
@ -157,14 +157,14 @@ walkthrough:
|
|||||||
text: "This walkthrough will show you how to..."
|
text: "This walkthrough will show you how to..."
|
||||||
```
|
```
|
||||||
|
|
||||||
Abraham creates a JavaScript event based on the tour name that you can wire into a link or button on that page. In the above example, you would use the `abraham:walthrough:start` event to make the tour appear:
|
This tour will not start automatically; instead, use the `Abraham.startTour` method with the tour name:
|
||||||
|
|
||||||
```
|
```
|
||||||
<button id="startTour">Start tour</button>
|
<button id="startTour">Start tour</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.querySelector("#startTour").addEventListener("click", function() {
|
document.querySelector("#startTour").addEventListener("click", function() {
|
||||||
document.dispatchEvent(new Event('abraham:walthrough:start'));
|
Abraham.startTour("walkthrough"));
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
@ -173,7 +173,7 @@ Abraham creates a JavaScript event based on the tour name that you can wire into
|
|||||||
|
|
||||||
```
|
```
|
||||||
<script>
|
<script>
|
||||||
$("#startTour").on("click", function() { $(document).trigger('abraham:walthrough:start'); })
|
$("#startTour").on("click", function() { Abraham.startTour('walkthrough'); })
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
//= require js-cookie/src/js.cookie
|
//= require js-cookie/src/js.cookie
|
||||||
//= require shepherd.js/dist/js/shepherd
|
//= require shepherd.js/dist/js/shepherd
|
||||||
|
|
||||||
var abrahamReady = (callback) => {
|
var Abraham = new Object();
|
||||||
if (document.readyState != "loading") callback();
|
|
||||||
else document.addEventListener("DOMContentLoaded", callback);
|
Abraham.tours = {};
|
||||||
|
Abraham.incompleteTours = [];
|
||||||
|
Abraham.startTour = function(tourName) {
|
||||||
|
if (!Shepherd.activeTour) {
|
||||||
|
Abraham.tours[tourName].start();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
Abraham.startNextIncompleteTour = function() {
|
||||||
|
if (Abraham.incompleteTours.length) {
|
||||||
|
Abraham.tours[Abraham.incompleteTours[0]].checkAndStart();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", Abraham.startNextIncompleteTour);
|
||||||
|
document.addEventListener("turbolinks:load", Abraham.startNextIncompleteTour);
|
||||||
|
|
||||||
document.addEventListener('turbolinks:before-cache', function() {
|
document.addEventListener('turbolinks:before-cache', function() {
|
||||||
// Remove visible product tours
|
// Remove visible product tours
|
||||||
|
@ -1,29 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AbrahamHelper
|
module AbrahamHelper
|
||||||
# def abraham_tour
|
|
||||||
# # Do we have tours for this controller/action in the user's locale?
|
|
||||||
# tours = Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.locale}"]
|
|
||||||
|
|
||||||
# tours ||= Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.default_locale}"]
|
|
||||||
|
|
||||||
# if tours
|
|
||||||
# completed = AbrahamHistory.where(
|
|
||||||
# creator_id: current_user.id,
|
|
||||||
# controller_name: controller_name,
|
|
||||||
# action_name: action_name
|
|
||||||
# )
|
|
||||||
# remaining = tours.keys - completed.map(&:tour_name)
|
|
||||||
|
|
||||||
# if remaining.any?
|
|
||||||
# # Generate the javascript snippet for the next remaining tour
|
|
||||||
# render(partial: "application/abraham",
|
|
||||||
# locals: { tour_name: remaining.first,
|
|
||||||
# steps: tours[remaining.first]["steps"] })
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
def abraham_tour
|
def abraham_tour
|
||||||
# Do we have tours for this controller/action in the user's locale?
|
# Do we have tours for this controller/action in the user's locale?
|
||||||
tours = Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.locale}"]
|
tours = Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.locale}"]
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script>
|
<script>
|
||||||
var abraham_tour_<%= tour_name %> = new Shepherd.Tour(<%= Rails.configuration.abraham.tour_options.html_safe unless Rails.configuration.abraham.tour_options.nil? %>);
|
Abraham.tours["<%= tour_name %>"] = new Shepherd.Tour(<%= Rails.configuration.abraham.tour_options.html_safe unless Rails.configuration.abraham.tour_options.nil? %>);
|
||||||
|
|
||||||
<% if trigger != 'manual' %>
|
<% if trigger != 'manual' %>
|
||||||
abraham_tour_<%= tour_name %>.on("complete", function() {
|
Abraham.tours["<%= tour_name %>"].on("complete", function() {
|
||||||
// Make AJAX call to save history of tour completion
|
// Make AJAX call to save history of tour completion
|
||||||
return fetch("/abraham_histories/", {
|
return fetch("/abraham_histories/", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -16,13 +16,13 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
abraham_tour_<%= tour_name %>.on("cancel", function() {
|
Abraham.tours["<%= tour_name %>"].on("cancel", function() {
|
||||||
Cookies.set('<%= abraham_cookie_prefix %>-<%= tour_name %>', 'later', { domain: '<%= abraham_domain %>' });
|
Cookies.set('<%= abraham_cookie_prefix %>-<%= tour_name %>', 'later', { domain: '<%= abraham_domain %>' });
|
||||||
});
|
});
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% steps.each_with_index do |(key, step), index| %>
|
<% steps.each_with_index do |(key, step), index| %>
|
||||||
abraham_tour_<%= tour_name %>.addStep({
|
Abraham.tours["<%= tour_name %>"].addStep({
|
||||||
id: 'step-<%= key %>',
|
id: 'step-<%= key %>',
|
||||||
<% if step.key?('title') %>
|
<% if step.key?('title') %>
|
||||||
title: "<%= step['title'] %>",
|
title: "<%= step['title'] %>",
|
||||||
@ -37,14 +37,14 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
buttons: [
|
buttons: [
|
||||||
<% if index == steps.size - 1 %>
|
<% if index == steps.size - 1 %>
|
||||||
{ text: '<%= t('abraham.done') %>', action: abraham_tour_<%= tour_name %>.complete }
|
{ text: '<%= t('abraham.done') %>', action: Abraham.tours["<%= tour_name %>"].complete }
|
||||||
<% else %>
|
<% else %>
|
||||||
<% if index == 0 %>
|
<% if index == 0 %>
|
||||||
{ text: '<%= t('abraham.later') %>', action: abraham_tour_<%= tour_name %>.cancel, classes: 'shepherd-button-secondary' },
|
{ text: '<%= t('abraham.later') %>', action: Abraham.tours["<%= tour_name %>"].cancel, classes: 'shepherd-button-secondary' },
|
||||||
{ text: '<%= t('abraham.continue') %>', action: abraham_tour_<%= tour_name %>.next }
|
{ text: '<%= t('abraham.continue') %>', action: Abraham.tours["<%= tour_name %>"].next }
|
||||||
<% else %>
|
<% else %>
|
||||||
{ text: '<%= t('abraham.exit') %>', action: abraham_tour_<%= tour_name %>.cancel, classes: 'shepherd-button-secondary' },
|
{ text: '<%= t('abraham.exit') %>', action: Abraham.tours["<%= tour_name %>"].cancel, classes: 'shepherd-button-secondary' },
|
||||||
{ text: '<%= t('abraham.next') %>', action: abraham_tour_<%= tour_name %>.next }
|
{ text: '<%= t('abraham.next') %>', action: Abraham.tours["<%= tour_name %>"].next }
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
]
|
]
|
||||||
@ -52,7 +52,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if trigger != "manual" %>
|
<% if trigger != "manual" %>
|
||||||
abraham_tour_<%= tour_name %>.start = function (start) {
|
Abraham.tours["<%= tour_name %>"].checkAndStart = function (start) {
|
||||||
return function () {
|
return function () {
|
||||||
// Don't start the tour if the user dismissed it once this session
|
// Don't start the tour if the user dismissed it once this session
|
||||||
var tourMayStart = !Cookies.get('<%= abraham_cookie_prefix %>-<%= tour_name %>', {domain: '<%= abraham_domain %>'});
|
var tourMayStart = !Cookies.get('<%= abraham_cookie_prefix %>-<%= tour_name %>', {domain: '<%= abraham_domain %>'});
|
||||||
@ -65,18 +65,11 @@
|
|||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(abraham_tour_<%= tour_name %>.start)
|
}(Abraham.tours["<%= tour_name %>"].start)
|
||||||
|
|
||||||
<% if !tour_completed %>
|
<% if !tour_completed %>
|
||||||
abraham_tour_<%= tour_name %>.start();
|
Abraham.incompleteTours.push("<%= tour_name %>");
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
document.addEventListener('abraham:<%= tour_name %>:start', function() {
|
|
||||||
// Don't start the tour if another one is already active on the screen
|
|
||||||
if (!Shepherd.activeTour) {
|
|
||||||
abraham_tour_<%= tour_name %>.start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -11,15 +11,15 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.querySelector("#restart_automatic").addEventListener("click", function() {
|
document.querySelector("#restart_automatic").addEventListener("click", function() {
|
||||||
document.dispatchEvent(new Event('abraham:intro:start'));
|
Abraham.startTour("intro");
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector("#show_manual").addEventListener("click", function() {
|
document.querySelector("#show_manual").addEventListener("click", function() {
|
||||||
document.dispatchEvent(new Event('abraham:a_manual_tour:start'));
|
Abraham.startTour("a_manual_tour");
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector("#show_another_manual").addEventListener("click", function() {
|
document.querySelector("#show_another_manual").addEventListener("click", function() {
|
||||||
document.dispatchEvent(new Event('abraham:another_manual_tour:start'));
|
Abraham.startTour("another_manual_tour");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ tour_one:
|
|||||||
element: "p"
|
element: "p"
|
||||||
placement: "top"
|
placement: "top"
|
||||||
|
|
||||||
# tour_two:
|
tour_two:
|
||||||
# steps:
|
steps:
|
||||||
# 1:
|
1:
|
||||||
# title: "TOUR TWO step one ENGLISH"
|
title: "TOUR TWO step one ENGLISH"
|
||||||
# text: "we show this on your second visit"
|
text: "we show this on your second visit"
|
||||||
|
@ -93,4 +93,22 @@ class ToursTest < ApplicationSystemTestCase
|
|||||||
# No tour should be visible, since the first step is invalid
|
# No tour should be visible, since the first step is invalid
|
||||||
refute_selector ".shepherd-element"
|
refute_selector ".shepherd-element"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "page with two incomplete tours shows them on consecutive visits" do
|
||||||
|
# First tour should appear at first visit
|
||||||
|
visit dashboard_other_url
|
||||||
|
assert_selector ".shepherd-element", visible: true
|
||||||
|
assert_selector ".shepherd-header", text: "TOUR ONE step one ENGLISH"
|
||||||
|
find(".shepherd-button", text: "Done").click
|
||||||
|
|
||||||
|
# Second tour should appear at second visit
|
||||||
|
visit dashboard_other_url
|
||||||
|
assert_selector ".shepherd-element", visible: true
|
||||||
|
assert_selector ".shepherd-header", text: "TOUR TWO step one ENGLISH"
|
||||||
|
find(".shepherd-button", text: "Done").click
|
||||||
|
|
||||||
|
# Now no tours should appear since they're both done
|
||||||
|
visit dashboard_other_url
|
||||||
|
refute_selector ".shepherd-element"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user