Loading Data to Variable Height Table in HTML - javascript

I am using ASP.NET to create a web app. JS, JQuery, CSS, and HTML are being used. New to web dev, so if you have some good resources to read, they would be appreciated.
I am using Google Maps API to plot some locations. I have created a sidebar which I would like to list nearby properties (eventually click-able). Here are my two concerns:
1) How can I load all properties? Currently my code only displays the first one. The following JS code only lists the last location. In HTML I am using the following label:
<label id ="SidebarLabelName"></label>
In JS:
for (i = properties.length - 1; i >= 0 ; i--) {
var displayNum = i + 1;
SidebarLabelName.text(displayNum + ") " + properties[i]);
}
2) How do I create a table that has a variable number of rows? For example, if I have 10 properties I want to show on my sidepane, then I want 10 rows. I would also like to have pages; if I have 30 properties to list, 26 items on the first page (google maps api limits alpha characters to label markers), 4 on the next.
Thanks for helping.

Question 1:
The code you have overwrites the text in SidebarLabelName for each property, thats why you see only the last property. This can be fixed by following code:
var allprops = "";
for (i = properties.length - 1; i >= 0 ; i--) {
var displayNum = i + 1;
allprops = allprops + "(" + displayNum + ") " + properties[i]);
}
SidebarLabelName.text(allprops);
Question 2:
One of the ways to sovle this is to use the same approach as above:
HTMLCode
<div id ="tableDiv"></div>
and JS code:
var allpropRows = "";
for (i = properties.length - 1; i >= 0 ; i--) {
var displayNum = i + 1;
allpropRows = allpropRows + "<tr> <td> (" + displayNum + ") " + properties[i] + "</td> </tr>");
}
tableDiv.html( "<table>" + allpropRows + "</table>");
Hope this helps!

Related

How do I select specific tags from a data set?

I'm doing a project for uni and I'm a bit of a coding noob. I'm wanting to have 3 buttons on a page, which all connect to one js dataset. I want each button to only show specific information from the data. For example - the data references different businesses in Melbourne that provide printing services. I want each button to be a different service i.e general printing, binding, photography. Can someone please help this poor soul? ps: sorry if my technical language is terrible.
This is what I currently have;
<script type="text/javascript">
window.onload = function(){
populateData();
}
function populateData(){
var table = document.getElementById("DATA");//get <table>
table.innerHTML = ""//make blank
table.innerHTML = "<tr><th>Name</th><th>Address</th><th>URL</th></tr>";//add table headers
for(i = 0; i < plData.length; i++){
var tableRow = document.createElement("tr");//make <tr>
tableRow.className = plData[i].plTags("printing");//apply printer linker category as class name
tableRow.innerHTML += "<td>" + plData[i].plName + "</td><td>"+ plData[i].plStreet + " " + plData[i].plCity + " " + plData[i].plRegion + " " + plData[i].plPostcode + "</td><td><a href='" + plData[i].plHyperlink + "'>" + plData[i].plHyperlink + "</a></td>";//add HTML to <tr>
table.appendChild(tableRow);
}
}

Creating and deleting divs using javascript

I have a few JavaScript functions designed to add and remove HTML divs to a larger div. The function init is the body's onload. New lines are added when an outside button calls NewLine(). Divs are removed when buttons inside said divs call DeleteLine(). There are a few problems with the code though: when I add a new line, the color values of all the other lines are cleared, and when deleting lines, the ids of the buttons, titles, and line boxes go out of sync. I've gone through it with the Chrome debugger a few times, but each time I fix something it seems to cause a new problem. I would greatly appreciate some input on what I'm doing wrong.
function init()
{
numOfLines = 0; //Keeps track of the number of lines the Artulator is displaying
}
function NewLine()
{
var LineBoxHolder = document.getElementById("LineBoxHolder");
numOfLines += 1;
LineBoxCode += "<div class = 'Line Box' id = 'LineBox" + numOfLines + "'>" //The code is only split onto multiple lines to look better
+ " <h6 id = 'Title " + numOfLines + "' class = 'Line Box Title'>Line " + numOfLines + "</h6>";
+ " <p>Color: <input type = 'color' value = '#000000'></p>"
+ " <input type = 'button' value = 'Delete Line' id = 'DeleteLine" + numOfLines + "' onclick = 'DeleteLine(" + numOfLines + ")'/>"
+ "</div>";
LineBoxHolder.innerHTML += LineBoxCode;
}
function DeleteLine(num)
{
deletedLineName = "LineBox" + num;
deletedLine = document.getElementById(deletedLineName);
deletedLine.parentNode.removeChild(deletedLine);
num++;
for ( ; num < numOfLines + 1 ; )
{
num++;
var newNum = num - 1;
var changedLineName = "LineBox" + num;
var changedHeaderName = "Title" + num;
var changedButtonName = "DeleteLine" + num;
var changedButtonOC = "DeleteLine(" + newNum + ")";
var changedLine = document.getElementById(changedLineName);
var changedHeader = document.getElementById(changedHeaderName);
var changedButton = document.getElementById(changedButtonName);
var changedLine.id = "LineBox" + newNum;
var changedHeader.innerHTML = "Line" + newNum;
var changedHeader.id = "Title" + newNum;
var changedButton.setAttribute("onclick",changedButtonOC);
var changedButton.id = "DeleteLine" + newNum;
}
num--;
numOfLines = num;
}
You are having a hard time debugging your code because of your approach. You are "marking" various elements with the IDs you construct, and using the IDs to find and address elements. That means that when things change, such as line being deleted, you have to go back and fix up the markings. Almost by definition, the complicated code you wrote to do something like that is going to have bugs. Even if you had great debugging skills, you'd spend some time working through those bugs.
Do not over-use IDs as a poor-man's way to identify DOM elements. Doing it that way requires constructing the ID when you create the element and constructing more IDs for the sub-elements. Then to find the element again, you have to construct another ID string and do getElementById. Instead, use JavaScript to manage the DOM. Instead of passing around IDs and parts of IDs like numbers, pass around the DOM elements themselves. In your case, you don't need IDs at all.
Let's start off with DeleteLine. Instead of passing it a number, pass it the element itself, which you can do my fixing the code inside your big DOM string to be as follows:
<input type='button' value='Delete Line' onclick="DeleteLine(this.parentNode)"/>
So we have no ID for the line element, no ID for the element, and no ID within the onclick handler. DeleteLine itself can now simply be
function DeleteLine(line) {
{
line.parentNode.removeChild(line);
renumberLines();
}
We'll show renumberLines later. There is no need to adjust IDs, rewrite existing elements, or anything else.
Since we no longer need the ID on each line or its sub-elements, the code to create each element becomes much simpler:
function NewLine()
{
var LineBoxHolder = document.getElementById("LineBoxHolder");
numOfLines += 1;
var LineBoxCode = "<div class='LineBox'>" +
+ " <h6 class='LineBoxTitle'>Line " + "numOfLines + "</h6>"
+ " <p>Color: <input type='color' value='#000000'></p>"
+ " <input type='button' value='Delete Line' onclick= 'DeleteLine(this.parentNode)'/>"
+ "</div>";
LineBoxHolder.innerHTML += LineBoxCode;
}
The only remaining work is to fix up the titles to show the correct numbers. You can do this by just looping through the lines, as in
function renumberLines() {
var LineBoxHolder = document.getElementById("LineBoxHolder");
var lines = LineBoxHolder.childElements;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var h6 = line.querySelector('h6');
h6.textContent= "Line " + (i+1);
}
}
I voted to close because the question is too broad, but will answer anyway on a few points to... well, point in the right direction.
var changedButton.setAttribute("onclick",changedButtonOC); This is not a variable declaration. Omit the var.
for ( ; num < numOfLines + 1 ; ) { num++; ... The correct form here would be simply for (; num < numOfLines + 1; num++) { ....
Instead of incrementing (num++) then decrementing (num--) around the loop, why not just use the right math?
See:
for (; num < numOfLines; num++) {
...
}

JQuery mobile list prepend

trying to prepend my list in jquery mobile but I just can't get the divider to be on top of the most recent item added to the listview.
I've tried prepending the item that's being added but it then switches the divider to the bottom.
function loadScanItems(tx, rs) {
var rowOutput = "";
var $scanItems = $('#scanItems');
$scanItems.empty();
var bubbleCount = 0;
for (var i = 0; i < rs.rows.length; i++) {
bubbleCount = bubbleCount + 1;
//rowOutput += renderScan(rs.rows.item(i));
var row = rs.rows.item(i)
var now = row.added_on;
var date = get_date(now);
rowOutput += '<li data-icon="false"><div class="ui-grid-b"><div class="ui-block-a" style="width:50%"><h3>Su # ' + row.sunum + '</h3><p> Bin # ' + row.binnum + '</p></div><p class="ui-li-aside"><strong>' + date + '</strong></p><div class="ui-block-b" style="width:20%"></div><div class="ui-block-c" style="width:25%"><br><p>User: ' + row.userid + '</p></div></div></li>';
// rowOutput += '<li>' + row.sunum + row.binnum+ "<a href='javascript:void(0);' onclick='webdb.deleteScan(" + row.ID + ");'>Delete</a></li>";
}
$scanItems.append('<li data-role="list-divider">Scanned Items <span class="ui-li-count">' + bubbleCount + '</span></li>').listview('refresh');
$scanItems.append(rowOutput).listview('refresh');
}
The code is above with it correctly formatted with the divider on top but the list items being appended to the bottom instead of prepended to the top.
Thanks!
The problem is that your are building a string with all the scan items. That string already has an order so whether you prepend or append makes no difference. Try this simple change.
Change:
rowOutput += '<li data-icon="false">...</li>';
to:
rowOutput = '<li data-icon="false">...</li>' + rowOutput;
This will put your rowOutput string in the correct order before appending to the listview.
Here is a working DEMO

JavaScript & HTML - Modifying dynamically created subclasses within a dynamically created class

Problem:
I have a dynamically created HTML table, that is used for filling out time sheets. It is created programmatically - there is no formal control. The design is a mix of CSS with text boxes being created through JavaScript. Now each 'row' of this table is in a class called 'divRow', and is separated from the others by having 'r' and the number of the row assigned to it as the class (i.e 'divRow r1', 'divRow r2', etc.).
Within each of these 'divRow's, I have cells in a class called 'divCell cc'. These do not have any identifiers in the class name. At the very last cell, I have a 'Total' column, which ideally calculates the total of the row and then adds it into a dynamically created text box.
What I have at the moment:
// Function to create textboxes on each of the table cells.
$(document).on("click", ".cc", function(){
var c = this;
if(($(c).children().length) === 0) {
var cellval = "";
if ($(c).text()) {
cellval = $(this).text();
if(cellval.length === 0) {
cellval = $(this).find('.tbltxt').val();
}
}
var twidth = $(c).width() + 21;
var tid= 't' + c.id;
if(tid.indexOf('x17') >= 0){
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' readonly />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
//var getRow = $(this).parent().attr('class'); - this gets the 'divRow r#' that it is currently on.
var arr = document.getElementsByClassName('cc');
var tot = 0;
for(var i = 0; i<arr.length; i++){
if(parseInt(arr[i].innerHTML) > 0){
tot += parseInt(arr[i].innerHTML);}
}
$('#t' + c.id).focus();
$(this).children().val(tot);
}else{
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
$('#t' + c.id).focus();
$('#t' + c.id).val(cellval);
}}
});
As you can see, when the user clicks on the 'divCell cc', it creates a text box if one is not present. If the user clicks on the 17th column ('x17'), then it runs the for loop, and assigns the value of the total to the text box.
What I need to happen:
So what happens now is that the last cell sums the total of each cell that has a value. However, they are not row-dependent. I need it to calculate based on the row that it is currently 'on'. So if I'm calculating the 2nd row, I don't want the sum of the first, second and third being entered into the total, I just want the 2nd rows' values summed.
What I've tried:
I've tried looping through and using the 'divRow r#' number to try and get the items in the array that end in that number. (cells are given an id of 'x#y#' and the text boxes assigned to those cells are given an id of 'tx#y#').
I've tried getting elements by the cell class name, and then getting their parent class and sorting by that; didn't get far though, keep running into simple errors.
Let me know if you need more explanation.
Cheers,
Dee.
For anyone else that ever runs into this issue. I got it. I put the elements by the row class into an array, and then using that array, I got the childNodes from the row class. The reason the variable 'i' starts at 2 and not 0 is because I have 2 fields that are not counted in the TimeSheet table (Jobcode and description). It's working great now.
Cheers.
$(document).on("click", ".cc", function(){
var c = this;
if(($(c).children().length) === 0) {
var cellval = "";
if ($(c).text()) {
cellval = $(this).text();
if(cellval.length === 0) {
cellval = $(this).find('.tbltxt').val();
}
}
var twidth = $(c).width() + 21;
var tid= 't' + c.id;
if(tid.indexOf('x17') >= 0){
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' readonly />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
// Get current row that has focus
var getRow = $(this).parent().attr('class');
// Get the row number for passing through to the next statement
var rowPos = getRow.split('r', 5)[1];
// Get all the elements of the row class and assign them to the rowClass array
var rowClass = document.getElementsByClassName('r' + rowPos)
// Given the rowClass, get the children of the row class and assign them to the new array.
var arr = rowClass.item(0).childNodes
// Initialize the 'total' variable, and give it a value of 0
var tot = 0;
// Begin for loop, give 'i' the value of 2 so it starts from the 3rd index (avoid the Req Code and Description part of the table).
for(var i = 2; i<arr.length; i++){
if(parseInt(arr[i].innerHTML) > 0){
tot += parseInt(arr[i].innerHTML);}
}
// Assign focus to the 'Total' cell
$('#t' + c.id).focus();
// Assign the 'total' variable to the textbox that is dynamically created on the click.
$(this).children().val(tot);
}else{
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
$('#t' + c.id).focus();
$('#t' + c.id).val(cellval);
}}
});

JS Fine in FF, bugged in Chrome

I built a page that uses a simple JSon table and JS/JQ to present that data. Hosted together on one sheet it works fine in both Chrome and FF. Split into seperate HTML, CSS, JS and JSON files, however, there is a slightly variable bug in Chrome.
Page: http://www.lafairclough.co.uk/JTest/index.html
Select two options from the drop down and the charts on the right should show the relative performance data from two cars (top to bottom: 0-60, 0-100, Standing Qtr and Top Speed). These are colour coded with green being the faster result and orange denoting a draw for a given variable.
The charts are made using Java to calculate and set a CSS div width. In Chrome, however, this div width is (sometimes, but often) getting calculated as a much higher figured than expected. As flows:
// Perf. BAR CHART SIZE CSS CAR A
$.getJSON("cars.json", function (data) {
$(document).ready(function () {
$('#dropdown1').change(function () {
var index = parseInt($(this).val()),
html = "<p class=\"barText\">" + " " + data.carList[index].model + " " + data.carList[index].variant + "</p>";
$(".carA060").html(html);
var index = parseInt($(this).val());
var num = data.carList[index].zero60 * 10;
$(".carA060").css('width', num + '%').show();
html = "<p class=\"barText\">" + " " + data.carList[index].model + " " + data.carList[index].variant + "</p>";
$(".carA0100").html(html);
var index = parseInt($(this).val());
var num = data.carList[index].zero100 * 5;
$(".carA0100").css('width', num + '%').show();
html = "<p class=\"barText\">" + " " + data.carList[index].model + " " + data.carList[index].variant + "</p>";
$(".carAsQTR").html(html);
var index = parseInt($(this).val());
var num = data.carList[index].sQTR * 5;
$(".carAsQTR").css('width', num + '%').show();
html = "<p class=\"barText\">" + " " + data.carList[index].model + " " + data.carList[index].variant + "</p>";
$(".carAvMAX").html(html);
var index = parseInt($(this).val());
var num = data.carList[index].vMAX * 0.5;
$(".carAvMAX").css('width', num + '%').show();
});
});
});
Any idea as to why it's going awry in Chrome would be hugely appreciated.
Thanks,
Lee.
your are passing 14.6 ( the mazda ) in your json and multiplying it by 10 for the width so thats why you are
out of bound of container change the logic of the calculation of the width and you will be fine. and the reason why in fire fox its ok and chrome not is because each browser parse the CSS differently . hope this helped

Categories