I am trying to get anchor links to open up tabs on a specific page.
When I am on the page that the tabs are on, and I click on the anchor link, it correctly scrolls to the tab and opens it --- however, if I am on a different page than the tabs are on, the anchor link only goes to that page, it does not open the tab.
URL: http://elkodowntown.wpengine.com/
The Anchor links are under the OUR MEMBERS menu in the navigation.
JS:
jQuery(function($) {
$('.menu-item-179 a').on('click', function(event){
tabScroll('.et_pb_tab_0');
return false;
});
$('.menu-item-180 a').on('click', function(event){
tabScroll('.et_pb_tab_1');
return false;
});
$('.menu-item-181 a').on('click', function(event){
tabScroll('.et_pb_tab_2');
return false;
});
$('.menu-item-182 a').on('click', function(event){
tabScroll('.et_pb_tab_3');
return false;
});
$('.menu-item-183 a').on('click', function(event){
tabScroll('.et_pb_tab_4');
return false;
});
function tabscroll(target) {
$("html, body").animate({ scrollTop: $('#member-tabs').offset().top }, 1000);
setTimeout($('#member-tabs' + target + ' a').click(), 2000 );
}
$(function hash() {
var hash = window.location.hash.replace('#', "");
if (hash == '#shop') { tabscroll('.et_pb_tab_1'); }
if (hash == '#service') { tabscroll('.et_pb_tab_0'); }
if (hash == '#eat-drink') { tabscroll('.et_pb_tab_2'); }
if (hash == '#arts-entertainment') { tabscroll('.et_pb_tab_3'); }
if (hash == '#stay') { tabscroll('.et_pb_tab_4'); }
});
});
Anchor Links HTML:
<ul class="sub-menu">
<li id="menu-item-179" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-179">Shop</li>
<li id="menu-item-180" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-180">Service</li>
<li id="menu-item-181" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-181">Eat & Drink</li>
<li id="menu-item-182" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-182">Arts & Entertainment</li>
<li id="menu-item-183" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item menu-item-183">Stay</li>
</ul>
Tabs HTML:
<div id="member-tabs" class="et_pb_module et_pb_tabs et_pb_tabs_0 et_slide_transition_to_3 et_slide_transition_to_0">
<ul class="et_pb_tabs_controls clearfix">
<li class="et_pb_tab_0 et_pb_tab_active">Shop</li><li class="et_pb_tab_1">Service</li><li class="et_pb_tab_2">Eat & Drink</li><li class="et_pb_tab_3">Arts & Entertainment</li><li class="et_pb_tab_4">Stay</li>
</ul>
The anchor links (#shop,#service, etc) are being called by <a name="#shop"> here (directly under the Tabs HTML):
<div class="et_pb_tab clearfix et_pb_active_content et_pb_tab_0 et-pb-active-slide" style="z-index: 1; display: block; opacity: 1;">
<a name="shop"></a><!--- tab content here --->
</div>
I'm sure there is a better way to organize my JS.
Any help is appreciated!
After looking through the code for a while, the problem finally dawned on me. You currently wrap each of the click handlers inside their own jQuery function:
jQuery(function($) {
$('.menu-item-183 a').on('click', function(event){
tabScroll();
return false;
});
function tabScroll(){
$('#member-tabs .et_pb_tab_4 a').click();
$("html, body").animate({ scrollTop: $('#member-tabs').offset().top }, 1000);
}
});
jQuery(function($) { ...
In each of these contexts, tabscroll() only has scope relative to the outer jQuery function. That is to say, in the above context, only menu-item-183 will have access to that particular tabscroll() function.
You later try to reference the tabscroll() function outside of that scope:
$(function hash() {
var hash = window.location.hash.replace('#', "");
if (hash == '#shop') { tabscroll(); }
if (hash == '#service') { tabscroll(); }
if (hash == '#eat-drink') { tabscroll(); }
if (hash == '#arts-entertainment') { tabscroll(); }
if (hash == '#stay') { tabscroll(); }
});
As this block reads, all conditionals are trying to do the exact same thing (call tabscroll() with no given parameter), and the condition could essentially be written as:
if (hash == '#shop' || hash == '#service' || ... ) {
tabscroll();
}
But you need the tabscroll function to redirect to different locations that aren't the same as hash, which means you have to manually separate them out:
if (hash == '#shop') { tabscroll('.et_pb_tab_1'); }
if (hash == '#service') { tabscroll('.et_pb_tab_0'); }
if (hash == '#eat-drink') { tabscroll('.et_pb_tab_2'); }
if (hash == '#arts-entertainment') { tabscroll('.et_pb_tab_3'); }
if (hash == '#stay') { tabscroll('.et_pb_tab_4'); }
Then simply change your tabscroll function to allow for this:
function tabscroll(target) {
$('#member-tabs' + target + ' a').click();
$("html, body").animate({ scrollTop: $('#member-tabs').offset().top }, 1000);
}
The final step is to make sure that this new tabscroll() function is accessible from your condition. With your current code structure, it should be placed just above or below $(function hash() {});
Ultimately you should restructure your code so that every click links to this new tabscroll() function, but this should be enough to solve the problem for now :)
Hope this helps! :)
Related
I have a website where I am not able to change the HTML, I can only inject JavaScript and CSS. The website has a dropdown menu that doesn't work properly on Android. The parent menu is also a link, and when people click it they are taken to the link on the parent instead of opening the child/submenu.
The HTML (simplified)
<ul id="menu">
<li>
Parent menu ▼
<ul>
<li>Submenu link</li>
<li>Submenu link</li>
<li>Submenu link</li>
</ul>
</li>
<li>
Parent menu link
</li>
</ul>
And I have this jQuery:
var topmenuclicked == 0;
$("#menu > li a").click(function(event){
event.preventDefault();
if (topmenuclicked == 0) {
topmenuclicked = 1;
} else {
topmenuclicked = 0;
window.location.href = $(this).attr('href');
}
});
It's a bit messy and not the best way to solve this, but my main problem is with selecting only the a elements that have a submenu.
With the code as it is now I have to click all parent menu links twice and I'm not sure why.
So I need to be able to say something like $("#menu > li:has(ul) a) but I don't believe that works.
Use children("ul").length of li element
$("#menu > li a").click(function(event){
//use $(this).parent().children("ul").length
if($(this).closest("li").children("ul").length) {
event.preventDefault();
// the clicked on <li> has a <ul> as a direct child
}
if (topmenuclicked == 0) {
topmenuclicked = 1;
} else {
topmenuclicked = 0;
window.location.href = $(this).attr('href');
}
});
the previous answer won't work, cause submenu is not inside of A tag, but the rest is good.
Here is how can you fix it:
$('#menu > li a').on('click', function (event) {
if ($(this).next('ul').length) {
event.preventDefault();
// Parent link clicked
} else {
// Nested link clicked
// The ELSE part can be removed if custom logic is not needed
}
});
Another option can be:
$('#menu > li > a').on('click', function (event) {
event.preventDefault();
// Parent link clicked
});
$('#menu > ul a').on('click', function (event) {
// Nested link clicked
});
You can use parents for this. Also, use .on instead of .click
$('#menu').on('click', 'li a', function(event){
event.preventDefault();
var topmenuclicked = 0;
if($(this).parents('ul').length == 1) {
topmenuclicked = 1;
}
console.log('topmenuclicked -> ', topmenuclicked)
// do your stuff here
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul id="menu">
<li>
Parent menu ▼
<ul>
<li>Submenu link</li>
<li>Submenu link</li>
<li>Submenu link</li>
</ul>
</li>
<li>
Parent menu link
</li>
</ul>
put > before a. See below
var topmenuclicked == 0;
$("#menu > li > a").click(function(event){
event.preventDefault();
if (topmenuclicked == 0) {
topmenuclicked = 1;
} else {
topmenuclicked = 0;
window.location.href = $(this).attr('href');
}
});
In part because of #Love-Kesh his solution I came up with this that seems to be working.
$("#menu > li a").click(function(event){
// save parent in variable
var clickedlinkparent = $(this).parent();
// check if parent has any ul element as children
if (clickedlinkparent.children('ul').length) {
// prevent the link from opening
event.preventDefault();
// if link has not been clicked, do nothing
if (topmenuclicked == 0) {
topmenuclicked = 1;
// if link has already been clicked, go to href
} else {
topmenuclicked = 0;
window.location.href = $(this).attr('href');
}
}
});
So this mostly works, however, the only URL that works is what is specified as "Blog." All the anchor references with # are smooth scrolling on click but all my external links on my page aren't doing anything.
Can I write the prevent default in a way that only includes the href links with "#" in them? I have image links, etc throughout my page and want a simple method to manage it rather than pointing each url out.
<ul class="snip1143">
<li class>Home</li>
<li>About</li>
<li>Work</li>
<li>Blog </li
<li>Contact</li>
<script>
$(document).on('click', 'a', function(event) {
if($(this).data('hover') !== "Blog"){
event.preventDefault();
$('html, body').animate({
scrollTop: $( $.attr(this, 'href') ).offset().top
}, 500);
});
</script>
var doc = document;
var myList = doc.getElementsByClassName("snip1143")[0];
var myListItems = myList.children;
var isHash = false;
var href;
for (var i = 0; i < myListItems.length; i++) {
href = myListItems[i].firstChild.getAttribute('href');
isHash = href.includes("#");
if(!isHash){
myListItems[i].firstChild.addEventListener('click', function(evt) {
event.preventDefault();
});
myListItems[i].classList.add("strike");
}
}
.strike{
text-decoration: line-through;
}
<ul class="snip1143">
<li>Home</li>
<li>About</li>
<li>Work</li>
<li>Blog </li>
<li>Contact</li>
</ul>
Coded directly on SO, I hope I got it right:
$(document).on('click', 'a', function(e) {
if ($(this).attr('href').indexOf('#') !== -1)
e.preventDefault();
};
How can I get the browser to remember which tab the user was viewing when the page is refreshed or revisited ?
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#home" role="tab" aria-controls="home">Home</a>
Profile
Messages
Settings
<div class="tab-content">
<div class="tab-pane active" id="home" role="tabpanel">...</div>
<div class="tab-pane" id="profile" role="tabpanel">...</div>
<div class="tab-pane" id="messages" role="tabpanel">...</div>
<div class="tab-pane" id="settings" role="tabpanel">...</div>
</div>
This did the trick for me..
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var hash = $(e.target).attr('href');
if (history.pushState) {
history.pushState(null, null, hash);
} else {
location.hash = hash;
}
});
var hash = window.location.hash;
if (hash) {
$('.nav-link[href="' + hash + '"]').tab('show');
}
Creates sharable links using the URL hash.
This is the multiple tabs example :
$('a[data-toggle="tab"]').on('click', function (e) {
var theTabId = $(this).attr('href');
var activeTabs = (window.localStorage.getItem('activeTab') ? window.localStorage.getItem('activeTab').split(',') : []);
var $sameLevelTabs = $(e.target).parents('.nav-tabs').find('[data-toggle="tab"]');
$.each($sameLevelTabs, function (index, element) {
var tabId = $(element).attr('href');
if(theTabId != tabId && activeTabs.indexOf(tabId) !== -1){
activeTabs.splice(activeTabs.indexOf(tabId), 1);
}
});
//unique tabs
if (activeTabs.indexOf($(e.target).attr('href')) === -1) {
activeTabs.push($(e.target).attr('href'));
}
window.localStorage.setItem('activeTab', activeTabs.join(','));
});
var activeTabs = window.localStorage.getItem('activeTab');
if (activeTabs) {
var activeTabs = (window.localStorage.getItem('activeTab') ? window.localStorage.getItem('activeTab').split(',') : []);
$.each(activeTabs, function (index, element) {
$('[data-toggle="tab"][href="' + element + '"]').tab('show');
});
}
Here's one way you could do it. Obviously, this won't quite work since the snippet is on stackoverflow.com and the hash won't be appended to the url. I tested this locally though and it works.
Note: This will only work if you refresh the page or otherwise use the specific URL that refers to the tab to be opened. If you want it to "remember" the tab after you close the browser/tab or whatever, you would probably be best off using cookies or perhaps storing it in a database if you are dealing with client sessions.
//When the page loads, get the current # value and mark the li as "active" if the href attribute matches.
$(document).ready(function() {
var v = "#" + window.location.hash.substr(1);
$("#myTab li").each(function() {
var href = $(this).children().first().attr("href");
if (href == v) $(this).addClass("active");
else $(this).removeClass("active");
});
});
//Whenever we click on a li, remove all "active" classes and finally add "active" to the one we clicked.
$("#myTab li").on("click", function() {
$("#myTab li").each(function() {
$(this).removeClass("active");
});
$(this).addClass("active");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<ul class="nav nav-tabs" id="myTab">
<li>Home</li>
<li>Profile</li>
<li>Messages</li>
<li>Settings</li>
</ul>
If you want to save a value for after refresh, You can use cookie or sessionStorage (as said in comments). The easier is sessionStorage i think.
$('.tab-pane').click(function(){
sessionStorage.setItem("clicked", $(this).attr('id'));
});
And after page refresh, you can retrieve the saved value:
if(sessionStorage.getItem("clicked") != null)
var clickeId = sessionStorage.getItem("clicked")
I used local storage to store the active-tab-id and it works for me.
$('a[data-toggle="tab"]').on("click", function(e) {
localStorage.setItem("active-tab-id", $(e.target).attr("href"));
});
var activeTabId = localStorage.getItem("active-tab-id");
var activeTab = $(`a[href="${activeTabId}"]`);
if(activeTab.length == 1)
activeTab.tab("show");
else
$('a[data-toggle="tab"]')[0].click();
if your tab is not activated, by default it's clicked on the first tab.
Following is my HTML,
<div class="container">
<ul class="navbar">
<li class="nb-link"><a>Home</a></li>
<li class="dropdown">
<a>CBSE</a>
<ul class="dropdown-menu">
<li>10th Standard</li>
<li>12th Standard</li>
</ul>
</li>
<li class="dropdown">
<a>Engineering</a>
<ul class="dropdown-menu">
<li>JEE - Main</li>
<li>JEE - Advanced</li>
</ul>
</li>
</ul>
I have 2 dropdowns . When I click one, it comes down. But when I click another, even that comes down without closing the previous one . This creates an overlap. The way I'm handling this using JS is as follows
$(document).ready(function() {
$('.dropdown').click(function() {
var $this = $(this);
if ($this.children('.dropdown-menu').hasClass('open')) {
$this.removeClass('active');
$('.navbar').$this.children('.dropdown-menu').removeClass('open');
$this.children('.dropdown-menu').fadeOut("fast");
}
else {
$this.addClass('active');
$this.children('.dropdown-menu').addClass('open');
$this.children('.dropdown-menu').fadeIn("fast");
}
});
});
How can I achieve a functionality using JS such that the previous dropdown closes when I click a new dropdown ? Also, the dropdowns should close when anywhere on the page is clicked ?
can try this
$(document).ready(function() {
$('.dropdown').click(function() {
var $this = $(this);
$('.dropdown').not($this).removeClass('active')
$('.dropdown-menu').not($this.find('.dropdown-menu')).removeClass('open');
$this.toggleClass('active');
$this.find('.dropdown-menu').toggleClass('open');
});
});
Working Demo
this is a function you can use if selectors is not target
// function for if selectors not target
function actionwindowclick(e , selector , action){
if (!$(selector).is(e.target) // if the target of the click isn't the container...
&& $(selector).has(e.target).length === 0) // ... nor a descendant of the container
{
action();
}
}
and you can use it in window click event like this
$(window).on('click', function(e){
actionwindowclick(e , ".dropdown , .dropdown-menu" , function(){
$('.dropdown').removeClass('active')
$('.dropdown-menu').removeClass('open');
});
});
Working Demo
Note: I think you may need to
event.stopPropagation()
while you trying to click on .dropdown-menu itself
$('.dropdown-menu').click(function(e) {
e.stopPropagation()
});
Try:
$(document).ready(function() {
$('.dropdown').click(function() {
var $this = $(this);
$this.children('.dropdown-menu').toggleClass('open');
if ($this.children('.dropdown-menu').hasClass('open')) {
$this.removeClass('active');
$this.children('.dropdown-menu').fadeOut("fast");
}
else {
$this.addClass('active');
$this.children('.dropdown-menu').fadeIn("fast");
}
});
});
I've implemented with success a Vertical jScrollPane with tabs
I'm trying to make a tab show up by default.
Can I do this by simulating a click on the link with the id #default ? If so, how?
The code is identical to the on that site. Here's the javascript:
$(function()
{
// Create the "tabs"
$('.tabs').each(
function()
{
var currentTab, ul = $(this);
$(this).find('a').each(
function(i)
{
var a = $(this).bind(
'click',
function()
{
if (currentTab) {
ul.find('a.active').removeClass('active');
$(currentTab).hide();
}
currentTab = $(this).addClass('active')
.attr('href');
$(currentTab).show().jScrollPane();
return false;
}
);
$(a.attr('href')).hide();
}
);
}
);
});
Here's the html code:
<ul class="tabs">
<li>Pane 1</li>
<li>Pane 2</li>
<li>Pane 3</li>
</ul>
Thank you!
Does this not work as expected, after it's initialized?
$('#default').click()