JavaScript(19):HTML DOM 事件




一、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" 事件先被觸發呢?

  1. 冒泡 中,內部元素的事件會先被觸發,然后再觸發外部元素,即:元素的點擊事件先觸發,然后會觸發元素的點擊事件。
  2. 捕獲 中,外部元素的事件會先被觸發,然后才會觸發內部元素的事件,即:元素的點擊事件先觸發 ,然后再觸發元素的點擊事件。

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("提示的內容");


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM