Button click not firing when leaving textarea - javascript

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

Related

Trigger Button with Key instead of Mouse Click

Thanks for any help with this. Basically I have a stop button on a timer - and I need to have it be activated via a key press instead of or in addition to being able to click it with mouse. I've tried a few different ways using document.addeventlistener for example but nothing I have done has worked. Below is the relevant HTML/JS. Can anyone point me in the right direction of how I should best go about this? For example ideally I will press a number on the num pad to stop my counter. I'm not sure how to separate the two lines of code in the block format wise below, but just know button is in its proper html tags and the stop button is within script tags.
Thank you
<button id="stop" class="btn btn-danger">STOP</button>
/* Stop button */
stop.onclick = function() {
clear = true;
start.disabled = false;
stop.disabled = true;
}
Here, I created an example for the keydown event. Use tab key navigate to stop button and then press enter key it will get disabled.
document.getElementById("stop").addEventListener("keypress", stopTimer, false);
function stopTimer() {
document.getElementById("stop").setAttribute('disabled', true);
}
<button id="stop">STOP</button>
For the button element, click event has triggered on both, click and keypress as you can see below (this happen when you press spacebar or return, with another key just trigger keypress event); but on anyway you can set more than one event on your element.
document.getElementById("stop").addEventListener("click",function(){
console.log('Clicked!');
});
document.getElementById("stop").addEventListener("keypress",function(){
console.log('Keypressed!');
});
<button id="stop">Stop!</button>
if you need no-mouse interaction, you have to focus the element...
document.getElementById("stop").addEventListener("click",function(){
console.log('Clicked!');
});
document.getElementById("stop").addEventListener("keypress",function(){
console.log('Keypressed!');
});
document.getElementById("stop").focus();
<button id="stop">Stop!</button>

Angular - Implementing event handler on button mouseup when mouse is not over the button

I want to implement a Push To Talk button that enables voice when I mouse down, and disables voice when I release the mouse. Here's the code I have right now:
<button ng-mousedown="enablePushToTalk()" ng-mouseup="disablePushToTalk()" class="btn"> PushToTalk </button>
The problem scenario is this:
User hits push to talk button (mouseDown: enablePushToTalk is called)
User moves mouse away from button
User releases mouse: mouseUp event is never called, thus disablePushToTalk is never called! So Push To Talk stays enabled.
Here's a gif:
How do I ensure that "disablePushToTalk" gets called for every time that "enablePushToTalk" is called?
How about adding an ng-mouseup event listener to a parent element?
Created a jsBin using above idea for your problem.
Solution 1:
//html
<body style='height:500px;border:1px solid black;' ng-controller="MyCtrl" ng-mouseup='disable()'>
<div >
<button ng-mousedown="enablePushToTalk()" ng-mouseup="disablePushToTalk()" class="btn"> PushToTalk </button>
</div>
</body>
//js
function MyCtrl($scope) {
$scope.name = 'Superhero';
var isMouseUp = false;
$scope.enablePushToTalk = function(){console.log('mouseup');isMouseUp=true;}
$scope.disablePushToTalk = function(){console.log('mousedown');isMouseUp=false;}
$scope.disable = function(){if(!isMouseUp) return;console.log('mousedown from body');isMouseUp=false;}
}
jsBin link: http://jsbin.com/nedijudaga/edit?html,js,console,output
Solution 2:
Adding an ng-mouseup event only to parent element and not on button would do the trick.

Prevent clicking an anchor link while an input is focused?

I'm attempting to prevent a user from clicking a link and it going to another page while any input is focused. Sometimes the only available space around the input and the keyboard is a link and some users click the link accidentally. I'm trying to make it so when they click the link it blurs the input (closes the keyboard) and prevents the page from following the link. Then let them click the link again if they want to go to another page after the input is no longer in focus.
html
<input type="text">
Example
I've tried the following...
jQuery
$('a').on('click', function (event) {
if ($('input').is(":focus")) {
console.log('focused');
event.preventDefault();
}
});
(nothing gets logged)
Also tried this...
if ($('input').is(":focus")) {
$('a').on('click', function (event) {
event.preventDefault();
$('input').each(function(){
$(this).trigger('blur');
});
});
}
Neither one prevent the page from going to whatever link was clicked...
I don't think you can do this. You can disable the click event on the links while input is focused, and enable it back again when blur occurs on the input elements. However, while if user clicks on a link while focused on the input element blur event will occur first (which would enable clicking) then click even occurs and links acts as normal.
You could try disabling the links while input elements have focus, then you can enable them on the first click and restore normal operation.
$("input").on("focus", function() {
$("a").on("click", function (event) {
event.preventDefault();
$("a").off();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
example
I think I found a solution.
HTML
Example.com
jQuery
$('input').on('focus', function () {
$('a').each(function(){
$(this).addClass('cant-click');
});
});
$(document).on('touchend', function (e) {
if (!$(e.target).closest('input').length) {
$('a').each(function(){
$(this).removeClass('cant-click');
});
}
});
CSS
a.cant-click { pointer-events: none; }
When the input takes focus, every link gets this class. When anything on the page is clicked that is not an input, it removes this class from every link.

Disable focus event on left click only in AngularJS

I have an angular-strap datepicker that I only want to show on right click.
This I want to do over the default focus() method, as this is convenient for closing the thing once it blurs. To use the focus method on any element like a DIV, I added a tabindex.
The problem is, I can't seem to be able to disable the focus on the left click only. It's either disabled completely, or working for both.
I've already prevented the context menu to show on right click.
directives.directive('ngRightClick', ["$parse", function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngRightClick);
element.bind('contextmenu', function(event) {
scope.$apply(function() {
event.preventDefault();
fn(scope, {$event:event});
});
});
};
}])
For the left click, I've tried preventDefault(), but that doesn't really work. Then I've tried to blur it on click, which works, but the focus event is still called beforehand, for a fraction of a second.
directives.directive('ngLeftNofocus', ["$parse", function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngLeftNofocus);
element.bind('click', function(event) {
scope.$apply(function() {
event.preventDefault();
element[0].blur();
});
});
};
}])
This can all be found in a Plnkr: http://plnkr.co/edit/T2YBYwfqSLKxCUL0ITgk?p=preview
I know there are some solutions to prevent the focus using jQuery on this site, but I need it to stay active for the right click somehow.
Alternatively, if someone has a better way to trigger the datepicker on right click only (that it also closes once the user clicks anywhere else), I'd love to look at that too.
You could use bs-show attribute to toggle the datepicker manually.
Combined with the ng-right-click and ng-blur, it will give what you want.
<div bs-datepicker ng-model="test" tabindex="1"
data-trigger="manual"
bs-show="showDatePicker"
ng-blur="showDatePicker = false"
ng-right-click="showDatePicker = true">CLICK HERE</div>
Example Plunker: http://plnkr.co/edit/zJXdZOIZ9XQey3BkQ3I2?p=preview

Google Chrome: Focus issue with the scrollbar

I am using jQuery 1.3.2.
There is an input field in a form.
Clicking on the input field opens a div as a dropdown. The div contains a list of items. As the list size is large there is a vertical scrollbar in the div.
To close the dropdown when clicked outside, there is a blur event on the input field.
Now the problem is:
In chrome(2.0.172) when we click on the scrollbar, the input field will loose focus.
And now if you click outside, then the dropdown won't close(as the input has already lost focus when you clicked on the srollbar)
In Firefox(3.5), IE(8), opera(9.64), safari() when we click on the scrollbar the input field will not loose focus. Hence when you click outside (after clicking on the srollbar) the dropdown will close. This is the expected behaviour.
So In chrome once the scrollbar is clicked, and then if I click outside the dropdown won't close.
How can i fix this issue with chrome.
Well, I had the same problem in my dropdown control. I've asked Chrome developers concerning this issue, they said it's a bug that is not going to be fixed in the nearest future because of "it has not been reported by many people and the fix is not trivial". So, let's face the truth: this bug will stay for another year at least.
Though, for this particular case (dropdown) there is a workaround. The trick is: when one click on a scrollbar the "mouse down" event comes to the owner element of that scrollbar. We can use this fact to set a flag and check it in "onblur" handler. Here the explanation:
<input id="search_ctrl">
<div id="dropdown_wrap" style="overflow:auto;max-height:30px">
<div id="dropdown_rows">
<span>row 1</span>
<span>row 2</span>
<span>row 2</span>
</div>
</div>
"dropdown_wrap" div will get a vertical scrollbar since its content doesn't fit fixed height. Once we get the click we are pretty sure that scrollbar was clicked and focus is going to be taken off. Now some code how to handle this:
search_ctrl.onfocus = function() {
search_has_focus = true
}
search_ctrl.onblur = function() {
search_has_focus = false
if (!keep_focus) {
// hide dropdown
} else {
keep_focus = false;
search_ctrl.focus();
}
}
dropdow_wrap.onclick = function() {
if (isChrome()) {
keep_focus = search_has_focus;
}
}
That's it. We don't need any hacks for FF so there is a check for browser. In Chrome we detect click on scrollbar, allow bluring focus without closing the list and then immediately restore focus back to input control. Of course, if we have some logic for "search_ctrl.onfocus" it should be modified as well. Note that we need to check if search_ctrl had focus to prevent troubles with double clicks.
You may guess that better idea could be canceling onblur event but this won't work in Chrome. Not sure if this is bug or feature.
P.S. "dropdown_wrap" should not have any paddings or borders, otherwise user could click in this areas and we'll treat this as a scrollbar click.
I couldn't get these answers to work, maybe because they are from 2009. I just dealt with this, I think ihsoft is on the right track but a bit heavy handed.
With two functions
onMouseDown() {
lastClickWasDropdown=true;
}
onBlur() {
if (lastClickWasDropdown) {
lastClickWasDropdown = false;
box.focus();
} else {
box.close();
}
}
The trick is in how you bind the elements. The onMouseDown event should be on the "container" div which contains everything that will be clicked (ie, the text box, the dropdown arrow, and the dropdown box and its scroll bar). The Blur event (or in jQuery the focusout event) should be bound directly to the textbox.
Tested and works!
I was facing the same situation/problem and I tested the solution from "ihsoft" but it has some issues. So I worked on an alternative for that and made just one similar to "ihsoft" but one that works. here is my solution:
var hide_dropdownlist=true;
search_ctrl.onblur = function() {
search_has_focus = false
if (hide_dropdownlist) {
// hide dropdown
} else {
hide_dropdownlist = true;
search_ctrl.focus();
}
}
dropdow_wrap.onmouseover = function() {
hide_dropdownlist=false;
}
dropdow_wrap.onmouseoout = function() {
hide_dropdownlist=true;
}
I hope this will help someone.
Earlier also I faced such situation and this is what I have been doing.
$('html').click(function() {
hasFocus = 0;
hideResults();
});
and on the input field i will do this
$('input').click()
{
event.stopPropagation();
}
So this will close the drop down if clicked anywhere outside the div (even the scrollbar).
But I thought if someone could provide a more logical solution.
Could you maybe set the blur event to fire on the drop down div as well? This way, when either the input or the drop down loses focus, it will dissapear...
I'm curious...
You're using the last version of every browser, why don't you try it in chrome 4.0.202?
instead of detecting the blur, detect the document.body or window click and grab the mouse point. determine if this mouse point is outside of the menu box. presto, you've detected when they clicked outside the box!
I solved this by doing the following:
#my_container is the container which has the "overflow: auto" CSS rule
$('#my_container')
.mouseenter(function(){
// alert('ctr in!');
mouse_in_container = true;
})
.mouseleave(function(){
// alert('ctr out!');
mouse_in_container = false;
});
And then:
$('input').blur(function(){
if(mouse_in_container)
return;
... Normal code for blur event ...
});
When I select an element in the drop down, I rewrite the code as:
(>> ADDED THIS) mouse_in_container=false;
$('input').attr('active', false); // to blur input
$('#my_container').hide();

Categories