Piece of jQuery code to enable class selector? - javascript

I am not using jQuery, but I have one line of code that enables the $ selector shortcut, as follows:
let $ = function (id) { return document.getElementById(id); }
I would like to also add whatever code necessary so that I can use the class selector shortcut as well.
Right now I have this:
let $c = function (cl) { return document.getElementsByClassName(cl); }
And I can select elements by class with $c("some-class"), but that returns a list that I need to then cycle through.
I would like to be able to use stuff like $(".some-class").remove("some-class") - to remove the class from all elements that have it without having to have a loop cycle through the list and remove them one by one.
Could anyone point me toward the part of jQuery that does that so I can include it and not the entire library?
I tried looking through the jQuery code for the term className but there are 39 instances and I'm not sure which part I need.

The closest thing native JS has to jQuery's sizzle selector engine is querySelector() or querySelectorAll(), depending on whether you're expecting a single element to be found, or multiple.
In your example, this would be:
let $ = selector => document.querySelectorAll(selector);

Related

When in JS you need to identify element by array order?

Ok so I finally have a code example to show this!
if ($('#Snowsports-row')[0].classList.contains("hidden") == false) {
$('#snowsports-only').removeClass("hidden")
}
The code works ONLY as written above, i.e., if the [0] were moved to the second line and removed from the first line, or if it were present/absent in both lines, it would fail.
I understand the output difference...
$('#Snowsports-row')
=> [<div>...]
$('#Snowsports-row')[0]
=> <div>...
...but I'm not understanding under what circumstances you're OK to get an array of element(s) and in which you need to tease out the exact element.
THANKS FOR ALL ANSWERS! Very clearly helped me to figure out that the problem may have been confusing JS/jQuery methods. Final version:
if ($('#Snowsports-row').hasClass("hidden") == false) {
$('#snowsports-only').removeClass("hidden")
}
The .classList method is not widely supported (not in MSIE 9.0 for example) so it's not portable, although where it exists it's fast.
Since every ID in a document is supposed to be unique, and since calling removeClass for a class that isn't present is harmless, just replace your entire call with:
$('#Snowsports-row').removeClass('hidden')
Or better yet, if that class means what I think it does, use .hide() and let jQuery do its job for you, potentially animation the transition in the process.
Alternatively, if you actually wanted to stick with using DOM and classList, you should use the .remove() method that classList already supports:
document.getElementById('#Snowsports-row').classList.remove('hidden')
although there's a minor disadvantage in that this code will crash if that element isn't found (since .getElementById will return null) whereas jQuery silently ignores calls made on empty selectors.
As for the meta-question - you use [n] if you want to access the single DOM element at position n within the jQuery object, as you've done when you use .classList.
You use .eq(n) to obtain a jQuery object representing that DOM element, e.g. if you want to apply jQuery methods to that (single) element.
If there's only a single element, or you want the jQuery method to apply to every matching element, just call the method directly on the selector, as I've done above.
First off, by using jQuery for what it's good at, you can replace this:
if ($('#Snowsports-row')[0].classList.contains("hidden") == false) {
$('#snowsports-only').removeClass("hidden")
}
with this:
$('#Snowsports-row').removeClass("hidden");
Your first block of code does the following:
With $('#Snowsports-row'), make a jQuery object that contains all DOM elements that match the select '#Snowsports-row'.
Then reach into the jQuery object with [0] and get the first DOM object in that jQuery object.
Then, use a property/method on that DOM element to determine if a class exists on that DOM element with your .classList.contains("hidden") reference.
Then, if you find that class, remove it.
A jQuery object contains inside it an array of DOM elements. If you call a method on the jQuery object itself like:
$('.tableRows').html("hello");
Then, you are asking jQuery to operate on ALL the DOM elements inside the jQuery object. You must use jQuery methods, not DOM methods.
If, on the other hand, you want to use a method such as .classList.contains(), that is only a method on an actual DOM element. That isn't a jQuery method. So, you have to reach inside of the jQuery object to get a specific DOM element out of it. That's what the [0] does. It reaches into the jQuery object and gets the first DOM element from its internal data structure. Once you have that DOM element, you can then use any DOM element methods on that DOM object.
FYI, if you ever want to get just the first DOM element from a jQuery object, but want the result to be a jQuery object, not just a DOM element, instead of [0], you can use .eq(0) like ths:
$('#Snowsports-row').eq(0).removeClass("hidden");
Now, in this specific case, this is never necessary because $('#Snowsports-row') cannot ever contain more than one DOM element because internally jQuery will only return the first matching DOM element when you are searching for a ID value (since there's never supposed to be more than one matching element with the same ID).
Just keep in mind that DOM element and a jQuery object are completely different types of objects with different methods on them. What makes it slightly confusing is that a jQuery object contains an internal list of DOM elements. But, if the object you are operating on is a jQuery object, then you can only call jQuery methods on it. If you reach into the jQuery object and pull out a DOM element, then you can only call DOM methods on it.
First of all, ids must be unique, so if you have more than one #Snowsports-only elements you can experience problems.
In your question, you are mixing jQuery code with pure Javascript code.
This:
if ($('#Snowsports-row')[0].classList.contains("hidden") {
...
}
Means that you get the first instance of #Snowsports-row (remember that is better if there is only one element with this id), but you get the DOM object (pure javascript) with the jQuery selector. You can do the same thing in jQuery like this:
$('#Snowsports-row').hasClass("hidden")
See more:
https://api.jquery.com/hasclass/
https://developer.mozilla.org/es/docs/Web/API/Element/classList
Sure, because you are operating over a list. Now, you're kind of mistaking the jQuery/javascript code. If you would like to use the same line twice you can basically drop jQuery altogether and write something like this:
var el = document.getElementById('Snowsports-row');
if (el.classList.contains('hidden')){
el.classList.remove('hidden');
}
In the first line you're selecting one specific DOM element, whereas in the second line you are selecting ALL elements in the DOM that fit that selector and removing the "hidden" class from all of them. Basically checking whether the element has a class can only be performed over an element (that's why you need to select the index, specifying a given element), but jQuery allows you to remove the class of every element inside a list (hence your second line)
Use jQuery's .eq() function. So:
var el = $('#Snowsports-row').eq(0);
if (el.hasClass("hidden")) {
$(el.removeClass("hidden")
}
There's also no harm in calling removeClass on an element that might not have that class... so:
$('#Snowsports-row').eq(0).removeClass('hidden');

TypeError getElementsByTagName is not a function issue

I'm having trouble getting to the source of this problem. Basically the error message I am getting in my console is:
TypeError: $(...).getElementsByTagName is not a function
When I click through to the line it is occuring on it is here:
var inputs = $('directoryresults').getElementsByTagName('input');
I'm not sure why this is happening as I have included jQuery in the header of the page itself:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.0/jquery-ui.min.js"></script>
Does anyone have any ideas what might be causing this?
Does anyone have any ideas what might be causing this?
The object returned by the jQuery constructor doesn't have the .getElementsByTagName() method.
$('selector') returns a jQuery object. .getElementsByTagName() is a native JavaScript method of DOM elements.
To look for elements with a certain tagname using the jQuery object you currently have:
var inputs = $('directoryresults input');
// OR
var inputs = $('directoryresults').find('input');
To get a like-for-like node list that .getElementsByTagName() would return (note this isn't exactly the same, this will return an array where .getElementsByTagName() will return a HTMLCollection):
var inputs = $('directoryresults input').get();
Note: directoryresults, I am assuming, is either a class or id of a DOM element. Either way you'll want to amend the selector above
getElementsByTagName is a method you will find on Element and Document objects.
$('directoryresults') will return a jQuery object (containing any <directoryresult> elements … so nothing if you are working on an HTML document).
to use getElementsByTagName, you need to extract the elements from the jQuery object:
$('directoryresults')[0].getElementsByTagName
The above will only get the first element from the jQuery object (and it assumes that there will be at least one element) so you should probably replace the hard coded [0] with a for loop.
That said, you should generally use the find method instead:
$('directoryresults').find('input')
… or just use a descendant combinator in the first place:
$('directoryresults input')
As noted earlier, directoryresults won't find anything in a valid HTML document. You probably want to prefix it with . or # depending on what you are actually trying to match.
You are ussing a DOM API mixed with jQuery API sintax:
it's document.getElementsByTagName('input');
The first error is not specific if directoryresults is a class or an ID
Nor do you tell if a target item or the item you wish to call
If you use jQuery by TagName type this:
var inputs = $('input');
if you want put values in a div
$.each(inputs, function(){
$('div').append( $(this).val() );
});

Select ALL elements with specific data attribute Javascript?

With jquery, I've got the following code:
$('a[data-hello]').click(function(){ = That select all "a" elements with "data-hello".
I'm trying to make this with raw Javascript. I stop here:
document.querySelectorAll("data-hello").onclick = function() {
(btw, theres a way to select all the A elements with data-hello and not all with data-hello? o.O)
But querySelectorAll returns a Array. Because of this, it only works if I determine a position. This way:
document.querySelectorAll("data-hello")[5].onclick = function() {
But I want ALL ELEMENTS, not specific elements, like with jQuery. I cant use jQuery.
It is so simple with Jquery :( I must make a "for" to wade through all the positions in JS? Is this necessary? sorry I do not understand...
What I want to do:
I want to get the data attribute value of the element that is clicked. I use this for this inside the function and, then, I applied another function that add a class in a specific element.
Basically, there is buttons with classes in data attribute value. This classes will be applied to a specific element.
Put the array (actually a NodeList) of elements in a variable and loop through them to set the event handler on each of them. That's what the jQuery methods do to apply something to all elements in a jQuery object. There is no way around the loop, with jQuery it's just hidden within the methods. You can use the same selector syntax as in jQuery with querySelectorAll.
var arr = document.querySelectorAll("a[data-hello]");
var f = function() {
// do something
};
for (var i = 0; i < arr.length; i++) {
arr[i].onclick = f;
}
querySelectorAll accepts a string of comma-separated CSS selectors, just like jQuery, so you can give it the same string: 'a[data-hello]'.
The difference between native and jQuery that you are running into is in calling methods on the elements returned. jQuery returns a jQuery object, which has methods that often loop over all the elements, .click() being one such methods. You need to replicate that with the array of elements that querySelectorAll is returning by looping over the array and applying the same handler to each element's onclick property.
Try this:
var myElements = document.querySelectorAll("a[data-hello]");
Array.prototype.forEach.call(myElements, function (element) {
element.onclick = function () {
// Your onclick handler code goes here.
console.log('clicked', element);
};
});
as simple as that:
var dataElems = document.querySelectorAll("[data-hello]")
for (var i=0;i<dataElems.length;i++) {
dataElems[i].onclick = function(i,v) {
alert(this.innerHTML)
}
}
example http://jsfiddle.net/acrashik/W86k8/

Return jQuery object (instead of DOM) from jQuery array using index

I have a jQuery array of <span>s and I'd like to get just one of them as a jQuery object so that I can string additional methods on it. Something like $mySpans[2] (which returns a string), or $mySpans.get(2), (which returns the DOM element directly).
I know that this will work:
$($mySpans[2]).someJQueryMethod( ... );
...but it seems a little redundant. What is the right way to do this?
Like this:
$myspans.eq(2).method();
jsFiddle Demo
You are going to want to use eq. Note that it will return the jQuery object wrapped element at that index, so if you only have one match you should use 0 (which follows that 2 will return the third of the set).
var $thirdMatch = $mySpans.eq(2);//== jQuery object with third match
var htmlElement = $thirdMatch[0];//== actual dom element
var matchedHtml = $thirdMatch.html();// call some jQuery API method
It is common practice when storing jQuery objects to use a $variableName for readability purposes.

Strange ie behaviour with jquery inArray

Hello this seems to be working on IE8 :
var clsName = link.parents("div.fixed_column").attr("class").split(" ");
if($.inArray("column_one", clsName)
While this one reports error (Object expected errror in jquery).
var clsName = link.parents("div.fixed_column").attr("class");
What is the right way to do this? I thought purpose of inArray was that jquery will handle cross browser issues.
Unfortunately, this is indirectly answering your question, but... You seem to be looking to detect if an element has a class, and since you're already using jQuery, just use the hasClass method - http://api.jquery.com/hasClass/
For your specific code, try:
if (link.parents("div.fixed_column").hasClass("column_one")) {
// It has the "column_one" class
}
The more immediate answer to your question is that link.parents("div.fixed_column").attr("class") returns a single string. When the jQuery selector (div.fixed_column) returns multiple elements, which is very possible when using classes, using jQuery methods that get information (like .attr, using one parameter...to "get" the value) return the first matched element's value only.
So say the selector matches 3 elements:
["<div id='div30' class='fixed_column div30_class'></div>",
"<div id='div2' class='fixed_column div2_class'></div>",
"<div id='div17' class='fixed_column div17_class'></div>"]
Then the value returned from .attr("class") will be: fixed_column div30_class because it's the first matched element.
I'm not sure, but I think you're expecting jQuery to return an array of all the matched elements' values, which it just doesn't. So that doesn't mean jQuery isn't handling cross-browser issues, it just means you need to look up what the method does/returns.
I could've sworn that jQuery 2.0 has options for doing what you want - directly from calling the getters (or something similar), but I can't find it anymore :( Maybe I'm remembering incorrectly. Anyways, you could easily use $.each and/or $.map to look at every matched element, but it depends on what you were really trying to do with it.
You can't read the attributes of multiple elements into an array with .attr("class"). But why don't you just target the desired class in the selector like this?
var cols = link.parents("div.fixed_column.column_one");
Then change your conditional to check for an empty set:
if(cols.length) { ...

Categories