Have a loading gif while query loads in ColdFusion - javascript

I've seen a couple similar questions on here already, but none that were close enough to what I want that actually had an answer.
I have a CF page. The query that generates most of the page has the potential, depending on the user, to go long and then we're staring at a blank page for a moment, thinking that it's unresponsive.
Basically, I've been tasked with having a loading gif of sorts on the page until it's ready so that the user doesn't think it's crashed.
I've tried the CFFLUSH method, and besides the fact that it doesn't really work as expected (we're using IE9 and IIS and apparently there are settings not playing nicely with each other) it also leaves the "loading" text/image on the screen once the main page loads. I want it to go away once the page loads.
I can't use jQuery
I can't really use native Ajax anymore than what I can access using CFAJAX calls, etc.
The other developer here has suggested using CFWINDOW like he does elsewhere to check if the session is timing out, etc., but I haven't figured out how yet. I'd be open to those if someone could guide me on that.
Thoughts?

cfdiv.
The other developer was racking his brains since he said he knew he did this somewhere before. In the end, he found it and it was a cfdiv.
Basically, you take the "offending" (i.e.: long lasting) code and cut it out into another file. Then, you add a <cfajaximport> to the head and then, in place where the code was you put:
<cfdiv id="divID" name="divName" bind="url:pageWithCode.cfm?(anyparameters)" bindonload="true" />
and be sure to refer to the parameters in the file as "url." and it all works perfectly!
Thanks all for your help!

Maybe i am missing something but the answer seems simple to me. Just spit up the page with executes the query and the page that shows the result. The page that executes the query can also contain the actual formatting. Below a simple example.
<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY>
<div id="body" style="width:100px">loading statement or loading images</div>
<script>
function load_url(url)
{
var obj;
if (window.XMLHttpRequest) obj = new XMLHttpRequest();
else if (window.ActiveXObject) obj = new ActiveXObject("Microsoft.XMLHTTP");
if (obj !== null)
{
obj.onreadystatechange = function()
{
if (obj.readyState === 4)
{
var response = obj.responseText;
alert(response);
document.getElementById('body').innerHTML = response;
}
};
obj.open("GET", url, true);
obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
obj.send();
}
}
load_url('/loadActualdata.cfm?timestamp=' + new Date().getTime().toString());
</script>
</BODY>
</HTML>
HTML on loadActualdata.cfm
<table style="width:100%;border:1px solid red" border="0" cellpadding="0" cellspacing=""0">
<tr>
<td><b>test</b></td>
</tr>
</table>

Related

Firefox hangs on a long lasting operation

I have an MVC application and I am using a gif to indicate loading by using JQuery.
The code below works okay on Chrome.
// show loading
window.parent.loading(true);
$.get('#Url.Action("getUserAccounts")', function (data) {
$("#usersAccountsDiv").html(data);
window.parent.resizeIframe();
});
However, in Firefox, the loading indicator freezes along with the whole page. Since the operation is not taking too much time, I tried to mock this by using a sleep function like that and the results were the same on Chrome and Firefox. While Chrome keeps playing the gif, Firefox stops playing it:
window.parent.loading(true);
$.get('#Url.Action("getUserAccounts")', function (data) {
function (data) {
function sleepFor(sleepDuration) {
var now = new Date().getTime();
while (new Date().getTime() < now + sleepDuration) {
/* Do nothing */
}
}
sleepFor(10000);
$("#usersAccountsDiv").html(data);
window.parent.resizeIframe();
});
I used w3schools' editor to see the difference:
w3 try editor
I used this code below in both browsers for comparison:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$("#showMe").show();
$.get("demo_test.asp", function(data, status){
function sleepFor(sleepDuration) {
var now = new Date().getTime();
while (new Date().getTime() < now + sleepDuration) {
/* Do nothing */
}
}
sleepFor(10000);
});
});
});
</script>
</head>
<body>
<button>Send an HTTP GET request to a page and get the result back</button>
<div id="showMe" style="display:none">
<img src="https://media.giphy.com/media/3o7bu3XilJ5BOiSGic/giphy.gif" />
</div>
</body>
</html>
I tried to mock it that way because I could not reproduce this issue on my local. It only happens in QA environment. The operation takes longer in QA and that causes Firefox to freeze.
On Firefox, once the code hits to $("#usersAccountsDiv").html(data); function, the problem occurs. That's why I remove .html() function and replaced it with sleepFor function to make the JS engine wait on Firefox. My expectation was gif should keep playing as it does in Chrome while I wait for sleepFor function to end.
First, replace
sleepFor(10000);
$("#usersAccountsDiv").html(data);
window.parent.resizeIframe();
with
window.setTimeout(function() {
$("#usersAccountsDiv").html(data);
window.parent.resizeIframe();
}, 10000);
See https://developer.mozilla.org/en-US/docs/Web/API/setTimeout for usage of setTimeout().
Do not make busy-waiting loops like your function sleepFor() - this precisely bogs down the browser's JavaScript engine.
Then, I suggest to focus on the first code snippet (without sleepFor() nor setTimeOut()) and use the Firefox debug console (press F12 key) to figure out what kind of answer you get from the server on your get() request.
To do this, press F12, a sidebar opens, go to the "network" tab and look for the GET request that your code sends (each GET is a line, timing diagram to the right of it). Select it by clicking, another sub-window opens with details of the GET request - go to the "response" sub-window and inspect whether it is what you expect.
I have checked the response data returning from get action and I found the solution. Returned html data contains 18 lines of scripts.
$("#usersAccountsDiv").html(data);
After that, I debugged the JQuery html and append methods and realized that script tags are making Firefox freeze in a for loop (domManip function). I resolved the issue by reducing the included scripts to my response but it is still a weird problem. All those scripts are working fine on Chrome but not on Firefox.
Thanks!

Modal popup window's contents not being rewritten in IE after load

I'm trying what should have been a simple operation: when a user clicks a link a modal window pops up that's populated with some appropriate data in a string. Here's the HTML for the window:
<!DOCTYPE HTML>
<html>
<head>
<title>Modal Display Window</title>
</head>
<body>
<div id="modal_display_block">REPLACE THIS</div>
</body>
</html>
And this is the Javascript function that calls and populates the window:
function displayCenterBlock(data) {
DispWin = window.open("modal_window.html", "", 'toolbar=no,status=no,width=300,height=300');
DispWin.onload = function() {
DispWin.document.getElementById('modal_display_block').innerHTML = data;
}
}
This works great in every browser I've tried except Internet Explorer. In IE the innerHTML does not get rewritten by the data. Is there some IE-specific trick or tweak I need to apply to get this working in that browser?
Many thanks in advance!
ON EDIT: I've discovered that if I move the element rewrite line out of the onload function it then works fine in IE but not in other browsers. It appears my options are to use some conditional code to rewrite at once for IE and to wait for page load for all other browsers, or to abandon the rewrite element approach and just use a document.write. I get from forum searches people like to discourage document.write but that's looking pretty appealing right now.
Okay, for better or worse this code achieves the goal and appears to work cross browser, even in IE.
DispWin = window.open("", "Display", 'toolbar=no,status=no,width=300,height=300');
DispWin.document.open();
DispWin.document.write(data);
DispWin.document.close();
DispWin.focus();
I get that document.write can re-write the whole page, and that is sometimes bad, but in this case that is exactly what I want: a single small page displaying only what was passed in the data argument. I can style it inline.

How to use Javascript/jQuery to load the content from another domain?

I need to create a javascript application that can display the content from another domain (admittedly another big website). Further interpretation of the DOM tree is not needed at the moment. It will be used by only ten more people.
I can make it work via php's get_content function. But that is very slow since it runs on the server side. I looked into any origin but cannot get it to work. It is best to not touch any origin since we use it extensively and we don't have much cash to spend around. Can anyone help? By the way, iframe is not an option since the big website blocked it. The code is below. Admittedly I kind of took it from another stackoverflow answer. Thank you in advance!
Btw. another engineer told me if I use the extension .hta instead of html, the same-origin policy issue would be resolved. I tried it and it did not work. But I was wondering if I did it right.
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
function myCallbackFunction(myData) {
$(function() {
$("#test").contents().find('html').html(myData.contents);
});
}
</script>
<script src="http://anyorigin.com/get?url=http://http://www.amazon.com/dp/B001F7SGHQ/&callback=myCallbackFunction"></script>
</head>
<body>
</body>
<iframe id='test' style='width: 100%; height: 100%'>
</html>
Try something like the following.
var invocation = new XMLHttpRequest();
var url = 'http://http://www.amazon.com/dp/B001F7SGHQ/&callback=myCallbackFunction';
function callOtherDomain() {
if(invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler;
invocation.send();
}
}
Addition of [withCredentials = true] will enable the HTTP header "Access-Control-Allow-Origin:".
there's another good solution might be what you need via PHP ,
is to use class called PHP
Simple HTML DOM Parser
this class can copy all source of a websites and you can save it in your server with extension you want also you can modified what you need before you save and this class have a full documentation (You need to be good in PHP5 POO )
this a link for class
http://simplehtmldom.sourceforge.net/
and there a good advanced thing you can do it for make your website faster , is use a Cash System so you can download the source from website one time a Day or 1H or 12 Hours ,
and save it in your host .
i hope that will give you what you need .

Trying to load an API and a JS file dynamically

I am trying to load Skyscanner API dynamically but it doesn't seem to work. I tried every possible way I could think of and all it happens the content disappears.
I tried console.log which gives no results; I tried elements from chrome's developers tools and while all the content's css remains the same, still the content disappears (I thought it could be adding display:none on the html/body sort of). I tried all Google's asynch tricks, yet again blank page. I tried all js plugins for async loading with still the same results.
Skyscanner's API documentation is poor and while they offer a callback it doesn't work the way google's API's callback do.
Example: http://jsfiddle.net/7TWYC/
Example with loading API in head section: http://jsfiddle.net/s2HkR/
So how can I load the api on button click or async? Without the file being in the HEAD section. If there is a way to prevent the document.write to make the page blank or any other way. I wouldn't mind using plain js, jQuery or PHP.
EDIT:
I've set a bounty to 250 ontop of the 50 I had previously.
Orlando Leite answered a really close idea on how to make this asynch api load although some features doesn't work such as selecting dates and I am not able to set styling.
I am looking for an answer of which I will be able to use all the features so that it works as it would work if it was loading on load.
Here is the updated fiddle by Orlando: http://jsfiddle.net/cxysA/12/
-
EDIT 2 ON Gijs ANSWER:
Gijs mentioned two links onto overwriting document.write. That sounds an awesome idea but I think it is not possible to accomplish what I am trying.
I used John's Resig way to prevent document.write of which can be found here: http://ejohn.org/blog/xhtml-documentwrite-and-adsense/
When I used this method, I load the API successfuly but the snippets.js file is not loading at all.
Fiddle: http://jsfiddle.net/9HX7N/
I belive what you want is it:
function loadSkyscanner()
{
function loaded()
{
t.skyscanner.load('snippets', '1', {'nocss' : true});
var snippet = new t.skyscanner.snippets.SearchPanelControl();
snippet.setCurrency('GBP');
snippet.setDeparture('uk');
snippet.draw(document.getElementById('snippet_searchpanel'));
}
var t = document.getElementById('sky_loader').contentWindow;
var head = t.document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.onreadystatechange= function() {
if(this.readyState == 'complete') loaded();
}
script.onload= loaded;
script.src= 'http://api.skyscanner.net/api.ashx?key=PUT_HERE_YOUR_SKYSCANNER_API_KEY';
head.appendChild(script);
}
$("button").click(function(e)
{
loadSkyscanner();
});
It's load skyscanner in iframe#sky_loader, after call loaded function to create the SearchPanelControl. But in the end, snippet draws in the main document. It's really a bizarre workaround, but it works.
The only restriction is, you need a iframe. But you can hide it using display:none.
A working example
EDIT
Sorry guy, I didn't see it. Now we can see how awful is skyscanner API. It puts two divs to make the autocomplete, but not relative to the element you call to draw, but the document.
When a script is loaded in a iframe, document is the iframe document.
There is a solution, but I don't recommend, is really a workaround:
function loadSkyscanner()
{
var t;
this.skyscanner;
var iframe = $("<iframe id=\"sky_loader\" src=\"http://fiddle.jshell.net/orlleite/2TqDu/6/show/\"></iframe>");
function realWorkaround()
{
var tbody = t.document.getElementsByTagName("body")[0];
var body = document.getElementsByTagName("body")[0];
while( tbody.children.length != 0 )
{
var temp = tbody.children[0];
tbody.removeChild( temp );
body.appendChild( temp );
}
}
function snippetLoaded()
{
skyscanner = t.skyscanner;
var snippet = new skyscanner.snippets.SearchPanelControl();
snippet.setCurrency('GBP');
snippet.setDeparture('uk');
snippet.draw(document.getElementById('snippet_searchpanel'));
setTimeout( realWorkaround, 2000 );
}
var loaded = function()
{
console.log( "loaded" );
t = document.getElementById('sky_loader').contentWindow;
t.onLoadSnippets( snippetLoaded );
}
$("body").append(iframe);
iframe.load(loaded);
}
$("button").click(function(e)
{
loadSkyscanner();
});
Load a iframe with another html who loads and callback when the snippet is loaded. After loaded create the snippet where you want and after set a timeout because we can't know when the SearchPanelControl is loaded. This realWorkaround move the autocomplete divs to the main document.
You can see a work example here
The iframe loaded is this
EDIT
Fixed the bug you found and updated the link.
the for loop has gone and added a while, works better now.
while( tbody.children.length != 0 )
{
var temp = tbody.children[0];
tbody.removeChild( temp );
body.appendChild( temp );
}
For problematic cases like this, you can just overwrite document.write. Hacky as hell, but it works and you get to decide where all the content goes. See eg. this blogpost by John Resig. This ignores IE, but with a bit of work the trick works in IE as well, see eg. this blogpost.
So, I'd suggest overwriting document.write with your own function, batch up the output where necessary, and put it where you like (eg. in a div at the bottom of your <body>'). That should prevent the script from nuking your page's content.
Edit: OK, so I had/took some time to look into this script. For future reference, use something like http://jsbeautifier.org/ to investigate third-party scripts. Much easier to read that way. Fortunately, there is barely any obfuscation/minification at all, and so you have a supplement for their API documentation (which I was unable to find, by the way -- I only found 'code wizards', which I had no interest in).
Here's an almost-working example: http://jsfiddle.net/a8q2s/1/
Here's the steps I took:
override document.write. This needs to happen before you load the initial script. Your replacement function should append their string of code into the DOM. Don't call the old document.write, that'll just get you errors and won't do what you want anyway. In this case you're lucky because all the content is in a single document.write call (check the source of the initial script). If this weren't the case, you'd have to batch everything up until the HTML they'd given you was valid and/or you were sure there was nothing else coming.
load the initial script on the button click with jQuery's $.getScript or equivalent. Pass a callback function (I used a named function reference for clarity, but you can inline it if you prefer).
Tell Skyscanner to load the module.
Edit #2: Hah, they have an API (skyscanner.loadAndWait) for getting a callback once their script has loaded. Using that works:
http://jsfiddle.net/a8q2s/3/
(note: this still seems to use a timeout loop internally)
In the skyrunner.js file they are using document.write to make the page blank on load call back... So here are some consequences in your scenario..
This is making page blank when you click on button.
So, it removes everything from page even 'jQuery.js' that is why call back is not working.. i.e main function is cannot be invoked as this is written using jQuery.
And you have missed a target 'div' tag with id = map(according to the code). Actually this is the target where map loads.
Another thing i have observed is maps is not actually a div in current context, that is maps api to load.
Here you must go with the Old school approach, That is.. You should include your skyrunner.js file at the top of the head content.
So try downloading that file and include in head tag.
Thanks

Adding a loading gif when submitting form?

While my code calculates, Id like the submit button to go from the "RUN" that it is now to the loading gif that I have. Now when I click the RUN button, I also need a certain script to run which calculates all sorts of data and returns it back to the page. I wrote a function that holds the other two function and calls them in sequence. I even added a 3rd function that would revert back the submit button but I can't seem to figure this out.
The website is www.fsaesim.com/simulation.html which would be much easier to see the code, however attached is the code.
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="framework.js"></script>
<script type="text/javascript">
function ShowCalculation() {
var results = Main($("#vehicleWeightTxt").val(), $("#tireChoiceSel").val(), $("#wheelBaseTxt").val(), $("#wheelRadiusTxt").val(), $("#trackWidthTxt").val(), $("#hcgTxt").val(), $("#weightDistributionTxt").val(), $("#shiftRpmTxt").val(), $("#ntTxt").val());
$('#outputTotalTime').empty();
$('#outputTotalPoints').empty();
$('#outputFuelUsed').empty();
$('#outputTimeOpenThrottle').empty();
$('#outputCorneringTimeTotal').empty();
$('#outputTotalStraightSectionTime').empty();
$('#outputTotalNumberOfShifts').empty();
$('#outputTractionLimitedDuration').empty();
$('#outputMeanLongAccel').empty();
$('#outputMeanHorsepower').empty();
$('#outputAccelerationTime').empty();
$('#outputMeanAccelerationLongAccel').empty();
$('#outputAccelerationTractionLimitedTime').empty();
$('#outputAccelerationTotalPoints').empty();
$('#outputAccelerationWideOpenThrottlePercentage').empty();
$('#outputAccelerationShifts').empty();
$('#outputAccelerationTrapSpeed').empty();
$('#outputTotalEnduranceTime').empty();
$('#outputTotalEndurancePoints').empty();
$('#outputTotalEnduranceFuelUsed').empty();
$('#outputTotalWOTPercentage').empty();
$('#outputTotalEnduranceShifts').empty();
$('#outputTotalEnduranceTractionLimitedTime').empty();
$('#outputTotalEnduranceAcceleration').empty();
$('#outputSkidpadTime').empty();
$('#outputSkidpadPoints').empty();
$('#outputSkidpadVelocity').empty();
$('#outputSkidpadAcceleration').empty();
$('#outputAutocrossTime').empty();
$('#outputAutocrossPoints').empty();
$('#outputAutocrossTotalShifts').empty();
$('#outputAutocrossTractionLimitedTime').empty();
$('#outputAutocrossVelocity').empty();
$('#outputAutocrossWOTPercentage').empty();
$('#outputAutocrossLongitudinalAcceleration').empty();
$('#outputMaxHorsepower').empty();
$("#outputTotalTime").append(results.output1);
$("#outputTotalPoints").append(results.output2);
$("#outputFuelUsed").append(results.output3);
$("#outputTimeOpenThrottle").append(results.output4);
$("#outputCorneringTimeTotal").append(results.output5);
$("#outputTotalStraightSectionTime").append(results.output6);
$("#outputTotalNumberOfShifts").append(results.output7);
$("#outputTractionLimitedDuration").append(results.output8);
$("#outputMeanLongAccel").append(results.output9);
$("#outputMeanHorsepower").append(results.output10);
$("#outputMaxHorsepower").append(results.output27);
$("#outputAccelerationTime").append(results.output11);
$("#outputMeanAccelerationLongAccel").append(results.output12);
$("#outputAccelerationTractionLimitedTime").append(results.output13);
$("#outputAccelerationTotalPoints").append(results.output14);
$("#outputAccelerationWideOpenThrottlePercentage").append(results.output15);
$("#outputAccelerationShifts").append(results.output16);
$("#outputAccelerationTrapSpeed").append(results.output17);
$("#outputTotalEnduranceTime").append(results.output1);
$("#outputTotalEndurancePoints").append(results.output2);
$("#outputTotalEnduranceFuelUsed").append(results.output3);
$("#outputTotalWOTPercentage").append(results.output4);
$("#outputTotalEnduranceShifts").append(results.output7);
$("#outputTotalEnduranceTractionLimitedTime").append(results.output8);
$("#outputTotalEnduranceAcceleration").append(results.output9);
$("#outputSkidpadTime").append(results.output18);
$("#outputSkidpadPoints").append(results.output19);
$("#outputSkidpadVelocity").append(results.output20);
$("#outputSkidpadAcceleration").append(results.output21);
$("#outputAutocrossTime").append(results.output22);
$("#outputAutocrossPoints").append(results.output23);
$("#outputAutocrossTotalShifts").append(results.output24);
$("#outputAutocrossTractionLimitedTime").append(results.output25);
$("#outputAutocrossVelocity").append(results.output26);
$("#outputAutocrossWOTPercentage").append(results.output4);
$("#outputAutocrossLongitudinalAcceleration").append(results.output9);
}
function mouseClick() {
document.getElementById("submitButton").src = "images/loading.gif";
}
function revertBack() {
document.getElementById("submitButton").src = "images/simulationSubmit.png";
}
function simulationEvents() {
mouseClick();
ShowCalculation();
revertBack();
}
</script>
<center><img src="images/simulationSubmit.png" alt="" id="submitButton" onmouseover="mouseOver()" onmouseout="mouseOut()" onclick="simulationEvents(); return false;" /></center>
Since all your processing is being done in javascript, that will tie up your script until it finishes.
Javascript isn't multithreaded, it does one task at a time until that task is done.
Generally, when you see that animated gif while a form is being processed the page is using AJAX or something similar. The number crunching is happening server-side using PHP or Python or something like that.
The animation just runs while the javascript waits to hear back from the server-side script.
You might be able to work around it somewhat with this tutorial but that seems like overkill for this situation. The easiest thing would probably be to send the form data to a server-side script or just deal with not having an animation during processing.
Edit: If you're wanting to learn how to do AJAX, here's a tutorial that uses jQuery, which your site is already loading.

Categories