mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
the activator
This commit is contained in:
@ -36,7 +36,6 @@ $action-menu-ios-icon-font-size: 1.4em !default;
|
||||
|
||||
background: transparent;
|
||||
|
||||
&:active,
|
||||
&.activated {
|
||||
background: $action-menu-ios-background-active;
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ $action-menu-md-icon-font-size: 2.4rem !default;
|
||||
font-weight: normal;
|
||||
min-height: $action-menu-md-height;
|
||||
|
||||
&:active,
|
||||
&.activated {
|
||||
background: $action-menu-md-background-active;
|
||||
}
|
||||
|
94
ionic/components/app/test/tap/index.ts
Normal file
94
ionic/components/app/test/tap/index.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class IonicApp {}
|
||||
|
||||
|
||||
function onEvent(ev) {
|
||||
var c = pointerCoord(ev);
|
||||
var l = '(' + c.x + ',' + c.y + ')';
|
||||
if (ev.isIonicTap) {
|
||||
l += ' isIonicTap';
|
||||
}
|
||||
console.debug(ev.type, l);
|
||||
}
|
||||
|
||||
function pointerCoord(ev) {
|
||||
// get coordinates for either a mouse click
|
||||
// or a touch depending on the given event
|
||||
let c = { x: 0, y: 0 };
|
||||
if (ev) {
|
||||
const touches = ev.touches && ev.touches.length ? ev.touches : [ev];
|
||||
const e = (ev.changedTouches && ev.changedTouches[0]) || touches[0];
|
||||
if (e) {
|
||||
c.x = e.clientX || e.pageX || 0;
|
||||
c.y = e.clientY || e.pageY || 0;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
document.addEventListener('touchstart', onEvent);
|
||||
document.addEventListener('touchcancel', onEvent);
|
||||
document.addEventListener('touchend', onEvent);
|
||||
document.addEventListener('mousedown', onEvent);
|
||||
document.addEventListener('mouseup', onEvent);
|
||||
document.addEventListener('click', onEvent);
|
||||
|
||||
|
||||
var msgs = [];
|
||||
var index = 0;
|
||||
var timeId;
|
||||
var winConsoleError = console.error;
|
||||
|
||||
console.error = function() {
|
||||
winConsoleError.apply(this, arguments);
|
||||
var args = ['ERROR!'];
|
||||
for (var i = 0, j = arguments.length; i < j; i++){
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
console.debug.apply(this, args);
|
||||
};
|
||||
|
||||
console.debug = function() {
|
||||
index++;
|
||||
var msg = [];
|
||||
msg.push(index);
|
||||
for (var i = 0, j = arguments.length; i < j; i++){
|
||||
msg.push(arguments[i]);
|
||||
}
|
||||
msg.push(getTime());
|
||||
|
||||
msg = msg.join(', ');
|
||||
|
||||
if(arguments[0] === 'ERROR!') msg = '<span style="color:red;font-weight:bold">' + msg + '</span>';
|
||||
|
||||
if(arguments[0] === 'touchstart') msg = '<span style="color:blue">' + msg + '</span>';
|
||||
if(arguments[0] === 'touchend') msg = '<span style="color:darkblue">' + msg + '</span>';
|
||||
|
||||
if(arguments[0] === 'mousedown') msg = '<span style="color:red">' + msg + '</span>';
|
||||
if(arguments[0] === 'mouseup') msg = '<span style="color:maroon">' + msg + '</span>';
|
||||
|
||||
if(arguments[0] === 'click') msg = '<span style="color:purple">' + msg + '</span>';
|
||||
|
||||
msgs.unshift( msg );
|
||||
|
||||
if(msgs.length > 25) {
|
||||
msgs.splice(25);
|
||||
}
|
||||
|
||||
// do this so we try not to interfere with the device performance
|
||||
clearTimeout(timeId);
|
||||
timeId = setTimeout(function(){
|
||||
document.getElementById('logs').innerHTML = msgs.join('<br>');
|
||||
}, 100);
|
||||
|
||||
}
|
||||
|
||||
function getTime() {
|
||||
var d = new Date();
|
||||
return d.getSeconds() + '.' + d.getMilliseconds();
|
||||
}
|
6
ionic/components/app/test/tap/main.html
Normal file
6
ionic/components/app/test/tap/main.html
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
<button primary>
|
||||
<div><div><p>TAP ME</p></div></div>
|
||||
</button>
|
||||
|
||||
<div id="logs"></div>
|
@ -247,7 +247,6 @@ a[button] {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.activated {
|
||||
opacity: 1;
|
||||
background-color: darken($bg-color, 12%);
|
||||
|
@ -1,16 +1,15 @@
|
||||
import {Directive, ElementRef, Optional, Ancestor, onDestroy} from 'angular2/angular2';
|
||||
import {Directive, ElementRef, Optional, Ancestor, onDestroy, NgZone} from 'angular2/angular2';
|
||||
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {Gesture} from '../../gestures/gesture';
|
||||
import {Activator} from '../../util/activator';
|
||||
import * as dom from '../../util/dom';
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'button,[button]'
|
||||
})
|
||||
export class Button {
|
||||
constructor(elementRef: ElementRef, config: IonicConfig) {
|
||||
}
|
||||
}
|
||||
export class Button {}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: '[tap-disabled]'
|
||||
@ -19,43 +18,126 @@ export class TapDisabled {}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'a,button,[tappable]'
|
||||
selector: 'a,button,[tappable]',
|
||||
host: {
|
||||
'(^touchstart)': 'touchStart($event)',
|
||||
'(^touchend)': 'touchEnd($event)',
|
||||
'(^touchcancel)': 'pointerCancel()',
|
||||
'(^mousedown)': 'mouseDown($event)',
|
||||
'(^mouseup)': 'mouseUp($event)',
|
||||
'(^click)': 'click($event)',
|
||||
}
|
||||
})
|
||||
export class TapClick {
|
||||
|
||||
constructor(
|
||||
elementRef: ElementRef,
|
||||
config: IonicConfig,
|
||||
ngZone: NgZone,
|
||||
@Optional() @Ancestor() tapDisabled: TapDisabled
|
||||
) {
|
||||
this.ele = elementRef.nativeElement;
|
||||
this.tapEnabled = !tapDisabled;
|
||||
this.tapPolyfill = config.setting('tapPolyfill');
|
||||
this.zone = ngZone;
|
||||
|
||||
if (config.setting('tapPolyfill') && !this.tapGesture && !tapDisabled) {
|
||||
this.tapGesture = new Gesture(elementRef.nativeElement);
|
||||
this.tapGesture.listen();
|
||||
let self = this;
|
||||
self.pointerMove = function(ev) {
|
||||
let moveCoord = dom.pointerCoord(ev);
|
||||
console.log('pointerMove', moveCoord, self.start)
|
||||
|
||||
this.tapGesture.on('tap', (gestureEv) => {
|
||||
this.onTap(gestureEv.gesture.srcEvent);
|
||||
if ( dom.hasPointerMoved(10, self.start, moveCoord) ) {
|
||||
self.pointerCancel();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
touchStart(ev) {
|
||||
this.pointerStart(ev);
|
||||
}
|
||||
|
||||
touchEnd(ev) {
|
||||
let self = this;
|
||||
|
||||
if (this.tapPolyfill && this.tapEnabled) {
|
||||
|
||||
let endCoord = dom.pointerCoord(ev);
|
||||
|
||||
this.disableClick = true;
|
||||
this.zone.runOutsideAngular(() => {
|
||||
clearTimeout(self.disableTimer);
|
||||
self.disableTimer = setTimeout(() => {
|
||||
self.disableClick = false;
|
||||
}, 600);
|
||||
});
|
||||
|
||||
if ( this.start && !dom.hasPointerMoved(3, this.start, endCoord) ) {
|
||||
let clickEvent = document.createEvent('MouseEvents');
|
||||
clickEvent.initMouseEvent('click', true, true, window, 1, 0, 0, endCoord.x, endCoord.y, false, false, false, false, 0, null);
|
||||
clickEvent.isIonicTap = true;
|
||||
this.ele.dispatchEvent(clickEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onTap(ev) {
|
||||
if (ev && this.tapGesture) {
|
||||
this.pointerEnd();
|
||||
}
|
||||
|
||||
mouseDown(ev) {
|
||||
if (this.disableClick) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
let c = dom.pointerCoord(ev);
|
||||
} else {
|
||||
this.pointerStart(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);
|
||||
mouseUp(ev) {
|
||||
if (this.disableClick) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
this.pointerEnd();
|
||||
}
|
||||
|
||||
pointerStart(ev) {
|
||||
this.start = dom.pointerCoord(ev);
|
||||
|
||||
this.zone.runOutsideAngular(() => {
|
||||
Activator.start(ev.currentTarget);
|
||||
Activator.moveListeners(this.pointerMove, true);
|
||||
});
|
||||
}
|
||||
|
||||
pointerEnd() {
|
||||
this.zone.runOutsideAngular(() => {
|
||||
Activator.end();
|
||||
Activator.moveListeners(this.pointerMove, false);
|
||||
});
|
||||
}
|
||||
|
||||
pointerCancel() {
|
||||
this.start = null;
|
||||
|
||||
this.zone.runOutsideAngular(() => {
|
||||
Activator.clear();
|
||||
Activator.moveListeners(this.pointerMove, false);
|
||||
});
|
||||
}
|
||||
|
||||
click(ev) {
|
||||
if (!ev.isIonicTap) {
|
||||
if (this.disableClick || !this.start) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.tapGesture && this.tapGesture.destroy();
|
||||
this.ele = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ $button-material-border-radius: 3px !default;
|
||||
background-color 0.2s $animation-curve-default,
|
||||
color 0.2s $animation-curve-default;
|
||||
|
||||
&:active, &.activated {
|
||||
&.activated {
|
||||
box-shadow: $button-material-box-shadow-active;
|
||||
}
|
||||
|
||||
@ -68,7 +68,6 @@ $button-material-border-radius: 3px !default;
|
||||
}
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.activated {
|
||||
opacity: 1;
|
||||
background-color: get-color($color, base);
|
||||
@ -84,7 +83,7 @@ $button-material-border-radius: 3px !default;
|
||||
background-color: get-color($color, base);
|
||||
}
|
||||
}
|
||||
&:active,
|
||||
|
||||
&.activated {
|
||||
opacity: 1;
|
||||
background: transparent;
|
||||
@ -98,10 +97,11 @@ $button-material-border-radius: 3px !default;
|
||||
color: get-color($color, inverse);
|
||||
}
|
||||
|
||||
&:hover, &.hover {
|
||||
&:hover,
|
||||
&.hover {
|
||||
background-color: rgba(158, 158, 158, 0.2);
|
||||
}
|
||||
&:active, &.active {
|
||||
&:activated {
|
||||
background-color: rgba(158, 158, 158, 0.4);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
$toolbar-material-title-font-size: 2rem !default;
|
||||
$toolbar-material-button-font-size: 1.8rem !default;
|
||||
$toolbar-material-button-font-size: 1.4rem !default;
|
||||
|
||||
|
||||
.toolbar[mode="md"] {
|
||||
|
61
ionic/util/activator.ts
Normal file
61
ionic/util/activator.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import {raf} from './dom';
|
||||
|
||||
var queueElements = {}; // elements that should get an active state in XX milliseconds
|
||||
var activeElements = {}; // elements that are currently active
|
||||
var keyId = 0; // a counter for unique keys for the above ojects
|
||||
var ACTIVATED_CLASS = 'activated';
|
||||
var DEACTIVATE_TIMEOUT = 180;
|
||||
|
||||
|
||||
export class Activator {
|
||||
|
||||
static start(ele) {
|
||||
queueElements[++keyId] = ele;
|
||||
if (keyId > 9) keyId = 0;
|
||||
raf(Activator.activate);
|
||||
}
|
||||
|
||||
static activate() {
|
||||
// activate all elements in the queue
|
||||
for (var key in queueElements) {
|
||||
if (queueElements[key]) {
|
||||
queueElements[key].classList.add(ACTIVATED_CLASS);
|
||||
activeElements[key] = queueElements[key];
|
||||
}
|
||||
}
|
||||
queueElements = {};
|
||||
}
|
||||
|
||||
static end() {
|
||||
setTimeout(Activator.clear, DEACTIVATE_TIMEOUT);
|
||||
}
|
||||
|
||||
static clear() {
|
||||
// clear out any elements that are queued to be set to active
|
||||
queueElements = {};
|
||||
|
||||
// in the next frame, remove the active class from all active elements
|
||||
raf(Activator.deactivate);
|
||||
}
|
||||
|
||||
static deactivate() {
|
||||
|
||||
for (var key in activeElements) {
|
||||
if (activeElements[key]) {
|
||||
activeElements[key].classList.remove(ACTIVATED_CLASS);
|
||||
}
|
||||
delete activeElements[key];
|
||||
}
|
||||
}
|
||||
|
||||
static moveListeners(pointerMove, shouldAdd) {
|
||||
document.removeEventListener('touchmove', pointerMove);
|
||||
document.removeEventListener('mousemove', pointerMove);
|
||||
|
||||
if (shouldAdd) {
|
||||
document.addEventListener('touchmove', pointerMove);
|
||||
document.addEventListener('mousemove', pointerMove);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -174,9 +174,9 @@ export function pointerCoord(ev) {
|
||||
return c;
|
||||
}
|
||||
|
||||
export function hasPointerMoved(tolerance, startCoord, endCoord) {
|
||||
export function hasPointerMoved(threshold, startCoord, endCoord) {
|
||||
return startCoord && endCoord &&
|
||||
(Math.abs(startCoord.x - endCoord.x) > tolerance || Math.abs(startCoord.y - endCoord.y) > tolerance);
|
||||
(Math.abs(startCoord.x - endCoord.x) > threshold || Math.abs(startCoord.y - endCoord.y) > threshold);
|
||||
}
|
||||
|
||||
export function hasFocus(ele) {
|
||||
|
Reference in New Issue
Block a user