Set td value based on another td name from ajax - javascript

I have the following table structre:
<tr>
<td class="name">
Stock1
</td>
<td class="price">
</td>
</tr>
<tr>
<td class="name">
Stock2
</td>
<td class="price">
</td>
</tr>
Based on the names Stock1 and Stock2, I need to set the corresponding price in the next td. I am web scraping the price thru ajax and trying to set the value as follows:
For Stock1:
$(document).ready(function() {
$.ajax({
*everything else working fine*
success: function(data) {
if($('.name').html().indexOf("Stock1") != -1) {
$(this).closest('tr').find('.price').html(data);
}
}
});
});
In this scenario, this is not working, which I'm expecting to be the td tag with class name where value is Stock1. If I replace this with ".name", the code works only if there's one name td. When I have two td tags with the class name, it doesn't work.
I need to get this done as soon as the document loads, and not on some event like mouse click or hover.

this doesn't refers to td.name element nor table.
The :contains() Selector selects all elements that contain the specified text to target the td and then use can use DOM relationship to target immediate following sibling td using .next().
$('td.name:contains("Stock1")').next('.price').html(data);
or
$('td.name:contains("Stock1")').closest('tr').find('.price').html(data);
You can also use .filter()
var var1 = 'Stock1';
$('td.name').filter(function(){
return this.textContent.indexOf(var1) != -1;
}).closest('tr').find('.price').html(data);
As per comment, now you are returning an array. So need to iterate the data object and target the desired element.
var data = [{
name: "Stock1",
price: "$12"
}, {
name: "Stock2",
price: "$15"
}]
$.each(data, function(_, d){
$('td.name').filter(function() {
return this.textContent.indexOf(d.name) != -1;
}).closest('tr').find('.price').html(d.price);
})
DEMO

Use the below code in success method, assuming the data would be in the format mentioned below.
success:function(data)
// Assigning dummy values for assumption
var data = [{
stockName: "Stock1",
price: "$12"
}, {
stockName: "Stock2",
price: "$15"
}]
// Iterating throw all td which has name [class] elements
$(".name").each(function(i, obj) {
// Dummy Validation as per the mock data to repalce the data as per the stockName
if ($(this).closest('tr').find('.name').text().trim() === data[i].stockName){
$(this).closest('tr').find('.price').html(data[i].price);
}
})
});
FIDDLE

success: function(data) {
$('.name').each(function(index, element) {
if ($(element).html().indexOf("Stock1") != -1) {
$(element).closest('tr').find('.price').html(data);
}
}
}

The current implementation may not work correctly if you have multiple Stocks are present on your page. So i will suggest you to modify your server side code a bit to return back node name (like Stock1) as well as its price. So that your ajax success data will have 2 components; like data.name and data.price. first one will get used to target DOM td and later one will be used to set the price text as follows:
For Stock1:
$(document).ready(function(){
$.ajax({
url: "someBaseURL?name=Stock1"
success: function(data) {
var name = data.name; //grab the stock name
var price = data.price; //grab the stock price
//iterate over all the names and target the one associated
$('.name').each(function(){
if($.trim($(this).text()).indexOf(name) != -1)
$(this).closest('tr').find('.price').html(price);
});
}
});
});

Related

Change appended td by condition inside loop

I am appending rows and columns to a table using javascript. But I need one of the classname inside the td to somethings else based on the condition inside a `$.post() response.
I did this:
let arr = ['Hermione', 'Ron', 'Harry']
arr.forEach(d=>{
$('#the_table>tbody').append(`
<tr id='tr_${d}'>
<td'>${d}</td>
<td><i id='change' class='no'></i></td>
</tr>
`);
});
const myfunc = () => {
$.post(api, json_object,
function(data, status) {
if (data.value === 'started') {
setTimeout(myfunc, 5000);
} else {
$('#change').removeClass('no').addClass('yes');
}
}, 'json');
}
myfunc();
When I do this, it is only changing the value for the first value (Hermione). But in the console.log, I can see that the data.value is not started so it should've changed to yes.
Hoe can I change it to yes for each of the rows once the condition has been passed
$('#change').removeClass('no').addClass('yes');
you need to fix this selector $('#change')
i dont know if the api return has id
but you need to select it like this
$(`tr#${data.something} #change`)
Can you provide JSfiddle or any online code setup to debug more? I could see there is first element is having a single quote that is not being ignored.
${d} should be like this ${d}
Thanks
The problem is that You are using the same id name for identifying many differents rows .
Each ID must be unique . So if you have many elements to manipulate it is better to identify them by their classname instead . Change the the the attribute ID to CLASS as illustrated below .
// I have only change the attribute id to class
let arr = ['Hermione', 'Ron', 'Harry']
arr.forEach(d=>{
$('#the_table>tbody').append(`
<tr id='tr_${d}'>
<td'>${d}</td>
<td><i class='change' class='no'></i></td>// now their identified by class name
</tr>
`);
});
const myfunc = () => {
$.post(api, json_object,
function(data, status) {
if (data.value === 'started') {
setTimeout(myfunc, 5000);
} else {
$('.change').removeClass('no').addClass('yes');
}
}, 'json');
}
myfunc();

datatables rows().ids() return undefined

In my datatable I set the ID attribute for rows:
'createdRow': function (row, data, dataIndex) {
$(row).attr('id', data.json.unid);
}
Under a button I want to grab the ID's:
action: function () {
var count = table
.rows({
selected: true
})
.ids();
alert("id:s" + count)
for (i = 0; i < count.length; i++) {
alert("id:" + count[i])
}
rpcService
.setIds(count
.toArray());
}
In the alert I get for the ID "undefined".
Here is what a row looks like:
<tr id="FF97C3CFC0F5FA76C12583D1003EA028" role="row" class="odd selected">
<td class=" select-checkbox"> </td>
<td>Anne Weinstein</td>
<td>ORP B</td>
<td>Anne Weinstein</td>
<td>s41660</td>
</tr>
What am I doing wrong?
You are setting IDs on the elements in the DOM, but the .ids() method is not supposed to return those.
https://datatables.net/reference/api/rows().ids()
Important This method does not read the DOM id for the tr elements, but rather gets the row id from the row's data source (location specified by rowId).
You would need to provide the IDs upfront in your data source already, so that you can match them via the rowId option, to get what datatables considers a “row id”.

Object not printing/returning information to HTML(using jquery .hover())?

I have the following table in which I have two ids, mPoint and bPoint. I want to insert data here using html() when I hover over elements with id hydrogen or helium.
<div class="info" id="hydrogen">
<em>1</em>
H
<p>Hydrogen</p>
</div>
<div class="info" id="helium">
<em>2</em>
Li
<p>Helium</p>
</div>
<table class="propTable">
<tr>
<td>Melting Point</td>
<td id="mPoint"></td>
</tr>
<tr>
<td>Boiling Point</td>
<td id="bPoint"></td>
</tr>
</table>
Here is the JS Function
function PropElements() {
var propHydrogen = {
"m_point": "14.01",
"b_point": "20.28"
};
var propHelium = {
"m_point": "0",
"b_point": "4.22"
};
$('.info').hover(function() {
var getId = this.id;
var getPropName = "prop" + getId.charAt(0).toUpperCase() + getId.slice(1);
console.log(getPropName);
$("#mPoint").html(getPropName.m_point + " K");
$("#bPoint").html(getPropName.b_point + " K");
}, function() {
$("#mPoint").html("unknown");
$("#bPoint").html("unknown");
});
}
Here are two objects for Hydrogen and Helium. getPropName will change the name of the hovered element such that it becomes prop[hoveredElementID]. Now If I hover over div with #hydrogen, getPropName will change name to propHydrogen, which is also the name of the object. And then using html(), it should print the value of m_point and b_point at the position of specified IDs.
But its showing the value of getPropName.m_point and getPropName.b_point as unknown. I have tried putting the objects inside the function but it still returns unknown even though console is returning the exact propName that should work. I tried using innerHTML, but that returns undefined instead.
Though, If I use the name directly(propHydrogen.m_point), it prints the value correctly. What could be the problem here?
The issue is because you cannot dynamically use the value of a variable to point to another defined variable in the manner you are attempting. A better method would be to use a single object to store all information required and then access the properties of that object dynamically. Try this:
function propElements() {
var elements = {
hydrogen: {
"m_point": "14.01",
"b_point": "20.28"
},
helium: {
"m_point": "0",
"b_point": "4.22"
}
};
$('.info').hover(function() {
$("#mPoint").html(elements[this.id].m_point + " K");
$("#bPoint").html(elements[this.id].b_point + " K");
}, function() {
$("#mPoint").html("unknown");
$("#bPoint").html("unknown");
});
}
Working example
Note that by making the property names in the object match the id of the .info elements it saves a lot of unnecessary string manipulation.

Table must have clickable cells to display more options from XML file

I need to have a clickable cell within a table, so it will show a description of a TV show. I have it feeding in the XML to make the table called 'tvGuide1' and a tooltip like function shows a brief description. The XML create the first row with the first 5 elements within XML.
<script type="text/javascript">
$(document).ready(function()
{
$.ajax({
type: "GET",
url: "MonWedSatXML.xml",
cache: false,
success: function(xml){
$(xml).find('#1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16').each(function(){
var Time = $(this).find('Time').text();
dcs1 = $(this).find('Desc1').text();
dcs2 = $(this).find('Desc2').text();
dcs3 = $(this).find('Desc3').text();
dcs4 = $(this).find('Desc4').text();
dcs5 = $(this).find('Desc5').text();
var Program1 = $(this).find('Title1').text();
var Program2 = $(this).find('Title2').text();
var Program3 = $(this).find('Title3').text();
var Program4 = $(this).find('Title4').text();
var Program5 = $(this).find('Title5').text();
$('<tr></tr>').html('<th>'+Time+"</th><td Title='"+dcs1+"' <div onClick='info()'>"+Program1+"</td><td Title='"+dcs2+"'<div onClick='info()'>"+Program2+"</td><td Title='"+dcs3+"'<div onClick='info()'>"+Program3+"</td><td Title='"+dcs4+"'<div onClick='info()'>"+Program4+"</td><td Title='"+dcs5+"'>"+Program5+'</td>').appendTo('#tvGuide1');
});
}
});
$( "#tvGuide1" ).on("click","td", function(e){
console.log('hello');
$("#myModal").modal("show");
});
});
</script>
XML EXAMPLE
<Programs>
<TVShows id="1">
<Time>08:00</Time>
<Title1>Breakfast</Title1>
<Desc1>The latest news, sport, business and weather from the team. Also in HD. [S] Including regional news at 25 and 55 minutes past each hour.</Desc1>
<Title2>Fake Britain</Title2>
<Desc2>Matt Allwright investigates the activities of conmen, revealing the fake high-EndTimesome farmers' markets and looking at counterfeit bike parts.</Desc2>
<Title3>Family Guy</Title3>
<Desc3>Hilarious show about a modern family</Desc3>
<Title4>ITV News</Title4>
<Desc4>Your latest news, sport and weather</Desc4>
<Title5>Homes Under the Hammer</Title5>
<Desc5>People buy rubbish houses and give them a make over then sell them</Desc5>
</TVShows>
'<table id="tvGuide1">
<tr>
<th>Time 24hr Clock</th>
<th>BBC 1<img src="Channel1.png" style="width:150px;height:150px"></th>
<th>BBC 2<img src="Channel2.png" style="width:150px;height:150px"></th>
<th>Comedy Central<img src="ComedyCentral.png" style="width:150px;height:150px"></th>
<th>ITV<img src="Channel3.jpeg" style="width:150px;height:150px"></th>
<th>Channel 4<img src="Channel4.jpg" style="width:150px;height:150px"></th>
</tr>
</table>'
The problem the XML will create the table and pull in the data but I have no idea how to implement the modal to display the description from the XML
Any help would be great.
You could add the information you want to display in the modal as data-attributes to each <td> - e.g. like this:
<td data-desc="Hilarious show about a modern family">Family Guy</td>
and either add a class to each clickable <td> or check on click if this data-attribute is set:
$("td").on("click", function (e) {
e.stopPropagation();
if($(this).data("desc")){
modal($(this).data("desc"));
}
});
with either a self written modal function or an existing solution. As example I've just created a Fiddle with a simple modal function and set the data for the first three entries. In case you have more information that you want to display in the modal, this can be added as another data-attribute. This is only an example, as you already have set the short description as title-tag I suppose there's an additional longer description in the XML that you would like to only display in a modal.
For reference: http://api.jquery.com/data/
Update: For the mentioned requirement to get the description for the modal from the XML on click on td - following approach:
function loadXml(item) {
$.ajax({
type: "GET",
url: 'programs.xml',
dataType: "xml",
success: function (xml) {
parseXml(xml, item);
}
});
}
function parseXml(xml, item) {
var $xml = $(xml),
desc = $xml.find(item).text();
modal(desc);
}
function modal(desc) {
$("body").addClass("inactive");
$("#modal").text(desc).show();
}
$(document).ready(function () {
$(".programm td").on("click", function (e) {
e.stopPropagation();
var col = $(this).parent().children().index($(this));
if (col > 0) {
loadXml("Desc" + col);
}
});
$("body").on("click", function (e) {
if (!$("#modal").is(e.target)) {
$("#modal").hide();
$("body").removeClass("inactive");
}
});
});
Adjusted but not working Fiddle - not working because the XML (even if referenced as absolute URL) wouldn't be readable from there because of CORS. The XML has to be on the same domain as the page that's reading the XML, so for testing purposes I've just uploaded it on a testserver and it's working, using an absolute URL to the XML as well as using the relative URL when the XML is next to the HTML.
As explanation - each tr has the class programm, on click of an td with an index > 0 (as the first td with index 0 is the time) calls the function loadXml() with desc + index of the clicked td as parameter. On success, parseXml() is called, retrieves the text of the description (e.g. Desc2) and calls the modal() function with the retrieved text.
I've only written this as an example for the XML you provided, as you will have more entries, e.g. for the next time slot under <TVShows id="2">, you can adjust this to take the number/index of the clicked tr with class programm into account.

Populate and display an html table based on the values from two dropdown menus

I have two cascading dropdown boxes controlled with JQuery and Ajax objects. The first determines the values in the second. Then, once a selection is made in the second, the values from the two dropdowns would be used to find a record in an SQL table and display the record in an html table.
So far the dropdowns work correctly but I'm having difficulty getting the record from the database and then displaying it on screen. I've done this before by getting the database values, sending them to the view in a Json object, and using an Ajax object to to create the table with Jquery. However, in this case I don't mind if the page reloads and would like to use a simpler method.
What is a simple method of sending two values from two dropdowns to the controller, using those values to find a record in an sql table, sending the values from the record back to the view to be displayed? Also, I don't want anything to be displayed until the second dropdown box has a selection made.
Here is what I have so far:
Controller methods:
List<Car> GetCars()
{
using (var service = new Service())
{
return service.GetCars().OrderBy(x => x.CarName).Select(x => new Car
{
CarId = x.CarId,
CarName = x.CarName
}).ToList();
}
}
List<Color> GetColors(int carId)
{
using (var service = new Services())
{
return service.GetColors(carId).OrderBy(x => x.ColorName).Select(x => new Color
{
ColorId = x.ColorId,
ColorName = x.ColorName
}).ToList();
}
}
[HttpPost]
public ActionResult CurrentSaus(int townCode, int fiscalYear)
{
var colors = GetColors(carId);
return Json(new SelectList(colors, "ColorId", "ColorName"));
}
Jquery methods:
$(document).ready(function () {
$("#Car_CarId").change(function () {
var carId = $(this).val();
var carName = $(":selected", this).text();
// put the car name into a hidden field to be sent to the controller
document.getElementById("Car_CarName").value = carName;
getColors(carId);
})
});
function getColors(carId) {
if (carCode == "") {
$("#Color_ColorId").empty().append('<option value="">-- select color --</option>');
}
else {
$.ajax({
url: "#Url.Action("Colors", "HotWheels")",
data: { colorId: clrId },
dataType: "json",
type: "POST",
error: function () {
alert("An error occurred");
},
success: function (data) {
var colors = "";
var numberOfColors = data.length;
if (numberOfColors > 1) {
colors += '<option value="">-- select color --</option>';
}
else {
var colorId = data[0].Value;
var colorName = data[0].Text;
document.getElementById("Color_ColorName").value = colorName;
}
$.each(data, function (i, color) {
colors += '<option value="' + color.Value + '">' + color.Text + '</option>';
});
$("#Color_ColorId").empty().append(colors);
}
});
}
and some of the html:
#Html.HiddenFor(x => x.Car.CarName)
#Html.HiddenFor(x => x.Color.ColorName)
<table>
<tr>
<td> Select Car:</td>
<td style="text-align:left">
#Html.DropDownListFor(
x => x.Car.CarId,
new SelectList(Model.CarList, "CarId", "CarName"),
"-- select town --")
<br />
#Html.ValidationMessageFor(x => x.Car.CarId)
</td>
</tr>
<tr>
<td> Select Color:</td>
<td colspan="4">
#Html.DropDownListFor(
x => x.Color.ColorId,
new SelectList(Model.ColorList, "ColorId", "ColorName"),
"-- select color --")
<br />
#Html.ValidationMessageFor(x => x.Color.ColorId)
</td>
</tr>
</table>
}
The easiest method is to use an old fashion FORM element and POST the values of the two drop downs to an action in your controller. That action would expect a carId and a colorId and use them to retrieve a record from the DB and then pass the result to your 'view' where you would take care of render/display the result.
Of course using this method has some caveats:
The entire page will refresh after a user selects a value from the
second drop down.
You would have to POST the form using JavaScript
when the user picks the second option, or at least enable a button so
the form can be POSTed.
You would have to keep track of the carId and
colorId in your controller and view
Another option is to use AJAX to POST (send to the server) the carId and colorId where and action in a controller will take care of using those parameters to find a record in the DB and then return a JSON object with the result. The response will be handled by a 'success' handler where you will take care parsing the JSON object and add rows to a table.
So if you feel more comfortable working on the server side of the code pick the first option, however if you prefer to use AJAX and do this in the front end use the later.

Categories

Resources