diff --git a/ionic/components.ts b/ionic/components.ts
index 19f64eec56..a98961691f 100644
--- a/ionic/components.ts
+++ b/ionic/components.ts
@@ -2,12 +2,13 @@
export * from 'ionic/components/app/app'
export * from 'ionic/components/action-menu/action-menu'
export * from 'ionic/components/aside/aside'
+export * from 'ionic/components/button/button'
export * from 'ionic/components/checkbox/checkbox'
export * from 'ionic/components/content/content'
export * from 'ionic/components/icon/icon'
export * from 'ionic/components/item/item'
export * from 'ionic/components/item/item-group'
-export * from 'ionic/components/form/form'
+export * from 'ionic/components/form/input'
export * from 'ionic/components/form/text-input'
export * from 'ionic/components/form/tap-input'
export * from 'ionic/components/form/label'
diff --git a/ionic/components/action-menu/action-menu.ts b/ionic/components/action-menu/action-menu.ts
index 027ea4c2b4..fe669bbd93 100644
--- a/ionic/components/action-menu/action-menu.ts
+++ b/ionic/components/action-menu/action-menu.ts
@@ -8,6 +8,7 @@
import {View, Injectable, NgFor, NgIf} from 'angular2/angular2';
+import {TapClick} from '../button/button';
import {Overlay} from '../overlay/overlay';
import {Animation} from '../../animations/animation';
import * as util from 'ionic/util';
@@ -15,7 +16,7 @@ import * as util from 'ionic/util';
@View({
template: `
-
+
`,
- directives: [NgFor, NgIf]
+ directives: [NgFor, NgIf, TapClick]
})
class ActionMenuDirective {
diff --git a/ionic/components/button/button.ts b/ionic/components/button/button.ts
new file mode 100644
index 0000000000..0a406611f0
--- /dev/null
+++ b/ionic/components/button/button.ts
@@ -0,0 +1,54 @@
+import {Directive, ElementRef, Optional, Ancestor} from 'angular2/angular2';
+
+import {IonicConfig} from '../../config/config';
+import {Gesture} from '../../gestures/gesture';
+import * as dom from '../../util/dom';
+
+
+@Directive({
+ selector: '[tap-disabled]'
+})
+export class TapDisabled {}
+
+
+@Directive({
+ selector: 'a,button,[tappable]'
+})
+export class TapClick {
+
+ constructor(
+ elementRef: ElementRef,
+ config: IonicConfig,
+ @Optional() @Ancestor() tapDisabled: TapDisabled
+ ) {
+
+ if (config.setting('tapPolyfill') && !this.tapGesture && !tapDisabled) {
+ this.tapGesture = new Gesture(elementRef.nativeElement);
+ this.tapGesture.listen();
+
+ this.tapGesture.on('tap', (gestureEv) => {
+ this.onTap(gestureEv.gesture.srcEvent);
+ });
+ }
+
+ }
+
+ onTap(ev) {
+ if (ev && this.tapGesture) {
+ ev.preventDefault();
+ ev.stopPropagation();
+
+ let c = dom.pointerCoord(ev);
+
+ let clickEvent = document.createEvent("MouseEvents");
+ clickEvent.initMouseEvent('click', true, true, window, 1, 0, 0, c.x, c.y, false, false, false, false, 0, null);
+ clickEvent.isIonicTap = true;
+ this.tapGesture.element.dispatchEvent(clickEvent);
+ }
+ }
+
+ onDestroy() {
+ this.tapGesture && this.tapGesture.destroy();
+ }
+
+}
diff --git a/ionic/components/checkbox/checkbox.ts b/ionic/components/checkbox/checkbox.ts
index 3939f674e7..e54fd584aa 100644
--- a/ionic/components/checkbox/checkbox.ts
+++ b/ionic/components/checkbox/checkbox.ts
@@ -8,7 +8,7 @@ import {
} from 'angular2/angular2';
import {Ion} from '../ion';
-import {IonInputItem} from '../form/form';
+import {IonInputItem} from '../form/input';
import {IonicConfig} from '../../config/config';
import {IonicComponent, IonicView} from '../../config/annotations';
import {Icon} from '../icon/icon';
diff --git a/ionic/components/form/focus-holder.ts b/ionic/components/form/focus-holder.ts
index 415060fbc1..ae14af6499 100644
--- a/ionic/components/form/focus-holder.ts
+++ b/ionic/components/form/focus-holder.ts
@@ -3,7 +3,7 @@ import {Component, Directive, View, Parent, ElementRef, forwardRef} from 'angula
import {IonicConfig} from '../../config/config';
import * as dom from '../../util/dom';
import {Platform} from '../../platform/platform';
-import {IonInput} from './form';
+import {IonInput} from './input';
@Component({
diff --git a/ionic/components/form/tap-input.ts b/ionic/components/form/tap-input.ts
index 93ae80af8c..b8712c35f4 100644
--- a/ionic/components/form/tap-input.ts
+++ b/ionic/components/form/tap-input.ts
@@ -1,6 +1,6 @@
import {Parent, Ancestor, Optional, ElementRef, Attribute, Directive} from 'angular2/angular2';
-import {IonInput} from './form';
+import {IonInput} from './input';
import {IonicApp} from '../app/app';
import {IonicConfig} from '../../config/config';
import {Content} from '../content/content';
diff --git a/ionic/components/form/text-input.ts b/ionic/components/form/text-input.ts
index deb06b7f91..0fc17624ac 100644
--- a/ionic/components/form/text-input.ts
+++ b/ionic/components/form/text-input.ts
@@ -2,7 +2,7 @@ import {Directive, View, Parent, Ancestor, Optional, ElementRef, Attribute, forw
import {IonicDirective} from '../../config/annotations';
import {IonicConfig} from '../../config/config';
-import {IonInput, IonInputItem} from './form';
+import {IonInput, IonInputItem} from './input';
import {IonicApp} from '../app/app';
import {Content} from '../content/content';
import {ClickBlock} from '../../util/click-block';
diff --git a/ionic/components/nav/swipe-handle.ts b/ionic/components/nav/swipe-handle.ts
index f92878eaa7..9d7c63bbcc 100644
--- a/ionic/components/nav/swipe-handle.ts
+++ b/ionic/components/nav/swipe-handle.ts
@@ -93,4 +93,8 @@ export class SwipeHandle {
return (this.viewCtrl ? this.viewCtrl.swipeBackEnabled() : false);
}
+ onDestroy() {
+ this.gesture && self.gesture.destroy();
+ }
+
}
diff --git a/ionic/config/annotations.ts b/ionic/config/annotations.ts
index c2c0221d98..4721d42e06 100644
--- a/ionic/config/annotations.ts
+++ b/ionic/config/annotations.ts
@@ -16,6 +16,7 @@ import {
Segment, SegmentButton, SegmentControlValueAccessor,
RadioGroup, RadioButton, SearchBar,
Nav, NavbarTemplate, Navbar, NavPush, NavPop,
+ TapClick, TapDisabled,
Register
} from '../ionic';
@@ -71,7 +72,11 @@ export const IonicDirectives = [
forwardRef(() => Navbar),
forwardRef(() => NavPush),
forwardRef(() => NavPop),
- forwardRef(() => Register)
+ forwardRef(() => Register),
+
+ // Gestures
+ forwardRef(() => TapClick),
+ forwardRef(() => TapDisabled),
];
class IonicViewImpl extends View {
diff --git a/ionic/gestures/gesture.ts b/ionic/gestures/gesture.ts
index 5b3ff89a38..9b4a7d1836 100644
--- a/ionic/gestures/gesture.ts
+++ b/ionic/gestures/gesture.ts
@@ -1,6 +1,7 @@
import * as util from 'ionic/util';
import {Hammer} from 'ionic/gestures/hammer';
+
export class Gesture {
constructor(element, opts = {}) {
util.defaults(opts, {
@@ -18,6 +19,7 @@ export class Gesture {
this._callbacks = {};
}
+
options(opts = {}) {
util.extend(this._options, opts);
}
@@ -31,6 +33,7 @@ export class Gesture {
listen() {
this.hammertime = Hammer(this.element, this._options);
}
+
unlisten() {
this.hammertime.destroy();
this.hammertime = null;
@@ -41,6 +44,7 @@ export class Gesture {
}
this._callbacks = {}
}
+
destroy() {
this.unlisten()
}
diff --git a/ionic/ionic.ts b/ionic/ionic.ts
index 12595b6f9d..80f99394d1 100644
--- a/ionic/ionic.ts
+++ b/ionic/ionic.ts
@@ -16,7 +16,6 @@ export * from 'ionic/routing/url-state'
export * from 'ionic/util/click-block'
export * from 'ionic/util/focus'
-export * from 'ionic/util/tap'
export * from 'ionic/animations/animation'
export * from 'ionic/animations/builtins'
diff --git a/ionic/util/tap.ts b/ionic/util/tap.ts
deleted file mode 100644
index a7fce7596a..0000000000
--- a/ionic/util/tap.ts
+++ /dev/null
@@ -1,603 +0,0 @@
-import {dom} from './dom'
-import {Platform} from '../platform/platform'
-
-/**
- * @ngdoc page
- * @name tap
- * @module ionic
- * @description
- * On touch devices such as a phone or tablet, some browsers implement a 300ms delay between
- * the time the user stops touching the display and the moment the browser executes the
- * click. This delay was initially introduced so the browser can know whether the user wants to
- * double-tap to zoom in on the webpage. Basically, the browser waits roughly 300ms to see if
- * the user is double-tapping, or just tapping on the display once.
- *
- * Out of the box, Ionic automatically removes the 300ms delay in order to make Ionic apps
- * feel more "native" like. Resultingly, other solutions such as
- * [fastclick](https://github.com/ftlabs/fastclick) and Angular's
- * [ngTouch](https://docs.angularjs.org/api/ngTouch) should not be included, to avoid conflicts.
- *
- * Some browsers already remove the delay with certain settings, such as the CSS property
- * `touch-events: none` or with specific meta tag viewport values. However, each of these
- * browsers still handle clicks differently, such as when to fire off or cancel the event
- * (like scrolling when the target is a button, or holding a button down).
- * For browsers that already remove the 300ms delay, consider Ionic's tap system as a way to
- * normalize how clicks are handled across the various devices so there's an expected response
- * no matter what the device, platform or version. Additionally, Ionic will prevent
- * ghostclicks which even browsers that remove the delay still experience.
- *
- * In some cases, third-party libraries may also be working with touch events which can interfere
- * with the tap system. For example, mapping libraries like Google or Leaflet Maps often implement
- * a touch detection system which conflicts with Ionic's tap system.
- *
- * ### Disabling the tap system
- *
- * To disable the tap for an element and all of its children elements,
- * add the attribute `data-tap-disabled="true"`.
- *
- * ```html
- *
- * ```
- *
- * ### Additional Notes:
- *
- * - Ionic tap works with Ionic's JavaScript scrolling
- * - Elements can come and go from the DOM and Ionic tap doesn't keep adding and removing
- * listeners
- * - No "tap delay" after the first "tap" (you can tap as fast as you want, they all click)
- * - Minimal events listeners, only being added to document
- * - Correct focus in/out on each input type (select, textearea, range) on each platform/device
- * - Shows and hides virtual keyboard correctly for each platform/device
- * - Works with labels surrounding inputs
- * - Does not fire off a click if the user moves the pointer too far
- * - Adds and removes an 'activated' css class
- * - Multiple [unit tests](https://github.com/driftyco/ionic/blob/master/test/unit/utils/tap.unit.js) for each scenario
- *
- */
-/*
-
- IONIC TAP
- ---------------
- - Both touch and mouse events are added to the document.body on DOM ready
- - If a touch event happens, it does not use mouse event listeners
- - On touchend, if the distance between start and end was small, trigger a click
- - In the triggered click event, add a 'isIonicTap' property
- - The triggered click receives the same x,y coordinates as as the end event
- - On document.body click listener (with useCapture=true), only allow clicks with 'isIonicTap'
- - Triggering clicks with mouse events work the same as touch, except with mousedown/mouseup
- - Tapping inputs is disabled during scrolling
-*/
-
-var tapDoc; // the element which the listeners are on (document.body)
-var tapActiveEle; // the element which is active (probably has focus)
-var tapEnabledTouchEvents;
-var tapMouseResetTimer;
-var tapPointerMoved;
-var tapPointerStart;
-var tapTouchFocusedInput;
-var tapLastTouchTarget;
-var tapTouchMoveListener = 'touchmove';
-
-// how much the coordinates can be off between start/end, but still a click
-var TAP_RELEASE_TOLERANCE = 12; // default tolerance
-var TAP_RELEASE_BUTTON_TOLERANCE = 50; // button elements should have a larger tolerance
-
-var tapEventListeners = {
- 'click': tapClickGateKeeper,
-
- 'mousedown': tapMouseDown,
- 'mouseup': tapMouseUp,
- 'mousemove': tapMouseMove,
-
- 'touchstart': tapTouchStart,
- 'touchend': tapTouchEnd,
- 'touchcancel': tapTouchCancel,
- 'touchmove': tapTouchMove,
-
- 'focusin': tapFocusIn,
- 'focusout': tapFocusOut
-};
-
-Platform.ready().then(config => {
-
- if (config.setting('tapPolyfill')) {
- // console.log('Tap.register, tapPolyfill')
- // Tap.register(document);
- }
-
-});
-
-
-export let Tap = {
-
- register: function(ele) {
- tapDoc = ele;
-
- tapEventListener('click', true, true);
- tapEventListener('mouseup');
- tapEventListener('mousedown');
-
- tapEventListener('touchstart');
- tapEventListener('touchend');
- tapEventListener('touchcancel');
-
- tapEventListener('focusin');
- tapEventListener('focusout');
-
- return function() {
- for (var type in tapEventListeners) {
- tapEventListener(type, false);
- }
- tapDoc = null;
- tapActiveEle = null;
- tapEnabledTouchEvents = false;
- tapPointerMoved = false;
- tapPointerStart = null;
- };
- },
-
- ignoreScrollStart: function(e) {
- return (e.defaultPrevented) || // defaultPrevented has been assigned by another component handling the event
- (/^(file|range)$/i).test(e.target.type) ||
- (e.target.dataset ? e.target.dataset.preventScroll : e.target.getAttribute('data-prevent-scroll')) == 'true' || // manually set within an elements attributes
- (!!(/^(object|embed)$/i).test(e.target.tagName)) || // flash/movie/object touches should not try to scroll
- Tap.isElementTapDisabled(e.target); // check if this element, or an ancestor, has `data-tap-disabled` attribute
- },
-
- isTextInput: function(ele) {
- return !!ele &&
- (ele.tagName == 'TEXTAREA' ||
- ele.contentEditable === 'true' ||
- (ele.tagName == 'INPUT' && !(/^(radio|checkbox|range|file|submit|reset|color|image|button)$/i).test(ele.type)));
- },
-
- isDateInput: function(ele) {
- return !!ele &&
- (ele.tagName == 'INPUT' && (/^(date|time|datetime-local|month|week)$/i).test(ele.type));
- },
-
- isKeyboardElement: function(ele) {
- if (Platform.isDevice('ipad') ) {
- return Tap.isTextInput(ele) && !Tap.isDateInput(ele);
- } else {
- return Tap.isTextInput(ele) || ( !!ele && ele.tagName == "SELECT");
- }
- },
-
- isLabelWithTextInput: function(ele) {
- var container = tapContainingElement(ele, false);
-
- return !!container &&
- Tap.isTextInput(tapTargetElement(container));
- },
-
- containsOrIsTextInput: function(ele) {
- return Tap.isTextInput(ele) || Tap.isLabelWithTextInput(ele);
- },
-
- cloneFocusedInput: function(container) {
- if (Tap.hasCheckedClone) return;
- Tap.hasCheckedClone = true;
-
- dom.raf(function() {
- var focusInput = container.querySelector(':focus');
- if (Tap.isTextInput(focusInput)) {
- var clonedInput = focusInput.cloneNode(true);
-
- clonedInput.value = focusInput.value;
- clonedInput.classList.add('cloned-text-input');
- clonedInput.readOnly = true;
- if (focusInput.isContentEditable) {
- clonedInput.contentEditable = focusInput.contentEditable;
- clonedInput.innerHTML = focusInput.innerHTML;
- }
- focusInput.parentElement.insertBefore(clonedInput, focusInput);
- focusInput.classList.add('previous-input-focus');
-
- clonedInput.scrollTop = focusInput.scrollTop;
- }
- });
- },
-
- hasCheckedClone: false,
-
- removeClonedInputs: function(container) {
- Tap.hasCheckedClone = false;
-
- dom.raf(function() {
- var clonedInputs = container.querySelectorAll('.cloned-text-input');
- var previousInputFocus = container.querySelectorAll('.previous-input-focus');
- var x;
-
- for (x = 0; x < clonedInputs.length; x++) {
- clonedInputs[x].parentElement.removeChild(clonedInputs[x]);
- }
-
- for (x = 0; x < previousInputFocus.length; x++) {
- previousInputFocus[x].classList.remove('previous-input-focus');
- previousInputFocus[x].style.top = '';
-
- // TODO(tlancina): Get this back to life
- // if ( ionic.keyboard.isOpen && !ionic.keyboard.isClosing ) {
- // previousInputFocus[x].focus();
- // }
- }
- });
- },
-
- requiresNativeClick: function(ele) {
- if (!ele || ele.disabled || (/^(file|range)$/i).test(ele.type) || (/^(object|video)$/i).test(ele.tagName) || Tap.isLabelContainingFileInput(ele)) {
- return true;
- }
- return Tap.isElementTapDisabled(ele);
- },
-
- isLabelContainingFileInput: function(ele) {
- var lbl = tapContainingElement(ele);
- if (lbl.tagName !== 'LABEL') return false;
- var fileInput = lbl.querySelector('input[type=file]');
- if (fileInput && fileInput.disabled === false) return true;
- return false;
- },
-
- isElementTapDisabled: function(ele) {
- if (ele && ele.nodeType === 1) {
- var element = ele;
- while (element) {
- if ((element.dataset ? element.dataset.tapDisabled : element.getAttribute('data-tap-disabled')) == 'true') {
- return true;
- }
- element = element.parentElement;
- }
- }
- return false;
- },
-
- setTolerance: function(releaseTolerance, releaseButtonTolerance) {
- TAP_RELEASE_TOLERANCE = releaseTolerance;
- TAP_RELEASE_BUTTON_TOLERANCE = releaseButtonTolerance;
- },
-
- cancelClick: function() {
- // used to cancel any simulated clicks which may happen on a touchend/mouseup
- // gestures uses this method within its tap and hold events
- tapPointerMoved = true;
- },
-
- pointerCoord: function(event) {
- // This method can get coordinates for both a mouse click
- // or a touch depending on the given event
- var c = { x: 0, y: 0 };
- if (event) {
- var touches = event.touches && event.touches.length ? event.touches : [event];
- var e = (event.changedTouches && event.changedTouches[0]) || touches[0];
- if (e) {
- c.x = e.clientX || e.pageX || 0;
- c.y = e.clientY || e.pageY || 0;
- }
- }
- return c;
- }
-
-};
-
-function tapEventListener(type, enable, useCapture) {
- if (enable !== false) {
- tapDoc.addEventListener(type, tapEventListeners[type], useCapture);
- } else {
- tapDoc.removeEventListener(type, tapEventListeners[type]);
- }
-}
-
-function tapClick(e) {
- // simulate a normal click by running the element's click method then focus on it
- var container = tapContainingElement(e.target);
- var ele = tapTargetElement(container);
-
- if (Tap.requiresNativeClick(ele) || tapPointerMoved) return false;
-
- var c = Tap.pointerCoord(e);
-
- //console.log('tapClick', e.type, ele.tagName, '('+c.x+','+c.y+')');
- triggerMouseEvent('click', ele, c.x, c.y);
-
- // if it's an input, focus in on the target, otherwise blur
- tapHandleFocus(ele);
-}
-
-function triggerMouseEvent(type, ele, x, y) {
- // using initMouseEvent instead of MouseEvent for our Android friends
- var clickEvent = document.createEvent("MouseEvents");
- clickEvent.initMouseEvent(type, true, true, window, 1, 0, 0, x, y, false, false, false, false, 0, null);
- clickEvent.isIonicTap = true;
- ele.dispatchEvent(clickEvent);
-}
-
-function tapClickGateKeeper(e) {
- //console.log('click ' + Date.now() + ' isIonicTap: ' + (e.isIonicTap ? true : false));
- if (e.target.type == 'submit' && e.detail === 0) {
- // do not prevent click if it came from an "Enter" or "Go" keypress submit
- return null;
- }
-
- // do not allow through any click events that were not created by Tap
-
- // TODO(mlynch): re-enable this check
- //if ((ionic.scroll.isScrolling && Tap.containsOrIsTextInput(e.target)) || (!e.isIonicTap && !Tap.requiresNativeClick(e.target))) {
- if (!e.isIonicTap && !Tap.requiresNativeClick(e.target)) {
- //console.log('clickPrevent', e.target.tagName);
- e.stopPropagation();
-
- if (!Tap.isLabelWithTextInput(e.target)) {
- // labels clicks from native should not preventDefault othersize keyboard will not show on input focus
- e.preventDefault();
- }
- return false;
- }
-}
-
-// MOUSE
-function tapMouseDown(e) {
- //console.log('mousedown ' + Date.now());
- if (e.isIonicTap || tapIgnoreEvent(e)) return null;
-
- if (tapEnabledTouchEvents) {
- console.log('mousedown', 'stop event');
- e.stopPropagation();
-
- if ((!Tap.isTextInput(e.target) || tapLastTouchTarget !== e.target) && !(/^(select|option)$/i).test(e.target.tagName)) {
- // If you preventDefault on a text input then you cannot move its text caret/cursor.
- // Allow through only the text input default. However, without preventDefault on an
- // input the 300ms delay can change focus on inputs after the keyboard shows up.
- // The focusin event handles the chance of focus changing after the keyboard shows.
- e.preventDefault();
- }
-
- return false;
- }
-
- tapPointerMoved = false;
- tapPointerStart = Tap.pointerCoord(e);
-
- tapEventListener('mousemove');
-
- // TODO(mlynch): re-enable
- // ionic.activator.start(e);
-}
-
-function tapMouseUp(e) {
- //console.log("mouseup " + Date.now());
- if (tapEnabledTouchEvents) {
- e.stopPropagation();
- e.preventDefault();
- return false;
- }
-
- if (tapIgnoreEvent(e) || (/^(select|option)$/i).test(e.target.tagName)) return false;
-
- if (!tapHasPointerMoved(e)) {
- tapClick(e);
- }
- tapEventListener('mousemove', false);
- // TODO(mlynch): re-enable
- // ionic.activator.end();
- tapPointerMoved = false;
-}
-
-function tapMouseMove(e) {
- if (tapHasPointerMoved(e)) {
- tapEventListener('mousemove', false);
- // TODO(mlynch): re-enable
- // ionic.activator.end();
- tapPointerMoved = true;
- return false;
- }
-}
-
-
-// TOUCH
-function tapTouchStart(e) {
- //console.log("touchstart " + Date.now());
- if (tapIgnoreEvent(e)) return;
-
- tapPointerMoved = false;
-
- tapEnableTouchEvents();
- tapPointerStart = Tap.pointerCoord(e);
-
- tapEventListener(tapTouchMoveListener);
- // TODO(mlynch): re-enable
- //ionic.activator.start(e);
-
- if (Tap.isLabelWithTextInput(e.target)) {
- // if the tapped element is a label, which has a child input
- // then preventDefault so iOS doesn't ugly auto scroll to the input
- // but do not prevent default on Android or else you cannot move the text caret
- // and do not prevent default on Android or else no virtual keyboard shows up
-
- var textInput = tapTargetElement(tapContainingElement(e.target));
- if (textInput !== tapActiveEle) {
- // don't preventDefault on an already focused input or else iOS's text caret isn't usable
- e.preventDefault();
- }
- }
-}
-
-function tapTouchEnd(e) {
- //console.log('touchend ' + Date.now());
- if (tapIgnoreEvent(e)) return;
-
- tapEnableTouchEvents();
- if (!tapHasPointerMoved(e)) {
- tapClick(e);
-
- if ((/^(select|option)$/i).test(e.target.tagName)) {
- e.preventDefault();
- }
- }
-
- tapLastTouchTarget = e.target;
- tapTouchCancel();
-}
-
-function tapTouchMove(e) {
- if (tapHasPointerMoved(e)) {
- tapPointerMoved = true;
- tapEventListener(tapTouchMoveListener, false);
-
- // TODO(mlynch): re-enable
- // ionic.activator.end();
- return false;
- }
-}
-
-function tapTouchCancel() {
- tapEventListener(tapTouchMoveListener, false);
- // TODO(mlynch): re-enable
- // ionic.activator.end();
- tapPointerMoved = false;
-}
-
-function tapEnableTouchEvents() {
- tapEnabledTouchEvents = true;
- clearTimeout(tapMouseResetTimer);
- tapMouseResetTimer = setTimeout(function() {
- tapEnabledTouchEvents = false;
- }, 600);
-}
-
-function tapIgnoreEvent(e) {
- if (e.isTapHandled) return true;
- e.isTapHandled = true;
-
- // TODO(mlynch): re-enable
- /*
- if (ionic.scroll.isScrolling && Tap.containsOrIsTextInput(e.target)) {
- e.preventDefault();
- return true;
- }
- */
- if (Tap.containsOrIsTextInput(e.target)) {
- e.preventDefault();
- return true;
- }
-}
-
-function tapHandleFocus(ele) {
- tapTouchFocusedInput = null;
-
- var triggerFocusIn = false;
-
- if (ele.tagName == 'SELECT') {
- // trick to force Android options to show up
- triggerMouseEvent('mousedown', ele, 0, 0);
- ele.focus && ele.focus();
- triggerFocusIn = true;
-
- } else if (tapActiveElement() === ele) {
- // already is the active element and has focus
- triggerFocusIn = true;
-
- } else if ((/^(input|textarea)$/i).test(ele.tagName) || ele.isContentEditable) {
- triggerFocusIn = true;
- ele.focus && ele.focus();
- ele.value = ele.value;
- if (tapEnabledTouchEvents) {
- tapTouchFocusedInput = ele;
- }
-
- } else {
- tapFocusOutActive();
- }
-
- if (triggerFocusIn) {
- tapActiveElement(ele);
- // ionic.trigger('ionic.focusin', {
- // target: ele
- // }, true);
- }
-}
-
-function tapFocusOutActive() {
- var ele = tapActiveElement();
- if (ele && ((/^(input|textarea|select)$/i).test(ele.tagName) || ele.isContentEditable)) {
- console.log('tapFocusOutActive', ele.tagName);
- ele.blur();
- }
- tapActiveElement(null);
-}
-
-function tapFocusIn(e) {
- //console.log('focusin ' + Date.now());
- // Because a text input doesn't preventDefault (so the caret still works) there's a chance
- // that its mousedown event 300ms later will change the focus to another element after
- // the keyboard shows up.
-
- if (tapEnabledTouchEvents &&
- Tap.isTextInput(tapActiveElement()) &&
- Tap.isTextInput(tapTouchFocusedInput) &&
- tapTouchFocusedInput !== e.target) {
-
- // 1) The pointer is from touch events
- // 2) There is an active element which is a text input
- // 3) A text input was just set to be focused on by a touch event
- // 4) A new focus has been set, however the target isn't the one the touch event wanted
- console.log('focusin', 'tapTouchFocusedInput');
- tapTouchFocusedInput.focus();
- tapTouchFocusedInput = null;
- }
- //ionic.scroll.isScrolling = false;
-}
-
-function tapFocusOut() {
- //console.log("focusout");
- tapActiveElement(null);
-}
-
-function tapActiveElement(ele) {
- if (arguments.length) {
- tapActiveEle = ele;
- }
- return tapActiveEle || document.activeElement;
-}
-
-function tapHasPointerMoved(endEvent) {
- if (!endEvent || endEvent.target.nodeType !== 1 || !tapPointerStart || (tapPointerStart.x === 0 && tapPointerStart.y === 0)) {
- return false;
- }
- var endCoordinates = Tap.pointerCoord(endEvent);
-
- var hasClassList = !!(endEvent.target.classList && endEvent.target.classList.contains &&
- typeof endEvent.target.classList.contains === 'function');
- var releaseTolerance = hasClassList && endEvent.target.classList.contains('button') ?
- TAP_RELEASE_BUTTON_TOLERANCE :
- TAP_RELEASE_TOLERANCE;
-
- return Math.abs(tapPointerStart.x - endCoordinates.x) > releaseTolerance ||
- Math.abs(tapPointerStart.y - endCoordinates.y) > releaseTolerance;
-}
-
-function tapContainingElement(ele, allowSelf) {
- var climbEle = ele;
- for (var x = 0; x < 6; x++) {
- if (!climbEle) break;
- if (climbEle.tagName === 'LABEL') return climbEle;
- climbEle = climbEle.parentElement;
- }
- if (allowSelf !== false) return ele;
-}
-
-function tapTargetElement(ele) {
- if (ele && ele.tagName === 'LABEL') {
- if (ele.control) return ele.control;
-
- // older devices do not support the "control" property
- if (ele.querySelector) {
- var control = ele.querySelector('input,textarea,select');
- if (control) return control;
- }
- }
- return ele;
-}