IE8 append on $(document).ready() - javascript

I'm aware there are similar questions to this but have looked at several and none have provided and actual solution.
I have a function that populates a table with row when the page loads if there are items to fill it with. This works fine in all browsers except IE8. If you refresh the page then the works as it should, however in IE8 if you simply navigate to the page the table is unchanged. I have put break points in the js in Developer Tools and the function was called and reached the end without error and when I examined the objects the table did contain the rows it was supposed to as far as the object was concerned but rows were not rendered in the actual table on the page.
Here is the code at the bottom of the page:
<script type="text/javascript">
$(document).ready(function () {
addToTicketTable('12345');
});
</script>
Any thoughts?
Edit
Yes I am using tbody and function works fine when called by selecting a seat on the page or refreshing the page. It's only when navigating to the page that it doesn't work correctly.
As requested here is the code for the addToTicketTable function.
function addToTicketTable(seatId) {
var zone = $("#ddlSections").val();
var sectText = $("#ddlSections option:selected").text();
var sectName = sectText.split(":")[0]
var sect = sectText.split(" ")[0];
if (sectText.toLowerCase().indexOf(" box") >= 0) {
sect += " " + sectText.split(" ")[1];
}
var seat = "Best Available";
var priceType = -1;
var seatInfo = "";
if ($(".dvSeat").length > 0) {
var arrInfo = document.getElementById(seatId).getElementsByTagName("input")[0].value.split(",");
priceType = arrInfo[4];
sect = arrInfo[3];
if ($("#" + seatId).attr("class").indexOf(" box") >= 0) {
sect += " box";
}
seat = arrInfo[0] + arrInfo[1];
if ($("#" + seatId).attr("class").indexOf("restrictedView") > -1) {
seatInfo = "Restricted View";
}
if ($("#" + seatId).attr("class").indexOf("standingSeat") > -1) {
seatInfo = "Standing Ticket";
}
if ($("#" + seatId).attr("class").indexOf("wheelchair") > -1) {
seatInfo = "Wheel Chair Space";
}
if ($("#" + seatId).attr("class").indexOf("behindConductor") > -1) {
seatInfo = "Behind Conductor";
}
if ($("#" + seatId).attr("class").indexOf("noSurtitles") > -1) {
seatInfo = "Surtitles not visible";
}
if ($("#" + seatId).attr("class").indexOf("restrictedLegRoom") > -1) {
seatInfo = "Restricted Leg Room";
}
zone = arrInfo[2];
}
var tdSect = document.createElement("td");
tdSect.innerHTML = sectName;
var tdSeat = document.createElement("td");
tdSeat.innerHTML = seat;
if (seatInfo.length > 0) {
tdSeat.innerHTML += " (" + seatInfo + ")";
}
var hdSeat = document.createElement("input");
hdSeat.id = "tblHd" + seatId;
hdSeat.className = "seatHD";
hdSeat.type = "hidden";
hdSeat.value = seatId;
$(tdSeat).append(hdSeat);
var tdTicket = document.createElement("td");
var ddl = document.createElement("select");
ddl.id = "ddlTicket" + seatId;
ddl.className = "ddlTicket";
var ddlStr = "";
if (document.getElementById("ddl" + zone) != null) {
ddlStr = "ddl" + zone;
} else {
ddlStr = "ddl" + sect.split(":")[0];
if (ddlStr.indexOf(" ") > -1) {
ddlStr = ddlStr.split(" ")[0];
}
}
$("#" + ddlStr + " option").each(function () {
var arrVal = this.value.split(',');
if (arrVal[0] == zone) {
var selected = false;
if (priceType != null) {
if (this.value.split(',')[1] == priceType) {
selected = true;
}
}
if (selected) {
$(ddl).append($("<option></option>").attr("value", this.value).text(this.text).attr("selected", "true"));
} else {
$(ddl).append($("<option></option>").attr("value", this.value).text(this.text));
}
}
});
$(ddl).change(function () {
$("#lblPrice" + seatId).html($(this).val().split(',')[2]);
updateSeatInfo();
});
$(tdTicket).append(ddl);
var tdPrice = document.createElement("td");
var lblPrice = document.createElement("span");
lblPrice.id = "lblPrice" + seatId;
$(tdPrice).append(lblPrice);
var tdRemove = document.createElement("td");
var btnRemove = document.createElement("span");
btnRemove.className = "btnRem";
$(btnRemove).click(function () {
remSeat(seatId);
});
$(tdRemove).append(btnRemove);
var tr = document.createElement("tr");
tr.id = "tr" + seatId;
$(tr).append(tdSect);
$(tr).append(tdSeat);
$(tr).append(tdTicket);
$(tr).append(tdPrice);
$(tr).append(tdRemove);
$("#tblSeats tbody").append(tr);
$("#lblPrice" + seatId).html($(ddl).val().split(',')[2]);
}

So I'm speculating a little here since enough code wasn't provided to fully determine the problem, so I'll share my experience with appending rows in IE8.
More than likely, you have a simple table structure like this:
<table>
<tr>
<th>Header</th>
</tr>
<tr>
<td>Stuff</td>
</tr>
</table>
and your script is something like this:
<script>
$("table").append("<tr><td>More Stuff</td></tr>");
</script>
Well, IE8 doesn't allow you to append directly to a <table> element. Instead, it requires that you set up the table structure correctly and append to a <tbody> element instead. Like so:
<table>
<thead>
<tr>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Stuff</td>
</tr>
</tbody>
</table>
and your jQuery would have to change to reflect the append to the <tbody> element:
<script>
$("tbody").append("<tr><td>More Stuff</td></tr>");
</script>

Related

Slight trouble with table row fetch script

I'm kinda new to scripting and all and just wanted to know if anyone could help me edit my code to hide the whole table from the start and then just display the rows that match the keyword.
Right now what the code does is:
You enter a keyword in an inputbox
The script searches through a table looking for rows matching the keyword.
Hide all other rows.
But i would like it to work another way, but don't really know how to.
What i would like it to do is:
Display the inputbox only on the page.(Table is hidden)
Display the results that match the keyword without displaying the whole table.
Code:
var TableSearch = function(searchBoxId, dataTableId, options) {
this.searchBox = document.querySelector('#' + searchBoxId);
this.dataTable = document.querySelector('#' + dataTableId);
this.options = options;
}
TableSearch.prototype = {
init: function(searchBoxId, dataTableId, options) {
// defaults options
var settings = {
firstRowHeader: true,
highlightCss: "style='background-color:yellow'",
noResultsText: null
};
if (this.options) {
for (var key in settings) {
// Update settings if valid option and value was supplied.
if (this.options.hasOwnProperty(key) && (this.options[key] != null && this.options[key].toString() != '')) {
if (key == 'highlightCss') {
settings[key] = "class='" + this.options[key] + "'";
continue;
}
settings[key] = this.options[key];
}
}
}
this.options = settings;
this.searchBox.addEventListener('keyup', this.search.bind(this), false);
},
search: function(e) {
if(e.keyCode == 27) {
this.searchBox.value = ''; // Clear search on Esc
}
this.toggleNoResult('remove');
var keyword = this.escapeSpecialChars(this.searchBox.value);
var textSearchRegex = new RegExp(keyword, "ig"); // case in-sensitive
var rowDisplay, rowObj, rowHtml, match;
var firstRowIndex = (this.options.firstRowHeader == true) ? 1 : 0;
for (var rowIndex = firstRowIndex; rowIndex < this.dataTable.rows.length; rowIndex++) {
rowDisplay = '';
rowObj = this.dataTable.rows.item(rowIndex);
rowHtml = rowObj.innerHTML.replace(/<mark[^/>]*>/g,'').replace(/<\/mark>/g,''); // remove previous highlighting
if (keyword == '')
rowDisplay = 'table-row';
else {
match = rowHtml.replace(/<[^>]*>/g, '').match(textSearchRegex); // strip html tags and search for keyword
if(match) {
// Get unique matches: http://stackoverflow.com/a/21292834/1440057
match = match.sort().filter(function(element, index, array) { return index == array.indexOf(element); });
var tempHtml = rowHtml;
for (var i = 0; i < match.length; i++)
tempHtml = this.highlight(tempHtml, match[i]);
if (tempHtml.search(/<\/mark>/g) > -1) {
rowHtml = tempHtml;
rowDisplay = 'table-row';
}
else // Keyword did not match with any column content
rowDisplay = 'none';
}
else // Keyword did not match even in the row text content
rowDisplay = 'none';
}
rowObj.innerHTML = rowHtml;
rowObj.style.display = rowDisplay;
}
// Check if 'no results' row needs to be added
if (keyword != '' && this.options.noResultsText && this.dataTable.innerHTML.search(/style=\"display: table-row;\"/g) == -1)
this.toggleNoResult('add');
},
highlight: function(rowHtml, match) {
var row = document.createElement('tr');
row.innerHTML = rowHtml;
var textReplaceRegex = new RegExp(this.escapeSpecialChars(match), "g"); // case sensitive
var highlightMarkup = '<mark ' + this.options.highlightCss + '>' + match + '</mark>';
var cell = null;
var htmlOut = '';
for (var i = 0; i < row.cells.length; i++) {
cell = row.cells.item(i);
// Highlighting works only for direct text content, not nested tags.
// e.g. searching "blog" in <td>my blog</td> won't work.
if (cell.children.length == 0) {
if (cell.textContent.indexOf(match) > -1) {
// Match found in this cell, highlight it
htmlOut += '<td>' + cell.textContent.replace(textReplaceRegex, highlightMarkup) + '</td>';
continue;
}
}
htmlOut += '<td>' + cell.innerHTML + '</td>';
}
return htmlOut;
},
escapeSpecialChars: function(inStr) {
return inStr.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
},
toggleNoResult: function(mode) {
var noResultsRow;
if (mode == 'add') {
noResultsRow = this.dataTable.insertRow(this.dataTable.rows.length);
noResultsRow.setAttribute('id', 'noResultsRow');
var noResultsRowCell = noResultsRow.insertCell(0);
noResultsRowCell.setAttribute('colspan', this.dataTable.rows[0].cells.length);
noResultsRowCell.setAttribute('align', 'center');
noResultsRowCell.textContent = this.options.noResultsText;
}
else if (mode == 'remove') {
noResultsRow = this.dataTable.querySelector('#noResultsRow');
if (noResultsRow != null) {
this.dataTable.deleteRow(this.dataTable.rows.length - 1);
}
}
}
}
Thanks in advance :)

Child element is not getting selected in jquery

I have a gridview that is being rendered as follows
<table cellspacing="0" cellpadding="4" rules="cols" id="ContentPlaceHolder1_ucstockcount1_GridView1" style="color:Black;background-color:White;border-color:#DEDFDE;border-width:1px;border-style:None;width:100%;border-collapse:collapse;">
<tr style="color:White;background-color:#6B696B;font-weight:bold;">
<th scope="col">Sr.no</th><th scope="col">Style</th><th scope="col">Stk Last Mon</th><th scope="col">Stk Received</th><th scope="col">Stk This Mon</th><th scope="col">Change</th><th scope="col">Price</th><th scope="col">Value</th>
</tr><tr style="background-color:#F7F7DE;">
<td>1</td><td>T1-34H</td><td>0</td><td>0</td><td>
<input name="ctl00$ContentPlaceHolder1$ucstockcount1$GridView1$ctl02$TextBox2" type="text" id="ContentPlaceHolder1_ucstockcount1_GridView1_TextBox2_0" onblur="updatevals("ContentPlaceHolder1_ucstockcount1_GridView1_TextBox2_0",0,0,5.00,"ContentPlaceHolder1_ucstockcount1_GridView1_Label1_0","ContentPlaceHolder1_ucstockcount1_GridView1_Label2_0")" />
</td><td>
<span id="ContentPlaceHolder1_ucstockcount1_GridView1_Label1_0">0</span>
</td><td>5.00</td><td>
<span id="ContentPlaceHolder1_ucstockcount1_GridView1_Label2_0">0</span>
</td>
</tr><tr style="background-color:White;">
<td>2</td><td>T1-43B</td><td>0</td><td>0</td><td>
<input name="ctl00$ContentPlaceHolder1$ucstockcount1$GridView1$ctl03$TextBox2" type="text" id="ContentPlaceHolder1_ucstockcount1_GridView1_TextBox2_1" onblur="updatevals("ContentPlaceHolder1_ucstockcount1_GridView1_TextBox2_1",0,0,5.00,"ContentPlaceHolder1_ucstockcount1_GridView1_Label1_1","ContentPlaceHolder1_ucstockcount1_GridView1_Label2_1")" />
</td><td>
<span id="ContentPlaceHolder1_ucstockcount1_GridView1_Label1_1">0</span>
</td><td>5.00</td><td>
<span id="ContentPlaceHolder1_ucstockcount1_GridView1_Label2_1">0</span>
</td>
</tr>
I use the following code to extract values at client side.
function updatea(grid) {
$('#' + grid + ' tr').each(function (i) {
var style = "";
var lastmon = 0;
var received = 0;
var thismon = 0;
var change = 0;
var price = 0;
var value = 0;
$(this).children('td').each(function (j) {
if (j == 2) {
style = $(this).html();
} else if (j == 3) {
lastmon = $(this).html();
} else if (j == 4) {
received = $(this).html();
} else if (j == 5) {
thismon = $(this).children('input').val().trim();
alert(thismon);
}
// else if (j == 6) {
// change = $(this).children('span').val().trim();
// alert(change);
// }
// alert($(this).html());
});
});
}
Till 4th column I am able to get values as required but when i need to extract the value of a textbox that is inside the 5th column I get error TypeError: $(...).children(...).val(...) is undefined
I have taken the code from Traverse html table using jQuery
please help. Thankx
Two problems, the index starts from 0 so column with index 4 has input element, second the first row does not have input element
function updatea(grid) {
//start processing from row 1
$('#' + grid + ' tr').slice(1).each(function (i) {
var style = "";
var lastmon = 0;
var received = 0;
var thismon = 0;
var change = 0;
var price = 0;
var value = 0;
$(this).children('td').each(function (j) {
if (j == 1) {
style = $(this).html();
} else if (j == 2) {
lastmon = $(this).html();
} else if (j == 3) {
received = $(this).html();
//column 5 has index 4
} else if (j == 4) {
thismon = $(this).children('input').val().trim();
alert(thismon);
}
});
});
}
Demo: Fiddle
The index in each() is zero based, and the fifth TD doesn't have an input, the fourth has:
} else if (j == 4) {
thismon = $(this).children('input').val().trim();
alert(thismon);
}
You can make selections easier this way
$('#' + grid + ' tr').slice(1).each(function (i) {
var style = $('td:eq(1)', this).html();
var lastmon = $('td:eq(2)', this).html();
var received = $('td:eq(3)', this).html();
var thismon = $('td:eq(4) input', this).val();
}
+1 to #arun-p-johny for .slice(1)
Sometimes val() function didn't work for me in some conditions. You may test attr('value') instead of val() or you can change children() to $($(this).find('input')).val().trim() or $(this+'input').val().trim() or $(this).children().val().trim()
So I don't really remember right now but sometimes the returning object is not DOM Object.
Finally you can test $($(this).children('input')).val().trim().
As you can see there are too much moves to find anything. I just focused the main problem, so you need to test these and if any of them don't work, just tell me.
But I think the main problem is returning value is not DOM object. So it tries to reach non object and it gives error.

How to populate a table with vertical and horizontal results?

HeaderA HeaderB HeaderA HeaderB
stuff 232 hey 3434
world 033 boy 221
bat 435 girl 930
This table is dynamic and gets populated live. Here's my JS code, but the logic is not working correctly. I need to tell it that every 2 columns is a new record, and make a new row every 4th column. Here's what I have so far:
function html_data(data) {
var html = '';
$.each(data, function (index, value) {
if ((index+1) % 4 == 0 && index != 0) {
html += '<td>'+value+'</td>';
html += '</tr>'
} else if ((index+1) % 5 == 0) {
html += '<tr>';
html += '<td>'+value+'</td>';
} else {
html += '<td>'+value+'</td>';
}
html += '</tr>';
});
return html;
}
Obviously the above code is completely wrong, but that's all I have so far. If I can the get the mod logic, I can fill in the blanks.
Try this http://jsfiddle.net/G3JK5/
HTML
<table id="table">
<tr>
<th>HeaderA</th>
<th>HeaderB</th>
<th>HeaderA</th>
<th>HeaderB</th>
<th>HeaderA</th>
<th>HeaderB</th>
</tr>
</table>
<input type="button" id="btn" value="Add some random data" />
Javascript
//Sample usage
var tbl = new weirdTable('table');
document.getElementById('btn').addEventListener('click', function(){
tbl.addData([
parseInt(Math.random() * 100),
parseInt(Math.random() * 100)
]);
});
weirdTable
function weirdTable(tableId){
var _me = null;
var _currentIndex = 0;
var _colCount = 0;
var _lastRowIndex = 0;
var construct = function(tableId){
_me = document.getElementById(tableId);
_colCount = _me.rows[0].cells.length;
_currentIndex = _colCount;
};
this.addData = function(data){
var row = _me.rows[_lastRowIndex];
//or var data = arguments;
for(var i = 0; i < data.length; i++){
if(_currentIndex >= _colCount){
_lastRowIndex++;
_currentIndex = 0;
row = _me.insertRow(_lastRowIndex);
}
row.insertCell(_currentIndex).innerText = data[i];
_currentIndex++;
}
};
construct(tableId);
}
Unless I'm missing something, you can just do this:
if (index%4===0) { // start of a row
html += '<tr>';
}
html += '<td>'+value+'</td>';
if (index%4===3) { // end of row
html += '</tr>';
}

Replace html element with data in javascript

I trying to auto increment the serial number when row increases and automatically readjust the numbering order when a row gets deleted in javascript. For that I am using the following clone method for doing my task. Rest of the thing is working correct except its not increasing the srno because its creating the clone of it. Following is my code for this:
function addCloneRow(obj) {
if(obj) {
var tBody = obj.parentNode.parentNode.parentNode;
var trTable = tBody.getElementsByTagName("tr")[1];
var trClone = trTable.cloneNode(true);
if(trClone) {
var txt = trClone.getElementsByTagName("input");
var srno = trClone.getElementsByTagName("span");
var dd = trClone.getElementsByTagName("select");
text = tBody.getElementsByTagName("tr").length;
alert(text) //here i am getting the srno in increasing order
//I tried something like following but not working
//var ele = srno.replace(document.createElement("h1"), srno);
//alert(ele);
for(var i=0; i<dd.length; i++) {
dd[i].options[0].selected=true;
var nm = dd[i].name;
var nNm = nm.substring((nm.indexOf("_")+1),nm.indexOf("["));
dd[i].name = nNm+"[]";
}
for(var j=0; j<txt.length; j++) {
var nm = txt[j].name;
var nNm = nm.substring((nm.indexOf("_")+1),nm.indexOf("["));
txt[j].name = nNm+"[]";
if(txt[j].type == "hidden"){
txt[j].value = "0";
}else if(txt[j].type == "text") {
txt[j].value = "";
}else if(txt[j].type == "checkbox") {
txt[j].checked = false;
}
}
for(var j=0; j<txt.length; j++) {
var nm = txt[j].name;
var nNm = nm.substring((nm.indexOf("_")+1),nm.indexOf("["));
txt[j].name = nNm+"[]";
if(txt[j].type == "hidden"){
txt[j].value = "0";
}else if(txt[j].type == "text") {
txt[j].value = "";
}else if(txt[j].type == "checkbox") {
txt[j].checked = false;
}
}
tBody.insertBefore(trClone,tBody.childNodes[1]);
}
}
}
Following is my html :
<table id="step_details" style="display:none;">
<tr>
<th width="5">#</th>
<th width="45%">Step details</th>
<th>Expected Results</th>
<th width="25">Execution</th>
<th><img src="gui/themes/default/images/ico_add.gif" onclick="addCloneRow(this);"/></th>
</tr>
<tr>
<td><span>1</span></td>
<td><textArea name="step_details[]"></textArea></td>
<td><textArea name="expected_results[]"></textArea></td>
<td><select onchange="content_modified = true" name="exec_type[]">
<option selected="selected" value="1" label="Manual">Manual</option>
<option value="2" label="Automated">Automated</option>
</select>
</td>
<td><img src="gui/themes/default/images/ico_del.gif" onclick="removeCloneRow(this);"/></td>
</tr>
</table>
I want to change the srno. of span element dynamically after increment and decrement on it.
Need help thanks
I think that what you want is something this:
var varcharCurrentNumber = trClone.getElementsByTagName("span")[0].innerHTML;
var nextNumber= eval(varcharCurrentNumber) +1;
trClone.getElementsByTagName("span")[0].innerHTML = nextNumber;

remove/hide table's empty column(s), including <th>

How can I hide the column with all empty cells including the title <th> in that column, while leaving the other columns and their titles as it is. Following jquery hides the entire <th>, which is not I want. Here is a sample, where I want to hide only the entire 'Column3' including <th>. Many thanks in advance.
$('table#mytable tr').each(function() {
if ($(this).children('td:empty').length === $(this).children('td').length) {
$(this).hide();
}
});
Took a while to piece together. Thanks to nxt for some of the code.
$('#mytable th').each(function(i) {
var remove = 0;
var tds = $(this).parents('table').find('tr td:nth-child(' + (i + 1) + ')')
tds.each(function(j) { if (this.innerHTML == '') remove++; });
if (remove == ($('#mytable tr').length - 1)) {
$(this).hide();
tds.hide();
}
});
If you want to hide the column if all cells (ignoring the header) are empty, you could do something like:
$('#mytable tr th').each(function(i) {
//select all tds in this column
var tds = $(this).parents('table')
.find('tr td:nth-child(' + (i + 1) + ')');
//check if all the cells in this column are empty
if(tds.length == tds.filter(':empty').length) {
//hide header
$(this).hide();
//hide cells
tds.hide();
}
});
Sample: http://jsfiddle.net/DeQHs/
Sample 2 (adapted for jQuery > 1.7): http://jsfiddle.net/mkginfo/mhgtmc05/
None of the solutions here worked for me. This was what I used to hide empty columns with or without a text in the header:
$('table').each(function(a, tbl) {
var currentTableRows = $(tbl).find('tbody tr').length;
$(tbl).find('th').each(function(i) {
var remove = 0;
var currentTable = $(this).parents('table');
var tds = currentTable.find('tr td:nth-child(' + (i + 1) + ')');
tds.each(function(j) { if ($(this).text().trim() === '') remove++; });
if (remove == currentTableRows) {
$(this).hide();
tds.hide();
}
});
});
http://jsfiddle.net/nlovatt/JsLn8/
A multi-table example which avoids using the table id in the selectors
You need the next code:
HTML
<table id="mytable" border="1">
<thead>
<tr><th>Column1</th><th>Column2</th><th>Column3</th><th>Column4</th></tr>
</thead>
<tbody>
<tr class="data"><td>1st</td><td>1.1</td><td></td><td>1</td></tr>
<tr class="data"><td>2nd</td><td>2.01</td><td></td><td>2</td></tr>
<tr class="data"><td>3rd</td><td>3.001</td><td></td><td>3</td></tr>
<tr class="data"><td>4th</td><td>4.01</td><td></td><td>4</td></tr>
</tbody>
</table>
JavaScript
var $table = $('#mytable');
var thead = $table[0].tHead, tbody = $table[0].tBodies[0];
var colsLen = tbody.rows[0].cells.length, rowsLen = tbody.rows.length;
var hideNode = function(node) { if (node) node.style.display = "none"; };
for (var j = 0; j < colsLen; ++j) {
var counter = 0;
for (var i = 0; i < rowsLen; ++i) {
if (tbody.rows[i].cells[j].childNodes.length == 0) ++counter;
}
if (counter == rowsLen) {
for (var i = 0; i < rowsLen; ++i) {
hideNode(tbody.rows[i].cells[j]);
}
hideNode(thead.rows[0].cells[j]);
}
}
If the table data are from a MySQL query it possible to verify if a column is empty by using count on the field (count = 0 means that there are no values).
It is quite fastidious when you have many fields, and the IF condition is needed for the corresponding header and footer cells too. But it works...
if ($sum_field>'0') echo "<th>field</th>";
if ($sum_field>'0') echo "<td>" . $row['field'] . "</td>";
#nmat solution works fine but doesn't handle footers.

Categories