angularJS ngTouch - can't get relative coordinates - angularjs

using ngClick i am easily able to get the relative click coordinates from event.offsetX. however using ngTouch there seems to be no obvious way of doing this. i've inspected the event.originalEvent.changedTouches[] array thoroughly but all of the coordinates in my touch event are absolute.
the only way appears to be traversing the DOM and getting each element's offset relative to its parent...a terrible solution indeed. am i missing something? where is the easy access to the x,y coordinates of the touch relative to the listening element?

i ended up using jQuery to hack out a solution - something that i've found occasionally necessary even when trying to avoid it and go all angular. since the relative coordinates aren't provided you have to figure out the viewport offset of the target element being clicked.
perhaps ngTouch is so young that the authors hadn't thought to add this by default, but it feels like an oversight to me.
i should note that i also discovered what appears to be an ngTouch bug where, if you tap just outside the ng-click element but close enough that the touch overlaps into the element, it fires with a MouseEvent whereas if you tap well inside the element it uses a TouchEvent instead. getting the offsetX parameter is different for each of these events as shown below.
scope.click = function( event )
{
var offsetX = null;
if( event.originalEvent.changedTouches )
{
offsetX = event.originalEvent.changedTouches[0].clientX - $(event.currentTarget).offset().left;
}
else
{
offsetX = event.offsetX;
}
... do stuff with offsetX ...
}

Related

How do I return focus to an element when the entire page changes?

I have a complicated setup. My application is driven by a set of "rules" which dictate what the user interface is. The UI is rendered by looping through the rules and creating the individual dropdowns. Initially, everything renders properly. However, once a user makes a change to the UI, other rules may be affected. In my application, an api call is made, which then returns a modified set of rules. In the attached plunker, I've simplified things such that only the new set of rules is applied, which causes the page to re-render. The problem is that my users would like to be able to tab between all of the entries on the page and make changes. However, once the page is re-rendered, the currently selected page element is now gone nothing has the focus. I've tried to put the focus back on the proper element by tracking a common Id, but to no avail.
Using either of these doesn't seem to work.
var el = document.getElementById(focusId);
el.focus();
angular.element(el).focus();
I've also tried using the autofocus attribute on the dropdown that I want to have focus, but that didn't work either. I'm using angularjs 1.2. Any ideas are appreciated.
http://plnkr.co/edit/ND9PKqULIOlixWR4XChN?p=preview
If you want to assign auto focus dynamically to a element on the DOM from angular you can use this:
var myEl = angular.element(document.querySelector('select'));
myEl.attr('autofocus',"attr val");
You can also pass in an id like: angular.element(document.querySelector('#focusId'));
You can look here for a prior answer which may be of some more help!
-Cheers!
Problem here is, you are trying to focus the element before the blur event completes. So you need to execute the focus code after blur event. Async execution of your focus code would solve the problem. You can use either setTimeout or $timeout.
setTimeout(function(){
angular.element('#'+focusId).focus();
/* //or
var el = document.getElementById(focusId);
el.focus();
*/
});
or
$timeout(function(){
angular.element('#'+focusId).focus();
/* //or
var el = document.getElementById(focusId);
el.focus();
*/
});
dont forgot to inject $timeout to your controller if you are using second code. Hope this helps :)

angular-google-maps - listen for infowindow domready event

Listening for the domready event in normal js Google maps is relatively easy
as outlined here :
infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(infoWindow, 'domready', function() {
// whatever you want to do once the DOM is ready
});
However it doesn't seem obvious how to do it in angular-google-maps.
Is there a solution ?
The solution when using Angular Google Maps involves using the infowindow control object - see docs.
As noted in this issue - where I first posted this solution - you can create an empty infowindow control object within the main controller :
$scope.infowindowControl = {};
Then you scope bind your new object in the ui-gmap-window directive definition like :
<ui-gmap-window
options="windowOptions"
closeClick="closeClick()"
control="infowindowControl"
>
On infowindow open (actually unsure at what point) - it will pass five functions to the empty object you created within $scope. Some of these functions are noted in the documentation but in a rather haphazard and non-defined way :
getChildWindows()
getGWindows()
getPlurals()
hideWindow()
showWindow()
The one that you need is getGWindows() - which you put inside your marker click event.
This will get you an array of the open infowindows and you can now attach an event listener in the standard google maps fashion, like :
var windows = $scope.infowindowControl.getGWindows();
console.log('inside click after getGWindows ', windows);
google.maps.event.addListener(windows[0], 'domready', function() {
console.log('infowindow domready just fired !!');
});
While it's not an ideal, well documented or easy solution (and took me a number of hours to figure out) - and passing functions to an empty object is frankly counter-intuitive - it does seem to work.
Plunker here.

How to 1. detect url in textarea event, 2: convert to url. Using AngularJS

We have a simple control (textarea), where we would like to detect user input of 'proper' urls and:
1. Visually convert these 'proper' urls to links and
2. Trigger an event we can hook on to detect a 'proper' link has been entered.
Of course the contents of textareas cannot be styled. As far as we see, though, TinyMCE (via AngularUI) might be the solution along with its 'autolink' plugin. However, other than whitelisting, it is not clear how 1. we can control/manage what a 'proper' link is (for example bit.ly or deliciou.us, etc are common domains now) or 2. how we can detect an event that a proper url has been entered other than using TinyMCE's 'onChange' and using our own custom regular expressions.
Although we can imagine solutions, this is a common requirement nowadays and we're having difficulty finding pre-built solutions to achieve this. BTW, we are using AngularJS.
Any help or pointers greatly appreciated!
Thanks,
Mo
We have a very similar situation where we have a textArea where the user can enter anything and any urls are supposed to be converted and displayed as clickable links. We solved it as follows.
Display the textarea value in a div. Prior to display we translate the value with a small function like this:
$scope.transformHrefsInAnswer = function(value) {
var retval = value;
if(retval != null) {
var urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
retval = value.replace(urlRegex, function (url) {
return '' + url + '';
});
}
return retval;
};
When the user clicks on the div we switch it to be a editable textarea with the actual value bound to the proper ng-model. They can then put in anything they want. When the area loses focus it switches back to a DIV and we call the transform function again so it displays as a valid, clickable link.
If all you want to do is validate you can use the transform function with minor mods to check for matches.
Hope this helps.

Cursor (caret ) moves to beginning when call on change event on contenteditable div using angular js

The cursor gets moved to the beginning instead of being set to last type position when the change event is fired. I am using content editable div using angular js.
plunker
http://plnkr.co/edit/FFaWNZmgk00Etubtjgg8?p=preview
Why does the cursor position move to beginning?
I know this is an old question but, as I've been searching my whole working day to find a solution to this issue, I'd like to share this solution to people who might still looking for a working answer :
var el, el2, range, sel;
el = element[0];
range = document.createRange();
sel = window.getSelection();
if (el.childNodes.length > 0) {
el2 = el.childNodes[el.childNodes.length - 1];
range.setStartAfter(el2);
} else {
range.setStartAfter(el);
}
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
I got this code originally from akatov/angular-contenteditable directive, "moveCaretToEndOnChange" method.
and this worked for me.
I would assume Angular is rewriting the innerHTML property of the editable element, thus destroying and recreating all of the DOM tree within it, which results in the caret resetting to the start. See these answers for potential solutions:
https://stackoverflow.com/a/13950376/96100
https://stackoverflow.com/a/8240055/96100
In my case I was using the same reference of array for changing the innerHTML as was used on the DOM (two way binding). Hence the dom re-rendered and thus the cursor moved to the beginning.
The Solution was to make a deep copy of the array using JSON.parse(JSON.stringify(a)); where a is the array that stores the words that are contenteditable and then do the change
let filetexts =JSON.parse(JSON.stringify(this.filetexts));
// updating the current text
filetexts[alternativesIndex].Alternatives[0].Words[wordIndex].Word = html;
let data = { Text: JSON.stringify(filetexts) };
this.fileService.changeFileText(data, this.file.fileId).subscribe(res => {
});

Angular JS Touch and Swipe

I am very new to angular JS and working on a mobile application. As a part of it, I need to write a service that handles touch events like swipe-left, swipe-right, swipe-up and swipe down and I need to call back depending on which action is made. Please let me know if there any useful tutorials.
As mentioned in the comments ngTouch is a good place to start, however it only has swipe left and swipe right. I recommend using Angular Gestures; it's an angular implementation of hammer.js, and has pretty much everything you'd ever need:
doubletap
dragstart
drag
dragup
dragdown
dragleft
dragright
dragend
hold
pinch
pinchin
pinchout
release
rotate
swipe
swipeup
swipedown
swipeleft
swiperight
tap
touch
transformstart
transform
transformend
Another option is the angular-swipe module. It replaces ng-swipe and uses the same directives, adding up and down:
ng-swipe-up
ng-swipe-down
ng-swipe-left
ng-swipe-right
In html i used 5 tabs and i am able to swipe left or right smoothly.
my code given below.
RECEIVED | SENT | DELETED | ARCHIVED Reports
In html
ng-swipe-left="leftTab()" ng-swipe-right="rightTab()"
and In controller.
$scope.leftTab = function(){
if($scope.tab != 4 ){
$scope.getAlertsSummary($scope.tab + 1);
}
};
$scope.rightTab = function(){
if($scope.tab != 0 ){
$scope.getAlertsSummary($scope.tab - 1);
}
};
Here getAlertsSummary used for get tab data.

Resources