Ng Touch MouseUp Doesn't Apply - angularjs

I have a plunk here:
https://plnkr.co/edit/EKpqNwQEHHHiFoiv43s3
I am having an issue where my ng-touch on a phone or tablet is firing on the mousedown but not on the mouseup, resulting in the incrementation going on ad infinitum which is not desired.
Code here:
$scope.mouseDown = function(dir) { //this function fires when I press down on a phone
promise = $interval(function() {
if (dir === "up")
$scope.quantity++;
else
$scope.quantity--;
}, 100);
};
$scope.mouseUp = function() { //this function doesn't seem to fire when I stop the press on a phone
$interval.cancel(promise);
};

mouseup does not fire on touch devices. ngTouch does not give you directives to bind touch events unfortunately. You'll need to grab a custom directive that will allow you to bind touchstart and touchend events. There are a few out there. I've created a gist with one I've written that has worked well for me on several projects:
https://gist.github.com/Toddses/fdd862648e10530038550e253212d9c1
With this, as is, you can bind flux-touchstart and flux-touchend in the markup the same way you bind ng-mousedown and ng-mouseup.

Related

angular datepicker why calendar box is closed after click away

This is the link of the the example I am talking about.
Go to the link
https://angular-ui.github.io/bootstrap/
then check the datepicker example in plunker.
If we look in the code, I don't see any magic code there to do the closing part.
All I see is
$scope.open = function($event) {
$scope.status.opened = true;
};
which only opens the calendar.
My questions is how does it close on a click event that is outside of the calendar. This is a pretty good feature that I want to have on my other directives too.
---------------------Temp Solution----------------
Since no1 have provided an answer yet. For any1 who wants to know how to do this. I have a temp solution for you guys.
1. Add ng-click on the outter most tag.
2. Add ng-mouseleave and ng-mouseenter event on your custom tag.
Here is the flow:
When user mouse out/in of your custom tag. You set a flag to true/false.
Then when user clicks, close the div when mouse is outside the custom tag (You will use the flag to check ).
I found it myself.
It is because of the following code.
var documentClickBind = function(event) {
if (scope.isOpen && event.target !== element[0]) {
scope.$apply(function() {
scope.isOpen = false;
});
}
};

Scoping a click method for an angular application

I have an angular application where I am showing some menu bar upon clicking on an icon. I am using a scope variable and using ng-show to show/hide the same. It works fine, but there is a new requirement which states that if someone clicks on any other part of the application the menu should close. Now the problem is that when I am using an ng-click in the body it is triggering both the scope methods, i.e. for the icon click as well as the body click, since the icon is also within the body. What approach should I take for this? Do I need a different controller for the same?
on the click event you need to make sure the target is not the icon (consider also excluding the menu itself).
something like this:
$document.on('click', function (event) {
if (event.pageX == 0 && event.pageY == 0) return;
var target = event.target || event.srcElement;
if (!(elm.contains(target))) {
// close the menu
}
});
elm is your icon element
also, consider using a directive such as: https://github.com/IamAdamJowett/angular-click-outside
In the close listener added to the body, check that the event doesn't come from your the icon:
var closeListener = function(event) {
if (!iconElement.contains(event.target)) {
closeMenu();
}
};

ng-blur is not called from a function triggered by ng-keyup

so I have a ng-blur function that correctly fires if I do this
$scope.disableReturnButton = function($event){
document.onkeyup=function(e) {
if(e.which == 13){
$event.target.blur();
return false;
}
}
}
however if I try to set the keyup event on the element only, it doesn't seem to trigger ng-blur when the blur event happens
$scope.disableReturnButton = function($event){
if($event.which == 13){
$event.target.blur();// this blurs the element but doesn't trigger the ng-blur
return false;
}
}
here's the markup
<span contenteditable="true" class="blanks"
ng-blur="blurredWhy($event)"
ng-focus="focusedWhy($event)"
ng-bind="data.why"
ng-keyup="disableReturnButton($event)"></span>
If you use return false; in the event handler, with jQuery it will stop propagation and stop other events from firing in the chain. Since Angular uses jQuery lite (or you have jQuery full as well on the page) returning false will kill upstream events.
The first example would work because it uses the document.onkeyup which registers the event listener outside of jQuery.
See event.preventDefault() vs. return false

Dynamically add and remove events in angular.js

I'm new to angular.js and still struggling to catch best practices. In this particular case I'm unsure what would be angular way to dynamically add and remove event handlers.
I've created an simplified example that mimic my problem. In this example user can select from one of the items in a list. To select an item, user clicks on button that will display list. Clicking on a list, selection will be changed and list hidden.
But, what I want to do now is enable user to click anywhere on a page to hide list. Using jQuery approach I would add click event handler on body or document that would change view state and hide popup list.
I've created an example on jsfiddle with this approach. My question is: Is this good practice in angular.js? It feels kind of hackish.
Also, please note that I don't want to have a event handler present on document all the time, only when list is displayed.
Using practices described in angular.js guide, I've created directive that should handle the show/hide events.
.directive('toggleListDisplay', function($document) {
return function(scope, element, attr) {
var hideList = function (event) {
scope.listDisplayed = false;
$document.off('click', hideList);
scope.$apply();
};
element.on('click', function(event) {
event.stopPropagation();
scope.listDisplayed = !scope.listDisplayed;
if (scope.listDisplayed) {
$document.on('click', hideList);
} else {
$document.off('click', hideList);
}
scope.$apply();
});
};
});
This directive will add click event handler on element, and will start looking for a click on a document untill list is displayed. When it is not displayed anymore, it will stop watching for click event on document.
Working example can be found on jsfiddle.

Hide angular-ui tooltip on custom event

I've been looking around and trying out different things but can't figure it out. Is it possible to hide an angular-ui tooltip with a certain event?
What I want to do is to show a tooltip when someone hovers over a div and close it when a users clicks on it because I will show another popup. I tried it with custom trigger events but can't seem to get it working. I made this:
<div ng-app="someApp" ng-controller="MainCtrl" class="likes" tooltip="show favorites" tooltip-trigger="{{{true: 'mouseenter', false: 'hideonclick'}[showTooltip]}}" ng-click="doSomething()">{{likes}}</div>
var app = angular.module('someApp', ['ui.bootstrap']);
app.config(['$tooltipProvider', function($tooltipProvider){
$tooltipProvider.setTriggers({
'mouseenter': 'mouseleave',
'click': 'click',
'focus': 'blur',
'hideonclick': 'click'
});
}]);
app.controller('MainCtrl', function ($scope) {
$scope.showTooltip = true;
$scope.likes = 999;
$scope.doSomething = function(){
//hide the tooltip
$scope.showTooltip = false;
};
})
http://jsfiddle.net/3ywMd/
The tooltip has to close on first click and not the 2nd. Any idea how to close the tooltip if user clicks on div?
I tried #shidhin-cr's suggestion of setting $scope.tt_isOpen = false but it had the rather significant issue that, while the tooltip does fade out, it is still present in the DOM (and handling pointer events!). So even though they can't see it, the tooltip can prevent users from interacting with content that was previously behind the tooltip.
A better way that I found was to simply trigger the event used as tooltip-trigger on the tooltip target. So, for example, if you've got a button that's a tooltip target, and triggers on click...
<button id="myButton"
tooltip="hi"
tooltip-trigger="click">
</button>
Then in your JavaScript, at any point, you can trigger the 'click' event to dismiss your tooltip. Make sure that the tooltip is actually open before you trigger the event.
// ... meanwhile, in JavaScript land, in your custom event handler...
if (angular.element('#myButton').scope().tt_isOpen) {
angular.element('#myButton').trigger('click');
}
Since this triggers the actual internals of AngularUI's Tooltip directive, you don't have the nasty side-effects of the previous solution.
Basically you cannot play with the tooltip-trigger to make this work. After digging through the ToolTip directive code, I found that the ToolTip attribute exposes a scope attribute called tt_isOpen.
So in your ng-click function, if you set this attribute to false, that will make the tooltip hide.
See the updated demo here
http://jsfiddle.net/3ywMd/10/
Like this
app.controller('MainCtrl', function ($scope) {
$scope.likes = 999;
$scope.doSomething = function(){
//hide the tooltip
$scope.tt_isOpen = false;
};
})
Michael's solution got me 90% of the way there but when I executed the code, angular responded with "$digest already in progress". I simply wrapped the trigger in a timeout. Probably not the best solution, but required minimal code
// ... meanwhile, in JavaScript land, in your custom event handler...
if (angular.element('#myButton').scope().tt_isOpen) {
$timeout( function(){
angular.element('#myButton').trigger('click');
}, 100);
}
For future reference, the accepted answer angular.element('.yourTooltip').scope().tt_isOpen will not work in new versions as tooltip has been made unobservable. Therefore, the entire tootlip is removed from DOM. Simple solution is to just check if tooltip is present in DOM or not.
Borrowing from #liteflier's answer,
// ... meanwhile, in JavaScript land, in your custom event handler...
if (angular.element('.yourTooltip').length) { //if element is present in DOM
setTimeout( function(){
//Trigger click on tooltip container
angular.element('.yourTooltipParent').trigger('click');
}, 100);
}

Resources