How is this done?
This is a good question, and I actually don't think it can be done easily. (Some discussion on this)
If it is super duper important for you to have this functionality, you could hack it like so:
function singleClick(e) {
// do something, "this" will be the DOM element
}
function doubleClick(e) {
// do something, "this" will be the DOM element
}
$(selector).click(function(e) {
var that = this;
setTimeout(function() {
var dblclick = parseInt($(that).data('double'), 10);
if (dblclick > 0) {
$(that).data('double', dblclick-1);
} else {
singleClick.call(that, e);
}
}, 300);
}).dblclick(function(e) {
$(this).data('double', 2);
doubleClick.call(this, e);
});
And here is an example of it at work.
As pointed out in the comments, there is a plugin for this that does what I did above pretty much, but packages it up for you so you don't have to see the ugly: FixClick.
Raymond Chen has discussed some of the implications of single-versus-double clicking - although he's talking in the context of Windows, what he says is relevant to browser-based UI design.
Basically, the action taken on a double click should be a logical thing to do after a single click. So for example, in a desktop UI, single click selects an item, and double click opens it (e.g. opens the file, or launches the application). The user would have to select the file to open it anyway, so it doesn't matter that the single click action is taken before the double click action.
If you have a UI component whose double click action is completely unrelated to the single click action, such that it becomes necessary to prevent the single click action from occurring once the system realises it was actually a double click, then you really ought to rethink your design. Users will find it awkward and counter-intuitive, in that it will not act in the way they are used to things acting.
If you still want to go that way, then you will either have to use the debouncing technique (in which case all single click actions will be delayed) or else implement some mechanism whereby the double click handler undoes the work done by the single click handler.
You should also be aware that some users set a very long double click time. Somebody with, for example, arthritic hands might have a double click time of more than a second set in their system preferences, so the debouncing technique based on some arbitrary time period of your choosing is going to make your UI component inaccessible to those people if taking the single click action precludes taking the double click action. The "undo what just happened on single click" technique is the only viable workaround for this, as far as I know.
The technique outlined in the other answers is known as debouncing.
jQuery Sparkle provides a clean elegant solution for this, by implementing a singleclick custom event. By doing this, you can use it just like any other event, so:
$('#el').singleclick(function(){});
// or event
$('#el').bind('singleclick', function(){});
It also provides custom events for the last and first clicks of a series of clicks. And the lastclick custom event actually passes the amount of clicks back! So you could do this!
$('#el').lastclick(function(event,clicks){
if ( clicks === 3 ) alert('Tripple Click!');
});
You can find the source code for defining the custom event here.
It's open source under the AGPL licence, so you can feel free to grab what you need out of it worry free! :-) It's also actively developed on a day to day basis so you will never be short on support.
But most importantly it is a DRY Plugin/Effect Framework to allow you to develop plugins and extensions much more easily. So hope this helps to achieve that goal!
If this is for a button submitting a form (which is not necessarily the case for the original poster, but may be the case for other people getting here via Google), an easier option would be to disable the element that is being clicked on in your click event handler:
$(selector).click(function(e) {
$(this).prop('disable', true);
}
Related
I want to offer very limited drawing possibilities in a html canvas, on any device. Only three things can happen when the user interacts : a "unit" (it might be 40px for example, or 10, it is not very important) square appears where there was none, a rectangle disappears when "clicked", and lastly, several rectangles are fused.
The first two need a click to be detected (same down and up coordinates), the latter needs a drag to be detected (different down and up coordinates).
Therefore, the only thing the app needs to do is to detect (and remember) down, then up coordinates, whether it is a touch, a click, or anything at all.
Lastly, I do not wish to use jquery or any lib, but rather learn something from my coding.
Does this code look ok for that purpose? Can you propose ameliorations?
canvas.ontouchstart = canvas.onmousedown = onDown;
function onDown(e) {
saveDownCoords(e);
e.preventDefault();
};
canvas.ontouchend = canvas.onmouseup = onUp;
function onUp(e) {
...do whatever;
};
Second question, about preventDefault(), stopPropagation() (or whatever it is called): I have read it was needed to stop events from registering twice, as touches and clicks - but under which circumstances and devices, exactly, do touch events then click events fire for a unique user physical action?
For your first question, it's better to use element.addEventListener() : https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
canvas.addEventListener("mouseup", function(event) {
event.preventDefault(); // If you need to
// ... Do whatever
}
As for your second question, the event.preventDefault() call is there to stop the default behavior. It could be used to prevent double-clicking from selecting text, for example.
I want to redirect client to custom controller when he click back browser button.
Do you know any clear ways to catch back button event and force to call server?
Bests,
Thank you
Back button question is quite well answered on SO. A quick search will turn up lots of extra information. Here is a bit of a summary.
You have a few strategies to choose from.
1 - If you are developing an SPA (or not) you may find making use of the history api useful.
https://developer.mozilla.org/en-US/docs/Web/API/History
https://developer.mozilla.org/en-US/docs/Web/API/History_API
You will find plenty on SO about history api.
Try starting here Preserve dynamically changed HTML on back button
Basically, by adding a listener for popstate event which fires everytime the active history entry changes :
(in jQuery)
$(document).ready(function () {
$(window).on('popstate' , function (event) {
console.log('popstate');
console.log(event);
console.log(event.originalEvent);
});
};
http://caniuse.com/#search=history
2 - add a listner for the pageshow event, will fire when a page load is completed and when session history entry is used for navigation, so basically forward & back buttons.
https://developer.mozilla.org/en-US/docs/Web/Events/pageshow
$(window).on('pageshow' , function (event) {
console.log('pageshow');
console.log(event);
console.log(event.originalEvent);
});
http://caniuse.com/#search=pageshow
3 - Append a hashvalues to your urls with window.location.hash = 'pageHashValue'.
Listen for hashchange event and you can then act based on the #value if needed.
https://developer.mozilla.org/en-US/docs/Web/Events/hashchange
This is a common approach in single page applications.
$(window).on('hashchange' , function (event) {
console.log('hashchange');
console.log(event);
console.log(event.originalEvent);
console.log(window.location.hash);
});
http://caniuse.com/#search=hashchange
Finally take note that while you, as a developer, no doubt hate the browser back button (like me) our users tend to love it. If you change the expected behavior of the back button you can also expect your user experience to be negatively affected. The best strategy is to use these events to maintain the expected behavior of the back button rather than to try and change it.
I have a website that I am creating and there are different divs each with their own content. All of them are hidden except the main one that shows up on the homepage. The transitions are pretty long, and I like it that way, but the problem is that if somebody spams the navbar buttons it opens up all those divs ontop of each other. So to prevent that I want to temporarily disable the onClick for an <a></a> element. Then enable it after the transition is done. Currently I am able to disable it, but cannot find a way to re-enable it.
function disable(){
$(".bar").unbind();
$(".bar").removeAttr("onClick");
}
I know how to call a function after a certain amount of time, but what is the "enable" equivalent to the code in this function?
The exact opposite would be to set the onClick back on the element.
$('.bar').attr('onClick', function() { alert('blah'); });
or with vanilla js
document.querySelector(".bar")
.setAttribute('onClick', function() {...});
However, this is difficult to manage for many elements with the same functionality. It would be easier to have this entirely managed with javascript (and jQuery in this case).
function clickEvent(event) {
var self = $(this);
// Unbind the event
self.off(clickEvent);
// Click logic here
// Rebind event
self.on('click', clickEvent);
}
$('.bar').on('click', clickEvent);
Instead of disabling the event on the DOM, you can just add an extra piece of logic to your dynamic divs:
$('#mydiv').click(function() {
if(!inTransition())
// DO A THING
else
// DON'T DO A THING
});
As a side note: If you're doing a lot of dynamic DOM manipulation, you may want to look into using a data binding framework such as Angular or Knockout. jQuery is nice for simple DOM manipulations, but it can quickly become messy and hard to maintain if you're doing something complex (which it sounds like you are).
As somewhat of an extension to nmg49's answer, I'd like to provide a solution that's a little more in depth.
Essentially what you'll want to do is create a flag to determine whether or not you are currently transitioning, and cancel the onClick if it is true (disabling it after the transition is complete).
var isTransitioning = false;
$('.bar').onClick(function(){
if(isTransitioning) return;
isTransitioning = true;
// DO TRANSITION
});
Once the transition is complete, you simply set isTransitioning to false (either in a callback, or at the end of your onClick function; which ever one applies to your code).
This will ensure that, no matter how many times they click the button, they will not be able to transition if they're already in transition.
This is a bit of an abstract question, but I've been pondering its usefulness, and maybe it's either already been solved or inspires someone to do something based on it.
Well recently I ran across an issue whereby three browser events were fired, all as the result of a single user interaction: click, blur and focus. When the user clicks from one input to another, these events occur; and a similar set occur when the user tabs from one to another.
The trouble I had was that they fired in this order: blur, focus, click. It meant that, if the blur event caused DOM changes, the click event could be affected. I really wanted click, blur, focus - but that's not what the browser gave me.
I figured a general utility could be produced, capturing and cancelling browser events, then synchronising them and firing a single handler for all three. Perhaps extending the Event class so that the event could be reinstated.
Is there a more abstract design pattern I can use here? Something that will allow me to set up an arbitrary number of event listeners, and then fire a single event when all are complete? Does it have an implementation already? All advice welcome.
Dont need to break head around this! you can always trigger these events Programmatically
Note: object referenced here is any element selected using javascript selector.
Initially onBlur & onFocus do event.preventDefault which allows onClick to do its job first
var clicked=false;
object.onblur = function(e) {
if (!clicked) {
e.preventDefault
}
};
object.onfocus = function(e) {
if (!clicked) {
e.preventDefault
}
};
inside click event undo the above preventions and trigger the events in the order you wanted
object.onclick=function(){
clicked=true;
//Do anything
object.unbind('blur'); //this do undo prevent default
object.unbind('focus'); //this do undo prevent default
object.blur(); //in order you want
object.focus();
//make sure to put condition if click clicked
};
Thats it ! Hope it helps
I would like to replace the Javascript confirm() function to allow custom buttons instead of Yes/Cancel. I tried searching but all the solutions are event driven such as jquery dialog(where the code does not wait for a response but it is event driven). Does anyone know of a non-event driven solution. It must work in Safari as well as IE (so no vbscript).
Here is sample code in many parts of my system. This is old code and was not designed with event driven windows in mind. I am trying to avoid a rewrite.
**
// Wait for users response
if (result>2000) {
if (confirm("Are you sure this is right?")){
... do stuff
}
}
... continue with other stuff
... lots of other code.
if (confirm("Did you double check your numbers?")){
... do more stuff
} else {
... do something
}
**
Like the others have said, this isn't possible. confirm is a blocking function - no more script is executed until the user has dismissed the dialog - and you can't simulate that with other methods of Javascript.
A better solution would be to structure your code for asynchronous execution. This is almost always a better idea -- firstly, it lets you decide how your dialogs should look, what buttons there are, etc; and secondly, it doesn't block the user. They might have the important information they need to double-check open in another tab, or elsewhere on the page. With confirm they'd have to answer your question before being able to get to either of these places.
Here's a snippet of what the code might look like. There's a lot of blank bits here, but it might put you on the right track:
if (result>2000) {
displayConfirm("Are you sure this is right?", {
"Yes": function () {
// ... do stuff
},
"No": function () {
// do.. nothing? up to you.
}
}
}
You'll see here that there are two functions defined, but none actually get executed. The displayConfirm function would have to construct a dialog box (in whichever way) and then create buttons, using those functions as the click handlers (or at least, calling them from the click handler).
What you're trying to do is impossible. You'll have to use an event driven custom dialog solution, or stick with the browsers default confirmation dialog.
You will not be able to do this w/o changing your calls. No custom code can stop execution like the confirm box can. Any solution will require editing code to an event model.
As others have mentioned you can't do it directly, but I managed to do it in a round about way. Assuming like me you have a HTML button which submits a form, and want that button to have a jQuery modal dialog...
add an onclick event to the HTML button
make the onlick event open a jQueryUI dialog, and have the onclick event return false to cancel the button's default action
On your jQueryUI dialog, get the Yes/Ok button to remove the onclick event from the button in step 1, and then call then trigger the button to fire the click event