change label foreach element in html using javascript - javascript

I am using both html and velocity and came up with this code. The names and images are stored in an array and this is the code I used to display each of the contents of this array to the page.
#foreach($starter in $starter)
<div class="product">
<div class="color"><img src= "$starter.img" width="100" height="100"></div>
<span class="product-name">$starter.name</span>
<div class="compare-wrap">
<input type="checkbox" id="">
<label id="view">Compare</label>
</div>
</div>
#end
I wanted the label to change from "Compare" to "View Compare" while at the same time storing its id in the array upon checking their correspondng check box. I eventually came up with this code:
var checkedArray = [];
$(":checkbox").change(function(){
if((this).checked){
checkedArray.push(this.id);
document.getElementById('view').innerHTML = "<a href='/compare'>View Compare</a>";
}
else{
checkedArray.splice(checkedArray.indexOf(this.id), 1);
document.getElementById('view').innerHTML = 'Compare';
}
var str = checkedArray.join(', ');
alert(str);
});
but it seems it is only applicable to the first content of the array. Any idea how I can use a foreach code at this point?

document.getElementById() only supports one name at a time and only returns a single node not an array of nodes. You should use a class:
var views = document.getElementsByClassName('view');
var i = views.length;
while(i--) {
views[i].innerHTML = "Compare";
}
HTML
<label class="view">Compare</label>
Element ID must be unique.
Hope it helps.

Related

How do I change more than one element?

EDIT: I changed the var to class but I might have some error in here.
Here it goes, I want to have this paragraph in which the user can change the name on the following paragraph. The code I'm using only changes one name but the rest remains the same.
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
<input id="userInput" type="text" value="Name of kid" />
<input onclick="changey()" type="button" value="Change Name" /><br>
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
No error messages, the code only changes one name instead of all three.
Use class="kiddo" instead of id in the html.
You can then use var kiddos = document.getElementsByClassName('kiddo') which will return an array of all the elements of that class name stored in kiddos.
Then you just need to loop through the values and change what you want.
Example of loop below:
for (var i = 0; i < kiddos.length; i++) {
kiddos[i].innerHTML = userInput;
}
id should be unique on the page. Javascript assumes that there is only one element with any given id. Instead, you should use a class. Then you can use getElementsByClassName() which returns an entire array of elements that you can iterate over and change. See Select ALL getElementsByClassName on a page without specifying [0] etc for an example.
Hello You should not use id, instead use class.
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
After That on Js part :
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
you should use class instated of id. if you use id then the id [kiddo] must be unique
In short, document.querySelectorAll('.kiddo') OR
document.getElementsByClassName('kiddo') will get you a list of elements to loop through. Take note of querySelectorAll, though - it uses a CSS selector (note the dot) and doesn't technically return an array (you can still loop through it, though).
See the code below for some full working examples (const and arrow functions are similar to var and function, so I'll put up a version using old JavaScript, too):
const formEl = document.querySelector('.js-name-change-form')
const getNameEls = () => document.querySelectorAll('.js-name')
const useNameFromForm = (formEl) => {
const formData = new FormData(formEl)
const nameValue = formData.get('name')
const nameEls = getNameEls()
// Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(el => el.textContent = nameValue)
}
// Handle form submit
formEl.addEventListener('submit', (e) => {
useNameFromForm(e.target)
e.preventDefault() // Prevent the default HTTP request
})
// Run at the start, too
useNameFromForm(formEl)
.name {
font-weight: bold;
}
<!-- Using a <form> + <button> (submit) here instead -->
<form class="js-name-change-form">
<input name="name" value="dude" placeholder="Name of kid" />
<button>Change Name</button>
<form>
<!-- NOTE: Updated to use js- for js hooks -->
<!-- NOTE: Changed kiddo/js-name to spans + name class to remove design details from the HTML -->
<p>
Welcome to the site, <span class="js-name name"></span>! This is how you create a document that changes the name of the <span class="js-name name"></span>. If you want to say <span class="js-name name"></span> more times, you can!
</p>
var formEl = document.querySelector('.js-name-change-form');
var getNameEls = function getNameEls() {
return document.querySelectorAll('.js-name');
};
var useNameFromForm = function useNameFromForm(formEl) {
var formData = new FormData(formEl);
var nameValue = formData.get('name');
var nameEls = getNameEls(); // Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(function (el) {
return el.textContent = nameValue;
});
};
// Handle form submit
formEl.addEventListener('submit', function (e) {
useNameFromForm(e.target);
e.preventDefault(); // Prevent the default HTTP request
});
// Run at the start, too
useNameFromForm(formEl);
<button class="js-get-quote-btn">Get Quote</button>
<div class="js-selected-quote"><!-- Initially Empty --></div>
<!-- Template to clone -->
<template class="js-quote-template">
<div class="js-quote-root quote">
<h2 class="js-quote"></h2>
<h3 class="js-author"></h3>
</div>
</template>
You have done almost everything right except you caught only first tag with class="kiddo".Looking at your question, as you need to update all the values inside tags which have class="kiddo" you need to catch all those tags which have class="kiddo" using document.getElementsByClassName("kiddo") and looping over the list while setting the innerHTML of each loop element to the userInput.
See this link for examples:https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp
try:
document.querySelectorAll('.kiddo')
with
<b class="kiddo">dude</b>

Search for contents of element and click its parent

I am trying to create an extention which clicks on an item of the price given by the user. Here is the relevant popup.html:
<input style="display:none" /><input type="text" id="userInput" value='' />
<button id="clickme">Run</button>
When 'clickme' is clicked, it runs this popup.js:
document.getElementById('clickme').addEventListener('click', function() {
var price = '$'+ document.getElementById("userInput").value+".00";
alert(price);
$("p:contains("price")").parentNode.click();
});
If you type the desired price in in the form as 48, it returns an alert with the value $48.00.
It then shuold click on the item of that price, however this currently isn't working. Here is the code of the relevant part of the website which I am trying to run my extention on (not my website):
<div class="grid__item wide--one-fifth large--one-quarter medium-down--one-half">
<a href="/collections/1seventeenweek7/products/copy-of-supreme-dazzle-warm- up-top-red" class="grid-link text-center">
<p class="grid-link__title">Supreme Corner Cap Light Blue</p>
<p class="grid-link__meta">
<span class="visually-hidden">Regular price</span>
$48.00
</p>
</a>
</div>
I am trying to get it to search for the p element containing $48.00, and then click on the a element which is the parent element, but this is not currently working. What am I doing wrong? - thanks
Here you go. This will work!
document.getElementById('clickme').addEventListener('click', function() {
var price = '$'+document.getElementById('userInput').value+'.00'
var metas = document.getElementsByClassName('grid-link__meta')
alert(price)
for (let i = 0; i < metas.length; i++) {
if (metas[i].innerHTML.includes(price)) metas[i].parentNode.click()
break
}
})
Personally, I'd really like to use something like the following, yet I forgot that getElementsByClassName doesn't return an array, but rather a NodeList object.
var price = '$'+document.getElementById('userInput').value+'.00'
var metas = document.getElementsByClassName('grid-link__meta')
var match = metas.find((curr) => curr.innerHTML.includes(price))
match.parentNode.click()

On click, compare id's of selected checkboxes to list hrefs

There is a list of checkboxes, that change on container li click.
Here is one for example, and the rest of them are the same (except for a few id's and classes , that dynamically change like #lips here)
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="lips" checked="checked">
<label for="Lips..." class="lips">
Lips
</label>
</li>
on click, .filtercheck gets class of .checkchecked (if it helps)
there is also a list of links
<div class="collectionurls">
<a class="colurls colurl1" href="/collections/lips"></a>
<a class="colurls colurl2" href="/collections/face-lips"></a>
<a class="colurls colurl3" href="/collections/face-cheeks"></a>
</div>
I'm trying to compare checkbox id, when .lifilter is clicked to that list of urls, pick one that has all the checked id's, add it to current domain, and redirect page there.
For example: Let's say, #face is already checked, site visitor clicks on #lips. Script checks .colurls for face and lips. In our case, finds .colurl2, gets its href, adds to curdomain, and redirects page to domain.com/collections/face-leeps
There is a pretty long script of forming these id's and classes, but i got really stuck here.
$(document).ready(function(){
var curdomain = document.domain;
//id's and classes forming code
$('.lifilter').click(function(){
//compare ids to hrefs
var addurl = // that class attr('href')
var curdomain = curdomain + addurl;
window.location = curdomain;
});
});
I'm pretty new to js, and have no clue where to go from here. And there is most likely a syntax error where i'm combining vars.
Help a noob out plz
Seems like a strange way to do the navigation, but I would do this like so:
Build an array of jQuery attribute contains selectors, using all the checked checkboxes and Array.map()
Join those selectors together and apply the resulting multiple attribute selector
Check how many results you get. Once you have narrowed-down to one result, you have enough information to redirect.
There's a running snippet below. It doesn't actually redirect, but shows the redirect location, or the number of possible results.
$(".filtercheck").on("click", function() {
//build an array of jQuery contains selectors
var selected = $(".filtercheck:checked").get().map(function(item) {
return '[href*="' + item.id + '"]';
});
//join the selectors into a continuous string
var selector = selected.join('');
//run the jQuery selectors
var result = $(".collectionurls " + selector);
//if there is one result you can successfully navigate
if (result.length === 1) {
var href = result.attr("href");
$("#result").val(href);
//window.location = href; //uncomment to redirect
}
else {
$("#result").val(result.length + " results");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="face" checked>
<label for="face" class="face">
Face
</label>
</li>
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="lips">
<label for="lips" class="lips">
Lips
</label>
</li>
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="cheeks">
<label for="cheeks" class="cheeks">
Cheeks
</label>
</li>
</ul>
<div class="collectionurls">
<a class="colurls colurl1" href="/collections/lips"></a>
<a class="colurls colurl2" href="/collections/face-lips"></a>
<a class="colurls colurl3" href="/collections/face-cheeks"></a>
</div>
<input id="result" />
From what I'm gathering, you'll need to go through the checked checkboxes on your page and concatenate them together. The easiest way may be with map. You mentioned that the checked checkboxes get the class checkchecked, so:
var url = '/collections/' + $('.checkchecked').map(function (index, element) {
return this.id;
}).join('-');
However, the order of the items in the URL will depend on the order in the document. For instance, if the lips checkbox comes before the face checkbox in document order, the url will be '/collections/face-lips', but if the opposite is true, it will be '/collections/lips-face'.
If there needs to be a defined order, sort the array returned by map:
var parts = $('.checkchecked').map(function (index, element) {
return this.id;
}).sort(); // This will sort them alphabetically
var url = '/collections/' + parts.join('-');
If you have a preset order, store that order in a separate array:
var order = [ 'face', 'cheeks', 'lips' ];
var parts = $('.checkchecked').map(function (index, element) {
return this.id;
}).sort(function (a, b) {
return order.indexOf(a) - order.indexOf(b);
}); // This will sort by separate "order"
var url = '/collections/' + parts.join('-');

how to remove the lastchild element of dynamically generated DIV and return the html as string

How to remove the lastchild of the dynamically generated div and regenerate the html as string.
Sample HTML DIV
strHtmlString = "<div contenteditable='true' id='undefined'>Test1</div>
<div contenteditable='true' id='sentenceFreeTextField67' type='sentenceFreeTextField'>One</div>
<div id='multiselectAnchors' type='multi'>
<div id='options32' >Two</div>
<div contenteditable='true' id='sentenceFreeTextField68' type='sentenceFreeTextField'>One</div>
</div>
<div id='blank4' contenteditable='true' type='blankField'> </div>
<div id='Div1' type='multi'>
<div id='options33' >Three</div>
<div contenteditable='true' id='sentenceFreeTextField69' type='sentenceFreeTextField'>One</div>
</div>"
here is the code sample
if (($('<DIV/>').html(strSentence)[0].lastChild.lastChild.type === 'sentenceFreeTextField') && (!$.trim($('<DIV/>').html(strSentence)[0].lastChild.lastChild.innerText))) {
strHtmlString = $('<DIV/>').html(strSentence)[0].lastChild.lastChild.remove().html; (this remove().html doesn't work)
}
the need is to delete the lastchild of the div at runtime and convert back to string as it was earlier. I can do string manipulation however, might not the be the right way, please suggest
var el = $(strHtmlString);
// dont know what you meant by last child, so taking the id
el.children().find("#sentenceFreeTextField69").remove();
var str = el.wrap("<div/>").parent().html()
Generate a DIV dynamically:
$('body').append('<div>');
Access the DIV immediately after generation:
var $divElement = $('body').append('<div>').find('div');
Get the last child:
var $lastChildElement = $divElement.last();
Get the HTML of the last child (more specifically, the innerHTML):
var $lastChildHTML = $lastChildElement.html();
Do it all together then you turn around:
var $lastChildHTML = $('body').append('<div>').find('div').last().html();
That's what it's all about.
var last = $(element).children(':last-child');
var html = $(last).html();
$(last).remove();
var newHtml = $(element).html();
//incase you want the html with it's parent as well do this
var newHtml = $(element).parent().html();

javascript: use getElementByID to populate multiple divs

is there a way to write the same thing clientside using javascript to multiple divs or multiple spots on a page?
I have a php script outputting rows from a database. To edit the contents, I would like to insert a checkbox before each row as with the iphone edit contacts and to do it quickly, I'm trying to use javascript to populate a div with a checkbox before each row using getElemenByID.
One problem is you cannot have more than one div of the same name on a page so I can't write once and have it populate multiple divs of the same name. If I give divs different names than I have to write multiple times which is not appealing especially as the number of rows may vary.
As a related question would checkboxes inserted using javascript even work?
Here is non working code:
js
function edit() }
var box = '<input type="checkbox name=num[]>';
var target = "checkbox";
document.getElementById(target).innerHTML = box;
return;
}//end function
html (generated by PHP from dbase)
<form action="edit.php" method="post">
<a href="javascript:void" onclick="edit()";>edit</a>
<div id="checkbox"></div>Row1 contents<br>
<div id="checkbox"></div>Row2 contents<br>
<form type = "submit" value="Edit">
</form>
Does anyone know a way to do this ie make boxes appear that can then be selected for submission?
Many thanks for any suggestions.
Should be generated using PHP instead, but...
HTML
I'm guessing that you want to use a span element (not a div) for your checkbox placeholder, otherwise you'd have a checkbox on one line, and then "Row1 contents" below the checkbox, versus having the checkbox next to the text.
[X]
Row 1 Contents
versus (span)
[X] Row 1 Contents
<form action="edit.php" method="post" name="frmRows" id="frmRows">
edit
<span class="checkbox"></span>Row1 contents<br>
<span class="checkbox"></span>Row2 contents<br>
<input type = "submit" value="Edit">
</form>
JavaScript
It's not recommended to use .innerHTML in JavaScript unless absolutely necessary (not supported in all browsers, and there are better ways to accomplish the same task.)
function edit() {
var newCb;
var i;
var checkboxList = document.getElementsByClassName( 'checkbox' );
for ( i = 0; i < checkboxList.length; i++ ) {
newCb = document.createElement( 'input' ); // Create a new input element
newCb.setAttribute( 'type', 'checkbox' ); // Set attributes for new element
newCb.setAttribute( 'value', 'SomeValueHere' );
newCb.setAttribute( 'name', 'checkboxName' );
newCb.setAttribute( 'id', 'checkbox-' + i );
checkboxList[i].appendChild( newCB ); // Add checkbox to span.checkbox
}
}
The ID attribute must be unique on each page. You could use the class attribute like this:
<div class="checkbox"></div>Row1 contents<br>
<div class="checkbox"></div>Row2 contents<br>
and then you can use
var check = getElementsByClassName('checkbox');
for (var i=0; i< check.length; i++) {
check[i].innerHTML = box;
}
But... this will not work in IE < 9. If you are using a framework like jQuery they already implemented a workaround for this but with pure JS you have to implement this yourself.
jQuery example
HTML
<div class="checkbox"></div>Row1 contents<br>
<div class="checkbox"></div>Row2 contents<br>
JS
var box = '<input type="checkbox" name="num[]" />';
$(".checkbox").html(box);
The HTML
The first thing to do is to update the generated HTML. In HTML element id attributes should be unique just like field names inside a form. To classify multiple elements as similar you should use the class attribute.
Here is an example of how you could structure the HTML.
<form action="edit.php" method="post">
edit
<div id="row1Identifier" class="editCheckbox"></div>Row1 contents</br>
<div id="row2Identifier" class="editCheckbox"><?div>Row2 contents</br>
<input type="submit" value="Submit">
</form>
The javascript
Using document.getElementsByClassName will return a list of elements with the matching class.
​function edit () {
// set up the variables used in this function
var checkboxDivs = document.getElementsByClassName('editCheckbox'),
i,
loopDiv;
// make the change to each div
for (i = 0; i < checkboxDivs.length; i += 1) {
loopDiv = checkboxDivs[i];
loopDiv.innerHTML = '<input type="checkbox" name="' + loopDiv.id + '">';
}
}​
Even if you could do it with a single line (using jQuery, for exemplo), you would actually be running a loop through all the divs (that's the only way to change something in various elements: change it in each one).
So you can do this with pure JavaScript using a loop to run the modifications in all the divs, getting them by id (the faster way):
for(var i = 0; i < numberOfDivs; i++){
document.getElementById("myElement" + i).innerHTML = box; //concatenating i to a base id
}
You could also use another slower techniques to get elements by tag name or class, or even use a lib such as jQuery.
If you use jquery:
function edit() {
// box = '<input type="checkbox name=num[]>';
var target = "checkbox";
$(".cb").html(box);
return;
}//end function
<form action="edit.php" method="post">
edit
<div class="cb" id="checkbox">aa</div>Row1 contents<br>
<div class="cb" id="checkbox">bb</div>Row2 contents<br>
</form>

Categories

Resources