0

I am making a website with a splash screen that I want to make disappear after 3 seconds. I can successfully do it when I include jQuery, but this takes time to load (especially if it's not cached) and so the splash still displays for a small time.

I am also using cookies so that it will only show on the first load of the page (so it's not overly irritating).

Here's my HTML:

<div class="splash">
    splash content
</div>

Here's the working jQuery (that I want to avoid):

if(document.cookie.indexOf("visited=true") === -1) {
    $(".splash").delay(3000).queue(function(){
        $(this).addClass("hidden").dequeue();
    });
} else {
    $(".splash").addClass("hidden");
}

Here's what I have come up with regarding javascript, but it doesn't work:

document.getElementsByClassName("splash").addEventListener("load",
function() {
    if(document.cookie.indexOf("visited=true") === -1) {
        setTimeout(function(){
            this.classList.add("hidden");
        }, 3000);
    } else {
        this.classList.add("hidden");
    }
});
  • Are you sure this works? I don't think `if(document.cookie.indexOf === -1)` works as `indexOf` is a function, and you also haven't specified what you are looking for. In terms of your second piece of code, I think `this` isn't your element, but rather `window`. – putvande Feb 04 '17 at 17:54
  • @putvande The second code snippet (which the OP says he's using, does use `indexOf` correctly. – Scott Marcus Feb 04 '17 at 17:58
  • yeah, i changed it.. thanks @putvande! – marcellothearcane Feb 04 '17 at 18:10

3 Answers3

5

I don't think you want to add the function as the load event listener of the splash. You should add it to the load event of the page.

See comments inline for more details on reorganizing the code. Unfortunately, it won't work with cookies here in the Stack Overflow snippet environment.

Note that the splash is set to be hidden (via CSS) by default. This is a better practice than showing it by default and then hiding it. If, after reading the cookie, it is determined that the splash should not be shown, some users may wind up seeing the splash momentarily on their screens due to processing limitations, or worse if there is any kind of error in your code, the splash may wind up being shown and never taken away because the JS stops executing at the error.

// Get a reference to the splash dialog
var splash = document.querySelector(".splash");

// When the window is loaded....
window.addEventListener("load", function() {
  
  // Check to see if the cookie indicates a first-time visit
  if(document.cookie.indexOf("visited=true") === -1) {

    // Reveal the splash (remember: splash is hidden by default by CSS)
    splash.classList.remove("hidden");
    
    // .5 seconds later, hide the splash
    setTimeout(function(){
      splash.classList.add("hidden");
      
      // >> Set cookie to visited here <<
    }, 500);
  } 
});
.splash {
  height:200px;
  width:200px;
  background:yellow;
}

.hidden {
  display:none;
}
<div class="splash hidden">S P L A S H !</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Good, but you just forgot to set the cookie. – ibrahim mahrir Feb 04 '17 at 17:59
  • I've upvoted, but don't have the reputation.. thanks! – marcellothearcane Feb 04 '17 at 18:25
  • Please see: https://jsfiddle.net/qoh0mz2p/4/ for a working example. I've swapped out cookies (which don't work in that environment either) with `localStorage` (which you may want to use instead of cookies anyway). Press "Run" and the first time, you'll see the splash for .5 seconds. Then press "Run" again and you won't. You can open your developer tools and navigate to actually look at localStorage and clear it out to run the demo over and over it you like. – Scott Marcus Feb 04 '17 at 18:25
  • probably another question in its own right, but `document.cookie.indexOf("visited=true")` isn't reading the cookie set in the root level. (i'm setting the cookie with `document.cookie = "visited=true; path=/"`, no expiry because I want it as a session cookie). How can I change this? – marcellothearcane Feb 04 '17 at 19:02
  • That's best for a new question. I haven't used cookies for quite some time and I'm a bit rusty on them, but if there's no expiration, then yes, they are more like session cookies, but in your case, that's not what you want because the cookie will be gone when the user leaves your site and they will always see the splash. You want the cookie to persist.. Did you see the `localStorage` example I showed? That is much more modern and easier to use. – Scott Marcus Feb 04 '17 at 19:08
  • Turns out i hadn't changed all the pages from my old way to yours.. the cookies are all working fine. I'll look into local storage too, thanks! – marcellothearcane Feb 04 '17 at 19:34
0
document.getElementsByClassName("splash").addEventListener("load", //not possible as ByClassName returns a collection not an element
function() {
if(document.cookie.indexOf("visited=true") === -1) {//why not simply !...
    setTimeout(function(){
        this.classList.add("hidden");//this is window as setTimeout is a window function...
    }, 3000);
} else {
    this.classList.add("hidden");//the only that work
}
});

The right way:

document.getElementsByClassName("splash").forEach(el=>{el.addEventListener("load",function() {
if(!document.cookie.indexOf("visited=true")) {
    setTimeout(function(){
        this.classList.add("hidden");
    }.bind(this), 3000);//fix of context
} else {
    this.classList.add("hidden");
}
})});
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

You can include this IIFE at the bottom of your page so that it will be executed when the splash DOM element is ready. This way you can avoid the event listener.

I also converted your splash to use the ID splash rather than a class. If you prefer the class, when you use document.getElementsByClassName("splash") it returns an array of elements. In that case you'll have to specify which elements of the returned array you want to use (i.e. document.getElementsByClassName("splash")[0] or iterate through them).

(function() {
  var splash = document.getElementById("splash");
  if (document.cookie.indexOf("visited=true") === -1) {
    splash.classList.remove("hidden"); // Display the splash
    setTimeout(function() {
      splash.classList.add("hidden"); // Hide it after the timeout
    }, 500);
  }
})();
#splash { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background: #ddd; }
.hidden { display: none; }
Not splashed!
<div id="splash" class="hidden">Splashed!</div>
Community
  • 1
  • 1
grovesNL
  • 6,016
  • 2
  • 20
  • 32
  • It's better to have the splash hidden by default and then reveal it via code. This will avoid some users seeing the splash flicker momentarily when the page first loads. A good example is right here in the SO snippet. Because there is an error, the splash is shown and never goes away. – Scott Marcus Feb 04 '17 at 18:06
  • @ScottMarcus: I agree, although I generally try to keep the logic the same as the question. I've edited my answer to invert the logic. – grovesNL Feb 04 '17 at 18:16