移动Safari:inputfield上的JavaScript focus()方法仅适用于单击吗?


75

我有一个像这样的简单输入字段。

<div class="search">
   <input type="text" value="y u no work"/>
</div>​

我正在尝试focus()在函数中进行操作。因此,在随机函数内部(与它的功能无关),我有这行代码……

$('.search').find('input').focus();

在任何台式机上,这都可以正常工作。

但是,它不适用于我的iPhone。该领域没有得到重点关注,并且键盘没有显示在我的iPhone上。

为了测试目的并向大家展示这个问题,我做了一个快速示例:

$('#some-test-element').click(function() {
  $('.search').find('input').focus(); // works well on my iPhone - Keyboard slides in
});

setTimeout(function() {
  //alert('test'); //works
  $('.search').find('input').focus(); // doesn't work on my iPhone - works on Desktop
}, 5000);​

知道为什么focus()我的iPhone无法使用超时功能。

要查看实时示例,请在iPhone上测试此小提琴。http://jsfiddle.net/Hc4sT/

更新:

我创建了与当前项目完全相同的案例。

我有一个选择框,应该在“更改”时将焦点设置到输入字段,然后将其滑入iPhone或其他移动设备上的Kexboard。我发现focus()设置正确,但是键盘没有出现。我需要显示键盘。


也许它聚焦的,但是键盘却没有显示(我的诺基亚X6就是这种情况)。
2012年

1
为我工作。您粘贴的jsfiddle刚好对准了盒子,并在我的iPhone上打开了一个键盘。您正在使用哪个iOS?我已经检查过5.1。
2012年

好的,您看起来是对的。我在iOS 5.1.1上。正如我所知,input:focus { background:green; }通过输入上的CSS设置了focus()似乎可以正常工作。但是,键盘不适合我使用。查看我当前正在处理的这个工作案例。cl.ly/1d210x1W3Y3W在iPhone上进行测试。在选择框中选择“搜索”时,是否有机会在键盘中滑动?
马特2012年

1
我正在尝试很多东西。我尝试了triggerHandler(),focusin(),trigger(“ focus”)。我什至试图先模糊它,然后重新添加焦点。我认为这可能是Webkit中的错误。您可能对此不走运...但是我将尝试更多尝试...
Alex

1
我放弃了 我尝试了一切。这不是您可以在iOS Safari Web浏览器中执行的操作。希望苹果做出改变以允许这样做,因为我当然不认为这是“功能”!哈哈,我不知道为什么你可以这么轻易地使field()变得模糊(blur),却无法将焦点集中在它上面。对我来说没有意义。
亚历克斯(Alex)

Answers:


77

伙计们,实际上是有办法的。我竭尽全力为[LINK REOVEDED](在iPhone或iPad上尝试)解决此问题。

基本上,触摸屏设备上的Safari涉及focus()文本框。如果您愿意,甚至某些台式机浏览器的性能也会更好click().focus()。但是在触摸屏设备上使用Safari的设计人员意识到,键盘不断抬起时,这对用户来说很烦人,因此他们仅在以下情况下显示焦点:

1)用户单击某处并focus()在执行click事件时被调用。如果要进行AJAX调用,则必须同步进行,例如使用$.ajax({async:false})jQuery中已弃用(但仍可用)的选项。

2)而且-这使我忙了一阵子-focus()如果当时专注于其他文本框,似乎仍然无法正常工作。我有一个执行AJAX的“执行”按钮,因此我尝试在执行“执行”按钮时模糊文本框touchstart,但这只是使键盘消失并移动了视口,然后才有机会完成对“执行”按钮的单击。最后,我尝试在“touchend转到”按钮事件中模糊文本框,这就像一个魅力!

将#1和#2放在一起时,您将获得一个神奇的结果,通过将焦点放在密码字段中,可以使登录表单与所有糟糕的Web登录表单区分开,并使它们看起来更自然。请享用!:)


2
这听起来很聪明,但是我很难“将#1和#2放在一起”。在我的应用程序中,使用jQueryMobile,当用户单击页面A中的列表项时,将打开一个只有一个可见输入的新页面B。我希望为该输入自动打开键盘。您是说我必须将.focus()调用放在页面A上的单击处理程序中的某个位置吗?
Wytze 2014年

1
谢谢您节省我的时间。那真是太明显了。
vogdb 2014年

4
我能够得到它!我没有对元素进行模糊和聚焦,而是添加event.preventDefault()touchstart。请注意,这阻止了ng-click的执行,因此我不得不在事件处理程序和$scope.$apply()
ErikAGriffin 2015年

2
我发现仅从input.focus()按钮的单击处理程序运行即可。iPhone 5和iPad上的Safari。如果我focus()将setTimeout设置为in,则不起作用。所以也许这就是“同步”的意思,@ Michael。
Dan Dascalescu 2015年

1
感谢您发布实际的解决方案。在iOS10上仍然可以模糊touchend上的上一个元素+将焦点设置为click事件。
Kirill E.

18

WunderBart答案的本地javascript实现。

function onClick() {

  // create invisible dummy input to receive the focus first
  const fakeInput = document.createElement('input')
  fakeInput.setAttribute('type', 'text')
  fakeInput.style.position = 'absolute'
  fakeInput.style.opacity = 0
  fakeInput.style.height = 0
  fakeInput.style.fontSize = '16px' // disable auto zoom

  // you may need to append to another element depending on the browser's auto 
  // zoom/scroll behavior
  document.body.prepend(fakeInput)

  // focus so that subsequent async focus will work
  fakeInput.focus()

  setTimeout(() => {

    // now we can focus on the target input
    targetInput.focus()

    // cleanup
    fakeInput.remove()
    
  }, 1000)

}

其他参考:在输入“文本”标签中禁用自动缩放-iPhone上的Safari


1
这对我有用。如果要防止在fakeInput焦点上显示键盘,请向其添加readonly =“ true”。
Branislav Kuliha,

唯一可行的解​​决方案。requestAnimationFrame对我来说足够了,并且消除了延迟。
托马斯

这个答案应该在其他类似问题上共享,这些问题涉及将setTimeout +集中在Safari浏览器上。这是真正有效的一件事!
gotjun

谢谢!这是唯一对我有用的解决方案。
Offek

5

我最近遇到了同样的问题。我找到了一个显然适用于所有设备的解决方案。您无法以编程方式进行异步焦点调整,但可以在其他一些输入焦点已经对准时将焦点切换到目标输入。因此,您需要做的是创建,隐藏,附加到DOM并将伪造的输入集中在触发事件上,并且当异步操作完成时,只需再次将focus集中在目标输入上即可。这是一个示例片段-在您的手机上运行。

编辑:

这是带有相同代码小提琴。显然您不能在手机上运行附加的片段(或者我做错了)。

var $triggerCheckbox = $("#trigger-checkbox");
var $targetInput = $("#target-input");

// Create fake & invisible input
var $fakeInput = $("<input type='text' />")
  .css({
    position: "absolute",
    width: $targetInput.outerWidth(), // zoom properly (iOS)
    height: 0, // hide cursor (font-size: 0 will zoom to quarks level) (iOS)
    opacity: 0, // make input transparent :]
  });

var delay = 2000; // That's crazy long, but good as an example

$triggerCheckbox.on("change", function(event) {
  // Disable input when unchecking trigger checkbox (presentational purpose)
  if (!event.target.checked) {
    return $targetInput
      .attr("disabled", true)
      .attr("placeholder", "I'm disabled");
  }

  // Prepend to target input container and focus fake input
  $fakeInput.prependTo("#container").focus();

  // Update placeholder (presentational purpose)
  $targetInput.attr("placeholder", "Wait for it...");

  // setTimeout, fetch or any async action will work
  setTimeout(function() {

    // Shift focus to target input
    $targetInput
      .attr("disabled", false)
      .attr("placeholder", "I'm alive!")
      .focus();

    // Remove fake input - no need to keep it in DOM
    $fakeInput.remove();
  }, delay);
});
label {
  display: block;
  margin-top: 20px;
}

input {
  box-sizing: border-box;
  font-size: inherit;
}

#container {
  position: relative;
}

#target-input {
  width: 250px;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="container">
  <input type="text" id="target-input" placeholder="I'm disabled" />

  <label>
    <input type="checkbox" id="trigger-checkbox" />
    focus with setTimetout
   </label>
</div>


这是我到目前为止找到的最佳解决方案。
anwerso

您可以设置fontSize: '16px'为禁用自动缩放。另外,请参阅下面有关本机js实现的答案。
Raine Revere

3

我有一个带有图标的搜索表单,单击该图标可以清除文本。但是,问题(在移动设备和平板电脑上)是键盘会折叠/隐藏,因为click移除的事件focus已从中移除input

带有关闭图标的文本搜索输入

目标:清除搜索表单(单击/轻按x-icon)后,保持键盘可见

为此,请stopPropagation()在事件上应用如下:

function clear ($event) {
    $event.preventDefault();
    $event.stopPropagation();
    self.query = '';
    $timeout(function () {
        document.getElementById('sidebar-search').focus();
    }, 1);
}

和HTML形式:

<form ng-controller="SearchController as search"
    ng-submit="search.submit($event)">
        <input type="search" id="sidebar-search" 
            ng-model="search.query">
                <span class="glyphicon glyphicon-remove-circle"
                    ng-click="search.clear($event)">
                </span>
</form>

3

我在手机上测试了此解决方案的效果:

document.body.ontouchend = function() { document.querySelector('[name="name"]').focus(); };

请享用


此ALMOST有效。但是不会扩展到两个日期字段,并且使页面有点毛刺
Shayne

谢谢!尝试了各种各样的东西,终于为我做了,由于某种原因document.getElementById没有这样做
daamsie

2

我设法使其与以下代码一起使用:

event.preventDefault();
timeout(function () {
    $inputToFocus.focus();
}, 500);

我正在使用AngularJS,所以我创建了一条指令来解决我的问题:

指示:

angular.module('directivesModule').directive('focusOnClear', [
    '$timeout',
    function (timeout) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                var id = attrs.focusOnClear;
                var $inputSearchElement = $(element).parent().find('#' + id);
                element.on('click', function (event) {
                    event.preventDefault();
                    timeout(function () {
                        $inputSearchElement.focus();
                    }, 500);
                });
            }
        };
    }
]);

如何使用指令:

<div>
    <input type="search" id="search">
    <i class="icon-clear" ng-click="clearSearchTerm()" focus-on-clear="search"></i>
</div>

看来您使用的是jQuery,所以我不知道该指令是否有帮助。


2
众所周知,这不适用于ios Safari。Safari专门区分了由用户交互生成的事件与纯粹由js本身生成的事件,并且不会以这种方式传递焦点/选择事件。
本·惠勒2014年

嗯,那是不对的,我正在Cordova / Phonegap的应用程序中使用它。为什么要投反对票?我的答案与其他答案有何不同?除了我创建了可以使用的Angular Directive。
martinmose 2014年

通常在Angular上本身一个超时就足够了,您不需要设置超时值。它使它等待摘要周期,因此在其他妨碍焦点的事件完成时运行。
2014年

嗨@Maarten,谢谢您的评论,您的意思是我为超时设置的500吗?:)
martinmose14年

好吧,我会测试一下。谢谢 :)。
martinmose14年

1

更新

我也尝试过,但无济于事:

$(document).ready(function() {
$('body :not(.wr-dropdown)').bind("click", function(e) {
    $('.test').focus();
})
$('.wr-dropdown').on('change', function(e) {
    if ($(".wr-dropdow option[value='/search']")) {
        setTimeout(function(e) {
            $('body :not(.wr-dropdown)').trigger("click");
        },3000)         
    } 
}); 

});

我对您为什么说这不起作用感到困惑,因为您的JSFiddle工作得很好,但是无论如何我还是建议您...

在您的Click事件上,在SetTimeOut函数中尝试以下代码:

document.myInput.focus();

myInput与输入标签的名称属性相关。

<input name="myInput">

并使用以下代码模糊字段:

document.activeElement.blur();

谢谢,请参阅我的问题更新。我似乎也无法使它符合您的建议。
马特2012年


-3

请尝试使用点按而不是ng-click事件。我有这个问题。我通过在搜索表单标签内放置我的clear-search-box按钮来解决此问题,并用点按替换了clear-button的ng-click。现在工作正常。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.