var _useCapture = false; /** DOM_VK_BACK_SPACE : 8 DOM_VK_TAB : 9 DOM_VK_RETURN : 13 DOM_VK_SPACE : 32 DOM_VK_PAGE_UP : 33 DOM_VK_PAGE_DOWN : 34 DOM_VK_END : 35 DOM_VK_HOME : 36 DOM_VK_LEFT : 37 DOM_VK_UP : 38 DOM_VK_RIGHT : 39 DOM_VK_DOWN : 40 DOM_VK_DELETE : 46 DOM_VK_0 ~ DOM_VK_9 : 48 ~ 57 DOM_VK_SEMICOLON : 59 (;:) DOM_VK_EQUALS : 61 (=+) (+) DOM_VK_A ~ DOM_VK_Z : 65 ~ 90 DOM_VK_MULTIPLY : 106 (*) DOM_VK_SUBTRACT : 109 (-_) (-) DOM_VK_DECIMAL : 110 (.) DOM_VK_DIVIDE : 111 (/) DOM_VK_COMMA : 188 (,<) DOM_VK_PERIOD : 190 (.>) DOM_VK_SLASH : 191 (/?) DOM_VK_BACK_QUOTE : 192 (`~) DOM_VK_OPEN_BRACKET : 219 ([{) DOM_VK_BACK_SLASH : 220 (\|) DOM_VK_CLOSE_BRACKET : 221 (]}) DOM_VK_QUOTE : 222 ('") */ // 输入文字的键值 var _INPUT_KEY_MAP = _toMap('8,9,13,32,46,48..57,59,61,65..90,106,109..111,188,190..192,219..222'); // 移动光标的键值 var _CURSORMOVE_KEY_MAP = _toMap('33..40'); // 输入文字或移动光标的键值 var _CHANGE_KEY_MAP = {}; _each(_INPUT_KEY_MAP, function(key, val) { _CHANGE_KEY_MAP[key] = val; }); _each(_CURSORMOVE_KEY_MAP, function(key, val) { _CHANGE_KEY_MAP[key] = val; }); // add native event function _bindEvent(el, type, fn) { if (el.addEventListener){ el.addEventListener(type, fn, _useCapture); } else if (el.attachEvent){ el.attachEvent('on' + type, fn); } } // remove native event function _unbindEvent(el, type, fn) { if (el.removeEventListener){ el.removeEventListener(type, fn, _useCapture); } else if (el.detachEvent){ el.detachEvent('on' + type, fn); } } var _EVENT_PROPS = ('altKey,attrChange,attrName,bubbles,button,cancelable,charCode,clientX,clientY,ctrlKey,currentTarget,' + 'data,detail,eventPhase,fromElement,handler,keyCode,metaKey,newValue,offsetX,offsetY,originalTarget,pageX,' + 'pageY,prevValue,relatedNode,relatedTarget,screenX,screenY,shiftKey,srcElement,target,toElement,view,wheelDelta,which').split(','); // create KEvent class function KEvent(el, event) { this.init(el, event); } _extend(KEvent, { init : function(el, event) { var self = this, doc = el.ownerDocument || el.document || el; self.event = event; _each(_EVENT_PROPS, function(key, val) { self[val] = event[val]; }); if (!self.target) { self.target = self.srcElement || doc; } if (self.target.nodeType === 3) { self.target = self.target.parentNode; } if (!self.relatedTarget && self.fromElement) { self.relatedTarget = self.fromElement === self.target ? self.toElement : self.fromElement; } if (self.pageX == null && self.clientX != null) { var d = doc.documentElement, body = doc.body; self.pageX = self.clientX + (d && d.scrollLeft || body && body.scrollLeft || 0) - (d && d.clientLeft || body && body.clientLeft || 0); self.pageY = self.clientY + (d && d.scrollTop || body && body.scrollTop || 0) - (d && d.clientTop || body && body.clientTop || 0); } if (!self.which && ((self.charCode || self.charCode === 0) ? self.charCode : self.keyCode)) { self.which = self.charCode || self.keyCode; } if (!self.metaKey && self.ctrlKey) { self.metaKey = self.ctrlKey; } if (!self.which && self.button !== undefined) { self.which = (self.button & 1 ? 1 : (self.button & 2 ? 3 : (self.button & 4 ? 2 : 0))); } /** DOM_VK_SEMICOLON : 59 (;:) - IE,WEBKIT: 186 - GECKO,OPERA : 59 DOM_VK_EQUALS : 61 (=+) - IE,WEBKIT : 187 - GECKO : 107 - OPERA : 61 DOM_VK_NUMPAD0 ~ DOM_VK_NUMPAD9 : 96 ~ 105 - IE、WEBKIT,GECKO : 96 ~ 105 - OPERA : 48 ~ 57 DOM_VK_MULTIPLY : 106 (*) - IE、WEBKIT,GECKO : 106 - OPERA : 42 DOM_VK_ADD : 107 (+) - IE、WEBKIT,GECKO : 107 - OPERA : 43 DOM_VK_SUBTRACT : 109 (-_) (-) - IE,WEBKIT : 189, 109 - GECKO : 109, 109 - OPERA : 109, 45 DOM_VK_DECIMAL : 110 (.) - IE、WEBKIT,GECKO : 110 - OPERA : 78 DOM_VK_DIVIDE : 111 (/) - IE、WEBKIT,GECKO : 111 - OPERA : 47 Reference: https://developer.mozilla.org/en/DOM/Event/UIEvent/KeyEvent http://msdn.microsoft.com/en-us/library/ms536940(v=VS.85).aspx */ switch (self.which) { case 186 : self.which = 59; break; case 187 : case 107 : case 43 : self.which = 61; break; case 189 : case 45 : self.which = 109; break; case 42 : self.which = 106; break; case 47 : self.which = 111; break; case 78 : self.which = 110; break; } if (self.which >= 96 && self.which <= 105) { self.which -= 48; } }, preventDefault : function() { var ev = this.event; if (ev.preventDefault) { ev.preventDefault(); } else { ev.returnValue = false; } }, stopPropagation : function() { var ev = this.event; if (ev.stopPropagation) { ev.stopPropagation(); } else { ev.cancelBubble = true; } }, stop : function() { this.preventDefault(); this.stopPropagation(); } }); var _eventExpendo = 'kindeditor_' + _TIME, _eventId = 0, _eventData = {}; function _getId(el) { return el[_eventExpendo] || null; } function _setId(el) { el[_eventExpendo] = ++_eventId; return _eventId; } function _removeId(el) { try { delete el[_eventExpendo]; } catch(e) { if (el.removeAttribute) { el.removeAttribute(_eventExpendo); } } } function _bind(el, type, fn) { if (type.indexOf(',') >= 0) { _each(type.split(','), function() { _bind(el, this, fn); }); return; } var id = _getId(el); if (!id) { id = _setId(el); } if (_eventData[id] === undefined) { _eventData[id] = {}; } var events = _eventData[id][type]; if (events && events.length > 0) { _unbindEvent(el, type, events[0]); } else { _eventData[id][type] = []; _eventData[id].el = el; } events = _eventData[id][type]; if (events.length === 0) { events[0] = function(e) { var kevent = e ? new KEvent(el, e) : undefined; _each(events, function(i, event) { if (i > 0 && event) { event.call(el, kevent); } }); }; } if (_inArray(fn, events) < 0) { events.push(fn); } _bindEvent(el, type, events[0]); } function _unbind(el, type, fn) { if (type && type.indexOf(',') >= 0) { _each(type.split(','), function() { _unbind(el, this, fn); }); return; } var id = _getId(el); if (!id) { return; } if (type === undefined) { if (id in _eventData) { _each(_eventData[id], function(key, events) { if (key != 'el' && events.length > 0) { _unbindEvent(el, key, events[0]); } }); delete _eventData[id]; _removeId(el); } return; } if (!_eventData[id]) { return; } var events = _eventData[id][type]; if (events && events.length > 0) { if (fn === undefined) { _unbindEvent(el, type, events[0]); delete _eventData[id][type]; } else { _each(events, function(i, event) { if (i > 0 && event === fn) { events.splice(i, 1); } }); if (events.length == 1) { _unbindEvent(el, type, events[0]); delete _eventData[id][type]; } } var count = 0; _each(_eventData[id], function() { count++; }); if (count < 2) { delete _eventData[id]; _removeId(el); } } } function _fire(el, type) { if (type.indexOf(',') >= 0) { _each(type.split(','), function() { _fire(el, this); }); return; } var id = _getId(el); if (!id) { return; } var events = _eventData[id][type]; if (_eventData[id] && events && events.length > 0) { events[0](); } } function _ctrl(el, key, fn) { var self = this; key = /^\d{2,}$/.test(key) ? key : key.toUpperCase().charCodeAt(0); _bind(el, 'keydown', function(e) { if (e.ctrlKey && e.which == key && !e.shiftKey && !e.altKey) { fn.call(el); e.stop(); } }); } var _readyFinished = false; function _ready(fn) { if (_readyFinished) { fn(KindEditor); return; } var loaded = false; function readyFunc() { if (!loaded) { loaded = true; fn(KindEditor); _readyFinished = true; } } function ieReadyFunc() { if (!loaded) { try { document.documentElement.doScroll('left'); } catch(e) { setTimeout(ieReadyFunc, 100); return; } readyFunc(); } } function ieReadyStateFunc() { if (document.readyState === 'complete') { readyFunc(); } } if (document.addEventListener) { _bind(document, 'DOMContentLoaded', readyFunc); } else if (document.attachEvent) { _bind(document, 'readystatechange', ieReadyStateFunc); // 在跨域的frame里调用会报错 var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if (document.documentElement.doScroll && toplevel) { ieReadyFunc(); } } _bind(window, 'load', readyFunc); } /** Note: 发现绑定dbclick事件后移除element会有内存泄漏,以下代码也不起作用。 Reference: http://isaacschlueter.com/2006/10/msie-memory-leaks/ http://msdn.microsoft.com/en-us/library/bb250448.aspx */ if (window.attachEvent) { window.attachEvent('onunload', function() { _each(_eventData, function(key, events) { if (events.el) { _unbind(events.el); } }); }); } K.ctrl = _ctrl; K.ready = _ready;