📄 xquared.js
字号:
/** * Namespace for entire Xquared classes */var xq = { majorVersion: '0.2', minorVersion: '20071205'};/** * Add prototype.js like functions */xq.Class = function() { // TODO var parent = null, properties = xq.$A(arguments); if (typeof properties[0] == "function") parent = properties.shift(); function klass() { this.initialize.apply(this, arguments); } if(parent) { for (var key in parent.prototype) klass.prototype[key] = parent.prototype[key]; } for (var key in properties[0]) klass.prototype[key] = properties[0][key]; if (!klass.prototype.initialize) klass.prototype.initialize = function() {}; klass.prototype.constructor = klass; return klass;}xq.observe = function(element, eventName, handler) { if (element.addEventListener) { element.addEventListener(eventName, handler, false); } else { element.attachEvent('on' + eventName, handler); } element = null;}xq.stopObserving = function(element, eventName, handler) { if (element.removeEventListener) { element.removeEventListener(eventName, handler, false); } else { element.detachEvent("on" + eventName, handler); } element = null;}xq.cancelHandler = function(e) {xq.stopEvent(e); return false};xq.stopEvent = function(event) { if(event.preventDefault) event.preventDefault(); if(event.stopPropagation) event.stopPropagation(); event.returnValue = false; event.cancelBubble = true; event.stopped = true;}xq.isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code);}xq.isLeftClick = function(event) {return isButton(event, 0);}xq.isMiddleClick = function(event) {return isButton(event, 1);}xq.isRightClick = function(event) {return isButton(event, 2);}xq.getEventPoint = function(event) { return { x: event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)), y: event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)) };}xq.getCumulativeOffset = function(element) { var top = 0, left = 0; do { top += element.offsetTop || 0; left += element.offsetLeft || 0; element = element.offsetParent; } while (element); return {top:top, left:left};}xq.$ = function(id) { return document.getElementById(id);}xq.isEmptyHash = function(h) { for(var key in h) { return false; } return true;}xq.$A = function(arraylike) { var len = arraylike.length, a = new Array(len); while (len--) a[len] = arraylike[len]; return a;}xq.hasClassName = function(element, className) { var classNames = element.className; return (classNames.length > 0 && (classNames == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(classNames)));}xq.serializeForm = function(f) {try{ var options = {hash: true}; var data = {}; var elements = f.getElementsByTagName("*"); for(var i = 0; i < elements.length; i++) { var element = elements[i]; var tagName = element.tagName.toLowerCase(); if(element.disabled || !element.name || ['input', 'textarea', 'option', 'select'].indexOf(tagName) == -1) continue; var key = element.name; var value = xq.getValueOfElement(element); if(value === undefined) continue; if(key in data) { if(data[key].constructor == Array) data[key] = [data[key]]; data[key].push(value); } else { data[key] = value; } } return data;} catch(e) {alert(e)}}xq.getValueOfElement = function(e) { var type = e.type.toLowerCase(); if(type == 'checkbox' || type == 'radio') return e.checked ? e.value : undefined; return e.value;}xq.getElementsByClassName = function(element, className) { if(element.getElementsByClassName) return element.getElementsByClassName(className); var elements = element.getElementsByTagName("*"); var len = elements.length; var result = []; var p = new RegExp("(^|\\s)" + className + "($|\\s)"); for(var i = 0; i < len; i++) { var cur = elements[i]; if(p.test(cur.className)) result.push(cur); } return result;}try {Prototype.version; __prototype = true;} catch(ignored) {__prototype = false;}if(!__prototype) { if(!Function.prototype.bind) { Function.prototype.bind = function() { var __m = this, arg = xq.$A(arguments), o = arg.shift(); return function() { return __m.apply(o, arg.concat(xq.$A(arguments))); } } } if(!Function.prototype.bindAsEventListener) { Function.prototype.bindAsEventListener = function() { var __m = this, arg = xq.$A(arguments), o = arg.shift(); return function(event) { return __m.apply(o, [event || window.event].concat(arg)); } } } Array.prototype.find = function(f) { for(var i = 0; i < this.length; i++) { if(f(this[i])) return this[i]; } } Array.prototype.findAll = function(f) { var result = []; for(var i = 0; i < this.length; i++) { if(f(this[i])) result.push(this[i]); } return result; } Array.prototype.first = function() {return this[0]} Array.prototype.last = function() {return this[this.length - 1]} Array.prototype.include = function(o) { if (this.indexOf(o) != -1) return true; var found = false; for(var i = 0; i < this.length; i++) { if(this[i] == o) return true; } return false; } Array.prototype.flatten = function() { var result = []; var _flatten = function(array) { for(var i = 0; i < array.length; i++) { if(array[i].constructor === Array) { _flatten(array[i]); } else { result.push(array[i]); } } } _flatten(this); return result; } String.prototype.blank = function() { return /^\s*$/.test(this); } String.prototype.stripTags = function() { return this.replace(/<\/?[^>]+>/gi, ''); } String.prototype.escapeHTML = function() { xq._text.data = this; return xq._div.innerHTML; } xq._text = document.createTextNode(''); xq._div = document.createElement('div'); xq._div.appendChild(xq._text); String.prototype.strip = function() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); } Array.prototype.indexOf = function(n) { for(var i = 0; i < this.length; i++) { if(this[i] == n) return i; } return -1; }}/** * Make given object as event source * * @param {Object} object target object * @param {String} prefix prefix for generated functions * @param {Array} events array of string which contains name of events */xq.asEventSource = function(object, prefix, events) { object._listeners = [] object._registerEventFirer = function(prefix, name) { this["_fireOn" + name] = function() { for(var i = 0; i < this._listeners.length; i++) { var listener = this._listeners[i]; var func = listener["on" + prefix + name]; if(func) func.apply(listener, xq.$A(arguments)); } } } object.addListener = function(l) { this._listeners.push(l); } for(var i = 0; i < events.length; i++) { object._registerEventFirer(prefix, events[i]); }}Date.preset = null;Date.pass = function(msec) { if(Date.preset == null) return; Date.preset = new Date(Date.preset.getTime() + msec);}Date.get = function() { return Date.preset == null ? new Date() : Date.preset;}Date.prototype.elapsed = function(msec) { return Date.get().getTime() - this.getTime() >= msec;}String.prototype.merge = function(data) { var newString = this; for(k in data) { newString = newString.replace("{" + k + "}", data[k]); } return newString;}String.prototype.parseURL = function() { var m = this.match(/((((\w+):\/\/(((([^@:]+)(:([^@]+))?)@)?([^:\/\?#]+)?(:(\d+))?))?([^\?#]+)?)(\?([^#]+))?)(#(.+))?/); var includeAnchor = m[0]; var includeQuery = m[1] || undefined; var includePath = m[2] || undefined; var includeHost = m[3] || undefined; var includeBase = null; var protocol = m[4] || undefined; var user = m[8] || undefined; var password = m[10] || undefined; var domain = m[11] || undefined; var port = m[13] || undefined; var path = m[14] || undefined; var query = m[16] || undefined; var anchor = m[18] || undefined; if(!path || path == '/') { includeBase = includeHost + '/'; } else { var index = path.lastIndexOf('/'); includeBase = includeHost + path.substring(0, index + 1); } return { includeAnchor: includeAnchor, includeQuery: includeQuery, includePath: includePath, includeBase: includeBase, includeHost: includeHost, protocol: protocol, user: user, password: password, domain: domain, port: port, path: path, query: query, anchor: anchor };}/** * Automatic finalizer */xq.autoFinalizeQueue = [];xq.addToFinalizeQueue = function(obj) { xq.autoFinalizeQueue.push(obj);}xq.finalize = function(obj) { if(typeof obj.finalize == "function") { try {obj.finalize();} catch(ignored) {} } for(key in obj) obj[key] = null;}xq.observe(window, "unload", function() { for(var i = 0; i < xq.autoFinalizeQueue.length; i++) xq.finalize(xq.autoFinalizeQueue[i]); xq = null;});/** * Script loader */xq.findXquaredScript = function() { return xq.$A(document.getElementsByTagName("script")).find(function(script) { return script.src && script.src.match(/xquared\.js/i); });}xq.shouldLoadOthers = function() { var script = xq.findXquaredScript(); return script && !!script.src.match(/xquared\.js\?load_others=1/i);}xq.loadScript = function(url) { document.write('<script type="text/javascript" src="' + url + '"></script>');}xq.loadOthers = function() { var script = xq.findXquaredScript(); var basePath = script.src.match(/(.*\/)xquared\.js.*/i)[1]; var others = [ 'Editor.js', 'Browser.js', 'Shortcut.js', 'DomTree.js', 'RichDom.js', 'RichDomW3.js', 'RichDomGecko.js', 'RichDomWebkit.js', 'RichDomTrident.js', 'RichTable.js', 'Validator.js', 'ValidatorW3.js', 'ValidatorGecko.js', 'ValidatorWebkit.js', 'ValidatorTrident.js', 'EditHistory.js', 'Controls.js', '_ui_templates.js' ]; for(var i = 0; i < others.length; i++) { xq.loadScript(basePath + others[i]); };}if(xq.shouldLoadOthers()) xq.loadOthers();/** * @fileOverview xq.Editor manages configurations such as autocompletion and autocorrection, edit mode/normal mode switching, handles editing commands, keyboard shortcuts and other events. */xq.Editor = xq.Class({ /** * Initialize editor but it doesn't automatically start designMode. setEditMode should be called after initialization. * * @constructor * @param {Object} contentElement HTML element(TEXTAREA or normal block element such as DIV) to be replaced with editable area, or DOM ID string. * @param {Object} toolbarContainer HTML element which contains toolbar icons, or DOM ID string. */ initialize: function(contentElement, toolbarContainer) { xq.addToFinalizeQueue(this); if(typeof contentElement == 'string') contentElement = xq.$(contentElement); if(!contentElement) throw "[contentElement] is null"; if(contentElement.nodeType != 1) throw "[contentElement] is not an element"; if(typeof toolbarContainer == 'string') toolbarContainer = xq.$(toolbarContainer); xq.asEventSource(this, "Editor", ["ElementChanged", "BeforeEvent", "AfterEvent", "CurrentContentChanged", "StaticContentChanged", "CurrentEditModeChanged"]); /** * Editor's configuration * @type object */ this.config = {}; this.config.enableLinkClick = false; this.config.changeCursorOnLink = false; this.config.generateDefaultToolbar = true; this.config.defaultToolbarButtonMap = [ [ {className:"foregroundColor", title:"Foreground color", handler:"xed.handleForegroundColor()"}, {className:"backgroundColor", title:"Background color", handler:"xed.handleBackgroundColor()"} ], [ {className:"link", title:"Link", handler:"xed.handleLink()"}, {className:"strongEmphasis", title:"Strong emphasis", handler:"xed.handleStrongEmphasis()"}, {className:"emphasis", title:"Emphasis", handler:"xed.handleEmphasis()"}, {className:"underline", title:"Underline", handler:"xed.handleUnderline()"},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -