I have the following code:
jQuery(document).ready(function($) {
$("ul.accordion-section-content li[id*='layers-builder'] button.add-new-widget").click(function() {
$("#available-widgets-list div:not([id*='layers-widget'])").css('display','none');
});
});
The idea is, when i click a button that contains the class "layers-builder", all divs in "available-widgets-list" that DO NOT contain the class "layers-widget" are hidden.
The problem I'm facing is that using this code also hides all the divs inside "layers-widget" (as not all of them have "layers-widget" in the id.
for example, here is a mockup markup:
<div id="some-id">
...
</div>
<div id="this-layers-widget-89">
<div id="hello"></div>
<div id="yes"></div>
</div>
In the above example, the first div "some-id" would be hidden, along with all the child divs inside "this-layers-widget-89"
How can I make it so that all the content within the div containing "layers-widget" still shows?
The ">" operator specifies that the div must be a direct child of #available-widgets-list:
$("#available-widgets-list > div:not([id*='layers-widget'])").css('display','none');
You should add a class instead of relying on finding parts of some-id but this will work also work: $('[id*="some-id"]');
You should also be using jquery's built in hide()method instead of css('display', 'none'). They do literally the exact same thing but using the built in methods is more readable.
Related
I'm making a turn-based game in javascript. I want to move the player from div to div. I have put all those divs in a section and then into an array using queryselectorall. Now my problem is that I also have another divs who I want to use and I can't select them separately. Can anyone tell me how to select only some divs? I have seen something like section>div to differentiate them, but that doesn't work for me.
I have tried replacing div with span on rollDice, zar1, and zar2, but by doing that some CSS breaks.
~
<div class="rollDice">Roll the dice</div>
<div class="zar1">
<img src="poze/dice-5.png" alt="Dice" class="dice" id="dice-1" style="width:150px">
</div>
<div class="zar2">
<img src="poze/dice-5.png" alt="Dice" class="dice2" id="dice-2" style="width:150px">
</div>
<section class="mutari">
<div class="nr1 mutabil"><h1>1</h1></div>
<div class="nr2 mutabil"><h1>2</h1></div>
<div class="nr3 mutabil"><h1>3</h1></div>
</section>
~
I want to select the div only from the section. And after that I want to select the first 3 divs.
What you are looking for is:
document.querySelectorAll('section > div:nth-child(-n+3)')
section (a type selector) finds your <section>. If you had more section elements, you could use section.mutari to be more precise (using a class selector).
> div selects all the <div> tags that are direct children of that section. > is a child combinator.
:nth-child(-n+3), a pseudo-class, restricts this to only select the first three elements, not all of them. It is not needed in your example, as you only have three divs; but if you had more, this would give you only the first three.
With document.body.childNodes
Just replace document.body with your HTML Element.
You can filter after that through the list you get an select all divs.
If you want to get all divs you can also use following:
var dh = document.body.getElementsByTagName('div');
Get all div nodes:
Use document.body.getElementsByTagName('div')
Or
Get filtered div nodes:
Take array from document.body.childNodes.
filter by using for loop and if condition.
Condition Example: use like node[i].nodeName and node[i].id
On a web page we have a list of profiles. On the right hand side of the profile is some text, followed by an arrow img#arrow.
When img#arrow is clicked, we have the following jQuery we hope to run:
However, the corresponding .bottom-sec is not toggling.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent +' .bottom-sec').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec" style="display: none;">
<p>Initially hidden text.</p>
</div>
<img id="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
Problem
The problem with your code is exactly what the comment on your question is saying, but he didn't explain anything:
You're combining two different ways of selecting elements. One is with selectors, the other is traversing. You're using them in a way which isn't possible (the $parent + ' .bottom-sec' part). The comment linked to a jQuery page about traversing which you should definitely read! It tells you a lot about how to use traversing functions, which you could use!
Solution
There are multiple solutions to this, but I'll write down the one I think is the best:
First of all, change the HTML a bit. I've removed the element style of .bottom-sec and changed the id of the image to a class, because you have multiple images with the same id on the page, which is not a recommended thing to do. Classes can occur more than once, id's cannot.
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec">
<p>Initially hidden text.</p>
</div>
<img class="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
I've reduced the JavaScript to the following. Note that is just reduced to one line, where a click on the .arrow element goes searching for the closest .profile-right parent. If, for whatever reason, you decide to change the HTML and the .arrow element is no longer a child of the .profile-right, this code still works. The only thing it does is toggle an active class on the .profile-right.
jQuery(document).on('ready', function() {
jQuery('.arrow').on('click', function(){
jQuery(this).closest('.profile-right').toggleClass('active');
});
});
The document ready listener was added because of OP's comment.
With CSS, we can use the new .active class to show or hide the element.
.profile-right .bottom-sec {
display: none
}
.profile-right.active .bottom-sec {
display: block
}
Original Code Fix
If for some reason you wanted to use your original code, this is how it should be:
// Nothing wrong about this part.
// Your only worry should be that there could be
// multiple elements with the same ID, which is something really bad.
jQuery('#arrow').click(function(){
// This part is correct, no worries
var $parent = $(this).parent();
// Removed the $(...), because $parent is already a jQuery object
$parent.addClass('active');
// Changed the selector to a find function
$parent.find('.bottom-sec').toggle();
});
You could also combine all of the code inside the listener function to just one line:
jQuery('#arrow').click(function(){
$(this).parent().addClass('active').find('.bottom-sec').toggle();
});
Change your js code like below.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent).find('.bottom-sec').toggle();
});
In your event listener you can catch the element (the down arrow) that triggered the event. It will be referred as this.
Then you can go through the DOM tree using .next() and .parent() to access the <div> to toggle.
Note: you may need more functions than the one I explained above.
Note 2: without code or more detailed information, we can't help you further, I will edit this answer if you add details.
I've used this exact code on a different div element and it works perfectly. When I went to add the same code to another div element with a different id it registers the element has been clicked but it doesn't add or remove any of the classes.
$('#quoteClick').click(function(){
$('#cbox-1').addClass('displayCboxBackground');
$('#cbox-2').removeClass('displayCboxBackground');
$('#cbox-3').removeClass('displayCboxBackground');
$('#dbox-1').addClass('displayBlock');
$('#dbox-2').removeClass('displayBlock');
$('#dbox-3').removeClass('displayBlock');
console.log("clicked");
});
The html structure is as follows:
<div id="cbox-1">
<div id="dbox-1">
content...
</div>
</div>
<div id="cbox-2">
<div id="dbox-2">
content...
</div>
</div>
<div id="cbox-3">
<div id="dbox-3">
<div id="quoteClick">
a quote
</div>
</div>
</div>
JSFiddle: https://jsfiddle.net/m81c23cx/1/
In the fiddle you can see the content will changes when each header is clicked. When the "quoteClick" element is clicked I want it to change to the second headers content exactly how it does when the second header is clicked.
I can see in Chrome's console that when I click the div element that it highlights all the classes but it doesn't change any of them. I have the jQuery inside a document.ready() function so it should be waiting for the DOM to load and it works perfectly when I just write the lines into the console.
I'm surprised that nobody actually questioned your use of ids (instead of suggesting that you should double-check for dupes). The reason why this code is hard to debug is because it's too complicated. As a result, you'll have a hard time fixing issues similar to this in the future too.
Drop it, do it better.
I didn't even go through your fiddle. Instead, I'm going to propose that you change your approach altogether.
Update your HTML and use classes instead of ids. Something similar to this:
<div class="cbox">
<div class="dbox">
content...
</div>
</div>
<div class="cbox">
<div class="dbox">
content...
</div>
</div>
<div class="cbox">
<div class="dbox">
<div id="quoteAdvert">
a quote
</div>
</div>
</div>
Update your JavaScript and use this to get the context of the current box:
$('.cbox').click( function cboxClicked () {
// Remove the previous class from all .cbox & .dbox elements; we don't care which
$('.cbox').removeClass('displayCboxBackground')
$('.dbox').removeClass('displayBlock')
// Add a new class to the clicked .cbox & it's child .dbox
$(this).addClass('displayCboxBackground')
$(this).children('.dbox').addClass('displayBlock')
})
The beauty of this? You can have 1000 boxes, it'll still work. No need to add any extra lines of code.
Here's a fiddle showing it in action.
The example code you provided is not consistent with the jsfiddle you created.
In your fiddle, you use the jquery selector $('#quoteClick') but there is no element with that id. There is a #quoteAdvert element however. Change that and you'll see the click in the console.
The classList property returns a token list of the class attribute of the element in question. Luckily for us, it also comes with a few handy methods:
add - adds a class
remove - removes a class
toggle - toggles a class
contains - checks if a class exists
// adds class "foo" to el
el.classList.add("foo");
// removes class "bar" from el
el.classList.remove("bar");
// toggles the class "foo"
el.classList.toggle("foo");
// outputs "true" to console if el contains "foo", "false" if not
console.log( el.classList.contains("foo") );
// add multiple classes to el
el.classList.add( "foo", "bar" );
I have dynamically generated content which I'm outputting using two divs:
<div id="data1">Some info</div> -- <div id="data2">different info</div>
I want to only show "data2" in certain instances, so I'm trying to use JavaScript to hide it when it's not needed. Basically, my code is:
var getDivs = document.getElementById('data2');
IF STATEMENT {
getDivs.style.display='none'; }
However, this is only kind of working - it's hiding the very first div that it comes across, but it's not hiding ALL of the divs with that ID.
This means that my code is basically correct - the IF STATEMENT is working, the display='none' DOES hide something, it's just not hiding everything that it should...
I tried to change it from div id= to div class= and instead use document.getElementByClassName('data2') but that doesn't seem to be working at all - it doesn't even hide the first .
What am I missing / doing wrong? What do I need to change to get this to hide all of the divs that are "data2"?
Thanks!
Your code seems fine. You can see it works: http://js.do/code/zeek
Later Edit:
Using class instead of id:
<div id="data1">Some info</div> --
<div class="data2">different info</div>
<div class="data2">different info</div>
<div class="data2">different info</div>
<script type="text/javascript">
var getDivs = document.getElementsByClassName('data2');
for(var i= 0; i< getDivs.length; i++){
var div = getDivs[i];
div.style.display='none';
}
</script>
Use jQuery and select by class instead of by ID. See http://api.jquery.com/class-selector.
jQuery is not only easy and readable, you'll also not write getElementByClassName instead of getElementsByClassName.
$('#data2').hide();
This assumes jQuery is on your page: http://api.jquery.com/
Note: You're going to have problems if this is dynamic and there are several elements with the ID of data2. Instead, use classes for selecting relevant divs if you can help it.
I have a function here for centering an element within it's parent.
Check out the demo: http://jsfiddle.net/kE9xW/1/
right now it's only applying the centering to the first element, how do i make the function loop itself so it centers every #element on the page. the demo is self explanatory, thanks!
There are a few things you need to do.
As already suggested, id's must be unique, so change the id="..." to class="...". You will also need to change your css to be based on the class not the id (change #element' to '.element')
<div class="container">
<p> ... </p>
<div class="element">
</div>
</div>
Use each in your method to loop over all elements selected by the selector $('.element').
element.each(function(){
// work here in $(this) for the current element
});
You forgot to take the top of the parent div into account, which made all elements overlap each other. So your yPas becomes:
var yPos = $(this).parent().position().top +
parseInt($(this).parent().css('height'))/2 -
parseInt($(this).css('height'))/2 - yPosFromCenter;
Check the working fiddle: http://jsfiddle.net/H99DT/
First, the easiest but most important part: change your IDs to classes. IDs must be unique per page so jQuery's ID selector and JavaScript's document.getElementById() function are only going to give you the first matching element:
Each id value must be used only once within a document. If more than one element has been assigned the same ID, queries that use that ID will only select the first matched element in the DOM.
Change
<div id="container">
...
<div id="element">
to
<div class="container">
...
<div class="element">
and change
$('#element')
to
$('.element')
Next, the more difficult part: you are currently issuing one centerDiv() call to your elements with coordinates from center of 0, 0. That's going to take all your .elements and position them at the exact same spot.
If that's not what you intend, you're going to have to loop through them using .each() and decide the xPosFromCenter and yPosFromCenter in each iteration. It's not clear to me yet how your function works so you may have to explore on your own and see what you can come up with.
Scratch that, see Jamiec's working example for the solution.
Change Id to class in you divs, then make container's position relative with css, and I'll suggest make jQuery plugin from your function. See results http://jsfiddle.net/kE9xW/1/