/** * addEvent & removeEvent -- cross-browser event handling * Copyright (C) 2006-2007  Dao Gottwald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA * * Contact information: *   Dao Gottwald  <dao at design-noir.de> * * @version  1.2 */function addEvent(o, type, fn) {  o.addEventListener(type, fn, false);}function removeEvent(o, type, fn) {  o.removeEventListener(type, fn, false);}/*@cc_on if (!window.addEventListener) {  var addEvent = function (o, type, fn) {    if (!o._events) o._events = {};    var queue = o._events[type];    if (!queue) {      o._events[type] = [fn];      if (!o._events._callback)        o._events._callback = function (e) { Event._callListeners(e, o) };      o.attachEvent("on" + type, o._events._callback);    } else if (Event._fnIndex(o, type, fn) == -1)      queue.push(fn);    else return;    Event._mem.push([o, type, fn]);  };  var removeEvent = function (o, type, fn) {    var i = Event._fnIndex(o, type, fn);    if (i < 0) return;    var queue = o._events[type];    if (queue.calling) {      delete queue[i];      if (queue.removeListeners)        queue.removeListeners.push(i);      else        queue.removeListeners = [i];    } else      if (queue.length == 1)        Event._detach(o, type);      else        queue.splice(i, 1);  };  var Event = {    AT_TARGET: 2,    BUBBLING_PHASE: 3,    stopPropagation: function () { this.cancelBubble = true },    preventDefault: function () { this.returnValue = false },    _mem: [],    _callListeners: function (e, o) {      e.stopPropagation = this.stopPropagation;      e.preventDefault = this.preventDefault;      e.currentTarget = o;      e.target = e.srcElement;      e.eventPhase = e.currentTarget == e.target ? this.AT_TARGET : this.BUBBLING_PHASE;      switch (e.type) {        case "mouseover":          e.relatedTarget = e.fromElement;          break;        case "mouseout":          e.relatedTarget = e.toElement;      }      var queue = o._events[e.type];      queue.calling = true;      for (var i = 0, l = queue.length; i < l; i++)        if (queue[i])          if ("handleEvent" in queue[i])            queue[i].handleEvent(e);          else            queue[i].call(o,e);      queue.calling = null;      if (!queue.removeListeners)        return;      if (queue.length == queue.removeListeners.length) {        this._detach(o, e.type);        return;      }      queue.removeListeners = queue.removeListeners.sort(function(a,b){return a-b});      var i = queue.removeListeners.length;      while (i--)        queue.splice(queue.removeListeners[i], 1);      if (queue.length == 0)        this._detach(o, e.type);      else        queue.removeListeners = null;    },    _detach: function (o, type) {      o.detachEvent("on" + type, o._events._callback);      delete o._events[type];    },    _fnIndex: function (o, type, fn) {      var queue = o._events[type];      if (queue)        for (var i = 0, l = queue.length; i < l; i++)          if (queue[i] == fn)            return i;      return -1;    },    _cleanup: function () {      for (var m, i = 0; m = this._mem[i]; i++)        if (m[1] != "unload" || m[2] == this._cleanup)          removeEvent(m[0], m[1], m[2]);    }  };  addEvent(window, "unload", Event._cleanup);} @*/