+function($){ /** * 定义基础内部全局变量 */ var /** * 当前window对象 * @type {jQuery Object} */ $win = $(window), /** * 当前document对象 * @type {jQuery Object} */ $doc = $(document), /** * ThinkEditor 对象 * @type {Object} */ ThinkEditor, /** * 封装过的textarea Range对象 * @type {Object} */ Range, /** * 编辑器弹出层对象 * 主要提供给一些需要复杂功能的插件使用 * 在插件中使用 this.dialog()方法调用 * @type {Object} */ Dialog, /** * ThinkEditor插件对象,所有的操作都是通过该对象实现 * @type {Object} */ Plugin = {}, /** * ThinkEditor语言包对象 */ Language = {}, /** * 键盘按键对应数值表 * @type {Object} */ KeyCode = { "BACKSPACE" : 8, "TAB" : 9, "ENTER" : 13, "ESC" : 27, "SPACE" : 32, "F1" : 112, "F2" : 113, "F3" : 114, "F4" : 115, "F5" : 116, "F6" : 117, "F7" : 118, "F8" : 119, "F9" : 120, "F10" : 121, "F11" : 122, "F12" : 123 }, /** * 默认配置项,创建Tree时传入的配置项会和该配置合并 * @type {Object} */ Defaults = { /** * 显示风格 * 目前仅支持默认风格,可自己扩展 */ "style" : "default", /** * 编辑器插件按钮配置 * 没配置到这里的插件不能显示在工具栏 * 如果设置了快捷键依然生效 */ "items" : "h1,h2,h3,h4,h5,h6,-,link,image,-,bold,italic,code,-," + "ul,ol,blockquote,hr,-,fullscreen,save", /** * 编辑器默认宽度 * 默认自适应父容器 */ "width" : "100%", /** * 编辑器高度,默认自适应父容器 * 设置为100%时一定要给父元素设置高度 */ "height" : "100%", /** * 编辑器显示语言 * 目前仅支持简体中文和英文 * 可以在调用编辑器之前调用$.thinkeditor.language方法扩展 */ "lang" : "zh-cn", /** * 按TAB键插入的字符 * 默认为四个空格,一般情况下为空格或制表符 * 插入制表符请写 \t */ "tab" : " ", /** * 图片上传插件上传到的URL * 该URL必须返回JSON数据 * 数据格式: * { * "status" : 1, * "info" : "message", * "files" : [] //文件信息 * } */ "uploader" : "", /** * 图片上传表单名称 * 即name属性默认设置的值 */ "dataName" : "images", /** * 保存按钮点击后调用的回调函数 */ "onSave" : $.noop //保存按钮回调接口 }, DialogWraper = [ '
', '
', '', '', '
', '
', '', '
' ].join(""); /** * Range构造器,用于创建一个新的Range对象 * @param {Object} textarea 一个textarea对象,用于创建Range */ Range = function(textarea){ /* 绑定Range对象的textarea */ this.textarea = textarea; } /** * 扩展Range原型,主要添加了get,set,insert三个方法 * @type {Object} */ Range.prototype = { /** * 获取当前range * @return {Object} 当前range对象 */ "get" : function(){ var textarea = this.textarea, data = {"start" : 0, "end" : 0, "text" : ""}, range, dupRange, rangeNl, dupRangeNl; textarea.focus(); if (textarea.setSelectionRange) { // W3C data.start = textarea.selectionStart; data.end = textarea.selectionEnd; data.text = (data.start != data.end) ? textarea.value.substring(data.start, data.end) : ""; } else if (document.selection) { // For IE range = document.selection.createRange(), dupRange = range.duplicate(); dupRange.moveToElementText(textarea); dupRange.setEndPoint("EndToEnd", range ); data.text = range.text; //选中的文本内容 rangeNl = range.text.split("\n").length - 1; //选中文本换行数 dupRangeNl = dupRange.text.split("\n").length - 1; //选中之前换行数 data.start = dupRange.text.length - range.text.length - dupRangeNl + rangeNl; data.end = data.text.length + data.start - rangeNl; } return data; }, /** * 设置当前range的位置 * @param {Integer} start 起始位置 * @param {Integer} end 结束位置 * @return {Object} 当前Range对象 */ "set" : function (start, end) { var range, textarea = this.textarea; textarea.focus(); if (textarea.setSelectionRange) { // W3C textarea.setSelectionRange(start, end); } else if (textarea.createTextRange) { // For IE range = textarea.createTextRange(); range.collapse(true); range.moveStart("character", start); range.moveEnd("character", end - start); range.select(); } return this; }, /** * 在当前Range处插入文本 * @param {String} text 文本内容 * @return {Object} 当前Range对象 */ "insert" : function (text) { var textarea = this.textarea, data = this.get(), oValue, nValue, range, scroll; if (textarea.setSelectionRange) { // W3C oValue = textarea.value; nValue = oValue.substring(0, data.start) + text + oValue.substring(data.end); scroll = textarea.scrollTop; data.end = data.start + text.length; textarea.value = nValue; /** * Fixbug: * After textarea.values = nValue, scrollTop value to 0 */ if(textarea.scrollTop != scroll) { textarea.scrollTop = scroll; } textarea.setSelectionRange(data.start, data.end); } else if (textarea.createTextRange) { //For IE range = document.selection.createRange(); range.text = text; range.setEndPoint("StartToEnd", range); range.select(); } return this; } }; /** * 简单的弹出层对象,供需要弹出显示的插件调用 * @param {Object} editor 编辑器对象 * @param {Object} options 编辑器配置对象 */ Dialog = function(editor, options){ var self = this, $dialog, $modal, defaults, $editor = $(editor.range.textarea).closest(".thinkeditor"); /* 弹出层默认配置 */ defaults = { "title" : "title", "content" : "
", "onOkClick" : $.noop, "onCancelClick" : $.noop } //合并配置并创建弹出层 options = $.extend({}, defaults, options || {}); /* 创建弹出层内容区 */ this.dialog = $dialog = $(DialogWraper).appendTo($editor); //创建遮罩层 this.modal = $modal = $("
").addClass("thinkeditor-dialog-modal") .appendTo($editor); /* 弹出层相关容器 */ this.title = $dialog.find(".thinkeditor-dialog-title"); //标题 this.content = $dialog.find(".thinkeditor-dialog-body"); //内容 this.status = $dialog.find(".thinkeditor-dialog-status"); //状态信息 /* 弹出层按钮 */ this.btn = { "close" : $dialog.find(".thinkeditor-dialog-close"), "ok" : $dialog.find(".thinkeditor-dialog-btn-ok"), "cancel" : $dialog.find(".thinkeditor-dialog-btn-cancel") } /* 绑定关闭事件 */ this.btn.close.click(function(){ self.remove(); }); /* 绑定确定按钮事件 */ this.btn.ok.click(function(){ options.onOkClick.call(self, this); }); /* 绑定取消按钮事件 */ this.btn.cancel.click(function(){ options.onCancelClick.call(self, this); self.remove(); }); //添加弹出层内容并 this.setTitle(options.title); this.setContent(options.content); this.btn.ok.text(editor.lang("ok")); this.btn.cancel.text(editor.lang("cancel")); //显示弹出层 $dialog.add($modal).fadeIn("fast"); } /** * 弹出层标准接口 * @type {Object} */ Dialog.prototype = { /** * 查找弹出层内容里的元素 * @param {String} expr jQuery支持的所有选择器 * @return {Object} jQuery对象 */ "find" : function(expr){ return this.content.find(expr); }, /** * 移动弹出层到屏幕中央 * @return {Object} 弹出层对象 */ "moveToCenter" : function(){ this.dialog.css({ "top" : ($win.height() - this.dialog.outerHeight()) / 2, "left" : ($win.width() - this.dialog.outerWidth()) / 2 }); return this; }, /** * 重置弹出层内容 * @param {Object} content 弹出层内容对象,可以是html代码 * @return {Object} 弹出层对象 */ "setContent" : function(content){ this.content.empty().append(content); this.moveToCenter(); return this; }, /** * 改变弹出层标题 * @param {String} title 弹出层标题文字,可以是html代码 * @return {Object} 弹出层对象 */ "setTitle" : function(title){ return this.title.html(title); }, /** * 设置弹出层状态信息 * @param {String} info 状态信息 * @param {String} status 状态标识,success,error * @param {Boolean} dealy 是否自动关闭 * @return {Object} 当前弹出层对象 */ "setStatus" : function(info, status, dealy){ var $status = $("").text(info), timeout; /* 清楚原来计时器 */ timeout = this.status.children("span").data("timeout"); timeout && clearTimeout(timeout); /* 显示状态信息 */ status && $status.addClass("thinkeditor-dialog-" + status); this.status.empty().append($status); /* 延时关闭 */ if(dealy){ $status.data("timeout", setTimeout(function(){ $status.fadeOut("fast"); }, 5000)); } return this; }, /** * 卸载当前弹出层 */ "remove" : function(){ this.dialog.add(this.modal).fadeOut("fast", function(){ this.remove(); }); } }; /** * 创建编辑器工具栏 * @param {Object} $editor 编辑器对象 * @param {Object} options 配置项 */ function create_editor_tools($editor, options){ var self = this, items, groups = options.items.split(",-,"), $group, $tools = $("
"); /* 创建按钮组 */ for(i in groups){ items = groups[i].split(","); $group = $("
").addClass("thinkeditor-tools-group") .appendTo($tools); for(j in items){ $("").addClass("thinkeditor-tools-" + items[j]) .attr({"title" : this.lang(items[j]), "href" : "javascript:;"}) .data("name", items[j]) .appendTo($group); } } /* 工具栏放入editor */ $tools.addClass("thinkeditor-tools clearfix").prependTo($editor); /* 绑定操作事件 */ $tools.on("click", ".thinkeditor-tools-group a", function(event){ event.stopPropagation(); self.plugin($(this).data("name"), options); }); } /** * 执行快捷键 * @param {event} event 事件对象 */ function keyboard(event){ var keyboard = Array(4), self = event.data.self, options = event.data.options; /* 当前按键 */ keyboard[0] = event.ctrlKey ? "ctrl" : ""; keyboard[1] = event.shiftKey ? "shift" : ""; keyboard[2] = event.altKey ? "alt" : ""; keyboard[3] = event.which; keyboard = keyboard.join(""); /* 执行快捷键 */ if(self.keyboards[keyboard]){ if($.isFunction(self.keyboards[keyboard])){ self.keyboards[keyboard].call(self); } else { self.plugin(self.keyboards[keyboard], options); } return false; } } /** * 编辑器构造器,用于创建一个新的编辑器对象 * @param {Object} textarea 被创建编辑器的textarea对象 * @param {Object} options 编辑器初始化选项 */ ThinkEditor = function(textarea, options){ var options, self = this, $textarea = $(textarea), $editor; /* 合并配置项 */ options = $.extend({}, Defaults, options || {}); options.width = options.width ? options.width : $textarea.width(); options.height = options.height ? options.height : $textarea.height(); /* 创建Range对象 */ this.range = new Range(textarea); this.language = Language[options.lang] ? options.lang : "en-us"; /* 创建编辑器 */ $textarea.wrap("
").parent().wrap("
"); $editor = $textarea.parent().parent(); $editor.addClass("thinkeditor thinkeditor-" + options.style); $editor.children("div").addClass("thinkeditor-textarea"); //如果是预览创建预览div if(options.preview){ options.width = '50%'; $textarea.parent().after('
'); $textarea.css({resize: 'none'}); $preview = $editor.find('.thinkeditor-textarea').next('div'); } /* 设置editor尺寸 */ $editor.css({"width" : options.width, "height" : options.height}); /* 创建工具栏 */ create_editor_tools.call(this, $editor, options); /* 绑定快捷键事件 */ $textarea.keydown({"self" : this, "options" : options}, keyboard); /* 绑定插件的快捷键 */ for(name in Plugin){ Plugin[name].keyboard && this.keyboard(Plugin[name].keyboard, name); } if(options.preview){ $preview.css({ "width" : '100%', "height" : $textarea.outerHeight(true)+'px', left: '100%' }); $preview.addClass('thinkeditor-preview'); $preview.html(this.preview(this.range.textarea.value)); _this = this; $textarea.keyup(function(){ $preview.html(_this.preview(this.value)); }); $textarea.scroll(function(){ fix_img_scroll(); }); var fix_img_scroll = function(){ imgs = $preview.find("img") //获取预览下所有图片 if (imgs.length > 0){ imgs_height = 0 for (var i in imgs){ tm = new Image() tm.src = this.src tow = tm.width toh = tm.height var limit_width = $preview.width()*0.5 //父容器50%的宽度 if (tow > limit_width){ //如果原始图片宽度大于限制宽度,真实rh高度也要缩放比例 r = tow / limit_width rh = toh / r }else{ rh = toh } imgs_height += rh //这个就是得到所有图片的高度 } } caculate_and_scroll($textarea, $preview, imgs_height); } var caculate_and_scroll = function(editor, preview, imgs_height){ //这里只要再按比例计算一下滚动高度就行 real_height = preview[0].scrollHeight + imgs_height; setTimeout(function(){ if (real_height > editor[0].scrollHeight){ r = real_height / editor[0].scrollHeight; preview.prop('scrollTop', editor.scrollTop() * r); }else{ r = editor[0].scrollHeight / real_height; preview.prop('scrollTop', editor.scrollTop() / r); } }, 500); } } } /** * 编辑器原型,用于扩展编辑器的外部调用接口 * @type {Object} */ ThinkEditor.prototype = { /** * 获取语言变量 * @param {String} name 变量名 * @param {String} language 语言,默认去当前options.lang * @return {String} 指定语言的值 */ "lang" : function(name, language){ return Language[language || this.language][name] || name; }, /** * 执行某个插件插件 * @param {String} name 插件名称 * @param {Object} options 编辑器配置项 */ "plugin" : function(name, options){ var plugin = Plugin[name] plugin.markdown.call(this, options, plugin); return this; }, /** * 插入数据到编辑器光标处 * @param {String} text 要插入的数据 * @return {Object} ThinkEditor对象 */ "insert" : function(text){ var range = this.range.get(), start, _start, end, length, line = 0; if(arguments.length > 1){ //首尾添加文本 start = arguments[0]; end = arguments[1]; if(arguments[2]){ //按行添加 text = range.text.split("\n"); length = range.text.length; /* 逐行添加 */ for(i in text){ if(!length || $.trim(text[i])){ _start = start.replace("{$line}", ++line) .replace("{$i}", i); text[i] = _start + text[i] + end; } } /* 插入数据 */ this.range.insert(text.join("\n")); /* 没有选中文本时设置光标位置 */ if(!length){ start = range.start + _start.length; this.range.set(start, start); } } else { this.range.insert(start + range.text + end); } } else { //插入文本 this.range.insert(text); } return this; }, /** * 设置或获取编辑器的值 * @param {String} text 要设置的值,不传递此参数则获取编辑器的值 * @return {String} 设置值 - 返回ThinkEditor对象, 获取值 - 返回当前值 */ "value" : function(text){ if(text === undefined){ return this.range.textarea.value; } else { this.range.textarea.value = text; return this; } }, /** * 给编辑器绑定快捷键 * @param {String} keys 快捷键名称 * @param {Function} callback 触发快捷键时执行额函数或插件名称 * @return {Object} 当前编辑器对象 */ "keyboard" : function(keys, callback){ var keyboard = Array(4); //[ctrl, shift, alt, code] //初始化快捷键 if(!this.keyboards) { this.keyboards = {}; } keys = keys.toUpperCase().split("+"); for(i in keys){ switch(keys[i]){ case "CTRL" : keyboard[0] = "ctrl"; break; case "SHIFT" : keyboard[1] = "shift"; break; case "ALT" : keyboard[2] = "alt"; break; default: keyboard[3] = KeyCode[keys[i]] || keys[i].charCodeAt(); break; } } this.keyboards[keyboard.join("")] = callback; return this; }, "dialog" : function(options){ return new Dialog(this, options); }, "preview": function(text){ var opt = { renderer: new marked.Renderer(), gfm: true, tables: true, breaks: false, pedantic: false, sanitize: true, smartLists: true, smartypants: false } return marked(text, opt); } } /** * 通过textarea获取通过当前textarea创建的ThinkEditor对象 * @param {elements} textarea textarea对象或jquery textarea选择器 * @return {Object} ThinkEditor对象 */ $.thinkeditor = function(textarea){ return $(textarea).data("ThinkEditor"); }; /** * 添加ThinkEditor全局扩展 * 提供对编辑器的语言包,插件,全局设置等功能 */ $.extend($.thinkeditor, { /** * 扩展语言包 * @param {Object} language 语言包 */ "language" : function(language){ $.extend(Language, $.isPlainObject(language) ? language : {}); }, /** * 扩展插件 * @param {Object} plugin 一个或多个插件 */ "plugin" : function(plugin){ $.extend(Plugin, $.isPlainObject(plugin) ? plugin : {}); }, /** * 全局设置ThinkEditor * @param {Object} options 要改变的编辑器默认设置项 */ "defaults" : function(options){ $.extend(Defaults, $.isPlainObject(options) ? options : {}); } }); /** * jQuery.fn对象,用于创建ThinkEditor插件 * @param {Object} options ThinkEditor初始化参数 */ $.fn.thinkeditor = function(options){ return this.each(function(){ $(this).data("ThinkEditor", new ThinkEditor(this, options)); }); } /** * ThinkEditor编辑器插件,工具按显示的每一个按钮代表一个插件 * 一个合法的插件必须包含markdown方法,用于内部调用 * 如果需要给插件设置快捷键,则可以通过 keyboard 属性来设置 * 插件的this指针指向当前ThinkEditor对象 */ $.thinkeditor.plugin({ /* 标题一插件 */ "h1" : { /* 标题一快捷键 */ "keyboard" : "ctrl+1", /* 执行标题一 */ "markdown" : function(options){ this.insert("# ", "", true); } }, /* 标题二插件 */ "h2" : { /* 标题二快捷键 */ "keyboard" : "ctrl+2", /* 执行标题二 */ "markdown" : function(options){ this.insert("## ", "", true); } }, /* 标题三插件 */ "h3" : { /* 标题三快捷键 */ "keyboard" : "ctrl+3", /* 执行标题三 */ "markdown" : function(options){ this.insert("### ", "", true); } }, /* 标题四插件 */ "h4" : { /* 标题四快捷键 */ "keyboard" : "ctrl+4", /* 执行标题四 */ "markdown" : function(options){ this.insert("#### ", "", true); } }, /* 标题五插件 */ "h5" : { /* 标题五快捷键 */ "keyboard" : "ctrl+5", /* 执行标题五 */ "markdown" : function(options){ this.insert("##### ", "", true); } }, /* 标题六插件 */ "h6" : { /* 标题六快捷键 */ "keyboard" : "ctrl+6", /* 执行标题六 */ "markdown" : function(options){ this.insert("###### ", "", true); } }, /* 添加链接 */ "link" : { /* 连接快捷键 */ "keyboard" : "ctrl+l", /* 插入连接 */ "markdown" : function(options){ var range = this.range.get(), start; if(range.text.length){ if(range.text.match(/^http:\/\/.*/i)){ this.insert("[" + range.text + "](" + range.text + ")"); } else { this.insert("[" + range.text + "]()"); start = range.start + range.text.length + 3; this.range.set(start, start); } } else { this.insert("[]()"); start = range.start + 1; this.range.set(start, start); } } }, /* 添加图片 */ "image" : { /* 图片快捷键 */ "keyboard" : "ctrl+p", /* 插入图片 */ "markdown" : function(options, self){ var $text, drop, dialog, start, editor = this, range = this.range.get(); /* 当选中文本是远程图片URL时不弹出上传层 */ if(range.text.length && range.text.match(/^http:\/\/.*/i)){ this.insert("![ALT](" + range.text + ")"); start = range.start + 2; this.range.set(start, start + 3); return; } //拖动上传容器 $text = $("").text(this.lang("image-text")); self.drop = drop = $("
").addClass("thinkeditor-plugin-image") .append($text); //弹出图片上传层 self.dialog = dialog = this.dialog({ "title" : this.lang("image-title"), "content" : drop, "onOkClick" : function(){ self.upload(editor, options) } }); /* 初始化数据对象 */ self.data = new FormData(); //初始化文件数 self.data.length = 0; /* 绑定drag事件,主要是用来设置文件放置框的样式 */ drop.on("dragenter dragleave", function(event){ drop.toggleClass("thinkeditor-image-draghover"); event.stopPropagation(); return false; }); /* 文件拖动事件,不绑定该事件 drop 事件不生效 */ drop.on("dragover", function(){ return false }); /** * 文件拖动结束事件 * 该事件必须用原生方式绑定,拖动结束后浏览器会自动跳转到图片预览页面 * ?暂不明白是什么原因 */ drop[0].addEventListener("drop", function(event) { var files = event.target.files || event.dataTransfer.files; if(!files) return; //不支持文件拖动 /* 取消拖动样式,阻止事件冒泡及默认事件 */ drop.removeClass("thinkeditor-image-draghover"); event.stopPropagation(); event.preventDefault(); //上传文件 self.show(files, options); }, false); }, /** * 将上传好的图片插入到编辑器 * @param {Array} imgs 上传的图片数组 * @param {Object} editor 图片对象 */ "insert" : function(imgs, editor){ var range = editor.range.get(), img, alt, src, text = []; for(name in imgs){ img = imgs[name]; alt = range.text.length ? range.text : img.name.split(".")[0]; src = img.rootpath + img.savepath + img.savename; text.push("![" + alt + "](" + src + ")"); } editor.insert(text.join("\n")); text = text[0]; editor.range.set(range.start + 2, range.start + text.indexOf("]")); }, /** * 预览选择的图片 * @param {Object} files 选择的图片对象 * @param {Object} options 编辑器配置对象 */ "show" : function(files, options){ var data = this.data, msg; for(var i = 0, file; file = files[i]; i++){ //禁止上传非图片文件 if(!file.type.match(/^image\/(?:png|jpeg|jpg|gif)$/)){ msg = "忽略非图片文件:" + file.name; this.dialog.setStatus(msg, "error", true); } else if(file.size > 1024 * 1024 * 10) { msg = "忽略超过大小限制的图片:" + file.name; this.dialog.setStatus(msg, "error", true); } else { if(data.length < 3){ data.append(options.dataName + i, file); data.length ++; this.reader(file); } else { msg = "最多同时上传3张图片,"; msg += "已忽略" + (files.length - i) + "张"; this.dialog.setStatus(msg, "error", true); break; } } } }, /** * 读取图片数据以提供预览 * @param {Object} file 图片对象 */ "reader" : function(file){ var self = this, reader = new FileReader(); //初始化文件对象 /* 展示选择的图片 */ reader.onload = function(){ var html = [ "
", //用于浮动 "", //再添加一层标签主要是为了解决图片垂直居中 "", "", "
" ].join(""); self.drop.append(html); } reader.readAsDataURL(file); }, /** * AJAX上传图片,只有支持HTML的浏览器才能支持该方法 * @param {Object} editor 编辑器对象 * @param {Object} options 编辑器配置对象 */ "upload" : function(editor, options){ var self = this, xhr = new XMLHttpRequest(), msg; if (!xhr.upload) { msg = "您的浏览器不支持ajax上传文件!"; this.dialog.setStatus(msg, "error", true); return; } // 上传中 xhr.upload.addEventListener("progress", function(event) { var progress = Math.round(event.loaded / event.total); msg = "正在上传图片..." + progress + "%"; self.dialog.setStatus(msg, "success"); }, false); // 文件上传成功或是失败 xhr.onreadystatechange = function() { var data, images = []; if (xhr.readyState == 4) { if (xhr.status == 200) { data = $.parseJSON(xhr.responseText); if(data.status){ self.insert(data.files, editor); self.dialog.remove(); } else { self.dialog.setStatus(data.info, "error", true); } } else { self.dialog.setStatus("图片上传失败!", "error", true); } } }; // 开始上传 this.dialog.setStatus("正在上传图片...0%", "success"); xhr.open("POST", options.uploader, true); xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); xhr.send(this.data); } }, /* 文本加粗插件 */ "bold" : { /* 文本加粗快捷键 */ "keyboard" : "ctrl+b", /* 执行文本加粗 */ "markdown" : function(options){ this.insert("**", "**", true); } }, /* 文字倾斜插件 */ "italic" : { /* 文字倾斜快捷键 */ "keyboard" : "ctrl+i", /* 执行文字倾斜 */ "markdown" : function(options){ this.insert("_", "_", true); } }, /* 插入代码 */ "code" : { /* 代码快捷键 */ "keyboard" : "ctrl+d", /* 插入代码 */ "markdown" : function(options){ var range = this.range.get(), start; if(range.text.length){ if(range.text.split("\n").length > 1){ this.insert("~~~\n"+ range.text +"\n~~~"); start = range.start + 3; this.range.set(start, start); } else { this.insert("`"+ range.text +"`"); } } else { this.insert("``"); start = range.start + 1; this.range.set(start, start); } } }, /* 无序列表插件 */ "ul" : { /* 代码快捷键 */ "keyboard" : "ctrl+u", /* 插入代码 */ "markdown" : function(options){ this.insert("* ", "", true); } }, /* 插入有序列表 */ "ol" : { /* 有序列表捷键 */ "keyboard" : "ctrl+o", /* 插入有序列表 */ "markdown" : function(options){ this.insert("{$line}. ", "", true); } }, /* 引用文本 */ "blockquote" : { /* 引用快捷键 */ "keyboard" : "ctrl+q", /* 插入代码 */ "markdown" : function(options){ this.insert("> ", "", true); } }, /* 插入水平分割线 */ "hr" : { /* 分割线快捷键 */ "keyboard" : "ctrl+h", /* 插入分割线 */ "markdown" : function(options){ var range = this.range.get(), start = range.start + range.text.length + 11; this.insert(range.text + "\n* * * * *\n"); this.range.set(start, start); } }, /* 全屏编辑 */ "fullscreen" : { /* 全屏编辑快捷键 */ "keyboard" : "ctrl+f", /* 执行全屏编辑 */ "markdown" : function(options){ var $body = $("body"), $editor = $(this.range.textarea).closest(".thinkeditor"); if($editor.hasClass("thinkeditor-fullscreen")){ $body.css("overflow", ""); $editor.removeClass("thinkeditor-fullscreen"); } else { $body.css("overflow", "hidden"); $editor.addClass("thinkeditor-fullscreen"); } } }, /* 保存数据 */ "save" : { /* 保存数据快捷键 */ "keyboard" : "ctrl+s", /* 执行全屏编辑 */ "markdown" : function(options){ if($.isFunction(options.onSave)){ options.onSave.call(this.range.textarea); } } }, /* 文本缩进 */ "indent" : { /* 缩进快捷键 */ "keyboard" : "tab", /* 插入缩进 */ "markdown" : function(options){ var range = this.range.get(), text, start; if(range.start){ text = this.range.textarea.value.substring(0, range.start); start = text.lastIndexOf("\n") + 1; if(range.text.length && start != text.length){ this.range.set(start, range.end); } } this.insert(options.tab, "", true); } }, /* 减少缩进 */ "outdent" : { /* 减少缩进快捷键 */ "keyboard" : "shift+tab", /* 插入代码 */ "markdown" : function(options){ var range = this.range.get(), text, start; if(range.start){ text = this.range.textarea.value.substring(0, range.start); start = text.lastIndexOf("\n") + 1; if(start != text.length){ range = this.range.set(start, range.end).get(); } } if(range.text.length){ text = range.text.split("\n"); for(i in text){ text[i] = text[i].replace(/^((\t)|( {1,4}))/, ""); } this.insert(text.join("\n")); } } } }); /** * ThinkEditor编辑器默认语言包 * 默认仅支持英文和简体中文语言包 * 其他语言包可以通过 $.thinkeditor.laguage() 方法扩展 */ $.thinkeditor.language({ /* 英文语言包 */ "en-us" : { /* 工具栏语言 */ "h1" : "H1 (Ctrl+1)", "h2" : "H2 (Ctrl+2)", "h3" : "H3 (Ctrl+3)", "h4" : "H4 (Ctrl+4)", "h5" : "H5 (Ctrl+5)", "h6" : "H6 (Ctrl+6)", "link" : "Link (Ctrl+L)", "image" : "Image (Ctrl+P)", "bold" : "Blod (Ctrl+B)", "italic" : "Italic (Ctrl+I)", "code" : "Code (Ctrl+D)", "ul" : "Unordered List (Ctrl+U)", "ol" : "Ordered List (Ctrl+O)", "blockquote" : "Blockquote (Ctrl+Q)", "hr" : "Horizontal Rule (Ctrl+H)", "fullscreen" : "Full Screen (Ctrl+F)", "save" : "Save (Ctrl+S)", /* 弹出层语言 */ "ok" : "OK", "cancel" : "Cancel", /* 图片插件语言 */ "image-title" : "Insert Image", "image-text" : "Drag the image to here" }, /* 简体中文语言包 */ "zh-cn" : { /* 工具栏语言 */ "h1" : "标题一 (Ctrl+1)", "h2" : "标题二 (Ctrl+2)", "h3" : "标题三 (Ctrl+3)", "h4" : "标题四 (Ctrl+4)", "h5" : "标题五 (Ctrl+5)", "h6" : "标题六 (Ctrl+6)", "link" : "链接 (Ctrl+L)", "image" : "图片 (Ctrl+P)", "bold" : "加粗 (Ctrl+B)", "italic" : "斜体 (Ctrl+I)", "code" : "代码 (Ctrl+D)", "ul" : "无序列表 (Ctrl+U)", "ol" : "有序列表 (Ctrl+O)", "blockquote" : "引用 (Ctrl+Q)", "hr" : "分割线 (Ctrl+H)", "fullscreen" : "全屏编辑 (Ctrl+F)", "save" : "保存 (Ctrl+S)", /* 弹出层语言 */ "ok" : "确定", "cancel" : "取消", /* 图片插件语言 */ "image-title" : "插入图片", "image-text" : "拖动图片到这里上传" } }); }(jQuery);