前幾天用戶反映在錄入資料時一不當心錯按Backspace鍵,就會直接回退到是一個頁面,致使以前辛辛苦苦錄入的資料所有丟失了。哦?竟然還有這種狀況。下面咱們來一塊兒探討一下吧!html
Windows下的IE、FireFox和Chrome 52以前的瀏覽器,當焦點不在一個可編輯的元素上時,按Backspace
鍵就會回退到上一個頁面,按Shift
+Backspace
鍵則會前進到下一個頁面。
而Chrome 52之後的瀏覽器則屏蔽了Backspace
和Shift
+Backspace
的上述行爲,而是採用Alt
+Left
實現回退和Alt
+Right
實現前進。若是想恢復Backspace
回退,則須要安裝Go Back With Backspace的Extension才行。
對於FireFox而言,咱們能夠設置Backspace
和Shift
+Backspace
的行爲。瀏覽器
在地址欄輸入about:config
app
在搜索框輸入browser.backspace_action
,而後設置項目值便可。有3個可選項0
,表示Backspace
和Shift
+Backspace
的行爲對應頁面回退和前進(Windows下的默認值)dom
1
,表示Backspace
和Shift
+Backspace
的行爲對應頁面向下滾動和向上滾動2
或其餘值,表示不響應Backspace
和Shift
+Backspace
(Ubuntu16下的默認值)ide
注意:Linux和OS X下的瀏覽器按Backspace
和Shift
+Backspace
不會觸發頁面的回退和前進。函數
經過beforeunload
事件實現頁面跳轉時彈出二次確認模態窗,讓用戶有後悔的機會。但會截斷其餘正常跳轉的操做流暢性,在確實沒有辦法時才使用!ui
屏蔽Backspace
和Shift
+Backspace
的默認行爲,僅當焦點落在可編輯區域中時才暫時取消屏蔽。
那麼哪些算是能得到焦點的可編輯區域呢?就下面這些咯!!url
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])
就是說當焦點落在上述符合規則的元素上時,按Backspace
和Shift
+Backspace
的默認行爲就不是頁面跳轉,所以不用屏蔽掉。spa
如今咱們的目的是頁面不會由於用戶誤操做而刷新,致使頁面數據丟失。這裏有兩個組合鍵一樣會的致使頁面刷新prototype
ctrl
+r
刷新當前頁面,可被阻止;
ctrl
+w
關閉當前窗體或標籤頁,沒法阻止。
;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) // 判斷標籤是否不受阻止 var isEscapableTag = function(rEscapableTag){ return function(tag){ return rEscapableTag.test(tag) } }(/input|textarea/i) // 判斷是否設置爲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 = {}))
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事件響應函數" [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的基礎上按其餘鍵" [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 "是否設置爲可編輯元素"} content-editable? identity) (def ^{:doc "是否設置爲只讀"} 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)))
尊重原創,轉載請註明來自:http://www.cnblogs.com/fsjohn... ^_^肥仔John