Result of map not re-rendering - javascript

I'm looking to update an array like this :
// JSX in Render
<Table size="sm" responsive striped bordered hover>
<tbody>
<tr key={-1} className="defTabCra">
<th>Date</th>
<th>Morning</th>
<th>Afternoon travaillée</th>
</tr>
{this.generateMonth()}
</tbody>
</Table>
My function generateMonth() :
generateMonth = () => {
return MyArrayOfMomentJs.map((item,i) => { // Item is a momentJS object
var jour = item.format("ddd");
jour = jour.charAt(0).toUpperCase() + jour.slice(1);
if (item.isoWeekday() > 5 || item.CheckIfholiday()) {
return (
<tr key={i} className="NotWorked">
<th>{jour + ' ' + item.format("D")}</th>
<td />
<td />
</tr>
);
}
else {
var rowContainer = [];
//Morning
if (ArrayOfBooleanForTheMorning[i] !== null) { //null means that no choices has been made
if (ArrayOfBooleanForTheMorning[i]) {
rowContainer.push(
<td key={i}>
<input type="checkbox" value="true" />
<MaterialIcon color="green" icon="check" />
</td>
);
}
else rowContainer.push(
<td key={i}>
<input type="checkbox" value="false" />
<MaterialIcon icon="close" color="red" />
</td>
);
}
else rowContainer.push(<td key={i}>
<input type="checkbox" />
<MaterialIcon icon="remove" />
</td>);
//Afternoon
if (ArrayOfBooleanForTheAfternoon[i] !== null) {
if (ArrayOfBooleanForTheAfternoon[i])
rowContainer.push(
<td key={i + 31}>
<input type="checkbox" value="true" />
<MaterialIcon color="green" icon="check" />
</td>
);
else rowContainer.push (
<td key={i + 31}>
<input type="checkbox" value="false" />
<MaterialIcon icon="close" color="red" />
</td>
);
}
else rowContainer.push(<td key={i+31}> // If null
<input type="checkbox" />
<MaterialIcon icon="remove" />
</td>);
var row = [<tr key={i}><th>{jour + ' ' + item.format("D")}</th>{rowContainer}</tr>];
return row;
}
}, this);
}
The goal is quite simple : Everytime I make a change in the ArrayOfBooleanForTheAfternoon or ArrayOfBooleanForTheMorning, I would like to re-render the component.
And now things get strange (or maybe not, you guys will tell me :p) : The function is called everytime I make a change, which is good. The map function returns an array of JSX and the content of is good aswell. However, this new array doesn't replace the actual array already rendered.
I tried to put my jsx array in a state, to put directly my funtion in the code. Nothing works.
Anyone has any idea of what is going on ?
PS: I'm using bootstrap-react for the style of the page and his layout.

Wrong usage of key prop looks to be the likely issue.
Do you have something unique in the item object.You could use that.
Instead of
<td key={i}...>
try
<td key = {item.id} ...>
where id is the key for the unique entity in the item object.
Same for the tr tag.

Related

Trying to delete Row from table using react.js

So what I have done here is created a table with 5 ByDefault rows for that aI created a array with 5 elements and mapped over it and I got the rows. After that I created an input field in which user can enter the number of extra rows they want, using the "increaseRow" function and the user input I push Elements in the array so that i can get that number of rows and got it as well. But when I Keep the By Default rows as it is and some new rows e.g 5 rows and try to DELETE all 10 rows it creates problem
All I want is the rows should get DELETED.
import { useState } from "react";
import Table from "react-bootstrap/Table";
import './App.css'
const App = () => {
const row1 = [];
const [row, setRow] = useState();
const [NewRow, setNewRow] = useState([1,2,3,4,5]);
const [allRowsAdded, updateAllRows] = useState(0);
const addRow = (e) => {
e.preventDefault();
setRow(e.target.value);
};
const increaseRow = () => {
for (let i = 0; i < parseInt(row); i++) {
row1[i] = allRowsAdded + i;
}
updateAllRows((allRowsAdded) => allRowsAdded + parseInt(row));
setNewRow([...NewRow, ...row1]);
};
const deleteRow = (id) => {
const updatedRows = [...NewRow].filter((rowId) => {
return rowId !== id;
});
setNewRow(updatedRows);
};
return (
<>
<div>
<form>
<input type="text" onChange={addRow} placeholder="Enter Number Of Row's" /><br />
</form>
<button onClick={increaseRow}> Add </button>
</div>
<div className="container">
<form >
<Table striped bordered hover responsive variant="light">
<thead>
<tr>
<th>
{" "}
<h6> No. </h6>{" "}
</th>
<th>
{" "}
<h6> Injection Speed </h6>{" "}
</th>
<th>
{" "}
<h6> Fill Time </h6>{" "}
</th>
<th>
{" "}
<h6> Peak Inj Press </h6>{" "}
</th>
<th>
{" "}
<h6> Viscocity </h6>{" "}
</th>
<th>
{" "}
<h6> Shear Rate </h6>{" "}
</th>
<th>
{" "}
<h6> AbsoluteDropViscocity </h6>{" "}
</th>
<th>
{" "}
<h6> %DropViscocity </h6>{" "}
</th>
<th>
{" "}
<h6> Action </h6>{" "}
</th>
</tr>
</thead>
<tbody className="grid_style">
{NewRow.map((rowId) => {
return (
<tr key={rowId}>
<td> {rowId} </td>
<td>
<input type="text" className="form-control" />
</td>
<td>
<input type="text" className="form-control" />
</td>
<td>
<input type="text" className="form-control" />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<i
className="fa fa-trash viscocity_icons"
onClick={() => deleteRow(rowId)}
>
</i>
</td>
</tr>
);
})}
</tbody>
</Table>
</form>
</div>
</>
);
};
export default App;
https://codesandbox.io/s/silly-allen-iun6b?file=/src/App.js
This is just a logical error (rowId clashes) that you are doing.
const increaseRow = () => {
for(let i=0; i < row; i++){
row1[i] = i;
}
setNewRow([...NewRow, ...row1]);
}
Here when u are assigning value to a row, you are taking index as id for that row. According to which, this is happening with rowId
and on removing a row and filtering based on rowId, for eg: id=1
const deleteRow = (id) => {
const updatedRows = NewRow.filter((rowId) => {
return rowId!== id;
})
setNewRow(updatedRows)
}
2 rows are removed with rowId=1, ie. at serial number 1 and 6.
Solution
You can correct this by adding anything for unique Keys, like uuid. Here I have used an extra state variable const [allRowsAdded, updateAllRows] = useState(0); which stores the total number of rows added from now and add the rowIds next to the addedRows.
const increaseRow = () => {
for (let i = 0; i < parseInt(row); i++) {
row1[i] = allRowsAdded + i;
}
updateAllRows((allRowsAdded) => allRowsAdded + parseInt(row));
setNewRow([...NewRow, ...row1]);
};
Now, rowIds becomes
And there will be no rowId clashes.
Code Link : https://codesandbox.io/s/quiet-snowflake-26v1o?file=/src/App.js
here is by my understanding will work,
const deleteRow = (id) => {
const updatedRows = NewRow.filter((index) => {
return index !== id;
})
setNewRow(updatedRows)
}
change your html code,
<td> <i className="fa fa-trash viscocity_icons" onClick={() => deleteRow(index)}></i> </td>
i dont know about datastructure or json of array,
const deleteRow = (id) => {
const updatedRows = NewRow.filter((e) => {
return e.id !== id;
})
setNewRow(updatedRows)
}

vuejs3 - update computed value from v-model

I'm using vue-3
I am not familiar with vuejs and I am a newbie developer.
Situation
To add translations in batch on salesforce I wanted to code a tool.
I coded a webservice in rust which gets a json and turns it into a zip for salesforce.
The client provides me with data from a spreadsheet, and I have to format it in json to send it to my webervice.
I wanted to allow a copy / paste in a cell then split each line with "\ n" that I link to an input in order to edit the entry if necessary.
Problem
The input fill well with splited values, but if I change the input, the value in "computed" does not update. see image here
Questions
How can I update my value in my computed array with splited values ?
V-model update my input from the computed but not the reverse.
what is the best function to do this?
I saw that there is reactive but I do not know if this is the right solution.
Here my code
<template>
<div>
<label for="fr">fr</label>
<input type="checkbox" value="fr" id="fr" v-model="fr.state" />
<label for="en">en</label>
<input type="checkbox" value="en" id="en" v-model="en.state" />
<label for="it">it</label>
<input type="checkbox" value="it" id="it" v-model="it.state" />
<label for="es">es</label>
<input type="checkbox" value="es" id="es" v-model="es.state" />
<label for="german">german</label>
<input type="checkbox" value="german" id="german" v-model="german.state" />
</div>
{{ formated.fr }}
<div class="Array">
<table>
<thead>
<tr>
<th>The table header</th>
<th>default Value</th>
<th v-if="fr.state === true">fr</th>
<th v-if="en.state === true">en</th>
<th v-if="it.state === true">it</th>
<th v-if="es.state === true">es</th>
<th v-if="german.state === true">german</th>
</tr>
</thead>
<tbody>
<tr>
<td>C/C</td>
<td><textarea v-model="defaultentry" cols="40" /></td>
<td v-if="fr.state === true"><textarea v-model="fr.value" cols="40" /></td>
<td v-if="en.state === true"><textarea v-model="en.value" cols="40" /></td>
<td v-if="it.state === true"><textarea v-model="it.value" cols="40" /></td>
<td v-if="es.state === true"><textarea v-model="es.value" cols="40" /></td>
<td v-if="german.state === true">
<textarea v-model="german.value" cols="40" />
</td>
</tr>
<tr v-for="(entry, index) in formated.default" :key="index">
<td v-if="formated.default[index]">{{ index }}</td>
<td v-if="formated.default[index]">
<input type="text" v-model="formated.default[index]" />
</td>
<td v-if="formated.fr">
<input type="text" v-model="formated.fr[index]" />
</td>
<td v-if="formated.en">
<input type="text" v-model="formated.en[index]" />
</td>
<td v-if="formated.it">
<input type="text" v-model="formated.it[index]" />
</td>
<td v-if="formated.es">
<input type="text" v-model="formated.es[index]" />
</td>
<td v-if="formated.german">
<input type="text" v-model="formated.german[index]" />
</td>
</tr>
</tbody>
</table>
</div>
<script>
export default {
name: "Array",
entries: {},
data() {
return {
defaultentry: [],
fr: { state: false, value: [] },
en: { state: false, value: [] },
it: { state: false, value: [] },
es: { state: false, value: [] },
german: { state: false, value: [] },
};
},
computed: {
formated: function() {
let entries = {};
let base = this.defaultentry
.toString()
.split("\n")
.map((x) => {
if (x.length > 40) {
return "error";
}
return x.trim();
});
let fr = this.fr.value
.toString()
.split("\n")
.map((x) => {
if (x.length > 40) {
return "error";
}
return x.trim();
});
let en = this.en.value
.toString()
.split("\n")
.map((x) => {
if (x.length > 40) {
return "error";
}
return x.trim();
});
let it = this.it.value
.toString()
.split("\n")
.map((x) => {
if (x.length > 40) {
return "error";
}
return x.trim();
});
let es = this.es.value
.toString()
.split("\n")
.map((x) => {
if (x.length > 40) {
return "error";
}
return x.trim();
});
let german = this.german.value
.toString()
.split("\n")
.map((x) => {
if (x.length > 40) {
return "error";
}
return x.trim();
});
entries.default = base;
if (this.fr.state == true) {
entries.fr = fr;
} else {
delete entries.fr;
}
if (this.en.state == true) {
entries.en = en;
} else {
delete entries.en;
}
if (this.it.state == true) {
entries.it = it;
} else {
delete entries.it;
}
if (this.es.state == true) {
entries.es = es;
} else {
delete entries.es;
}
if (this.german.state == true) {
entries.german = german;
} else {
delete entries.german;
}
return entries;
},
},
};
</script>
Thank you for your time and help
v-model works both ways, so it needs to get something and to set something. You have only defined a get computed property but not a set. You use formated like it is a data property.
So split the computed property in a get() and a set() method make this work.
See the documentation on how this works.

Highlighting duplicate words in an HTML page

I have a table that contains v-html results (thus the text inside the table would not be there until the page is rendered). I would like to compare two rows and if they have duplicate words then they should be highlighted.
Here is an example project of what I wanted, but way beyond the scope of what I need. My question seems most like this one in the stacks but it requires that the words be defined, I want the page to find them itself.
For example, this would be the expected output:
<table>
<tr>
<td v-html="link.orderdesciption">
order:<br />
<mark> TV </mark><br /> <!--note that the contents of the td would not appear in markup due to being v-html-->
PS3 <br />
Laptop
</td>
<td>
qty:<br />
1<br />
2<br />
1<br />
</td>
</tr>
<tr>
<td>
----------------
</td>
<td>
----------------
</td>
</tr>
<tr>
<td v-html="link.orderrecieved">
recieved:<br /> <!--same note as above, v-html only shows-->
<mark> TV </mark><br />
Desktop<br />
</td>
</tr>
</table>
I've been working on this but I have really no idea where to go from here:
var text = $('td').text(),
words = text.split(' '),
sortedWords = words.slice(0).sort(),
duplicateWords = [];
for (var i=0; i<sortedWords.length-1; i++) {
if (sortedWords[i+1] == sortedWords[i]) {
duplicateWords.push(sortedWords[i]);
}
}
duplicateWords = $.unique(duplicateWords);
Thanks for any advice,
Use reduce to get the duplicate words, then you can iterate over tds to check in the text in it is present
within the duplicate words Array. If yes, then wrap the the text in mark tag.
const tds = document.querySelectorAll('td');
const groupByOccurence = [...tds].reduce((accu, td) => {
const textArr = td.innerHTML.split('<br>').map((word) => word.trim()).filter((word) => word.length > 0 && word.match(/[a-zA-Z]+/g));
textArr.forEach((text) => {
accu[text] = (accu[text] || 0) + 1;
});
return accu;
}, {});
const duplicateWords = Object.entries(groupByOccurence).filter(([_, val]) => val > 1).map(([key, _]) => key);
tds.forEach((td) => {
const textArr = td.innerHTML.split('<br>').map((word) => word.trim());
let str = "";
textArr.forEach((text) => {
if (duplicateWords.includes(text)) {
str += '<mark>' + text + '</mark><br>';
} else {
str += text + '<br>';
}
td.innerHTML = str;
})
});
const trs = document.querySelectorAll('tr');
trs.forEach((tr, i) => {
const specialChartds = [...tr.querySelectorAll('td')].filter((td) => !td.textContent.match(/[a-zA-Z]+/g));
if (!specialChartds) {
tr.append(tds[i]);
}
});
<table>
<tr>
<td>
order:<br /> TV
<br /> PS3 <br /> Laptop
</td>
<td>
qty:<br /> 1
<br /> 2
<br /> 1
<br />
</td>
</tr>
<tr>
<td>
----------------
</td>
<td>
----------------
</td>
</tr>
<tr>
<td>
recieved:<br /> TV <br /> Desktop
<br />
</td>
</tr>
</table>
To achieve expected result, use below option
Getting all words from table by looping $('table') with each
Creating array with all duplicate words from step1 using filter method
Looping all tds with each and adding mark tag for duplicate words
var text = $('table');
var arr = [];
//Step 1: Getting All words from table
var words = text.each(function(){
let val = $(this).text().replace(/\n|\r/g,' ').split(' ').filter(Boolean);
arr.push(...val)
})
//Step 2: Finding duplicate words
let duplicate = arr.filter(function(value,index,self){ return (self.indexOf(value) !== index && isNaN(parseInt(value)) && value.match(/[A-Za-z]/) !== null)})
//Step 3: Marking duplicate words in each row
$('td').each(function(){
let val = $(this).text();
let openMark = '<mark>'
let closeMark = '</mark>'
duplicate.forEach(v => {
if(val.indexOf(v) !== -1){
var html = $(this).html().replace(v, openMark + v + closeMark)
$(this).html(html)
}
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>
order:<br />
TV<br />
PS3 <br />
Laptop
</td>
<td>
qty:<br />
1<br />
2<br />
1<br />
</td>
</tr>
<tr>
<td>
----------------
</td>
<td>
----------------
</td>
</tr>
<tr>
<td>
recieved:<br />
TV<br />
Desktop<br />
</td>
</tr>
</table>
codepen - https://codepen.io/nagasai/pen/YoPPMv?editors=1010

jQuery Validation - How to create a method using two or more fields?

I have several start and end dates in my system, in some cases I have several start and end dates in a screen. All of them are grouped in sets of two and have the same behaviour: the start date can't be greater than the end date and the difference between them can't be greater than a user-entered input.
I know that i have to create two methods, one for validating the first case and other for the second case. The problem is that I don't know how to reference the fields, for example:
// A custom method for validating the date range.
$.validator.addMethod("dateRange", function() {
var startDate = $("#startDate").val();
var endDate = $("#endDate").val();
return isDate(startDate) && isDate(endDate) ? Date.parse(startDate) <= Date.parse(endDate) : true;
});
The problem is: this way I hard-coded the input names. This would work if I had only one set of dates per screen, but when I have more than one this won't work. How do I create a method without hard-coding the IDs of the elements that I want to use so as to use it all around the system?
I've read the online documentation in http://jqueryvalidation.org/jQuery.validator.addMethod/ but does seem to handle my problem and I think using groups wouldn't be enough to handle all elements, I probably would have to copy/paste for each set of dates.
I believe if you help me with one of the cases the second will be resolved using the same logic.
EDIT: As requested, here's the HTML
<table width="95%" id="tabela_interna">
<thead><tr valign="middle"><th colspan="6">Relatório Internações Concierge</th></tr></thead>
<tbody>
<tr valign="middle">
<td width="11%" align="left" class="td_label"><label for="dataInicialSolicitacao">Data Solicitação Inicial</label></td>
<td width="25%" align="left" class="td_dados">
<input type="text" name="filtro.dataInicialSolicitacao" size="12" value="" id="dataInicialSolicitacao" class="data"/>
</td>
<td width="11%" align="left" class="td_label"><label for="dataFinalSolicitacao">Data Solicitação Final</label></td>
<td width="25%" align="left" class="td_dados">
<input type="text" name="filtro.dataFinalSolicitacao" size="12" value="" id="dataFinalSolicitacao" class="data"/>
</td>
</tr>
<tr valign="middle">
<td width="11%" align="left" class="td_label"><label for="dataInicialLiberacao">Data Liberação Inicial</label></td>
<td width="25%" align="left" class="td_dados">
<input type="text" name="filtro.dataInicialLiberacao" size="12" value="" id="dataInicialLiberacao" class="data"/>
</td>
<td width="11%" align="left" class="td_label"><label for="dataFinalLiberacao">Data Liberação Final</label></td>
<td width="25%" align="left" class="td_dados">
<input type="text" name="filtro.dataFinalLiberacao" size="12" value="" id="dataFinalLiberacao" class="data"/>
</td>
</tr>
<tr valign="middle">
<td width="11%" align="left" class="td_label"><label for="dataInicialInternacao">Data Internação Inicial</label></td>
<td width="25%" align="left" class="td_dados">
<input type="text" name="filtro.dataInicialInternacao" size="12" value="" id="dataInicialInternacao" class="data"/>
</td>
<td width="11%" align="left" class="td_label"><label for="dataFinalInternacao">Data Internação Final</label></td>
<td width="25%" align="left" class="td_dados">
<input type="text" name="filtro.dataFinalInternacao" size="12" value="" id="dataFinalInternacao" class="data"/>
</td>
</tr>
</table>
I tend to do this using custom attributes, e.g.:
<input type="text" id="x" data-validate-date="true" data-validate-against="y" value="01/01/2000" />
<input type="text" id="y" value="1/1/2001" />
<input type="text" id="a" data-validate-date="true" data-validate-against="b" value="01/01/2000" />
<input type="text" id="b" value="4/4/2020" />
You can then define your validation rule something like:
$.validator.addMethod("dateRange", function() {
var allValid = true;
var results = [];
var datesToValidate = $("[data-validate-date]");
for(var i = 0; i < datesToValidate.length; i++) {
var d = datesToValidate[i];
var startDate = $(d).val();
var endDateSelector = "#" + $(d).attr("data-validate-against");
var endDate = $(endDateSelector).val();
results[i] = isDate(startDate) && isDate(endDate) && (Date.parse(startDate) <= Date.parse(endDate));
}
for(var j = 0; j < datesToValidate.length; j++) {
if(!(results[j] == true)) {
allValid = false;
}
}
return allValid;
});
I don't know if that's the best way to do it, but I think it could work for you.
I used the approach suggested by Blazemonger and created a method based on equalTo.
$.validator.addMethod("startDateCantBeGreaterThanEndDate", function(value, element, param) {
var target = $(param);
if (this.settings.onfocusout) {
target.unbind(".validate-startDateCantBeGreaterThanEndDate").bind("blur.validate-startDateCantBeGreaterThanEndDate", function() { $(element).valid(); });
}
value > target.val();
});
And used the method the same way equalTo does:
$("form").validate({
rules: {
"filtro.dataInicialSolicitacao": { startDateCantBeGreaterThanEndDate: "#dataFinalSolicitacao" },
},
messages: {
"filtro.dataInicialSolicitacao": { startDateCantBeGreaterThanEndDate: "Type your custom message." },
}
});

For loop breaking IndexOf

Well I've ripped my hair off because I assumed I was finished this script but suddenly adding ONE more for loop broke every single indexOf, I tried to create checks so the console wouldn't freak out, but sadly no success. using a static value for "z" or LevelCheck allows for all the indexOfs to work properly but as soon as a for loop is involved, it seems none of the indexOfs wishes to work
<script type="text/javascript">
var tempval = new Array();
function Renew(){ //Reset tempval back to val
for(d=0;d<val.length;d++){
tempval[d] = val[d];
}
}
function UpdateLoop(){
Renew();
var Levels = document.getElementById("Lvl");
if(Levels){
for(z=0; z<=Levels.value; z++){
Update(z);
}
}
}
function Update(LevelCheck){
for (i=0; i<=key.length; i++){
if(key[i] != null){
if ( key[i].indexOf("rate") > -1 ) { //Search through
for (r=0; r<=key.length; r++){
if(key[i].indexOf(key[r]) > -1){ //Finds out which form it should replace
var raw=tempval[i];
for (y=0; y<=key.length; y++){
if(key[i] != "movespeed" && key[i] != "Movrate"){ //add a check to see if string is not there
var item = document.getElementById(key[y]);
if (item) { //Make it use formula value and then put that result into a value and loop back into function until level reached. If level changed to a lower number, reset to original value and repeat
//raw=raw.replace(key[y],document.getElementById(key[y]).value); //replace this with val[y]
raw=raw.replace(key[y],tempval[y]);
}
}
else
break;
}
if(raw != null){
if(raw.indexOf("Mov") > -1){
for(x=0; x<=key.length; x++){
if(key[x].indexOf("movespeed") > -1){
//raw=raw.replace("Mov",document.getElementById(key[x]).value);
raw=raw.replace("Mov",tempval[x]);
break;
}
}
}
if(raw.indexOf("Lvl") > -1){
raw=raw.replace("Lvl",document.getElementById('Lvl').value);
}
if(raw.indexOf("Exp") > -1){
raw=raw.replace("Exp","0");
}
}
if( document.getElementById('Lvl').value == LevelCheck){
alert("Input:"+tempval[i]);
if(key[i] == "Movrate"){
document.getElementById("movespeed").value = eval(raw);
}
else{
var check = document.getElementById(key[r]);
if (check){
document.getElementById(key[r]).value = eval(raw);
}
}
}
else{
tempval[r] = eval(raw);
}
break; //So it doesn't keep searching
}
}
}
}
}
}
</script>
Html portion(This is generated via php so I just used what the browser generated)
<table>
<tbody>
<tr>
<td>Creature Name:</td>
<td>
<input type="Text" name="CName" value="Thing" size="10%">
</td>
</tr>
<tr>
<td>Level:</td>
<td>
<input type="Text" id="Lvl" name="level" onchange="" value="1" size="10%">
</td>
</tr>
<tr>
<td>movespeed:</td>
<td>
<input type="Text" name="movespeed" id="movespeed" value="1" size="10%">
</td>
</tr>
<tr>
<td>str:</td>
<td>
<input type="Text" name="str" id="str" value="4" size="10%">
</td>
</tr>
<tr>
<td>dex:</td>
<td>
<input type="Text" name="dex" id="dex" value="3" size="10%">
</td>
</tr>
<tr>
<td>int:</td>
<td>
<input type="Text" name="int" id="int" value="1" size="10%">
</td>
</tr>
<tr>
<td>will:</td>
<td>
<input type="Text" name="will" id="will" value="2" size="10%">
</td>
</tr>
<script type="text/javascript">
var key=new Array();
var val=new Array();
key.push("movespeed");
val.push("1");
key.push("str");
val.push("4");
key.push("dex");
val.push("3");
key.push("int");
val.push("1");
key.push("will");
val.push("2");
key.push("Movrate");
val.push("Mov+1");
key.push("strrate");
val.push("1+str");
key.push("dexrate");
val.push("1+dex+(str/4)");
key.push("intrate");
val.push("1+int");
key.push("willrate");
val.push("1+will");
</script>
<tr>
<td>
<input type="button" name="button" value="Use Formula" onclick="UpdateLoop();">
</td>
<td>
<input type="submit" value="Save">
</td>
Console:
Uncaught TypeError: Object 2 has no method 'indexOf' Monsters.php:62
Update Monsters.php:62
UpdateLoop Monsters.php:39
onclick Monsters.php:28
you need to change your Update function to the following:
function UpdateLoop(){
var Levels = document.getElementById("Lvl");
if(Levels){
for(z=0; z<=Levels.value; z++){
Renew();
Update(z);
}
}
}
After processing Level 0, the tempval array had the values from Level 0, which wiped out the original values from the val array.
Making this change fixed the problem in my tests: http://jsfiddle.net/jimmym715/xTUND/
oh, and what MaxArt said in the comments above is right on the money... there are far better ways to accomplish what you're going for here
Turns out that flat numbers are NOT strings so in order to safely go through every value .toString() had to be present, thanks everyone for trying though.
so it would look like:
key[i].toString().indexOf(key[r])

Categories