How to count classnames of dynamically added elements - javascript

Is there something I should keep in mind when trying to count ClassNames of dynamically added elements?
For the following description, refer to the link. Upon clicking the "(+)Course" button on any Semester (which are dynamically added), a Course will be appended to the corresponding Semester, with buttons of its own. This works. However, like I have for the Semesters, I have a limit of how many of each element there can be (i.e., 5 Semesters in total, 7 Courses per Semester), but I can't seem to be able to count my Courses.
Each Semester has a unique ClassName for its Courses, which is a concatenation of the Semester's Id and the word "Course", resulting in something like "sem#4Course". This code snippet is how I assemble and count the ClassNames for each Course. Is there something wrong with it? I've attached the rest of my code in the link.
var parentId = $(this).parent().attr('id');
var crsClass = parentId+"Course";
var crsCount = $('.'+crsClass).length;
https://jsfiddle.net/4efzf681/2/
I only started learning JavaScript/JQuery last week, so please bear with me. And I apologize for not separating my code between HTML, CSS and JavaScript. I work in a single file and separate it upon completion, and I've also never used fiddle before. I appreciate any help.

The # character in your class name values sem#1 and sem#1Course are creating a problem for the $() query selector which sees a class .sem and an id #1 or #1Course. It is better not to use the # and . characters in your class names and IDs. Instead use hyphens and underscore characters.
The improved fiddle is here: https://jsfiddle.net/6pdfjbt1/

You are confusing jQuery's selector engine by adding the parents id attribute to your course class name. The classes will inculde #, guess jquery thinks you want to select an element by it's id.
Changed that by doing
var crsClass = parentId.replace("#", "")+"Course";
I fixed your fiddle. Make sure to put your js in the bottom window next time ;).
I also moved the crsCount variable to the bottom to assign the value after the courses have been appended to the DOM.
YOUR FIDDLE

You can get the elements by class name using javascript method getElementsByClassName
var crsCount = document.getElementsByClassName(crsClass).length;

Related

Puppeteer select element id where beginning and end are dynamically generated

I'm trying to use puppeteer to select a dynamic element id. I've found how to select and element using just the beginning or just the end, but what I'm currently trying to do is find the element by the static part of the id in the center.
await page.waitForSelector('[id^="holder"][id$="_private_1"]');
In the above code snippet the original id looks like holder123456_private_1. I've gotten that part fine. However, the end of "_private_1" the number may change. So essentially I need the same code above but leave off the number at the end.
What you probably could do is to use '[id^="holder"][id*="_private_"]' as your selector (id starts with "holder" and has "_private_" somewhere in the id name. That would work if you don't have elements with e.g. id="holder123_not_private_321" which you don't want to target.
Otherwise i don't think there is any other selector options (https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)

How can I add a disable class to a single select, not all of that I have

I want to put a disabled class into my select, but when I do this:
$("input").attr("disabled",true);
//I tried to to this but it didn't work too:
$("#myId").attr("disabled",true);
It disable all of my selects and not one.
How can I disable only "myId"?
Without seeing your HTML (which at the time of writing has not been supplied) it's very difficult for us to tell you why it's not working.
However, if $("#myId").attr("disabled",true); isn't working, then it suggests to me that you do not have an element in your HTML with id='myId'.
Things to check in the rendered HTML (as seen by the browser, not your code)...
Is there an element with an id of myId
Is the id exactly myId, and not myID for instance (as the case is important)
Are you using something like ASP.Net where naming containers could be changing the id of the rendered control to something like ctl00_myId
Do you have 2 elements with an id of myId... in which case, this is invalid HTML, as each element must have a unique id, and would result in jQuery only setting the disabled on the first item
It disables them all because $("input").attr("disabled",true); adds the attribute disabled to all input elements. Without seeing your HTML it's hard to tell what the reason is for it not disabling when you try using #myId
Here are some mistakes I've made in the past for similar problems:
1) I did not actually have the id on the element that I thought I had. Whether it was a misspelling, or capitalization difference, or underscore vs dash...the point is the id I was trying to reference on the page simply did not match the one I was looking for with jQuery
2) I referenced it as an id but really it was a class or vice versa. . for classes, and # for id's is second nature, but sometimes if you're tired or exhausted you can very easily make that mistake
3) I had given an id that existed in multiple elements. id is supposed to be unique by convention. Duplicate id's will produce unexpected behavior
Hopefully one of these simple reasons is the cause for your issue and you can quickly resolve it. Maybe take a 30 minute break and come back to it.

Targeting an inputs value inside an HTML collection

I am making a card flipping game and I'm stuck on a particular function. During gameplay, cards disappear (by changing class name)
function reShuffle() {
var cds = document.getElementsByClassName('nocard');
for (var t = 0; t < cds.length; t++) {
console.log(cds[t]);
///i need to target an input within a div, inside another div, inside cds[t];
///make sense?
}
}
The function above is sending a collection of HTML to my console. The console looks like this: (the html collection are the items that the user got points for, so the console return can vary based on user actions)
Now, i want to target all inputs inside of divs that have class 'nocard', but not the other inputs of the same name. When I tried to make a loop to call the class 'fntCls' the console returned all of the inputs and not just the ones inside of the divs with class 'nocard'.
I hope i explained this right. I need to target the values of class 'fntCls' that are in the cards that have the class 'nocard', but not the ones that are in class 'cards'.
I went to make a fiddle, but it doesn't work properly with the way i use localStorage. So i can post a git if necessary. Also, i should mention that i am not using Jquery or any other libraries. I would like "vanilla" JavaScript assistance.
I'm sorry if this is long, or not precise to describe what i need. I really struggled to find the right words to explain what is going on here, it's my first time trying to do this particular action. Thanks in advance.
Using document.querySelectorAll you can target the inputs like so:
document.querySelectorAll('.nocard input.fntCls')
The .nocard targets the elements with the class nocard and input.fntCls will target the inputs inside those elements with the fntCls class.

How to use common js function for two divs containig elements of identical ids?

I have common jQuery function and two div tags. Both div tags have different names but both containing elements of identical ids now i want to use this common Jquery function for them both?
I have implemented common function but it's not working for both.
Here's link to my jsfiddle -jsfiddle.net/xS7zF/1/
In my jsfiddle there are two div tags namely example1 and example2 and both tags have elements of identical ids. Function is working fine for first div but not for second.
please help me to sort out this.
Yeah, under the hood, jQuery selection on an ID will use the Document.GetElementById() function implemented by the browser, which is really fast, but (i guess depending on the browser) will stop after it finds the first element, since ID's should be unique and no further searching is needed after the first one is found.
For instance, rename the divs with id="eb" to class="eb" and you can still target specific elements using $("#example1 .eb") and $("#example2 .eb")
UPDATE:
Using your new Fiddle I created this: http://jsfiddle.net/xS7zF/5/
I cleaned up a lot of code and hopefully you can see what I have done. I changed all elements that appear twice from id to class. Now, when you attach an event to an element using $(".classname").click(), it attaches to all the elements. In the handler function where you set HTML and do your show()/hide(), you don't target a specific element using it's ID, but you find it relative to the element that does the event. You can do this using parent(), parentsUntil(), next(), find(), etc. Check jQuery docs for all possibilities. So for instance, the change-handler attaches to all inputs with name=Assets. But instead of doing $("#b1").show(), I go to the parent of the specific input that fires using $(this).parent(). Then I find the element with a class=".b1", which it will only find the one that is next to this specific input and I set the HTML to just that element.
Since there is another input, the same actions happen when THAT input changes, but instead it finds IT's parent, and finds the element with class=".b1" that is next to IT. So both divs with input are contained since they act on elements relative to itself and not across the document.
For extra fun and to show you how flexible this way of programming is, here is a fiddle with the Javascript-code unchanged, but with the exact same question-div copied 8 times. No matter how many times you repeat this, the same code will act on as many divs as you create since everything works relative. http://jsfiddle.net/xS7zF/7/
Hopefully this helps, the rest is up to you!
ID's must be unique, you should not repeat them. You could replace id with class and in the jQuery function do (".ub").each() or manually referencing the object using eq(x). e.g. (".ub").eq(1).
You shouldn't assign same id's to different elements.
You CAN but you SHOULDN'T. Instead of giving the same id, use class
IDs must be unique, try fix this, change to classes.
You can try something like this:
$("div div:first-child")
instead of
$("#eb")
But depends of the rest of your page code. So, change to classes first and use
$(".eb")
when jQuery / javascript find the first ID it would ignore the rest, please read more about it
http://www.w3schools.com/tags/att_global_id.asp

JavaScript String .replace method is replacing all my content?

I have successfully implemented finding and replacing some text with something else in the following way:
$(".class").html($(".class").html().replace(/\text\b/g, '<span class="newclass newclass2">new text</span>'));
When I apply this to my element 'class' it finds all the 'text' and replaces with 'new text' and everything relating to the new classes.
However, if I have more than one element on the page with the same class, it replaces all the classes with whatever text is in the first class.
For example, if my first class has the content "Hello everyone", when the script is applied to this class, it works fine. Any subsequent class of the same name is then replaced with "Hello everyone". These also have the function applied in the same way as the first occurrence of that class.
IE, it applies the script, then replicates this in every single class of the same name on the page.
I do not understand why it would do this, and rather renders the function pointless in many ways if it can't be used to change text throughout different sections without setting up new scripts and different classes.
Hopefully there is something simple at work here that I am not aware of, any help would be much appreciated.
Many thanks
Richard
That is the nature of class selectors--the .html(...) will replace the HTML of everything that matches the .class selector.
If you want to replace text in each individual .class element, you can use the .each function. (There are probably jQuerier ways, too.)
$(`.class`).each(function(n, el) {
var myHtml = $(this).html();
myHtml = mungeIt(myHtml);
$(this).html(myHtml);
});
If you want to select only an individual .class element, then you either (a) don't really want to be using classes, but IDs, or (b) need to understand enough of your structure or the context you wish to operate in to select only the targeted DOM element.
(And hope the structure or context doesn't change without a corresponding code update.)
You're specifying a class with the jQuery selector $(".class") That's what the period indicates. jQuery has a ton of selectors to choose from. A list is provided in the documentation here: http://api.jquery.com/category/selectors/
Also, I'd look at http://api.jquery.com/hasClass/ for your problem as you could then use if...then statements to not run into others
Dave is right about needing to use the .each method. We need to loop through each element at a time because .html() will only return the first element when there are multiple matches.
Try:
$('.class').each(function() {
$(this).html($(this).html().replace(/someWord/g,'withAnother'));
});

Categories