getElementById works only after refreshing the page - javascript

I'm Trying to access results div in the results page of google.co.uk.
Using firebug one can see that the id of the div is "res" but for some reason getElementById('res') fails. to make things even weirder - if i refresh the page (F5 or ctrl+F5), the function succeeds.
Also, if i look in the source code of the results page i dont see anything that looks like the DOM described in firebug.
Why is this happening and how can i ensure getElementById('res') will succeed with any refresh by the user.
Thanks.
EDIT: im adding a a short code to simplify the problem. after placing a query in google.co.uk the page redirects and the alert 'working' pops but the second alert doesnt.
after refreshing, both alerts pop although the second one says 0 which is not right
because the div has children according to the firebug DOM.
p.s: i also failed to mention that im using greasmonkey
(function() {
alert('working');
var results = document.getElementById('res');
alert(results.childNodes.length);
})();

window.addEventListener("DOMContentLoaded", function () {
var results = document.getElementById('res');
alert(results.childNodes.length);
}, false);

Related

Chrome console: snippet command can't open dialog

I have a simple oneline snippet to "click" on a «load file» button on a visible page to call a dialog-popup (to load an image, for example).
this.document.getElementsByName("image")[0].click() // snippet code
While manual paste and run this line in console is successful (it opens the dialog), the above snippet can't do that. Seems like Chrome doesn't allow to open dialog not by user call. So, I set browser to allow all popups but there is no result.
Tested on different pages where file load button presents.
Thanks for any ideas.
A similar but different issue, solved
Seems like Chrome doesn't allow to open dialog not by user call.
I created a snippet to test if this statement is true. It seems like it is incorrect.
Click the Run Snippet button in this answer.
Open DevTools.
Click Inspect and click the image that says 350x150.
Evaluate document.querySelector('img').click() in the Console. The text below the image increments.
Run the same statement from a Snippet. The text still increments.
document.querySelector('img').addEventListener('click', () => {
let p = document.querySelector('p');
p.textContent = parseInt(p.textContent) + 1;
});
<img src="https://via.placeholder.com/350x150"/>
<p>0</p>
Possible solutions:
Make sure that you are in the correct Console context when you run the snippet. See Selecting Execution Context.
The use of this in your statement might be causing problems. Try removing it.
Try adding an ID to your element and then referencing it by its ID, rather than the getElementsByName array. So, use document.getElementById('myCustomId').click() instead. Make sure to add the ID to the HTML element, e.g. <img id="myCustomId" .../>. It's possible that you're referencing the wrong element, so that's why you're seeing the wrong result when you execute click().
Add comments to this answer and we'll eventually figure out what's going wrong.

Loading a page from hash on refresh

So I wrote this piece of JavaScript using the JQuery library. Its functionality is to have the pages load inside of a div instead of an entire page (to make modifying the layout way easier).
I've made it so it successfully saves the 'file URL' in the hash and I've made it so it loads correctly, but I can't for the life of me figure out how to go to that page.
When I try to go to a page with the hash in the name (so for example refreshing a page, or going through a link/URL) it replicates itself (I think) two times inside each other. You can see it happening live at overeten.be and then try to refresh a random page except the main one.
Could someone help me with this problem? Thanks in advance!
$("document").ready(function(){
$('._body').load("pages/default.html");
var locationhash = window.location.hash.replace('#','');
if ((locationhash=='pages/default.html')||(locationhash=='')){
console.log("no page, "+locationhash);
} else{
$('._body').load(window.location.hash);
console.log(locationhash);
}
$('.menubundle a, footer a').on('click', function (e) {
e.preventDefault();
var page = $(this).attr('href');
$('._body').fadeOut(1000,function(){
document.location.hash = page;
$('._body').load(page).fadeIn(1000);
});
});
});
The problem is on this line:
$('._body').load(window.location.hash);
If you inspect window.location.hash, you get this:
window.location.hash
"#pages/over_eten/feit.html"
That URL points to the current page. What you really want is this:
window.location.hash.slice(1) // Skip the first character
"pages/over_eten/feit.html"
On a side note, it seems weird to me that you have two calls to $('._body').load(). The first one seems like it belongs right above console.log('No page...') instead.

How to call a Greasemonkey function when a JavaScript link is clicked

So I recently started working on Greasemonkey scripts without much prior experience in JavaScript. It was going fine until I hit this roadbloack.
I'm writing a script for a page that has a small table of information. If a link at the bottom is clicked, the table expands fully in the page to display all information. I need to call a function in Greasemonkey when this happens, however, the link doesn't appear to have an ID or anything I can actually reference to watch it. It's simply this:
When it's clicked, the table expands and it then shows as true. I initially used the following to expand the table upon loading the page, but that broke several things:
window.location.href = ('javascript: expandFullTable(false)');
I've attempted using "click", "onclick", and even "mouseover" to have Greasemonkey detect when it's pressed but nothing seems to work. From what I can tell it's simply a link that calls a function, but after some significant searching I wasn't able to find out anything about how to reference it in my script. I'm sure it's incredibly simple, but it's frustrated me to no end.
You can hijack the function like this:
var oldExpandFullTable = unsafeWindow.expandFullTable;
unsafeWindow.expandFullTable = function() {
// Do something
alert("You clicked on that thing!");
// Call the original function
oldExpandFullTable.apply(this, arguments);
};
But since you tagged this jquery this should let you retrieve the link:
var link = $("a[href^=\"javascript: expandFullTable\"]);
It should work if jQuery is injected into your script with #require. If it's already in the page, you can add this before to access it: var $ = unsafeWindow.jQuery;.
And by the way, perhaps you should learn more about unsafeWindow to avoid security holes.

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

Element is not displaying on FireFox & Opera, but on Chrome & Safari is working

I have a problem where an element is not showing on Opera nor Firefox. Using firebug on Firefox I could see that an error saying that a function I use to initialize the code 'is not defined'
Now here's the thing, when I empty the cache on the Firefox browser, I can see my element which contains a "facebook button" and the error is gone, but once I refresh the browser I can't see my element and returns the error again. I would have to empty out the cache in order to see the button once again.
The element is supposed to be triggered with jQuery to show if a facebook user is online, and if not it will show that button. But this is only working on Chrome & Safari, and I believe on IE8 (which i don't have) but someone told me it worked.
This is the code to show the element on my Javascript file:
jQuery('#fbLogin').show();
Now, if i was to change this on my .css file:
#fbLogin {
display:none;
}
to this:
#fbLogin {
display:block;
}
it will display, but the problem i saw was that it showed all the time, and this needs to be hidden if the user is logged in. I basically have a code that says .show the button and .hide if logged in...
here's a link to a page if you want to take a look further:
http://gullypost.com/entertainment/tim-westwood-kendrick-lamar-interview/
On Safari & Chrome you will notice that the facebook button shows up on the right sidebar, but not visible on the other browsers.
Can someone help me solve the problem to this? Thanks.
There's a weird problem when using jQuery when trying to use .show() on an element that doesn't have a defined height. The fix is to set the height either explicitly or dynamically.
​$(selector).height(function() { return $(this).height() });​​
It looks like the second time the page loads, you're getting the following JavaScript error:
fb_og_actions_init_vid is not defined
The file that contains the function is being added to the page correctly. My only guess would be to try and move the reference to the function:
fb_og_actions_init_vid("Connected to Facebook", "108821");
To within a document.ready function:
$(document).ready(function(){
fb_og_actions_init_vid("Connected to Facebook", "108821");
});
I believe this will work:
document.getElementById('fbLogin').style.display = 'block';

Categories