I actually have a list of item, that open each a diffrent menu, thanks to an href (the #mat for example display a menu)
<div class ="row d-none d-lg-block classer no-gutters ">
<h4>Order by
<a class = "navigation" href="#mat" id="navMat" >localisation</a> /
<a class = "navigation" href="#new" id="navNew" >new</a>
and this jquery, to underline the current active item (ex : localisation)
jQuery( document ).ready(function() {
jQuery('.navigation').on('click', function(e){
jQuery('.navigation').removeClass('navigationU');
this.className = 'navigationU navigation';
})
});
The problem is that i would like this href to underline the current active item, to open the menu, but it scrolls to it and i don't want it.
I already tried e.preventDefault(); but i disable everything : the scroll, but also the underline and the display of the menu.
Do you have any idea ?
Thanks
Try this:
$(document).on('click', '[href^="#"]', function(e) {
location.hash = e.target.hash;
e.preventDefault();
});
it will disable all links that start with # and recreated updating the hash in address bar.
Related
So I was trying to find a Vue Solution of the jQuery SlideUp() and slideDown() functionality. And I have run into a problem while creating the same for my Side Bar Menu Open and Close funtion. See my code below:
UPDATE: Here's the stackblitz link to the problem: https://stackblitz.com/edit/vue-lvjxmz
I'd really appreciate if someone helps me to solve this problem. Thanks.
export default {
mounted() {
let hasSubmenu = Array.from(document.querySelectorAll(".hasSubmenu.close"));//Select all hasSubmenu
let self = this;
hasSubmenu.forEach(function (el) {//Show Hide Submenu Based On Clicks
el.addEventListener("click", self.menuOpen.bind(this, el));
});
},
methods:{
//Menu Opener Function
menuOpen(el){
let ul = el.querySelector("ul");
ul.style.height = `${ul.scrollHeight}px`;
el.classList.remove("close");//Remove The Class "close"
el.classList.add("open");// add the class "open"
this.menuClose();//Call this function to close the menu
},
//Menu Closer Function
menuClose(){
console.log(document.querySelector(".hasSubmenu.open"));//Log the Selected Element
document.querySelector(".hasSubmenu.open").addEventListener("click", function (e) {
e.currentTarget.querySelector("ul").style.height = "0px";
e.currentTarget.classList.remove("open");
e.currentTarget.classList.add("close");
});
}
},
}
<ul id="main-nav">
<li class="hasSubmenu close">
<div> Main Menu One</div>
<ul style="height: 0px">
<li>
Sub Menu One
</li>
<li>
Sub Menu Three
</li>
</ul>
</li>
</ul>
So what we are doing here is: we are first selecting all the hasSubmenu items with the class close has in it. Then firing the click event where the menu opens and replace the class close with "open". Then we are calling the menuClose function where we are selecting the element which has the .open class. then firing another click event when the menu closes and removes the class .open and adds .close again.
The problem is somehow the menuClose function keeps selecting the element as if it was pointing to the hasSubmenu element and caching it in, it doesn't matter whether the class has been changed or not. I mean, even after the .open class has been removed on the click event it stills selecting it and thus clicking on the menuItem after the first 2 clicks the menuOpen function first opens the menu then calls the menuClose function and immediately closes the menu again although menuClose functionality only added to document.querySelector(".hasSubmenu.open"). As if, it first selected the element itself not the class and cached it in.
Okay, as per James Reply I have managed to solve the problem in another way. So the solution goes as below:
// Simply write one function and check if the submenu's
// height is 0px or not. Based on that write your
// open and close logics
menuOpenClose(el){
let ul = el.querySelector("ul");
let getHeight = ul.style.height;
console.dir(getHeight);
if (getHeight == '0px' || !getHeight.length) {
ul.style.height = `${ul.scrollHeight}px`;
el.classList.remove("close");
el.classList.add("open");
} else{
ul.style.height = `0px`;
el.classList.remove("open");
el.classList.add("close");
}
}
I have several items in my navigation bar, and a div next to it, ie:
<nav>
<a id="a"></a>
<a id="b"></a>
<a id="c"></a>
</nav>
<div id="menu-col"></div>
If the same link is clicked twice in a row, I want to hide #menu-col. If not, I want #menu-col to remain visible.
I'm not a javascript guy so I tried this:
var lastClicked;
$('nav a').on('click', function(e) {
alert(e.target.id + " - " + this.lastClicked);
if (e.target.id == this.lastClicked) {
$('#menu-col').hide();
this.lastClicked = '';
}
else {
$('#menu-col').show();
this.lastClicked = e.target.id;
}
});
Then I remembered that javascript assigns references, and not values. So when I did this.lastClicked = e.target.id; I'm assigning a reference to my element's id, then on the next click I make that e.target.id == ''.
In javascript, what would be the proper way of closing a box if the same link is clicked twice, and if not making sure the box is visible.
You can achieve this using toggleClass() to set a state class on the clicked a and also using toggle() on the .menu-col to show or hide it based on that state class. Try this:
$('nav a').click(function(e) {
e.preventDefault();
var $a = $(this);
$a.toggleClass('active').siblings().removeClass('active');
$('.menu-col').toggle($a.hasClass('active'));
});
.menu-col {
display: none;
}
.active {
color: #C00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<a id="a" href="#">a</a>
<a id="b" href="#">b</a>
<a id="c" href="#">c</a>
</nav>
<div class="menu-col">menu-col</div>
As long as you keep those ids unique across you app (which you should be doing anyway) the approach you've chosen isn't wrong. Any primitive in javascript is actually stored by value. Those primitives are string, number, boolean, and symbol. For more info see here https://developer.mozilla.org/en-US/docs/Glossary/Primitive
I would suggest something like this, you should have some kind of condition in which the div shows after it has been hidden.
$('nav a').dblclick(function(event) {
event.preventDefualt();
alert($(this).attr('id'));
$('#menu-col').toggle();
});
Something like that should be exactly what you are looking for, like I said though, there should be a condition in which it shows itself again, I made it a toggle so any double click on any 'nav a' element will cause it to show/hide the div.
Just for the sake of an option. Here is another way for double clicks(clicked twice in a row).
Using ondblclick event.
Double-click me.
I found some code that might work, but I can't decipher how to change it so it works with my current accordion structure.
Here is the fix I had found:
$(function () {
$(".tab-content").hide().first().show();
$(".inner-nav li:first").addClass("active");
$(".inner-nav a").on('click', function (e) {
e.preventDefault();
$(this).closest('li').addClass("active").siblings().removeClass("active");
$($(this).attr('href')).show().siblings('.tab-content').hide();
});
var hash = $.trim( window.location.hash );
if (hash) $('.inner-nav a[href$="'+hash+'"]').trigger('click');
});
and Here is part of the accordion on my page:
<div class="container">
<div class="accordion-trigger">
<h3>Wedding</h3>
</div>
<div class="accordion-container">
<p>
<tab>
<bgcolor class="shadow">
<font color="black" size="+1"><strong>Wedding Packages PDF</strong></font>
</bgcolor>
</tab>
</p>
<hr class="separator1">
</div>
Inside the div container are several other div class="accordion-trigger"'s that get activated when you click. Of course, only the first accordion is active on the page on load.
The fix above is supposed to check for a hash ID and do a Click event on the hash id.
Since you are using CSS you haven't provided, to open navigation:
$(function () {
var hash = parseInt($.trim(window.location.hash)), // hash as number
$triggers = $('.accordion-trigger'); // list of triggers
if (hash) { // if hash exists
if($triggers.length >= hash) { // if not greater than number of triggers
$triggers.eq(hash+1).trigger('click'); // open n-th item
}
}
});
example.com/site/#4 should open 4th item, if it exists.
That's terrible code, by the way.
I have three content boxes that i want to show and hide using controls.
The HTML is as follows:
<div id="leermat1">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
<div id="leermat2">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
<div id="leermat3">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
I have the two anchors pag-next and pag-prev that will control which of the content divs should be visible at any given point:
I want to write jquery such as, when #leermat1 'pag-next' is clicked, it hides #leermat1 and shows #leermat2. Then when #leermat1 is hidden and #leermat2 shows, when '.pag-next' is clicked, it hides #leermat2, and shows #leermat3.
Also the 'pag-prev' should work the same way.
I started with the following but dont know where to go from here.
$(document).ready(function() {
$('.pag-next').on('click',function() {
$('#leermat1').addClass('hide');
$('#leermat2').addClass('show');
});
});
One more thing is that the '.pag-next' should stop functioning after it has shown #leermat3.
You need this
$('[class^=pag-]').click(function() {
var elem = $('[id^=leermat]').filter(":visible"); // take the visible element
var num = Number(elem[0].id.match(/\d+$/)[0]); // take the number from it
var step = $(this).is('.pag-next') ? 1 : -1; // ternary operator
$('#leermat'+ (num + step)).show(); // show next or back
elem.hide(); // hide the visible element
});
Looks like in your anchor tag you have not given it a class.
Next
You then go on in your JQuery code to add a click function to a class which does not exist.
$('.pag-next').on('click',function()
Try adding class="pag-next" to your anchor tag.
This is what worked for me through a little trial and error. Although I am not sure if this is the most efficient solution.
$('#leermat1 .pag-next').on('click',function(){
$('#leermat1').addClass('hide');
$('#leermat1').removeClass('show');
$('#leermat3').addClass('hide');
$('#leermat3').remove('show');
$('#leermat2').addClass('show');
});
$('#leermat2 .pag-next').on('click',function(){
$('#leermat1').removeClass('show');
$('#leermat2').addClass('hide');
$('#leermat2').removeClass('show');
$('#leermat3').addClass('show');
});
$('#leermat2 .pag-prev').on('click',function(){
$('#leermat2').addClass('hide');
$('#leermat2').removeClass('show');
$('#leermat1').addClass('show');
$('#leermat3').removeClass('show');
});
$('#leermat3 .pag-prev').on('click',function(){
$('#leermat3').addClass('hide');
$('#leermat2').addClass('show');
$('#leermat1').addClass('hide');
$('#leermat3').removeClass('show');
$('#leermat1').removeClass('show');
});
I have created a 3 x 2 grid of squareish buttons that are monotone in colour. I have a slidetoggle div that pops down inbetween both rows of 3 and as it does so it pushes the content down of the rest of hte page, this is all working perfectly so far.
But i have made a class (.active) thats css is the same as the :hover state so that when i hover over a button the coloured version replaces the monotone version, however i have tried to add some js to make the colour (.active) stay on once i have clicked on a certain button so that you can see which button (product) the slidedown div relates to and the rest are still in monotone around it...
The .active code below works perfectly to turn the bottons colour on and off when you click that one button, but i have set it up so that if one button's div is open and you click on a different one, the open one closes and then the new one opens. This feature however throws off the balance of the code i have for the .active state here. When you have say button 1 open and you click button 1 to close, this works fine, the color goes on and then off, but if yo uhave button 1 open and click on button 2, button 1's div closes and opens button 2's div but then botton 1 stays in colour as button 2 turns to colour. the order is thrown off...
I need to add some js to say, that only one button can be in color (.active) at a time, or that if one is .active it must be turned off before the new one is turned on... Please help :)
$(document).ready(function(){
$("a.active").removeClass('active'); //<<this .active code &
$("#product1").click(function(){
if($(this).parent('a').hasClass('active')){ //<<<this .active code
$(this).parent('a').removeClass('active'); //<<
}else{ //<<
$(this).parent('a').addClass('active'); //<<
} //<<
$("#product2box").slideUp('slow', function() {
$("#product3box").slideUp('slow', function() {
$("#product4box").slideUp('slow', function() {
$("#product5box").slideUp('slow', function() {
$("#product6box").slideUp('slow', function() {
$("#product1box").stop().slideToggle(1000);
//do i need
//something here??
});
});
});
});
});
});
And here is the HTML
<div id="row1">
<a href="#!" class="active"><span id="product1">
<div id="productblueheader">
<div id="productlogosblue1"></div>
</div>
<div id="productstitle">Stops all spam and unwanted email.</div>
<div id="producttext">With over 8 million users ******* is the leading in anit-spam software on the market today! Sort all your spam issues in one place now!</div>
</span></a>
<a href="#!" class="active"><span id="product2">
<div id="productblueheader">
<div id="productlogosblue2"></div>
</div>
<div id="productstitle">The easiest email encryption ever.</div>
<div id="producttext">In todays world, we won’t enter personal details in to untrusted websites, but we send personal information via regular (insecure) email all the time.</div>
</span></a>
<a href="#!" class="active"><span id="product3">
<div id="productblueheader">
<div id="productlogosblue3"></div>
</div>
<div id="productstitle">The easiest email encryption ever.</div>
<div id="producttext">****** is a revelation in security and ease of use. Get the best protection against viruses, spyware, scam websites and other threats.</div>
</span></a>
</div>
(then the same for row2 products 4-6)
you use .each() method of jquery and find .active class to remove it,
and then add .active class.
$(this).parent('a').each(function(){
$(this).removeClass('active');
});
$(this).parent('a').addClass('active');
This ought to work, but I couldn't test it without the relevant HTML:
$(document).ready(function () {
$("#product1").click(function () {
$("a.active").removeClass('active');
$(this).parent('a').toggleClass('active'));
$("#product2box").slideUp('slow', function () {
$("#product3box").slideUp('slow', function () {
$("#product4box").slideUp('slow', function () {
$("#product5box").slideUp('slow', function () {
$("#product6box").slideUp('slow', function () {
$("#product1box").stop().slideToggle(1000);
});
});
});
});
});
});
});
Also, there would probably be a better way to write all those sliding up functions. Do they really need to go on by one by the way?
$(document).ready(function() {
$(".producthandler").click(function() {
var ctx = $(this);
var productboxId = ctx.children().eq(0).attr("id");
ctx.toggleClass('active');
$("#" + productboxId + "box").stop().slideToggle(1000);
$(".producthandler").each(function() {
var ctx = $(this);
var producthandlerId = ctx.children().eq(0).attr('id');
if (productboxId !== producthandlerId) {
ctx.removeClass('active');
$("#" + producthandlerId + "box").slideUp(1000);
}
});
});
});