移動端彈窗輸入密碼的那些事

富途web開發團隊發表於2018-09-03

歡迎關注富途web開發團隊,php , 前端需要你。缺人從眾

該從何說起呢?我先理一理,東西有點多,怕把大家帶溝裡。那現在開門見山,先說一下是什麼事吧。如題所說,其實就是在移動端瀏覽器的新股認購頁面裡面讓使用者輸入交易密碼。

不就是輸入交易密碼,心想看著很簡單,做著也簡單。

以下內容均已富途證券的新股認購模組為背景。

入坑前

很happy,果然和心裡想的一樣。新股認購上線沒啥問題。視覺稿的輸入交易密碼大概就是下圖的樣子。新股認購的原稿找不到了,就找了一張bug單代替吧。很簡單,只要校驗輸入的交易密碼是否符合校驗邏輯後提交,沒有多餘的操作。這樣的設計其實前端要做的事並沒有[多?]少。

pwd

舊版WEB輸入交易密碼

嗯,沒錯。今天說的就是我和上面那個不起眼的輸入交易密碼框的故事。

人生處處有驚喜。要是都是這麼簡單,那麼也就沒那麼多事了。

入坑中

上線後沒過多久。由於新股認購業務的發展需要,頁面需要內嵌到App裡面。心想應該也沒問題,畢竟頁面已經做了移動端適配的。

N天就這麼過去了。突然有一天,負責App設計規範的同學找到了我。說新股認購頁面的輸入交易密碼操作不符合App設計規範,需要進行修改。滿腦子的???那我,當時就說啦,我這是按WEB這邊的設計規範來做的啊。

先說說背景:是這樣的,公司App和WEB都各有一套不同的設計規範,平時都不會有太多交集。但是一旦一個按WEB規範製作的頁面內嵌到App裡面,那就有問題了呀。因為根據WEB設計規範做出了的頁面,內嵌到了App裡面,就不一定符合App的設計規範。

pwd

App 輸入交易密碼設計稿,可以看到和WEB完全不一樣,這是原生App的輸入框

好吧,這個規範設計交集讓我踩到了。那怎麼辦呢,拉前端負責人,WEB設計負責人,App設計負責人,視覺負責人一起討論唄。

吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧吧唧!!

經過大家的討論,最終決定修改WEB這邊的規範,嘗試使用彈窗輸入交易密碼,把WEB這邊的輸入交易密碼改成和App的規範一致。也就是下面的彈窗輸入交易密碼的樣子。

交易密碼是6位數字組合

pwd

新版-01 WEB輸入交易密碼

從上圖可以看到,點選“立即認購”按鈕,就會彈出輸入交易密碼的彈窗,然後點選彈窗進行輸入(軟鍵盤這個版本並沒有自動拉起)。輸入完成後,按右圖的1,2步驟提交密碼。

部分交易密碼彈窗HTML:

<div class="ui-dialog-body ui-form">
    <div class="ui-form-item" ng-class="{'ui-focus':focused}">
        <ul class="pwdList ui-form-text">
            <li ng-repeat="item in passwordList track by $index" ng-click="inputFocus()">
                <span ng-class="{'dot':item}"></span>
            </li>
        </ul>
    </div>
    <input type="text" name="txtPassword" ng-trim="false" ng-model="pwdValue" ng-change="updatePassword();" ng-focus="onFocus();" ng-blur="onBlur()" autocomplete="off" autocorrect="off" maxlength="6">
</div>
複製程式碼

通過li展示交易密碼輸入的長度

原理就是把一個透明的input框放在ul上面,ul裡面的li用來展示輸入密碼的長度。

上線沒多久,有使用者反饋不能提交交易密碼。原因就是,ios在軟鍵盤沒有隱藏的情況下,點選"確認"提交按鈕無效。

pwd

使用者反饋,點選提交無效,這無解。。。求拯救

就這樣,我成功入坑了。

上線第一版,總結上面的輸入交易密碼框在移動端存在的問題:

  1. 不能自動拉起軟鍵盤;
  2. 軟鍵盤沒有隱藏時,無法正常提交交易密碼問題;
  3. 點選輸入交易密碼拉起的不是數字鍵盤;
  4. 密碼輸入錯誤,沒有重試機會,需要使用者重新點選“立即認購”,彈出密碼框。

挖坑中...

針對上面出現的問題,優先決定處理問題2和問題4。因為已經影響了正常業務流程體驗。這樣優化版就開始了。

為了解決問題2,大家(又是那一波人)討論決定刪除“取消”和“確認”按鈕,改為自動提交(也就是當使用者輸入密碼位數到達6位,即自動發起後端Ajax請求)。這樣就可以保證不影響業務。對於問題4,提供二次彈窗輸入交易密碼,使得整個業務操作流程更加流暢。

pwd

新版-02 點選“立即認購”,彈出輸入交易密碼框,輸入完後自動提交,提交完發現密碼錯誤提示“重試”

優化後的版本,更加美觀和高效了,最重要的是使用者體驗也爽了。沒有"確認"按鈕的交易密碼彈窗HTML:

<div class="ui-dialog-box passwordBox" ng-class="{'ui-show': isShowPwd}" ng-show="isShowPwd">
    <div class="ui-dialog ui-center">
        <div class="ui-dialog-header">
            <h3 class="ui-dialog-header-title">{{dtitle||'請輸入富途交易密碼'}}</h3>
        </div>
        <div class="ui-dialog-body ui-form">
            <div class="ui-form-item" ng-class="{'ui-focus':focused}">
                <ul class="pwdList ui-form-text">
                    <li ng-repeat="item in passwordList track by $index" ng-click="inputFocus()">
                        <span ng-class="{'dot':item}"></span>
                    </li>
                </ul>
            </div>
            <input type="text" name="txtPassword" ng-trim="false" ng-model="pwdValue" ng-change="updatePassword();" ng-focus="onFocus();" ng-blur="onBlur()" autocomplete="off" autocorrect="off" maxlength="6">
        </div>
        <i class="ui-icon ui-dialog-close icon-close" ng-click="closeClick()"></i>
    </div>
</div>
複製程式碼

就這樣,填了自己埋下的2個坑。同時,又給自己挖了2個坑。

沒過多久,客服同學反饋過來說,Android使用者點選“立即認購”按鈕後,彈出交易密碼框,點選輸入交易密碼時發現(這個時候,還沒有做自動拉起軟鍵盤),軟鍵盤擋住了輸入框。

pwd

點選輸入交易密碼,軟鍵盤擋住了交易密碼框,我的天呀。。。。

第二個問題是測試的時候,發現自動提交交易密碼後,軟鍵盤並沒有自動隱藏。被測試同學提了bug。

pwd

嗚嗚嗚嗚嗚嗚嗚嗚,bug。移動端咋這麼多破事。

剛解決2個問題,又來2個。

只能怪自己太想當然,得好好反省。總結一下,現在存在的問題:

  1. 不能自動拉起軟鍵盤;
  2. android機交易密碼框被軟鍵盤擋住;
  3. 點選輸入交易密碼拉起的不是數字鍵盤;
  4. 自動提交程式碼後,軟鍵盤沒有自動隱藏。

好吧,還是四個問題。

填坑中...

再來排一次問題優先順序,還是問題2和問題4需要優先處理。

問題2 android機交易密碼框被軟鍵盤擋住解決辦法

我們都知道,當我們在頁面輸入資料的時候。一般軟鍵盤拉起的時候,都會把對應的輸入框往上移一段。保證輸入框在頁面的可視範圍內。正常情況如下圖左邊圖1,但是有的瀏覽器在彈出軟鍵盤後,會擋住輸入框,如下圖右2。

pwd

左1正常,右2有問題

解決的方法就是:

.pwd-wrapper{
    position:fixed;//主要是這個
    top: 10px; //這個
    z-index:999;
}
複製程式碼

彈窗原本就是fixed,通過設定彈窗的top屬性,把交易密碼彈窗放到頁面的最上面。這樣就避免彈窗被軟鍵盤擋住。

可能你會覺得這樣很不協調,彈窗沒有上下居中。其實只有存在問題的瀏覽器才會不居中,但比起軟鍵盤擋住了交易密碼框,要好得多了。除此之外,正常的瀏覽器,儘管我上面寫了top:10px看起來好像沒有上下居中對齊,但是結果確實正常的上下居中對齊。

這讓我相信了,一句話,沒問題的怎麼都沒問題;有問題的,沒問題那也是有問題。

好了,問題2就這樣愉快的解決了。

問題4 軟鍵盤沒有自動隱藏

這個應該很好解決。也就是讓輸入框失去焦點就可以了。

$('input[name="txtPassword"]').blur();
複製程式碼

是不是這個問題很白吃呀。這麼簡單,那時候為什麼沒有加,我記得加了呀。

“明明就是隔壁那位在整理成彈窗密碼元件時JavaScript事件沒加對位置嘛。。。。”。>_> ,開玩笑的。

前端黑科技的降臨

通過一頓猛如虎的操作,使用者體驗上升了不少有沒有。筆芯。。。。

可以鬆一口氣了。然後再來慢慢解決上面還剩下的2個問題。

  1. 不能自動拉起軟鍵盤;
  2. 點選輸入交易密碼拉起的不是數字鍵盤。

想著,要不先優化拉起的不是數字鍵盤的問題吧。

解決輸入交易密碼沒有拉起數字鍵盤問題

如果沒有對input做特殊型別設定的話,一般都會根據使用者的設定選擇的語言來展示軟鍵盤。

Input 設定type="text" 方案

一直以來都是使用的type="text"的輸入框。所以點選彈窗拉起的軟鍵盤是可以輸入中文的,這顯然和交易密碼要求的數字不符合。

預設彈窗輸入部分程式碼:

 <div class="ui-dialog-body ui-form">
    <div class="noticeInfo">{{notice}}</div>
    <div class="ui-form-item" ng-class="{'ui-focus':focused}">
        <ul class="pwdList ui-form-text">
            <li ng-repeat="item in passwordList track by $index" ng-click="inputFocus()">
                <span ng-class="{'dot':item}"></span>
            </li>
        </ul>
    </div>
    <input type="text" name="txtPassword" ng-trim="false" ng-model="pwdValue" ng-change="updatePassword();" ng-focus="onFocus();" ng-blur="onBlur()" autocomplete="off" autocorrect="off" maxlength="6">
</div>
複製程式碼

type="text"的基礎上,通過新增pattern="[0-9]*",發現ios可以正常拉起了數字鍵盤,android上也不是中文輸入法。

開心,這個方案可以接受。

程式碼修改如下:

<input type="text" pattern="[0-9]*" name="txtPassword" ng-trim="false" ng-model="pwdValue" ng-change="updatePassword();" ng-focus="onFocus();" ng-blur="onBlur()" autocomplete="off" autocorrect="off" maxlength="6">
複製程式碼

只需要做一點小改動,軟鍵盤的展示已經符合了預期。對比如下圖所示。

pwd

左圖為預設type="text" , 右圖為type="text" pattern="[0-9]*"

嘗試使用type="number"type="password"。發現效果並沒有上面使用<input type="text" pattern="[0-9]*"> 的效果好。

測試程式碼如下:

<!-- type = number -->
<input type="number" name="txtPassword" ng-trim="false" ng-model="pwdValue" ng-change="updatePassword();" ng-focus="onFocus();" ng-blur="onBlur()" autocomplete="off" autocorrect="off" maxlength="6">
<!-- type= password -->
<input type="password" name="txtPassword" ng-trim="false" ng-model="pwdValue" ng-change="updatePassword();" ng-focus="onFocus();" ng-blur="onBlur()" autocomplete="off" autocorrect="off" maxlength="6">
複製程式碼

可以看到type="number"彈出的是數字鍵盤;但不是9宮格的,type="password"彈出的是字母,就更不用說了,效果一般。

pwd

左圖為預設type="number" , 右圖為type="password"

最後,經過對比,決定使用<input type="text" pattern="[0-9]*"> 格式。起碼ios拉起的是9宮格,android拉起的是數字鍵盤。

就這樣,優化走一波。。。。。。。

有問題的一般都是老闆們的手機

正當我喝著橙汁,聽著小曲兒,擼著程式碼的時候。產品發來了一張圖。

pwd

當使用者設定搜狗為預設輸入法

什麼?????????拉起的軟鍵盤居然時搜狗輸入法,這一定是廣告。

大概問了一下前因後果,原來是VVIP客戶呀,難怪輸入法都有特殊待遇。這就尷尬了,我總不能讓客戶去修改系統的預設輸入法吧。

主要還是因為第三方輸入法有記錄密碼的風險。

不能等,馬上拉著一票人一起討論,呱唧呱唧呱唧呱唧呱唧呱唧呱唧呱唧呱唧!!!!!

通過討論,得以下幾個方案:

  1. 改為<input type="password">格式,這樣就可以拉起原生輸入法,但是就不一定時數字鍵盤了
  2. 找客戶端同學幫忙看能不能限制輸入法;這樣做App裡面正常,但是瀏覽器裡面還是會有問題
  3. 自己實現密碼輸入鍵盤,想挖坑的方案

但是,上面的所有的方案都不好。況且產品,產品老大也不同意啊。怎麼辦呢???

齊心協力上網搜呀,看看哪些網站有拉起軟鍵盤是原生數字鍵盤的, 終於扒到了一個。

程式碼很簡單:

pwd

勞資,看到這行程式碼的時候,差點一屁股坐到了地上。什麼!!!還有這種操作,黑科技呀有沒有。反正我是信了。還等什麼,趕緊試一試。

部分程式碼如下:

<div class="ui-dialog-body ui-form">
    <div class="noticeInfo">{{notice}}</div>
    <div class="ui-form-item" ng-class="{'ui-focus':focused}">
        <ul class="pwdList ui-form-text">
            <li ng-repeat="item in passwordList track by $index" ng-click="inputFocus()">
                <span ng-class="{'dot':item}"></span>
            </li>
        </ul>
    </div>
    <input type="tel" pattern="[0-9]*" name="txtPassword" ng-trim="false" ng-model="pwdValue" ng-change="updatePassword();" ng-focus="onFocus();" ng-blur="onBlur()" autocomplete="off" autocorrect="off" maxlength="6">
</div>
複製程式碼

居然真的可以了,有沒有。使用type="tel"真的可以做到彈起的是原生的9宮格鍵盤。看來打電話還是親爹的。

pwd

設定輸入框 type="tel"

這種操作一定要拿小本本記下來。

git commit -a '為了使用者密碼安全,預設拉起原生9宮格鍵盤'
複製程式碼

完事。

如何自動拉起軟鍵盤

原來的軟鍵盤一直都沒有自動拉起來。互動邏輯是下面這個樣子,使用者必須手動點選輸入框,才會拉起軟鍵盤。

pwd

不能自動拉起軟鍵盤

現在想實現成可以在使用者點選“立即認購”按鈕之後,可以自動拉起軟鍵盤。如下圖所示。

pwd

自動拉起軟鍵盤

一般的做法就是在“立即認購”按鈕上新增click事件,一旦"立即認購"按鈕被點選,就觸發交易密碼框的focus事件。

嘗試實現:

修改認購按鈕html:

<button type="submit" class="ui-btn"  ng-click="submitApply()">立即認購</button>
複製程式碼

通過JavaScript事件進行處理。

$scope.submitApply = function(){
    //密碼框聚焦
    $input.focus();
    $scope.focused = true;//設定flag
}
複製程式碼

這種方法,在網上也有一大把。雖然pc端可以正常執行,但是在移動端卻不能正常拉起軟鍵盤。

結論:直接focus()行不通,需要進行深入研究。

利用Input聚焦可以拉起軟鍵盤的特徵

既然,軟鍵盤只有在使用者手動touch輸入框foucus的時候才會彈起。是不是可以在原有的基礎上,嘗試把“立即認購”按鈕也改成input輸入框,同時使用原有按鈕做背景。

案例走一波,修改按鈕結構為以下格式:

<div class="sub-container">
    <button type="submit" class="ui-btn" ng-class="{'ui-btn-loading': !isCanApplyNewStock}" ng-disabled="!render.agreement||!isCanApplyNewStock" ng-click="submitApply()">立即認購</button>
    <input type="tel" pattern="[0-9]*" class="trade-pwd" ng-click="submitApply()">
</div>
複製程式碼

做法:也就是把一個透明的input框放在認購按鈕上面,當使用者點選的時候,其實是點選的是input輸入框。猜想:這個時候,因為點選的是輸入框,所以軟鍵盤就會拉起來,同時執行上面的submitApply()函式,可以把游標聚焦到交易密碼框上。

pwd

按鈕結構

通過真機進行測試,發現居然可以正常拉起軟鍵盤。猜想成立。

pwd

正常拉起數字軟鍵盤

實踐說明,通過一個input輸入框,拉起軟鍵盤後,可以通過JavaScript執行focus()聚焦到其他輸入框,並保證軟鍵盤不會收起,並且可以正常對聚焦的輸入框進行輸入。

走一波。。。。

總結

總體上,都是一些輸入框上的操作,知道了原理,其實也挺簡單的。坑都踩了,還等什麼,趕緊去優化你的輸入框吧。

如果有好的建議,歡迎大家留言交流。

原文:futu.im/article/inp…

作者:Jin

相關文章