成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

前端魔法堂:屏蔽Backspace導(dǎo)致頁面回退

plus2047 / 3326人閱讀

摘要:而以后的瀏覽器則屏蔽了和的上述行為,而是采用實現(xiàn)回退和實現(xiàn)前進。附加功能現(xiàn)在我們的目的是頁面不會因為用戶誤操作而刷新,導(dǎo)致頁面數(shù)據(jù)丟失。這里有兩個組合鍵同樣會的導(dǎo)致頁面刷新刷新當(dāng)前頁面,可被阻止關(guān)閉當(dāng)前窗體或標(biāo)簽頁,無法阻止。

前言

?前幾天用戶反映在錄入資料時一不小心錯按Backspace鍵,就會直接回退到是一個頁面,導(dǎo)致之前辛辛苦苦錄入的資料全部丟失了。哦?居然還有這種情況。下面我們來一起探討一下吧!

Windows系統(tǒng)下獨有的行為

?Windows下的IE、FireFox和Chrome 52之前的瀏覽器,當(dāng)焦點不在一個可編輯的元素上時,按Backspace鍵就會回退到上一個頁面,按Shift+Backspace鍵則會前進到下一個頁面。
?而Chrome 52以后的瀏覽器則屏蔽了BackspaceShift+Backspace的上述行為,而是采用Alt+Left實現(xiàn)回退和Alt+Right實現(xiàn)前進。如果想恢復(fù)Backspace回退,則需要安裝Go Back With Backspace的Extension才行。
?對于FireFox而言,我們可以設(shè)置BackspaceShift+Backspace的行為。

在地址欄輸入about:config

在搜索框輸入browser.backspace_action,然后設(shè)置項目值即可。有3個可選項
0,表示BackspaceShift+Backspace的行為對應(yīng)頁面回退和前進(Windows下的默認值)

1,表示BackspaceShift+Backspace的行為對應(yīng)頁面向下滾動和向上滾動
2或其他值,表示不響應(yīng)BackspaceShift+Backspace(Ubuntu16下的默認值)

注意:Linux和OS X下的瀏覽器按BackspaceShift+Backspace不會觸發(fā)頁面的回退和前進。

如何應(yīng)對 方案一:頁面跳轉(zhuǎn)時彈出二次確認

?通過beforeunload事件實現(xiàn)頁面跳轉(zhuǎn)時彈出二次確認模態(tài)窗,讓用戶有后悔的機會。但會截斷其他正常跳轉(zhuǎn)的操作流暢性,在確實沒有辦法時才使用!

方案二:直接屏蔽

?屏蔽BackspaceShift+Backspace的默認行為,僅當(dāng)焦點落在可編輯區(qū)域中時才暫時取消屏蔽。
那么哪些算是能獲得焦點的可編輯區(qū)域呢?就下面這些咯??!

input[type=text]:not([readonly])
input[type=password]:not([readonly])
input[type=number]:not([readonly])
input[type=email]:not([readonly])
input[type=url]:not([readonly])
input[type=search]:not([readonly])
input[type=tel]:not([readonly])
textarea:not([readonly])
[contenteditable]:not([readonly])

就是說當(dāng)焦點落在上述符合規(guī)則的元素上時,按BackspaceShift+Backspace的默認行為就不是頁面跳轉(zhuǎn),因此不用屏蔽掉。

附加功能

?現(xiàn)在我們的目的是頁面不會因為用戶誤操作而刷新,導(dǎo)致頁面數(shù)據(jù)丟失。這里有兩個組合鍵同樣會的導(dǎo)致頁面刷新

ctrl+r刷新當(dāng)前頁面,可被阻止;

ctrl+w關(guān)閉當(dāng)前窗體或標(biāo)簽頁,無法阻止。

代碼時間.js
    ;window.nobsgb || (function(exports){
                var started = false
                exports.start = function(){started = true}
                exports.stop = function(){started = false}

        var KEYCODE = {
            BACKSPACE: 8,
            R: 82
        }
        // 判斷type是否不受阻止
        var isEscapableType = function(rEscapableTypes){
            return function(type){
                return rEscapableTypes.test(type)
            }
        }(/text|textarea|tel|email|number|search|password|url/i)
        // 判斷標(biāo)簽是否不受阻止
        var isEscapableTag = function(rEscapableTag){
            return function(tag){
                return rEscapableTag.test(tag)
            }
        }(/input|textarea/i)
        // 判斷是否設(shè)置為content editable
        var isContentEditable = function(el){
            return el.isContentEditable
        }
        // 判斷是否為不受阻止的Backspace
        var isEscapableBackspace = function(el){
            return or(isEscapableTag(el.tagName)
                      && 
                      or(!("type" in el)
                         , ("type" in el) && isEscapableType(el.type) && !el.readOnly)
                      , isContentEditable(el))
        }
        var isCtrlR = function(e, keycode){
            return e.ctrlKey && KEYCODE.R === keycode
        }
        var isArray = function(x){
            return /Array/.test(Object.prototype.toString.call(x))
        }
        
        var getEvt = function(e){
            return e || window.event
        }
        var getTarget = function(e){
            return e.target || e.srcElement
        }
        var getKeycode = function(e){
            return e.keyCode || e.which
        }
        var preventDefault = function(e){
            e.preventDefault && e.preventDefault()
            e.returnValue = false
            return false
        }
        var listen = function(listen){
            return function(evtNames, handler){
                if (!isArray(evtNames)){
                    evtNames = [evtName]
                }
                var i = 0
                  , len = evtNames.length
                for (; i < len; ++i){
                    listen(evtNames[i], handler)
                }
            }
        }(function(evtName, handler){
            if (or(document["addEventListener"] && (document["addEventListener"].apply(document, arguments) || true)
                   , document["attachEvent"] && (document["attachEvent"].apply(document, arguments) || true))){
                document["on"+evtName] = handler
            }
            
        })
        
        var or = function(){
            var ret = false
              , i = 0
              , len = arguments.length
            for (; !ret && i < len; ++i){
                ret = ret || arguments[i]
            }
            return ret
        }
        var handler = function(e){
                        if (!started) return true
            var evt = getEvt(e)
              , el = getTarget(evt)
              , keyCode = getKeycode(evt)

            if (or(KEYCODE.BACKSPACE === keyCode && !isEscapableBackspace(el)
                  , isCtrlR(evt, keyCode))){
                return preventDefault(evt)
            }
        }
        
        listen(["keydown"], handler)
    }(window.nobsgb = {}))
代碼時間.cljs

core.cljs

(ns nobsgb.core
  (:require [nobsgb.dom :as dom]
            [nobsgb.pred :as pred]))

(def started false)
(defn ^:export start []
  (set! started true))
(defn ^:export stop []
  (set! started false))

(defn handler
  "keydown事件響應(yīng)函數(shù)"
  [e]
  (when started
    (let [evt (dom/get-evt e)
          el (dom/get-el evt)
          key-code (dom/get-key-code evt)
          ctrl-key (dom/get-ctrl-key evt)
          read-only (dom/get-read-only el)
          type (dom/get-type el)
          content-editable (dom/get-content-editable el)
          tag (dom/get-tag el)]
      (if-not
        (pred/escapable?
          key-code read-only type tag content-editable ctrl-key)
        (dom/prevent-default evt)
        true))))

(defonce init
  (#(dom/listen! js/document "keydown" handler)))

dom.cljs

(ns nobsgb.dom)

(defn get-evt
  [e]
  (if (some? e) e (.event js/window)))

(defn get-el
  [e]
  (let [el (.-target e)]
    (if (some? el) el (.-srcElement e))))

(defn get-key-code
  [e]
  (.-keyCode e))

(defn get-ctrl-key
  [e]
  (.-ctrlKey e))

(defn get-read-only
  [el]
  (-> el (aget "readOnly") js/Boolean))

(defn get-type
  [el]
  (let [type (.-type el)]
    (if (some? tpye) type "")))

(defn get-tag
  [el]
  (.-tagName el))

(defn get-content-editable
  [el]
  (.-isContentEditable el))

(defn prevent-default
  [e]
  (if (some? (.-preventDefault e))
    (do
      (.preventDefault e)
      (set! (.-returnValue e) false)
      false)
    true))

(defn listen!
  [el evt-name handler]
  (cond
    (fn? (.-addEventListener el)) (.addEventListener el evt-name handler)
    (fn? (.-attachEvent el))      (.attachEvent el (str "on" evt-name) handler)
    :else (aset el (str "on" evt-name) handler)))

pred.cljs

(ns nobsgb.pred)
;;;; 斷言

(defonce ^:const KEYCODES
  {:backspace 8
   :r 82})

(defn matches-key?
  "是否匹配指定鍵碼"
  [indicated-key-code key-code]
  (= indicated-key-code key-code))

(def ^{:doc "是否為退格鍵"}
  backspace?
  (partial matches-key? (:backspace KEYCODES)))

(def ^{:doc "是否為字母R鍵"}
  r?
  (partial matches-key? (:r KEYCODES)))

(defn with-ctrl?
  "是否在按ctrl的基礎(chǔ)上按其他鍵"
  [ctrl-key]
  (or (= ctrl-key "1")
      (true? ctrl-key)))

(defn ctrl+r?
  "是否為ctrl+r"
  [ctrl-key key-code]
  (and (with-ctrl? ctrl-key)
       (r? key-code)))
(def not-ctrl+r? (complement ctrl+r?))

(defn escapable-type?
  "是否為可跳過的type屬性"
  [type]
  (some?
    (some->> type
      (re-matches #"(?i)text|password|tel|number|email|search|url"))))

(defn escapable-tag?
  "是否為可跳過的tag"
  [tag]
  (some?
    (some->> tag
      (re-matches #"(?i)input|textarea"))))

(def ^{:doc "是否設(shè)置為可編輯元素"}
  content-editable? identity)

(def ^{:doc "是否設(shè)置為只讀"}
  read-only? identity)
(def writable? (complement read-only?))

(defn escapable-backspace?
  [key-code read-only type tag content-editable]
  (and (backspace? key-code)
       (writable? read-only)
       (or (escapable-type? type)
           (escapable-tag? tag)
           (content-editable? content-editable))))

(defn escapable?
  [key-code read-only type tag content-editable ctrl-key]
  (or
    (and (not-ctrl+r? ctrl-key key-code)
         (not (backspace? key-code)))
    (escapable-backspace? key-code read-only type tag content-editable)))
總結(jié)

?尊重原創(chuàng),轉(zhuǎn)載請注明來自:http://www.cnblogs.com/fsjohn... ^_^肥仔John

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/83153.html

相關(guān)文章

  • 前端魔法:解秘FOUC

    摘要:前言對于問題多多的,瀏覽器樣式閃爍是一個不可忽視的話題,但對于的瀏覽器就不用理會了嗎下面嘗試較全面地解密。示例說明,不管在哪里引入,在頁面的所有下載完成前,整個頁面將不會被渲染。 前言 ?對于問題多多的IE678,F(xiàn)OUC(flash of unstyled content)——瀏覽器樣式閃爍是一個不可忽視的話題,但對于ever green的瀏覽器就不用理會了嗎?下面嘗試較全面地解密F...

    Dean 評論0 收藏0
  • 前端魔法:解秘FOUC

    摘要:前言對于問題多多的,瀏覽器樣式閃爍是一個不可忽視的話題,但對于的瀏覽器就不用理會了嗎下面嘗試較全面地解密。示例說明,不管在哪里引入,在頁面的所有下載完成前,整個頁面將不會被渲染。 前言 ?對于問題多多的IE678,F(xiàn)OUC(flash of unstyled content)——瀏覽器樣式閃爍是一個不可忽視的話題,但對于ever green的瀏覽器就不用理會了嗎?下面嘗試較全面地解密F...

    MRZYD 評論0 收藏0
  • 前端魔法:解秘FOUC

    摘要:前言對于問題多多的,瀏覽器樣式閃爍是一個不可忽視的話題,但對于的瀏覽器就不用理會了嗎下面嘗試較全面地解密。示例說明,不管在哪里引入,在頁面的所有下載完成前,整個頁面將不會被渲染。 前言 ?對于問題多多的IE678,F(xiàn)OUC(flash of unstyled content)——瀏覽器樣式閃爍是一個不可忽視的話題,但對于ever green的瀏覽器就不用理會了嗎?下面嘗試較全面地解密F...

    VEIGHTZ 評論0 收藏0
  • 前端魔法——異常不僅僅是try/catch

    摘要:我打算分成前端魔法堂異常不僅僅是和前端魔法堂調(diào)用棧,異常實例中的寶藏兩篇分別敘述內(nèi)置自定義異常類,捕獲運行時異常語法異常網(wǎng)絡(luò)請求異常事件,什么是調(diào)用棧和如何獲取調(diào)用棧的相關(guān)信息。 前言 ?編程時我們往往拿到的是業(yè)務(wù)流程正確的業(yè)務(wù)說明文檔或規(guī)范,但實際開發(fā)中卻布滿荊棘和例外情況,而這些例外中包含業(yè)務(wù)用例的例外,也包含技術(shù)上的例外。對于業(yè)務(wù)用例的例外我們別無它法,必須要求實施人員與用戶共同...

    bladefury 評論0 收藏0
  • JS魔法:定義頁面的Dispose方法——[before]unload事件啟示錄

    摘要:坑無視和是十分特殊的事件,要求事件處理函數(shù)內(nèi)部不能阻塞當(dāng)前線程,而卻恰恰就會阻塞當(dāng)前線程,因此規(guī)范中以明確在和中直接無視這幾個方法的調(diào)用。 前言 ?最近實施的同事報障,說用戶審批流程后直接關(guān)閉瀏覽器,操作十余次后系統(tǒng)就報用戶會話數(shù)超過上限,咨詢4A同事后得知登陸后需要顯式調(diào)用登出API才能清理4A端,否則必然會超出會話上限。?即使在頁面上增添一個登出按鈕也無法保證用戶不會直接關(guān)掉瀏覽器...

    Chiclaim 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<