I have a button, "Add to Cart" which sends an ajax request when clicked. After the request returns successfully, the the button is replaced by "In Your Cart". "In Your Cart" has a mouseover state: "Remove From Cart".
The design requirement is that "Remove From Cart" only appear when the user physically moves the mouse over "In Your Cart". If they simply click "Add to Cart" and don't move the mouse, the button should say "In Your Cart" after the ajax call completes, even if the mouse is still over the element.
A simple mouseover event listener doesn't work, because it triggers when the element becomes visible. I'm considering counting mouseovers and mouseouts of a wrapper element, in order to determine if the mouseover event is "real", or just the result of the element becoming visible, but that's really ugly. Any other ideas for me?
You could do something like this (edit as appropriate for your AJAX call):
HTML:
<div class="cart">
<button class="add-cart">Add to Cart</button>
<button class="in-cart" style="display:none;">In Your Cart</button>
</div>
Javascript:
var $addCart = $('.add-cart');
var $inCart = $('.in-cart');
$addCart.click( function(e){
$addCart.hide();
$inCart.show().addClass( 'initial' );
});
$inCart.mouseover( function(){
if( ! $inCart.is( '.initial' ) ){
$inCart.text( 'Remove from Cart' );
}
});
$inCart.mouseout( function(){
$inCart.text( 'In Your Cart' ).removeClass( 'initial' );
});
jsFiddle
UPDATE
Based on OP's comment below, I've update the HTML and Javascript as follows:
<span class='cart'>
<button class="add-cart">Add to Cart</button>
<button class="in-cart" style="display:none;">In Your Cart</button>
</span>
Javascript:
var $cart = $('.cart');
var $addCart = $('.add-cart');
var $inCart = $('.in-cart');
$addCart.click( function(e){
$addCart.attr('disabled','disabled');
setTimeout(function(){
$addCart.hide();
$inCart.show();
}, 1000);
});
$cart.mouseenter( function(){
if( $inCart.is(':visible') ){
$inCart.text( 'Remove from Cart' );
}
});
$cart.mouseleave( function(){
if( $inCart.is(':visible') ){
$inCart.text( 'In Your Cart' );
}
});
The differences here are:
The add-cart button is disabled while AJAX is simulated and then hidden.
mouseover and mouseout have been replaced with mouseenter and mouseleave.
These events are now tied to the span wrapper so that the user mouse behavior can be tracked better since the span never hides itself.
Updated jsFiddle
You can prevent an event from firing by using jQuery's event.preventDefault();
I would write it this way:
$('#elementid').mouseover(function(){
event.preventDefault();
});
This will stop it from doing what it is supposed to do until you manually fire it later, or add code after the event.preventDefault(); to make it do what you want.
using jquery, mouseenter and mouseleave only fire when you enter or leave... so use a static sized wrapper for your image
onsuccess of the ajax, fade the image to what you want
mouseenter, check a flag you set when add to cart was clicked, if its set, you know the user clicked order, moved the mouse, then moved back in..
Related
I've been working on a web UI automation task with Selenium, Javascript and SeLion. I would like to take a screenshot of some equivalent scenario as Google homepage below:
In which the "Search by voice" should be present when mouse moves in that microphone icon (neither Click or Hover). I have search bunch of solutions, unfortunately non of them works as expected.
I'm basically dealing with something like this:
<div id="div_id">
<button type="button" class="button_class" disabled="" data-marko=" .
{"onclick":"handleClick s0-2-0-27-0
false","onkeydown":"handleKeydown s0-2-0-27-0 false"}"
title="This message shows by mouseenter event" aria-label="This
message shows by mouseenter event">
<span class="span_class"></span>
</button>
</div>
When mouse enters that button, "This message shows by mouseenter event" will be present. The page is likely written by Marko-js. Couldn't really handle it with plain Javascript, I tried.
Any idea?
Thanks in advance!
In which the "Search by voice" should be present when mouse moves in that microphone icon (neither Click or Hover)
if u read this link : https://www.w3.org/TR/DOM-Level-3-Events/#trusted-events , it says that only user agent events can trigger "search by voice" . its cant be done by scripts
I provided you a simple working example, give me a feedback if it is suitable for your needs.
function simulateMouseEnter() {
var event = new MouseEvent('mouseenter', {
'view': window,
'bubbles': true,
'cancelable': true
});
var myTarget = document.getElementById('target_div');
var canceled = !myTarget.dispatchEvent(event);
if (canceled) {
// A handler called preventDefault.
alert("canceled");
} else {
// None of the handlers called preventDefault.
alert("not canceled");
}
}
function mouseEnterBehaviour() {
myElement = document.getElementById("target_div");
// attach mouseenter event listener to element
myElement.addEventListener("mouseenter", function(event) {
// change the color of the font
event.target.style.color = "red";
});
// call the simulation
setTimeout(simulateMouseEnter,3000);
}
mouseEnterBehaviour();
<div id="target_div">target div</div>
Note: this should work with the most of the browser events
This happens very rarely but it still happens sometimes. I have two buttons next to each others with a jQuery click event on each:
JS:
$("#accepttrade").click(function(){
if(document.getElementById("agreeterms").checked ){
//accept process
$("#acceptdeposit").slideUp(200);
}
});
$("#declinetrade").click(function(){
//decline
$("#acceptdeposit").slideUp(200);
});
HTML:
<div id="acceptdeposit">
<button id="declinetrade" >Decline</button>
<button id="accepttrade" >Accept</button><input type="checkbox" id="agreeterms">
</div>
But sometimes when someone click on decline, it occurs the click of accept button, and go through even if the checkbox is unchecked.
I have never experienced it myself, but is it possible that this could happend? How can I be sure that "accept process" is never reached unless the user checks the box and click on accept?
Try this, cancel your click event:
$("#accepttrade").click(function(e){
if($("#agreeterms").is(':checked') ){
//accept process
$("#acceptdeposit").slideUp(200);
}
e.preventDefault();
});
I am currently making a textarea that will auto expand. This seems to work fine however the button click never seems to fire when the textarea is expanded. I am also using angularjs. Here is my code
HTML:
<body >
<div my-dir></div>
</body>
Javascript:
var app = angular.module('myApp',[]);
app.directive('myDir', function(){
return {
restrict:'A',
template:'<textarea id="textarea1">'+'</textarea>' + '<button ng-click="clicked()">Click me</button><textarea id="textarea2"></textarea>',
link:function(scope){
scope.clicked = function(){
alert("click worked");
}
}
}
});
If anybody could help me find a workaround or explain why exactly this is happening that would be greatly appreciated.
Link to codepen: http://codepen.io/anon/pen/mJrjpP
When the textarea is focused the button moves down a bit, and when you click the button the textareas blur event fires first, moving the button up, so the click never happens because the button moved.
The solution is to make sure the button stays put, using CSS positioning, or as noted in the comment by gyantasaurus below
<button ng-mousedown="clicked()">Click me</button>
The problem is that, when the textarea loses focus, it resizes and the button moves so, if you've removed focus from the textarea by clicking on the button, the click event, which consists of a mousedown and mouseup event, will never fire as, when the mouse is released, the cursor is no longer over the button.
You can test this yourself by focussing on the textarea, clicking down on the button, moving your cursor to the button's new position and then releasing your mouse button.
One solution, therefore, would be simply to use the muosedown event, rather than the click event.
One possible solution is to move your button at the last and apply position:fixed to it.
template:'<textarea id="textarea1">'+'</textarea>' + '<textarea id="textarea2"></textarea><button class="btn" ng-click="clicked()">Click me</button>'
CSS:
.btn{
position: fixed;
}
But of-course this involves changing your element's position.
app.directive('myDir', function(){
return{
restrict:'A',
template:'<div ng-click="clicked()"><textarea id="textarea1">'+'</textarea>' + '<button >Click me</button><textarea id="textarea2"></textarea></div>',
link:function(scope){
scope.clicked = function(){
alert("click worked");
}
}
}
});
This is called event event propagation or event bubbling
Example: http://codepen.io/anon/pen/ZGpjZw
I am showing and hiding a div based on some options selection.
Have a dropdown list with options 'enabled and disabled'.once user selects enabled needs to display the div else Hide the div.
Based on dropdown option selection Hide/Show div is working fine, but
If Disabled is the configured value. when I load the page , div will be hidden(working fine) , Then I will select Enabled, then div shows but ....... When I click on reset option,
Dropdown option is getting back to Disabled but Div section which should be hiden is not hiding
Here I have my code like this, protection switch is the wtform field recieved from flask
{{form.protection_switch}}
<div align="center" >
<button class="btn btn-info btn-sm" type="submit"><i class="icon-ok bigger-110"></i>Submit</button>
<button class="btn btn-sm" type="reset"><i class="icon-undo bigger-110"></i>Reset</button>
</div>
Section should be hide or display
<div id="protection_data"></br>
<table id="grid-table"></table>
<div id="grid-pager"></div>
</div>
Jquery code
function protection_selected() {
if ($('#protection_switch option:selected').val() == '0') {
$('#protection_data').hide();
} else if ($('#protection_switch option:selected').val() == '1') {
$('#protection_data').show();
}
}
$(document).ready(function() {
$('#protection_switch').change(function() {
protection_selected();
});
});
window.onload = protection_selected;
Listen for the click on the reset.
function protection_selected() {
var isVisible = $('#protection_switch').val() == '1';
$('#protection_data').toggle(isVisible);
}
$(function(){ //document ready
$("#protection_switch") //get your select element
.on("change", protection_selected) //listen for change event
.change(); //trigger the change event so defaults can be set
$('input:reset').on("click", function(e){ //bind click event to reset button
this.form.reset(); //force reset so we guarantee it has finished running
protection_selected(); //run the update code
e.preventDefault(); //cancel the click since we already ran the reset code
});
});
The pain in the rear thing about reset is you can detect when it has called, but there is no event for after it has successfully run. That is why I captured the click, run the reset on the form, called your function, and cancelled the click. Other way is to just use a delay inside and than call the function, but that can lead to a race condition.
I have a form with multiple rows and each row has a delete button with a link. I want to progressively enhance the links to add a bootstrap modal to these buttons. So what I'm doing is:
Grab all the delete button elements on the page.
Loop through each button.
For each button and change some attributes on the modal based on what button is clicked, including the url that is called when "OK" is cicked.
Everything is working like I want, except that each time the modal is triggered and the "OK" button is clicked the url attached to that gets appended to the previous one.
http://jsfiddle.net/bittersweetryan/9TpX8/ (click the remove button then OK more than once, have your console open)
Here's the code
//anonymous function to grab all delete buttons and turn into a modal
(function(){
var delBtn = $(".delete"),
$modal = $("#modal-delete");
if(!$modal.size()){
$modal = $('<div id="modal-delete" class="modal hide fade"><div class="modal-header"> ×<h3>Confirm Delete</h3></div><div class="modal-body" id="modal-content"></div><div class="modal-footer"> OK Cancel </div></div>').appendTo("body");
}
delBtn.each(function(){
var $button = $(this),
clickHandler,
href= $button.attr("href");
if(href){
clickHandler = function(){
console.log(href);
//return window.location=href;
};
}
else{
clickHandler = $button.click;
}
$button.attr("data-toggle","modal").
attr("data-target","#modal-delete");
$button.on("click",function(){
$modal.find("#okButton").on("click",function(){
clickHandler();
$modal.modal('hide');
}).
end().
find("#cancelButton").on("click",function(){
$modal.modal('hide');
}).
end().
find("#modal-content").html($button.attr("title"));
});
});
})();
You attach another click handler to 'ok' every time you invoke a dialog. Quick fix:
$modal.find("#okButton").one("click",function(){
clickHandler();
$modal.modal('hide');
})
Your updated fiddle.
In general, binding handlers with jQuery sticks a new handler in the queue; it doesn't overwrite the existing handler with a new one.
After getting burned by this a number of times, mostly trying to properly bind to dynamically generated controls, I just started sticking
.unbind("click")
in the queue before setting up onclick bindings.
Some new fiddle.