Modifying all DOM elements using Javascript - javascript

I am working on a page which has certain number of Dojo textarea elements.
<textarea readonly class="readTextBox versionText"></textarea>
The number of these elements is more than one. I am trying to add a javascript function or formatting of a textarea. The function gives me certain line count for the textarea elements. The script is :
<script type="application/javascript">
window.onload=function() {
var versionElement = document.getElementsByClassName("versionText");
console.log("length:" + versionElement.length);
var versionElementText = versionElement.value;
var lines = versionElementText.split(/\r\n|\r|\n/);
var rowCount = 0;
for(var line=0;line<lines.length;line++) {
rowCount += Math.ceil(lines[line].length/82);
}
versionElement.rows=rowCount;
}
The problem is, i am not able to add it for all the textarea elements. I am just bale to get only one textarea elements.
I tried Windo.onload still i am getting textarea element count as 1. JS snippet is placed at the very bottom of the page as well.
the parent file which calls up the textarea is :
<div class="box-content">
<div id="pnl_{$id}">
{foreach from=$version item=version name=version}
{assign var=textBoxes value=$version->textBoxes}
<div data-dojo-type="dijit.TitlePane>
{include file="addTextArea.tpl"}
</div>
{/foreach}
</div>
</div>
The generated HTML looks like:
<div class="box-content">
<div id="productPanel_80920">
<div data-dojo-type="dijit.TitlePane" data-dojo-props="title:'Version 4 <span class=versionDate>2014-01-16 15:35:21</span>'">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td class="tableCell">
<textarea readonly class="readTextBox versionText" style="resize: none; outline: none; word-wrap: break-word;" spellcheck="true"> random text
</textarea>
</td>
</tr>
</tbody>
</table>
</div>
<br class="box-divider"/>
<div data-dojo-type="dijit.TitlePane" data-dojo-props="href:'addTextArea.html?id=4059&version=3', title:'Version 3 <span class=versionDate>2014-01-10 14:52:46</span>',open:false"></div>
<br class="box-divider"/>
<div data-dojo-type="dijit.TitlePane" data-dojo-props="href:'addTextArea.html?id=4059&version=2', title:'Version 2 <span class=versionDate>2014-01-10 14:48:09</span>',open:false"></div>
<br class="box-divider"/>
<div data-dojo-type="dijit.TitlePane" data-dojo-props="href:'addTextArea.html?id=4059&version=1', title:'Version 1 <span class=versionDate>2014-01-10 14:47:41</span>',open:false"></div>
<br class="box-divider"/>
the textarea is populated anytime i click on the div.

First off, the proper HTML would be this (you were missing a closing >):
<textarea readonly class="readTextBox versionText"></textarea>
Second off, document.getElementsByClassName returns a nodeList which is like an array. You have to go through each DOM element in the nodeList to operate on all your textarea elements.
I'm not sure I know exactly what you're trying to do, but converting your code to perform the oepration you've code on each textarea returned, it would be something like this:
window.onload=function() {
var items = document.getElementsByClassName("versionText");
for (var i = 0; i < items.length; i++) {
var versionElement = items[i];
var versionElementText = versionElement.value;
var lines = versionElementText.split(/\r\n|\r|\n/);
var rowCount = 0;
for(var line=0;line<lines.length;line++) {
rowCount += Math.ceil(lines[line].length/82);
}
versionElement.rows=rowCount;
}
}

var objs=document.getElementsByTagName('textarea');
for (var i=0;i<objs.length;i++){
var obj=objs[i];
if (!obj.className||obj.className!='versionText') continue;
//do your transformation here
}

Related

Clear contents of multiple input fields?

Hi I am dynamically adding rows with a button and when I am finished entering information, I would like it to then clear the contents. The button "Add Pokemon" is the one I want to press and it should clear all the contents.
function addPokemon() {
var pokemonName = document.getElementById("pokemon-name-container");
pokemonName.innerHTML = document.getElementById("pokemon-names").value;
for (var i = 0; i < element.length; i++) {
if (element[i].value !== "undefined") {
pokemonArray.push(element[i].value);
}
}
console.log(pokemonArray);
for (var i = 0; i < pokemonArray.length; i++) {
document.getElementById("pokemon-container").innerHTML += "<li>" + pokemonArray[i] + "</li>";
}
document.getElementById("pokemon-name-container").value = "";
document.getElementById("move-name").value = "";
}
This is my function I am using. ^^
And below is my HTML vv
<div>
<table>
<tbody id="tbody">
<tr>
<td>
<div id="pokemon-name-container">
<p>Pok&eacutemon Name:</p>
<input type="text" id="pokemon-names" size="30">
</td>
</tr>
<tr>
<td>
<p class="moves">Moves:</p>
</td>
</tr>
<tr>
<td>
<input class="move-container" type="text" id="move-name" placeholder="Enter move here">
</td>
<td>
<input class="button-container" type="button" id="remove-btn" value="Remove Move" onclick="removeRow()">
</td>
</tr>
</tbody>
</table>
</div>
<div>
<input type="button" class="add-move-button" id="add-move-button" value="Add Move" onclick="addRow()">
</div>
<div>
<input type="button" class="add-pokemon-button" id="add-pokemon-button" value="Add Pokémon" onclick="addPokemon()">
</div>
You could put to all the inputs you create a unique class that defines them under a parent with a unique id. Then use inside the function of javascript the next pice of code const childs = document.querySelectorAll('#idParent.classChilds') this querySelectorAll is kind of like the getElementsById but uses selectors of CSS so it's more powerfull. The querySelectorAll returns you a NodeList of all the elements that matches de DOM with the CSS query.
Then you would only need to do something similar to this using functional programming:
const childs = document.querySelectorAll('#idParent .classChilds')
childs.forEach(child=>{
child.value = ""
})
I'm not sure if this code works (I'm not with an code editor and a browser to check if there isn't mistakes), as I said, you could do something similar to it
HOPE IS HELPFULL
FYI, try to avoid the selectors like getElementById or getElementsByClass....
Try to use this:
document.querySelector('CSS SELECTOR') // GIVES YOU THE FIRST MATCH OF THE CSS SELECTOR
document.querySelectorAll('CSS SELECTOR') // GIVES YOU A NODELIST WITH ALL MATCHES

target only relevant div

I have a div structured this way:
<div class="sez-form ripart">
<table class="inc_prev"></table>
<div class="previsioni">A</div>
</div>
In table "inc_prev" I have a button that allows you to add another group of these. So by hitting the button you will get a structure like this:
<div class="sez-form ripart">
<table class="inc_prev"></table>
<div class="previsioni">A</div>
</div>
<div class="sez-form ripart">
<table class="inc_prev"></table>
<div class="previsioni">B</div>
</div>
Each "inc_prev" table has this html:
<table class="inc_prev">
<tbody>
<tr>
<td><label>Mese: </label><select id="mese[]" name="mese[]"></td>
<td><label>Anno: </label><select id="anno[]" name="anno[]"></td>
<td><label>Percentuale: </label><input class="importo" type="text" name="percent[]" maxlength="14" size="15" value="">%</td>
<td><img class="addRow" src="../images/plus.png"></td>
</tr>
</tbody>
</table>
This is my JS:
$(document).on('blur','.importo',function(){
var input_value = $(this).val();
var azione =$('#azione').val();
if ($(this).closest('.sez-form').find('.previsioni').length) {
$('.previsioni').load('bp/ripart_prev.php?perc='+input_value+'&id='+azione);
}else{
console.log('qui');
$(this).closest('.sez-form').append('<div class="previsioni"></div>');
$('.previsioni').load('bp/ripart_prev.php?perc='+input_value+'&id='+azione);
}
});
It appends the "previsioni" div if it's not there or update it loading content from DB. In the starting situation it works fine: previsioni div is added or updated in the right way. If I hit the plus button and add the second block when this JS gets triggered both the "previsioni" div get updated with the same content.
So my question is: "how do I change my JS so that when executed only the target "previsioni" is updated?" So if I blur the second "importo" only it's "previsioni" (B) gets updated? I am already using closest as mentioned here but this is not preventing the other previsioni to be updated too
Problem is $('.previsioni') will select all the existing elements with the class. You need to reuse the relationship to target the specific div. Here in the code snippet I have cached the $(this).closest('.sez-form').find('.previsioni') in an object.
Read inline comments
$(document).on('blur','.importo',function(){
var input_value = $(this).val();
var azione =$('#azione').val();
//Use the relationship again to traverse and cache it in a vraible the content
var previsioni = $(this).closest('.sez-form').find('.previsioni');
//If exist
if (previsioni.length) {
previsioni.load('bp/ripart_prev.php?perc='+input_value+'&id='+azione)
}else{
console.log('qui');
//Create div using JQuery
var div = $('<div class="previsioni"></div>');
//Load the content
div.load('bp/ripart_prev.php?perc='+input_value+'&id='+azione)
//Append the data
$(this).closest('.sez-form').append(div);
}
});

Removing a class from multiple elements in JavaScript

I want to be able to remove a class from x amount of elements. The elements that I am currently using is a tags. There can be unlimited amount of a tags on the document at any given time because in a different div an user can create links. This prevents me from using specific ids. But I want to only have one tag highlighted at any given time. However, I have only seen how to do it with JQuery, which I can't use. I saw a different example using Javascript, but that was for a fixed size array.
This is the code for my highlighting class:
<DOCTYPE html>
<html>
<head>
<style>
.selected{border:dotted 2px;border-color:gray;}
</style>
</head>
<body>
<div id='linkEditDiv'>
<form name='linkEditor'>
<table>
<input type="hidden" name='linkId'>
<tr><th>Label:</th><td> <input type='text' name='label'></td></tr>
<tr><th>Link:</th><td> <input type='text' name='link'></td></tr>
<tr><th></th><td><input type="button" onclick='submitForm()' value="OK" ><input type="button" onclick='cancel()' value="Cancel" ></td></tr>
</table>
</form>
</div>
<a href='#' onclick='edit("lr1")' id='lr1'>link1</a>
<a href='#' onclick='edit("lr2")' id='lr2'>link1</a>
<a href='#' onclick='edit("lr3")' id='lr3'>link1</a>
</body>
</html>
This is the JavaScript that adds the highlighting:
function edit(link)
{
var elems = document.getElementsByClassName('selected');
for (var i = 0; i < elems.length; i++) {
elems[i].className = elems[i].className.replace('selected', '')
}
document.getElementById(link).className += "selected"
}
This is the JavaScript that I tried:
var id=document.forms['linkEditor'].elements['linkId'].value;
document.getElementById(id).className = document.getElementById(id).className.replace( /(?:^|\s)selected(?!\S)/g , '' );
Create a removeClass function that iterates over the elements and replaces the class with an empty string, thus removing it.
function removeClass(selector, klass) {
var elems = document.querySelectorAll(selector);
for (var i = elems.length; i--;) {
var reg = new RegExp("(?:^|\\s)"+ klass +"(?!\\S)", "gi");
elems[i].className = elems[i].className.replace(reg, "");
}
}
to be used as
removeClass('.classname', 'classToRemove');
FIDDLE
First you grab all selected nodes, you loop through them and then you remove the class from each node.
You can't use getElementsByClassName because once you remove the class from the first element, the live dom object updates and shifts the positions, which will lead to moving the for loop one position and skipping that element.
for (const node of document.querySelectorAll('.selected')) {
node.classList.remove('selected')
}
.selected {
color: red
}
<p class="selected">Red text</p>
<p class="selected">Red text</p>
<p>Black text</p>
Try something like this to remove the class from all of the links, and then add the "selected" class back onto the link that you want to have it:
var elems = document.getElementsByClassName('selected');
for (var i = 0; i < elems.length; i++) {
elems[i].className = elems[i].className.replace('selected', '')
}
UPDATE: Just to clarify, the code works in the form you have in the question. I have taken it and applied two tweaks. 1) The hidden input should not be inside the table tags but outside of td/th tags. 2) I added "return false;" to the links.
<DOCTYPE html>
<html>
<head>
<style>.selected{border:dotted 2px;border-color:gray;}</style>
<script>
function edit(link) {
var elems = document.getElementsByClassName('selected');
for (var i = 0; i < elems.length; i++) {
elems[i].className = elems[i].className.replace('selected', '')
}
document.getElementById(link).className += "selected"
}
</script>
</head>
<body>
<div id='linkEditDiv'>
<form name='linkEditor'>
<input type="hidden" name='linkId'>
<table>
<tr><th>Label:</th><td> <input type='text' name='label'></td></tr>
<tr><th>Link:</th><td> <input type='text' name='link'></td></tr>
<tr><th></th><td><input type="button" onclick='submitForm()' value="OK" ><input type="button" onclick='cancel()' value="Cancel" ></td></tr>
</table>
</form>
</div>
<a href='#' onclick='edit("lr1"); return false;' id='lr1'>link1</a>
<a href='#' onclick='edit("lr2"); return false;' id='lr2'>link1</a>
<a href='#' onclick='edit("lr3"); return false;' id='lr3'>link1</a>
</body>
</html>
This is no longer the issue that you were asking for help with.

How to get next input element id by using class in jquery?

I have to get next textbox id on change event of the first textbox using jquery.
How can i get that. I have used next() for that but its not working as i wanted.
Here is my code,
<table>
<tbody>
<tr>
<td>
<p>PF Value</p><br>
</td>
<td>
<span id="ctl00_ctl00_bcr_bcr_TextBox1" class="txtfill" style="display: inline-block;">
<input name="ctl00$ctl00$bcr$bcr$TextBox1$textbox1" class="txtSec80CCD" value="0" id="ctl00_ctl00_bcr_bcr_TextBox1_textbox1" onblur="calcDedSecCCD(this)" style="width: 70px;" type="text">
<span id="ctl00_ctl00_bcr_bcr_TextBox1_valCustom" style="color: Red; display: none;">*</span>
<div id="ctl00_ctl00_bcr_bcr_TextBox1_ErrorDiv" class="ValidatorErrorDiv" style="display:none">
<span id="ctl00_ctl00_bcr_bcr_TextBox1_Label1">You must enter a <br>number</span>
</div>
</span>
</td>
<td>
<span id="ctl00_ctl00_bcr_bcr_TextBox2" class="txtfill" style="display: inline-block;">
<input name="ctl00$ctl00$bcr$bcr$TextBox2$textbox1" class="txtSec80CCD" value="0" id="ctl00_ctl00_bcr_bcr_TextBox2_textbox1" style="width: 70px;" type="text">
<span id="ctl00_ctl00_bcr_bcr_TextBox2_valCustom" style="color: Red; display: none;">*</span>
<div id="ctl00_ctl00_bcr_bcr_TextBox2_ErrorDiv" class="ValidatorErrorDiv" style="display:none">
<span id="ctl00_ctl00_bcr_bcr_TextBox2_Label1">You must enter a <br>number</span>
</div>
</span>
</td>
</tr>
<tr>
<td>
<p>Life Insurance Premium</p><br>
</td>
<td>
<span id="ctl00_ctl00_bcr_bcr_TextBox3" class="txtfill" style="display: inline-block;">
<input name="ctl00$ctl00$bcr$bcr$TextBox3$textbox1" class="txtSec80CCD" value="0" id="ctl00_ctl00_bcr_bcr_TextBox3_textbox1" onblur="calcDedSecCCD(this)" style="width: 70px;" type="text">
<span id="ctl00_ctl00_bcr_bcr_TextBox3_valCustom" style="color: Red; display: none;">*</span>
<div id="ctl00_ctl00_bcr_bcr_TextBox3_ErrorDiv" class="ValidatorErrorDiv" style="display:none">
<span id="ctl00_ctl00_bcr_bcr_TextBox3_Label1">You must enter a <br>number</span>
</div>
</span>
</td>
<td>
<span id="ctl00_ctl00_bcr_bcr_TextBox4" class="txtfill" style="display: inline-block;">
<input name="ctl00$ctl00$bcr$bcr$TextBox4$textbox1" class="txtSec80CCD" value="0" id="ctl00_ctl00_bcr_bcr_TextBox4_textbox1" style="width: 70px;" type="text">
<span id="ctl00_ctl00_bcr_bcr_TextBox4_valCustom" style="color: Red; display: none;">*</span>
<div id="ctl00_ctl00_bcr_bcr_TextBox4_ErrorDiv" class="ValidatorErrorDiv" style="display:none">
<span id="ctl00_ctl00_bcr_bcr_TextBox4_Label1">You must enter a <br>number</span>
</div>
</span>
</td>
</tr>
......
......
......
</tbody>
</table>
I have written my script like this,
function calcDedSecCCD(id) {
var eid = $(id).attr('id');
//var elementVal = $('#' + eid).val();
//var nxtEid = $(eid).next(':input .txtSec80CCD').attr('id');
var nextele = $(this + ':input .txtSec80CCD').next();
//alert(nextele);
var nextId = $(nextele).attr('id');
alert("First Element: "+eid);
alert("First Element: " + nextId);
}
I want textbox id : ctl00$ctl00$bcr$bcr$TextBox2$textbox1 on change event of textbox1.
How can i get the id of text input using class.
Or any other way to get id of next textbox on change of first one.
You've written your markup so that it is too hard to read. In time you will you come to appreciate short ID's, names etc. as there is no need to use 40 characters in every selector, it just makes it hard to write javascript and css, and even harder to read and understand the code later.
You've also managed to create an elaborate system of nested elements that are almost certainly unnecessary, and hard to traverse with javascript, keeping it more simple is usually a good idea.
First of, you should probably not pass "id" as a variable to your function, as "id" actually does something in javascript (it gets the elements id, see below script).
If it's only within each "td" you are looking for the next input element, the below will work, but it will not work for the last input in a "td" to find the next input that is within the next "tr" etc.
function calcDedSecCCD(elm) {
var eid = elm.id;
var nextId = $(elm).parents('td').next().find('input')[0].id;
alert("First Element: "+eid);
alert("Next Element: "+nextId);
}
Here's a FIDDLE
You might use the jquery index function
var $spans = $("td>span.txtfill");
// Your next function
function get_next_span(elem){
var $span = $(elem).closest('td>span.txtfill'),
index = $spans.index($span);
return $spans.eq(index+1);
}
So if you had a text field you would use the helper function like this:
var $current = $("#ctl00_ctl00_bcr_bcr_TextBox2_textbox1"),
$next = get_next_span($current).find('input[type=text]');
Or in a change event:
$("input[type=text]").change(function(){
get_next_span(this).find('input[type=text]').show();
});

find inputs in HTML using JavaScript

In the below table which is generated dynamically, I want to traverse and find html controls (input,select,textarea) using JavaScript DOM. I don't want span and div values.
Can anyone give an idea on how to traverse?
<html>
<head>Html</head>
<body>
<tr>
<td>
<div id="one"></div>
</td>
<td>
<input type="text" name="textbox" id="txtid" value=10"/>
</td>
<td>
<select id="cuskstatus" name="cuskstatus" class="selectStyleBorder">
<option selected value="LOCAL">Local</option>
<option value="GLOBAL">Global</option>
</select>
</td>
</tr>
<tr>
<td>
<textarea id="tareaid" name="" value="10"/>
</td>
<td>
<span id="span1">value</span>
</td>
</tr>
</body>
</html>
I would do it like this
var desired_tag_names = new Array('select', 'input', 'textarea');
function getElements(e) {
var elements = new Array();
for (i=0; i<e.length; i++) {
var el = document.getElementsByTagName(e[i]);
for (j=0; j<el.length; j++) {
elements.push(el[j]);
}
}
return elements;
}
var all_the_desired_elements = getElements(desired_tag_names);
In plain JavaScript, just use form.elements.
Assuming that you've a <form id="formid">:
var inputs = document.getElementById("formid").elements;
// ...
Or if you want to traverse all forms of the document on a per-form basis, just use document.forms to get all forms first.
for (var i = 0; i < document.forms.length; i++) {
var form = document.forms[i];
var inputs = form.elements;
// ...
}
If you're already using jQuery, or are open to, use :input selector.
var $inputs = $(':input');
// ...
Applying jQuery makes this problem trivial:
$('input','select','textarea')
This will return a jQuery collection of all input, select and textarea elements.

Categories