So basically I have a set of questions(<div>s), all with the same class name and I want to simply loop through all of those classes and append the questions(<div>s) inside a container but at the minute it seems to just loop through it but only display the 1st question over and over or however many questions I put in.
if($('.option').hasClass('c_questions')){
var y = document.getElementsByClassName('c_questions');
for(var i = 0; i < y.length; i++){
$('.main-body').append($('.c_questions').html());
}
}
$('.c_questions').each(function(a){
$('.main-body').append($(this).html()+" ");
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="c_questions">hi</div>
<div class="c_questions">hey</div>
<div class="c_questions">test</div>
<p class="main-body"></p>
by edit into code. (squint suggested.)
if($('.option').hasClass('c_questions')){
var y = document.getElementsByClassName('c_questions');
for(var i = 0; i < y.length; i++){
$('.main-body').append(y[i].innerHTML);
} ^^^^^change
}
Don't use a for loop, look at jQuery's each.
So this would loop through each element with the class example below:
$( ".test" ).each(function( index ) {
console.log($( this ).text() );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">hi</div>
<div class="test">hey</div>
<div class="test">test</div>
Related
I want to dynamically add the id and for attribute for each input and label element.
<div id="splash">
<div class="tab">
<input id="tab-1">
<label for="tab-1"><label>
</div>
<div class="tab">
<input id="tab-2">
<label for="tab-2"><label>
</div>
<div class="tab">
<input id="tab-3">
<label for="tab-3"><label>
</div>
</div>
So basically I would want the id for the input to be tab-# with the # increasing by 1 for each input field and the same for the "for=" attribute for the label.
It's super easy. Just iterate through each .tab, using each's index argument, and modify the attributes of the elements.
$('.tab').each(function (index) {
var tabName = 'tab-' + (index + 1);
$('input', this).attr('id', tabName);
$('label', this).attr('for', tabName);
});
Jsbin: http://jsbin.com/rawatag/4/edit?html,js,output
Ok.
I won't give you a straight answer but this should be more useful in future.
Basically make the container <div id=splash>
Then run this command document.getElementById("parentID").innerHTML += "Something here"
This will add the content (pay attention to. The += sign) to the div (splash)
Then, just wrap this in a loop using a counter to get the desired result
Eg: ...innerHTML += "<div id=tab-" + counter + "></div>"
Note that this can be done in raw JS. No JQuery required.
No need for jQuery here:
es5 (jsfiddle)
function assignInputsAndLabels(root) {
var children = root.children;
var tabNumber = 1;
for (var i = 0; i < children.length; i++) {
if (children[i].classList.contains('tab')) {
children[i].getElementsByTagName('input')[0].setAttribute('id', 'tab-' + tabNumber);
children[i].getElementsByTagName('label')[0].setAttribute('for', 'tab-' + tabNumber);
tabNumber++;
}
}
}
assignInputsAndLabels(document.getElementById('splash'));
es6
function assignInputsAndLabels(root) {
const children = root.children;
let tabNumber = 1;
for (let i = 0; i < children.length; i++) {
if (children[i].classList.contains('tab')) {
children[i].getElementsByTagName('input')[0].setAttribute('id', `tab-${tabNumber}`);
children[i].getElementsByTagName('label')[0].setAttribute('for', `tab-${tabNumber}`);
tabNumber++;
}
}
}
assignInputsAndLabels(document.getElementById('splash'));
The parameter to the function is the wrapper of the elements that have the class of tab. In your case, you'd pass in the DOM node of the element with id of splash. So you'd call the function like this:
assignInputsAndLabels(document.getElementById('splash'));
I have done it using javascript.Check it below
function init(){
var sel = document.getElementsByClassName("tab");
var i=1;
for(let obj of sel){
var attr = "tab-"+i;
obj.getElementsByTagName('input')[0].setAttribute("id",attr);
obj.getElementsByTagName('label')[0].setAttribute("for",attr);
i++;
}
}
addEventListener("load",init);
<div class="tab">
<input type="text">
<label></label>
</div>
<div class="tab">
<input type="text">
<label></label>
</div>
I use this code for get data-isAirTour attribute but always is undefined.
var tours = $('#WrapTours').find('div.tour');
var toursTmp;
var length = tours.length;
for (var i = 0; i < length; i++) {
if (tours.eq(i).value.data('isForeignTour') == isForeignTour) {
toursTmp.push(tours[i]);
}
}
html:
<div class="col-sms-6 col-sm-6 col-md-3 tour" data-isAirTour="#item.IsAirTour" data-isForeignTour="#item.IsForeignTour" data-TourType="#item.TourType">
</div>
How to solve this?
tours[i] will return DOM element. To get jQuery object use .eq(index), to get the object at index then you can use jQuery methods like .attr()
tours.eq(i).attr('data-isAirTour')
Apart from the other proposed solutions, you can also use the vanilla JS getAttribute() method, like so:
var tours = $('#WrapTours').find('div.tour');
for (var i = 0; i < tours.length; i++) {
var attr01 = tours[i].getAttribute("data-isAirTour");
console.log(attr01);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="WrapTours">
<div class="tour" data-isAirTour="yes"></div>
</div>
Alternatively, you can use dataset.isairtour (remember to keep it all in lowercase) to achieve the same result:
var tours = $('#WrapTours').find('div.tour');
for (var i = 0; i < tours.length; i++) {
var attr01 = tours[i].dataset.isairtour;
console.log(attr01);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="WrapTours">
<div class="tour" data-isAirTour="yes"></div>
</div>
think I have some class of same content
<div class="parentclass">
<div class="childClass">
</div>
<div class="childClass">
</div>
<div class="childClass">
</div>
</div>
<div class="parentclass">
<div class="childClass">
</div>
<div class="childClass">
</div>
<div class="childClass">
</div>
</div>
I can get all the parent class object in an array by
var pClassList= document.getElementsByClassName("parentclass");
My question is how can I access the child classes "childClass" from pClassList array calling it index like
var childClassList1= pClassList[0].getElementsByClassName("childClass");
var childClassList2= pClassList[1].getElementsByClassName("childClass");
Simply loop over the initial collection and use index of each iteration to access individual elements
var pClassList= document.getElementsByClassName("parentclass");
for(var i=0; i < pClassList.length; i++){
var parentElement = pClassList[i];
// do something to each parent as needed
// access children of parent element
var childClassList= parentElement.getElementsByClassName("childClass");
// do something with `childClassList`
for (var j= 0; j < childClassList.length; j++){
var child = childClassList[j];
// do something with each child here
}
}
Could be:
var childClassList1= pClassList[0].getElementsByClassName("childClass")[0];
var childClassList2= pClassList[1].getElementsByClassName("childClass")[0];
I prefer to use JQuery, in this case it would be.
var pClassList = $(".parentclass")
var childClassList1 = $(pClassList[0]).children().first()
var childClassList2 = $(pClassList[1]).children().first()
The following will retrieve child nodes with classname="childClass" for the first element in pClassList array:
for (var i = 0; i < pClassList[0].childNodes.length; i++) {
if (pClassList[0].childNodes[i].className == "childClass") {
//Do something with pClassList[0].childNodes[i]
}
}
You can do the same for the rest of the elements in pClassList array by iterating over each of them.
An alternative I think is you select as you want childClass is like :
var childClassList1= document.querySelector('.childClass:nth-child(2)');
I want to find div element that contain custom attribute mod than append that div to list item. But first I have to remove divs that contain duplicate mod value. Here's what I have done
<div class="list"></div>
<div class="container">
<div mod="dog"></div>
<div mod="man"></div>
<div mod="woman"></div>
<div mod="dog"></div>
<div mod="bird"></div>
<div mod="insects"></div>
<div mod="dog"></div>
</div>
this is my script
modArr($('.container').find('[mod]'))
function modArr(el){
var filterArray = [] // store mod
, modNames = [] // store mod value
, arrIndex = [] // store non duplicate index
, li = [] // store
modArray = el
// store mod value
for(var i=0; i < modArray.length; i++){
modNames.push($(modArray[i]).attr('mod')) // get mod value from div
}
// search for non duplicate mod value and get the index of none duplicate mod
for(var i=0; i < modArray.length; i++){
if(filterArray.indexOf(modNames[i]) === -1){
filterArray.push(modNames[i])
arrIndex.push(i) // push non duplicate index value
}
}
filterArray = [] // reset filterArray
// push module from modArray to filterArray using index in arrIndex
for(var i=0; i < arrIndex.length; i++){
filterArray.push(modArray[arrIndex[i]])
}
// push to li array
$.each(filterArray,function(i,el){
li[i] = '<li>'+ el.outerHTML +'</li>'
})
$('<ul></ul>')
.append(li.join(''))
.appendTo('.list')
}
What you can see is that I've used to many loops, is there any simple way to do this. Thanks!
We can use an object as a map for checking duplicates, see comments (I've added text to the mod divs so we can see them):
modArr($('.container').find('[mod]'));
function modArr(elements) {
// A place to remember the mods we've seen
var knownMods = Object.create(null);
// Create the list
var ul = $("<ul></ul>");
// Loop the divs
elements.each(function() {
// Get this mod value
var mod = this.getAttribute("mod");
// Already have one?
if (!knownMods[mod]) {
// No, add it
knownMods[mod] = true;
ul.append($("<li></li>").append(this.cloneNode(true)));
}
});
// Put the list in the .list element
ul.appendTo(".list");
}
<div class="list"></div>
<div class="container">
<div mod="dog">dog</div>
<div mod="man">man</div>
<div mod="woman">woman</div>
<div mod="dog">dog</div>
<div mod="bird">bird</div>
<div mod="insects">insects</div>
<div mod="dog">dog</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
We can also just use the DOM to check for duplicates, but it's a bit slower (not that it matters for the number of elements here):
modArr($('.container').find('[mod]'));
function modArr(elements) {
// Create the list
var ul = $("<ul></ul>");
// Loop the divs
elements.each(function() {
// Get this mod value
var mod = this.getAttribute("mod");
// Already have one?
if (ul.find('div[mod="' + mod + '"]').length == 0) {
// No, add it
ul.append($("<li></li>").append(this.cloneNode(true)));
}
});
// Put the list in the .list element
ul.appendTo(".list");
}
<div class="list"></div>
<div class="container">
<div mod="dog">dog</div>
<div mod="man">man</div>
<div mod="woman">woman</div>
<div mod="dog">dog</div>
<div mod="bird">bird</div>
<div mod="insects">insects</div>
<div mod="dog">dog</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Note: I used this.cloneNode(true) rather than outerHTML because there's no need to take a roundtrip through markup. If you want more jQuery there, it's $(this).clone(); ;-) Similarly, if you don't like this.getAttribute("mod"), there's $(this).attr("mod").
I'd be remiss if I didn't point out that mod is an invalid attribute name for div elements. You can use any name you want starting with data-, though, so perhaps use <div data-mod="dog"> instead.
Try this, only adds if an element with mod is not already in list:
$('.list').append('<ul>');
$('.container [mod]').each(function(index, el) {
if($('.list [mod=' + $(el).attr('mod') + ']').length === 0) {
$('.list ul').append($('<li>' + el.outerHTML + '</li>'));
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="list"></div>
<div class="container">
<div mod="dog">Dog1</div>
<div mod="man">Man1</div>
<div mod="woman">Woman1</div>
<div mod="dog">Dog2</div>
<div mod="bird">Bird1</div>
<div mod="insects">Insect1</div>
<div mod="dog">Dog3</div>
</div>
I have here the following script which is causing me some errors:
var sections = ["#general_info", "#address_records", "#employment_history", "#driver_experience", "#military_experience", "#eeo_survey", "#psp_notice", "#eva"];
for(var i = 0; i < sections.length; i++){
$(sections[i]).find('input, select').each(function(){
$(this).change(function(){
validate();
$(this).closest('.placement').find('.module-heading').removeClass('module-heading-bad');
$(this).closest('.placement').find('.glyphicon').addClass('glyphicon-ok text-success');
$(this).closest('.placement').find('.glyphicon').removeClass('glyphicon-warning-sign text-danger');
$(sections[i]).find('input, select').each(function(){
if($(this).closest('div').hasClass('has-error')){
$(this).closest('.placement').find('.module-heading').addClass('module-heading-bad');
$(this).closest('.placement').find('.glyphicon').addClass('glyphicon-warning-sign text-danger');
$(this).closest('.placement').find('.glyphicon').removeClass('glyphicon-ok text-success');
return false;
}
});
});
});
}
function validate(){
var driving_qs = ['driving_exp_qa', 'driving_exp_qb', 'driving_exp_qc', 'driving_exp_qd'];
for( var i = 0; i < driving_qs.length; i++){
if($('input[name='+driving_qs[i]+']:checked').val()){
$('input[name='+driving_qs[i]+']').closest('.form-group').removeClass('has-error');
$('input[name='+driving_qs[i]+']').closest('.form-group').addClass('has-success');
}else{
$('input[name='+driving_qs[i]+']').closest('.form-group').addClass('has-error');
$('input[name='+driving_qs[i]+']').closest('.form-group').removeClass('has-success');
}
}
var fields = [{
selector: $('.not-empty'),
validations: [ isNotEmpty]
},{
selector: $('.email'),
validations: [ isNotEmpty, isEmail]
},{
selector: $('.number'),
validations: [ isNotEmpty, isNumber]
},{
selector: $('.number-noreq'),
validations: [isNumberNotRequired]
}];
$('.form-control').closest('div').removeClass('has-error');
var i = 0, k = 0, z = 0, j = fields.length, item, selector, fn, info;
for(; i < j; i++){
item = fields[i];
for(k = 0; k < item.validations.length; k++){
fn = item.validations[k];
for( z = 0; z < item.selector.length; z++){
selector = $(item.selector[z]);
info = selector.closest('div');
if(info)
var result = fn(selector.val());
if(result){
info.removeClass("has-error");
info.addClass('has-success');
}else{
info.removeClass('has-success');
info.addClass("has-error")
}
}
}
}
}
The script works perfectly fine if I am running it without the for loop in front of it. Here is a quick step by step of what my code does (note: this is without the for loop):
Locate the section in code and find each input an select field
Assign the change event to each target input and select field
On change find closest span of class placement, and fine the first module heading and perform all the adding and removing of classes, just to refresh the heading to a success heading if no errors exist below.
Find all the inputs and selects and check for errors, if they exists return false, and add the error classes back on everything
This script will work all the way to the end of each section like it is supposed to do. However after I tried to do this with the for loop, it created a success scenario after only one input. Why is this happening, and is it even possible to have this function inside a loop like I am currently doing?
Also below I have included samples of the html mark-up
<!-- this tag serves no purpose other than being a bookmark for scripting -->
<span class='placement'>
<!-- Section 1: General Information -->
<div id='general-heading' class='row module-heading module-heading-bad general' data-toggle='#general_info'>
<div class='form-group'>
<div class='col-md-12'>
<h4 class='text-info '>General Information<div id='general-confirmation' class='glyphicon glyphicon-warning-sign pull-right text-danger'></div></h4>
</div>
</div>
</div>
<div id='general_info' class='app-section'>
<div class='form-group'>
<div class='col-xs-12'>
<div class='form-group row'>
<div class='col-sm-6 col-xs-12'>
<label class='control-label'>First Name<span class='req'> *</span></label><br />
<input type='text' class='form-control not-empty' id='first_name' value="<?=$first_name?>"/>
</div>
<div class='col-sm-6 col-xs-12'>
<label class='control-label'>Middle Name</label><br />
<input type='text' class='form-control' id='middle_name' value="<?=$middle_name?>"/>
</div>
</div>
</div>
</div>
</span>
The problem in this block of code:
for(var i = 0; i < sections.length; i++){
$(sections[i]).find('input, select').each(function(){
$(this).change(function(){
...
$(sections[i]).find('input, select').each(function(){
...
}
});
});
});
}
Is that it uses the variable i, which will have changed when the function() inside change is run.
In your case, the simplest way to fix it would be by using the forEach function instead of a for loop, and not using the index at all:
sections.forEach(function(section){
$(section).find('input, select').each(function(){
$(this).change(function(){
...
$(section).find('input, select').each(function(){
...
}
});
});
});
})
This will ensure that the i you mean is different each time.