I have a button, which when clicked I want to display two additional buttons Cancel and Confirm.
When o class is added a negative margin left is added and the button disappears.
$('.a_bttn_inner_action').click(function() {
if ($(this).children().find('.button')) {
$(this).parent().find('.button').queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).removeClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).removeClass('o');
next();
});
} else if ($(this).children().find('.confirm.no')) {
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.button').queue(function(next) {
$(this).removeClass('o');
next();
});
}
});
li.o {
margin-left: -800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bttn_inner_action">
<ul class="action">
<a href="#" class="a_bttn_inner_action">
<li class="button ">Do something...</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm no o">Cancel!</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm yes o">Confirm...</li>
</a>
</ul>
</div>
With the jQuery I have a problem here if($(this).children().find('.button')) and here else if($(this).children().find('.confirm.no')).
I want to detect which of the current element's children were selected by the class of the li element.
Is this possible?
I've tried if($(this).children().attr('class') == 'button') also doesn't work.
I believe this is what you are looking after. For checking children you can use
.find('.button').length
it will give back 0 or a positive integer so you can use it inside an if. In your code the first if was always true, so the other would never run.
$('.a_bttn_inner_action').click(function() {
if ($(this).find('.button').length) {
$(this).parent().find('.button').queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).removeClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).removeClass('o');
next();
});
} else if ($(this).find('.confirm.no').length) {
$(this).parent().find('.confirm.yes').delay(300).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.confirm.no').delay(100).queue(function(next) {
$(this).addClass('o');
next();
});
$(this).parent().find('.button').queue(function(next) {
$(this).removeClass('o');
next();
});
}
});
li.o {
margin-left: -800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="">
<ul class="action">
<a href="#" class="a_bttn_inner_action only-here">
<li class="button ">Do something...</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm no o">Cancel!</li>
</a>
<a href="#" class="a_bttn_inner_action">
<li class="confirm yes o">Confirm...</li>
</a>
</ul>
</div>
To simply know which button is clicked, you can use the target property of the click event to get the html element clicked =>
$('.elements').on('click', function(e){
var $targer = $(e.target);
});
You can use the hasClass() jQuery method on a jQuery element, or the is() method, to test the properties of an jQuery/html element.
I rewrite your code snippet keeping the logic, but changing some html. Look at the tests of the clicked element (target).
Your html is malformed, because children of a list ul must be an li element.
So your html should be something like this :
<div class="bttn_inner_action">
<ul class="action">
<li class="a_bttn_inner_action">
Do something...
</li>
<li class="a_bttn_inner_action">
Cancel!
</li>
<li class="a_bttn_inner_action">
Confirm...
</li>
</ul>
</div>
$('.button').click(function(e) {
var $target = $(e.target);
if ($target.hasClass('do-something')) {
$('.button.confirm.yes').delay(300).queue(function(next) {
$(this).parent('li').removeClass('o');
next();
});
$('.button.confirm.no').delay(100).queue(function(next) {
$(this).parent('li').removeClass('o');
next();
});
} else if ($target.is('.confirm.no')) {
$('.button.confirm.yes').delay(300).queue(function(next) {
$(this).parent('li').addClass('o');
next();
});
$('.button.confirm.no').delay(100).queue(function(next) {
$(this).parent('li').addClass('o');
next();
});
}
});
li.o {
margin-left: -800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bttn_inner_action">
<ul class="action">
<li class="li_bttn_inner_action">
Do something...
</li>
<li class="li_bttn_inner_action o">
Cancel!
</li>
<li class="li_bttn_inner_action o">
Confirm...
</li>
</ul>
</div>
The event listener can be optiomized. With $('.class').click() function, listener is attached to each .class elements. Use $('parentElement').on('click', 'subElement', function(e){...}) instead to attach just one event listener to a parent element.
See .on() function on jQuery doc.
You could just check the count of children with button class.
if ($(this).find('.button').length > 0) {
// there are some
}
children() gets all the direct child elements of the selected elements. find() gets all the child elements all the way down the hierarchy.
So $(this).children() is going to select all the <li> elements, and then find() is going to look through all of the child elements of those <li> and not at the <li> itself
What you want is just
$(this).find('.button').length
//or
$(this).find('.confirm.no').length
//or you could just find the li itself and then test for the class
var button = $(this).find('li');
if(button.is('.button')){
} else if(button.is(".confirm.no")){
}
Also note do not test against the return of children() or find() as both will return a new jQuery object wither or not anything was actually found, so the result will always test as truthy.
You could also just put the click handler on the LI themselves and not worry about the invalid wrapping them in an anchor tag
$('ul.action li').click(function() {
var $this = $(this);
if($this.is('.button')){
} else if($this.is('.confirm.no')){
}
});
The answer is the exists() function.
The following statement:
$(this).children().find('.button')
returns a JQuery object whose length is zero even there is no element selected.
So, if ($(this).children().find('.button')) is always going to be passed.
Either you can check the length of the return object or use JQuery exists() function.
Details are here.
Related
I have been searching for whole day and found several examples but none of them work correctly. I have a navigation bar and I want to keep class active after clicking on it and refreshing page but it gets lost.
This is my code:
HTML
<li class="sub-menu" style="border-bottom: 1px solid grey;">
<a class="menuItem active" href="#Url.Action("Index", "Administrator")">
<i class="fa fa-th"></i>
<span>Index</span>
</a>
</li>
<li class="sub-menu">
<a class="menuItem normal" href="#Url.Action("Products", "Administrator")">
<i class="fa fa-shopping-cart"></i>
<span>product</span>
</a>
</li>
Javascript
var retrievedObject = localStorage.getItem('classChange');
if (retrievedObject) {
$('.menuItem').addClass(retrievedObject)
}
$(".menuItem").click(function () {
if ($(this).hasClass("normal")) {
$(this).removeClass('normal').addClass('active');
localStorage.setItem('classChange', 'active');
} else {
$(this).removeClass('active').addClass('normal');
localStorage.setItem('classChange', 'normal');
}
});
I expected to change class on active after click but all classes change after click, I understand why it happens but don't know how to fix it.
Can you give each element an id value and, in the function, store in the local storage the id of the element and the class? Then, on reload check for the both id's?
And if you need for more elements you can save an array of the id's and then use it to loop between all id's if necessary.
So something like this:
var ids = ['id1','id2'];
for(i of ids) {
var retrievedObject = localStorage.getItem(i);
if (retrievedObject) {
var id = "#" + i;
$(id).addClass(retrievedObject);
}
}
$(".menuItem").click(function (event) {
if ($(this).hasClass("normal")) {
$(this).removeClass('normal').addClass('active');
localStorage.setItem('classChange', 'active');
} else {
$(this).removeClass('active').addClass('normal');
localStorage.setItem(event.target.id, 'normal');
}
});
The code
if (retrievedObject) {
$('.menuItem').addClass(retrievedObject)
}
should be wrapped on jQuery.ready().
So, I'm struggling here. I want to make an on click even that when I click on a navigation, it opens nested list and add class to parent list.
That part almost works, problem is that it adds that class to all elements from parent list.
<ul>
<li><div><p class="hidden">Test 1</p>
<ul class="shown">
<li>
<p>Inner 1</p>
</li>
</ul>
</div>
</li>
<li><div><p class="hidden">Test 2</p>
<ul class="shown">
<li>
<p>Inner 2</p>
</li>
</ul>
</div>
</li>
</ul>
<ul>
jque
$(document).ready(function () {
$('.shown').hide();
$('.hidden').click(function () {
var $answer = $(this).next('.shown');
if ($answer.is(':hidden')) {
$answer.show();
$('.hidden').addClass('color1');
} else {
$answer.hide();
$('.hidden').removeClass('color1');
}
});
});
css
.color1{
background:red;
}
jsfiddle
https://jsfiddle.net/Lc5n8k81/1/
here while adding and removing color1 class change $('.hidden') to $(this).. as $('.hidden') will add class to all element with .hidden class
Jsfiddle: https://jsfiddle.net/6moznpbr/
$(document).ready(function () {
$('.shown').hide();
$('.hidden').click(function () {
var $answer = $(this).next('.shown');
if ($answer.is(':hidden')) {
$answer.show();
$(this).addClass('color1');
} else {
$answer.hide();
$(this).removeClass('color1');
}
});
});
Inside your click handler, you want to refer to $(this) not $('.hidden') - the latter means all elements with class hidden:
$('.hidden').click(function () {
var $answer = $(this).next('.shown');
if ($answer.is(':hidden')) {
$answer.show();
$(this).addClass('color1');
} else {
$answer.hide();
$(this).removeClass('color1');
}
});
https://jsfiddle.net/Lc5n8k81/2/
I'm trying to show/hide an element on mouse click but it has to be the element that is clicked not just the class because multiple classes will exist on the page.
Heres what I've got;
<i class="fa fa-bars dropMenu">here</i>
<nav class="drop-down">
<ul>
<li class="active">Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Blog</li>
<li>Contact</li>
<li>Buy Now<span>5</span></li>
</ul>
</nav>
the javascript
$(".dropMenu").click(function(){
if ($(".drop-down",this).is(':visible')) {
$(".drop-down",this).hide();
} else if ($(".drop-down",this).is(':hidden')) {
$(".drop-down",this).show();
}
});
JSFiddle - http://jsfiddle.net/75yek8do/
You've not included jQuery and you're using <i> as a context but it is inline element and cannot have any elements inside it. So remove this, as the context.
$(".dropMenu").click(function() {
if ($(".drop-down").is(':visible')) {
$(".drop-down").hide();
} else if ($(".drop-down").is(':hidden')) {
$(".drop-down").show();
}
});
DEMO
But you can simply toggle it
$(".dropMenu").click(function(){
$('.drop-down').toggle();
});
If you must stick to your current markup and have many dropdowns :
$(".dropMenu").on('click', function(){
$(this).next('.drop-down').toggle();
});
Fiddle
Here you are http://jsfiddle.net/75yek8do/2/
You can have as many as you like items to click on (.dropMenu). It will search for the next occurrence of the .drop-down element and it will toggle its visibility.
$(".dropMenu").on('click', function () {
$(this).next(".drop-down").toggle();
});
I'm new to javascript and I wanted to create an event onclick to list items. The problem is that I want to create an event to the li tag, but it keeps firing when I click the descendent ul's.
Here goes part of my code:
<li id="1660761" class="HTMLFirstLevel HTMLHorizontalArrowDown">
<ul id="ul1223945" class="HTMLItem">
<li id="1490659" class="HTMLRemainingLevels"></li>
<li id="483463" class="HTMLRemainingLevels"></li>
<li id="80919" class="HTMLRemainingLevels"></li>
<li id="1280053" class="HTMLRemainingLevels"></li>
<li id="1799353" class="HTMLRemainingLevels"></li>
<li id="1882209" class="HTMLRemainingLevels"></li>
<li id="462917" class="HTMLRemainingLevels"></li>
</ul>
</li>
<li id= ......>
<ul....>
<ul...>
</li>
and my javascript:
var parentNode = document.getElementById('1660761');
parentNode.addEventListener("click",function(e) {
alert('Hi There');
});
}
Now I only want it to fire on the item li with the id 1660761, and not the items inside the list.
The list is an imported component and I can't create events inside the html, that's why I'm accessing it outside with javascript.
Now here's how I've done it by scaning the div by tag name and then adding a "click" event listener if the content equals the tag inner html that I was searching for.
I leave the rest of the html that it's important to this aproach:
<div id="MainMenu" class="HTMLMenuContainer HTMLMenuHorizontal">
<ul id="ul1351387" class="HTMLMenu">
<li id="1660761" class="HTMLFirstLevel HTMLHorizontalArrowDown">
<a href="#">
<span>Back Office</span>
</a>
<ul id="ul1172716" class="HTMLItem">
<li id="1490659" class="HTMLRemainingLevels">
<a href="#">
<span>
Some submenu Here
</span>
</a>
</li>
.....
and the code:
var divs = document.getElementsByClassName('HTMLMenuHorizontal');
var span = divs[0].getElementsByTagName('span');
//I iterate till 19 cause its more than all the spans in the page.
for(var i=0; i<20; i++) {
var sp= span[i];
if(sp.innerHTML==('Back Office')){
sp.addEventListener("click",function back(){
//do something here like
alert('Back Office');
});
}
}
This works fine and it doesn't fire on the itens inside.
This works because in my case the itens doesn't change the content, only the visibility.
I do the same for all the other itens that have descendents.
Thank you all.
Below is my jQuery code for this problem:
$(function(){
$("li.1660761").live("click", onListItemLink);
}
function onListItemLink(){
alert('Hello World!');
}
This one is for JavaScript:
var parentNode = document.getElementById('1660761');
parentNode.onclick = onListItemLink;
function onListItemLink(){
alert('Hello World!');
}
take a look at this page to undersand correctly:
capture event
and what's function(e-->??)
I hope it helps.
$('#1660761').unbind('click').click(function(e) {
if (e.target !== this) return;
alert('Hey There!');
});
Try This code : http://jsfiddle.net/sd5LZ/
I´m trying to target a <div> which is the next <li> of the parent <div> of the function show_projectinfo(). I've tried .next(), .closest(), etc... with no luck, any ideas?
The function is that if I click on a.more_info then the li.slider img is hidden... I don´t know if it is out of scope completely... This is a div that is repeated so I can´t just use the IDs.
markup:
<li class="info">
<a id="previous-slider"> < </a>
<span>01/15</span>
<a id="next-slider" href="javascript:void(0)"> > </a>
<a class="more_info" href="javascript:void(0)" onclick="show_projectinfo()">Info</a>
</li>
<li class="slider">
<img src="img/horizontal.jpg" alt="horizontal" width="624" height="429">
</li>
this is the script:
function show_projectinfo(){
$(this).closest('.slider img').hide();
$('.info_content').fadeIn();
}
The basic problem is that you are calling the method from onclick instead of binding it with jquery.
In the way you use it, the this refers to the window and not the element that was clicked.
function show_projectinfo(e){
e.preventDefault();
$(this).parent().next().find('img').hide();
$('.info_content').fadeIn();
}
$(function(){
$('.more_info').click(show_projectinfo);
});
and remove the onclick attribute from the html
If you have (although you shouldn't) to use the onclick attribute then pass it the this as an argument
function show_projectinfo(element){
$( element ).parent().next().find('img').hide();
$('.info_content').fadeIn();
}
and
<a class="more_info" href="javascript:void(0)" onclick="show_projectinfo(this)">Info</a>
Try:
$(this).parent().next() // parent() should be the <li> then next() will get your next <li>
$('.more_info').click(function(e){
e.preventDefault();
$(this).parent().next().find('img').hide();
$('.info_content').fadeIn();
});
Instead of .closest use .parent and .next, then select the img with .find.
Check out this jsFiddle:
$("a.more_info").bind("click", function(e){
e.preventDefault();
$(this).parent("li").next("li.slider").find("img").hide();
$('.info_content').fadeIn();
return false;
});
$('li').click( function (){
var nextLi = $(this).closest('div').next().children('li:first-child').attr('id');
console.log(nextLi);
});
Considering below markup:
<div id='div1'>
<li id='1'>1</li>
<li id='2'>2</li>
<li id='3'>3</li>
</div>
<div id='div2'>
<li id='4'>4</li>
<li id='5'>5</li>
<li id='6'>6</li>
</div>
You can see my live jsFiddle for more details.