How to avoid double click on different button? - javascript

My problem is not a double click on same button but on 2 buttons.
User make a double click on a button.
The first click is detected by a first button
the controller do the action
the UI is refreshed, another button is display at same position
the second click is catched by the second button
=> user don't want click on the second button
How can I avoid this ?
I have tested :
To disable all UI buttons during action
but if action is really quick, buttons are enable before the second click
To not put 2 buttons on same place in the UI
not always possible and with responsive UI it's not possible to manage all cases
To add a global timestamp on click, and test during the second click if we have 500ms
_click: function(args)
{
// to avoid double click user need wait 500ms between each click
if(window.paperbutton_timestamp)
{
var diff = new Date() - window.paperbutton_timestamp;
if(diff < 500)
{
window.paperbutton_timestamp = new Date();
return;
}
}
window.paperbutton_timestamp = new Date();
if(scope.click)
{
scope.click(args);
}
},
Ok it does the job.
Now my problem is I have many protractor end to end tests, with more 2000 clicks.
Some protractor click are done in less 500ms.
Which solution can I have ?
1. Add a wait after each click
(more 2000 wait to add manually)
2. Set the 500ms in a global variable and override this value to 0ms
how to override on each test and each page refresh ?
3. Override protractor click ?
Seam is the better solution but I don't know how to do this.
Do you have another better idea :) ?

This is usually solved using good old human-computer interaction. Try using a style of button that visually reacts to hover, mousedown and mouseup events. This is usually enough to the user understand that a double click is not necessary. Stackoverflow itself has an awesome example:
Iddle button:
Hover button:
Mousedown button:
Mouseup button:
But if you really wish to prevent undesired clicks, maybe the best approach would be to disable buttons during actions and when you are about to re-enable then, put this action in a timeout, so the disabled buttons will last a little longer.
Another suggestion
You could implement a global function to spawn an invisible div covering the whole screen when required. This would prevent everything onscreen from working.
<div style="position:fixed; top:0; left:0; width:100vw; height:100vh; z-index: 10000"></div>
Put it in your layout file, usually app.component.html, and implement a *ngIf for it show up only when necessary. Also, its z-index should be greater than the z-index of any other element in your whole app.

have you consider Using *NgIf for both the buttons
**
<button *NgIf="oneActive" (click)="oneActive=false;callfunction()">one</button>
<button *NgIf="!oneActive" (click)="oneActive=true;callfunction2()">two</button>
**

It would be better if you write a custom function for protractor click:
protractor.ElementFinder.prototype.waitClick = function(wait){
browser.sleep(wait);
this.click();
};
describe('Tests', function() {
element.all(by.css('#testElements')).get(0).waitClick(1000)
});
Since, overriding the default click function is not recommended.

Related

Button generated by Javascript unrecognized until right click

Issue: generated button isn't registered on click ~1/20 times.
I'm generating a button :
var thebutton = document.createElement("BUTTON");
thebutton.setAttribute("id", "mybutton");
thebutton.setAttribute("class", "mybuttonclass");
thebutton.setAttribute("onclick","function()");
thebutton.innerHTML = '<i class="icon info"></i>';
document.getElementById("row").appendChild(thebutton);
Which is appended on top an existing button element as a second z-index layer:
.mybuttonclass {
z-index:9999;
}
I am also using
focusMethod = function getFocus() {
document.getElementById("mybutton").focus();
}
focusMethod();
In order to shift the browser selection from the trigger of the generating code (also a button) to #mybutton which works as it is highlighted.
Still for some reason, arbitrarily, every few times the button is created, any clicks will not registered to the created button, and in order to fix it and be able to trigger it, i need to right click the page -- after which the button starts to work.
Is there any way to have the browser rescan the page for elements after I generate the button? Or is there some other issue causing this that I'm missing?
Seems to happen in chrome more often, bootstrap is also run on CSS for the page.

Simulate div click multiple times

I've got slider in template glitching, and code is minimized. So, got tired of looking for the cause of the problem and decided to use a quick hack.
I need to fire a div click multiple times.
I've used this piece of code to trigger a click
$('.control-prev').trigger('click');
Works fine for one time click.
Now, how do i make it click multiple times?
http://jsfiddle.net/br4Lmyso/ (warning: creates three alerts, just to quickly show it works)
// set your count to whatever you want. Get a reference to the div
// so you're not querying the DOM everytime.
var triggerCount = 3;
var triggerDiv = $('.control-prev');
// loop!
for(var i = 0; i < triggerCount; i++) {
triggerDiv.trigger('click');
}
To be clear, trigger(...) does not simulate the click behavior and there is no way you can simulate the click behavior. What it does is to call the function that handle given event. These two are total different. For example:
$('#test').click(function() {
console.log("Clicked");
});
$('#test').dblclick(function() {
console.log("Double Click");
});
$('#test').trigger('click');
$('#test').trigger('click');
Despite of rapidly trigger two clicks, the double click will not trigger.

JavaScript Restrict User From Clicking Button Multiple Times

I am trying to restrict the user from clicking on a button multiple times. They can click on the button once when the page loads. If the page is reloaded the same should apply the user can click on the button only once.
I am using the following code however it doesn't seem to work for me
$("#doAccess").click(function() {
$("#doAccess").removeAttr('onclick');
DoSave();
});
Disable the button after it's been clicked
var accessBtn = $('#doAccess');
accessBtn.click(function() {
accessBtn[0].disabled = true;
DoSave();
});
Sounds like what you really need is:
$("#doAccess").one('click', DoSave);
jsFiddle example
.one() - Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
Why not this?
$("#doAccess").once('click', function() {
DoSave();
});
You should probably also gray out or disable #doAccess, whatever it is.

How can I put a button in the down state?

Suppose I have a button, which goes into a down state when someone clicks on it, but before the mouse is released.
Now suppose instead that someone presses the 'a' key, I want the button to go into the down state, until the key is released, at which point it is triggered. Is this possible?
After dooing some research here is the final answer I got:
You can trigger mousedown or mouseup events on a button element using keyup and keydown
if your button is programmed to change its style according to these events than you are good to go.
See this fiddle example: http://jsfiddle.net/FwKEQ/15/
Note that if you use jQuery's UI components than it does work. But for standard buttons there is no way that you can move them to their pressed state using javascript
html:
<button id="jQbutton">Press 'A' to move me to pressed state</button>
Javascript:
<script>
$( "#jQbutton" ).button();
$(document).keydown(function(event) {
if ((event.keyCode === 97)||(event.keyCode === 65))
$("#jQbutton").mousedown();
});
$(document).keyup(function(event) {
if ((event.keyCode === 97)||(event.keyCode === 65))
$("#jQbutton").mouseup();
});
</script>
EDIT:
There might be a hack that we could utilize:
using accesskey for the button element and then try to simulate the accesskey press (that i am not sure if possible)
here is where i'm at so far http://jsfiddle.net/FwKEQ/28/
EDIT 2:
So looking further into this topic i have found the following:
Default buttons (without styles) are rendered by the OS, I was not able to find a formal proof for that but if you try to load the same page using a mac OS you'll get mac OS style buttons while in windows you will get the "ugly" gray button.
Because the default buttons are rendered by the OS they comply to OS events meaning events that are sent by the browser and are trusted.
this is not true for custom styled buttons as they comply to CSS an JS to change their appearance on press that is why the JQ button is affected by JS.
so to summarize you would need a trusted press event to fire on a default button to change its style and that cannot be done due to security constraints.
read a bit more about trusted events here: http://www.w3.org/TR/DOM-Level-3-Events/#trusted-events
and if someone could find a formal reference with regards to the default buttons being rendered by the OS please comment or edit this answer.
Unfortunately the rendering of the active state on default buttons neither
is a simple matter of css styling nor can be easily changed by applying
javascript.
An option to do this on default buttons is to use the hotkeys jquery plugin: https://github.com/jeresig/jquery.hotkeys or implement alternative key codes for different browsers.
and to apply 50% opacity to the default button when pressed (to indicate the keydown).
(To me it seems almost perfect ;-) It probably is as good as it can easily get to work across platforms and browsers using default buttons.
jsfiddle DEMO
and the code ...
html:
<button id="test">Test Button</button>
Selected: <span class="selected" id="out"></span>
javascript:
$('#test').click(function () {
fn_up();
});
fn_down = function(event){
$('#test').css("opacity", 0.5);
$('#test').focus();
event.preventDefault();
}
fn_up = function(event){
$('#test').css("opacity", 1);
$('#out').append(" test");
event.preventDefault();
}
//to bind the event to the 'a' key
$(document).bind('keydown','a', fn_down);
$(document).bind('keyup','a', fn_up);
//to get the same effect with the 'space' key
$(document).bind('keydown','space', fn);
$(document).bind('keyup','space', fn2);
In the fiddle I apply it to the space button and the mousedown/up to achieve the same effect with all events (but you could just use it with the 'a' key ... this is a matter of taste).
Here is a jsfiddel that shows how it's done using jQuery: http://jsfiddle.net/KHhvm/2/
The important part:
$("#textInput").keydown(function(event) {
var charCodeFor_a = 65;
if ( event.which == charCodeFor_a ) {
// "click" on the button
$('#button').mousedown();
// make the button look "clicked"
$('#button').addClass('fakeButtonDown');
// do some stuff here...
// release the button later using $('#button').mousedown();
}
});
The button event is triggered when entering "a" in the input field. But as Mark pointed out you need to fake the styling for the clicked button because the browser doesn't do it.
Edit: I'm not sure if you're using jQuery in your project. I just wanted to show that it is possible at all. If it can be done with the jQuery library there is also a way to do it in pure javascript. ;)

CAAT - repeating behavior effect on event trigger

Using CAAT I can bind an event to adding a behavior to an actor. However I cannot figure out how to repeat the behavior effect on consequent event trigger.
Here is the code:
circle.mouseDown = function(e){
circle.emptyBehaviorList();
circle.addBehavior(circle_jump);
}
http://jsfiddle.net/S4frL/1/
Clicking on the circle makes it jump once, then clicking again does nothing, although BehaviorList should be empty before adding the same behavior again.
Am I missing something?
Thanks in advance!
That's because you have to declare/apply the behaviour once, then when you need the actor (ball) to move you just have to say "when".
Basically you have to change your code to something like this:
circle.addBehavior(circle_jump);
scene.addChild(circle);
circle.mouseDown = function(e){
circle_jump.setFrameTime(scene.time,2000);
}
setFrameTime( ) tells the actor when [scene.time -> now] and how long [2000 ms] the actor has to follow his behaviour.
I hope I've been clear enough.
ps. The ball now takes a jump at page load, that's because you have to comment this line:
var circle_jump = new CAAT.PathBehavior().
setPath(path_jump).
/* THIS ONE setFrameTime(0,2000). */
setCycle(false).
setAutoRotate(false);

Categories

Resources