• 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;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" 事件先被触发呢?

    1. 冒泡 中,内部元素的事件会先被触发,然后再触发外部元素,即: <p> 元素的点击事件先触发,然后会触发 <div> 元素的点击事件。
    2. 捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即: <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};
    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("提示的内容");

  • 相关阅读:
    在ubuntu下安装phpmyadmin 出现404错误
    Jquery插件收藏
    PHP 时区设置
    Jquery动态进行图片缩略
    CSS设置图片垂直居中的方法
    解决CI框架的Disallowed Key Characters错误提示
    @Component默认是单例还是多例?
    ehcache的heap、off-heap、desk浅谈
    nginx负载均衡分配策略有哪些?
    HashSet的实现原理,简单易懂
  • 原文地址:https://www.cnblogs.com/springsnow/p/12407650.html
Copyright © 2020-2023  润新知