How do I increment multiple attributes on a page? - javascript

I'm trying to increment multiple attributes on the page with two objects. I have tried to use .split() like so
var words = $('.block').find('input').attr('js-data-reveals').split(',');
var num = 0;
words += '_' + num++
$('.block').find('input').attr('js-data-reveals', words);
Which returns:
js-data-box="TYPE_0,FONT_1"
I want to search the whole page for this attribute and increment each set. e.g
js-data-box="TYPE_1,FONT_1"
js-data-box="TYPE_2,FONT_2"

You should do a little of work with regex and jQuery, bellow a full working example:
$(function(){
$('.block').find('input').each(function(){
var attrName = 'js-data-reveals';
var $el = $(this);
var attrs = $el.attr(attrName);
var data = attrs.split(',').map(function(item){
return item.replace(/\d+/, function(num){ return ++num});
});
$el.attr(attrName, data.join(','));
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<div class="block">
<input js-data-reveals="TYPE_1,FONT_1" />
<input js-data-reveals="TYPE_5,FONT_2" />
</div>
<div class="block">
<input js-data-reveals="TYPE_8,FONT_0" />
<input js-data-reveals="TYPE_2,FONT_3" />
</div>
</body>
</html>

When you use String.split, you create an array. You must loop through each item in the array. The correct way to do this would be to do this:
var num = 0; // Set counter to 0
var newString = string.split(",").map(function(item) { // Split the string by ',' then loop through each item, replacing it with the correct value
return item + '_' + num;
}).join(','); // re-join the array of strings into a single string.
num++; // Increment counter.
EDIT:
It seems like you are asking for something else. In the case where you want to increment based on the current value, the correct way to do this would be to use a Regex as shown by Clieton. You still must use the Array.map function as split returns an array. The only difference is that you must use a regex to get the original number to increment.

In case you wish to collect the attributes and store them with a unique counter.
var num = 0;
var words = [];
var multiDimensional = [];
function CollectAttributes(params) {
console.log("Print attributes Line by Line");
$('.block').children('input').each(function () {
var attributes = $(this).attr('js-data-reveals').split(',');
var byLine = [];
for(i = 0; i < attributes.length; i++){
byLine.push(attributes[i]+ "_" + num);
words.push(attributes[i]+ "_" + num);
}
multiDimensional.push(byLine);
console.log(byLine.join()); // Result => Line by Line
num++;
});
console.log("Print attributes all in one array");
console.log(words); // Result => Basic array
console.log("Print attributes in multidimensional array");
console.log(multiDimensional); // Result => MultiDimensional array
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="block">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
<input type="text" js-data-reveals="TYPE,FONT,ETC">
</div>
<input type="button" value="Test" onclick="CollectAttributes(this);">

Related

How can I pattern match ID only making sure the variable number matches without having to hardcode all of the possibilities?

I've recently become familiar with Jquery selectors....and they work great. Starts with...ends with....
The problem I have currently is that all of my variable names essentially start with similar patterns and end with similar patterns. This ID is generated from somewhere else so I'm hoping I can do something to use it effectively.
The pattern ID format essentially looks like...
"#id_newbudgetlineitem_set-0-line_item_october"
"#id_newbudgetlineitem_set-0-line_item_november"
"#id_newbudgetlineitem_set-0-line_item_december"
I want to essentially matching on the set-* but only if it's identical to the other ids in my array. Is this even possible without having to hard code anywhere from set-0 to set-1000? Unfortunately the class for each one is the same as is the name situation. Is there someway to say if the set numbers all match in a given array then add them up? I can't use starts with or ends with in this case...and don't want to hardcode 1000 possibilities. Thanks in advance for any ideas or thoughts.
I am trying to do something like.....
function update_total()
{
var total = 0;
$('.budget').each(function(index, element) {
"#id_newbudgetlineitem_set-0-line_item_october" +
"#id_newbudgetlineitem_set-0-line_item_november" +
"#id_newbudgetlineitem_set-0-line_item_december"
var val = parseFloat($(element).val());
if( !isNaN( val )){
total += val;
}
});
$("#id_total").val(total);
}
Here's a working solution........
function update_total_total_total()
{
var ret = +$("input[name$='set-0-line_item_january']").val() + +$("input[name$='set-0-line_item_february']").val() + +$("input[name$='set-0-line_item_march']").val() + +$("input[name$='set-0-line_item_april']").val() + +$("input[name$='set-0-line_item_may']").val() + +$("input[name$='set-0-line_item_june']").val() + +$("input[name$='set-0-line_item_july']").val() + +$("input[name$='set-0-line_item_august']").val() + +$("input[name$='set-0-line_item_september']").val() + +$("input[name$='set-0-line_item_october']").val() + +$("input[name$='set-0-line_item_november']").val() + +$("input[name$='set-0-line_item_december']").val();
$("input[name$='set-0-line_item_total']").val(ret);
}
But I could have up to 1000 different set values. Is there some other way to do this without having to hard code this 999 more times?
This is a lot closer....but total still says 0. It's updating all of the totals to 0...so that's progress but not getting the actual totals. Forward progress thanks to Swati.
function update_total_total_total() {
//get length of input line_total for each sets..
for (var i = 0; i < $("[name$=line_item_total]").length; i++) {
var total = 0;
//get all inputs but not line_item _total
$(`input[name*=id_newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total]):not([name$=line_item_cost_center]):not([name$=line_item_description])`).each(function(index, element) {
var val = parseFloat($(element).val());
if( !isNaN( val )){
total += val;
}
})
$(`input[id$=set-${i}-line_item_total]`).val(total); //set value..of input
}
}
You can get length of total input whose name ends with line_item_total so this value will be counter for for-loop.
Then , inside for loop you can use $(`input[name*=id_newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total])`) this will fetch values from all inputs expect the line_total_item then add value on each iteration .
Lastly , use $(`input[name$=set-${i}-line_item_total]`).val(total); to set total inside line_total_item textbox.
Demo Code :
function update_total_total_total() {
//get length of input line_total for each sets..
for (var i = 0; i < $("[name$=line_item_total]").length; i++) {
var total = 0;
//get all inputs but not line_item _total
$(`input[name*=id_newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total]):not([name$=line_item_cost_center]):not([name$=line_item_description])`).each(function(i, element) {
var val = parseFloat($(element).val());
if (!isNaN(val)) {
total += val;
}
})
$(`input[name$=set-${i}-line_item_total]`).val(total); //set value..of input
}
}
update_total_total_total()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
SET 0 :
<input type="text" name="id_newbudgetlineitem_set-0-line_item_october" value="5">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_november" value="51">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_december" value="15">
<br/> Total :
<input type="text" name="id_newbudgetlineitem_set-0-line_item_total" value="" placeholder="total">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_cost_center">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_description">
</div>
<br/>
<div>
SET 1
<input type="text" name="id_newbudgetlineitem_set-1-line_item_october" value="5">
<input type="text" name="id_newbudgetlineitem_set-1-line_item_december" value="534">
<br/> Total :
<input type="text" name="id_newbudgetlineitem_set-1-line_item_total" value="" placeholder="total">
<input type="text" name="id_newbudgetlineitem_set-1-line_item_cost_center">
<input type="text" name="id_newbudgetlineitem_set-1-line_item_description">
</div>
<br/>
<div>
SET 2
<input type="text" name="id_newbudgetlineitem_set-2-line_item_december" value="4">
<input type="text" name="id_newbudgetlineitem_set-2-line_item_oct" value="5">
<br/> Total :
<input type="text" name="id_newbudgetlineitem_set-2-line_item_total" value="" placeholder="total">
<input type="text" name="id_newbudgetlineitem_set-2-line_item_cost_center">
<input type="text" name="id_newbudgetlineitem_set-2-line_item_description">
</div>
This was the final working code. As Swati suggested it was an incorrect name reference.
function update_total_total_total() {
for (var i = 0; i < $("[name$=line_item_total]").length; i++) {
var total = 0;
$(`input[name*=newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total]):not([name$=line_item_cost_center]):not([name$=line_item_description])`).each(function(i, element) {
var val = parseFloat($(element).val());
if( !isNaN( val )){
total += val;
}
})
$(`input[name$=set-${i}-line_item_total]`).val(total);
}
}

Does anyone know how to make a start number and end number produce a unordered list of square roots?

I'm having trouble figuring out how to make this work. I need the StartNumber box to have a value of 0 and the EndNumber to be 12. When clicking ClickMe! it produces an unordered list of each square root 0-12.
function wasClicked() {
let firstBox = document.getElementById("startNumber");
console.log("firstBox is " + firstBox);
let startNumber = firstBox.Value;
let secondBox = document.getElementById("endNumber");
let endNumber = secondBox.value || 12;
let line = "";
for (let i = startNumber; i = endNUmber; i++) {
line += "<li>The square root of " + i + " is " + Math.sqrt(i).toFixed(3) + "</li>\n";
}
console.log(line);
}
function isANumber(x) {
return !isNaN(x);
}
<div>
<label>Start Number:</label>
<input type="text" id="startNumber" /><br>
</div>
<div>
<label>End Number:</label>
<input type="text" id="endNumber" /><br>
</div>
<div>
<button onclick="wasClicked()">Click Me!</button>
</div>
<div></div>
<h2>The list</h2>
<ul id="theList"></ul>
Your code has a number of problems.
Firstly, casing matters in JavaScript, so it's firstBox.value not firstBox.Value, and endNumber is a completely different name than endNUmber. Make sure you know the correct case of any built-in properties or methods and use consistent casing in your variable names.
Secondly your for-loop syntax is off. It should be something along the lines of
for (let i = start; i <= end; i++) ...
Also, the .value property of HTML <input> elements is a string so you need to convert it to a number if you want to treat is as a number. There are a few ways to do this, but for this example, I'll use Number.parseFloat.
Lastly, you'll want to render the result on the DOM in some way. Again, there are a few ways to do this, but the simplest is Element.innerHTML.
Putting this all together, you'll have something like this:
function wasClicked() {
let firstBox = document.getElementById("startNumber");
let startNumber = Number.parseFloat(firstBox.value);
let secondBox = document.getElementById("endNumber");
let endNumber = Number.parseFloat(secondBox.value);
let line = "";
for (let i = startNumber; i <= endNumber; i++) {
line += `<li>The square root of ${i} is ${Math.sqrt(i).toFixed(3)}</li>`;
}
document.getElementById("theList").innerHTML = line;
}
function isANumber(x) {
return !isNaN(x);
}
<div>
<label>Start Number:</label>
<input type="text" id="startNumber" /><br>
</div>
<div>
<label>End Number:</label>
<input type="text" id="endNumber" /><br>
</div>
<div>
<button onclick="wasClicked()">Click Me!</button>
</div>
<div></div>
<h2>The list</h2>
<ul id="theList"></ul>

Re-feeding a variable into a looped function

I'm attempting to make a simple program for encoding things in base64 multiple times (not really for any particular reason, just more as an example and practice). I've been having quite a bit of trouble though, it could be because I've not had enough (or possibly had too much) coffee.
I can't seem to figure out how to refeed my variable (text) back into the function that encodes it until i is equal to times
Any assistance with this would be appreciated!
<html>
<head>
<script>
function encodeThis(text,times) {
var toEncode = text;
for (var i = 0; i < times, i++) {
btoa(toEncode);
}
document.getElementById("result").value = toEncode;
}
</script>
</head>
<body>
<b>Text to Encode</b><br/>
<input type="text" id="encode"><br/>
<b>Number of Times to Encode (Integers Only)<br/>
<input type="text" id="times">
<button type="submit" onclick="encodeThis(encode,times)">Test</button>
<br/>
<br/>
<b>Result</b><br/>
<input type="text" id="result">
</body>
</html>
Would I need to put a function inside of that function to refeed the variable in?
You need to assign the result of the encoding back to the variable.
function encodeThis(text, times) {
var toEncode = text;
for (var i = 0; i < times, i++) {
toEncode = btoa(toEncode);
}
document.getElementById("result").value = toEncode;
}
But in terms of the overall code in your example you also need to actually get the text from the #encode and the #times elements and fix the syntax error in the for loop.
So
function encodeThis(text, times) {
var toEncode = text.value, // read the value from the encode input element
numTimes = parseInt(times.value, 10); // read the value from the times element and convert to number
for (var i = 0; i < numTimes; i++) {
toEncode = btoa(toEncode);
}
document.getElementById("result").value = toEncode;
}
<b>Text to Encode</b><br/>
<input type="text" id="encode" /><br/>
<b>Number of Times to Encode (Integers Only)</b><br/>
<input type="text" id="times" />
<button type="submit" onclick="encodeThis(encode,times)">Test</button>
<br/>
<br/>
<b>Result</b><br/>
<input type="text" id="result">

Putting values into dynamically generated input types with JavaScript

I have Range/Number type inputs that are synchronized and dynamically generate input fields as much as their values.
Then I have a button that will fill the generated input fields with an arbitrary value.
The dynamically generated input fields each have unique IDs, but the document.getElementById() function fails to find any of the IDs and returns null.
Is there a way to change the value of the generated fields within the randomizeItemTypes() function?
function randomizeItemTypes(textbox) {
var rackNum = textbox.replace("itemSlider", "").replace("numOfTypes", "");
var numOfTypes = document.getElementById("numOfTypes1").value;
for (var i = 0; i < numOfTypes; i++) {
document.getElementById("rack" + rackNum + "." + i).value = 4;
}
}
The following link is the CodePen to my code:
http://codepen.io/cnc4ever/pen/LGNMEp
Thanks guys!
Your rackNum is giving some string instead of numbers
Your id for textbox is something like rack1.0 , rack1.1
use document.getElementById("rack1" + "." + i).value = 4; instead
<html>
<head>
<title></title>
</head>
<body>
<div class="itemsTypes1">
<input id="itemSlider1" type="range" value="" min="1" max="10" step="1" onchange="printValue(this.value);drawItemTypes('itemSlider1');" />
<input id="numOfTypes1" type="number" value="" min="1" max="10" onchange="printValue(this.value);drawItemTypes('numOfTypes1');" />
<p id="itemTypes1Area"></p>
<button id="randomize1" onclick="randomizeItemTypes()">Randomize</button>
</div>
<script type="text/javascript">
function printValue(data) {
var x = document.getElementById("itemSlider1").value = data;
var y = document.getElementById("numOfTypes1").value = data;
}
function randomizeItemTypes() {
var randomValue= Math.ceil(Math.random()*10);
printValue(randomValue);
}
</script>
</body>
</html>

How do I get the first child of each of these rows?

I have 2 rows, each with 2 text inputs. How do I go through each row w/ class "myRow" and, within each row, get the first child that has class "This"? I can get the first "This" class of row 1 but can't seem to get row 2.
My fiddle
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="http://code.jquery.com/jquery-1.8.1.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#btn').click(function(){
$(".myRow").each(function(){
var r = $(".This").eq(0).val();
alert(r);
});
});
});
</script>
</head>
<body>
<div class="myRow">
<input type="text" class="notThis" value="wrong!"/>
<input type="text" class="This" value="first one!"/>
<input type="text" class="This" value="almost!"/>
</div>
<br>
<br>
<div class="myRow">
<input type="text" class="notThis" value="wrong!"/>
<input type="text" class="This" value="second one"/>
<input type="text" class="This" value="almost!"/>
</div>
<button id="btn">Submit</button>
</body>
</html>
$('#btn').click(function(){
$(".myRow").each(function(){
var r = $(".This:first", this).val();
alert(r);
});
});
$('.This:eq(0)','.myRow').css('background-color','#F00');
$('.myRow').find('.This:eq(0)').css('border-color','#F00');
$('.This:first','.myRow').css('color','#0F0');
$('.myRow').find('.This:first').css('font-weight','bold');
Working example
$('#btn').click(function(){
$(".myRow").each(function(){
var r = $(".This", this).eq(0).val();
alert(r);
});
});
To get both in a selector, you could always do:
var elems = $('.This:eq(0)', '.myRow');
Then you could do this to get an array of the values:
var values = $.map($('.This:eq(0)', '.myRow'), function(el) {return el.value});
FIDDLE
Change to:
Demo
var r = $(this).find(".This").eq(0).val();
You need to look for .This relative to the current element, otherwise it will always find the first instance.
Side note: as an alternative to .eq(0) you can use .first().
You can get an array of JavaScript objects by using jQuery's factory method to search for a certain property. Example:
var search = $('input[class="This"]');
You can access the first one found by simply using:
search[0];
Essentially (and this is not the most optimized way of doing it), you can do this:
var rows = $('.myRow');
for(var i = 0; i < rows.length; i++) {
var first;
var row = $(rows[i]);
var children = row.find('input[class="This"]');
// You can also do row.find('input.This');
if(children.length > 0) {
first = children[0];
// Do something with it
}
}
Like I said, not the most optimal way, but each time you use the factory method, you're getting an array of objects and you can loop through them.
You can search through HTML properties like the above.
Examples:
$('input[type="button"]')
$('input[name="firstName"]')
$('a[href="www.google.com"]')
This should do the trick:
$('#btn').click(function(){
$(".myRow input:nth-child(1)").each(function(){
alert($(this).val());
});
});

Categories

Resources