I have a page setup for a presentation layout:
+------------------------+
|prev next|
|+----------------------+|
|| page ||
|| dynamic content ||
|| ||
|+----------------------+|
+------------------------+
In the example above, next/prev are nav buttons that control the dynamic content using $("page").load(url);
On one of the pages I have a popup that has buttons in it that are linked to an ajax call which controls the content of the popup.
These buttons do their job nicely when the page is first loaded. If the page is changed (using the nav buttons) and then changed back, the popup will open but the buttons don't work. If you click the buttons, close the popup, and then reopen the popup, the information you requested on the 1st click shows but the buttons still don't work.
This tells me that the ajax request is fine, there is a problem with the binding of the elements somewhere. Here is my Javascript:
$('#resTable').on('click',this,function() {
$('#ayAvgDPm').html("");
$('#aoAvgDPm').html("");
$('#ayTotProfit').html("");
$('#aoTotProfit').html("");
$('#ayAvgPcPm').html("");
$('#aoAvgPcPm').html("");
$('#ayTotPcProfit').html("");
$('#aoTotPcProfit').html("");
$('#ayrRes').html("");
$('#etfProductPopup').bPopup();
});
$('div[class^="sideNav"]').on('click',this,function() {
$('#yrSummary').fadeIn(200);
$('#yAvgDPm').html("");
$('#oAvgDPm').html("");
$('#yTotProfit').html("");
$('#oTotProfit').html("");
$('#yAvgPcPm').html("");
$('#oAvgPcPm').html("");
$('#yTotPcProfit').html("");
$('#oTotPcProfit').html("");
$('#yrRes').html("");
var yr = "20"+$(this).attr('class').substr(-2);
var req = $.ajax({
url : '../includes/prod_results.php',
type : 'POST',
dataType : "json",
data : {
y : yr,
t : 'ETF'
},
success : function(j) {
var table = "<table cellspacing='0'><tr><th>Year</th><th>Returns</th></tr>";
for(var i = 0; i < 12; i++) {
if (i === 5 && yr === '2014'){
break;
}
var obj = j[i];
var month = obj['month'];
var profit = obj['profit'];
var bal = obj['bal'];
table += "<tr><td style='width:75px'>"+month+"</td><td style='padding: 0 15px'>"+parseFloat(profit).toFixed(2)+"%</td><td style='width:75px'>$"+comma(parseFloat(bal).toFixed(2))+"</td></tr>";
if (i === (11)) {
table += "</table>";
}
}
var YAvgDPm = comma(parseFloat(j.YAvgDPm).toFixed(2));
var OAvgDPm = comma(parseFloat(j.OAvgDPm).toFixed(2));
var YTotProfit = comma(parseFloat(j.YTotProfit).toFixed(2));
var OTotProfit = comma(parseFloat(j.OTotProfit).toFixed(2));
var YAvgPcPm = comma(parseFloat(j.YAvgPcPm).toFixed(2));
var OAvgPcPm = comma(parseFloat(j.OAvgPcPm).toFixed(2));
var YTotPcProfit = comma(parseFloat(j.YTotPcProfit).toFixed(2));
var OTotPcProfit = comma(parseFloat(j.OTotPcProfit).toFixed(2));
$('#yAvgDPm').html("$"+YAvgDPm);
$('#oAvgDPm').html("$"+OAvgDPm);
$('#yTotProfit').html("$"+YTotProfit);
$('#oTotProfit').html("$"+OTotProfit);
$('#yAvgPcPm').html(YAvgPcPm+"%");
$('#oAvgPcPm').html(OAvgPcPm+"%");
$('#yTotPcProfit').html(YTotPcProfit+"%");
$('#oTotPcProfit').html(OTotPcProfit+"%");
$('#yrRes').html(table);
$('#yrGraph').html("<img src='../images/graphs/etf_"+yr+".jpg'>");
return false;
}
});
return false;
});
I know it's fairly lengthy...
I have tried the above script both inside and outside the $(document).ready() handler.
Can someone please help me as to what I am not doing?
EDIT As requested, HTML:
<table id="resTable" cellspacing="0">
<tr>
<th>Year</th>
<th> 1st Quarter</th>
<th>2nd Quarter</th>
<th>3rd Quarter</th>
<th>4th Quarter</th>
<th>Year Total</th>
<th>Month Avg</th>
</tr>
...
</table>
<div id="etfProductPopup">
<h1 style="text-align:center">ETF - Compounded Results</h1>
<div id="popupLeftBar">
<div class="sideNav14">
2014
</div>
<div class="sideNav13">
2013
</div>
<div class="sideNav12">
2012
</div>
<div class="sideNav11">
2011
</div>
<div class="sideNav10">
2010
</div>
<div class="sideNav09">
2009
</div>
<div class="sideNav08">
2008
</div>
<div class="sideNav07">
2007
</div>
<div class="sideNav06">
2006
</div>
<div class="sideNav05">
2005
</div>
<div class="sideNav04">
2004
</div>
<div class="sideNav03">
2003
</div>
</div>
<div id="popupMain">
<div id="yrSummary">
<table cellspacing="0">
<tr>
<th></th>
<th>Avg<br>$/Mth</th>
<th>Total<br>$ Profit</th>
<th>Avg<br>%/Mth</th>
<th>Total<br>% Profit</th>
</tr>
<tr>
<th>Year</th>
<td id="yAvgDPm"></td>
<td id="yTotProfit"></td>
<td id="yAvgPcPm"></td>
<td id="yTotPcProfit"></td>
</tr>
<tr>
<th>Overall</th>
<td id="oAvgDPm"></td>
<td id="oTotProfit"></td>
<td id="oAvgPcPm"></td>
<td id="oTotPcProfit"></td>
</tr>
</table>
</div>
<div id="yrGraph"></div>
<div id="yrRes"></div>
</div>
Really? No body got any other ideas on this? I really need you guys to come through for me on this!
Code for nav buttons:
function nav(d) {
n = page + d;
$('#slide').load('p/'+n+'.php');
}
HTML:
<div class="prev" onClick="nav(-1)" title="Previous Page"><< Previous</div>
<div class="next" onClick="nav(1)" title="Next Page">Next >></div>
EDIT
So I have tried all 3 of the (current) answers and am getting nowhere! This is very frustrating!
I am starting to think there may be some underlying issues and that the bindings are not the complete problem.
The page obviously nees to be loaded as if it was refreshed by the browser. The fact that the page works fine the 1st time it is loaded, regardless of how it is loaded, says to me that the bindings are all fine.
The page also works fine without the popup.
Are there any ideas, other than the bindings, what the underlying issue could be?
Also, I know it is against the rules of SO for me to publish a link to the webpage in question, but if anyone would like a link, I am desperate enough to provide it privately. Please ask.
EDIT
So, I'm thinking, the hidded div (for the popup) is staying populated even after I use the following script:
$('#etfProductPopup').bPopup({
onClose : function() {
postLoadBindings();
$('#ayAvgDPm').html("");
$('#aoAvgDPm').html("");
$('#ayTotProfit').html("");
$('#aoTotProfit').html("");
$('#ayAvgPcPm').html("");
$('#aoAvgPcPm').html("");
$('#ayTotPcProfit').html("");
$('#aoTotPcProfit').html("");
$('#ayrRes').html("");
}
});
I'm thinking the issue may be with the popup script...
https://raw.githubusercontent.com/dinbror/bpopup/master/jquery.bpopup.min.js
EDIT
Also just noticed that the popup div is being duplicated on page load. From the console:
<div id="etfProductPopup" style="display: none; left: 440px; position: absolute; top: 156px; z-index: 2147483650; opacity: 0;">...</div>
<div id="etfProductPopup" style="display: none; left: 440px; position: absolute; top: 156px; z-index: 2147483650; opacity: 0;">...</div>
EDIT
(Yes, I realize if there was a badge for 'Most Edits to Own Question' then I would have won, but I think the more data I provide, the better chance of a response)
I created a #resTable element on another page (loaded the same way as the previous). I noticed that, even when using $('#resTable').unbind() in the document ready handler, clicking the element brings up the popup from the previous page!
HOW IS THIS POSSIBLE WHEN THE SCRIPT FOR THE POPUP DOESN'T EVEN EXIST ON THAT PAGE, LET ALONE THE CONTENT??
Someone, PLEASE! There MUST be a rational explanation for this! I am not trying to program humans, this is a computer code, this runs of bits of data and cannot simply make it up as it goes along!
Can someone please help me with this?
Got this far: Popup is creating duplicate div inside the outer page (the one with the nav buttons). I guess it is doing this so that it layers properly over the whole page, rather than just the page that contains the original code for the div.
EDIT
A more in depth look as to what is happening. The div for the popup is obviously inside the page, not the container. bPopup is moving the div to within the <body> tags of the containing page. This means that the div is available on all pages navigated to after the bPopup call. Closing the popup is not moving the div back, so when the page is reloaded using the nav buttons, the div is being duplicated.
Latest Progress
After speaking to the client I am not able to plost a live link, unfortunately.And to create a jsFiddle would take ages.
As explained in the edits above, the issue is bPopup re-creating the popup div inside the parent page and not removing it on popup close.
I am not sure if there is a way to delete an element on the page? The problem is, if an element can be deleted, the copy that bpopup creates is exactly the same as the original, so any script that targets the duplicate will also target the original
change:
$('#resTable').on('click',this,function() {
...
to
$(document).on('click','#resTable',function() {
...
and
$('div[class^="sideNav"]').on('click',this,function() {
...
to
$(document).on('click','div[class^="sideNav"]',function() {
...
Event delegation that #Sudhir mentioned should have worked, but yet, if you are facing the problem you might wanna try forcefully binding new events every time the page loads. Something like -
In the Main Page, that has the Prev and Next button, define all your functions -
var bindEvents = function(){
//we are unbinding to make
//sure we are not attaching more than once since
//instead of on, I am using direct CLICK binding.
$('#resTable').unbind("click").click(function() {
....
});
$('div[class^="sideNav"]').unbind("click").click(function() {
....
});
};
var nav = function(d) {
n = page + d;
$('#slide').empty();
$('#slide').load('p/'+n+'.php', function(){
//bind events
bindEvents();
});
}
$(function(){
//the first page call, when page loads
nav(0);
});
Remember that, this is not the best approach, but this will ensure that other things are alright. If this binding works then we can isolate the issue and confirm that there is problem in how you are using your bindings. Let me know if it still does not work.
I didn't try any fiddle on this, but have you tried putting the events binding of popup buttons on the "complete" hanlder of the ajax request? It seems a safer way to assure bindings to a single element:
var req = $.ajax({
url : '../includes/prod_results.php',
type : 'POST',
dataType : "json",
data : {
y : yr,
t : 'ETF'
},
success : function(j) {
var table = "<table cellspacing='0'><tr><th>Year</th><th>Returns</th></tr>";
for(var i = 0; i < 12; i++) {
if (i === 5 && yr === '2014'){
break;
}
var obj = j[i];
var month = obj['month'];
var profit = obj['profit'];
var bal = obj['bal'];
table += "<tr><td style='width:75px'>"+month+"</td><td style='padding: 0 15px'>"+parseFloat(profit).toFixed(2)+"%</td><td style='width:75px'>$"+comma(parseFloat(bal).toFixed(2))+"</td></tr>";
if (i === (11)) {
table += "</table>";
}
}
var YAvgDPm = comma(parseFloat(j.YAvgDPm).toFixed(2));
var OAvgDPm = comma(parseFloat(j.OAvgDPm).toFixed(2));
var YTotProfit = comma(parseFloat(j.YTotProfit).toFixed(2));
var OTotProfit = comma(parseFloat(j.OTotProfit).toFixed(2));
var YAvgPcPm = comma(parseFloat(j.YAvgPcPm).toFixed(2));
var OAvgPcPm = comma(parseFloat(j.OAvgPcPm).toFixed(2));
var YTotPcProfit = comma(parseFloat(j.YTotPcProfit).toFixed(2));
var OTotPcProfit = comma(parseFloat(j.OTotPcProfit).toFixed(2));
$('#yAvgDPm').html("$"+YAvgDPm);
$('#oAvgDPm').html("$"+OAvgDPm);
$('#yTotProfit').html("$"+YTotProfit);
$('#oTotProfit').html("$"+OTotProfit);
$('#yAvgPcPm').html(YAvgPcPm+"%");
$('#oAvgPcPm').html(OAvgPcPm+"%");
$('#yTotPcProfit').html(YTotPcProfit+"%");
$('#oTotPcProfit').html(OTotPcProfit+"%");
$('#yrRes').html(table);
$('#yrGraph').html("<img src='../images/graphs/etf_"+yr+".jpg'>");
return false;
},
complete:function(){
//put the bindings to popup here
}
});
try this
$("body").delegate('#resTable','click',function() {
//some codes
}
$("body").delegate('div[class^="sideNav"]','click',function() {
//some codes
}
Related
I'm creating a button through JavaScript and am trying to assign it to an onclick event. At runtime the button is created but the onclick event isn't firing when I click it. Also in Chrome's Inspector, no error is generated when I click the button.
Here's my code:
function truncator(){
$.each($('td.rawdata-field').not(':empty'), function(i,v){
var count = parseInt($(v).text().length);
var maxChars = 650;
if(count > maxChars){
var str = $(v).text();
var trimmed = str.substr(0, maxChars - 2);
$(v).text(trimmed + '...');
var btn = document.createElement('button');
btn.setAttribute('content', 'test content');
btn.setAttribute('class', 'show-full-text-button');
btn.innerHTML = 'Show Full Log';
btn.onclick = function() {
alert("assd");
};
$(v).append(btn);
}
});
};
v is the parent container, which in this case is a td element.
What's the problem here?
EDIT:
One additional detail I can offer is that the above is being executed many times over a page, which is have something to do with why it isn't working. All the buttons are being created fine, but the alert's aren't working when done through the above method.
The container already exists when the above code is executed.
EDIT 2:
I've updated the code above to include more of what is going on. The function truncator basically is supposed to go through all td elements with class rawdata-field that are not empty, and check if the text mentioned in it is longer than 650 characters. If it is, it truncates the text to 650 characters and then puts a button there to showing the complete log if the user wishes to do so.
The table on which the above function operates already exists when truncator is called.
Your code work fine here: https://jsfiddle.net/dusfqtr9/
$(document).ready(function() {
var btn = document.createElement('button');
btn.setAttribute('content', 'test content');
btn.setAttribute('class', 'show-full-text-button');
btn.innerHTML = 'Show Full Log';
btn.onclick = function() {
alert("Hello !");
};
$("#container").append(btn);
});
Maybe your script is run before the parent container created, so $(v).append(btn) do nothing.
onclick only works with the elements that already exist at the time when the script (containing your onclick handler) is loaded. As such, elements that get created after that, are no longer bound to the onclick event that you specified in the loaded script.
I'm not sure what your full code set is, but I'm guessing that your button is regenerated probably several times after the script is loaded. This is the most likely reason why the onclick event does not fire.
As such, what you would want to do is to "attach" the event handler to a higher level in the DOM tree (highest being your html) that you are sure won't get 'programmatically' regenerated, then you'd want to check if the element in question, which is inside the DOM, exists. You then run your function when this element is found.
Below is a JQuery implementation of this logic using the .on :
EDIT1: I've edited the code based on your latest comment. You'll notice that I've separated the function that handles the click of your buttons. I urge you to try doing this in your original code set, and you'll see that the onclick event will always be bound to your buttons regardless of when your buttons are created, or even how many times you regenerate them.
EDIT2: I just noticed in the comments that you wanted to show the full text in the alert. Edited the code to show one way of doing that.
function truncator(){
$.each($('td.rawdata-field').not(':empty'), function(i,v){
var origContent = $(v).text();
$(v).attr('orig-content',origContent);
var count = parseInt($(v).text().length);
var maxChars = 10;
if(count > maxChars){
var str = $(v).text();
var trimmed = str.substr(0, maxChars - 2);
$(v).text(trimmed + '...');
var btn = document.createElement('button');
btn.setAttribute('content', 'test-content');
btn.setAttribute('class', 'show-full-text-button');
btn.innerHTML = 'Show Full Log';
$(v).append(btn);
}
});
};
$('html').on('click', '.show-full-text-button', function(){
content = $(this).closest('td').attr('orig-content');
alert(content);
});
truncator();
table td {
border:1px solid black;
padding:5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td class="rawdata-field"> this is a very long text </td>
<td class="rawdata-field"> another long text </td>
<td class="rawdata-field"> this is getting out ofhand </td>
</tr>
<tr>
<td class="rawdata-field"> okay another longtext </td>
<td class="rawdata-field"> more content here, and there's another one here </td>
<td class="rawdata-field"> what am i doing here </td>
</tr>
</table>
This is my first post as I usually find answers (or similar ones) to my questions easily via Google and StackExchange sites. However, I've tried researching various methods, but I am not finding one that meets what I am trying to do. Hopefully someone smarter than me can help me figure this out.
My main page has a "InitiativeContainer" DIV. This DIV loads content into sub DIV containers ListDetails and InitiativeDetails. These sub containers are separate pages loaded into the sub DIVs so that the entire main page is not reloaded, only these content containers. The mainpage loads with the ListDetails DIV populated and is a seperate page with a DataTable named tblDetails. I want to grab the ID of the row that is clicked on in the Datatable, and return that ID as a variable to the parent page so that it can be passed to the InitiativeDetails page.
Right now, I can achieve an alert with getKeyValue, but only after 2 clicks. The 1st click does nothing, but the second and following clicks provide the ID in an alert. The 2 clicks is not user friendly and has to be corrected. It is as if the ListDetails container is not being "initialized" or the "focus" set and the first click initializes/sets the focus of the DIV and the second click does what it is supposed to. Code Below:
Main Page snippet:
<div class="InitiativeContainer">
<div id="ListDetails"></div>
<div id="InitiativeDetails"></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
ListDetails.onload=ListLoad();
});/*End (document).ready*/
</script>
<script>
function ListLoad() {
var urlListDetails = './cfm/Initiative_List.cfm';
var ListDetails = $('#ListDetails');
$.ajax({
beforeSend: function() {
ListDetails.html('<b>Loading...</b>');
},
success: function(html) {
ListDetails.html(html);
},
url: urlListDetails
}); /*End Ajax*/
}; /*End ListLoad*/
ListLoad();
function DetailLoad(InitiativeID) {
var InitiativeID = 1
var urlInitiativeDetails = './cfm/Initiative_Info.cfm?InitiativeID=' + InitiativeID;
var InitiativeDetails = $('#InitiativeDetails');
$.ajax({
beforeSend: function() {
InitiativeDetails.html('<b>Loading...</b>');
},
success: function(html) {
InitiativeDetails.html(html);
},
url: urlInitiativeDetails
}); /*End Ajax*/
} /*End DetailsLoad*/
function getKeyValue(key){
var keyValue = key
alert('key Value: '+keyValue)
}
$('#ListDetails').on('click',function(event) {
// Get project_key
$('#tblDetail tbody tr').on('click',function(event){
var k2 = $(this).find('td').first().text();
event.stopPropagation();
getKeyValue(k2);
return false;
});
return false;
});
</script>
Initiative_List.cfm page Snippet:
<div id="ListDetails" align="center" style="width:100%;">
<table id="tblDetail" class="title display compact cell-border dataTable_pointer" cellpadding="0" cellspacing="0" border="0">
<thead>
<tr>
<th>ID</th>
<th>Prospect</th>
<th>Status</th>
<th>ClientType</th>
<th>Effective</th>
<th>Approved</th>
<th>Consultant</th>
<th>Audit Request</th>
<th>Completed</th>
</tr>
</thead>
<tbody>
<cfoutput query="qryListDetails">
<tr>
<td>#qryListDetails.ID#</td>
<td>#qryListDetails.Prospect#</td>
<td>#qryListDetails.ProspectStatus#</td>
<td>#qryListDetails.ClientType#</td>
<td>#dateFormat(qryListDetails.EffectiveDate,"yyyy-mm-dd")#</td>
<td>#qryListDetails.Approved#</td>
<td>#qryListDetails.Consultant#</td>
<td>#dateFormat(qryListDetails.AuditRequestDate,"yyyy-mm-dd")#</td>
<td>#qryListDetails.Completed#</td>
</tr>
</cfoutput>
</tbody>
</table>
</div>
Is the issue that I have a nested click event inside of a click event? If so how could I handle this better? I am looking to understand what I am doing wrong in addition to a better code solution. Thank you in advance.
The #tblDetail tbody tr click handler should be defined outside of your ListDetails click handler. That is likely causing the click-twice issues.
I don't see what the ListDetails handler is supposed to be doing, maybe we can just omit that and have the end of your code snippet look something like this:
function getKeyValue(key){
var keyValue = key
alert('key Value: '+keyValue)
}
$('#ListDetails').on("click", "#tblDetail tbody tr", function(event) {
var k2 = $(this).find('td').first().text();
event.stopPropagation();
getKeyValue(k2);
return false;
});
</script>
It seems you were on the right track, the nesting of click handlers caused the inner handler to be defined only after the outer click handler had fired. After the first click, the inner handler starts working.
Ladies and gents of the internet I have an issue with jquery.
I have 3 templates on a page one for the top of a table one for the bottom and one for the rows. They look like this.
Header
<div class="col-md-12 tableContainer">
<table class="table table-hover table-condensed">
<thead>
<tr>
<th class="hidden-xs"></th>
<th></th>
<th>Artist</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
Row
<tr data-bind='{"visible":"!isFiltered"}' class="handPointer">
<td style="width: 22px;">
<img alt="{{Libary}}" src="#:libaryImageSrc#" width="22"/>
</td>
<td style="width: 22px;">
<span
class="glyphicon glyphicon-cog"
aria-hidden="true"
data-bind='{"click":"spawnAddToPlaylistModal"}'>
</span>
</td>
<td><span>{{Name}}</span></td>
<td><span data-bind='{"click":"loadAlbums"}'>Albums</span></td>
<td><span data-bind='{"click":"loadSongs"}'>Songs</span></td>
</tr>
Footer
</tbody>
</table>
</div>
The issue is that when I try and use my templates as html objects jquery assumes I have just been lasy and left of the closing tag and breaks every thing. I have a function that parses and creates the templates in batches so the execution of the rendering of 1000s of lines does not lock up the user interface. I also have a widget binding engine I made so I can bind functions using data-bind on the html elements.
The catch is I want them to render all at the same time not section at a time so I create document fragments and then once all the batch is completed I Inject the pre-bound html like so. This is in a function that first calls the headers then x rows then the footer.
// Bootstrap render call function
// Results in correct markup as a string
template = bootstrapTemplateObject(dataSource[0]);
// At this point I need a htmlObject so I call it in jquery
// but then jquery decides it can fix it
htmlObject = $(template);
// Then I add the fragment
fragment.appendChild(htmlObject[0]);
// Then I bind the fragment
widget.bind(htmlObject, 0);
Question is can I stop jquery "fixing" my code. If so how?
----- Update 1 -----
Ok so following on from PJs answer I have created the following.
// First empty the target
target.empty();
// As Paul-Jan suggested we create one big string of html so it is well formed(or at least should be).
template = "";
// If we have a header we add it
if (header !== null) {
template += header(dataSource[0]);
}
// Then we start the hackyness by adding a target placeholder for later.
// I choose script as far as im aware this can go anywhere with out being incorrect html.
// And at this point I dont know if the header / footer are acting as a container ie nested or not.
template += "<script id='superMergerTarget'></script>";
// If we have footer add it.
if (footer !== null) {
template += footer(dataSource[0]);
}
// Now we make the string a html object
htmlObject = $(template);
// So at this point we could have nothing but the script or a container or a wrapper
// So we iterate over like so.
for (var k = 0; k < htmlObject.length; k++)
{
var targetReplaceo = $(htmlObject[k]).
// check if its nested in container situation.
find('#superMergerTarget').
// Check self if wrapper or single situation.
addBack('#superMergerTarget');
if (targetReplaceo.length === 1) {
var element = targetReplaceo[0];
if (element.parentElement === null)
{
// If we are in here then either the header and or footer dont exists.
// Or the header and footer are stand alone html not wrapping the content.
// So we just go ahead and chuck it in the target.
if (header !== null) {
template = header(dataSource[0]);
htmlObject = $(template);
widget.bind(htmlObject, 0);
target.append(htmlObject);
}
target[0].appendChild(fragment);
if (footer !== null) {
template = footer(dataSource[0]);
htmlObject = $(template);
widget.bind(htmlObject, 0);
target.append(htmlObject);
}
break;
}
widget.bind(htmlObject, 0);
// This part seems filthy and there is probably a much better way of doing it.
// First we get an element to add the fragment too.
var newElement = element.cloneNode();
newElement.innerHTML = "";
newElement.appendChild(fragment);
// then we get the individual templates and add them one at a time.
var childNodes = newElement.childNodes;
for (var l = 0; l < childNodes.length; l++)
{
element.parentNode.insertBefore(childNodes[l], element);
}
// then remove the placeholder
element.parentNode.removeChild(element);
// then we add it to the target.
target.append(htmlObject);
break;
}
}
I feel like it could be much better but it does work so I'm happy with that, can anyone suggest a better way?
You can't. DocumentFragments are DOM nodes, as such they cannot be constructed from "badly formed HTML". That's hardly jQuery's fault :)
However, I don't see (yet) why you need to construct your document fragments from malformed HTML. For instance, what is stopping you from initializing the fragment from the header and the footer (together they make a valid DOM node), then getting the tbody from the fragment, and batchwise attach your rows to it?
My code looks like this...
div to show content and loading image:
<div id="adS" style="float: left; width: 70%">
<div id="loading-image" style="background-image: url('images/processing.gif'); display: none;">
</div>
</div>
jQuery code:
$(function() {
$("#lets_search").bind('submit',function() {
var gen = $("input[name='radGen']:checked").val();
var mt = $('#selMtQ').val();
var agf = $('#agf').val();
var agt = $('#agt').val();
var rel = $('#religQ').val();
var cast = $('#selCstQ').val();
$('#loading-image').show();
$.post('adSearch.php',{gen:gen,mt:mt,agf:agf,agt:agt,rel:rel,cast:cast}, function(data){
$("#adS").html(data);
$('#loading-image').hide();
});
return false;
});
});
The loading image is only shown once on click event and not every time I click the search li... :(
Need help...
To check if it is the server that is responding very quickly you could test it with the setTimeOut() function at the ajax process. If the picture is not shown then it is not the server that is very quickly but something else. But more of your code is needed then to understand what is going on.
UPDATE: Sorry, forgot to include some of the code (face-palm). I included it in with the initial code provided so everything will be clear. I'm really new to this stuff so please forgive me for not having the time to learn jsfiddle right now (I know what it is and does though).
I have figured out the problem with the sort toggling every time the table updates. The sorting() function I put into the code was new and calling method.sorting(); inside of the getEvents(method) function solved the issue. However, I'm still stuck on the refresh button concept.
One other problem I noticed and haven't figured out how to solve is that when I load the page, I have to wait for the first setInterval to start until the table populates. How do I work around this so that when the page initially loads, it immediately loads the data without having to wait the specified time within the setInterval?
One last problem: when the table auto-updates, any rows that were added using the addRow() function disappear because they aren't part of the info from the server (and no, I can't have the rows be populated to the server); how can I make the auto-update leave the added rows in without having to get the added rows updated to the server?
I have a HTML Table that uses knockoutjs to bind the data into the columns dynamically from a server using the $.getJSON(http://.....) method. I wish to be able to create a refresh button to refresh/update the table-and ONLY the table (I.E. not refreshing the whole page).
As it is right now, the table updates using the setInterval() function at bottom of the js file, but keeps toggling the column sortings. I can't figure out how to stop this.
Here's the code snippets needed for this:
HTML file:
<table border="6" id="widget"><thead>
<tr>
<th>TimeObserved</th>
</tr></thead>
<tbody data-bind="foreach: rows">
<td><input data-bind="value: TimeObserved, valueUpdate: 'change' " /></td>
</tbody>
</table>
<div>
<button date-bind="click: addRow, enable: rows()">Add Row</button>
</div>
<script src="TableViewModel.js" type="text/javascript"></script>
Heres the javascript viewmodel file:
function Event(TimeObserved){
var self = this;
self.TimeObserved = TimeObserved;
}
function TableViewModel(){
var self = this;
self.sortColumn = ko.observable("TimeObserved");
self.sortAscending = ko.observable(true);
self.addRow = function(){
self.rows.push(new Event(""));
}
self.SortByTimeObserved(){
if(self.sortColumn == "TimeObserved")
self.sortAscending = !self.sortAscending;
else{
self.sortColumn = "TimeObserved";
self.sortAscending = true;
}
self.rows.sort(function(a,b){
if(self.sortAscending == true)
for(self.TimeObserved in self.rows)
return a.TimeObserved > b.TimeObserved ? -1 : 1;
else
return a.TimeObserved < b.TimeObserved ? -1 : 1;
});
}
self.sorting = function(){
if(self.sortColumn() = "TimeObserved"){
self.rows.sort(function(a,b){
if(self.sortAscending() == true)
for(self.TimeObserved in self.rows)
return a.TimeObserved > b.TimeObserved ? 1 : a.TimeObserved < b.TimeObserved ? -1 : 0;
else
return a.TimeObserved < b.TimeObserved ? 1 : a.TimeObserved > b.TimeObserved ? -1 : 0;
}
}
}
//Access the server and pulls the info from it. I also apply my sorting() method to initially sort the info here.
function getEvents(model){
$.getJSON("http://mywebpage.com",
function (data){
model.rows([]);
$.each(data.d, function(i,item){
hendleEvent(item)
});
model.sorting();
}
);
}
//Populates the rows of the table with the info from the server I.E. item."infoIwant"
function handleEvent(item){
var newEvent = new Event(item.TimeObserved);
this.Model.rows.push(newEvent);
}
this.Model = new TableViewModel();
var eventInterval = setInterval(function(){
getEvents(this.Model);
}, 5000);
ko.applyBindings(this.Model);
You should take a look at the knockout mapping pluggin:
http://knockoutjs.com/documentation/plugins-mapping.html
-- UPDATE
Also take a look at understanding the MVVM pattern
http://addyosmani.com/blog/understanding-mvvm-a-guide-for-javascript-developers/
I solved it by making the table itself update dynamically instead of having to rely on a button. The info is supposed to be read only anyway so editing is not a factor to consider. I also somehow got it to not undo the current sort that is activated.
by adding this into the viewmodel, I set the table to update after the given interval time:
var eventInterval = setInterval(function(){
getEvents(this.Model);
), 5000); //<-- in milliseconds