I am trying to convert a small jquery script to pure javascript. Whats the best way to go about it? I keep getting "$(this) is not defined" error.
var lastTab = localStorage.getItem('lastTab');
if (lastTab) {
$('a[href="'+lastTab+'"]').click();
}
You can convert the snippet to plain JS easily. But keep in mind, that this will not work, if the click event listener is registered with jQuery, because you can't trigger event listeners created with jQuery on vanilla JS. The reason is, that jQuery uses an own implementation of events.
For converting your snippet you will need querySelectorAll, to select all elements by it's href, and then loop the found elements to execute click.
var lastTab = localStorage.getItem('lastTab');
if( lastTab ) {
// get all elements by href
var elements = document.querySelectorAll("a[href='" + lastTab + "']");
// loop all elements because it could be more than one found
for( var i = 0, l = elements.length; i < l; i++ ) {
elements[i].click();
}
}
Fully working example.
(posted on jsfiddle, because SO don't allow usage of localStorage)
Related
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.
So I was reading this SO question earlier, and I am currently trying to get a basic implementation of Unobtrusive javascript working, but I don't know where I'm struggling. Normally this is something I would struggle with for much longer until I figure it out on my own, but I'm starting to get in a bit of a time crunch...
I have a several elements within my HTML document with a class called "RMButton", and I'm trying to make all of my elements with this class call a function called "RemoveQBox" (For clarity. The QBox is a DIV element, and the objects of class "RMButton" are small buttons that remove the div from the document). RemoveQBox, is already written and works just fine when I use inline JS to call it (Ex: REMOVE), but for some reason my binding within JS isn't really working out. Anybody know what I'm missing here?
Top of my Javascript file
var DBSetFields = [];
var NumQBoxes = 1;
window.onload = function() {
RMNodeList = document.getElementsByClassName("RMButton");
for (var i = 0; i < RMNodeList.length; ++i) {
console.log(RMNodeList[i]);
RMNodeList[i].onclick = RemoveQBox;
}
};
TLDR: How do I bind all elements of a particular class to a function in Javascript?
edit:
function RemoveQBox(e){
console.log("Remove");
var RemoveButton = this; //this == e.currentTarget
console.log(RemoveButton);
var QBox = RemoveButton.parentNode;
QBox.remove();
NumQBoxes -= 1;
}
I have a website I am working on that takes input from the user and calculates a results. All of the forms are html text input forms where they enter in certain number.
I want to use the input event to check for when the user enters a new value in one of these 6 text forms. The example in the book I am using, JavaScript and JQuery: Interactive Front-End Web Development, suggest to use the getElementById method with the dom event handler to do this:
For example:
function doWhatIwantToDo()
{
//Do something
}
var el = document.getElementById('username');
el.oninput = doWhatIwantToDo;
This is great and I could set up 6 unique ids for each text form, which I will need to do anyway in order to change their inner html in my javascript code, but is there someway I can check for input by using a class name?
I tried using getElementsByClassName but it is tripping me up because it returns an array of objects.
I want to avoid any jquery solutions right now because I am trying to learn vanilla javascript only right now.
Edit/Results:
I like "acbabis" and "mohamedrias" answers but the book implies that using Event Listeners is a newer method and not supported by all browsers. So for now, I would like to stick with the Traditional Dom Event Handlers that it talks about.
"dandavis" answer to just do it in a loop made me realize that perhaps binding an element to an event handler, in a loop, SHOULD actually work and that perhaps I was making a mistake in my loop.
I checked and stupidly I wasn't using array notation to loop through each object in the returned array which is why nothing was happening. Here is my final code that works:
var test = document.getElementsByClassName("test");
for (var i=0; i < test.length; i++)
{
console.log( test[i] );
test[i].onclick = testiness;
}
function testiness ()
{
alert("Success!");
}
var inputElements = document.querySelectorAll('.className');
for(var i = 0, len = inputElements.length ; i < len ; i++) {
inputElements[i].addEventListener('input', doSomethingFunction);
}
querySelectorAll returns you a static NodeList. You need to iterate and attach the event.
Instead of using getElementsByClassName which returns a live HTMLCollection, working with querySelectorAll would be preferrable.
I would document.querySelectorAll for this.
var inputs = document.querySelectorAll('input');
for(var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('input', doWhatIWantToDo);
}
This will find all input elements on the page and add the handler to each one. If you want to use a class, just add it to the desired input tags, and replace document.querySelectorAll('input') with document.querySelectorAll('input.classname').
I have a small block I wanted to convert to using jQuery for a couple of different purposes, but mainly to reverse engineer how it works to imporve my jQuery skills. I tried taking a go at it, but could not figure out all of the conversions.
The following Javascript block iterated through the checkboxes rendered in an ASP.NET TreeView control client-side and scan for checkboxes with a className=disabledTreeviewNode (this equivilent functionality cannot be achieved purely server side).
function DisableCheckBoxes(treeviewClientID) {
var treeView = document.getElementById(treeviewClientID);
if (treeView) {
//Get all the checkboxes which are 'inputs' in the treeview
var childCheckBoxes = treeView.getElementsByTagName("input");
//Iterate through the checkboxes and disable any checkbox that has a className="disabledTreeviewNode"
for (var i = 0; i < childCheckBoxes.length; i++) {
var textSpan = childCheckBoxes[i].parentNode.getElementsByTagName("span")[0];
if (textSpan != null && textSpan.firstChild)
if (textSpan.className == "disabledTreeviewNode" || textSpan.firstChild.className == "disabledTreeviewNode")
childCheckBoxes[i].disabled = true;
}
}
}
I tried changing the following:
var treeView = document.getElementById(treeviewClientID);
to
var treeView = $('#' + treeviewClientID);
However then I could no longer call getElementsByTagName. I tried to use the jQuery equivilent of .find but then the code started to behave differently and I was a bit lost.
Can anyone assist on converting this small block to use jQuery? Comments are welcome as to if this is worthwhile or even if there is a better way.
EDIT: This class=disabledTreeviewNode is assigned server-side like this:
tn.Text = "<span class=disabledTreeviewNode>" + tn.Text + "</span>";
It's a bit of a hack/flag so that client-side code can read it and set it's parent which is the checkbox to disabled. Why the Parent? I can't directly set the class on the checkbox in code because that property is not accessible. The hack: set the TreeView object's .Text to have the <span class=disabledTreeviewNode> value and then set it's parent (the checkbox) to disabled client-side.
Many of the jQuery object's methods call .each() method behind the scene, so you don't have to iterate through the collection, jQuery does this for you.
$('#' + treeviewClientID + ' input').filter(function() {
return $(this.parentNode).find('.disabledTreeviewNode').length;
}).prop('disabled', true);
$('#' + treeviewClientID + ' span:has(.disabledTreeviewNode) input')
.prop('disabled', true);
Using jQuery I can easily get the number of DOM elements used by a web page:
$('*').length;
But not all web sites are using jQuery.
So my question is: How do I get the number of DOM elements used in a web page using pure JavaScript and js console.
Assuming you mean "HTMLElementNodes" as opposed to "All nodes" (which would include such things as text nodes and also be skipped by your jQuery example) then:
document.getElementsByTagName('*').length
This still requires the use of DOM though. Pure JavaScript can't interact with an HTML document other than as a string of text.
It's quite simple really:
document.getElementsByTagName('*').length
If you can ignore older browsers, you could also preserve some of the jQuery-like syntax with:
var $;
$ = document.querySelectorAll.bind(document);
$('*').length;
This question is the top result on google for "js count all dom nodes" but it's 2021 now and we have ShadowDOM so none of these previous answers will actually give an accurate result.
Better to use this function which is based on the code used by Lighthouse to calculate the true DOM size.
function countNodes(element = document.body) {
let count = 0; let child = element.firstElementChild;
while (child) { count += countNodes(child);
if (child.shadowRoot) { count += countNodes(child.shadowRoot); }
child = child.nextElementSibling; count++;
} return count;
}
Using a recursive function countChildrenNumber:
function countChildrenNumber(el) {
let result = 0
if (el.children && el.children.length > 0) {
result = result + el.children.length
for (let i = 0; i < el.children.length; i++) {
result = result + countChildrenNumber(el.children[i])
}
}
return result
}
then call it by passing document as the parameter
countChildrenNumber(document)
The main answer doesn't really count everything (I think shadow DOM would be excluded)
Using snippet below works better for me:
$$('*').length