I'm trying to figure out how to write an if statement that works something like this:
if (element contains class 1 && class 2) {
// do this
}
How do I write that if statement to check for multiple classes?
Is there a way to make the .contains method check for more than one class?
What I've found so far:
How to check class of multiple class elements in javascript, without jquery
Problem is, it seems to be returning an array of all the classes that the element contains, which is not what I want. I need the function to check if the element contains the classes that I am supplying it with.
One of the solutions looks to me like it's asking us to create our own function to do this, but is there a native method on JS which will do the trick?
I'm quite new to this stuff and I really appreciate the patience you guys have shown in answering my questions.
You can use the .matches() API on the element, and it's pretty well-supported now:
if (element.matches(".class1.class2")) ...
It's like a built-in version of jQuery .is().
Documentation link.
Put the class names you want to test for into an array, then use Array.prototype.every() to check if all members of your array exist in the element's classList:
console.log(['a', 'b'].every(e=>div.classList.contains(e)))
console.log(['a', 'b', 'c'].every(e=>div.classList.contains(e)))
<div class="a b" id="div"></div>
Unfortunately Element.classList is read-only, so you cannot add anything to its prototype. You can however do that on the Array.prototype:
Array.prototype.contains = function(...args) {
return [...args].every(c=>this.includes(c))
}
console.log([...div.classList].contains('a', 'b'))
console.log([...div.classList].contains('a', 'c'))
console.log([...div.classList].contains('a', 'c.d'))
<div class="a b c.d" id="div"></div>
Important: Please note that this violates the basic OOP rule Do not modify objects you don't own. As such, it would be better to create a named function taking the element and an array with a list of classes to test for.
There is a native API for the browser that lets you play with the DOM. jQuery is not always needed. https://www.w3schools.com/jsref/prop_element_classlist.asp.
You can use the 'classList.contains' method
document.getElementById({id}).classList.contains({class}) -- returns true or flase
Related
For example for the given jquery snippet, what should be the equivalent javascript. An equivalent add method in javascript can be helpful.
$("h1").add("span").add("h2");
As it clearly is mentioned in the jquery docs - .add() does not add any DOM element. https://api.jquery.com/add/ So using, .appendChild() does not serve the purpose here
The documentation at https://api.jquery.com/add says
"Given a jQuery object that represents a set of DOM elements, the
.add() method constructs a new jQuery object from the union of those
elements and the ones passed into the method. ".
This method doesn't perform any DOM operations, it's purely something for use to manipulate a jQuery object. So as far as I can see there would be no direct equivalent - if you don't use jQuery then by definition you can't create or manpiulate a jQuery object.
P.S. You can always examine the jQuery source code for the method to see what it does.
That would create a collection of all <h1>, <span> and <h2> in page
A collection of those same elements using vanilla js would be:
document.querySelectorAll('h1, span, h2')
My guess is you expect add() to do something different than this but without more details about your use case this would do what is shown in the question
Using the native DOM API only you'd have to do a little more:
let collection = [];
let h1 = document.querySelectorAll("h1")
let span = document.querySelectorAll("span")
let h2 = document.querySelectorAll("h2")
collection.push([...h1]);
collection.push([...span]);
collection.push([...h2]);
console.dir(collection);
<h1>Headline 1</h1>
<p>THis will not end up in the collection (except <span>this</span>)</p>
<h2>Headline 2</h2>
<span>This closes it out.</span>
There are quite a number of jQuery methods that accept functions instead of values as parameters. .append() is an example of that. Instead of writing:
something.append( '<div></div>' );
one might write:
something.append( () => '<div></div>' );
That's... nice. But I'm wrecking my mind trying to come up with a use case for this. Why would I want to do that? Does this enable something that would not otherwise be possible? Or does it at least drastically shorten or beautify certain bits of code?
Just to quickly add the purpose of this question: I'm writing a JS library that doesn't operate on HTML but still might as well have an API that's similar to jQuery's. So now I'm trying to figure out what to copy and what not to.
EDIT:
One use case is to index elements based on their position in the matched set. (Thanks to #Satpal and #JasonSmith!)
A second use case is to conditionally add content - as long as there's no condition that requires not to add content. (Thanks again to #JasonSmith)
Are there other practical use-cases? Does this get used often?
In .append(fn) method. With in the function, this refers to the current element in the set. which lets us to manipulate the content to be appended.
Here is an example.
$('p').append(function(){
return $(this).index();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p></p>
<p></p>
<p></p>
<p></p>
OR
$('p').append(function(){
return $(this).next('a');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p></p>1
<p></p>2
<p></p>3
<p></p>4
#Satpal provided an excellent example of one use case using the append function in jQuery. In more general terms, however, I look at it this way: if you are creating an API method capable of operating on a set of objects, then accepting a function as an argument for that API method allows the user to vary the behavior of the API according to the unique properties of each object in the set. For example, suppose we have a collection of elements like this:
<li>100</li>
<li>1000</li>
<li>150</li>
Suppose also that we have a hypothetical API method called myAPI.colorize(). If the colorize function accepts only a string, then all items in the set will be made the same color
mySet.colorize('red');
If, on the other hand the colorize method also accepts a function as an argument, then the developer can dynamically colorize without being required to break the set into constituent parts, like this:
mySet.colorize(function(currentElement) {
return currentElement.text == '1000' ? 'green' : 'red';
});
Or, if our hypothetical API binds the this reference the way jQuery does, then we could make our code even simpler:
mySet.colorize(function() {
return this.text == '1000' ? 'green' : 'red';
});
Of course this is a somewhat contrived example, but I believe it illustrates the design point in question without getting too stuck on a specific feature of jQuery.
function eegetdropdownvalue_str(ctl){return ctl.selectedIndex>=0&&ctl[ctl.selectedIndex]?ctl[ctl.selectedIndex].value:''}
The above function is called with
co.p1A10=eegetdropdownvalue_str(document.formc.p1A10);
I want to switch the call over to jQuery to drop the document.form reference however doing this
co.p1A10=eegetdropdownvalue_str($('p1A10'));
Does not reference the control correctly - How should I do this?
There's two things wrong with your code.
First, $('p1A10') references nothing.
jQuery selectors work almost identically (if not completely identically) to the way css works.
So, just ask yourself how you would reference the object(s) in question in CSS and you're half way there.
I'm assuming that p1A10 is the name or id of an object. Since we're using CSS/jQuery syntax, this should be an id, although you can select by other attributes such as $("select[name='p1A10']") .
To reference an object by ID we use the # character (again, just like in CSS). So we can select your node via $('#p1A10').
The second problem is that your function is expecting a DOM object not a jQuery object. To keep your code intact, we need to say $('#p1A10')[0] where 0 is the first element within the collection of jQuery elements.
I've provided two examples to explain this a little better. One uses your existing infrastructure and one replaces it.
http://jsfiddle.net/TD6Uu/5/
Hope it helps.
Given a form with id formc and a select with name p1A10 you could e.g. use:
o.p1A10 = eegetdropdownvalue_str($('#formc select[name="p1A10"]').get(0));
If this doesn't do it, please provide use with the exact HTML structure
I have using prototype 1.5. Can you please tell me, how can i hide/show the div tag with same name or class.
Element.hide('indicate')
But, the above line only satisfy to hide the first element only. "indicate" is the id.
As pointed out, the $$ function is required. It returns an array so you need to invoke hide on all items.
$$('.indicate').invoke('hide');
Or, for bonus showing off points, you can use the function directly as an object:
var hideFunc = Element.hide;
$$('.indicate').each(hideFunc);
The advantage of this technique means you can easily swap the function for another, such as a Scriptaculous effect.
hideFunc = Effect.SwitchOff;
Having the same id for two elements isn't supported in HTML, so there's no methods in Javascript to handle it. No matter what framework you're using.
Prototype provides the $$() function which you can use to query any CSS selector.
So if you have multiple items with a single class, you can query them like this:
$$('.indicate');
See the Prototype manual: http://www.prototypejs.org/api/utility/dollar-dollar
By the way, since you're using Prototype 1.5, I could also mention that it gives you a .getElementsByClassName() function as well. However, this has now been deprecated in more recent versions since its functionality is already covered by $$(), and to avoid confusion, since modern browsers implement a native function with the same name, but different syntax.
So don't use it, but for the sake of completeness, here is the manual link: http://www.prototypejs.org/api/element/getElementsByClassName
ID's have to be unique. Select with a class instead.
$$('div.indicate').hide();
or with its name attribute
$$('div[name=indicate]').hide();
Before jQuery I would have used something like the following code to set a class on an element:
document.getElementById("MyElementID").className = 'MyClassName';
This has the intended behaviour of replacing anything that was there before my new class name MyClassName
In jQuery the equivalent seems to be:
$('#MyElementID').attr('class', 'MyClassName')
But, we also have the in-built class functions, addClass(), removeClass() and toggleClass(). So to achieve the same effect, I would say:
$('#MyElementID').removeClass().addClass('MyClassName');
Obviously, the first jQuery example is more concise and requires just one function call (to attr, instead of addClass() and removeClass())
Can we also work on the assumption that I can't use prop as its an earlier (and currently unchangeable) version that I'm working with.
So what would you say is the preferred approach? Does the second sample give me anything over and above the first?
Many thanks in advance.
The addClass(), removeClass() and has() methods of jQuery use the className property of the element. The big advantage they offer is that they allow you to add or remove a class without affecting the other class names set.
The attr() method uses something like this:
document.getElementById("MyElementID")[name] = value;
For cases that you only need one class name, the attribute method will be probably faster. I personally however find the addClass method more elegant and easier to adapt if you need to add more class names in the future.
I think you should check the performance of all these functions. personally i think prop method is fastest ( introduced in v1.6)
see here the performance jQuery().attr vs jQuery().data vs jQuery().prop
http://jsperf.com/jquery-data-vs-jqueryselection-data/8
The difference is in this guy:
<div class="a_class another_class a_third_class">
attr('class','no_other_classes_now') <-- will replace everything in the class attribute even if there are multiple space separated classes. It's probably the lightest-weight of JQ methods for doing this since it's just using DOM methods that already worked properly across browsers for over a decade now.
.removeClass('a_third_class') will remove a class, leaving other classes intact.
.addClass('a_fourth_class') will add a space-separated class without replacing other classes.
^^ These two would have to do more work for a simple class overwrite than attr since they need to do find/replace type operations.
Prop is for changing properties of DOM elements that don't have HTML representatives like the window object (not likely to be useful very often due to other convenience methods) or that would be confusing because different attribute strings can mean different things. Like simply having the attribute "checked" without an equal sign or value being equivalent to checked="checked" or checked="true" as far as the boolean (true/false only) JS property is concerned in certain flavors of HTML. With prop you'll get the javascript property and not necessarily whatever is considered to be between the quotes of the actual HTML element.
When you're not in that type of situation, I would stick with the attr method. The whole point of prop seems to be to take work from the old attr method so I'd be surprised if it was faster in most cases. More importantly it's common and easy to read.