How can I regain program control after <cfheader> opens a PDF file? - javascript

This is a ColdFusion 8 question.
I have a cfm page that has a button that onClick calls the following Javascript function located in the page header:
function confirm_expiration_letters() {
var resultOfConfirm = confirm("Would you like to send expiration and reminder letters?");
if (resultOfConfirm == true) {
document.body.style.cursor = "wait";
window.location="_expiration_letters.cfm";
}
}
On the page that is called, a series of emails are generated, then a PDF report file is generated and displayed using these two lines:
<cfheader name="Content-disposition" value="attachment;filename=#fileName#">
<cfcontent type="application/pdf" file="#docPath#/#fileName#" deletefile="true">
Notice in the JS function that the cursor is changed to "wait". But the program control appears to get lost after the above cfheader call and so I can't find anywhere that I can reset the cursor back to:
document.body.style.cursor = "default";
Do you have ideas on where I can place this to turn off the cursor animation? I tried multiple places and it doesn't work. Once the cfheader and cfcontent calls happen, control of previous window and cursor are lost it appears.

You might try something like this above the cfheader.
<script>
document.body.style.cursor = "default";
</script>
<cfflush/>
The problem is that doing so might (probably will) screw up the cfheaders since cfflush is designed to flush partial results and will include the headers. But it's the only thing I can think of.

If I understand you correctly, you want to have a "wait" cursor whilst the PDF is prepped, and then return to a standard cursor after that.
Don't web browsers do this automatically when you're waiting for a requested document? IE: as soon as you do your window.location, whilst the document is loading, the cursors automatically changes to a "wait", and then once the doc is served, returns to an "auto".
This is what I see (when running code similar to yours). Is this not what you see?

Instead of changing the cursor, display a loading message using HTML/animated gif. When the PDF loads, it will replace the loading screen.
I would suggest having a hidden div containing your loading message, then use JavaScript to make it appear when needed.
Here's some JavaScript. This is how it would be done with jQuery.
function confirm_expiration_letters() {
var resultOfConfirm = confirm("Would you like to send expiration and reminder letters?");
if (resultOfConfirm == true) {
$('#Loading').fadeIn(); //SHOW THE LOADING INDICATOR
$.post('PDFGenerator.cfm', function(returnData){ // AJAX POST, CALLBACK
//RETURN THE FILENAME OR LOCATION OF THE PDF
var FileName = $.trim(returnData); // TRIM THE RETURNED DATA
window.open("path_to_file/" + FileName,"_blank"); // NEW WINDOW
$('#Loading').fadeOut(); // HIDE THE LOADING INDICATOR
});
}
}

Related

How to get the contents of a Third Party lazy loading page?

Via a Chrome extension, I'm trying to get and modify the contents of a third-party page. Everything works for the part of the content that's immediately visible on initial page load.
The problem is that this page has a lazy-load/ajax pagination. To get all of the content I have to click "view all" (ajax link) (and I believe this works essentially the same way as lazy-loading that's why I put that keyword in the title).
Upon clicking that link (on that third-party website) all content gets loaded and becomes visible to the user but when I view source there's still only the originally loaded content present in the source code. i.e. none of the freshly loaded content can be found anywhere when I view page source after the new content has been loaded. The content is visible to the end user but not visible to me when I check the source code.
Initially, I tried to overcome the problem by using setInteval and checking the page content every second but as that wasn't working I checked the source code and sure enough, none of the newly loaded content is visible in the source code. No wonder my Chrome extension can't get that content.
Another confusing thing I just realized when typing here:
When I view source code, even the initial HTML content that my Chrome extension is detecting/loading is NOT actually present in the source code! It actually sits in a JavaScript array. So, somehow, my Chrome extension is correctly getting the initial HTML content that's constructed from that JS array. But it's NOT getting the content that gets loaded after clicking the "view all" ajax link on that page (even though I'm using setInteval and checking for new content every second).
What are possible solutions for this?
I can't post the link to the page because it's the "my certificates" page on Lynda.com and I don't know of a publicly accessible website/page with the same behavior.
you should find the actual service running in network-panel, when lazy loading happens, and then follow following code
//recursively make calls and gatther responses. cb is callback to run on response, end is end page-no (end of recursion condition) , pageId is the attribute changing in every subsequent lazy-loading call.
var callIfRequiredConfigured = ({cb,end,step=1,pageURL,pageId})=>callIfRequired = ()=>{
currentCounter = currentCounter + step;
if (currentCounter > end) {
return;
}
(async(currentCounter)=>{
queueCounter++;
//modify this as needed
const r = await fetch(pageURL+currentCounter,{credentials:"same-origin"});
//queueCounter to not make more than 6 calls at once
if (queueCounter > 6) {
return;
}
var response = await r.text();
cb(response);
queueCounter--;
callIfRequired();
}
)(currentCounter);
};
var call = (config)=>{
const callIfRequired = callIfRequiredConfigured(config);
callIfRequired();
}
call({
cb: (response)=>{
//do somrthing with response
}
,
end: 50,
step: 1,
pageId: 'PageNumber=',
pageURL: `https://www.lynda.com/home/CertificateOfCompletion/GetCertificatesByFilter?Start=0&Limit=99999&SortBy=CompletionDate&SortByOrder=1&_=[my_personal_id]&PageNumber=`
});
So main effort will be to deduce the service endpoint here and how it changes in subsequest requests. I have updated the url given in comments, but see if the fetch call is successful. Also this url should also have [my_personal_id] as given in url.

javascript function reloads page upon completion

I have a simple javascript program that runs onclick of an image.
However, whenever I clicked the image, the page reloaded.
After a lot of debugging I found that the page doesn't reload until right as the script completes.
There are several setTimeouts in the code, but I noticed the page was reloading instantly. I even changed these timeouts to 15000 milliseconds, but it still reloads immediately.
I am using jquery, if it makes any difference.
I also want a different result from the program every time you click it, so that each time you click it a different script runs and a some text changes in a specific order. I did this by changing the onclick attribute of the images in each script to the name of the next script, so that script one would switch onclick to script two, and so on. I set a timeout on these switches so that one click doesn't race through every single script. script two isn't running, so that much works.
my code:
function getSounds() {
console.log("script. initiated");
$("#soundwebGetSoundDirections").html("Now, Wait until the file is done downloading and click below again.");
console.log("new message");
$("#soundwebGetSoundA").attr('href',"");
console.log("href eliminated");
setTimeout($("#soundwebGetSoundImg").attr('onclick','findFile()'),2000);
console.log("onclick to findFile()");
}
function findFile(){
console.log("FINDFILE")
$("#soundwebGetSoundDirections").html("Find the file(it's probably in your downloads), copy the path of the file (usually at the top of the file explorer) and paste in it the box below. Then, make sure there is a '/' at the end of the path and type 'Linkiness.txt' (case sensitive, without quotes) at the end. Once you have all that stuff typed, click the icon again.");
console.log("FIND IT, DARN IT!!");
$("#soundwebGetSoundPathInput").css("opacity",1);
console.log("diving into reader");
setTimeout($("#soundwebGetSoundImg").attr('onclick','readFile()'),1000);
}
function readFile(){
console.log("loading...");
$("#soundwebGetSoundDirections").html("loading...");
if(document.getElementById("soundwebGetSoundPathInput").value.length == 0){
setTimeout($("#soundwebGetSoundDirections").html("Please fill in Path!"),1000);
setTimeout(findFile(),2000);
}
}
and the HTML that's linked to,
<a id = "soundwebGetSoundA" href = "https://docs.google.com/feeds/download/documents/export/Export?id=1ynhHZihlL241FNZEar6ibzEdhHcWJ1qXKaxMUKM-DpE&exportFormat=txt">
<img onclick = "getSounds();" class = "soundwebImgResize" src = "https://cdn3.iconfinder.com/data/icons/glypho-music-and-sound/64/music-note-sound-circle-512.png" id = "soundwebGetSoundImg"/>
</a>
Thanks for any help,
Lucas N.
If you don't want clicking the image to cause the anchor tag to load the href, then move the image tag outside of the anchor tag.
You aren't using setTimeout correctly. You should be passing in a function not a statement. So, for example, instead of
setTimeout($("#soundwebGetSoundDirections").html("Please fill in Path!"),1000);
setTimeout(findFile(),2000);
you should use
setTimeout(function () { $("#soundwebGetSoundDirections").html("Please fill in Path!") },1000);
setTimeout(findFile,2000);
I think the same goes for setting the onclick attribute but I've never tried dynamically changing an onclick attribute like that.
Since you're already using jQuery you could try using .on('click'... and .off('click'... if your current setup isn't working.

Clicking a link does not refresh the content

I've been looking at how to automate actions on a webpage with PhantomJS, however I'm having issues manipulating the page to do what I want it to.
I'm using this as test site. I've managed to get Phantom to open the webpage and scrape the random sentence from the #result span. But now what I want to do is get another sentence without re-launching the script. I don't want to close and re-open the page as Phantom takes ages to launch the webkit and load the page. So I thought I could get another sentence by getting Phantom to click on the 'Refresh' button below the sentence box. Here's what I have at the moment:
var page = require('webpage').create();
console.log("connecting...");
page.open("http://watchout4snakes.com/wo4snakes/Random/RandomSentence", function(){
console.log('connected');
var content = page.content;
var phrase = page.evaluate(function() {
return document.getElementById("result").innerHTML;
});
console.log(phrase);
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
page.evaluate(function() {
$("frmSentence").click();
});
});
var content = page.content;
var phrase = page.evaluate(function() {
return document.getElementById("result").innerHTML;
});
console.log(phrase);
phantom.exit();
});
As you can see I'm trying to click the refresh button by using a .click() function, but this isn't working for me as I still get the same sentence as beforehand. Given the HTML for the button:
<form action="/wo4snakes/Random/NewRandomSentence" id="frmSentence" method="post" novalidate="novalidate">
<p><input type="submit" value="Refresh"></p>
</form>
I'm not sure what I should be referencing in the script to be clicked on? I'm trying the form ID 'frmSentence' but that isn't working. I'm wondering if .click() is the right way to go about this, is there some way for Phantom to submit the form that the button is linked to? Or maybe I can run the associated script on the page that gets the sentence? I'm a bit lost on this one so I don't really know which method I should go with?
You have a problem with your control flow. page.includeJs is an asynchronous function. If you have some other statements page.includeJs, they are likely executed before the script is loaded and the callback is executed. It means in your case that you've read the sentence 2 times before you even trigger a click.
If you want to do this multiple times, I suggest to use recursion since you cannot write this synchronously. Also, since you want this to be fast, you cannot use a static setTimeout with a timeout of 1 second, because sometimes the request may be faster (you lose time) and sometimes slower (your script breaks). You should use waitFor from the examples.
Instead of loading jQuery every time, you can move page.includeJs up and include everything else in its callback. If you only need to click an element or if jQuery click doesn't work (yes, that happens from time to time), you should use PhantomJS; click an element.
web scraping is about sending require information to a web server and get the result. It is not about behaving like a user clicking button or entering search criteria.
All you need to do in this example is send a POST request to http://watchout4snakes.com/wo4snakes/Random/NewRandomSentence. The result is just text in page.content, it does not even need to evaluate. So to get more than one sentence you just need to do a loop of page.open

remember most recent click

So I want to be able to have a different styling for a link after you go to the page it's clicked on. I have been using the following code:
$(document).ready(function(){
var url = document.URL;
function contains(search, find) {
return search.indexOf(find) !== -1;
};
$('#topbar a').each(function(){
var link = $(this).attr('href');
var answer = contains(link,url);
if(answer === true){
$(this).addClass('check');
}
else{
$(this).addClass('nocheck');
};
});
});
This goes through the links in my navigation bar and checks if it's on the same page as the link, and it works, but I can't use it in one specific case: Random.
I have a link that generates a random page from the pages I have, so it does not have a specified link as it links to a function to randomly generate the page (note: I cannot change the function or access information from it).
So how can I detect that the random link was clicked previously so i can give it the .check class
If i understand your question correctly, your function does not work for the randomlink because this has a href like http://mysite.com/random, but the server will actualy redirect you to a different page, like http://mysite.com/about-me, and therefore the url of the active page does not match the href of the random button, and it will not get the active state.
One could argue if you would want it to get the active state, cause clicking it again would not (likely) bring you to the same page, but that is besides the question.
I can see to ways to solve this.
server side:
In stead of redirecting to ie. http://mysite.com/about-me in the random function, you could also redirect to http://mysite.com/about-me?random. By adding this get variable, you should not change the behaviour of the link (unless you have some very strict controller, or that variable is actually used, but that is unlikely). You could then detect with javascript if that variable is present in the url, and then activate the random button.
Something like this:
$(document).ready(function(){
var url = document.URL;
// check for random
if (url.indexOf('?random') >= 0) {
$('#topbar a.random').addClass('check');
}
// check all other
$('#topbar a:not(.random)').each(function(){
if($(this).attr('href').indexOf(url) >= 0){
$(this).addClass('check');
}
else{
$(this).addClass('nocheck');
};
});
});
cookie:
If you do not have acces to the server side random controller, you could do it entirely with javascript, by the use of a cookie (the only way I know to make a variable persist trough page requests).
On click of the random button, you would first set a random cookie to true with javascript, before letting the actual link do it's thing. On entering the page, you could then do a similar check as in my previous option, but in stead of the url you check if the cookie is tre. If so, you change it to false (so on the next page request the random button will not be active again) and set the randombutton to active.
As I believe the first solution is to be preferred (cookies should only be used as a last resort, they are sent on every page request, which means extra data, and your user might have cookies disabled, or there might be laws against using cookies, so the function could not always work), I will not write the javascript yet. Feel free to ask if you prefer this solution and need further help however.

Lightbox that can open automatically depending on url path

There are a million lightbox type modal overlay scripts out there.. but I am looking for one that has the ability to be automatically triggered, depending on the path that leads there. So a property would have to live in the url string that triggered it. Has anyone seen or implemented any such thing? I know colorbox has the ability to automatically open the modal when you land on the page, but I do not know how I could make that functionality dependant on the path that one arrives there. Any ideas?
You could implement some JavaScript that looks at the referring page and opens the light box accordingly, therefore you shouldn't be limited to a particular implementation. You can tie in to the document ready event to open it.
There is an example of how to access the referrer on the W3Schools website linked below.
http://www.w3schools.com/jsref/prop_doc_referrer.asp
You can do this with Colorbox by varying the settings in your initialisation.
Assuming that you do this to start Colorbox:
$('div.gallery a').colorbox({
onClosed: function() { alert('Colorbox closed');},
current: 'Image {current} of {total}'
});
You could do something like this instead:
var colorBoxSettings = {
onClosed: function() { alert('Colorbox closed');},
current: 'Image {current} of {total}',
open: false
};
if (your_logic) {
colorBoxSettings.open = true;
}
$('div.gallery a').colorbox(colorBoxSettings);
I suggest that there is no need for auto triggering. You can do it this way -
First check the whether the url consists of the appropriate value you want or not.
It can be done by server side language (like PHP ) or through javascript.
If done server side pass say a hidden field as below -
<input type="hidden" name="exists" value="true" />
If done using jquery save value as -
var value = "value from javascript if proper url exists";
If done through server side then -
var value = $('input[name="exists"]').val();
Then you can trigger manual cilck (if url value is as per your expectation) to anchor which consists of overlay link -
$('#id of anchor').trigger('click');
If you want auto triggering overlay though then you can try this -
http://flowplayer.org/tools/demos/overlay/trigger.html

Categories