I created an onboarding walkthrough tour for use in a SaaS App that is being loaded with A/B testing software. The tour automatically begins on initial page load. The user can close the tour at any time. I have used localStorage so the browser will recall at what point the user exits the page and that tour will start again at the further point in the tour. I also have a "replay" button that is disabled when the tour is running and enabled when the tour is finished or closed. The replay button's selector is ".tstour-replay". I am animating the movement of the tour steps by adding a class that is using CSS3 #keyframes rules and then delaying the removal of the class so that the animation will repeat if the user goes back and uses that Next animation again. Those are referred to as "popover-ani1", "popover-ani2" and so on.
I am having an issue that is not consistently happening so I cannot find a pattern that explains why it's happening. Sometimes, the Next and Back buttons of the individual tour modals, referred to in the code as #popoverid1, #popoverid2, and so on or #popoverback1, #popoverback2, and so on, will be disabled. They do not respond to clicks and they both have CSS hover effects that do not work properly. However, the close button, .popover-close, always works. I cannot figure out why sometimes the Next and Back buttons are just completely unclickable and lose their interactivity while the Close button is always fine.
I am fairly new to JavaScript and jQuery.
Here's my JavaScript code:
function tourFunction() {
$(".tstour-replay").addClass("tstour-replay-disable");
$("#tstour-start").click(function(){
//if clicked, do nothing
});
$("#popoverid1").click(function() {
$(".popover1").addClass("popover1-ani").delay(200).fadeOut(50);
$(".popover2").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover1").removeClass("popover1-ani");
}, 250);
});
$("#popoverid2").click(function() {
$(".popover2").fadeOut(50);
$(".popover3").delay(50).fadeIn(50);
});
$("#popoverback2").click(function() {
$(".popover2").addClass("popoverback2-ani").delay(200).fadeOut(50);
$(".popover1").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover2").removeClass("popoverback2-ani");
}, 250);
});
$("#popoverid3").click(function() {
$(".popover3").addClass("popover3-ani").delay(200).fadeOut(50);
$(".popover4").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover3").removeClass("popover3-ani");
}, 250);
});
$("#popoverback3").click(function() {
$(".popover3").addClass("popoverback3-ani").delay(200).fadeOut(50);
$(".popover2").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover3").removeClass("popoverback3-ani");
}, 250);
});
$("#popoverid4").click(function() {
$(".popover4").addClass("popover4-ani").delay(200).fadeOut(50);
$(".popover5").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover4").removeClass("popover4-ani");
}, 250);
});
$("#popoverback4").click(function() {
$(".popover4").addClass("popoverback4-ani").delay(200).fadeOut(50);
$(".popover3").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover4").removeClass("popoverback4-ani");
}, 250);
});
$("#popoverid5").click(function() {
$(".popover5").addClass("popover5-ani").delay(200).fadeOut(50);
$(".popover6").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover5").removeClass("popover5-ani");
}, 250);
});
$("#popoverback5").click(function() {
$(".popover5").addClass("popoverback5-ani").delay(200).fadeOut(50);
$(".popover4").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover5").removeClass("popoverback5-ani");
}, 250);
});
$("#popoverid6").click(function() {
$(".popover6").addClass("popover6-ani").delay(200).fadeOut(50);
$(".popover7").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover6").removeClass("popover6-ani");
}, 250);
});
$("#popoverback6").click(function() {
$(".popover6").addClass("popoverback6-ani").delay(200).fadeOut(50);
$(".popover5").delay(250).fadeIn(50);
setTimeout(function() {
$(".popover6").removeClass("popoverback6-ani");
}, 250);
});
}
function tourReplay() {
$(".tstour-replay").removeClass("tstour-replay-disable");
$("#tstour-start").click(function() {
$(".tstour-replay").addClass("tstour-replay-disable");
$(".popover1").fadeIn("fast");
});
}
function disableTourReplay() {
$(".tstour-replay").removeClass("tstour-replay-disable");
$("#tstour-start").click(function() {
//if clicked, do nothing
});
}
//END FUNCTIONS
$(".popover-btn-start").click(function() {
$(".tour-container").fadeOut();
$(".popover7").fadeOut();
$(".tstour-replay").removeClass("tstour-replay-disable");
$("#tstour-start").click(function() {
//if clicked, do nothing
});
tourReplay();
});
$(".popover-close").click(function(){
$(".tour-container").fadeOut();
$(".popover").fadeOut();
tourReplay();
});
//BEGIN FUNCTION TRIGGERS
var trigger_flag = localStorage.getItem('tstour');
if (!trigger_flag) {
disableTourReplay();
$(".popover1").fadeIn("fast");
tourFunction();
} else if (trigger_flag == '1') { //clicked next1
disableTourReplay();
$(".popover2").fadeIn("fast");
tourFunction();
} else if (trigger_flag == '2') { //clicked next2
disableTourReplay();
$(".popover3").fadeIn("fast");
tourFunction();
} else if (trigger_flag == '3') { //clicked next3
disableTourReplay();
$(".popover4").fadeIn("fast");
tourFunction();
} else if (trigger_flag == '4') { //clicked next4
disableTourReplay();
$(".popover5").fadeIn("fast");
tourFunction();
} else if (trigger_flag == '5') { //clicked next5
disableTourReplay();
$(".popover6").fadeIn("fast");
tourFunction();
} else if (trigger_flag == '6' || '7') { //got to last popover, finished tour or closed out
tourReplay();
}
//END FUNCTION TRIGGERS
//BEGIN LOCAL STORAGE SET
$(document).on("click", "#popoverid1", function(e){
localStorage.setItem('tstour', '1');
});
$(document).on("click", "#popoverid2", function(e){
localStorage.setItem('tstour', '2');
});
$(document).on("click", "#popoverid3", function(e){
localStorage.setItem('tstour', '3');
});
$(document).on("click", "#popoverid4", function(e){
localStorage.setItem('tstour', '4');
});
$(document).on("click", "#popoverid5", function(e){
localStorage.setItem('tstour', '5');
});
$(document).on("click", "#popoverid6", function(e){
localStorage.setItem('tstour', '6');
});
$(document).on("click", ".popover-btn-start", function(e){
localStorage.setItem('tstour', '7');
});
$(document).on("click", ".popover-close", function(e){
localStorage.setItem('tstour', '7');
});
And here is the HTML
<div class="tour-centered">
<div id="tstour-start" class="tstour-replay">How Does This Work?</div>
<div class="popover popover1">
<div class="popover-right">
<div id="popover-close" class="popover-close">
</div>
<div class="popover-content">
<div class="popover-title">Employees On Your Calendar</div>
<div class="popover-body">Here's Jane Deaux, a sample employee. I preloaded some events for her in your calendar.</div>
<div class="popover-footer">
<div class="popover-progress">1 of 6</div>
<div class="popover-buttons">
<div class="popover-next" id="popoverid1">Next</div>
</div>
</div>
</div>
</div>
</div>
<div class="popover popover2">
<div class="popover-above">
<div id="popover-close" class="popover-close">
</div>
<div class="popover-content">
<div class="popover-title">Calendar Events</div>
<div class="popover-body">Notice Jane's name on the calendar. Each listing is a scheduled or pending calendar event.
<br />
<br />Hover your mouse over her name to quickly see the event details.</div>
<div class="popover-footer">
<div class="popover-progress">2 of 6</div>
<div class="popover-buttons">
<div class="popover-back" id="popoverback2">Back</div>
<div class="popover-next" id="popoverid2">Next</div>
</div>
</div>
</div>
</div>
</div>
<div class="popover popover3">
<div class="popover-above">
<div id="popover-close" class="popover-close">
</div>
<div class="popover-content">
<div class="popover-title">Add a New Calendar Event</div>
<div class="popover-body">Double-click on any day to create a new calendar event. Use Jane to try it out and deduct hours from her time-off banks.
<br /><br />Give it a try. I'll wait right here until you're done.<br /></div>
<div class="popover-footer">
<div class="popover-progress">3 of 6</div>
<div class="popover-buttons">
<div class="popover-back" id="popoverback3">Back</div>
<div class="popover-next" id="popoverid3">Next</div>
</div>
</div>
</div>
</div>
</div>
<div class="popover popover4">
<div class="popover-below">
<div id="popover-close" class="popover-close">
</div>
<div class="popover-content">
<div class="popover-title">Create More Calendar Events</div>
<div class="popover-body">Great job! You can also click this icon to create more calendar events.</div>
<div class="popover-footer">
<div class="popover-progress">4 of 6</div>
<div class="popover-buttons">
<div class="popover-back" id="popoverback4">Back</div>
<div class="popover-next" id="popoverid4">Next</div>
</div>
</div>
</div>
</div>
</div>
<div class="popover popover5">
<div class="popover-below">
<div id="popover-close" class="popover-close">
</div>
<div class="popover-content">
<div class="popover-title">Customize Your Calendar</div>
<div class="popover-body">Visit Preferences to customize your calendar event codes, create time-off plans, and much more.</div>
<div class="popover-footer">
<div class="popover-progress">5 of 6</div>
<div class="popover-buttons">
<div class="popover-back" id="popoverback5">Back</div>
<div class="popover-next" id="popoverid5">Next</div>
</div>
</div>
</div>
</div>
</div>
<div class="popover popover6">
<div class="popover-below">
<div id="popover-close" class="popover-close">
</div>
<div class="popover-content">
<div class="popover-title">Add More Employees</div>
<div class="popover-body">When you're ready, add more of your employees and create calendar events for them.
<br />
<br />The more employees you load and track, the easier it is to avoid scheduling conflicts.</div>
<div class="popover-footer">
<div class="popover-progress">6 of 6</div>
<div class="popover-buttons">
<div class="popover-back" id="popoverback6">Back</div>
<div class="popover-next" id="popoverid6">Next</div>
</div>
</div>
</div>
</div>
</div>
<div class="popover popover7">
<div class="popover-content-final">
<div class="popover-title-final">Ready to Take Back Your Time?</div>
<div class="popover-btn-start">Start Tracking!</div>
<div class="popover-help">
<a href="https://tracksmart.zendesk.com/hc/en-us/requests/new" target="_blank">
I Need Some Help
</a></div>
</div>
</div>
</div>
Related
Can someone please help me understand the jQuery code and how it relates to my HTML. The links are going through and hiding all the divs, however I can't figure out why the div isn't showing when it's link is clicked.
HTML:
<section class="meet-the-team pt-5 pb-5">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
Link 1
Link 2
Link 3
Link 4
Link 5
<div class="meet-the-team-info">
<div class="conor-div">
<h1>Conor</h1>
<img src="https://www.w3schools.com/images/w3schools_green.jpg" alt="alternatetext" style="width:100px;">
<p>Hello Hello Hello</p>
</div>
<div class="kyle-div">I'm div2</div>
<div class="tracey-div">I'm div3</div>
<div class="frank-div">I'm div4</div>
<div class="rosie-div">I'm div5</div>
</div>
</div>
</div>
</section>
jQuery:
$(function () {
$(".kyle-div, .tracey-div, .frank-div, .rosie-div").hide();
$("a").bind("click", function () {
$(".conor-div, .kyle-div, .tracey-div, .frank-div, .rosie-div").hide();
var target = $(this).data("target");
$("."+target).toggle();
});
});
You just need to change one line of your jQuery.
$(function () {
$(".kyle-div, .tracey-div, .frank-div, .rosie-div").hide();
$("a").bind("click", function () {
$(".conor-div, .kyle-div, .tracey-div, .frank-div, .rosie-div").hide();
var target = $(this).data("target");
$("."+target+"-div").show() //added "-div" and changed toggle to show
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<section class="meet-the-team pt-5 pb-5">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
Link 1
Link 2
Link 3
Link 4
Link 5
<div class="meet-the-team-info">
<div class="conor-div">
<h1>Conor</h1>
<img src="https://www.w3schools.com/images/w3schools_green.jpg" alt="alternatetext" style="width:100px;">
<p>Hello Hello Hello</p>
</div>
<div class="kyle-div">I'm div2</div>
<div class="tracey-div">I'm div3</div>
<div class="frank-div">I'm div4</div>
<div class="rosie-div">I'm div5</div>
</div>
</div>
</div>
</section>
#natels's solution works and deserves to be the accepted answer. But even his solution can be shortened a little bit:
$(function () {
$("a").click(function () {
$(".meet-the-team-info div:visible").hide(); // first hide all visible team divs,
$("."+this.dataset.target+"-div").show(); // then show the chosen one
}).eq(0).click(); // emulate a click on the first link (index=0)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<section class="meet-the-team pt-5 pb-5">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
Link 1
Link 2
Link 3
Link 4
Link 5
Link 6
<div class="meet-the-team-info">
<div class="conor-div">
<h1>I'm Conor</h1>
<img src="https://www.w3schools.com/images/w3schools_green.jpg" alt="alternatetext" style="width:100px;">
<p>Hello Hello Hello</p>
</div>
<div class="kyle-div">I'm Kyle</div>
<div class="tracey-div">I'm Tracey</div>
<div class="frank-div">I'm Frank</div>
<div class="gwen-div">I'm Gwen</div>
<div class="rosie-div">I'm Rosie</div>
</div>
</div>
</div>
</section>
The code in this snippet does not need to be adjusted if more divs are to be included in the page. The individual class names do not occur in the code any more.
i think you have an extra hide() there. The first hide(), hides all the divs on page load. But then on click you say "hide" and "toggle". They're canceling each other or doing something unexpected. Try just toggle(). And also you're missing the "div" part in your selector.
$(function () {
$(".kyle-div, .tracey-div, .frank-div, .rosie-div").hide();
$("a").bind("click", function () {
// $(".conor-div, .kyle-div, .tracey-div, .frank-div, .rosie-div").hide();
var target = $(this).data("target");
$("."+target+"-div").toggle();
});
});
I need to make a button that views three consequent posts
when I click "view all" the three "div"s should show up
I need to make the three 'div's show up if I click the view all button
so I am using jquery here
$('.posts .repeat-grid').slice(0, 3).show();
$('#view-all').on('click', function() {
$('.posts .repeat-grid:hidden').slice(0, 1).slideDown();
if ($('.posts .repeat-grid:hidden').length === 0) {
$('#view-all').fadeOut();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="posts">
<div class="repeat-grid">1</div>
<div class="repeat-grid">2</div>
<div class="repeat-grid">3</div>
</div>
<div id="view-all">View All</div>
any idea why it is not working?
You Can Try this if that's what you mean
$('#view-all').on('click', function() {
$('.posts').slideToggle();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="posts">
<div class="repeat-grid">1</div>
<div class="repeat-grid">2</div>
<div class="repeat-grid">3</div>
</div>
<div id="view-all">View All</div>
I have some tabs set up with jQuery, but I would like to add the capability to change tabs based on URL. Ideally, once the URL is followed by the id/data-attribute, the browser scrolls to the appropriate section and the tab gets open.
$(document).ready(function(){
$('.gdlr-session-item-head-info').click(function(){
if( $(this).hasClass('gdlr-active') ) return;
$(".gdlr-session-item-head-info").removeClass('gdlr-active');
$('html, body').animate({
scrollTop: $(".gdlr-tab-session-item").offset().top-200
}, 1000);
var selected_tab = $(this).attr('data-tab');
var current_day = $(this).attr('current-day');
$(".currentDay-"+current_day).addClass('gdlr-active');
$('.gdlr-session-item-head').siblings('.gdlr-session-item-tab-content').hide();
$('.gdlr-session-item-head').siblings('.' + selected_tab).fadeIn();
});
}
HMTL
<div class="session-item-wrapper" id="agendaroduct" style="margin-bottom: 10px;">
<div class="gdlr-session-item gdlr-tab-session-item gdlr-item">
<div class="gdlr-session-item-head">
<a href="agenda/#currentDay-1">
<div id="currentDay-1" class="gdlr-session-item-head-info currentDay-0 gdlr-active" current-day="0" data-tab="gdlr-tab-1">
<div class="gdlr-session-head-day">Pre-Day</div>
<div class="gdlr-session-head-date">Tue, Nov 5</div>
</div>
</a>
<a href="agenda/#currentDay-2">
<div id="currentDay-2" class="gdlr-session-item-head-info currentDay-1" current-day="1" data-tab="gdlr-tab-2">
<div class="gdlr-session-head-day">Day 1</div>
<div class="gdlr-session-head-date">Wed, Nov 6</div>
</div>
</a>
<a href="agenda/#currentDay-3">
<div id="currentDay-3" class="gdlr-session-item-head-info currentDay-2" current-day="2" data-tab="gdlr-tab-3">
<div class="gdlr-session-head-day">Day 2</div>
<div class="gdlr-session-head-date">Thu, Nov 7</div>
</div>
</a>
<div class="clear"></div>
</div>
<div>
<div class="clear"></div>
</div>
<div class="gdlr-session-item-tab-content gdlr-tab-1 " style="display: block;"> content goes here
</div>
<div class="gdlr-session-item-tab-content gdlr-tab-2 gdlr-active" style="display: none;"> content goes here
</div>
<div class="gdlr-session-item-tab-content gdlr-tab-3 " style="display: none;"> conten goes here
</div>
<div class="gdlr-session-item-head end">
<div class="gdlr-session-item-head-info currentDay-0 gdlr-active" current-day="0" data-tab="gdlr-tab-1">
<div class="gdlr-session-head-day">Pre-Day</div>
<div class="gdlr-session-head-date">Tue, Nov 5</div>
</div>
<div class="gdlr-session-item-head-info currentDay-1" current-day="1" data-tab="gdlr-tab-2">
<div class="gdlr-session-head-day">Day 1</div>
<div class="gdlr-session-head-date">Wed, Nov 6</div>
</div>
<div class="gdlr-session-item-head-info currentDay-2" current-day="2" data-tab="gdlr-tab-3">
<div class="gdlr-session-head-day">Day 2</div>
<div class="gdlr-session-head-date">Thu, Nov 7</div>
</div>
<div class="clear"></div>
</div>
<div class="clear"></div>
</div>
Any help would be very much appreciate it.
Thanks!
You'll want to find a method of connecting the hash value to a DOM element. In your case, your id attribute on your tab triggers match this and also contain the relevant information to show the correct tabs amongst other functionality (as you've demonstrated in your click event).
You could separate your tab change logic into a function which can then be called by both click events and on page load by passing the intended tab to show as a parameter.
function showTab(element) {
if (element.hasClass("gdlr-active")) return;
$(".gdlr-session-item-head-info").removeClass("gdlr-active");
$("html, body").animate({
scrollTop: $(".gdlr-tab-session-item").offset().top - 200
}, 1000);
var selected_tab = element.attr("data-tab");
var current_day = element.attr("current-day");
$(".currentDay-" + current_day).addClass("gdlr-active");
$('.gdlr-session-item-head').siblings(".gdlr-session-item-tab-content").hide();
$('.gdlr-session-item-head').siblings("." + selected_tab).fadeIn();
}
Your click handler would then be bound to call the function...
$('.gdlr-session-item-head-info').click(function(){
showTab($(this));
})
When the page loads, you could verify the hash in the URL is an available DOM element and send that to your function also.
$(document).ready(function () {
if (window.location.hash) {
var targetTab = $(window.location.hash)
if (targetTab.length) {
showTab(targetTab);
}
}
})
So I was basically trying to create a drop-down list with jquery. I was successful in achieving but came across with a slight problem. Here's the code
HTML
<div class="dropdown_heading">
text
</div>
<div class="dropdown_container">
<div class="">
Competition1
</div>
<div class="">
Competition2
</div>
<div class="">
Competition3
</div>
</div>
JQUERY
$(document).ready(function(){
$(".dropdown_heading").mouseenter(function(){
$(".dropdown_container").slideDown();
});
$(".dropdown_container").mouseleave(function(){
$(".dropdown_container").slideUp();
});
});
Once I hover over the dropdown_heading the dropdown shows-up and I'm able to navigate over it but the only way the it slides back up is if i actually have the cursor in the dropdown_container. If I try to slide it up removing the mouse from dropdown_heading, the dropdown is still visible. How would I be able to slide the submenu back up when the mouse leaves both div_container and div_heading?
I've tried to execute this function but therefore I am unable to navigate over the container. Thanks.
$(".dropdown_heading").mouseleave(function(){
$(".dropdown_container").slideUp();
});
You can try a timer based solution like
jQuery(function($) {
var $target = $(".dropdown_container");
$('.dropdown_heading').hover(function() {
clearTimeout($target.data('hoverTimer'));
$target.stop(true, true).slideDown(500);
}, function() {
var timer = setTimeout(function() {
$target.stop(true, true).slideUp();
}, 200);
$target.data('hoverTimer', timer);
});
$target.hover(function() {
clearTimeout($(this).data('hoverTimer'));
}, function() {
$(this).stop(true, true).slideUp();
});
});
.dropdown_container {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dropdown_heading">
text
</div>
<div class="dropdown_container">
<div class="">
Competition1
</div>
<div class="">
Competition2
</div>
<div class="">
Competition3
</div>
</div>
The toggleClass() method toggles between adding and removing one or more class names from the selected elements.
This method checks each element for the specified class names. The class names are added if missing, and removed if already set - This creates a toggle effect..
Try this,
$(document).ready(function(){
$(".dropdown_heading").mouseenter(function(){
$(".dropdown_container").toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dropdown_heading">
text
</div>
<div class="dropdown_container">
<div class="">
Competition1
</div>
<div class="">
Competition2
</div>
<div class="">
Competition3
</div>
</div>
I have this Markup, and the way this is supposed to work is the user click on the "icon arrow" and this following JS is supposed to fire which will display the hidden content, in other words opening the window. this works in another program, but is there any reason this is not firing.
Here is the markup:
<div data-bind="foreach {data:movies}">
<div class="content-item full bottom-border">
<div class="content-item-container">
<div class="movie-listing-header">
<a class="icon arrow"></a>
<div class="movie-details">
<div class="title"></div>
<div class="info">
<div>
<span class="rating" data-bind="css: 'rating-' + (MovieRating || 'NR').toLowerCase().replace(/-/, '')"></span>
</div>
</div>
</div>
<a class="icon right-arrow"></a>
</div>
<div class="showtimes">
<div data-bind="template: { name: 'movie-grouped-showtimes-template', data: $data }"></div>
</div>
</div>
</div>
</div>
and here is the .js
$(document).ready(function () {
$('.icon.arrow').click(function () {
var active_el = $(this);
$('.movie-listing-header').each(function () {
if ($(this).get(0) === active_el.parent().get(0)) {
if ($(this).hasClass('active')) {
$(this).siblings('.showtimes').hide();
} else {
$(this).siblings('.showtimes').show();
}
$(this).toggleClass('active');
} else {
$(this).removeClass('active');
$(this).siblings('.showtimes').hide();
}
});
});
});