When using a web server as a back-end to an HTML page, for example filling in a form, the result from the back-end can be
- “Redirect to a new page”.
- A stream of HTML. This is an HTML document where the “boilerplate” or constant data, is intermixed with the variable data included inline. The HTML is displayed, and replaces the previous page.
- A stream of data containing data such as changed fields. The requesting page can use this stream to update its page.
multiple program, one for each language.
Sending back just updates.
I could have my back-end server program send back just changed elements.
#!/usr/bin/python3
import cgitb
import cgi
cgitb.enable()
print("Content-Type: application/json")
print("ColinHeader: Value")
print("ColinHeader2: Value")
# indicate end of headers
print()
#now the data
print('<p id=email>New-mail</p>')
print('<p id=pw>*********</p>')
Note: This does not send an HTML document, it just sends changed fields.
Where
- print(‘<p id=email>New-mail</p>‘) id=email is the field in the requester page to be updated
- print(‘<p id=pw>*********</p>‘) id=pw is the field in the requestor page to be updated.
The front page needs to be smarter, and be able to process these fields. See fetch in HTML sending stuff to the back-end server
In the example below it updates the content of the field with id=”passed”, so that the information returned is only displayed. It does not update the fields. This is described below.
<p id="errorField">No Errors yet</p>
<form id="target" action="cgi-bin/first.py" enctype="multipart/form-data" >
<label for="email">Enter your email: </label>
<input id=email name="email" value="test@example.com" title="colins email address">
<label for="password">Enter your pw: </label>
<input id=password name="password" value="pw">
<input type="submit">
<input type="text" onblur = "check(this)" >
</form>
<p id="passed">old info</p>
<script>
document.forms["target"].addEventListener('submit', (event) => {
event.preventDefault();
fetch("cgi-bin/first.py", {
method: 'POST',
body: new URLSearchParams(new FormData(event.target)) // event.target is the form
}).then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return (response.text());
})
.then(function(result)
{
// put the entire response into an exist field.
document.getElementById("passed").innerHTML = result;
}).catch((error) => {
console.log(error);// TODO handle error
return(error);
});
});
</script>
where
.then(function(result)
{
}
is passed the body of the html as a string. The value result is available within the function.
document.getElementById("passed").innerHTML = result;
This updates <p id=”passed”>old info</p> and gives it the content in result ( the whole data stream).
Parsing a returned document
If you are are returning a whole HTML document <!doctype>…</html> you can use DOMparser to parse the document.
var doc2 = new DOMParser().parseFromString(result, "text/xml");
let x = doc2.getElementById("...
I was using rexx and it was returning lines of data – not a whole HTML document, and so the DOMParser complained that there was an incomplete document.
Parsing data (not necessarily a document)
By adding the text to an element already in the front page you can use the page’s parser to process the data.
For example add the returned text to a field in the front page
document.getElementById("passed").innerHTML = result;
This will display all of the returned data in the field, and it will be visible ( unless the field is hidden). You can remove elements – see below.
You can now access this data using standard navigation.
My Python program had
print('<p id="z" style="color:red">incolinsz red</p>')
print('<p id="z">colins2</p>')
print('<p id="z">colins3</p>')
print('<p id="update" update="email">Updated@email</p>')
print('<p id="update" update="password">newpw</p>')
print('<p id="focus" which="email"/>')
I want to
- Display the elements with id=”z”
- Give a field a focus.
- Update the fields in the document from the data, where id=”update”, and update=”…” is the name of the field on the page.
Display the elements with id=”z”
let e = document.getElementById("errorField");
e.innerHTML = "";
let myzs = q.querySelectorAll("#z");
console.log("size of myzs" + myzs.length);
Array.from(myzs).forEach((element) => {
console.log(element.innerHTML )
e.innerHTML += element.outerHTML;
});
Where
- let e = document.getElementById(“errorField”); Locate the field where we want to store the error elements
- e.innerHTML = “”; Clear this
- let myzs = q.querySelectorAll(“#z”); Get a list of all the elements with id=”z”
- console.log(“size of myzs” + myzs.length); Debugging – display how many we have
- Array.from(myzs).forEach((element) => For each one. We need an array to use forEach
- {
- console.log(element.innerHTML ) Display the content
- e.innerHTML += element.outerHTML; Build up the field by concatenating the elements. Include the html, such as styling.
- });
Note: If element.innerHTML is used, then only the value is used. If outerHTML is used, the formatting is also copied across, for example the text <p id=”z” style=”color:red”>incolinsz red</p> is displayed in red.
Set the focus
This is an example of passing data across the interface. The Javascript looks for the first element like print(‘<p id=”focus” which=”email”/>’) with an id of focus. It uses the “which” attribute to pass a field name.
The Javascript code is
let focus=q.querySelectorAll("#focus");
if (focus.length > 0)
{
let f0 = focus[0].getAttribute("which");
let d = document.getElementById(f0);
d.focus()
d.setAttribute('style', 'color: red');
}
- let focus=q.querySelectorAll(“#focus”); Get all the elements with id=”focus”
- if (focus.length > 0) If we had at least one…
- {
- let f0 = focus[0].getAttribute(“which”); Use the first one found, and extract the value of the “which=” attribute.
- let d = document.getElementById(f0); Look for the element with the same name in the main document
- if (d !== null) if it was found
- {
- d.focus() Set the focus
- d.setAttribute(‘style’, ‘color: red’); As it is hard to see if the focus was set, change the colour of the field as well.
- }
- }
Updates the fields in the document
The Javascript is
let updates = q.querySelectorAll("#update");
Array.from(updates).forEach((element) => {
console.log(element.innerHTML )
let f0 = element.getAttribute("update");
let e = document.getElementById(f0);
if (e !== null)
{
e.value = element.innerHTML;
}
else
{
console.log("element not found:" + f0)
}
});
Where
- let updates = q.querySelectorAll(“#update”); Select all elements which have id=”update”
- Array.from(updates).forEach((element) => { We need an array to be able to use forEach
- console.log(element.innerHTML ) Display it
- let f0 = element.getAttribute(“update”); Get the value of the “update=…” attribute for the individual element
- let e = document.getElementById(f0); Locate the element in the main document
- if (e !== null) If it was found
- {
- e.value = element.innerHTML; Set the value to what was passed in
- }
- else Log we have a problem – and ignore it
- {
- console.log(“element not found:” + f0)
- }
- {
- });
Removing elements
If you want to display a subset of the elements, you may want to delete some elements.
Array.from(myzs).forEach((element) => {
x = element
x.parentNode.removeChild(x);
});
For the elements above with id=”z” the code does
- Array.from(myzs).forEach((element) => { Create an array so you can use forEach
- x = element save it
- x.parentNode.removeChild(x); Delete it
- });
Create a new field
If you want to create a new field and insert the data you can do
// append data to an existing field.
var d = document.createElement('div');
d.setAttribute("id", "Special");
var myPara = document.getElementById("passed");
myPara.appendChild(d);
d.innerHTML = result;
This does
- // append data to an existing field.
- var d = document.createElement(‘div’); create a div section
- d.setAttribute(“id”, “Special”); and give it a name
- var myPara = document.getElementById(“passed”); locate the element in the document with the id “passed“.
- myPara.appendChild(d); Attach our new field to the item.
- d.innerHTML = result; Sets the content to what was passed back.
You will see the data appear on the web page.
Note: if you execute the page more than one, you will get more and more data
2 thoughts on “Updating a web page from a server – sending back just the updates”