|
Making a fetch call and getting html back, like so:
<tr>
<td class="heading">JGServices</td>
<td class="numeric-amount">
<input type="text" size=10 value="99.00" onfocus="this.blur()">
</td>
<tr>
<tr>
<td class="heading">ShippingHandling</td>
<td class="numeric-amount">
<input type="text" size=10 value="25.00" onfocus="this.blur()">
</td>
<tr>
<tr>
<td class="heading">District</td>
<td class="numeric-amount">
<input type="text" size=10 value="123.00" onfocus="this.blur()">
</td>
<tr>
<tr>
<td class="heading">Penalty</td>
<td class="numeric-amount">
<input type="text" size=10 value="250.00" onfocus="this.blur()">
</td>
<tr>
...then using javascript to append it to the TBODY tag of the relevant table. I've tried two ways:
let T = document.getElementById('tblFees');
let t = T.querySelector('tbody');
let ih = t.innerHTML;
ih += data;
t.innerHTML = ih;
...and...
let T = document.getElementById('tblFees');
let t = T.querySelector('tbody');
t.insertAdjacentHTML('beforeend', data);
And in both cases, the browser renders it like this:
<tr>
<td class="heading">JGServices</td>
<td class="numeric-amount">
<input type="text" size="10" value="99.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
<tr>
<td class="heading">ShippingHandling</td>
<td class="numeric-amount">
<input type="text" size="10" value="25.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
<tr>
<td class="heading">District</td>
<td class="numeric-amount">
<input type="text" size="10" value="123.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
<tr>
<td class="heading">Penalty</td>
<td class="numeric-amount">
<input type="text" size="10" value="250.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
I can't figure out why or how to stop the extra, empty rows from appearing. Anyone have any ideas?
- Bill
Measure with a micrometer. Mark with a crayon. Cut with an ax.
|
|
|
|
|
What is data ?
From a cursory look, it seems likely to be a text-string which holds "<tr></tr>"
Updating the innerHTML of an element is discouraged, since it causes a complete recalculation of it and its children for the purposes of display. A better approach is to create elements and then append them to their parents.
Depending on the quantity of content to be added, the <template> may be the best way of creating all the new elements.
As a simple example, let's create a link
let a =document.createElement('a');
a.textContent = "Goto google homepage";
a.href = "<a href="https:
document.body.appendChild(a);
Which, is a much better approach than:
let parent = document.body;
parent.innerHTML += "<a href='www.google.com'>Goto google homepage</a>"
|
|
|
|
|
Quote:
<tr>
<td class="heading">JGServices</td>
<td class="numeric-amount">
<input type="text" size=10 value="99.00" onfocus="this.blur()">
</td>
<tr>
<tr>
... Your HTML has no closing </tr> tags; instead, it has two opening <tr> tags.
The browser will do its best to cope with this invalid HTML; a new opening <tr> tag will automatically terminate the previous row and start a new one.
But since you have two of them in a row, you end up with a blank row every time you have <tr><tr> .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: <tr><tr>. Reminds me of the policemen's song in The Pirates of Penzance.
|
|
|
|
|
Making a fetch call and getting html back, like so:
<tr>
<td class="heading">JGServices</td>
<td class="numeric-amount">
<input type="text" size=10 value="99.00" onfocus="this.blur()">
</td>
<tr>
<tr>
<td class="heading">ShippingHandling</td>
<td class="numeric-amount">
<input type="text" size=10 value="25.00" onfocus="this.blur()">
</td>
<tr>
<tr>
<td class="heading">District</td>
<td class="numeric-amount">
<input type="text" size=10 value="123.00" onfocus="this.blur()">
</td>
<tr>
<tr>
<td class="heading">Penalty</td>
<td class="numeric-amount">
<input type="text" size=10 value="250.00" onfocus="this.blur()">
</td>
<tr>
...then using javascript to append it to the TBODY tag of the relevant table. I've tried two ways:
let T = document.getElementById('tblFees');
let t = T.querySelector('tbody');
let ih = t.innerHTML;
ih += data;
t.innerHTML = ih;
...and...
let T = document.getElementById('tblFees');
let t = T.querySelector('tbody');
t.insertAdjacentHTML('beforeend', data);
And in both cases, the browser renders it like this:
<tr>
<td class="heading">JGServices</td>
<td class="numeric-amount">
<input type="text" size="10" value="99.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
<tr>
<td class="heading">ShippingHandling</td>
<td class="numeric-amount">
<input type="text" size="10" value="25.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
<tr>
<td class="heading">District</td>
<td class="numeric-amount">
<input type="text" size="10" value="123.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
<tr>
<td class="heading">Penalty</td>
<td class="numeric-amount">
<input type="text" size="10" value="250.00" onfocus="this.blur()">
</td>
</tr>
<tr></tr>
I can't figure out why or how to stop the extra, empty rows from appearing. Anyone have any ideas?
- Bill
Measure with a micrometer. Mark with a crayon. Cut with an ax.
|
|
|
|
|
I have been racking my brain trying to figure this out. All I want to do is have a element come from the right edge of screen into the center of the screen slowly. I'm trying to use the "transition" method via javascript and I'm just lost. I want this to happen as soon as a click on a button control. Please help!!!
Thanks!
|
|
|
|
|
Sometimes I use JavaScript to animate elements, and other times I use CSS to assign the object with animation parameters. Using CSS to animate an element is extremely simple. You specify the CSS property that you want to animate. For example, if I wanted to animate an element from point A, to point B on the screen, I would set the element's CSS parameters to animate any change in the element's top/left CSS value. From there, it's only a matter of setting the element's top or left position to a different value, and the animation occurs entirely on its own. Make sure that the div element you want to move has its position property set to "absolute", otherwise, the element will not be able to change its location on the screen. I'll include some JavaScript code that I've written which will provide you with an example.
function default_config_elem_for_animation(elem_id) {
var element = null;
var animations_on = null;
animations_on = global_animations_on;
if (animations_on === true) {
element = document.getElementById(elem_id);
if (element !== null) {
element.style.transitionProperty = "left, top, width, height, box-shadow";
element.style.transitionDuration = "0.3" + "s";
element.style.transitionDelay = "0.007" + "s";
element.style.transitionTimingFunction = "cubic-bezier(0, .55, .45, 1)";
}
}
}
|
|
|
|
|
Dear all,
I'm currently dealing with unit tests using Jasmine/KarmaRunner.
I'm wondering whether it is possible, that I can be shure,
that a tested method does not make other calls than the monitored.
I'v learned so far, how I can check the count, arguments and order
of calls from the tested method, which I expect.
But what if someone inserts a new line into the tested method,
that is unknown in the test und does "strange other things"...
Is there something like "Jasmine.allCalls( object, 'method')...?
Thx in advance and best regards!
Please stay objective and friendly
|
|
|
|
|
Perhaps you want to look at code coverage? Following in google returns results for me (addins for Jasmine.)
javascript jasmine code coverage
|
|
|
|
|
Hello jschell,
THX a lot for your reply and contribution.
No, the way to monitor code coverage was not ment.
Code coverage is very important, I use "ng test --code-coverage" and "..../coverage/TechRadar/lcov-report/index.html" for this.
What I want to accomplish is, that an existing unit test turns red, when a new call to some method or function is inserted,
that is not monitored by the test.
May be a method looks like this (simple example):
a() {
this.b(1);
this.c('x');
}
I write a test, thats reflects both calls, order and arguments.
Now (later) someone inserts a new call into the method and the method looks now like this:
a() {
this.b(1);
this.d();
this.c('x');
}
I want the test to turn red then.
I hope, I could make it somewhat clearer now
THX and best regards!
|
|
|
|
|
NoMoreStackOverflow wrote: that a tested method does not make other calls than the monitored
Looking at that again and based on your other response....
No I doubt that exists. I have no idea how a test framework would even implement that. It would at a minimum require that the test code would have to specify every call that the code would make.
Only reasonable way I could even think that part would work is that every single method call would need to be mocked. Because otherwise a call to another class could then call to another method that was not tracked.
Additionally I suspect that maintaining it would be a maintenance nightmare.
A unit test should test that the method works. Not how the method implemented the solution.
|
|
|
|
|
Hello jschell,
THX a lot again for your reply and contribution
I have no idea about how to implement such a testing framework.
I just had that idea about "what if" and thats why I asked the question
Also a solution (if there is any) should be easy to implement and handle for me
So thanks again and maybe at some pt in the future I'll get a clue..
Best Regards
|
|
|
|
|
I wrote a function, where one can update an invoice. So the user clicks edit, the modal pops up, they change the price, and the function calls an API, updates the database, and processes the returned data.
Then it calls a function within, that changes the invoice price on the page, and creates a mutation observer to detect the price change, and tallies up the invoice cost, and changes the total at the bottom.
The purpose of this mutation observer, is to wait for the DOM to update the cost, and when the DOM signals it's been done, then go back to the DOM and tally up the cost, and change the total cost span element value.
Everything works, but it only works if you do this twice. Like if I edit using the modal, submit, the observer doesn't fire. but if I edit the invoice again, then it works.
Should I call my function within my function again?
Or am I missing something here, and need to redesign the whole thing.
I'm reluctant to post any code, because the function is huge, I'll post the basics here.
I'd hate to have to split code up here, but might have to. move the mutation observer outside the posted function, to inside the API function call.
I want to do this the correct way, so it doesn't come back on me and works every time.
Calling function
function callApi() {
Prepare to send data
fetch {
.then(data => {
process data
call the function below
}
}
The function called after fetch, I can target the entire invoice within the DIV, but I targeted the single span element that contains the cost.
export function updateAnyTypeInvoiceInvoiceRecordMutationObservable(classCode, catalogId, invRecordId, jsonData, data) {
Javascript that changes the invoice values
const observer = new MutationObserver(mutationsList => {
for (const mutation of mutationsList) {
console.log('Text content has changed:', mutation.target.textContent);
Code that adds up all the invoice cost, and changes the total at the bottom
let mutationRecords = observer.takeRecords();
console.log(mutationRecords);
observer.disconnect();
}
});
const config = { childList: true, subtree: true, characterData: true };
const targetNode = document.getElementById('invInvoiceAmount_' + classCode + '_' + invRecordId);<br />
observer.observe(targetNode, config);
Perhaps, call this function again here?
} catch (error) {
console.log('updateAnyTypeInvoiceInvoiceRecordMutationObservable Error', error);
alert('updateAnyTypeInvoiceInvoiceRecordMutationObservable Error: ' + error);
}
}
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Strange how when I post something here, it makes me rethink the problem in a different way.
I concluded that I need to create the observer first, populate that observer with code to update the totals posted at the bottom, and then run the code to change the invoice. Pretty much backwards in order, but I get it now. At least I think this is correct, and it works so far, but I haven't tested enough to confirm that it doesn't conflict with anything.
Makes sense now, setup the mutation observer, program the response when it fires, then run the code to update the invoice.
export function updateAnyTypeInvoiceInvoiceRecordMutationObservable(classCode, catalogId, invRecordId, jsonData, data) {
const observer = new MutationObserver(mutationsList => {
for (const mutation of mutationsList) {
console.log('Text content has changed:', mutation.target.textContent);
Code that adds up all the invoice cost, and changes the total at the bottom
let mutationRecords = observer.takeRecords();
console.log(mutationRecords);
observer.disconnect();
}
});
const config = { childList: true, subtree: true, characterData: true };
const targetNode = document.getElementById('invInvoiceAmount_' + classCode + '_' + invRecordId);<br />
observer.observe(targetNode, config);
Javascript that changes the invoice values called last
} catch (error) {
console.log('updateAnyTypeInvoiceInvoiceRecordMutationObservable Error', error);
alert('updateAnyTypeInvoiceInvoiceRecordMutationObservable Error: ' + error);
}
}
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
jkirkerx wrote: I concluded that I need to create the observer first, populate that observer with code to update the totals posted at the bottom, and then run the code to change the invoice.
Correct - the mutation observer can't notify of mutations that occurred before you started observing them.
That leads to the question of why it seems to work the second time. Since the first observer is only disconnected once a mutation has been observed, it will still be waiting to observe a mutation when the second update is applied.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
It's my first time working with this, and it took me awhile to figure out how it works. That's for confirming my thought on this!
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Tammy Gombez wrote: I'm currently facing a perplexing issue Do you mean why have you posted a C++ question in the Javascript forum?
|
|
|
|
|
More like "How do I get banned for spam as quickly as possible?"
Spammer in JavaScript forum (Tammy Gombez)[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Still learning.
I'm using the SWAPI - The Star Wars API for my test data.
I can fetch the data from https://swapi.dev/api/people (no problem)
But I'd like to be able to iterate over the films array to fetch each movie name.
I'm not sure what the syntax I should use, or if it is the proper way to do it.
the getFilmName function returns
[object Promise]
I tried adding an await before the call to getFilmName and give does not "compile" :
const filmName = await getFilmName(filmURL);
Thanks.
async function getFilmName(url) {
const res = await fetch(url);
const data = await res.json();
return data.title;
}
async function getPeople() {
console.log("fetchNames");
const url = "<a href="https:
const res = await fetch(url);
const data = await res.json();
console.log(data);
const results = data.results;
results.map((person) => {
console.log(<code>${person.name} stars in :</code>);
person.films.map((filmURL) => {
console.log(filmURL);
const filmName = getFilmName(filmURL);
console.log(<code>filmName: ${filmName}</code>);
});
});
}
getPeople();
Thanks.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
Maximilien wrote: I tried adding an await before the call to getFilmName and give does not "compile" : The calling function would also have to be asynchronous or called within the context of a promise.
async function blah() {
try {
const response = await fetch('blah.com');
return await response.json();
} catch(ex) {
console.error(ex);
}
}
blah();
(async () => {
await blah();
})();
Jeremy Falcon
|
|
|
|
|
Thanks, but that does not help with my example.
My problem is with the getFilmName function (or the call to).
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
Jeremy is correct - any function that uses await needs to be marked as async .
In this case, the callback to map would need to be async . However, that would result in an array of promises.
But since you're not doing anything with the array returned from either map call, that won't make much difference.
Assuming you actually want to do something with the results, try:
async function getPeople() {
console.log("fetchNames");
const url = "https://swapi.dev/api/people";
const res = await fetch(url);
const data = await res.json();
console.log(data);
const results = data.results;
const promises = results.map(async (person) => {
const filmPromises = person.films.map(getFilmName);
const films = await Promise.all(filmPromises);
return { person, films };
});
return await Promise.all(promises);
}
(async () => {
const people = await getPeople();
people.forEach(person => {
console.log(`${person.person.name} stars in :`);
person.films.forEach(filmName => console.log(filmName));
});
})(); Demo[^]
Promise.all() - JavaScript | MDN[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks,
I'll study this.
I'm not sure I still understand.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
I'll help you with the array of promises part, but not until I get a thumbs up too.
Jeremy Falcon
|
|
|
|
|
I promise I will.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|