how to create html table results from JSON data - json

I have code that uses AJAX and JSON to output a chunk of SQL data when you do a search and I am trying to separate the data some and have it display into an HTML table. At first it was just the SQL data but I put some tags into the innerHTML line to at least visually separate it, however I would really like to be able to put each column into a separate table cell. Any ideas on how to do that would be greatly appreciated. Here is the code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="js/jquery-2.2.2.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>AJAX Search Example</title>
<script>
function fetch() {
// (A) GET SEARCH TERM
var data = new FormData();
data.append('search', document.getElementById("search").value);
data.append('ajax', 1);
// (B) AJAX SEARCH REQUEST
var xhr = new XMLHttpRequest();
// (CHANGE1) USING ONREADYSTATECHNAGE INSTEAD OF ONLOAD
xhr.onreadystatechange = function (event) {
// (CHANGE2) we will check if ajax process has completed or not it goes from 1,2,3,4 means end.
if(this.readyState == 4){
// (CHANGE2) when ready state comes to 4 we then check what response status was it if it is 200 good else error.
if(this.status == 200){
// (CHANGE3) MOVED ALL YOUR CODE HERE
// (CHANGE4) we need to use responseText instead of response because JSON comes as string that is why we are parsing it to be converted into array
var results = JSON.parse(this.responseText);
//I have added just a measure to check what the out put is you can remove it latter. open dev console to get the result.
console.log(results);
wrapper = document.getElementById("results");
if (results.length > 0) {
wrapper.innerHTML = "";
// (CHANGE5) UPDATED data ref with results
for (i = 0; i < results.length; i++) {
let line = document.createElement("div");
//it is just as simple to create id only it must start with alphabet not number
line.id=`res${[i]}`;
//we created span tag to display price and this is what we will change. on that span we will create a data-price attribute which will hold original price and we will run calculations using that number
//BIG CHANGE
//BIG CHANGE
//since after parsing individual record will be in Js object so we dont need to access them like array results[i]['item']
//we access them with dot notation results[i].item
line.innerHTML = `Category:${results[i].category} - OEM #:${results[i].oemnumber} - Price:$<span data-price='${results[i].price}'>${results[i].price}</span>
select discount >>
%70
%60
%50 100%`;
wrapper.appendChild(line);
}
// (CHANGE6) We moved event listeners here so any newly added elements will be updated.
//get all the links and apply event listener through loop
var links = document.querySelectorAll('a');
for ( ii = 0; ii < links.length; ii++) {
links[ii].addEventListener("click", function(event) {
//capture link value and get number to be converted to percentage
var percentage = event.target.innerText.match(/\d+/)[0]/100;
//capture the data-price which is within same div as anchor link
var pricetarget = event.target.parentElement.querySelector('[data-price]');
//get value of data-price
var actualprice= pricetarget.dataset.price;
//run math and chnage the value on display
pricetarget.innerHTML=(actualprice*percentage).toFixed(2);
});
}
} else { wrapper.innerHTML = "No results found"; }
} else {
//if reponse code is other ethan 200
alert('INTERNET DEAD OR AJAX FAILED ');
}
}
};
// (CHANGE7) We moved open event to end so everything is ready before it fires.
xhr.open('POST', "2-search.php");
xhr.send(data);
return false;
};
</script>
</head>
<body>
<!-- (A) SEARCH FORM -->
<form ID='myForm' onsubmit="return fetch();">
<h1>SEARCH FOR CATALYTIC CONVERTER</h1>
<input type="text" id="search" required/>
<input type="submit" value="Search"/>
</form>
<!-- (B) SEARCH RESULTS -->
<div id="results"></div>
</body>
</html>
Here is where I added the tags to at least visually separate it: "line.innerHTML = `Category:${results[i].category} - OEM #:${results[i].oemnumber} - Price:$${results[i].price}"
What I want to do is have Category, OEM #, and price each in a separate table cell. Thank you for any help offered.

You can simply generate trs inside your for (i = 0; i < results.len.. like you are already doing for divs . So , just use += to append every new tr inside tbody and then append this to your table
Demo Code :
//suppose json look like below :)
var results = [{
"category": "A",
"price": 13,
"oemnumber": "d1A"
}, {
"category": "B",
"price": 15,
"oemnumber": "d1B"
}, {
"category": "C",
"price": 12,
"oemnumber": "d1C"
}]
fetch();
function fetch() {
/* var data = new FormData();
data.append('search', document.getElementById("search").value);
data.append('ajax', 1);
var xhr = new XMLHttpRequest();
// (CHANGE1) USING ONREADYSTATECHNAGE INSTEAD OF ONLOAD
//some codes/..
console.log(results);*/
wrapper = document.getElementById("results");
wrapper.innerHTML = "";
var rows = "";
if (results.length > 0) {
for (i = 0; i < results.length; i++) {
//generate trs
rows += `<tr id=res${[i]}><td>${results[i].category}</td><td>${results[i].oemnumber}</td><td>$<span data-price='${results[i].price}'>${results[i].price}</span>
select discount >>
%70
%60
%50 100%</td></tr>`;
}
wrapper.innerHTML = `<table class="table">
<thead><th>Category</th><th>OEM</th><th>Price</th></thead><tbody>${rows}</tbody></table>`;
//sme other codes,,
}
};
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<div id="results">
</div>

Related

Why does this Javascript function rewrite the innerHTML of one div but not the other?

I'm using NodeJS to query a MySQL database for a single entry of a journal, but the results aren't going to both of the assigned divs. I have an iFrame in my center column, dedicated to two divs (one hidden at any given time). One div is a read-only page for the journal entry, and the other one contains a TinyMCE rich-text editor. I have buttons in left column to switch between the views.
The rich-text editor loads properly on initial load of page, but doesn't update as I navigate with the calendar; the read-only innerHTML does update properly as I navigate.
calDt[] is an array that holds dates. calDt[0] is the active date, while calDt[1] holds a dummy date used for navigating the calendar without changing the entry.
app.js:
app.get('/getdata/:dateday', (req, res) => {
let sql = `SELECT entry FROM main where dateID ='${req.params.dateday}'`
let query = db.query(sql, (err, results) => {
if(err) {
throw err
}
res.send(JSON.stringify(results));
})
})
middle-left.ejs
<button style= "height:22px"; type="button" onclick="readDivHere()">Lock</button>
<button style= "height:22px"; type="button" onclick="editDivHere()">Edit</button></div>
<script> // the Lock button brings us back to the completed entry in the middle stuff
function readDivHere() {
document.getElementById('frame1').contentWindow.readDivHere();
document.getElementById('frame1').scrolling = "yes";
}
</script>
<script> // the Edit button will bring tinymce rich-text editor to the middle stuff
function editDivHere() {
document.getElementById('frame1').contentWindow.editDivHere();
document.getElementById('frame1').scrolling = "no";
}
</script>
middle-center.ejs
<iframe id="frame1" class="entryon" src="" frameborder="0px"></iframe>
<script>
document.getElementById("frame1").src = "iframe";
</script>
iframe.ejs
<div id="readDiv" class="here" style="display: block; background: white; padding-top: 0px; padding-left: 10px; padding-right: 8px; min-height: 810px; width: 967px;"><%- include ('entry'); %></div>
<div id="editDiv" class="here" style="display: none; padding: 0px;" ><%- include ('editPage'); %></div>
<script> //function that switches from rich-text editor back to real entry
function readDivHere() { // here we run a function to update text of read-only entry
document.getElementById("readDiv").style.display="block";
document.getElementById("editDiv").style.display="none";
}
</script>
<script> //function that switches from read-only entry to rich-text editor
function editDivHere() {
document.getElementById("readDiv").style.display="none";
document.getElementById("editDiv").style.display="block";
}
</script>
entry.ejs
<div id="readOnlyEntry"></div>
<script>
// load the active entry into the middle column for proper reading
function loadEntry(p) {
var x = parent.calDt[1].getFullYear();
var y = parent.calDt[1].getMonth();
y = y + 1;
if (y < 10) {
y = "0" + y;
};
if (p < 10) {
p = "0" + p;
}
var newDate = x + "" + y + "" + p; // p is a date formatted like 20210808
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                const text = this.responseText;
                const obj = JSON.parse(text);
document.getElementById("readOnlyEntry").innerHTML = obj[0].entry;
document.getElementById("richTextEd").innerHTML = obj[0].entry; // doesn't work!
            }
xhttp.open("GET", "../getdata/" + newDate, true);
        xhttp.send();
}
</script>
<script>
// rich-text editor populates correctly on load
loadEntry(parent.calDt[0].getDate());
</script>
editPage.ejs
<%- include ('tinymce'); %>
<form method="POST" action="../result" enctype="multipart/form-data">
<textarea name="content" id="richTextEd">Here's the default text.</textarea>
</form>
calendar-clicker.ejs
var p = x.innerHTML; // get the value of the calendar cell text (i.e. day of the month)
p = p.match(/\>(.*)\</)[1];
var d = calDt[1].getFullYear(); // what year is the calendar referencing?
var q = calDt[1].getMonth(); // what month is the calendar referencing?
q = q + 1; // compensate for javascript's weird month offset
calDt[0] = new Date(q + "/" + p + "/" + d); // assign a new global date variable
calDt[1] = calDt[0]; // temporarily reset navigation date to active date
document.getElementById('frame1').contentWindow.loadEntry(p);
Does the failure have to do with assigning the innerHTML to a different .ejs? If I put the form into the same div as the read-only entry, the form still fails to update as I navigate.
Solved it.
In entry.ejs, I replaced...
document.getElementById("richTextEd").innerHTML = obj[0].entry;
with
tinymce.get("richTextEd").setContent(obj[0].entry);
https://www.tiny.cloud/blog/how-to-get-content-and-set-content-in-tinymce/

Make basic search in array with if and else

I am trying to make a basic search function. if input.value does exist in array alert message, if not, push it to array ans show in HTML. I think I have already most of work done, but there is somewhere a mistake. Thank you in advance for your help guys .)
<div id="main">
<input id="inputForMyDict">
<button id="ButtonForInputSave" onclick="buttonSave()">Speichern</button>
<p id="demo"></p>
</div>
<script>
var myDict = [];
var buttonSave = function() {
for (var i = 0; i < myDict.length; i++) {
if (document.getElementById("inputForMyDict").value = myDict[i]) {
alert("your input is already in your list");
} else {
myDict.push(document.getElementById("inputForMyDict").value);
document.getElementById("demo").innerHTML = myDict;
}
}
}
In javascript, there are 2 ways to do a comparison.
Strict Equality Operator === strict equality operator.
If you are not sure about the exact datatype for the values being compared, then you can use the == for comparison.
The line document.getElementById("inputForMyDict").value = myDict[i] needs comparison operator and not the assignment operator (=). So you need to replace the = with either == or ===.
so your javascript code should look like
var buttonSave = function() {
for (var i = 0; i < myDict.length; i++) {
if (document.getElementById("inputForMyDict").value == myDict[i]) {
// If you know exact data type, then use the below line instead and comment the above line if (document.getElementById("inputForMyDict").value === myDict[i]) {
alert("your input is already in your list");
} else {
myDict.push(document.getElementById("inputForMyDict").value);
document.getElementById("demo").innerHTML = myDict;
}
}
}
Update1: Based on the clarification, provided by comments, you don't need to have a for loop to check for existence of element in array. Javascript provides a convenient way by indexOf method on an array. indexOf method check for the existence of an element in an array and returns the index of the element in the Array. However, if the element is not found then it returns -1.
Full code below which should work.
<!DOCTYPE html>
<html>
<body>
<div id="main">
<input id="inputForMyDict">
<button id="ButtonForInputSave" onclick="buttonSave()">Speichern</button>
<p id="demo"></p>
</div>
<script>
var myDict = [];
var buttonSave = function() {
//for (var i = 0; i < myDict.length; i++) {
var valueInTextbox = document.getElementById("inputForMyDict").value;
if(myDict.indexOf(valueInTextbox) > -1){
alert("your input is already in your list");
} else {
myDict.push(valueInTextbox);
document.getElementById("demo").innerHTML = myDict;
}
}
//}
</script>
</body>
</html>

How to Read a text file using Java script and display it in column fashion in HTML.?

This is the code which reads the text file using the Jscript and displays it in HTML. But i need it to display it in table.
How to display it in Table.
< this is my first question so i hope i get solution >
`
Read File (via User Input selection)
var reader; //GLOBAL File Reader object for demo purpose only
/**
* Check for the various File API support.
*/
function checkFileAPI() {
if (window.File && window.FileReader && window.FileList && window.Blob) {
reader = new FileReader();
return true;
} else {
alert('The File APIs are not fully supported by your browser. Fallback required.');
return false;
}
}
/**
* read text input
*/
function readText(filePath) {
var output = ""; //placeholder for text output
if(filePath.files && filePath.files[0]) {
reader.onload = function (e) {
output = e.target.result;
displayContents(output);
};//end onload()
reader.readAsText(filePath.files[0]);
}//end if html5 filelist support
else if(ActiveXObject && filePath) { //fallback to IE 6-8 support via ActiveX
try {
reader = new ActiveXObject("Scripting.FileSystemObject");
var file = reader.OpenTextFile(filePath, 1); //ActiveX File Object
output = file.ReadAll(); //text contents of file
file.Close(); //close file "input stream"
displayContents(output);
} catch (e) {
if (e.number == -2146827859) {
alert('Unable to access local files due to browser security settings. ' +
'To overcome this, go to Tools->Internet Options->Security->Custom Level. ' +
'Find the setting for "Initialize and script ActiveX controls not marked as safe" and change it to "Enable" or "Prompt"');
}
}
}
else { //this is where you could fallback to Java Applet, Flash or similar
return false;
}
return true;
}
/**
* display content using a basic HTML replacement
*/
function displayContents(txt) {
var el = document.getElementById('main');
el.innerHTML = txt; //display output in DOM
}
</script>
</head>
<body onload="checkFileAPI();">
<div id="container">
<input type="file" onchange='readText(this)' />
<br/>
<hr/>
<h3>Contents of the Text file:</h3>
<div id="main">
...
</div>
</div>
</body>
</html>`
Please help me in this
You could format the text file like a SSV (TSV or CSV as well), then instead of ReadAll() I'd do something like this:
var file = reader.OpenTextFile(filePath, 1),
data = [], n;
while (!file.AtEndOfStream) {
data.push(file.ReadLine().split(';')); // or use some other "cell-separator"
}
Then the rest is a lot simpler and faster, if you've an empty table element in your HTML:
<table id="table"></table>
Now just create rows and cells dynamically based on the data array:
var table = document.getElementById('table'),
len = data.length,
r, row, c, cell;
for (r = 0; r < len; r++) {
row = table.insertRow(-1);
for (c = 0; c < data[r].lenght; r++) {
cell.row.insertCell(-1);
cell.innerHTML = data[r][c];
}
}

preload jQuery building of JSON results

So I am currently building an activity feed/news feed or sorts using JSON and jQuery (and of course PHP). Everything works really well, especially fetching new results. The only issue is the first load - and I'm wondering if there is some way to sort of preload the results to make it more slick?
jQuery code below:
for (var j = 0; j < jsonData.items.length; j++) {
var entryData = jsonData.items[j];
var entry = template.clone();
entry.removeClass("template");
entry.find(".message").text(entryData.statusid);
entry.find(".actName").text(entryData.name);
entry.find(".actContent").text(entryData.content);
//get the users ProfilePic
var profileImg = $("<img />");
profileImg.attr("src", "./img/" +entryData.profilePic);
profileImg.addClass("feed-user-img");
entry.find(".actProfilePic").append(profileImg);
//Get user-uploaded images.
entry.find(".actImage").text(entryData.imageKey);
if (entryData.imageKey != "")
{
var img = $("<img />"); // Create the image element
img.attr("src", "http://spartadev.s3.amazonaws.com/" + entryData.imageKey); // Set src to the s3 url plus the imageKey
entry.find(".actImage").append(img); // Append it to the element where it's supposed to be
}
spot.prepend(entry);
spot.find(".entry").first().hide().slideDown();
}

Problem in getting right result for select box

I am using jQuery as:
$(document).ready(function(){
test("price");
alert("hi");
$("#item2").change(function()
{
sort= $("#item2").val();
test(sort);
});
});
Function test() is some JavaScript function, my problem is when page loads function calls by "price" parameter. Now when I select some item from select box function test() is called using sort parameter (verify by alert box). but I am not getting the correct result. I mean when I select option from select box than also my result of test() is as with "price" , I suppose it might be the problem because of jQuery's $(document).ready(function(){,. test() function make some html code based on the parameter and show it on the web page.
Please suggest me what can be the solution
EDIT:
function test() is :
function test(sort)
{
<%
Ampliflex ms = Ampliflex.getInstance();
String solrIP = ms.getSolrIP();
String solrPort = ms.getSolrPort();
String rows = ms.getSearchResultCount();
%>
solrIP='<%= solrIP %>'; // get Solr IP address
solrPort='<%= solrPort %>'; // get Solr Port number
rows='<%= rows %>'; // get number of results to return
solrURL="http://"+solrIP+":"+solrPort;
var query="${searchStr}"; // get the query string entered by ECommerce user
query=query.replace(/[^a-zA-Z 0-9*?:.+-^""_]+/g,''); // Remove special characters
query=query.replace(/\*+/g,'*'); // Replace multiple occurrence of "*" with single "*"
var newquery=query;
if(parseInt(query)==NaN)
{
var lowerCaseQuery=query.toLowerCase();
newquery=lowerCaseQuery;
}
else{
var lowerCaseQuery=query;
}
// sort= document.getElementById("item2").value;
$.getJSON(solrURL+"/solr/db/select/?qt=dismax&wt=json&&start=0&rows="+rows+"&q="+lowerCaseQuery+"&hl=true&hl.fl=text&hl.usePhraseHighlighter=true&sort="+sort+" desc&json.wrf=?", function(result){
var highlight = new Array(result.response.numFound);
$.each(result.highlighting, function(i, hitem){
var rg = /<em>(.*?)<\/em>/g;
var res = new Array();
var match = rg.exec(hitem.text[0]);
while(match != null){
res.push(match[1])
match = rg.exec(hitem.text[0]);
}
highlight[i]=res[0]
for (j=1 ;j<res.length;j++)
{
highlight[i]= highlight[i]+","+res[j];
}
});
var html="<table><tr>"
var count=0;
var alt="NoImage";
var size="3pt";
var id;
var flag=1; // Flag for error messages
border="1";
// If no search results
if(result.response.numFound==0)
{
var msg= "<hr /><font size="+size+" >We're sorry, we found no results for <b>"+document.getElementById("queryString").value+"</font><hr />";
}
else
{
/* var msg= "<hr /><font size="+size+" >Total Results Found <b> "+ result.response.numFound+"</b> for "+"<b>"+document.getElementById("queryString").value+"</b> keyword</font><hr /> ";*/
if (newquery==lowerCaseQuery)
{
var msg= "<hr /><font size="+size+" >Total Results Found <b> "+ result.response.numFound+"</b> for "+"<b>"+query+"</b> </font><hr /> ";
}
else
{
var msg= "<hr /><font size="+size+" >There were no exact matches for <b> "+ query+"</b> , so we searched automatically for "+"<b>"+query+"</b> and yielded "+result.response.numFound+" result(s)</font><hr /> ";
}
// Parse solr response and display it on web page
$.each(result.response.docs, function(i,item){
var word = new Array();
word=highlight[item["UID_PK"]].split(",");
var result="";
var j=0;
for (j=0 ;j<=item.text.length;j++)
{
result = result+item.text[j]+"<br>";
}
for (j=0 ;j<word.length;j++)
{
result=result.replace(word[j],'<em>' + word[j] + '</em>');
}
html+="<td><table>";
var src=item.image;
id="id";
if(src!= null && src!= ""){
html+="<p><tr><td><br>"+"<img id= "+id+ " src="+src+ " border="+border+ " /></td></tr>";
count=count+1;
html += "<tr><td><b>ImagePath</b> "+ item.image+"</td></tr>";
}
// If not insert a default image
else
{
src="images/products/default.jpg";
html+="<tr><td><br><p>"+"<img id= "+id+ " src="+src+ " border="+border+" /></td></tr>";
count=count+1;
html += "<tr><td><b>ImagePath</b> "+"No image path found" +"</td></tr>";
}
html += "<tr><td>UID_PK: "+ item.UID_PK+"</td></tr>";
html += "<tr><td>Name: "+ item.name+"</td></tr>";
html+="<tr><td><b>Price: $"+item.price+"</td></tr>";
html+="<tr><td> "+result+"<br></td></tr>";
html+="</p></table></td>"
if(count%3==0)
{
html+="</tr>"
html+="<tr>"
}
});
html+="</table>"
}
$("#text_container").html(msg);
$("#result").append(html);
}
});
});
}
Your question isn't particularly clear, but your alert code only fires when the document is ready - it is not inside the "change" event function.
Try using the following to see what value is being returned when you change the select box:
$(document).ready(function(){
test("price");
$("#item2").change(function()
{
sort= $("#item2").val();
alert(sort);
test(sort);
});
});
When changing the select box, you should get an alert with the value you have chosen, which will help you understand why the test() function isn't functioning as you expect.
If you amend your question to include the HTML of the select box and the test() function itself I will amend my answer to help.
The JQuery code that you have posted is working fine. Demo: http://jsfiddle.net/DtnUr/
We need more details to figure out the issue, such as your HTML code and JS functions.