How to disable Link for some time after being clicked? - javascript

To prevent impatient users from clicking on a link to a webstart application too often, I tried to disable the hyperlink for some seconds after it has been called the first time.
<a href="file.jnlp" onclick="if (!this.clicked){this.clicked = true; setTimeout('this.clicked = false' ,10000); return true;} return false">
The code above only works for disabling the link, but it doesn't get re-enabled after the timeout of 10 seconds.
I've seen that the 'this.clicked' variable isn't true (as it is supposed to be) when I check it in the setTimeout call. Maybe i'm missing some basic JS-knowledge here..
Or perhaps there is a different approach to solve this problem?

First add a this function to a Javascript Script block
function Debounce()
{
var self = this
if (this.clicked) return false;
this.clicked = true;
setTimeout(function() {self.clicked = false;}, 10000);
return true;
}
Now change your onclick to:-
onclick="return Debounce.call(this)"

using your code modifying only a small part it may work
<a href="file.jnlp" onclick="if (!this.clicked){this.clicked = true; setTimeout(function(){this.clicked = false;} ,10000); return true;} return false">
looks like people say that didnt work and it didnt form a closure around 'this'

The this object is not defined in the code being evaluated by setTimeout which is done in the global scope.
Give the link an ID then use getElementById e.g.
<a href="file.jnlp" id='my_link' onclick="if(!this.clicked){this.clicked = true; setTimeout('document.getElementById(\'my_link\').clicked = false;' ,10000); return true;} return false;">

give this anchor an ID and then change your timeout call to:
setTimeout('document.getElementById("<id>").clicked = false;' , 10000);
I think the 'this' is not evaluated to anything when the timer comes around.

var a=this;
setTimeout(function(){a.clicked = false} ,10000);

Related

javascript help; pausing autorefresh

trying to figure a way to keep my chat div area from refreshing and annoyingly scrolling to the bottom. after searching the only solution I could come up with, is setting a global to a certain value and changing it when onfocus and back with onblur.
javascript was never my strongest area and I think it might just be me.
var chatarea = document.getElementById('usertalk');
window.onload= function() {
chatarea.scrollTop = chatarea.scrollHeight;
}
var chatfocus = false;
chatarea.onfocus=function(){ chatfocus = true; }
chatarea.onblur=function(){ chatfocus = false; }
setInterval("updateChat()", 5000);
function updateChat(){
var ajaxRequest;
ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
if(chatfocus === false){
chatarea.innerHTML = ajaxRequest.responseText;
chatarea.scrollTop = chatarea.scrollHeight;
}
}
}
ajaxRequest.open("GET", "comments.php?t=<?php echo $topicc; ?>", true);
ajaxRequest.send(null);
}
If javascript would print me errors I could probably figure it out or search enough to understand. I've tried many different variations and assigning it to window but still script doesn't wanna work. I finally gave up and moved on in php and im now able call a edit form to replace a comment inside this same div that I want to auto refresh and going to need to pause this script for that too. But once again have no idea of achieving in js without asking questions.
"usertalk" doesn't exist at the time execution so attaching your event handlers is failing. Put your event handlers in the onload function:
var chatarea = null;
window.onload= function() {
chatarea = document.getElementById('usertalk');
chatarea.scrollTop = chatarea.scrollHeight;
chatarea.onfocus=function(){ chatfocus = true; }
chatarea.onblur=function(){ chatfocus = false; }
}
Edit: Didn't realize you're also referencing chatarea in updateChat, define this outside onload's scope as null but only use getElementById after the page has loaded.
i apparently cannot have a onfocus or onblur event on a div area?
after trying every possible way to get those events to work and change a value i didnt quite know how to set as a global without guessing until success, i made a input button to enable/disable my auto updateChat function and set the value in my hidden html form.
also i found useful websites like jshint.com to diagnose possible errors. sorry for being unaware

Why is this working?

I have written some simple javascript to change the content of an iframe according to the input of a field. After hours of attempts, I have managed to get it working; however I didn't really understand why I should put the "return true" and "return false" at the end of my search function. Thank you in advance!
function search(){
var course=document.getElementById("field");
if(course.value!=""){
if(course.value!="Course code (e.g. COMP1004)"){
var target=document.getElementById("frame");
target.src=course.value + ".php";
return false;
}
}else{
return true;
}
}
<input id="field" name="field" type="text"></input>
<input id="searchButton" name="searchButton" type="button"value="Search"onclick="search()"></input>
You don't really need to, since you are calling the function without expecting any value. And even if you write onclick = return search() you have no default action to prevent, since your input has type="button"
When you trigger a javascript function using onclick (depending on the browser), the actual functionality of the click can be prevented by returning false. So if you click on a button and return true (or nothing) the actual click will be triggered and e.g. load a new page. If you return false, the original function of the button will not be called ...

Javascript confirm ain't working as it should

I have this js function that checks if OK or Cancel is pressed and returns false or true. What I am trying to do is that when is true to run the remaining js function in the order they appear but it isn't working; deleteList('$row->listID');updateList(); are never executed.
Javascript:
function deleteConfirm(){
if (confirm("Are you sure you wanna delete that list?")){
return true;
}
else{
return false;
}
}
HTML:
<a href="#" id="listID" onclick="return deleteConfirm();deleteList('$row->listID');updateList();">
What am I doing wrong?
Thanks in advance.
It's because you're returning on the first statement (so the others never run), instead only hop out on a cancel, like this:
onclick="if(deleteConfirm()) { deleteList('$row->listID'); updateList(); }"
You can also greatly simplify your function, like this:
function deleteConfirm(){
return confirm("Are you sure you wanna delete that list?");
}
...or if possible go the unobtrusive route, using data- attributes to get the listID.

asp.net page reloading on javascript onclick function

Novice question I guess:
The Scenario:
I have an asp.net page that contains 6 divs and 6 hyperlinks which are linked to javascript function:
function showdiv(divname)
{
hideallcontentdivs();
var targetdiv = document.getElementById(divname);
targetdiv.style.display="block";
}
var alldivs=new Array();
function hideallcontentdivs()
{
alldivs=document.getElementsByTagName("div");
for(var i=0; i<alldivs.length;i++)
{
if(alldivs[i].className=="content")
{
alldivs[i].style.display="none";
}
}
}
ImageButton:
<img alt="alternate_text" src="imagesource" border="0px" />
the divs have id's: item1, item2....item6 and the hyperlink specify to the javascript function the id of the div that needs to displayed.
The Problem:
Whenever I click on an hyperlink, the effect that I want is achieved but the page reloads too. Don't really know where I'm going wrong but if anyone could guide me in the right direction, I'll be very very thankful.
Just return false on click
onclick="showdiv('item1');return false;"
Update:I just point the issue :), you can return the false where ever you like.
onclick="return showdiv('item1');"
and say to showdiv() to return false
You should add return false to your onclick handler. This prevents the default behaviour of the link.
A better solution would be to use jQuery or some other library and attach the event to the element. They also contain special functions to prevent the default behaviour:
Html:
<a id="button1" href="#"><img alt="alternate_text" src="imagesource" /></a>
Javascript/jQuery:
$('#button1').click(function(event) {
$('div').hide(); // hides all divs
$('#div1').show(); // shows the div with the id 'div1'
event.preventDefault(); // prevents postback
});
always, return false :)
but i'd rather put it in the function
function showdiv(divname)
{
hideallcontentdivs();
var targetdiv = document.getElementById(divname);
targetdiv.style.display="block";
return false;
}
+1 for Aristos' answer, although if you refactor the return false; to the end of the showdiv function you want have to update all the links.
return false is the key, as the other answers have said.
Just to add my tuppence though: you don't really need to use an anchor here and imho it's not good semantic style. Just use a span or div instead, and then the problem goes away.

Javascript: How to temporarily disable all actions on the page?

On a page with Ajax event, I want to disable all actions until the Ajax call returns (to prevent issues with double-submit etc.)
I tried this by prepending return false; to the current onclick events when "locking" the page, and removing this later on when "unlocking" the page. However, the actions are not active any more after they are "unlocked" -- you just can't trigger them.
Why is this not working? See example page below. Any other idea to achieve my goal?
Example code:
both the link and the button are showing a JS alert; when pressing lock, then unlock the event handler is the same as it was before, but doesn't work...?!?
The code is meant to work with Trinidad in the end, but should work outside as well.
<html><head><title>Test</title>
<script type="text/javascript">
function lockPage()
{
document.body.style.cursor = 'wait';
lockElements(document.getElementsByTagName("a"));
lockElements(document.getElementsByTagName("input"));
if (typeof TrPage != "undefined")
{
TrPage.getInstance().getRequestQueue().addStateChangeListener(unlockPage);
}
}
function lockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.cursor = 'wait';
if (el[i].onclick)
{
var newEvent = 'return false;' + el[i].onclick;
alert(el[i].onclick + "\n\nlock -->\n\n" + newEvent);
el[i].onclick = newEvent;
}
}
}
function unlockPage(state)
{
if (typeof TrRequestQueue == "undefined" || state == TrRequestQueue.STATE_READY)
{
//alert("unlocking for state: " + state);
document.body.style.cursor = 'auto';
unlockElements(document.getElementsByTagName("a"));
unlockElements(document.getElementsByTagName("input"));
}
}
function unlockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.cursor = 'auto';
if (el[i].onclick && el[i].onclick.search(/^return false;/)==0)
{
var newEvent = el[i].onclick.substring(13);
alert(el[i].onclick + "\n\nunlock -->\n\n" + newEvent);
el[i].onclick = newEvent;
}
}
}
</script>
<style type="text/css">
</style>
</head>
<body>
<h1>Page lock/unlock test</h1>
<p>Use these actions to lock or unlock active elements on the page:
lock,
unlock.</p>
<p>And now some elements:</p>
<a onclick="alert('This is the action!');return false;" href="#">link action</a>
<input type="button" value="button action" onclick="alert('This is another action!')"/>
</body>
</html>
Thanks guys for your ideas and answers.
Now I see that I have mixed up Strings and functions, which obviously can't work ;(
I should have made clear that we use some Web FW and tag libraries (Trinidad) which create the event handling (and Ajax) code, hence I can't edit that directly or use synchronous Ajax etc.
Moreover, Ajax is only one scenario where this code should be executed. It's purpose is to prevent the user to double-submit a page/action, which is also relevant for non-Ajax pages where you could kind of doulbe-click on a button. I know that this is not really safe, and it's only meant to be a "convenience" thingy to avoid getting the navigation error page too often (we have server-side protection, of course).
So, will try the div overlay, probably.
Thanks again,
Christoph.
How about setting up a global var
actions_disabled = 0
increment when the AJAX call starts then decrement when it finishes. All your "action" handlers can then start with
if (actions_disabled) return false;
Much simpler than debugging self-modifying code!
Alternatively, to lock your controls you could set:
control.disabled="disabled"
which will have the bonus of greying them out, making it obvious to the user that they can't submit. To unlock, simply set:
control.disabled=""
NEW IDEA BASED ON COMMENTS (can't quote code in comments, it appears ...):
You can always just hang extra attributes off Javascript objects:
To lock, you could:
control.onclick_old = control.onclick
control.onclick = "return false;"
To unlock, you could:
control.onclick = control.onclick_old
I once achieved this goal by creating a DIV that covered the area I wanted disabled, setting its z-index higher than any of the other elements on the page, and then setting its opacity to 0. By default, this DIV was hidden by display: none, so that it wouldn't interfere with anything. However, when I wanted the area disabled, I just set its display to block.
Steve
AJAX. Asynchronous. Just make the HTTP request synchronous. Problem solved.
The problem with your code is a result of not coming to grips with types in javascript.
When you say:
var newEvent = 'return false;' + el[i].onclick
what this does is coerce el[i].onclick (which is a function) to a string, then concatenates it to the string 'return false;'. Then when you reassign it as so:
el[i].onclick = newEvent;
onclick which was previously a function is now a string.
Then you attempt to resurrect your old function from the string by taking a substring:
var newEvent = el[i].onclick.substring(13);
which is fine, except newEvent is still a string! So when you assign it back to onclick again, you are assigning the string representation of the original function, not the function itself.
You could use eval to evaluate the string and return the function, but please don't do that. There are a number of better ways to do this, as has been suggested by other commenters.
I would also question why you wish to use AJAX at all if you don't want to allow asynchronous requests.
Put lockPage() at top of activete() function, and unlockPage() at bottom of deactivate().
activate: function() {
function lockPage()
{
lockElements(document.getElementsByTagName("a"));
lockElements(document.getElementsByTagName("input"));
lockElements(document.getElementsByTagName("button"));
};
function lockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.pointerEvents="none";
}
};
lockPage();
// ...
},
deactivate: function() {
// ...
function unlockPage() {
unlockElements(document.getElementsByTagName("a"));
unlockElements(document.getElementsByTagName("input"));
unlockElements(document.getElementsByTagName("button"));
};
function unlockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.pointerEvents="auto";
}
};
unlockPage();
},
Using a div overlay does not prevent a user from tab-ing into your page. Usually that is OK, since most users do not tab through a page anyhow.
If you use any keyboard shortcuts on your page, they will still be available, so separate handling will be needed for those.
Alse, I assume that clicking an element that can have focus (eg. an <a> tag), then pressing enter, would still cause a double submit.

Categories