A user can search for people included in a database introducing the search terms in an input text.
I am using following Ajax script to show the database objects received from JSON:
<script type="text/javascript">
$(document).ready(function() {
// With JQuery
$("#ex6").slider();
$("#ex6").on("slide", function(slideEvt) {
$("#ex6SliderVal").text(slideEvt.value);
});
$('#keyword').on('input keyup change', function() {
var searchKeyword = $(this).val();
if (searchKeyword.length < 3) {
$('ul#content').empty()
}
if (searchKeyword.length >= 1) {
$.post('search.php', { keywords: searchKeyword }, function(data) {
$('#content').empty()
$('#content').append('<table class="table table-hover"><thead><tr><th>First Name</th><th>Last Name</th><th>Username</th></tr></thead><tbody>')
if (data == ""){
$('#content').append('No hay resultados para su búsqueda')
}
$.each(data, function() {
$('#content').append('<tr><td>'+this.nombre_doctor +'</td><td>'+ this.apellido1_doctor + '</td><td>'+ this.apellido2_doctor+'</td></tr>');
});
$('#content').append('</tbody></table>')
}, "json");
}
});
});
</script>
And this is the output when a user introduces a search term:
As you may see in the picture, the objects are not shown on the expected column.
What is wrong in the script?
When you call append with a string, jQuery constructs an object and appends that. In other words, append('<foo>') is really append($('<foo'>). The assumption in this code that append appends raw HTML is incorrect.
You want something like
var $table = $('<table class="table table-hover"><thead><tr><th>First Name</th><th>Last Name</th><th>Username</th></tr></thead></table>').appendTo('#content');
var $tbody = $('<tbody></tbody>').appendTo($table);
$.each(data, function() {
var $tr = $('<tr>').appendTo($tbody);
$('<td>').text(this.nombre_doctor).appendTo($tr);
$('<td>').text(this.apellido1_doctor).appendTo($tr);
$('<td>').text(this.apellido2_doctor).appendTo($tr);
});
// Nothing with </tbody></table> , those elements already exist
Note that your current code includes a significant vulnerability as it allows everybody who controls your data to inject arbitrary HTML and JavaScript into your website. The use of text avoids this.
You used a concate (+) function which packed all data into one column as a string. You should define 3 distinct columns to force a proper table layout.
<table width="100%" rules=groups border="0" cellspacing="0" cellpadding="0" class="table table-hover">
<colgroup>
<col width="33%" />
<col width="33%" />
<col width="33%" />
</colgroup>
Now you have a solid structure to insert your data, by column. The <th> will line up the way you have written the code.
Try building your table html as a string first, then use jquery's .html() to set it.
var htmlContents = "<table><tr><td>First column data</td><td>2nd column
data</td><td>etc</td></tr></table>";
$('#content').html(htmlContents);
That should do it.
Related
I'm trying to edit a table by adding rows, but running into an issue with the the partial view not being fully rendered (This is my assumption)
I'm loading the partials into their divs via page load and ajax calls;
<div id="preTestSteps">
</div>
<div id="mainTestSteps">
</div>
<div id="postTestSteps">
</div>
Scripts;
$(document).ready(function() {
var testSuiteExecutionId = #(Model.TestSuiteExecutionId);
var testSuiteId = #(Model.TestSuiteId);
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 1, "preTestSteps");
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 0, "mainTestSteps");
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 2, "postTestSteps");
});
function loadTestStepResultsPartialView( testSuiteExecutionId, testSuiteId, testStepType, divId) {
$.ajax({
type: 'POST',
url: '#Url.Action("DetailsTestStepResults", "TestSuiteExecutions")',
data: { 'testSuiteExecutionId': testSuiteExecutionId, 'testSuiteId': testSuiteId, 'testStepType': testStepType },
success: function(data) {
$("#" + divId).html(data);
}
});
In the partial view, the table has a unique ID which is accessed to append (view model is a list of viewmodels, using the first index is to get data which is unique for the list of logs);
<div id="#collapseStepItemName" class="collapse col-sm-12" role="tabpanel" aria-labelledby="headingOne">
<div class="card-body">
<table class="table" id="logTable_#Model[0].TestStepId#Model[0].MessageType">
<thead>
<tr>
<th width="5%"></th>
<th width="20% !important">Time</th>
<th width="75%">Message</th>
</tr>
</thead>
<tbody>
#foreach (var logEntry in Model)
{
<tr id="tableRow_#logEntry.TestStepId#logEntry.MessageType">
<td><img width="20" height="20" src="~/Content/Images/#HtmlUtilities.GetTestSuiteExecutionIconName(logEntry.LogType)" /></td>
<td><i>#logEntry.TimeStamp</i></td>
<td><i>#Html.Raw(HtmlUtilities.GetHtmlFormattedString(logEntry.Message))</i></td>
</tr>
}
</tbody>
</table>
</div>
The current test code (with hard coded tableID for the sake of testing) is the following;
var tableId = "logTable_" + 44 + "False";
var newRow = document.getElementById(tableId).insertRow();
newRow.innerHTML="<td>New row text</td><td>New row 2nd cell</td><td>Please work</td>";
The following error is thrown in the browser debug;
Uncaught TypeError: Cannot read property 'insertRow' of null
Is there a way to execute the script after the partial views are fully rendered? Or is this issue something else and not due to the views being loaded in?
I made sure the table appending script actually works by testing it on a table in the main view, and it worked as intended.
Since you're using jQuery, place this code inside document.ready function:
$(document).ready(function() {
// other stuff
var tableId = "logTable_" + #Model[0].TestStepId + #Model[0].MessageType;
var row = $('<tr>').append('<td>New row text</td><td>New row 2nd cell</td><td>Please work</td>');
$('#' + tableId).find('tbody').append(row);
});
If you insist using vanilla JS to add rows, make sure that all DOM objects are already loaded as given in example below:
document.addEventListener("DOMContentLoaded", function (ev) {
var tableId = "logTable_" + #Model[0].TestStepId + #Model[0].MessageType;
var newRow = document.getElementById(tableId).insertRow();
newRow.innerHTML="<td>New row text</td><td>New row 2nd cell</td><td>Please work</td>";
}
The reason behind insertRow has null value is that table DOM elements may not fully loaded when adding row script executes, hence row addition script should run when all required DOM elements are complete.
Demo example: JSFiddle
<script type="text/javascript">
function LoadData(){
var url = serverURL+"/List.php";
$.ajax({
type: "GET",
url: url,
dataType: "json",
success: function(data){
$.each(data.data, function (key, value) {
var doc_id=value['id'];
var doc_name=value['name'];
var doc_speci = value['specialize'];
$("#myTable").append("<tr><td>"+doc_name+"</td><td>"+doc_speci+"</td><td class='retrieve' data-did="+doc_id+" style='cursor: pointer;'>EDIT</td></tr>");
});
},
error: function(data){
toastr.error("Opps! Something went wrong");
$(".se-pre-con").fadeOut("slow");
},
});
}
</script>
The above appends a tr to my html table below.
The HTML TABLE is as follows:
<table id="myTable" class='table table-bordered table-hover table-striped'>
<tr>
<th>Name</th>
<th>Specialization</th>
<th>Action</th>
</tr>
</table>
Now i want to retrieve the id from the data attribute from td class retrieve so that i can send the id and redirect it to other page for editing.
// Clicks the edit field
$("td.retrieve").on("click", function(e) {
var id = $(e.currentTarget).attr("data-did");
// do with the ID what you want
alert(id);
});
I'm aware that jQuery has a "data(...)" function but I've run into issues with that sometimes in the past. "attr(...)" will do something similar but relies specifically on the attribute instead of stored objects.
First, to add your data attribute you should make sure you add quotes around the value:
data-did='"+doc_id+"'...
So the rendered cell must look something like this:
<td class='retrieve' data-did='n' style='cursor: pointer;'>EDIT</td>
(where n is some value)
Then you can easily retrieve this value with jQuery:
$('specific-td').data('did'); //specific-td referes to a specific cell in a row, you must write that, this is just an example
To get all of the rows:
var ids = [];
$('.retrieve').each(function() {
ids.push($(this).data('did'));
});
Example:
If you have a button for example:
$('#myTable').on('click', '.retrieve input[type="button"]', function() {
var id = $(this).parent().data('did');
alert(id);
});
JSFiddle: https://jsfiddle.net/y2an0fu7/1/
I'm currently learning Javascript & HTML and would like some advice.
I've created a very basic quiz using the following Javascript code and I'd like to store the PlayerName and TotalScore in a dynamic table which uses the localStorage functionality available, at the moment I'm simply storing the current PlayerName and TotalScore using the Document.write function in my HTML page, any thoughts, Can anyone help ?
I thought about creating an array called ListOfNames but unsure how to continually add to it the next time the browser opens without declaring the variable as just [ ] again ?
var getUsername = false;
var playerName = "string";
playerName = prompt("Please state your player name");
while( getUsername == false) {
if (confirm("Are you happy with " + playerName + " ?\n Press OK to proceed
OR Cancel to change player name")) {
getUsername = true;
}
else {
playerName = prompt("Please provide a valid player name");
}
};
alert(" Welcome to my Quiz \n\nPlease answer the following questions as
accurately as possible \n\nI will then give you a totalscore at the end");
var totalScore = 0;
var question1 = prompt(" Question 1.\n\nWhich country is José
Mourino from?");
if (question1 == "Portugal" || question1 =="portugal") {
totalScore++;
};
alert("You Scored " +totalScore + " out of a possible 1");
alert("Well done");
var listOfPlayers = [];
listOfPlayers.push(playerName);
localStorage.listOfPlayers = listOfPlayers;
console.log(listOfPlayers);
My HTML is currently set like this which correctly populates the CURRENT playerName and score, I would like to store the ONGOING results and consistently grow the table among friends etc ::
<table class="table">
<thead>
<tr>
<th>Player Name</th>
<th>Score</th>
</tr>
</thead>
<tbody>
<tr class="success">
<td><script> document.write(playerName)</script></td>
<td><script> document.write(totalScore)</script></td>
</tr>
<tr class="success">
<td>Liam</td>
<td>11</td>
</tr>
You should not use document.write() as this is an ancient way to include content into a document and leads to JavaScript having to be written in the correct sequence (as you've found out) and can lead to overwriting of the document if you aren't careful.
Instead, you can have the skeleton of a table hard-coded in your page (as you have done), but use the API for a table element to dynamically add rows, cells and cell content to it as needed.
Here's an example:
// Place the following code in a <script> element that comes
// just before the closing body tag (</body>)
// Get references to the table and the button.
var btnAdd = document.getElementById("btnAddRow");
var tbl = document.getElementById("tblOutput");
// Set up a click event handling function for the button
btnAdd.addEventListener("click", function(){
// Set up array for new data. The data can come from anywhere.
// Here, I'm just hard coding it.
var data = ["Scott", "999", "42"];
// Create a new row on the table
var row = tbl.insertRow();
// Loop through the array to insert the data into the cells of the new row
// and to store the data in localStorage
data.forEach(function(value, index){
// Insert a cell in the row at correct index
var newCell = row.insertCell(index);
// Place content from the array in the cell - this can be any data from anywhere
newCell.textContent = value;
});
// Append the array to previously stored data
localStorage.setItem("playerData", localStorage.getItem("playerData") + data.join(","));
});
/* Just some styling for the table */
table, td, th { border:1px solid black; }
td { padding: 3px; }
tr:nth-child(even){
background-color:rgba(255, 255, 0, .3);
}
<table id="tblOutput">
<thead>
<th>Name</th>
<th>ID</th>
<th>Level</th>
</thead>
</table>
<button id="btnAddRow">Add New Row</button>
I would like to populate an existing table with json data. I found an example on stackoverflow which does this but with only one column of data. The json data has three sets of data which requires obviously 3 columns. I have experimented with only one row but the jquery code (below) incorrectly displays the table.
<table class="table">
<tr id="row1">
<td = "col1"></td>
<td = "col2"></td>
<td = "col3"></td>
function myFunction() {
data = [{"indx":1,"amt":234.56,"vendor":11,"jDate":167},
{"indx":2,"amt":3345.4,"vendor":22,"jDate":168}];
$.each(data, function(key, value) {
$("#row1").eq(key).find('td').text(value.indx);
$("#row1").eq(key).find('td').text(value.amt);
$("#row1").eq(key).find('td').text(value.jDate);
});
}
OUTPUT IN BROWSER: 167 167 167
It is displaying the last field in all three columns. Any advise on how to do get table to display the correct values would be appreciated.
Your code is updating ALL CELLS with value.indx, then with value.amt and finally with value.jDate... So fast that you only see the final result.
I think what you want to achieve is something more like in this CodePen :
function myFunction() {
data = [{"indx":1,"amt":234.56,"vendor":11,"jDate":167},
{"indx":2,"amt":3345.4,"vendor":22,"jDate":168}];
$.each(data, function(key, value) {
$("table").find('tr').eq(key).find("td").eq(0).text(value.indx);
$("table").find('tr').eq(key).find("td").eq(1).text(value.amt);
$("table").find('tr').eq(key).find("td").eq(2).text(value.jDate);
});
}
myFunction();
Obviously you have to add rows dynamically into your table, because your data array may contain different amount of objects.
Try this code.
Here we have table which is populated with new rows for each element of data array.
data = [{"indx":1,"amt":234.56,"vendor":11,"jDate":167},
{"indx":2,"amt":3344.4,"vendor":22,"jDate":168},
{"indx":3,"amt":1414.1,"vendor":21,"jDate":169},
{"indx":4,"amt":3441.3,"vendor":31,"jDate":1610}];
$.each(data, function(key, value) {
var tr = $("<tr>");
tr.append($("<td>").text(value.indx));
tr.append($("<td>").text(value.amt));
tr.append($("<td>").text(value.vendor));
tr.append($("<td>").text(value.jDate));
$("#table").append(tr);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table" border="1">
</table>
I have the following table element:
<table id="my-table" class="table table-striped table-hover ">Loading...</table>
I am dynamically creating the table inside of an ajax call, and then writing the data to the table:
<script>
$.ajax({
success:function(result){
$.getScript("table-sort-controller.js", function () {
sortTable("my-table")
}); //makes table sortable using DataTables
$.getScript("search-controller.js"); //makes table searchable using DataTables
},
url: "http://myserver:8080/url/"
}).then(function(data) {
var table = "<thead>";
table += createTableHeader(data); //fake method to simplify code
table += "</thead>";
table += "<tbody id='sortable-cells'>";
table += createTableBody(data); //fake method to simplify code
table += "</tbody>";
//This is the line where I try to clear "Loading...".
document.getElementById("my-table").innerHTML = table;
});
</script>
However, I am failing to remove "Loading..." from on top of the loaded table. I have tried the following in the line directly after my table creation:
document.getElementById("my-table").innerHTML = "";
document.getElementById("my-table").empty();
//a few other attempts I cannot remember
Some more info:
alert(document.getElementById("my-table")); //output is [object HTMLTableElement]
alert(document.getElementById("my-table").innerHTML); //output is empty alert
alert(document.getElementById("my-table").getCaption()); //console says "undefined is not a function"
I am unclear as to why getCaption() returns undefined, as it appears to be a function under W3C.
How can I remove "Loading..." after my table has finished loading and before I populate #my-table with the appropriate HTML? Alternatively, how can I removing "Loading..." immediately after writing my table?
Thanks to #Phylogenesis and #Paul Roub, fixed it!
I changed
<table id="my-table" class="table table-striped table-hover ">Loading...</table>
to
<table id="my-table" class="table table-striped table-hover "><tr><td>Loading...</td></tr></table>
Then I added following to remove my old "Loading...".
$('#my-table').empty();
Now it works. Thanks!
EDIT: In my particular case, I actually was able to remove the clearing call altogether, as I was overwriting the element in the very next line.