Why does jQuery, outputs same rel each time? - javascript

so basically here is my script:
http://jsfiddle.net/JJFap/42/
Code -
jQuery(document).ready(function() {
var rel = new Array();
var count = 0;
jQuery(".setting").each(function() {
rel[count] = [];
if(jQuery("span").attr("rel")) {
rel[count].push(jQuery("span").attr("rel"));
}
console.log(count);
count++;
});
jQuery("body").text(rel);
console.log(rel);
});​
and
<div class="setting">
<span rel="Variable">Variable</span>
<span rel="Item">Item</span>
<span rel="Something">Something</span>
</div>
<div>
<span rel="Smth">Smth</span>
<span>Sec</span>
</div>
<div class="setting">
<span>Second</span>
<span rel="first">First</span>
<span rel="Third">Third</span>
</div>
​my question, is why does it display Variable, variable?
I would like it to display Variable, First, but I'm not able to do.
Basically what I would like to achieve is create new array, in which insert each div.setting span elements with rel attribute array.
So basically in this example it should output -
Array (
Array[0] => "Variable","Item","Something";
Array[1] => "first","Third";
)
Hope you understood what I meant :)
EDIT:
In my other example I tried to add jQuery("span").each(function() ... inside first each function, but it outputted two full arrays of all span elements with rel. I can't have different classes / ids for each div element, since all will have same class.

jQuery('span') is going to find ALL spans in your page, and then pull out the rel attribute of the first one. Since you don't provide a context for that span search, you'll always get the same #1 span in the document.

You should be using this:
jQuery('span',this).each(function() {
rel[count] = [];
if (jQuery(this).attr("rel")) {
rel[count].push(jQuery(this).attr("rel"));
}
console.log(count);
count++;
})
instead of this:
rel[count] = [];
if(jQuery("span").attr("rel")) {
rel[count].push(jQuery("span").attr("rel"));
}
console.log(count);
count++;
http://jsfiddle.net/mblase75/JJFap/52/
The trick is to use a second .each to loop over all the span tags inside each <div class="setting"> -- your original code was using jQuery("span"), which would just grab the first span tag in the document every time.

In addition to what has been said, you can also get rid of the count and one push() when using jQuery.fn.map() as well as getting rid of the if when adding [rel] to the selector:
jQuery(document).ready(function() {
var rel = [];
jQuery(".setting").each(function() {
rel.push(jQuery(this).find('span[rel]').map(function() {
return this.getAttribute('rel');
}).get());
});
jQuery("body").text(rel);
console.log(rel);
});

Within the .each() method, you have this code a couple times: jQuery("span").attr("rel"). That code simply looks for ALL span tags on the page. When you stick it inside the .push() method, it's just going to push the value for the rel attribute of the first jQuery object in the collection. Instead, you want to do something like $(this).find('span'). This will cause it to look for any span tags that are descendants of the current .setting element that the .each() method is iterating over.

Related

Count multiple div class in same page

I am trying to make a correct and incorrect question counter that shows groups of 4.
If I click on the first correct answer the counter works correctly and increases as I click, but it does not work with the second correct answer. The same happens with the wrong answers
This is the codes that I use, anyone could help me? Thx
HTML CODE:
¿Which of the following operations results in 8?
<input class="solucioncorrecta" value="6+2">
<input class="solucioncorrecta" value="7+1">
<input class="solucionincorrecta" value="1+1">
<input class="solucionincorrecta" value="2+2">
And the JS CODE:
<!-- CONTADOR FALLOS TEST -->
<script type="text/javascript">
var root = document.querySelector('.solucionincorrecta');
root.onclick = function() {
var elem = document.getElementById('contadorfallos');
elem.innerHTML = +elem.innerText + 1;
};
</script>
<!-- CONTADOR FALLOS TEST -->
<!-- CONTADOR ACIERTOS TEST -->
<script type="text/javascript">
var root = document.querySelector('.solucioncorrecta');
root.onclick = function() {
var elem = document.getElementById('contadoraciertos');
elem.innerHTML = +elem.innerText + 1;
};
</script>
The issue is that you are using document.querySelector() and not document.querySelectorAll()
document.querySelector() Returns the first match
document.querySelectorAll() Returns all matches
As a result, you are only setting an onclick property on the first .correcta and .incorrecta elements, not all of them.
To set this on all of them, you need to do two things:
You need use document.querySelectorAll() instead of document.querySelector(). This returns a list (specifically, a NodeList) of matching elements.
Loop over the items in your list, and attach onclick handlers to each of them. There are many ways to loop over a NodeList, listed here.
Here is an example:
// get all incorrect elements
var incorrectElements = document.querySelectorAll('.incorrecta');
// loop over each elements
for (var element of incorrectElements) {
// add an onclick
element.onclick = incorrectClickHandler
}
// this is the function being called by onclick
function incorrectClickHandler() {
score.innerText = parseInt(score.innerText) - 1;
}
It would be better if you upload your full codes. But anyway I write you some notes that probably answer your question.
-dont use the same name (root) for your .correcta and .incorrecta
-in your second <script>, you didnt defined button as an object . So browser cant understand it.

How to delete current element if previous element is empty in jquery?

I want to delete element with class "tehnicneinfo" but only if the element I'm checking ( with class "h2size") has no child. I have a bunch of those elements, generated by a plugin and I want to delete only the ones that have the next element without child. I wrote jquery code, but it delets all of my elements, not only the ones that have the next element without child. Here is my jquery code:
$('.news .h2size > div').each(function() {
var ul = $(this).find('ul');
if(!ul.length) $(this).remove();
var h1 = $('.news').find('.tehnicneinfo');
var h2size = $('.news').find('.h2size');
if(h2size.prev().is(':empty'))
{
h1.remove();
}
});
this code is inside $(document).ready(function(). Can you tell me what I'm doing wrong? The code is for something else also, so I'm having truble only from var h1 = $('.news').find('.tehnicneinfo'); this line on. Thanks in advance!
Html:
<div class="news">
<h1 class="tehnicneinfo">xxx</h1>
<div class="h2size">
<div id="xyxyxy">
.......
</div>
</div>
<h1 class="tehnicneinfo">yyy</h1>
<div class="h2size"></div>
....
</div>
That's the html, only that there is like 20 more lines that are the same, but with different values (not yyy and xxx). I would need to delete all 'yyy' (they are not all with same value).
You can use filter to filter the ones you want to remove then remove them
"I want to delete only the ones that have the next element without child"
$('.tehnicneinfo').filter(function(){
return !$(this).next().children().length;
// only ones with next sibling with no children
}).remove();
JSFIDDLE

jQuery: Target all elements with val less than 1

I have multiple elements in the dom with a class of .blockbadge if the value of any .block-badge is 0 then I want to add a class to that element in order to style it differently.
My JS adds the class to all of these elements if anyone of them equal 0. How do I make it only affect those elements which equal zero?
HTML
<span class="block-badge">1</span>
<span class="block-badge">0</span> // this element should have the class 'zero' added
<span class="block-badge">4</span>
JS
var blockBadgeVal = $('.block-badge').val();
if (blockBadgeVal < 0) {
$('.block-badge').addClass('zero');
}
The code in the OP will not work because $('.block-badge').html() will return the html of the first element with class block-badge so in this case return string 1, you should parse the returned value then compare it with the 0.
You could use filter() method instead.
Description: Reduce the set of matched elements to those that match the selector or pass the function's test.
$('.block-badge').filter(function(){
return parseInt($(this).text())==0;
}).addClass('zero');
Hope this helps.
$('.block-badge').filter(function(){
return parseInt($(this).text())==0;
}).addClass('zero');
.zero{
color: red;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="block-badge">1</span>
<span class="block-badge">0</span>
<span class="block-badge">4</span>
Like this
$('.block-badge').each(function(){
if(parseInt($(this).html()) ===0){
$(this).addClass('zero');
}
});
You could use the jQuery :contains selector for that specific markup
$('.block-badge:contains(0)').addClass('zero');
it won't work if any other elements contains a zero, like 10, 101 etc. so if you need only 0, use a filter
FIDDLE
Try using .text(function(index, originalText) {}) where this is current element within collection , originalHtml is current textContent
$(document).ready(function() {
$(".block-badge").text(function(index, originalText) {
if (originalText <= 0) {
$(this).addClass("zero");
}
return originalText
});
});
jsfiddle https://jsfiddle.net/s2g3zpwr/3/

Get All Parents Info Up Until Specified Parent

I have this html codes example:
<html>
<body>
<div>
<div id="stophere">
<h4 class="parentclass">
<span class="target">Clicked</span>
</h4>
</div>
</div>
</body>
</html>
From the html codes example above, I want to get all parents' tag name of class target (when receiving click event) down from div with id stophere.
I tried this code:
$(ev.target).parents()
.map(function() {
return this.tagName;
})
.get()
.join( ", " );
But it includes all parents' tag names above stophere. While the result I want is only 1 div and 1 h4.
What is the correct way to get all parents of target down from stophere?
You can use the parentsUntil method for that
$(ev.target).parentsUntil($('#stophere').parent())
Note that it's non-inclusive, so we pass the parent of #stophere to include that element as well
FIDDLE
I don't claim that this is a good solution, but can be used if adeneo's solution is failed in your situation like in my case.
This code is checking whether the traversing limit is containing that limit line itself or not, by using find() method:
jQuery('html').on("click", function (ev) {
var elemparentid = jQuery(ev.target).closest("[id]").attr("id");
var thisparents = jQuery(ev.target).parents()
.map(function () {
// check if traversing limit is a children of current element or not, by using find() method
if (jQuery(this).find("#" + elemparentid).length < 1) {
return this.tagName;
}
}).get()
.join(", ");
alert(thisparents);
});
FIDDLE

jquery, how to use nextAll() with css scope

HTML:
<div class="my_1"></div>
<div class="my_big">
<div class="small" id="id_1"></div>
<div class="small" id="id_2"></div>
<div class="small" id="id_3"></div>
<div class="small" id="id_4"></div>
</div>
javascript:
var css_scope=$(".my_big");
var next_div=$(".my_1").nextAll('.small',css_scope).first();
console.log(" \n next div = "+ next_div.attr('id'));
console shows undefined. But if I exclude the my_big div from html and define var next_div in javascript as follows:
var next_div=$(".my_1").nextAll('.small').first();,
expected output is obtained.
How to make nextAll() work with the mentioned css scoping ?
.nextAll is used to find all the next siblings, you should find the .small from the result of nextAll.
var next_div=$(".my_1").nextAll('.my_big').find('.small').first();
You cannot get to .small from my_1 using nextAll() since they are not siblings. You can get to it using the following selector.
// Get the first element matching ".small" inside an element matching ".my_big"
// that comes immediately after an element matching ".my_1"
var next_div = $('.my_1 + .my_big > .small:first')​;
Check this demo: http://jsfiddle.net/q6XKR/
If you want to access the first element in my_big div, there's no need to bring my_1 into the scene.
var next_div = $('.my_big').find('.small').first();
console.log(" \n next div = "+ next_div.attr('id'));
Hope it clarifies you somewhat about traversing elements in jQuery.

Categories