一、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;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;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标记时也可以添加事件监听。
事件传递有两种方式:冒泡与捕获。
事件传递定义了元素事件触发的顺序。 如果你将 <p> 元素插入到 <div> 元素中,用户点击 <p> 元素, 哪个元素的 "click" 事件先被触发呢?
- 在 冒泡 中,内部元素的事件会先被触发,然后再触发外部元素,即: <p> 元素的点击事件先触发,然后会触发 <div> 元素的点击事件。
- 在 捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即: <div> 元素的点击事件先触发 ,然后再触发 <p> 元素的点击事件。
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事件对象
事件的返回值
事件默认返回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 <input> tags * * This module finds all <input type="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 <input> 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: * <input id="zip" type="text" allowed="0123456789" messageid="zipwarn"> * <span id="zipwarn" style="color:red;visibility:hidden">Digits only</SPAN> * * 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 <input> 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;250px; border:1px solid black;"> <div style="background-color:#416ea5; 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};
.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("提示的内容");