问题
I\'m using this HTML code:
<form action=\"#\" method=\"post\">
<fieldset>
<label class=\"desc\" id=\"title10\" for=\"Field10\">
How many children do you have?
</label>
<select id=\"Field10\" name=\"Field10\" class=\"field select large\" tabindex=\"5\">
<option value=\"0\" selected=\"selected\">0 </option>
<option value=\"1\">1 </option>
<option value=\"2\">2 </option>
<option value=\"3\">3 </option>
<option value=\"4\">4 </option>
<option value=\"5\">5 </option>
<option value=\"6\">6 </option>
<option value=\"7\">7 </option>
<option value=\"8\">8 </option>
<option value=\"9\">9 </option>
</select>
<input type=\"submit\" value=\"Send message\" />
</fieldset>
</form>
<select>
is not working on iPhone and Android. When I tap on the selectbox nothing happens.
I\'m using iScroll 4 which is creating the problem.
<script type=\"application/javascript\" src=\"iscroll-lite.js\"></script>
<script type=\"text/javascript\">
var myScroll;
function loaded() {
myScroll = new iScroll(\'wrapper\');
}
document.addEventListener(\'touchmove\', function (e) { e.preventDefault(); }, false);
document.addEventListener(\'DOMContentLoaded\', loaded, false);
</script>
I think this is a solution but I don\'t know how to implement it.
回答1:
The problem is that iScroll cancels the default behavior of your select
tag (Not a very good implementation if you ask me).
This occurs in the _start()
function on line 195:
e.preventDefault();
If you comment that out you'll notice the select
tag works again.
But commenting it out means you've hacked the library which might break other desirable iScroll functionality. So here's a better workaround:
var selectField = document.getElementById('Field10');
selectField.addEventListener('touchstart' /*'mousedown'*/, function(e) {
e.stopPropagation();
}, false);
That code will allow the default behavior to occur, without propagating the event to iScroll where it screws everything up.
Since your JS is not inside any jQuery-like onReady()
event, you'll have to make sure to you put this code AFTER the HTML where your select
elements are defined.
Note that for mobile devices the event is touchstart
, but for your PC browser it will be mousedown
回答2:
I had the same issue on the iScroll 4.1.9 on android, I just replaced the line 95 (on my version) :
onBeforeScrollStart: function (e) { e.preventDefault(); },
by :
onBeforeScrollStart: function (e) {var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase():(e.target ? e.target.nodeName.toLowerCase():''); if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') e.preventDefault(); },
that enable focus on input, select and textarea tags
回答3:
Finally fixed this for Android. Ended up modifying a couple of lines in iscroll.js
Here's how we initialize iScroll.
// code from https://github.com/cubiq/iscroll/blob/master/examples/form-fields/index.html
// don't preventDefault for form controls
_menuScroll = new iScroll('menu_wrapper',{
useTransform: false,
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1) target = target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA')
e.preventDefault();
}
});
The onBeforeScrollStart is what allows the controls' default behaviors to take place. Android browser seems to have problem with useTransform, so turn to false.
Finally, some additional iscroll code needed to be excluded when useTransform is false:
// iscroll.js v4.1.9
// line 216:
if (that.options.useTransform) bar.style.cssText += ';pointer-events:none;-' + vendor + '-transition-property:-' + vendor + '-transform;-' + vendor + '-transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);-' + vendor + '-transition-duration:0;-' + vendor + '-transform:' + trnOpen + '0,0' + trnClose;
// line 295:
if (that.options.useTransform) that[dir + 'ScrollbarIndicator'].style[vendor + 'Transform'] = trnOpen + (dir == 'h' ? pos + 'px,0' : '0,' + pos + 'px') + trnClose;
Tried several other methods before realizing that it had to do with the css that iscroll adds.
回答4:
I Know am late,but it might be helpful for some one,
write the following code in pageshow event,but be sure that div ids not same.
it is because, iscroller prevents the default behaviors of elements
$('#yourpage').bind('pageshow',function (event, ui) {
var myScroll;
if (this.id in myScroll) {
myScroll[this.id].refresh();
}else{
myScroll[this.id] = new iScroll('wrapper', { //wrapper is div id
checkDOMChanges: true,
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1)
target =target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA'){ e.preventDefault(); }
}
});
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
});
回答5:
Here is the solution
/* on page add this after all scripts */
<script type="text/javascript">
var myScroll;
function loaded() {
myScroll = new iScroll('wrapper');
}
document.addEventListener('DOMContentLoaded', function(){ setTimeout(loaded,500);}, false);
</script>
/* attach a script for fix */
$(document).ready(function(){
var my_select = document.getElementsByTagName('select');
for (var i=0; i<my_select.length; i++) {
my_select[i].addEventListener('touchstart' /*'mousedown'*/, function(e) {
myScroll.destroy();
setTimeout(function(){myScroll = new iScroll('wrapper');},500);
}, false);
}
/*if you have input problems */
var input = document.getElementById('input');
if (input) {
input.addEventListener('touchstart' /*'mousedown'*/, function(e) {
e.stopPropagation();
}, false);
}
});
回答6:
another code example for solution. and thanks for previous comments! Using Jquery!
After:
$(document).ready(function() {
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', setTimeout(function () { loaded(); }, 200), false);
});
in loaded function
function loaded() {
var allSelects = $('select');
allSelects.each(function(index, item) {
item.addEventListener('touchstart' /*'mousedown'*/, function(e) { e.stopPropagation(); }, false);
});
}
回答7:
Replacing line, onBeforeScrollStart: function (e) { e.preventDefault(); },
By
onBeforeScrollStart: function (e) {
var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase():(e.target ? e.target.nodeName.toLowerCase():'');
if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') {
e.preventDefault();
}
},
In iScroll.js
Works
回答8:
Start with this code. This solution worked for me:
<script type="text/javascript">
var myScroll;
function iScrollLoad() {
myScroll = new iScroll('wrapper');
enableFormsInIscroll();
}
function enableFormsInIscroll(){
[].slice.call(document.querySelectorAll('input, select, button, textarea')).forEach(function(el){
el.addEventListener(('ontouchstart' in window)?'touchstart':'mousedown', function(e){
e.stopPropagation();
})
})
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', function () { setTimeout(iScrollLoad, 200); }, false);
</script>
回答9:
I'm late but I leave you my solution.
If your are using jQuery you can try that.
$('input, textarea, button, a, select').off('touchstart mousedown').on('touchstart mousedown', function(e) {
e.stopPropagation();
});
回答10:
// Setup myScroll
myScroll = new IScroll('#wrapper', {
scrollX: horizontalSwipe,
scrollY: !horizontalSwipe,
momentum: false,
snap: document.querySelectorAll('#scroller .slide'),
snapSpeed: 400,
bounceEasing: 'back',
keyBindings: true,
click: true
});
For me, I just need to add click: true on the last line... Spent the whole day debugging and implementing all the suggested solutions to no avail...
回答11:
he anyone.
i know's about all your answer's but i have new way to offer. without java-script or drop iscroll functions.
the big problems with all this solution is when you scroll on input's element you have no scroll on the page. when you make just one or two input's isn't really matter but when the page is a form you have big problem to scroll the page.
the solution i offering is to wrap the input in label tag or make the label tag with for pointer to the input. then make with absolute positioning and z-index the label above the input. when you touch on the label you focus the input.
and example please
HTML
<fieldset>
<label>
<input type="text" />
</label>
</fieldset>
CSS
fieldset {position:relative;z-index:20;}
label {position:relative;z-index:initial;}
input {position:relative;z-index:-1;}
you can also in this way put the label side of the input and with position absolute of the input put that into the label area
is working in 100%, check it
回答12:
There is a bug with Android when -webkit-transform:translate3d is applied to a container that has a select box or password box[1]. The boxed area to activate those elements move, and are not where you think they'd be. Additionally, password boxes paint in a different location, so it appears that you have two input elements instead of one.
I work at AppMobi and we have developed a toolkit library that has fixes for these. We've implemented custom select box widgets and a replacement for the password input field. Check it out below.
https://github.com/imaffett/AppMobi.toolkit
[1] I think the author of the comment is talking about this bug https://bugs.webkit.org/show_bug.cgi?id=50552
回答13:
I'm a bit late to the game, but if anyone is still interested, I took @bastien's approach and tweaked it a bit to get it to work on Android. I'm using JQM with my implementation.
Basically what I did was:
function scrollMe(element) {
var contentID = $wrapper.get(0).id;
var scroller = elm.find('[data-iscroll="scroller"]').get(0);
if (scroller) {
var iscroll = new iScroll(contentID, {
hScroll : false,
vScroll : true,
hScrollbar : false,
vScrollbar : true,
fixedScrollbar : true,
fadeScrollbar : false,
hideScrollbar : false,
bounce : true,
momentum : true,
lockDirection : true,
useTransition : true,
//the preceding options and their values do not have any to do with the fix
//THE FIX:
onBeforeScrollStart: function(e) {
var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase() : (e.target ? e.target.nodeName.toLowerCase():''); //get element node type
if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') e.preventDefault(); //be have normally if clicked element is not a select, option, input, or textarea.
else if (iscroll != null) { //makes sure there is an instance to destory
iscroll.destroy();
iscroll = null;
//when the user clicks on a form element, my previously instanced iscroll element is destroyed
}
},
onScrollStart: function(e) {
if (iscroll == null) { //check to see if iscroll instance was previously destoryed
var elm = $.mobile.activePage; //gets current active page
var scrollIt = setTimeout( function(){ scrollMe(elm) }, 0 );
} //recursively call function that re-instances iscroll element, as long as the user doesn't click on a form element
}
});
elm.data("iscroll-plugin", iscroll);
}
}
Basically all you need to do is destroy your iScroll instance when a form element is selected by the user, but before they actually start scrolling (onBeforeScrollStart) and if the user clicks on anything else within the element with the custom attribute data-iscroll="scroller"
, they can scroll using iScroll as usual.
<div data-role="page" id="pageNameHere" data-iscroll="enable">
回答14:
Here's a really easy fix that worked for me. I noticed in the Android browsers that on initial page load I could not click on a select box but I was able to click on a text input field that I was using for Search. Then I noticed that after I clicked on the text input field, it would recognize me clicking a select box. So all I did was add this to the javascript function I was using to load the Search page...
$('#search').focus();
So when the search page gets loaded, it automatically focuses on the text input field but does not pop up the keyboard, which is exactly what I wanted. Sorry my example is not publicly accessible, but hopefully this can still help somebody.
回答15:
try this solution
if (e.target.nodeName.toLowerCase() == "select" || e.target.tagName.toLowerCase() == 'input' || e.target.tagName.toLowerCase() == 'textarea')
{
return;
}
回答16:
What about, that works for me!:
$('input, select').on('touchstart', function(e) {
e.stopPropagation();
});
回答17:
Even if you've excluded form elements in onBeforeScrollStart(), there is another bug in android 2.2/2.3 browser/webview:
https://www.html5dev-software.intel.com/viewtopic.php?f=26&t=1278 https://github.com/01org/appframework/issues/104
You can't input chinese characters in input elements in the div with "-webkit-transform" css style. The iscroll 4 applied the "-webkit-transform" with the scroller div.
The solution is to keep form fields in a absolute div out of the scroller.
回答18:
Android browser bug is result of very old version of WebKit inside Android, even inside Android 4.3. The root cause of bug - wrong processing of the click event that iScroll sends back to the browser (removing preventDefault just stops sending this click event) The Android Chrome browser is free from this bug because it has upgraded WebKit library inside.
Waiting for Android WebKit upgrade from Google.
回答19:
Check this. This fixed my issue
https://github.com/cubiq/iscroll/issues/576
In option I have selected
click:false, preventDefaultException:{tagName:/.*/}
来源:https://stackoverflow.com/questions/5745374/iscroll-4-not-working-with-form-select-element-iphone-safari-and-android-brows