javascript function reloads page upon completion - javascript

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.

Related

How do I make a JS function triggered in one HTML page edit elements defined in a second HTML page?

Basically I have two HTML pages, and both are connected to the same JS file. I want a function triggered by an event handler element in the first HTML to edit an element in the second HTML page, and then open it.
Here's a very basic example:
$("#p1").click(function() {
$("#p2el").text("TEST");
})
<button id="p1">CLICK</button>
In this example, the button p1 is defined in the first HTML, and the p2el element is defined in a second HTML page, both linked to the same JS file.
In the above example, I also used location.href inside the function. The idea being that, the element is edited, and automatically the second HTML page is loaded.
It's not working, and I don't know why. The second HTML page loads, but the element p2el is not edited.
I suspect this is has to do with data not transferring to the second HTML, but I am not sure why and what is happening exactly. I tried using localStorage inside the function, and then use the stored data as a condition that edits the element in the second HTML page...
function second() {
if(localStorage["key"] == "on") {
$("#p2el").text("TEST");
location.href = "secondpage.html"
}
}
$("#p1").click(function() {
localStorage["key"] = "on";
second()
})
... but It didn't work.
I hope somebody can help me out.
Navigating to a new page completely resets the "JavaScript envirionment".
Your JS files are reloaded, everything starts anew. Some things persist through page loads, such as local storage and cookies, but function calls certainly don't.
To do what you want to do, you'll need to:
Listen to the click event, and save the fact it was clicked somewhere.
(You're already doing this)
On page load, check the storage to determine whether or not the button was clicked at some time. If it was, do whatever you want. You will probably want to reset the stored value so this happens only once.
This will probably do the trick for you:
if(localStorage["key"] === true) {
localStorage["key"] = false; // reset the key.
$("#p2el").text("TEST");
}
$("#p1").click(function() {
localStorage["key"] = true;
location.href = "secondpage.html"
});

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

How can I get an element's innerHTML to update immediately?

I have a web page with a text box. When entering in a .js file name into the box and clicking the Execute button, the file given will be loading via AJAX and eval()'d.
Also on this page is an empty <div> for used as output. If the file that is loaded needs to print something to the screen, it adds it to the div's innerHTML.
When adding text to the innerHTML, it usually doesn't render on the screen until the Javascript is completed, which is fine, except for the fact that, sometimes, the Javascript file performs heavy calculations which can take upwards to a minute to complete, and it would be useful to be able to see the output as it was executing.
Is there any way to "refresh" the document?
I would try solving this using setTimeout.
function performInitialHtmlRender() {
/// This sets the innerHtml that you want the user to see
/// While you are performing the calculations
}
function performExpensiveCalculationsAndRender() {
// This is the really expensive function that
// you want to run once the browser has rendered
// the initial HTML
}
performInitialHtmlRender();
setTimeout(performExpensiveCalculationsAndRender(), 0);
You can use setTimeout:
div.innerHTML = html;
setTimeout( function(){
doHeavyCalculations();
}, 35);
http://jsfiddle.net/YKEKK/

Change href with JavaScript

I am trying to add a click event to a link in SharePoint.
The current href set by SharePoint is href="javascript:ClickOnce()".
If I add the following code:
var saveNclose = document.getElementById("diidIOSaveItem");
saveNclose.href = "javascript:JSEPreSaveAction()";
alert(saveNclose.href);
The alert outputs the href I am trying to get, which is javascript:PreSaveAction() but when I look at it in the page it is still ClickOnce().
Why is the alert telling me the href is one thing and the source code and behavior says is another? Is there something causing SharePoints script to take priority over mine?
document.getElementById("diidIOSaveItem").setAttribute("href", "javascript:JSEPreSaveAction()");
alert( document.getElementById("diidIOSaveItem").getAttribute("href") );
I was able to do this by adding a timer to add PreSaveAction() to the button 10 seconds after the page had finished loading.

Global Javascript link handler

Here's what I have:
A web application that runs in a single HTML page (call it myapp.req), with content coming and going via AJAX
The application can be entered externally with a link such as myapp.req?id=123, and the application opens a tab with the item at id 123
The content on the page is mostly user's content, and many times has inner-application links to myapp.req?id=123
The problem is that clicking a link to myapp.req?id=123 reloads the browser, and removes any content or state that the user had loaded
What I want is to be able to catch link clicks whose destination is myapp.req?id=123, and instead of reloading the page, just open the tab for item 123, leaving anything else currently loaded alone. If the link is for an external website, though, obviously just let the browser leave.
So my question really: Can I have a global link handler that checks if I want to handle the link click, and if so, run some Javascript and don't leave?
I understand I could find all <a>s and add listeners, but my hope is that the solution would only require setting up the listener once, and not adding link handlers every time new content is loaded on the page. Since content can be loaded many different ways, it would be cumbersome to add code to all those places.
Does that make sense?
jQuery's live is what you need:
$('a').live("click", function () {
var myID = $(this).attr('href').match(/id=([a-zA-Z0-9_-]*)\&?/)[1];
if (myID) {
//run code here
alert(myID);
return false;
}
});
Any link will now have this click handler whether it's been added after this is called or not.
Sure you can. Add a clickhandler on the body. So you catch all clicks. Then you have to check if the target of the event or one of its parent is a link with your specific href. In this case stop the event and open the tab.
updated to use .live instead of .click
If you use jQuery, you can add a "live" click event handler to every a href at once:
<body>
click here
<br/>
whatever
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$('a').live('click',function() {
var myID = $(this).attr('href').match(/id=([a-zA-Z0-9_-]*)\&?/)[1];
if (myID) {
//run code here
alert(myID);
return false;
}
});
</script>
This should extract the id from the href's query string and let you do whatever you want with it.

Categories