繁体   English   中英

如何在用户首次登录时以及第一次加载特定页面时检测到?

[英]How do I detect the first time the user logs in and the first time a specific page is loaded?

我想仅在用户第一次登录时触发一些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>

所以我真正想要的是以下内容:

  • 每当他们重新加载页面时,不会在首次登录时执行新游览时轰炸用户。
  • 如果需要,允许他们通过简单地按下链接,以便以后手动执行巡视。
  • 如果我不需要,我不想在我的数据库中存储任何东西 - 所以最好这应该是基于cookie的方法或localStorage
  • 假设我将使用Rails跟踪他们已完成的登录次数。 所以一旦他们不止一次登录,我就无法触发这个JS。

真正的问题就在于第一次登录,如果他们刷新主页10次,这次巡演将被执行10次。 这就是我想要阻止的。

我希望这能提供更多的清晰度。

前言

我的理解是你有:

  1. 包含单个游览的多个页面(每个页面的游览不同)
  2. 检测首次登录帐户的方法(ruby登录计数)
  3. 能够根据首次登录添加script

方案概述

下面的解决方案使用localStorage存储每个游览的标识符的键值对,如果已经看到它。 localStorage页面刷新和会话之间持续存在,顾名思义, localStorage是唯一的各个领域,设备和浏览器(即Chrome的localStorage无法访问Firefox的localStorage即使是相同的领域,也不能Chrome的localStorage在笔记本电脑上使用Chrome浏览器的localStorage上您的手机即使是同一个域名)。 我提出这一点来说明如果用户先前已登录,则依赖前言3来切换JS标志。

为了开始游览,代码检查localStorage是否其相应的键值对未设置为true (表示已被“看到”)。 如果它确实存在且设置为true,则游览不会启动,否则它将运行。 当每个游览开始时,使用其onStart方法,我们将游览的标识符更新/添加到localStorage并将其值设置为true

如果您只想执行当前页面的巡视,可以通过手动调用巡视的start方法来执行巡视的手动执行,否则,您可以清除与巡回相关的所有localStorage并将用户发送回第一个page /如果你在第一页,再次调用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回调, BUG

您可以尝试使用Javascript的sessionStorage ,当用户关闭选项卡时会删除它,但会通过刷新生存。 只需使用sessionStorage.setItem(key, valuesessionStorage.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> 

要使用本地存储:

  if (typeof(Storage) !== "undefined") {
    var takenTour = localStorage.getItem("takenTour");
    if (!takenTour) {
      localStorage.setItem("takenTour", true);
      // Take the tour
    }
  }

我们使用此解决方案是因为我们的用户没有登录,而且比使用cookie轻一点。 如上所述,当用户切换机器或清除缓存时,它不起作用,但是您的登录计数覆盖了这一点。

如果用户已经在cookie中看过游览,您可以存储。 您可以维护一个“TrackingCookie”,其中包含所有用户跟踪信息(例如,tour_shown,promotion_shown等,可通过您的javascript代码访问。以下TrackingCookie代码是将所有此类跟踪信息保存在一个cookie中。我称之为tracking_cookie

可以使用服务器端访问Cookie

cookies[:tracking_cookie]

tracking_cookie.js

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;

})();

在您的HTML中

<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来实现简单的一个切换行为。 以上代码适用于所有首次登录和登出的用户。 如果您只想将其用于登录用户,请在服务器端的用户登录上设置标志。

本地存储不是跨浏览器解决方案。 试试这个跨浏览器的SQL实现 ,它使用不同的方法(包括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();
});

如果您想要做的就是为了生命而关闭页面,这应该可行。 如果您需要阻止重新执行更长时间,请考虑localStorage。

var triggered;
$(document).on('turbolinks:load', function() {
if (triggered === undefined) {
            triggered = "yes";
...code...
}}

根据您的评论,我认为您将要在数据中跟踪此信息(这实际上是您使用user.sign_in_count > 1检查所做的user.sign_in_count > 1 )。 我的建议是使用像Redis这样的轻量级键值数据存储。

在此模型中,每次用户访问具有此功能的页面时,都会检查Redis中与该用户关联的“已访问”值。 如果它不存在,则触发JS事件并为该用户添加"visited": true给Redis,这将阻止JS在将来触发。

您将不得不以某种方式与后端进行通信以获得登录计数。 无论是在注入变量中,还是在用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中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM