Skip to content

Commit 05a6d7c

Browse files
author
Adam Bradley
committed
fix(tap): input[file] clicks within ion-content, closes #1237
1 parent 517658e commit 05a6d7c

File tree

4 files changed

+59
-49
lines changed

4 files changed

+59
-49
lines changed

Diff for: js/utils/activator.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// when an element is touched/clicked, it climbs up a few
1515
// parents to see if it is an .item or .button element
1616
ionic.requestAnimationFrame(function(){
17-
if (tapRequiresNativeClick(e.target)) return;
17+
if ( ionic.tap.requiresNativeClick(e.target) ) return;
1818
var ele = e.target;
1919
var eleToActivate;
2020

Diff for: js/utils/tap.js

+19-19
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ ionic.tap = {
8484
ignoreScrollStart: function(e) {
8585
return (e.defaultPrevented) || // defaultPrevented has been assigned by another component handling the event
8686
(e.target.isContentEditable) ||
87-
(e.target.type === 'range') ||
87+
(/file|range/i).test(e.target.type) ||
8888
(e.target.dataset ? e.target.dataset.preventScroll : e.target.getAttribute('data-prevent-default')) == 'true' || // manually set within an elements attributes
8989
(!!(/object|embed/i).test(e.target.tagName)); // flash/movie/object touches should not try to scroll
9090
},
@@ -149,6 +149,22 @@ ionic.tap = {
149149
previousInputFocus[x].focus();
150150
}
151151
});
152+
},
153+
154+
requiresNativeClick: function(ele) {
155+
if(!ele || ele.disabled || (/file|range/i).test(ele.type) || (/object|video/i).test(ele.tagName) ) {
156+
return true;
157+
}
158+
if(ele.nodeType === 1) {
159+
var element = ele;
160+
while(element) {
161+
if( (element.dataset ? element.dataset.tapDisabled : element.getAttribute('data-tap-disabled')) == 'true' ) {
162+
return true;
163+
}
164+
element = element.parentElement;
165+
}
166+
}
167+
return false;
152168
}
153169

154170
};
@@ -166,7 +182,7 @@ function tapClick(e) {
166182
var container = tapContainingElement(e.target);
167183
var ele = tapTargetElement(container);
168184

169-
if( tapRequiresNativeClick(ele) || tapPointerMoved ) return false;
185+
if( ionic.tap.requiresNativeClick(ele) || tapPointerMoved ) return false;
170186

171187
var c = getPointerCoordinates(e);
172188

@@ -193,7 +209,7 @@ function tapClickGateKeeper(e) {
193209

194210
// do not allow through any click events that were not created by ionic.tap
195211
if( (ionic.scroll.isScrolling && ionic.tap.containsOrIsTextInput(e.target) ) ||
196-
(!e.isIonicTap && !tapRequiresNativeClick(e.target)) ) {
212+
(!e.isIonicTap && !ionic.tap.requiresNativeClick(e.target)) ) {
197213
console.debug('clickPrevent', e.target.tagName);
198214
e.stopPropagation();
199215

@@ -205,22 +221,6 @@ function tapClickGateKeeper(e) {
205221
}
206222
}
207223

208-
function tapRequiresNativeClick(ele) {
209-
if(!ele || ele.disabled || (/file|range/i).test(ele.type) || (/object|video/i).test(ele.tagName) ) {
210-
return true;
211-
}
212-
if(ele.nodeType === 1) {
213-
var element = ele;
214-
while(element) {
215-
if( (element.dataset ? element.dataset.tapDisabled : element.getAttribute('data-tap-disabled')) == 'true' ) {
216-
return true;
217-
}
218-
element = element.parentElement;
219-
}
220-
}
221-
return false;
222-
}
223-
224224
// MOUSE
225225
function tapMouseDown(e) {
226226
if(e.isIonicTap || tapIgnoreEvent(e)) return;

Diff for: test/unit/angular/service/activator.unit.js renamed to test/unit/utils/activator.unit.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ describe('Ionic Element Activator', function() {
44
window.setTimeout = ionic.requestAnimationFrame = function(cb) { cb(); };
55
});
66

7-
it('should not active an <a> if tapRequiresNativeClick is true', function() {
8-
spyOn(window, 'tapRequiresNativeClick').andReturn(true);
7+
it('should not active an <a> if ionic.tap.requiresNativeClick is true', function() {
8+
spyOn(ionic.tap, 'requiresNativeClick').andReturn(true);
99
var e = { target: document.createElement('a') };
1010
ionic.activator.start(e);
1111
expect(e.target.classList.contains('activated')).toEqual(false);

Diff for: test/unit/utils/tap.unit.js

+37-27
Original file line numberDiff line numberDiff line change
@@ -549,60 +549,60 @@ describe('Ionic Tap', function() {
549549
expect( tapClick(e) ).toEqual(false);
550550
});
551551

552-
it('Should tapRequiresNativeClick for invalid element', function() {
553-
expect( tapRequiresNativeClick( null ) ).toEqual(true);
552+
it('Should ionic.tap.requiresNativeClick for invalid element', function() {
553+
expect( ionic.tap.requiresNativeClick( null ) ).toEqual(true);
554554
});
555555

556-
it('Should tapRequiresNativeClick for input.disabled', function() {
556+
it('Should ionic.tap.requiresNativeClick for input.disabled', function() {
557557
var ele = document.createElement('input');
558558
ele.disabled = true;
559-
expect( tapRequiresNativeClick( ele ) ).toEqual(true);
559+
expect( ionic.tap.requiresNativeClick( ele ) ).toEqual(true);
560560
});
561561

562-
it('Should tapRequiresNativeClick for input[range]', function() {
562+
it('Should ionic.tap.requiresNativeClick for input[range]', function() {
563563
var ele = document.createElement('input');
564564
ele.type = 'range';
565-
expect( tapRequiresNativeClick( ele ) ).toEqual(true);
565+
expect( ionic.tap.requiresNativeClick( ele ) ).toEqual(true);
566566
});
567567

568-
it('Should tapRequiresNativeClick for input[file]', function() {
568+
it('Should ionic.tap.requiresNativeClick for input[file]', function() {
569569
var ele = document.createElement('input');
570570
ele.type = 'file';
571-
expect( tapRequiresNativeClick( ele ) ).toEqual(true);
571+
expect( ionic.tap.requiresNativeClick( ele ) ).toEqual(true);
572572
});
573573

574-
it('Should tapRequiresNativeClick for video element', function() {
574+
it('Should ionic.tap.requiresNativeClick for video element', function() {
575575
var ele = document.createElement('video');
576-
expect( tapRequiresNativeClick( ele ) ).toEqual(true);
576+
expect( ionic.tap.requiresNativeClick( ele ) ).toEqual(true);
577577
});
578578

579-
it('Should tapRequiresNativeClick for object element', function() {
579+
it('Should ionic.tap.requiresNativeClick for object element', function() {
580580
var ele = document.createElement('object');
581-
expect( tapRequiresNativeClick( ele ) ).toEqual(true);
581+
expect( ionic.tap.requiresNativeClick( ele ) ).toEqual(true);
582582
});
583583

584-
it('Should not tapRequiresNativeClick for common inputs', function() {
584+
it('Should not ionic.tap.requiresNativeClick for common inputs', function() {
585585
var inputTypes = ['text', 'email', 'search', 'tel', 'number', 'date', 'month', 'password', null, undefined, ''];
586586
for(var x=0; x<inputTypes.length; x++) {
587587
var targetEle = document.createElement('input');
588588
targetEle.type = inputTypes[x];
589-
expect( tapRequiresNativeClick(targetEle) ).toEqual(false);
589+
expect( ionic.tap.requiresNativeClick(targetEle) ).toEqual(false);
590590
}
591-
expect( tapRequiresNativeClick( document.createElement('img') ) ).toEqual(false);
592-
expect( tapRequiresNativeClick( document.createElement('div') ) ).toEqual(false);
593-
expect( tapRequiresNativeClick( document.createElement('textarea') ) ).toEqual(false);
594-
expect( tapRequiresNativeClick( document.createElement('select') ) ).toEqual(false);
591+
expect( ionic.tap.requiresNativeClick( document.createElement('img') ) ).toEqual(false);
592+
expect( ionic.tap.requiresNativeClick( document.createElement('div') ) ).toEqual(false);
593+
expect( ionic.tap.requiresNativeClick( document.createElement('textarea') ) ).toEqual(false);
594+
expect( ionic.tap.requiresNativeClick( document.createElement('select') ) ).toEqual(false);
595595
});
596596

597-
it('Should tapRequiresNativeClick for an element with data-tap-disabled attribute', function() {
597+
it('Should ionic.tap.requiresNativeClick for an element with data-tap-disabled attribute', function() {
598598
var div = document.createElement('div');
599-
expect( tapRequiresNativeClick( div ) ).toEqual(false);
599+
expect( ionic.tap.requiresNativeClick( div ) ).toEqual(false);
600600

601601
div.setAttribute('data-tap-disabled', "true");
602-
expect( tapRequiresNativeClick( div ) ).toEqual(true);
602+
expect( ionic.tap.requiresNativeClick( div ) ).toEqual(true);
603603
});
604604

605-
it('Should tapRequiresNativeClick for an element with one of its parents with data-tap-disabled attribute', function() {
605+
it('Should ionic.tap.requiresNativeClick for an element with one of its parents with data-tap-disabled attribute', function() {
606606
var div1 = document.createElement('div');
607607
var div2 = document.createElement('div');
608608
var div3 = document.createElement('div');
@@ -616,11 +616,11 @@ describe('Ionic Tap', function() {
616616

617617
div2.setAttribute('data-tap-disabled', "true");
618618

619-
expect( tapRequiresNativeClick( div1 ) ).toEqual(false);
620-
expect( tapRequiresNativeClick( div2 ) ).toEqual(true);
621-
expect( tapRequiresNativeClick( div3 ) ).toEqual(true);
622-
expect( tapRequiresNativeClick( div4 ) ).toEqual(true);
623-
expect( tapRequiresNativeClick( div5 ) ).toEqual(true);
619+
expect( ionic.tap.requiresNativeClick( div1 ) ).toEqual(false);
620+
expect( ionic.tap.requiresNativeClick( div2 ) ).toEqual(true);
621+
expect( ionic.tap.requiresNativeClick( div3 ) ).toEqual(true);
622+
expect( ionic.tap.requiresNativeClick( div4 ) ).toEqual(true);
623+
expect( ionic.tap.requiresNativeClick( div5 ) ).toEqual(true);
624624
});
625625

626626
it('Should not allow a click that has an textarea target but not created by tapClick', function() {
@@ -861,6 +861,16 @@ describe('Ionic Tap', function() {
861861
expect( ionic.tap.ignoreScrollStart(e) ).toEqual(true);
862862
});
863863

864+
it('Should prevent scrolling because the target is input[file]', function() {
865+
var target = document.createElement('input');
866+
target.type = 'file';
867+
var e = {
868+
target: target,
869+
defaultPrevented: true
870+
};
871+
expect( ionic.tap.ignoreScrollStart(e) ).toEqual(true);
872+
});
873+
864874
it('Should prevent scrolling because the target is input[range]', function() {
865875
var target = document.createElement('input');
866876
target.type = 'range';

0 commit comments

Comments
 (0)