var _plugins = {}; function _plugin(name, fn) { if (name === undefined) { return _plugins; } if (!fn) { return _plugins[name]; } _plugins[name] = fn; } var _language = {}; function _parseLangKey(key) { var match, ns = 'core'; if ((match = /^(\w+)\.(\w+)$/.exec(key))) { ns = match[1]; key = match[2]; } return { ns : ns, key : key }; } /** @example K.lang('about'); //get core.about K.lang('about.version'); // get about.version K.lang('about.').version; // get about.version K.lang('about', 'en'); //get English core.about K.lang({ core.about : '关于', about.version : '4.0' }, 'zh-CN'); //add language */ function _lang(mixed, langType) { langType = langType === undefined ? K.options.langType : langType; if (typeof mixed === 'string') { if (!_language[langType]) { return 'no language'; } var pos = mixed.length - 1; if (mixed.substr(pos) === '.') { return _language[langType][mixed.substr(0, pos)]; } var obj = _parseLangKey(mixed); return _language[langType][obj.ns][obj.key]; } _each(mixed, function(key, val) { var obj = _parseLangKey(key); if (!_language[langType]) { _language[langType] = {}; } if (!_language[langType][obj.ns]) { _language[langType][obj.ns] = {}; } _language[langType][obj.ns][obj.key] = val; }); } // 当前range为图片时返回KNode,否则返回undefined function _getImageFromRange(range, fn) { if (range.collapsed) { return; } range = range.cloneRange().up(); var sc = range.startContainer, so = range.startOffset; if (!_WEBKIT && !range.isControl()) { return; } var img = K(sc.childNodes[so]); if (!img || img.name != 'img') { return; } if (fn(img)) { return img; } } function _bindContextmenuEvent() { var self = this, doc = self.edit.doc; K(doc).contextmenu(function(e) { if (self.menu) { self.hideMenu(); } if (!self.useContextmenu) { e.preventDefault(); return; } if (self._contextmenus.length === 0) { return; } var maxWidth = 0, items = []; _each(self._contextmenus, function() { if (this.title == '-') { items.push(this); return; } if (this.cond && this.cond()) { items.push(this); if (this.width && this.width > maxWidth) { maxWidth = this.width; } } }); while (items.length > 0 && items[0].title == '-') { items.shift(); } while (items.length > 0 && items[items.length - 1].title == '-') { items.pop(); } var prevItem = null; _each(items, function(i) { if (this.title == '-' && prevItem.title == '-') { delete items[i]; } prevItem = this; }); if (items.length > 0) { e.preventDefault(); var pos = K(self.edit.iframe).pos(), menu = _menu({ x : pos.x + e.clientX, themeType : self.themeType, y : pos.y + e.clientY, width : maxWidth, css : { visibility: 'hidden' }, shadowMode : self.shadowMode }); _each(items, function() { if (this.title) { menu.addItem(this); } }); // 下拉菜单超过可视区域时调整菜单位置 var docEl = _docElement(menu.doc), menuHeight = menu.div.height(); if (e.clientY + menuHeight >= docEl.clientHeight - 100) { menu.pos(menu.x, _removeUnit(menu.y) - menuHeight); } menu.div.css('visibility', 'visible'); self.menu = menu; } }); } function _bindNewlineEvent() { var self = this, doc = self.edit.doc, newlineTag = self.newlineTag; if (_IE && newlineTag !== 'br') { return; } if (_GECKO && _V < 3 && newlineTag !== 'p') { return; } if (_OPERA && _V < 9) { return; } var brSkipTagMap = _toMap('h1,h2,h3,h4,h5,h6,pre,li'), pSkipTagMap = _toMap('p,h1,h2,h3,h4,h5,h6,pre,li,blockquote'); // 取得range的block标签名 function getAncestorTagName(range) { var ancestor = K(range.commonAncestor()); while (ancestor) { if (ancestor.type == 1 && !ancestor.isStyle()) { break; } ancestor = ancestor.parent(); } return ancestor.name; } K(doc).keydown(function(e) { /** * 修复 bug: 如果编辑器的最底部的元素是块级元素,如 p, quoteblock, table,则没有办法实现在块级元素后面新增其他元素, * 只能在元素里面新增子元素, 这里通过在后面追加
元素来解决 */ if (e.which == 39) { if (self.__startOffset == self.cmd.range.startOffset) { //console.log("Reaching the bottom"); var tagName = getAncestorTagName(self.cmd.range); if (tagName != 'body') { self.appendHtml('
') } } else { self.__startOffset = self.cmd.range.startOffset } return; } if (e.which != 13 || e.shiftKey || e.ctrlKey || e.altKey) { return; } self.cmd.selection(); var tagName = getAncestorTagName(self.cmd.range); if (tagName == 'marquee' || tagName == 'select') { return; } // br if (newlineTag === 'br' && !brSkipTagMap[tagName]) { e.preventDefault(); self.insertHtml('
' + (_IE && _V < 9 ? '' : '\u200B')); return; } // p if (!pSkipTagMap[tagName]) { _nativeCommand(doc, 'formatblock', '

'); } }); K(doc).keyup(function(e) { if (e.which != 13 || e.shiftKey || e.ctrlKey || e.altKey) { return; } if (newlineTag == 'br') { return; } if (_GECKO) { var root = self.cmd.commonAncestor('p'); var a = self.cmd.commonAncestor('a'); if (a && a.text() == '') { a.remove(true); self.cmd.range.selectNodeContents(root[0]).collapse(true); self.cmd.select(); } return; } self.cmd.selection(); var tagName = getAncestorTagName(self.cmd.range); if (tagName == 'marquee' || tagName == 'select') { return; } if (!pSkipTagMap[tagName]) { _nativeCommand(doc, 'formatblock', '

'); } // [WEBKIT] 将DIV改成P var div = self.cmd.commonAncestor('div'); if (div) { var p = K('

'), child = div[0].firstChild; while (child) { var next = child.nextSibling; p.append(child); child = next; } div.before(p); div.remove(); self.cmd.range.selectNodeContents(p[0]); self.cmd.select(); } }); } function _bindTabEvent() { var self = this, doc = self.edit.doc; K(doc).keydown(function(e) { if (e.which == 9) { e.preventDefault(); if (self.afterTab) { self.afterTab.call(self, e); return; } var cmd = self.cmd, range = cmd.range; range.shrink(); // Bugfix #271: 回车,按下tab键,光标在下一行显示 if (range.collapsed && range.startContainer.nodeType == 1) { range.insertNode(K('@ ', doc)[0]); cmd.select(); } self.insertHtml('    '); } }); } function _bindFocusEvent() { var self = this; K(self.edit.textarea[0], self.edit.win).focus(function(e) { if (self.afterFocus) { self.afterFocus.call(self, e); } }).blur(function(e) { if (self.afterBlur) { self.afterBlur.call(self, e); } }); } function _removeBookmarkTag(html) { return _trim(html.replace(/]*id="?__kindeditor_bookmark_\w+_\d+__"?[^>]*><\/span>/ig, '')); } function _removeTempTag(html) { return html.replace(/]+class="?__kindeditor_paste__"?[^>]*>[\s\S]*?<\/div>/ig, ''); } function _addBookmarkToStack(stack, bookmark) { if (stack.length === 0) { stack.push(bookmark); return; } var prev = stack[stack.length - 1]; if (_removeBookmarkTag(bookmark.html) !== _removeBookmarkTag(prev.html)) { stack.push(bookmark); } } // undo: _undoToRedo.call(this, undoStack, redoStack); // redo: _undoToRedo.call(this, redoStack, undoStack); function _undoToRedo(fromStack, toStack) { var self = this, edit = self.edit, body = edit.doc.body, range, bookmark; if (fromStack.length === 0) { return self; } if (edit.designMode) { range = self.cmd.range; bookmark = range.createBookmark(true); bookmark.html = body.innerHTML; } else { bookmark = { html : body.innerHTML }; } _addBookmarkToStack(toStack, bookmark); var prev = fromStack.pop(); if (_removeBookmarkTag(bookmark.html) === _removeBookmarkTag(prev.html) && fromStack.length > 0) { prev = fromStack.pop(); } if (edit.designMode) { edit.html(prev.html); if (prev.start) { range.moveToBookmark(prev); self.select(); } } else { K(body).html(_removeBookmarkTag(prev.html)); } return self; } function KEditor(options) { var self = this; // save original options self.options = {}; function setOption(key, val) { if (KEditor.prototype[key] === undefined) { self[key] = val; } self.options[key] = val; } // set options from param _each(options, function(key, val) { setOption(key, options[key]); }); // set options from default setting _each(K.options, function(key, val) { if (self[key] === undefined) { setOption(key, val); } }); var se = K(self.srcElement || '