一、HTML DOM 事件
1、HTML 事件屬性
如需向 HTML 元素分配 事件,您可以使用事件屬性。
向 button 元素分配 onclick 事件:
<button onclick="displayDate()">點這里</button> //名為 displayDate 的函數將在按鈕被點擊時執行。
2、使用 HTML DOM 來分配事件
向 button 元素分配 onclick 事件:按鈕點擊時Javascript函數將會被執行。
<script> document.getElementById("myBtn").onclick=function(){displayDate()}; //名為 displayDate 的函數被分配給 id="myBtn" 的 HTML 元素。 </script>
3、onload 和 onunload 事件
onload 和 onunload 事件會在用戶進入或離開頁面時被觸發。
onload 事件可用於檢測訪問者的瀏覽器類型和瀏覽器版本,並基於這些信息來加載網頁的正確版本。
onload 和 onunload 事件可用於處理 cookie。
<body onload="checkCookies()">
4、onchange 事件
onchange 事件常結合對輸入字段的驗證來使用。
下面是一個如何使用 onchange 的例子。當用戶改變輸入字段的內容時,會調用 upperCase() 函數。
<input type="text" id="fname" onchange="upperCase()">
5、onmouseover 和 onmouseout 事件
onmouseover 和 onmouseout 事件可用於在用戶的鼠標移至 HTML 元素上方或移出元素時觸發函數。
<div onmouseover="mOver(this)" onmouseout="mOut(this)" style="background-color:#D94A38;width:120px;height:20px;padding:40px;">Mouse Over Me</div> <script> function mOver(obj){ obj.innerHTML="Thank You" } function mOut(obj){ obj.innerHTML="Mouse Over Me" } </script>
6、onmousedown、onmouseup 以及 onclick 事件
onmousedown, onmouseup 以及 onclick 構成了鼠標點擊事件的所有部分。
首先當點擊鼠標按鈕時,會觸發 onmousedown 事件;當釋放鼠標按鈕時,會觸發 onmouseup 事件;最后,當完成鼠標點擊時,會觸發 onclick 事件。
<div onmousedown="mDown(this)" onmouseup="mUp(this)" style="background-color:#D94A38;width:200px;height:50px;padding-top:25px;text-align:center;"> 點擊這里 </div> <script> function mDown(obj) { obj.style.backgroundColor="#1ec5e5"; obj.innerHTML="松開鼠標" } function mUp(obj) { obj.style.backgroundColor="#D94A38"; obj.innerHTML="謝謝你" } </script>
二、HTML DOM 事件監聽器
1、addEventListener() 語法
addEventListener() 方法用於向指定元素添加事件句柄。
語法:element.addEventListener(event, function, useCapture);
- 第一個參數是事件的類型 (如 "click" 或 "mousedown").
- 第二個參數是事件觸發后調用的函數。
- 第三個參數是個布爾值用於描述事件是冒泡還是捕獲。該參數是可選的。
注意:不要使用 "on" 前綴。 例如,使用 "click" ,而不是使用 "onclick"。
2、向原元素添加事件句柄
當用戶點擊元素時彈出 "Hello World!" :
element.addEventListener("click", function(){ alert("Hello World!"); });
在用戶點擊按鈕時觸發監聽事件:
document.getElementById("myBtn").addEventListener("click", displayDate);
function displayDate() { alert ("Hello World!"); }
3、向同一個元素中添加多個事件句柄
- 你可以向同個元素添加多個同類型的事件句柄,如:兩個 "click" 事件。
- addEventListener() 方法添加的事件句柄不會覆蓋已存在的事件句柄。
element.addEventListener("click", myFunction); element.addEventListener("click", mySecondFunction);
4、向一個元素添加多個事件句柄
element.addEventListener("mouseover", myFunction); element.addEventListener("click", mySecondFunction); element.addEventListener("mouseout", myThirdFunction);
5、向任何 DOM 對象添加事件監聽
不僅僅是 HTML 元素。如: window 對象。
addEventListener() 方法允許你在 HTML DOM 對象添加事件監聽, HTML DOM 對象如: HTML 元素, HTML 文檔, window 對象。或者其他支出的事件對象如: xmlHttpRequest 對象。
當用戶重置窗口大小時添加事件監聽:
window.addEventListener("resize", function(){ document.getElementById("demo").innerHTML = sometext; });
6、傳遞參數
當傳遞參數值時,使用"匿名函數"調用帶參數的函數:
element.addEventListener("click", function(){ myFunction(p1, p2); });
7、事件冒泡或事件捕獲
addEventListener() 方法可以更簡單的控制事件(冒泡與捕獲)。當你使用 addEventListener() 方法時, JavaScript 從 HTML 標記中分離開來,可讀性更強, 在沒有控制HTML標記時也可以添加事件監聽。
事件傳遞有兩種方式:冒泡與捕獲。
事件傳遞定義了元素事件觸發的順序。 如果你將元素插入到元素中,用戶點擊元素, 哪個元素的 "click" 事件先被觸發呢?
- 在 冒泡 中,內部元素的事件會先被觸發,然后再觸發外部元素,即:元素的點擊事件先觸發,然后會觸發元素的點擊事件。
- 在 捕獲 中,外部元素的事件會先被觸發,然后才會觸發內部元素的事件,即:元素的點擊事件先觸發 ,然后再觸發元素的點擊事件。
addEventListener() 方法可以指定 "useCapture" 參數來設置傳遞類型:
addEventListener(event, function, useCapture); 默認值為 false, 即冒泡傳遞,當值為 true 時, 事件使用捕獲傳遞。
document.getElementById("myDiv").addEventListener("click", myFunction, true);
8、removeEventListener() 方法
你可以使用 removeEventListener() 方法來移除事件的監聽。
removeEventListener() 方法移除由 addEventListener() 方法添加的事件句柄:
element.removeEventListener("mousemove", myFunction);
三、跨瀏覽器的事件注冊函數
js中事件監聽方法總共有三種,分別如下所示:
- element.addEventListener(type, listener[, useCapture]); // IE6~8不支持,支持事件冒泡和捕獲
- element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持,只支持事件冒泡
- element[’on’ + type] = function(){} // 所有瀏覽器,只支持事件冒泡,不支持對同一個元素的同一個事件注冊多個事件監聽器
不是所有的事件都能冒泡,例如:blur、focus、load、unload。
1、綁定事件
IE 8 及更早 IE 版本,Opera 7.0及其更早版本不支持 addEventListener() 和 removeEventListener() 方法。但是,對於這類瀏覽器版本可以使用 detachEvent() 方法來移除事件句柄:
- element.attachEvent(event, function);
- element.detachEvent(event, function);
function addHandler(element, type, handler) { //綁定事件 if (element.addEventListener) { // IE9以下不兼容 element.addEventListener(type, handler, false) } else if (element.attachEvent) { //IE獨有 element.attachEvent('on' + type, handler) } else { element['on' + type] = handler; //一個元素只能綁定一個處理程序 } }
2、取消綁定事件
和綁定事件的處理基本一致,有一個注意點:傳入的handler必須與綁定事件時傳入的相同(指向同一個函數)
function removeHandler(element, type, handler) { //移除事件 if (element.removeEventListener) { //addEventListener element.removeEventListener(type, handler, false) } else if (element.detachEvent) { //attachEvent element.detachEvent('on' + type, handler) } else { element['on' + type] = null; } }
3、阻止默認行為
function preventDefault(event) { if (event.preventDefault) { event.preventDefault() } else { event.returnValue = false; } }
4、停止冒泡
function stoppropagation(event) { if (event.stopPropagation) { event.stopPropagation() } else { evenvt.cancelBubble = true; } }
5、獲取事件和目標
function getEvent(event) { return event ? event: window.event; } function getTarget(event) { return event.target || event.srcElement }
6、Handler.js—可移植事件處理程序注冊函數
/* * Handler.js -- Portable event-handler registration functions * * This module defines event-handler registration and deregistration functions * Handler.add( ) and Handler.remove( ). Both functions take three arguments: * * element: the DOM element, document, or window on which the handler * is to be added or removed. * * eventType: a string that specifies the type of event for which the * handler is to be invoked. Use DOM-standard type names, which do * not include an "on" prefix. Examples: "click", "load", "mouseover". * * handler: The function to be invoked when an event of the specified type * occurs on the specified element. This function will be invoked as * a method of the element on which it is registered, and the "this" * keyword will refer to that element. The handler function will be * passed an event object as its sole argument. This event object will * either be a DOM-standard Event object or a simulated one. If a * simulated event object is passed, it will have the following DOM- * compliant properties: type, target, currentTarget, relatedTarget, * eventPhase, clientX, clientY, screenX, screenY, altKey, ctrlKey, * shiftKey, charCode, stopPropagation( ), and preventDefault( ) * * Handler.add( ) and Handler.remove( ) have no return value. * * Handler.add( ) ignores duplicate registrations of the same handler for * the same event type and element. Handler.remove( ) does nothing if called * to remove a handler that has not been registered. * * Implementation notes: * * In browsers that support the DOM standard addEventListener( ) and * removeEventListener( ) event-registration functions, Handler.add( ) and * Handler.remove( ) simply invoke these functions, passing false as the * third argument (meaning that the event handlers are never registered as * capturing event handlers). * * In versions of Internet Explorer that support attachEvent( ), Handler.add( ) * and Handler.remove() use attachEvent( ) and detachEvent( ). To * invoke the handler function with the correct this keyword, a closure is * used. Since closures of this sort cause memory leaks in Internet Explorer, * Handler.add( ) automatically registers an onunload handler to deregister * all event handlers when the page is unloaded. To keep track of * registered handlers, Handler.add( ) creates a property named _allHandlers on * the window object and creates a property named _handlers on any element on * which a handler is registered. */ var Handler = {}; // In DOM-compliant browsers, our functions are trivial wrappers around // addEventListener( ) and removeEventListener( ). if (document.addEventListener) { Handler.add = function(element, eventType, handler) { element.addEventListener(eventType, handler, false); }; Handler.remove = function(element, eventType, handler) { element.removeEventListener(eventType, handler, false); }; } // In IE 5 and later, we use attachEvent( ) and detachEvent( ), with a number of // hacks to make them compatible with addEventListener and removeEventListener. else if (document.attachEvent) { Handler.add = function(element, eventType, handler) { // Don't allow duplicate handler registrations // _find( ) is a private utility function defined below. if (Handler._find(element, eventType, handler) != -1) return; // To invoke the handler function as a method of the // element, we've got to define this nested function and register // it instead of the handler function itself. var wrappedHandler = function(e) { if (!e) e = window.event; // Create a synthetic event object with partial compatibility // with DOM events. var event = { _event: e, // In case we really want the IE event object type: e.type, // Event type target: e.srcElement, // Where the event happened currentTarget: element, // Where we're handling it relatedTarget: e.fromElement?e.fromElement:e.toElement, eventPhase: (e.srcElement==element)?2:3, // Mouse coordinates clientX: e.clientX, clientY: e.clientY, screenX: e.screenX, screenY: e.screenY, // Key state altKey: e.altKey, ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, charCode: e.keyCode, // Event-management functions stopPropagation: function( ) {this._event.cancelBubble = true;}, preventDefault: function( ) {this._event.returnValue = false;} } // Invoke the handler function as a method of the element, passing // the synthetic event object as its single argument. // Use Function.call( ) if defined; otherwise do a hack if (Function.prototype.call) handler.call(element, event); else { // If we don't have Function.call, fake it like this. element._currentHandler = handler; element._currentHandler(event); element._currentHandler = null; } }; // Now register that nested function as our event handler. element.attachEvent("on" + eventType, wrappedHandler); // Now we must do some record keeping to associate the user-supplied // handler function and the nested function that invokes it. // We have to do this so that we can deregister the handler with the // remove( ) method and also deregister it automatically on page unload. // Store all info about this handler into an object. var h = { element: element, eventType: eventType, handler: handler, wrappedHandler: wrappedHandler }; // Figure out what document this handler is part of. // If the element has no "document" property, it is not // a window or a document element, so it must be the document // object itself. var d = element.document || element; // Now get the window associated with that document. var w = d.parentWindow; // We have to associate this handler with the window, // so we can remove it when the window is unloaded. var id = Handler._uid( ); // Generate a unique property name if (!w._allHandlers) w._allHandlers = {}; // Create object if needed w._allHandlers[id] = h; // Store the handler info in this object // And associate the id of the handler info with this element as well. if (!element._handlers) element._handlers = []; element._handlers.push(id); // If there is not an onunload handler associated with the window, // register one now. if (!w._onunloadHandlerRegistered) { w._onunloadHandlerRegistered = true; w.attachEvent("onunload", Handler._removeAllHandlers); } }; Handler.remove = function(element, eventType, handler) { // Find this handler in the element._handlers[] array. var i = Handler._find(element, eventType, handler); if (i == -1) return; // If the handler was not registered, do nothing // Get the window of this element. var d = element.document || element; var w = d.parentWindow; // Look up the unique id of this handler. var handlerId = element._handlers[i]; // And use that to look up the handler info. var h = w._allHandlers[handlerId]; // Using that info, we can detach the handler from the element. element.detachEvent("on" + eventType, h.wrappedHandler); // Remove one element from the element._handlers array. element._handlers.splice(i, 1); // And delete the handler info from the per-window _allHandlers object. delete w._allHandlers[handlerId]; }; // A utility function to find a handler in the element._handlers array // Returns an array index or -1 if no matching handler is found Handler._find = function(element, eventType, handler) { var handlers = element._handlers; if (!handlers) return -1; // if no handlers registered, nothing found // Get the window of this element var d = element.document || element; var w = d.parentWindow; // Loop through the handlers associated with this element, looking // for one with the right type and function. // We loop backward because the most recently registered handler // is most likely to be the first removed one. for(var i = handlers.length-1; i >= 0; i--) { var handlerId = handlers[i]; // get handler id var h = w._allHandlers[handlerId]; // get handler info // If handler info matches type and handler function, we found it. if (h.eventType == eventType && h.handler == handler) return i; } return -1; // No match found }; Handler._removeAllHandlers = function( ) { // This function is registered as the onunload handler with // attachEvent. This means that the this keyword refers to the // window in which the event occurred. var w = this; // Iterate through all registered handlers for(id in w._allHandlers) { // Get handler info for this handler id var h = w._allHandlers[id]; // Use the info to detach the handler h.element.detachEvent("on" + h.eventType, h.wrappedHandler); // Delete the handler info from the window delete w._allHandlers[id]; } } // Private utility to generate unique handler ids Handler._counter = 0; Handler._uid = function( ) { return "h" + Handler._counter++; }; }
調用:
Handler.add(document,”click”,function(e){alert(e.stopPropagation);});
四、Event事件對象
1、事件的返回值
事件默認返回true,會繼續執行默認動作.
onsubmit , onclick , onkeydown , onkeypress , onmousedown , onmouseup 和 onreset 返回false會阻止他們的默認行為發生.
Event是其他所有的事件父類,所有的事件都實現了這個接口.
支持屬性:
- type: 觸發的事件的名稱,如"click" 或 "mouseover"
- target: 發生事件的節點
- currentTarget: 當前正在處理該事件的節點,在捕捉階段或起泡階段他的值與target的值不同.在事件處理函數中應該用這個屬性而不是this來指代當前處理的節點
- eventPhase: 一個數字,指定了當前事件所處的傳播過程的階段.它的值是常量,可以是Event.CAPTURING_PHASE或Event.AT_TARGET或Event.BUBBLING_PHASE.
- timeStamp: 一個Date對象,表明事件的發生時間
- bubbles: 布爾值,表明該事件是否起泡
- cancelable :布爾值,表明事件是否可以用preventDefault()方法來取消默認的動作.
- stopPropagation( ): 停止事件的傳播
- preventDefault( ) :阻止默認事件發生,和0級DOM中返回false的作用類似
四、Key Event事件對象
IE和Firefox系列的模型
通常,一次按鍵有3個過程keydown, keypress, 和 keyup.
- 如果用戶按鍵事件足夠長,在keyup事件觸發之前,會觸發多次keydown事件
- keypress為輸入的ASCII字符,如"@"等.不可打印字符如空格,回車, 退格,方向鍵,F1到F12,如果沒有對應的ASCII碼,不產生該事件
- keypress,keyup為"virtual keycode" ,如同時按下 "shift"和"2", 發生事件"shift-2"
- altKey, ctrlKey, shiftKey屬性可以用來查詢這三個鍵的狀態(ALT在IE中不產生keypress事件),當按下時為true,否則為false
為了獲得嵌入的字符,
- Firefox定義了兩個屬性keyCode(返回"virtual keycode")和charCode(返回字符編碼),對於不可打印字符,charCode是0.
- IE中只有keyCode屬性,為keydown事件時,keyCode是virtual keycode;為keypress事件時, keyCodes是字符編碼
3級DOM並沒有標准化keyCode,而是定義了新屬性key,因此如果考慮后續符合規范,需要同時考慮使用key屬性。key和keyCode的區別是,key不是unicode編碼,而是直接的字符。
下邊提供一個Keymap類,可以利用它把按鍵標識映射成JavaScript函數,這些函數作為這些按鍵的響應而調用。Keymap.js:
/* * Keymap.js: bind key events to handler functions. * * This module defines a Keymap class. An instance of this class represents a * mapping of key identifiers (defined below) to handler functions. A * Keymap can be installed on an HTML element to handle keydown and keypress * events. When such an event occurs, the Keymap uses its mapping to invoke * the appropriate handler function. * * When you create a Keymap, pass a JavaScript object that represents the * initial set of bindings for the Keymap. The property names of this object * are key identifers, and the property values are the handler functions. * * After a Keymap has been created, you can add new bindings by passing a key * identifer and handler function to the bind( ) method. You can remove a * binding by passing a key identifier to the unbind( ) method. * * To make use of a Keymap, call its install( ) method, passing an HTML element, * such as the document object. install( ) adds an onkeypress and onkeydown * event handler to the specified object, replacing any handlers previously set * on those properties. When these handlers are invoked, they determine the * key identifier from the key event and invoke the handler function, if any, * bound to that key identifier. If there is no mapping for the event, it uses * the default handler function (see below), if one is defined. A single * Keymap may be installed on more than one HTML element. * * Key Identifiers * * A key identifier is a case-insensitive string representation of a key plus * any modifier keys that are held down at the same time. The key name is the * name of the key: this is often the text that appears on the physical key of * an English keyboard. Legal key names include "A", "7", "F2", "PageUp", * "Left", "Delete", "/", "~". For printable keys, the key name is simply the * character that the key generates. For nonprinting keys, the names are * derived from the KeyEvent.DOM_VK_ constants defined by Firefox. They are * simply the constant name, with the "DOM_VK_" portion and any underscores * removed. For example, the KeyEvent constant DOM_VK_BACK_SPACE becomes * BACKSPACE. See the Keymap.keyCodeToFunctionKey object in this module for a * complete list of names. * * A key identifier may also include modifier key prefixes. These prefixes are * Alt_, Ctrl_, and Shift_. They are case-insensitive, but if there is more * than one, they must appear in alphabetical order. Some key identifiers that * include modifiers include "Shift_A", "ALT_F2", and "alt_ctrl_delete". Note * that "ctrl_alt_delete" is not legal because the modifiers are not in * alphabetical order. * * Shifted punctuation characters are normally returned as the appropriate * character. Shift-2 generates a key identifier of "@", for example. But if * Alt or Ctrl is also held down, the unshifted symbol is used instead. * We get a key identifier of Ctrl_Shift_2 instead of Ctrl_@, for example. * * Handler Functions * * When a handler function is invoked, it is passed three arguments: * 1) the HTML element on which the key event occurred * 2) the key identifier of the key that was pressed * 3) the event object for the keydown event * * Default Handler * * The reserved key name "default" may be mapped to a handler function. That * function will be invoked when no other key-specific binding exists. * * Limitations * * It is not possible to bind a handler function to all keys. The operating * system traps some key sequences (Alt-F4, for example). And the browser * itself may trap others (Ctrl-S, for example). This code is browser, OS, * and locale-dependent. Function keys and modified function keys work well, * and unmodified printable keys work well. The combination of Ctrl and Alt * with printable characters, and particularly with punctuation characters, is * less robust. */ // This is the constructor function function Keymap(bindings) { this.map = {}; // Define the key identifier->handler map if (bindings) { // Copy initial bindings into it, converting to lowercase for(name in bindings) this.map[name.toLowerCase( )] = bindings[name]; } } // Bind the specified key identifier to the specified handler function Keymap.prototype.bind = function(key, func) { this.map[key.toLowerCase( )] = func; }; // Delete the binding for the specified key identifier Keymap.prototype.unbind = function(key) { delete this.map[key.toLowerCase( )]; }; // Install this Keymap on the specified HTML element Keymap.prototype.install = function(element) { // This is the event-handler function var keymap = this; function handler(event) { return keymap.dispatch(event); } // Now install it if (element.addEventListener) { element.addEventListener("keydown", handler, false); element.addEventListener("keypress", handler, false); } else if (element.attachEvent) { element.attachEvent("onkeydown", handler); element.attachEvent("onkeypress", handler); } else { element.onkeydown = element.onkeypress = handler; } }; // This object maps keyCode values to key names for common nonprinting // function keys. IE and Firefox use mostly compatible keycodes for these. // Note, however that these keycodes may be device-dependent and different // keyboard layouts may have different values. Keymap.keyCodeToFunctionKey = { 8:"backspace", 9:"tab", 13:"return", 19:"pause", 27:"escape", 32:"space", 33:"pageup", 34:"pagedown", 35:"end", 36:"home", 37:"left", 38:"up", 39:"right", 40:"down", 44:"printscreen", 45:"insert", 46:"delete", 112:"f1", 113:"f2", 114:"f3", 115:"f4", 116:"f5", 117:"f6", 118:"f7", 119:"f8", 120:"f9", 121:"f10", 122:"f11", 123:"f12", 144:"numlock", 145:"scrolllock" }; // This object maps keydown keycode values to key names for printable // characters. Alphanumeric characters have their ASCII code, but // punctuation characters do not. Note that this may be locale-dependent // and may not work correctly on international keyboards. Keymap.keyCodeToPrintableChar = { 48:"0", 49:"1", 50:"2", 51:"3", 52:"4", 53:"5", 54:"6", 55:"7", 56:"8", 57:"9", 59:";", 61:"=", 65:"a", 66:"b", 67:"c", 68:"d", 69:"e", 70:"f", 71:"g", 72:"h", 73:"i", 74:"j", 75:"k", 76:"l", 77:"m", 78:"n", 79:"o", 80:"p", 81:"q", 82:"r", 83:"s", 84:"t", 85:"u", 86:"v", 87:"w", 88:"x", 89:"y", 90:"z", 107:"+", 109:"-", 110:".", 188:",", 190:".", 191:"/", 192:"'", 219:"[", 220:"//", 221:"]", 222:"/"" }; // This method dispatches key events based on the keymap bindings. Keymap.prototype.dispatch = function(event) { var e = event || window.event; // Handle IE event model // We start off with no modifiers and no key name var modifiers = "" var keyname = null; if (e.type == "keydown") { var code = e.keyCode; // Ignore keydown events for Shift, Ctrl, and Alt if (code == 16 || code == 17 || code == 18) return; // Get the key name from our mapping keyname = Keymap.keyCodeToFunctionKey[code]; // If this wasn't a function key, but the ctrl or alt modifiers are // down, we want to treat it like a function key if (!keyname && (e.altKey || e.ctrlKey)) keyname = Keymap.keyCodeToPrintableChar[code]; // If we found a name for this key, figure out its modifiers. // Otherwise just return and ignore this keydown event. if (keyname) { if (e.altKey) modifiers += "alt_"; if (e.ctrlKey) modifiers += "ctrl_"; if (e.shiftKey) modifiers += "shift_"; } else return; } else if (e.type == "keypress") { // If ctrl or alt are down, we've already handled it. if (e.altKey || e.ctrlKey) return; // In Firefox we get keypress events even for nonprinting keys. // In this case, just return and pretend it didn't happen. if (e.charCode != undefined && e.charCode == 0) return; // Firefox gives us printing keys in e.charCode, IE in e.charCode var code = e.charCode || e.keyCode; // The code is an ASCII code, so just convert to a string. keyname=String.fromCharCode(code); // If the key name is uppercase, convert to lower and add shift // We do it this way to handle CAPS LOCK; it sends capital letters // without having the shift modifier set. var lowercase = keyname.toLowerCase( ); if (keyname != lowercase) { keyname = lowercase; // Use the lowercase form of the name modifiers = "shift_"; // and add the shift modifier. } } // Now that we've determined the modifiers and key name, we look for // a handler function for the key and modifier combination var func = this.map[modifiers+keyname]; // If we didn't find one, use the default handler, if it exists if (!func) func = this.map["default"]; if (func) { // If there is a handler for this key, handle it // Figure out what element the event occurred on var target = e.target; // DOM standard event model if (!target) target = e.srcElement; // IE event model // Invoke the handler function func(target, modifiers+keyname, e); // Stop the event from propagating, and prevent the default action for // the event. Note that preventDefault doesn't usually prevent // top-level browser commands like F1 for help. if (e.stopPropagation) e.stopPropagation( ); // DOM model else e.cancelBubble = true; // IE model if (e.preventDefault) e.preventDefault( ); // DOM else e.returnValue = false; // IE return false; // Legacy event model } }; /** * InputFilter.js: unobtrusive filtering of keystrokes for tags * * This module finds all "text"> elements in the document that * have a nonstandard attribute named "allowed". It registers an onkeypress * event handler for any such element to restrict the user's input so that * only characters that appear in the value of the allowed attribute may be * entered. If the element also has an attribute named "messageid", * the value of that attribute is taken to be the id of another document * element. If the user types a character that is not allowed, the messageid * element is made visible. If the user types a character that is allowed, * the messageid element is hidden. This message id element is intended to * offer an explanation to the user of why her keystroke was rejected. It * should typically be styled with CSS so that it is initially invisible. * * Here is some sample HTML that uses this module. * Zipcode: * "zip" type="text" allowed="0123456789" messageid="zipwarn"> * "zipwarn" style="color:red;visibility:hidden">Digits only * * In browsers such as IE, which do not support addEventListener( ), the * keypress handler registered by this module overwrites any keypress handler * defined in HTML. * * This module is purely unobtrusive: it does not define any symbols in * the global namespace. */ (function( ) { // The entire module is within an anonymous function // When the document finishes loading, call the init( ) function below if (window.addEventListener) window.addEventListener("load", init, false); else if (window.attachEvent) window.attachEvent("onload", init); // Find all the tags we need to register an event handler on function init( ) { var inputtags = document.getElementsByTagName("input"); for(var i = 0 ; i < inputtags.length; i++) { // Loop through all tags var tag = inputtags[i]; if (tag.type != "text") continue; // We only want text fields var allowed = tag.getAttribute("allowed"); if (!allowed) continue; // And only if they have an allowed attr // Register our event handler function on this input tag if (tag.addEventListener) tag.addEventListener("keypress", filter, false); else { // We don't use attachEvent because it does not invoke the // handler function with the correct value of the this keyword. tag.onkeypress = filter; } } } // This is the keypress handler that filters the user's input function filter(event) { // Get the event object and character code in a portable way var e = event || window.event; // Key event object var code = e.charCode || e.keyCode; // What key was pressed // If this keystroke is a function key of any kind, do not filter it if (e.charCode == 0) return true; // Function key (Firefox only) if (e.ctrlKey || e.altKey) return true; // Ctrl or Alt held down if (code < 32) return true; // ASCII control character // Now look up information we need from this input element var allowed = this.getAttribute("allowed"); // Legal chars var messageElement = null; // Message to hide/show var messageid = this.getAttribute("messageid"); // Message id, if any if (messageid) // If there is a message id, get the element messageElement = document.getElementById(messageid); // Convert the character code to a character var c = String.fromCharCode(code); // See if the character is in the set of allowed characters if (allowed.indexOf(c) != -1) { // If c is a legal character, hide the message, if any if (messageElement) messageElement.style.visibility = "hidden"; return true; // And accept the character } else { // If c is not in the set of allowed characters, display message if (messageElement) messageElement.style.visibility = "visible"; // And reject this keypress event if (e.preventDefault) e.preventDefault( ); if (e.returnValue) e.returnValue = false; return false; } } })( ); // Finish anonymous function and invoke it.
五、加載事件 onload Event
onload回在文檔完全加載完成后運行
一個跨平台的版本
function runOnLoad(f) { if (runOnLoad.loaded) f( ); // If already loaded, just invoke f( ) now. else runOnLoad.funcs.push(f); // Otherwise, store it for later } runOnLoad.funcs = []; // The array of functions to call when the document loads runOnLoad.loaded = false; // The functions have not been run yet. // Run all registered functions in the order in which they were registered. // It is safe to call runOnLoad.run( ) more than once: invocations after the // first do nothing. It is safe for an initialization function to call // runOnLoad( ) to register another function. runOnLoad.run = function( ) { if (runOnLoad.loaded) return; // If we've already run, do nothing for(var i = 0; i < runOnLoad.funcs.length; i++) { try { runOnLoad.funcs[i]( ); } catch(e) { /* An exception in one function shouldn't stop the rest */ } } runOnLoad.loaded = true; // Remember that we've already run once. delete runOnLoad.funcs; // But don't remember the functions themselves. delete runOnLoad.run; // And forget about this function too! }; // Register runOnLoad.run( ) as the onload event handler for the window if (window.addEventListener) window.addEventListener("load", runOnLoad.run, false); else if (window.attachEvent) window.attachEvent("onload", runOnLoad.run); else window.onload = runOnLoad.run;
六、鼠標事件
MouseEvent是UIEvent的一個子類
支持屬性:
- button: 一個數字,表明在mousedown,mouseup和click中,那個鼠標鍵改變了狀態.0表示左鍵,1表示中鍵,2表示右鍵.
- altKey , ctrlKey, metaKey, shiftKey: 表明對應的鍵盤上的鍵的狀態(PC上,Meta鍵通常對應 Alt 鍵)
- screenX , screenY: 鼠標指針相對於屏幕左上角X,Y坐標,如果你想在鼠標附近彈出一個窗口,這個值很有用
- clientX, clientY: 鼠標指針相對於瀏覽器頁面顯示部分左上角的X,Y坐標,注意,這個值不考慮文檔滾動。
如果需要相對於文檔的位置,IE中可以加上document.body.scrollLeft和document.body.scrollTop,其他瀏覽器可以加上window.pageXOffset and window.pageYOffset - relatedTarget: 該屬性僅對mouseover和mouseout生效。對於mouseover是它離開的節點,對於mouseout是它進入的節點.
button 點擊時按下的是鼠標的哪個鍵(不同瀏覽器的賦值不同,不易使用)
拖動文檔元素:
/** * 拖動絕對定位的HTML元素 * 該方法依賴之前收集的getScrollOffset方法 */ function drag( elementToDrag, event ){ // 初始化鼠標位置,轉換為文檔坐標 var scroll = getScrollOffset(), startX = event.clientX + scroll.x, startY = event.clientY + scroll,y, // 這里假設了elementToDrag的offsetParent是文檔的body元素,似乎會有問題 origX = elementToDrag.offsetLeft, origY = elementToDrag.offsetTop, deltaX = startX - origX, deltaY = startY - origY; if( document.addEventListener ){ document.addEventListener( "mousemove", movehandler, true ); document.addEventListener( "mouseup", upHandler, true ); }else if( document.attachEvent ){ // IE的事件模型中,捕獲事件是通過調用元素上的setCapture()實現的 elementToDrag.setCapture(); elementToDrag.attachEvent( "onmousemove", moveHandler ); elementToDrag.attachEvent( "onmouseup", upHandler ); // 作為mouseup事件看待鼠標捕獲的丟失??? elementToDrag.attachEvent( "onlosecapture", upHandler ); } if( event.stopPropagation ) event.stopPropagation(); else event.cancelBubble = true; // 現在阻止任何默認操作 if( event.preventDefault ) event.preventDefault(); else event.returnValue = false; function moveHandler( e ){ if( !e ) e = window.event; var scroll = getScrollOffset(); elementToDrag.style.left = ( e.clientX + scroll.x - deltaX ) + "px"; elementToDrag.style.top = ( e.clientY + scroll.y -deltaY ) + "px"; if( e.stopPropagation ) e.stopPropagation(); else e.cancelBubble = true; } function upHandler( e ){ if( !e ) e = window.event; if( document.removeEventListener ){ document.removeEventListener( "mouseup", upHandler, true ); document.removeEventListener( "mousemove", movehandler, true ); }else if( document.attachEvent ){ elementToDrag.detachEvent( "onlosecapture", upHandler ); elementToDrag.detachEvent( "onmouseup", upHandler ); elementToDrag.detachEvent( "onmousemove", movehandler ); elementToDrag.releasecapture(); } if( e.stopPropagation ) e.stopPropagation(); else e.cancelBubble = true; } }
調用:
<div style="position:absolute;left:120px;top:150px;width:250px; border:1px solid black;"> <div style="background-color:#416ea5; width:250px;height:22px;cursor:move;font-weight:bold; border-bottom:1px solid black;" onmousedown="drag(this.parentNode, event);">可拖動標題</div> <p>可被拖動的窗口</p> <p>窗口內容</p> </div> <img src="image/logo.jpg" alt="按住Shift可拖動" style="position:absolute;" onmousedοwn="if (event.shiftKey) drag(this, event);" />
tooltip 彈出層
鼠標坐標窗口幾何屬性,Geometry.js
var Geometry = {}; if (window.screenLeft) { Geometry.getWindowX = function() { return window.screenLeft; }; Geometry.getWindowY = function() { return window.screenTop; }; } else if (window.screenX) { Geometry.getWindowX = function() { return window.screenX; }; Geometry.getWindowY = function() { return window.screenY; }; } if (window.innerWidth) { Geometry.getViewportWidth = function() { return window.innerWidth; }; Geometry.getviewportHeight = function() { return window.innerHeight; }; Geometry.getHorizontalScroll = function() { return window.pageXOffset; }; Geometry.getVerticalScroll = function() { return window.pageYOffset; }; } else if (document.documentElement && document.documentElement.clientWidth) { Geometry.getViewportWidth = function() { return document.documentElement.clientWidth; }; Geometry.getviewportHeight = function() { return document.documentElement.clientHeight; }; Geometry.getHorizontalScroll = function() { return document.documentElement.scrollLeft; }; Geometry.getVerticalScroll = function() { return document.documentElement.scrollTop; }; } else if (document.body.clientWidth) { Geometry.getViewportWidth = function() { return document.body.clientWidth; }; Geometry.getviewportHeight = function() { return document.body.clientHeight; }; Geometry.getHorizontalScroll = function() { return document.body.scrollLeft; }; Geometry.getVerticalScroll = function() { return document.body.scrollTop; }; } if (document.documentElement && document.documentElement.scrollWidth) { Geometry.getDocumentWidth = function() { return document.documentElement.scrollWidth; }; Geometry.getDocumentHeight = function() { return document.documentElement.scrollHeight; }; } else if (document.body.scrollWidth) { Geometry.getDocumentWidth = function() { return document.body.scrollWidth; }; Geometry.getDocumentHeight = function() { return document.body.scrollHeight; }; }
Tooltip.js
Tooltip.X_OFFSET = 25; Tooltip.Y_OFFSET = 15; Tooltip.DELAY = 500; Tooltip.Text; function Tooltip() { this.tooltip = document.createElement("div");//create div for shadow this.tooltip.style.position = "absolute";// this.tooltip.style.visibility = "hidden"; this.tooltip.className = "tooltipShadow"; this.content = document.createElement("div");//create div for content this.content.style.position = "relative"; this.content.className = "tooltipContent"; this.tooltip.appendChild(this.content); } Tooltip.prototype.show = function(text, x, y) { this.content.innerHTML = text; this.tooltip.style.left = x + "px"; this.tooltip.style.top = y + "px"; this.tooltip.style.visibility = "visible"; if (this.tooltip.parentNode != document.body) document.body.appendChild(this.tooltip); }; Tooltip.prototype.hide = function() { this.tooltip.style.visibility = "hidden"; }; Tooltip.prototype.schedule = function(target, e) { var text = Tooltip.Text; if (!text) return; var x = e.clientX + Geometry.getHorizontalScroll(); var y = e.clientY + Geometry.getVerticalScroll(); x += Tooltip.X_OFFSET; y += Tooltip.Y_OFFSET; var self = this; var timer = window.setTimeout(function() { self.show(text, x, y); }, Tooltip.DELAY); if (target.addEventListener) target.addEventListener("mouseout", mouseout, false); else if (target.attachEvent) target.attachEvent("onmouseout", mouseout); else target.onmouseout = mouseout; function mouseout() { self.hide(); window.clearTimeout(timer); if (target.removeEventListener) target.removeEventListener("mouseout", mouseout, false); else if (target.detachEvent) target.detachEvent("mouseout", mouseout); else target.onmouseout = null; } }; Tooltip.tooltip = new Tooltip(); Tooltip.schedule = function(target, e) { Tooltip.tooltip.schedule(target, e); } Tooltip.init = function(value){Tooltip.Text = value};
tooltip.css
.tooltipShadow { background-color:#A9A9A9; } .tooltipContent { left:-4px; top:-4px; background-color:#F0F8FF; border:solid black 1px; padding:5px; font:9pt sans-serif; color:#0000CC; width:150px; }
使用:
在jsp需要提示的地方加入οnmοusemοve="Tooltip.schedule(this,event)"。js中要設置提示的內容Tooltip.init("提示的內容");