.find is not working - javascript

hi this is my problem im currently looping all the selected element using jquery selector and tried to use .find(Selector) of jquery but i think its not working or is it possible to find an element using this code
for (var i = 0; i < $('.MainElement').find('.ItemGroup').length; i++) {
var CurrentSelectedGroup = $('.MainElement').find('.ItemGroup')[i].find('span');
}
I debugged this code and its returning a unavailable but when i tried to jquery select the element manually its working is it possible to do this??
i need to select the span inside the current element inside the loop
I have searched in google i didnt find any

Though eq() as given below works, a better approach will be is to use .each() for iteration, as you are running your selector multiple times in your script
$('.MainElement').find('.ItemGroup').each(function(){
var CurrentSelectedGroup = $(this).find('span');
})
or at the least cache the value of your selector and then reuse it in your loop

use eq()
var CurrentSelectedGroup = $('.MainElement').find('.ItemGroup').eq(i).find('span');
NOTE: $('.MainElement').find('.ItemGroup')[i] will return javascript object not jquery

Try this as it's much cleaner:
$('.MainElement').find('.ItemGroup').each(function() {
var CurrentSelectedGroup = $(this).find('span');
});

Related

JavaScript - Find ID that matches data attribute value

I have a variable that finds the data attribute of an element that is clicked on in a callback function:
var dropdown = document.getElementsByClassName('js-dropdown');
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", callBack (dropdown[i]));
}
function callBack (i) {
return function () {
var thisDropdown = i.getAttribute('data-dropdown');
//rest of the code here
}
}
I am basically trying to do this
$('#' + thisDropdown ).toggleClass('is-active');
...but in vanilla JS.
This works fine using jQuery however I would like a vanilla version.
So when a user clicks on an element that activates a drop down, I want it to dynamically find its relevant ID matching value within the document so it can toggle a show/hide class.
I've searched through a lot of SO questions and everyone replies with a jQuery answer which is not what I am looking for.
I've been trying to do something along the lines of
var idValue = document.getElementById(thisDropdown);
Then
var findId= idValue + thisDropdown;
findId.toggleClass('is-active');
Obviously that does not work the same way the jQuery statement works... any ideas?
Ignore the toggleClass method! Some of you may find this contradictory as I want vanilla JS.
To replace $('#' + thisDropdown ).toggleClass('is-active'); with plain js, use Element.classList. Like this:
const someElement = document.querySelector('#' + thisDropdown);
someElement.classList.toggle("is-active");
I like #kamyl's answer, but you might need backward compatibility. For that, see if you can find a polyfill.
If you have to write it yourself, use string.split(" ") to get your list of active attributes and iterate to find if it exists; add if not, remove if so...then array.join(" ") and replace the class attribute with it.

Traversing elements in javaScript

I need to change the href of link in a box. I can only use native javaScript. Somehow I have problems traversing through the elements in order to match the correct <a> tag.
Since all the a tags inside this container are identical except for their href value, I need to use this value to get a match.
So far I have tried with this:
var box = document.getElementsByClassName('ic-Login-confirmation__content');
var terms = box.querySelectorAll('a');
if (typeof(box) != 'undefined' && box != null) {
for (var i = 0; i < terms.length; i++) {
if (terms[i].href.toLowerCase() == 'http://www.myweb.net/2/') {
terms[i].setAttribute('href', 'http://newlink.com');
}
}
}
However, I keep getting "Uncaught TypeError: box.querySelectorAll is not a function". What do I need to do in order to make this work?
Jsfiddle here.
The beauty of querySelectorAll is you dont need to traverse like that - just use
var terms = document.querySelectorAll('.ic-Login-confirmation__content a');
And then iterate those. Updated fiddle: https://jsfiddle.net/4y6k8g4g/2/
In fact, this whole thing can be much simpler
var terms = document.querySelectorAll('.ic-Login-confirmation__content a[href="http://www.myweb.net/2/"]');
if(terms.length){
terms[0].setAttribute('href', 'http://newlink.com');
}
Live example: https://jsfiddle.net/4y6k8g4g/4/
Try This:
var box = document.getElementsByClassName('ic-Login-confirmation__content')[0];
Since you are using getElementsByClassName ,it will return an array of elements.
The getElementsByClassName method returns returns a collection of all elements in the document with the specified class name, as a NodeList object.
You need to specify it as follows for this instance:
document.getElementsByClassName('ic-Login-confirmation__content')[0]
This will ensure that you are accessing the correct node in your HTML. If you console.log the box variable in your example you will see an array returned.
you can select by href attr with querySelector,
try this:
document.querySelector('a[href="http://www.myweb.net/2/"]')
instead of defining the exact href attribute you can simplify it even more :
document.querySelector('a[href?="myweb.net/2/"]'
matches only elments with href attribute that end with "myweb.net/2/"

GetElementById Alternative for more options

Okay, I am new to JavaScript, so I really need help with this.
I have a script, which looks like this:
function Change(){
var image = document.getElementById('id-img');
image.src = "somenotimportantlink" + document.getElementById('id-a1').title;
var link = document.getElementById('id-a2');
link.href="somenotimportantlink"+(document.getElementById('id-a1').title)+"/index.html";
}
My problem is that there are multiple tags that want to use this function on, but I can only use id="id-a1" on one tag, so I need an alternative for getElementById, one that would allow me to use multiple tags.
If you really need to select the elements by id, you can use querySelectorAll.
document.querySelectorAll("[id*='id-a']") will match all elements with an id containing 'id-a'
document.querySelectorAll("[id^='id-a']") matches all elements with an id starting with 'id-a'.
However, I'd consider using a class instead of an id:
document.querySelectorAll('.someClass')
Make sure to use querySelectorAll instead of querySelector to get all the matching elements.
More info on MDN
There's various ways in js to get elements, but if your want to use css selectors then you can use document.querySelectorAll(".myclass");
EDIT: sorry I goofed... use querySelectorAll
Most people use jQuery to do this, but you can also do it in JavaScript. The catch is, it only works on modern browsers.
JavaScript Method
You would need to grab a NodeList of all the objects with a query selector and iterate over every item of that NodeList.
function myStuff() {
var nodeList = document.querySelectorAll('.a');
for (var i = 0, length = nodeList.length; i < length; i++) {
nodeList[i].href = "somenotimportantlink"+(i.title)+"/index.html";
}
}
jQuery Method
First you'd want to have jQuery somewhere in your HTML, I prefer using a CDN but a normal file is alright.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
Once you have the jQuery file ready, you can select all classes by:
$('.a')
or if you want to select all <a> tags:
$('a')

Use a Selector instead of "this" in Jquery

Maybe it's a silly question. But I really can't understand it.
I'm using the Jquery Cycle2. And after some personalization I got a simple problem.
I need to know what is the "Index" of my current slide.
On the plugin's website a found this line of code that perfectly works.
$('#cycle-1 .cycle-slide').click(function(){
var index = $('#cycle-1').data('cycle.API').getSlideIndex(this);
alert(index);
});
It gives me the right index. But I'm trying to catch this Index when another element is clicked. So I can't use the parameter (this).
Then I tried this.
$('.anotherelement').click(function(){
var mycycle = $('#cycle-1 .cycle-slide');
var index = $('#cycle-1').data('cycle.API').getSlideIndex($(mycycle));
alert(index);
});
It doesn't return my current slide index. It returns "-1". Does anyone knows how I should pass the Object (selector) as a parameter to the getSlideIndex() ?
Thanks a lot :D
You can use $('.cycle-slideshow').data('cycle.opts').currSlide to get the current slide index
$('.anotherelement').click(function(){
var index = $('.cycle-slideshow').data('cycle.opts').currSlide;
var currSliderNum = index+1;
alert(currSliderNum);
return false;
});
FIDDLE
In the first piece of code this is a DOM element and not a jquery object. Try this instead:
var index = $('#cycle-1').data('cycle.API').getSlideIndex(mycycle[0]);
However, presumably, you have multiple .cycle-slide elements. This will just get the first one. In your first code you have access to a single one since only one was clicked. You need to decide which one you want to target here.

Select tags that starts with "x-" in jQuery

How can I select nodes that begin with a "x-" tag name, here is an hierarchy DOM tree example:
<div>
<x-tab>
<div></div>
<div>
<x-map></x-map>
</div>
</x-tab>
</div>
<x-footer></x-footer>
jQuery does not allow me to query $('x-*'), is there any way that I could achieve this?
The below is just working fine. Though I am not sure about performance as I am using regex.
$('body *').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
Working fiddle
PS: In above sample, I am considering body tag as parent element.
UPDATE :
After checking Mohamed Meligy's post, It seems regex is faster than string manipulation in this condition. and It could become more faster (or same) if we use find. Something like this:
$('body').find('*').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
UPDATE 2:
If you want to search in document then you can do the below which is fastest:
$(Array.prototype.slice.call(document.all)).filter(function () {
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
There is no native way to do this, it has worst performance, so, just do it yourself.
Example:
var results = $("div").find("*").filter(function(){
return /^x\-/i.test(this.nodeName);
});
Full example:
http://jsfiddle.net/6b8YY/3/
Notes: (Updated, see comments)
If you are wondering why I use this way for checking tag name, see:
JavaScript: case-insensitive search
and see comments as well.
Also, if you are wondering about the find method instead of adding to selector, since selectors are matched from right not from left, it may be better to separate the selector. I could also do this:
$("*", $("div")). Preferably though instead of just div add an ID or something to it so that parent match is quick.
In the comments you'll find a proof that it's not faster. This applies to very simple documents though I believe, where the cost of creating a jQuery object is higher than the cost of searching all DOM elements. In realistic page sizes though this will not be the case.
Update:
I also really like Teifi's answer. You can do it in one place and then reuse it everywhere. For example, let me mix my way with his:
// In some shared libraries location:
$.extend($.expr[':'], {
x : function(e) {
return /^x\-/i.test(this.nodeName);
}
});
// Then you can use it like:
$(function(){
// One way
var results = $("div").find(":x");
// But even nicer, you can mix with other selectors
// Say you want to get <a> tags directly inside x-* tags inside <section>
var anchors = $("section :x > a");
// Another example to show the power, say using a class name with it:
var highlightedResults = $(":x.highlight");
// Note I made the CSS class right most to be matched first for speed
});
It's the same performance hit, but more convenient API.
It might not be efficient, but consider it as a last option if you do not get any answer.
Try adding a custom attribute to these tags. What i mean is when you add a tag for eg. <x-tag>, add a custom attribute with it and assign it the same value as the tag, so the html looks like <x-tag CustAttr="x-tag">.
Now to get tags starting with x-, you can use the following jQuery code:
$("[CustAttr^=x-]")
and you will get all the tags that start with x-
custom jquery selector
jQuery(function($) {
$.extend($.expr[':'], {
X : function(e) {
return /^x-/i.test(e.tagName);
}
});
});
than, use $(":X") or $("*:X") to select your nodes.
Although this does not answer the question directly it could provide a solution, by "defining" the tags in the selector you can get all of that type?
$('x-tab, x-map, x-footer')
Workaround: if you want this thing more than once, it might be a lot more efficient to add a class based on the tag - which you only do once at the beginning, and then you filter for the tag the trivial way.
What I mean is,
function addTagMarks() {
// call when the document is ready, or when you have new tags
var prefix = "tag--"; // choose a prefix that avoids collision
var newbies = $("*").not("[class^='"+prefix+"']"); // skip what's done already
newbies.each(function() {
var tagName = $(this).prop("tagName").toLowerCase();
$(this).addClass(prefix + tagName);
});
}
After this, you can do a $("[class^='tag--x-']") or the same thing with querySelectorAll and it will be reasonably fast.
See if this works!
function getXNodes() {
var regex = /x-/, i = 0, totalnodes = [];
while (i !== document.all.length) {
if (regex.test(document.all[i].nodeName)) {
totalnodes.push(document.all[i]);
}
i++;
}
return totalnodes;
}
Demo Fiddle
var i=0;
for(i=0; i< document.all.length; i++){
if(document.all[i].nodeName.toLowerCase().indexOf('x-') !== -1){
$(document.all[i].nodeName.toLowerCase()).addClass('test');
}
}
Try this
var test = $('[x-]');
if(test)
alert('eureka!');
Basically jQuery selector works like CSS selector.
Read jQuery selector API here.

Categories