Angularjs Synced inputs for percetange - javascript

I need to have x amount of text input fields.
Each input field will start off with an equal value to the rest.
This value is 100 / Number of inputs.
I need to have the input fields synced, so when one value is changed, the rest of the values are recalculated to equal 100.
This problem seems fairly complex to solve, but I'm sure it must have been done before, it seems like it could be quite common.
Instead of me badly explaining the problem, here is an example of it working. It doesn't use text fields, rather sliders. But the solution is the same.
https://www.humblebundle.com/weekly
Click Choose where your money goes
jsFiddle for example: http://jsfiddle.net/r4qbx9Lb/5/

First of all, you need a $watch in your controller since you want all your input values to change based on a change in any of them. In your $watch callback function, you need to figure out which array index (what input) had been changed by the user.
All of this would look something like the following:
// 100 in this example, but can be whatever
$scope.totalValue = 100;
$scope.$watch('inputs', function(newValue, oldValue){
for(var i = 0; i < newValue.length; i++){
if(newValue[i].value != oldValue[i].value){
$scope.changedIndex = i;
$scope.leftOverValue = $scope.totalValue - newValue[i].value;
$scope.percentChange = (newValue[i].value - oldValue[i].value) / oldValue[i].value;
console.log($scope.leftOverValue);
console.log(percentChange);
}
}
}, true);
Once you have this information, you can apply it to all of the array values that weren't changed by the user. So run another loop (you'll need to split out your two loops because you don't know what index the changed value is initially) and change any of the non-affected index values in this loop:
for(var x = 0; x < newValue.length; x++){
if($scope.changedIndex != x){
//Do math and apply logic
}
}
Then you can apply any math formula you want to adjust your other values. You'll have to figure this part out - depending on if you want your other values to change proportionally to their old value or proportionally to the change the user made to the input they edited.
http://jsfiddle.net/r4qbx9Lb/10/

Related

How to compare current array element to next array element in JavaScript

I have color templates that users can choose between and also change the individual colors if they want. I have two arrays: one with all the templates, and each template containing a color palette of 8 total colors and a string of the template name. Most of my templates have white backgrounds, so I don't want the user to have to click 12 times or however many it takes to get to another index where the background color is different. My idea was to use a "for" statement to check the next element in my array, and compare it to the current element to see if they are identical. If the elements are identical, then I increment the array and the "for" statement checks again, effectively skipping any duplicate indices until a new value is found.
To do this, I use a "for" statement like this:
( ; array[index][colorSlot] == array[index+1][colorSlot]; index++)
This works perfectly until I get to the last array index and it looks for the next index which obviously doesn't exist, thus completely breaking my function. Is there a way to prevent it from looking into an array index that doesn't exist? Should I use something other than a "for" statement?
You'd prob want to go up to the second last array index and skip all repeats.
for(let index=0; index<array.length-2; index++)
{
if[index][colorSlot] != array[index+1][colorSlot]
{
}
}
You can try it with a while loop it's better choice than a for-loop in your case.
let index = 0;
while (index < array.length -2 && array[index][colorSlot] != array[index+1][colorSlot] ) {
...
index++;
}
Ok, I figured it out.
In my for loop, I check for two conditions: FIRST, I check to see if [index+1]!=array.length and THEN I check to see if the current array value is equal to the next (as written above). If checking the next value of the index would cause it to search an index that does not exist, it exits the for statement and resets my index.

checking if input is greater or lesser than array values

Sorry if this is a duplicate.
Let's say I have an array of 12 numbers, and I want to check those values against an input and then output how many values inside the array are higher than the input and lower than the input.
I wasn't sure how to do this in jQuery but if it's not possible in jQuery I am open to other suggestions. I wasn't sure if using the inArray or grep function would even work for this type of implementation.
Using jQuery you can run a foreach loop and count how many values are higher and lower from the array you have.
Try this:
var higher = 0;
var lower = 0;
$.each(arr, function(k,v){
// will miss if value is equals.
if (input < v) higher ++;
if (input > v) lower ++;
})
console.log("Higher values are: "+higher+ " | Lower values are: "+lower);
Assuming arr is your array and input variable is what user inputs.
ref: http://api.jquery.com/jquery.each/

Change the div's in another html page

still learning some javascript here, got done other things but now the final and most important part of it.
I have two html pages - one of which uses javascript to dynamically add text-fields (and to remove them of course) (genmain.html) and the other one where the text field input should go(table.html).
So i have already created a function to retrieve the array of values.
function getElementArray(divName){
var names = document.getElementsByName("namefield");
}
The variable names is an array and it has all the values from fields.
The problem is I would like to set these values from array to the values of another div on the page. After some searching i understood that it could be done with 'id'-s but i'm not that sure and don't completely understand how.
Let's say i have a lot of div's on another page (table.html) but some of them have id="MAIN". I would like to change the value inside of the div
For example
<div id="MAIN">THIS PART I WANT TO CHANGE</div>
Javascript is not part of my school system and i've done CodeAcademy tutorials and that's the most i've got about this, I hope you guys can help with my issue.
The variable names is an array and it has all the values from fields.
function getElementArray(divName){
var names = document.getElementsByName("namefield");
}
Nope, you've only got reference to the elements here. You've not got the value yet.
You can get the values by iterating through the names Nodelist array and use names[i].value
The problem is I would like to set these values from array to the
values of another div on the page
If it's going to be in same page, then use innerHTML or textContent property of the DOM to assign the value.
document.getElementById("MAIN").textContent= names[1].value;
Just for demo purpose am using names[1] here so it will load the second input value.
Let's say i have a lot of div's on another page (table.html) but some
of them have id="MAIN". I would like to change the value inside of the
div
Once you move to another page, the javascript state will be lost. So you wont have access to names inside that page.
Either you must store the values into localStorage and retrieve in next page.
Else add the values to query string of your URL and retrive it there.
Edit: Update based on comments
Let us assume you have var names = document.getElementsByName("namefield"); so to store the values inside localStorage.
var myValues = [],
names = document.getElementsByName("namefield");
for(var i = 0; i < names.length; i++) {
myValues.push(names[i].value);
}
localStorage.myValues = JSON.stringify(myValues);
Now if your next page, Iinside window.onload event:
window.onload = function() {
var myValues = localStorage.getItem("myValues") ? JSON.parse(localStorage.getItem("myValues")) : [],
divElements = document.querySelectorAll("#MAIN");
for(var i =0; i < myValues.length; i++) {
divElements[i].textContent = myValues[i];
}
}
If you want to set or change the contents of an element, you can use the innerHTML property.
So in your case, document.getElementById("MAIN").innerHTML = "Whatever you want";
For the record, names in your example technically isn't an array, but a NodeList. See https://developer.mozilla.org/en/docs/Web/API/NodeList#Why_is_NodeList_not_an_Array.3F.

property undefined but console.log can see it

I am creating a dynamic form which consists of sku, qty and subtotal. So the form starts out from no inputs and filled up as the user searches for products. Upon keypress I need to compute the total quantity and show it to the user via javascript.
I am using getting all quantity input elements via getElementsByClassName upon keypress and counting all values. however the browser is returning an error (Uncaught TypeError: Cannot read property 'value' of undefined) but I can log the value.
I only use native JavaScript no jQuery.
qtyelements = document.getElementsByClassName('qty-element');
var x;
var count = 0;
for(x = 0; x <= qtyelements.length; x++){
console.log(qtyelements[x].value);
count = count + parseInt(qtyelements[x].value);
}
Here is an image of my
problem
Length gives you the number of items, but the collection is zero based. So for example while the length may be three, you only loop to two (0, 1, 2).
So change:
x <= qtyelements.length
to:
x < qtyelements.length
In your case it looks like you only have two elements, so the indices would be 0 and 1, but you check to see if 2 exists with the <=, hence the undefined.

Appending a row to a JavaScript array not working as expected

I have a form that can submit a number of rows of data associated with a given date. One of those fields is a percentage (i.e.: 0-100). I could have three rows of a given date with percentages that add up to 100 (or not, but that's a different validation issue) or two rows with different dates and associated percentages, etc.
I need to keep track of everything and sort all the percentages into the right date buckets on submission so I can do my validation.
To that end, I created an array, PctArray. Each element of PctArray is a two field Object - date, pct. As I loop through submitted data, I check each row's date to see if it's in the PctArray already, and, if so, increment the associated pct field of that date and move on. If not, I create a new element in PctArray and insert the information.
This all works fine and dandy if there's only one row submitted, or even several rows for one date. But the minute I submit information for a second date, it chokes. At this point, I give you the code:
// If this is our first row to process
if(PctArray.length == 0){
PctArray[0] = new Object();
PctArray[0].effdt = datefield.options[datefield.selectedIndex].value;
PctArray[0].pct = parseInt(pctfield.value);
}
else{
// We loop through the array to see if this EffDt exists yet. Not very efficient, but the array will always be small
var found = "no";
for(p=0;p<PctArray.length;p++){
if(PctArray[p].effdt == datefield.options[datefield.selectedIndex].value){
PctArray[p].pct = PctArray[p].pct + parseInt(pctfield.value);
found = "yes";
}
}
if(found == "no"){
PctArray[PctArray.length] = new Object();
PctArray[PctArray.length].effdt = datefield.options[datefield.selectedIndex].value;
PctArray[PctArray.length].pct = pctfield.value;
}
}
The initital take, when it's the first row, everything creates and inserts just fine. But, when I need to go into the block of if(found == "no") it creates the new element, but then dies on the first assignment statement saying Unable to set value of the property 'effdt': object is null or undefined.
I don't get it. I'm declaring the new element the SAME EXACT WAY in both places, but there's something I'm missing that it's not liking about the second time.
I've also tried replacing new Object() with {"effdt":'', "pct":''} with identical results. It works on the top one, not the bottom one.
I'm lost. Does anyone see what I'm missing here?
Thanks.
PctArray[PctArray.length] = new Object();
PctArray[PctArray.length].effdt = datefield.options[datefield.selectedIndex].value;
After the first assignment PctArray.length has increased so you are trying to address non-existing element. You may improve the code by combining your assignments without expllicit new Object():
PctArray.push(
{ effdt: datefield.options[datefield.selectedIndex].value
, pct: pctfield.value
})

Categories