I'm trying to load some scripts into my pages being visited by phantomjs. I'm using 2.1.1 btw.
I'm kind of banging my head here because I've tried a variety of things and they all seem to fail in the same way which kind of makes me think maybe I'm missing a configuration setting or something.
Any who what I'm trying :
//I dont actually care about using jquery, just trying loading from different servers
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js');
and
page.includeJs('https://aSiteIControl.com/jquery.min.js');
and then I have a onResourceError handler like this:
page.onResourceError = function(resourceError) {
console.error(resourceError.url + ': ' + resourceError.errorString);
console.error(JSON.stringify(resourceError))
};
that outputs this no matter what I've tried:
https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js: Operation canceled
{"errorCode":5,"errorString":"Operation canceled","id":1,"status":null,"statusText":null,"url":"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"}
This seems to happen no matter what protocol I use or what server the script lives on. Also, both of those examples are visitable in a browser. Any body have any idea what I might be doing wrong?
TO BE CLEAR on the accepted answer since there is no code:
just go look at this question :
PhantomJS: injecting a script before any other scripts run
I bet you can include directly only local scripts. Please try:
(page.evaluate(function() {
var script = document.createElement('script');
script.src = 'http://urlToScript.com';
}))
This can be caused by a timeout or the call to the exit() function of the phantom object while the js is being loaded, or if you try to open another page. Can you add all your code?
Based on the documentation you can include external JS:
Includes external script from the specified url (usually a remote location)
Related
Heyo,
I'm trying to create a script that opens a URL and sign in using the given credentials.
Therefore I created this:
window.open("https://stackoverflow.com/users/login");
document.getElementById('email').value = "ThisIsMy#Email.com";
document.getElementById('password').value = "ThisIsMyPassword";
document.getElementById('submit-button').click();
But then I changed the code to wait for the page to load using window.onload:
window.open("https://stackoverflow.com/users/login");
window.onload = function() {
document.getElementById('email').value = "ThisIsMy#Email.com";
document.getElementById('password').value = "ThisIsMyPassword";
document.getElementById('submit-button').click();
}
However, this does not seem to work.
Therefore I added some console.log into my code to debug, like this:
console.log("starting")
window.open("https://stackoverflow.com/users/login");
console.log("page open")
window.onload = function() {
console.log("page loaded")
document.getElementById('email').value = "ThisIsMy#Email.com";
document.getElementById('password').value = "ThisIsMyPassword";
document.getElementById('submit-button').click();
console.log("signed in")
}
When I run the code in the console (Chrome/Firefox), I get back started and page open, but nothing else.
When I test the function isolated (i.e. the 3 different document.getElementById) it works just fine. Something must be wrong with the window.onload call?
From other sources here on StackOverflow I tried to use document.onload instead, and I also tried to use document.addEventListener('DOMContentLoaded', function() {...}, but none of these seems to be working either.
Does anyone have any suggestions?
#newbie
You simply can't access a cross origin page. What you are trying is only available to browser addons. And addons also require a specific permission granted by the user. For example the chrome permission to modify a webRequest: https://developer.chrome.com/docs/extensions/reference/webRequest/
window.open() returns the child window and this can be accessed IF it is about:blank or if the same-origin-rule applies (protocol, hostname and port - see pic below). Take a look at this fiddle it shows something similar to what you are trying. (CORS 1)
Here you can see which child windows you may have access to. This means modify it on the fly or override it's content/location completly.
The only method to communicate between two pages is: window.postMessage() and the window: Message-Event which provides an easy to use API for communication.
in your html page, in the script tag, where you call to your js page, add defer. like this:
<script src="your_script.js" defer></script>
I would like to remind you it is not a very good idea to use password credentials inside javascript since it is hard to protect from public appearance.
I believe you can solve this kind of problem with programs such as Python, C++ , maybe Java , but Javascript is a Client-Side program which has some limitations but if you ask me these limitations actually makes it quite fun to use most of the time.
My addon uses a content script to interact with the page. But it also needs access to the page's javascript so it can run one of the page's routines. So my content script needs access to the page's script context.
Here's what I mean.
Addon uses main.js which access content.js and uses messaging to communicate.
But the web-page (into which content.js is being injected) has it's own javascript. My content.js needs access to that context so it can fetch the values from variables there.
How can one get that?
I have been reading these mdn docs, but it seems like they are talking about an html page that you code yourself, like you would for a preferences page. But in my case I am working with an external website, not something coded just for the addon.
The approach listed on the MDN page also works for external pages, not just your own.
I.e. unsafeWindow.myPageVar will work.
This works:
var script = document.createElement("script");
script.innerHTML = "alert( myPageVar );";
document.body.appendChild( script );
Credit goes to this fellow.
I don't know whether this is the best way to do this, however. I hope that someone else more knowledgeable than me will answer.
Here's how to return a value:
var retval = unsafeWindow.SomePageFunction();
alert(retval);
It's called "unsafe" because you never know what about the page might be changed or might change. That's how it when the addon interacts with page scripts.
I have a Google +1 button on my site that requires the following script:
<script src="https://apis.google.com/js/platform.js" async defer></script>
The problem is as of today, apis.google.com can't be pinged from everywhere (servers are down) and some of my users don't see a button. I don't always want to use my own copy of the script because I can see that breaking the +1 functionality at some point. I'd like to use something like the solution from this question: my server's fallback copy should be fetched only when the CDN fails.
What's a good way to do that for this script? Is there a generic way to do this for any remote script using jQuery or plain js? Thanks in advance.
EDIT:
I tried jQuery getScript() and wrapped it in a function like this:
function fetch_script(script,fallback) {
$.getScript( script )
.fail(function() {
$.getScript( fallback );
});
};
This does not always work and is not reliable. Two problems I found:
500 errors trigger the fail method, but 404 errors do not and the fallback script is not loaded in these cases. Not sure what happens if the server is just down.
Some scripts are fetched (I see this in the console) but are somehow not executed (or they fail silently). Here's a script that doesn't work.
I have multiple <head> references to external js and css resources. Mostly, these are for things like third party analytics, etc. From time to time (anecdotally), these resources fail to load, often resulting in browser timeouts. Is it possible to detect and log on the server when external JavaScript or CSS resources fail to load?
I was considering some type of lazy loading mechanism that when, upon failure, a special URL would be called to log this failure. Any suggestions out there?
What I think happens:
The user hits our page and the server side processes successfully and serves the page
On the client side, the HTML header tries to connect to our 3rd party integration partners, usually by a javascript include that starts with "http://www.someothercompany.com...".
The other company cannot handle our load or has shitty up-time, and so the connection fails.
The user sees a generic IE Page Not Found, not one from our server.
So even though my site was up and everything else is running fine, just because this one call out to the third party servers failed, one in the HTML page header, we get a whole failure to launch.
If your app/page is dependent on JS, you can load the content with JS, I know it's confusing. When loading these with JS, you can have callbacks that allow you to only have the functionality of the loaded content and not have to worry about what you didn't load.
var script = document.createElement("script");
script.type = "text/javascript";
script.src = 'http://domain.com/somefile.js';
script.onload = CallBackForAfterFileLoaded;
document.body.appendChild(script);
function CallBackForAfterFileLoaded (e) {
//Do your magic here...
}
I usually have this be a bit more complex by having arrays of JS and files that are dependent on each other, and if they don't load then I have an error state.
I forgot to mention, obviously I am just showing how to create a JS tag, you would have to create your own method for the other types of files you want to load.
Hope maybe that helps, cheers
You can look for the presence of an object in JavaScript, e.g. to see if jQuery is loaded or not...
if (typeof jQuery !== 'function') {
// Was not loaded.
}
jsFiddle.
You could also check for CSS styles missing, for example, if you know a certain CSS file sets the background colour to #000.
if ($('body').css('backgroundColor') !== 'rgb(0, 0, 0)') {
// Was not loaded.
}
jsFiddle.
When these fail, you can make an XHR to the server to log these failings.
What about ServiceWorker? We can use it to intercept all http requests and get response code to log whether the external resource fails to load.
Make a hash of the js name and session cookie and send both js name in plain and the hash. Server side, make the same hash, if both are same log, if not, assume it's abuse.
We want to serve ads on our site but the adserver we are in talks with has issues with delivering their advertising fast enough for us.
The issue as I see it is that we are supposed to include a <script src="http://advertiserurl/myadvertkey"></script> where we want to display the ad and it will then download a script and use document.write to insert some html.
Problem is that the call to the advertiser website is slowish and the code returned then downloads another file (the ad) which means the speed of rendering our pages slows while we wait for the request to be filled.
Is there a way to take the output from the document.write call and write this in after the page has loaded?
Basically I want to do this:
<html>
<body>
<script>
function onLoad() {
var urlToGetContentFrom = 'http://advertiserurl/myadvertkey';
// download js from above url somehow
var advertHtml = // do something awesome to interprete document.write output
$('someElement').innerHTML = advertHtml;
}
</script>
</body>
</html>
Or anything similar that will let me get the output of that file and display it.
If I understand correctly, you want to capture document.write to a variable instead of writing it to the document. You can actually do this:
var advertHtml = '';
var oldWrite = document.write;
document.write = function(str)
{
advertHtml += str;
}
// Ad code here
// Put back the old function
document.write = oldWrite;
// Later...
...innerHTML = advertHtml;
You still have the hit of loading the script file though.
To decouple the main page loading from the ad loading, you can put the ad in its own page in an iframe or, similarly, download the script file with AJAX and execute it whenever it comes down. If the former is not adequate, because of referring URI or whatever, the latter gives you some flexibility: you could use string replacement to rewrite "document.write" to something else, or perhaps temporarily replace it like "document.write = custom_function;".
You may be interesed in the Javascript library I developed which allows to load 3rd party scripts using document.write after window.onload. Internally, the library overrides document.write, appending DOM elements dynamically, running any included scripts which may use document.write as well.
I have set up a demo, in which I load 3 Google Ads, an Amazon widget as well as Google Analytics dynamically.
You'd run into some security issues going cross domain due to the Same Origin Policy. I would look into JSONP if you have access to change the advertising content/service
http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback