我想在用户第一次登录时触发一些JS,并且只在第一次加载特定页面时才会触发。
我相信我可以在他们第一次登录时处理,只需查看user.sign_in_count < 2
,但我不知道如何仅在第一页加载时指定。
即。我不希望在用户首次登录后触发JS并刷新页面而不注销。
我正在使用Turbolinks和$(document).on('turbolinks:load', function() {
触发它。
修改1
所以我要做的就是在许多页面上执行Bootstrap Tour。但我只希望在第一页加载时自动执行该游览。游览本身将引导用户访问我的应用程序中的其他特定页面,但每个页面将在每个页面上具有特定于页面的游览JS。
现在,在我的HTML中,我有类似的东西:
<script type="text/javascript">
$(document).on('turbolinks:load', function() {
var tour = new Tour({
storage: false,
backdrop: true,
onStart: function(){
$('body').addClass('is-touring');
},
onEnd: function(){
$('body').removeClass('is-touring');
},
steps: [
{
element: "#navbar-logo",
title: "Go Home",
content: "All throughout the app, you can click our logo to get back to the main page."
},
{
element: "input#top-search",
title: "Search",
content: "Here you can search for players by their name, school, positions & bib color (that they wore in our tournament)"
}
]});
// Initialize the tour
tour.init();
// Start the tour
tour.start();
});
</script>
所以我真正想要的是以下内容:
真正的问题就在于第一次登录,如果他们刷新主页10次,这次巡演将被执行10次。这就是我想要阻止的事情。
我希望这能提供更多清晰度。
答案 0 :(得分:12)
<强>前言强>
我的理解是你有:
script
值的功能
醇>
解决方案概述
下面的解决方案使用localStorage
来存储每个游览的标识符的键值对,以及是否已经看到它。页面刷新和会话之间存在localStorage
,顾名思义,localStorage
对于每个域,设备和浏览器都是唯一的(即Chrome localStorage
无法访问firefox&#39 ; s localStorage
即使是同一个域,也不能在您的笔记本电脑上使用chrome localStorage
访问您手机上的Chrome localStorage
,即使是同一个域名也是如此。我提出这一点来说明如果用户先前已登录,则依赖前言3来切换JS标志。
要开始游览,代码会检查localStorage
是否其相应的键值对未设置为true
(表示已经&#34;看到&#34;)。如果它确实存在且设置为true,则游览不会启动,否则它将运行。每次巡视开始时,使用其onStart
方法,我们会将游览的标识符更新/添加到localStorage
,并将其值设置为true
。
如果您只想执行当前页面的游览,可以通过手动调用游览的start
方法来手动执行游览,否则,您可以清除所有游览与旅游相关的localStorage
并将用户返回到第一页/如果您在第一页上,请再次调用start
方法。
JSFiddle (基于其他问题的HTML,您已经询问过巡回演出)
HTML (这可以是具有id="tourAgain"
属性的任何元素,以便以下代码生效。
<button class="btn btn-sm btn-default" id="tourAgain">Take Tour Again</button>
<强> JS 强>
var isFirstLogin = true; // this value is populated by ruby based upon first login
var userID = 12345; // this value is populated by ruby based upon current_user.id, change this value to reset localStorage if isFirstLogin is true
// jquery on ready function
$(function() {
var $els = {}; // storage for our jQuery elements
var tour; // variable that will become our tour
var tourLocalStorage = JSON.parse(localStorage.getItem('myTour')) || {};
function activate(){
populateEls();
setupTour();
$els.tourAgain.on('click', tourAgain);
// only check check if we should start the tour if this is the first time we've logged in
if(isFirstLogin){
// if we have a stored userID and its different from the one passed to us from ruby
if(typeof tourLocalStorage.userID !== "undefined" && tourLocalStorage.userID !== userID){
// reset the localStorage
localStorage.removeItem('myTour');
tourLocalStorage = {};
}else if(typeof tourLocalStorage.userID === "undefined"){ // if we dont have a userID set, set it and save it to localStorage
tourLocalStorage.userID = userID;
localStorage.setItem('myTour', JSON.stringify(tourLocalStorage));
}
checkShouldStartTour();
}
}
// helper function that creates a cache of our jQuery elements for faster lookup and less DOM traversal
function populateEls(){
$els.body = $('body');
$els.document = $(document);
$els.tourAgain = $('#tourAgain');
}
// creates and initialises a new tour
function setupTour(){
tour = new Tour({
name: 'homepage', // unique identifier for each tour (used as key in localStorage)
storage: false,
backdrop: true,
onStart: function() {
tourHasBeenSeen(this.name);
$els.body.addClass('is-touring');
},
onEnd: function() {
console.log('ending tour');
$els.body.removeClass('is-touring');
},
steps: [{
element: "div.navbar-header img.navbar-brand",
title: "Go Home",
content: "Go home to the main page."
}, {
element: "div.navbar-header input#top-search",
title: "Search",
content: "Here you can search for players by their name, school, positions & bib color (that they wore in our tournament)"
}, {
element: "span.num-players",
title: "Number of Players",
content: "This is the number of players that are in our database for this Tournament"
}, {
element: '#page-wrapper div.contact-box.profile-24',
title: "Player Info",
content: "Here we have a quick snapshot of the player stats"
}]
});
// Initialize the tour
tour.init();
}
// function that checks if the current tour has already been taken, and starts it if not
function checkShouldStartTour(){
var tourName = tour._options.name;
if(typeof tourLocalStorage[tourName] !== "undefined" && tourLocalStorage[tourName] === true){
// if we have detected that the tour has already been taken, short circuit
console.log('tour detected as having started previously');
return;
}else{
console.log('tour starting');
tour.start();
}
}
// updates localStorage with the current tour's name to have a true value
function tourHasBeenSeen(key){
tourLocalStorage[key] = true;
localStorage.setItem('myTour', JSON.stringify(tourLocalStorage));
}
function tourAgain(){
// if you want to tour multiple pages again, clear our localStorage
localStorage.removeItem('myTour');
// and if this is the first part of the tour, just continue below otherwise, send the user to the first page instead of using the function below
// if you just want to tour this page again just do the following line
tour.start();
}
activate();
});
PS。我们不使用onEnd
来触发tourHasBeenSeen
函数的原因是bootstrap tour目前存在一个错误,如果最后一步的元素不存在,则游览结束时不会触发{onEnd
1}}回调,BUG。
答案 1 :(得分:6)
您可以尝试使用Javascript的sessionStorage
,当用户关闭标签时会将其删除,但会通过刷新生存。只需使用sessionStorage.setItem(key, value
和sessionStorage.getItem(key)
即可。请记住,sessionStorage
只能存储字符串!
<script type="text/javascript">
$(document).on('turbolinks:load', function() {
var tour = new Tour({
storage: false,
backdrop: true,
onStart: function(){
$('body').addClass('is-touring');
},
onEnd: function(){
$('body').removeClass('is-touring');
},
steps: [
{
element: "#navbar-logo",
title: "Go Home",
content: "All throughout the app, you can click our logo to get back to the main page."
},
{
element: "input#top-search",
title: "Search",
content: "Here you can search for players by their name, school, positions & bib color (that they wore in our tournament)"
}
]});
if(sessionStorage.getItem("loggedIn") !== "yes"){//Remember that sessionStorage can only store strings!
//Initialize the tour
tour.init();
// Start the tour
tour.start();
}
else{
//Set item "loggedIn" in sessionStorage to "yes"
sessionStorage.putItem("loggedIn", "yes");
}
var goBackToTour = function(e){
//You can also make a "fake" link, so that it looks like a link, but is not, and you don't have to put the following line:
e.preventDefault();
tour.init();
tour.start();
};
document.getElementById("goBackToTourLink").addEventListener("click", goBackToTour);
});
//On the logout
var logout = function(){
sessionStorage.setItem("loggedIn", "no");
};
</script>
答案 2 :(得分:4)
使用本地存储:
if (typeof(Storage) !== "undefined") {
var takenTour = localStorage.getItem("takenTour");
if (!takenTour) {
localStorage.setItem("takenTour", true);
// Take the tour
}
}
我们使用此解决方案是因为我们的用户没有登录,而且比使用cookie轻一点。如上所述,当用户切换机器或清除缓存时,它不起作用,但是您的登录计数会覆盖这些内容。
答案 3 :(得分:3)
如果用户在cookie中看过游览,您可以存储。你可以维持一个&#34; TrackingCookie&#34;它包含所有用户跟踪信息(例如,tour_shown,promotion_shown等,可通过您的javascript访问) 码。 TrackingCookie代码之后是将所有此类跟踪信息保存在一个cookie中。我称之为 tracking_cookie 。
可以使用
在服务器端访问Cookie cookies[:tracking_cookie]
var TrackingCookie = (function() {
function TrackingCookie() {
this.name = 'tracking_cookie';
this.expires = new Date(new Date().setYear(new Date().getFullYear() + 1));
}
TrackingCookie.prototype.set = function(name, value) {
var data={};
if(!this.readFromStore()) {
data = this.readFromStore();
}
data[name] = value;
return this.writeToStore(data);
};
TrackingCookie.prototype.set_if_unset = function(name, value) {
if (!this.get(name)) {
return this.set(name, value);
}
};
TrackingCookie.prototype.get = function(name) {
return this.readFromStore()[name];
};
TrackingCookie.prototype.writeToStore = function(data) {
return $.cookie(this.name, JSON.stringify(data), {
path: '/',
expires: this.expires
});
};
TrackingCookie.prototype.readFromStore = function() {
return $.parseJSON($.cookie(this.name));
};
return TrackingCookie;
})();
<script type="text/javascript">
$(document).on('turbolinks:load', function() {
//Instantiate the cookie
var tracking_cookie = new TrackingCookie();
//Cookie value not set means, it is a new user.
if(!tracking_cookie.get("tour_shown")){
//Set the value to be true.
tracking_cookie.set("tour_shown",true)
var tour = new Tour({
storage: false,
backdrop: true,
onStart: function(){
$('body').addClass('is-touring');
},
onEnd: function(){
$('body').removeClass('is-touring');
},
steps: [
{
element: "#navbar-logo",
title: "Go Home",
content: "All throughout the app, you can click our logo to get back to the main page."
},
{
element: "input#top-search",
title: "Search",
content: "Here you can search for players by their name, school, positions & bib color (that they wore in our tournament)"
}
]});
// Initialize the tour
tour.init();
// Start the tour
tour.start();
};
});
</script>
Cookie类很详细。您只需使用$.cookie
即可实现简单的切换行为。以上代码适用于所有首次登录和登出的用户。如果您只想将其用于登录用户,请在服务器端的用户登录上设置标志。
答案 4 :(得分:2)
本地存储不是跨浏览器解决方案。试试这个cross browser SQL implementation使用不同的方法(包括localstorage)来无限期地在用户硬盘上存储“数据库”。
var visited;
jSQL.load(function(){
// create a table
jSQL.query("create table if not exists visits (time date)").execute();
// check if the user visited
visited = jSQL.query("select * from visits").execute().fetchAll("ASSOC").length;
// update the table so we know they visited already next time
jSQL.query("insert into visits values (?)").execute([new Date()]);
jSQL.persist();
});
答案 5 :(得分:1)
根据您的评论,我认为您希望在数据中跟踪此信息(这实际上是您使用user.sign_in_count > 1
检查所做的事情)。我的建议是使用像Redis这样的轻量级键值数据存储。
在此模型中,每次用户访问具有此功能的页面时,都会检查Redis中与该用户关联的“已访问”值。如果它不存在,则触发JS事件并为该用户添加"visited": true
给Redis,这将阻止JS在将来触发。
答案 6 :(得分:1)
您将不得不以某种方式与后端进行通信以获得登录计数。无论是在注入变量中,还是在用ajax命中的json路径中,都要执行以下逻辑:
if !session[:seen_tour] && current_user.sign_in_count == 1
@show_tour = true
session[:seen_tour] = true
else
@show_tour = false
end
respond_to do |format|
format.html {}
format.json { render json: {show_tour: @show_tour } }
end
会话中的值将保持不变,但是您已配置会话存储,默认情况下存储在Cookie中。