UNPKG

hdjs

Version:
1,311 lines (1,087 loc) 166 kB
/* * Editor.md * * @file editormd.amd.js * @version v1.5.0 * @description Open source online markdown editor. * @license MIT License * @author Pandao * {@link https://github.com/pandao/editor.md} * @updateTime 2015-06-09 */ ;(function(factory) { "use strict"; // CommonJS/Node.js if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { module.exports = factory; } else if (typeof define === "function") // AMD/CMD/Sea.js { if (define.amd) // for Require.js { var cmModePath = "dist/static/package/editor.md/lib/codemirror/mode/"; var cmAddonPath = "dist/static/package/editor.md/lib/codemirror/addon/"; var codeMirrorModules = [ "jquery", "marked", "prettify", "katex", "raphael", "underscore", "flowchart", "jqueryflowchart", "sequenceDiagram", "dist/static/package/editor.md/lib/codemirror/lib/codemirror", cmModePath + "css/css", cmModePath + "sass/sass", cmModePath + "shell/shell", cmModePath + "sql/sql", cmModePath + "clike/clike", cmModePath + "php/php", cmModePath + "xml/xml", cmModePath + "markdown/markdown", cmModePath + "javascript/javascript", cmModePath + "htmlmixed/htmlmixed", cmModePath + "gfm/gfm", cmModePath + "http/http", cmModePath + "go/go", cmModePath + "dart/dart", cmModePath + "coffeescript/coffeescript", cmModePath + "nginx/nginx", cmModePath + "python/python", cmModePath + "perl/perl", cmModePath + "lua/lua", cmModePath + "r/r", cmModePath + "ruby/ruby", cmModePath + "rst/rst", cmModePath + "smartymixed/smartymixed", cmModePath + "vb/vb", cmModePath + "vbscript/vbscript", cmModePath + "velocity/velocity", cmModePath + "xquery/xquery", cmModePath + "yaml/yaml", cmModePath + "erlang/erlang", cmModePath + "jade/jade", cmAddonPath + "edit/trailingspace", cmAddonPath + "dialog/dialog", cmAddonPath + "search/searchcursor", cmAddonPath + "search/search", cmAddonPath + "scroll/annotatescrollbar", cmAddonPath + "search/matchesonscrollbar", cmAddonPath + "display/placeholder", cmAddonPath + "edit/closetag", cmAddonPath + "fold/foldcode", cmAddonPath + "fold/foldgutter", cmAddonPath + "fold/indent-fold", cmAddonPath + "fold/brace-fold", cmAddonPath + "fold/xml-fold", cmAddonPath + "fold/markdown-fold", cmAddonPath + "fold/comment-fold", cmAddonPath + "mode/overlay", cmAddonPath + "selection/active-line", cmAddonPath + "edit/closebrackets", cmAddonPath + "display/fullscreen", cmAddonPath + "search/match-highlighter" ]; define(codeMirrorModules, factory); } else { define(["jquery"], factory); // for Sea.js } } else { window.editormd = factory(); } }(function() { if (typeof define == "function" && define.amd) { $ = arguments[0]; marked = arguments[1]; prettify = arguments[2]; katex = arguments[3]; Raphael = arguments[4]; _ = arguments[5]; flowchart = arguments[6]; CodeMirror = arguments[9]; } "use strict"; var $ = (typeof (jQuery) !== "undefined") ? jQuery : Zepto; if (typeof ($) === "undefined") { return ; } /** * editormd * * @param {String} id 编辑器的ID * @param {Object} options 配置选项 Key/Value * @returns {Object} editormd 返回editormd对象 */ var editormd = function (id, options) { return new editormd.fn.init(id, options); }; editormd.title = editormd.$name = "Editor.md"; editormd.version = "1.5.0"; editormd.homePage = "https://pandao.github.io/editor.md/"; editormd.classPrefix = "editormd-"; editormd.toolbarModes = { full : [ "undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|", "goto-line", "watch", "preview", "fullscreen", "clear", "search", "|", "help", "info" ], simple : [ "undo", "redo", "|", "bold", "del", "italic", "quote", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "h5", "h6", "|", "list-ul", "list-ol", "hr", "|", "watch", "preview", "fullscreen", "|", "help", "info" ], mini : [ "undo", "redo", "|", "watch", "preview", "|", "help", "info" ] }; editormd.defaults = { mode : "gfm", //gfm or markdown name : "", // Form element name value : "", // value for CodeMirror, if mode not gfm/markdown theme : "", // Editor.md self themes, before v1.5.0 is CodeMirror theme, default empty editorTheme : "default", // Editor area, this is CodeMirror theme at v1.5.0 previewTheme : "", // Preview area theme, default empty markdown : "", // Markdown source code appendMarkdown : "", // if in init textarea value not empty, append markdown to textarea width : "100%", height : "100%", path : "./lib/", // Dependents module file directory pluginPath : "", // If this empty, default use settings.path + "../plugins/" delay : 300, // Delay parse markdown to html, Uint : ms autoLoadModules : true, // Automatic load dependent module files watch : true, placeholder : "", gotoLine : true, codeFold : false, autoHeight : false, autoFocus : false, autoCloseTags : true, searchReplace : true, syncScrolling : true, // true | false | "single", default true readOnly : false, tabSize : 4, indentUnit : 4, lineNumbers : true, lineWrapping : true, autoCloseBrackets : true, showTrailingSpace : true, matchBrackets : true, indentWithTabs : true, styleSelectedText : true, matchWordHighlight : true, // options: true, false, "onselected" styleActiveLine : true, // Highlight the current line dialogLockScreen : true, dialogShowMask : true, dialogDraggable : true, dialogMaskBgColor : "#fff", dialogMaskOpacity : 0.1, fontSize : "13px", saveHTMLToTextarea : false, disabledKeyMaps : [], onload : function() {}, onresize : function() {}, onchange : function() {}, onwatch : null, onunwatch : null, onpreviewing : function() {}, onpreviewed : function() {}, onfullscreen : function() {}, onfullscreenExit : function() {}, onscroll : function() {}, onpreviewscroll : function() {}, imageUpload : false, imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"], imageUploadURL : "", crossDomainUpload : false, uploadCallbackURL : "", toc : true, // Table of contents tocm : false, // Using [TOCM], auto create ToC dropdown menu tocTitle : "", // for ToC dropdown menu btn tocDropdown : false, tocContainer : "", tocStartLevel : 1, // Said from H1 to create ToC htmlDecode : false, // Open the HTML tag identification pageBreak : true, // Enable parse page break [========] atLink : true, // for @link emailLink : true, // for email address auto link taskList : false, // Enable Github Flavored Markdown task lists emoji : false, // :emoji: , Support Github emoji, Twitter Emoji (Twemoji); // Support FontAwesome icon emoji :fa-xxx: > Using fontAwesome icon web fonts; // Support Editor.md logo icon emoji :editormd-logo: :editormd-logo-1x: > 1~8x; tex : false, // TeX(LaTeX), based on KaTeX flowChart : false, // flowChart.js only support IE9+ sequenceDiagram : false, // sequenceDiagram.js only support IE9+ previewCodeHighlight : true, toolbar : true, // show/hide toolbar toolbarAutoFixed : true, // on window scroll auto fixed position toolbarIcons : "full", toolbarTitles : {}, toolbarHandlers : { ucwords : function() { return editormd.toolbarHandlers.ucwords; }, lowercase : function() { return editormd.toolbarHandlers.lowercase; } }, toolbarCustomIcons : { // using html tag create toolbar icon, unused default <a> tag. lowercase : "<a href=\"javascript:;\" title=\"Lowercase\" unselectable=\"on\"><i class=\"fa\" name=\"lowercase\" style=\"font-size:24px;margin-top: -10px;\">a</i></a>", "ucwords" : "<a href=\"javascript:;\" title=\"ucwords\" unselectable=\"on\"><i class=\"fa\" name=\"ucwords\" style=\"font-size:20px;margin-top: -3px;\">Aa</i></a>" }, toolbarIconsClass : { undo : "fa-undo", redo : "fa-repeat", bold : "fa-bold", del : "fa-strikethrough", italic : "fa-italic", quote : "fa-quote-left", uppercase : "fa-font", h1 : editormd.classPrefix + "bold", h2 : editormd.classPrefix + "bold", h3 : editormd.classPrefix + "bold", h4 : editormd.classPrefix + "bold", h5 : editormd.classPrefix + "bold", h6 : editormd.classPrefix + "bold", "list-ul" : "fa-list-ul", "list-ol" : "fa-list-ol", hr : "fa-minus", link : "fa-link", "reference-link" : "fa-anchor", image : "fa-picture-o", code : "fa-code", "preformatted-text" : "fa-file-code-o", "code-block" : "fa-file-code-o", table : "fa-table", datetime : "fa-clock-o", emoji : "fa-smile-o", "html-entities" : "fa-copyright", pagebreak : "fa-newspaper-o", "goto-line" : "fa-terminal", // fa-crosshairs watch : "fa-eye-slash", unwatch : "fa-eye", preview : "fa-desktop", search : "fa-search", fullscreen : "fa-arrows-alt", clear : "fa-eraser", help : "fa-question-circle", info : "fa-info-circle" }, toolbarIconTexts : {}, lang : { name : "zh-cn", description : "开源在线Markdown编辑器<br/>Open source online Markdown editor.", tocTitle : "目录", toolbar : { undo : "撤销(Ctrl+Z)", redo : "重做(Ctrl+Y)", bold : "粗体", del : "删除线", italic : "斜体", quote : "引用", ucwords : "将每个单词首字母转成大写", uppercase : "将所选转换成大写", lowercase : "将所选转换成小写", h1 : "标题1", h2 : "标题2", h3 : "标题3", h4 : "标题4", h5 : "标题5", h6 : "标题6", "list-ul" : "无序列表", "list-ol" : "有序列表", hr : "横线", link : "链接", "reference-link" : "引用链接", image : "添加图片", code : "行内代码", "preformatted-text" : "预格式文本 / 代码块(缩进风格)", "code-block" : "代码块(多语言风格)", table : "添加表格", datetime : "日期时间", emoji : "Emoji表情", "html-entities" : "HTML实体字符", pagebreak : "插入分页符", "goto-line" : "跳转到行", watch : "关闭实时预览", unwatch : "开启实时预览", preview : "全窗口预览HTML(按 Shift + ESC还原)", fullscreen : "全屏(按ESC还原)", clear : "清空", search : "搜索", help : "使用帮助", info : "关于" + editormd.title }, buttons : { enter : "确定", cancel : "取消", close : "关闭" }, dialog : { link : { title : "添加链接", url : "链接地址", urlTitle : "链接标题", urlEmpty : "错误:请填写链接地址。" }, referenceLink : { title : "添加引用链接", name : "引用名称", url : "链接地址", urlId : "链接ID", urlTitle : "链接标题", nameEmpty: "错误:引用链接的名称不能为空。", idEmpty : "错误:请填写引用链接的ID。", urlEmpty : "错误:请填写引用链接的URL地址。" }, image : { title : "添加图片", url : "图片地址", link : "图片链接", alt : "图片描述", uploadButton : "本地上传", imageURLEmpty : "错误:图片地址不能为空。", uploadFileEmpty : "错误:上传的图片不能为空。", formatNotAllowed : "错误:只允许上传图片文件,允许上传的图片文件格式有:" }, preformattedText : { title : "添加预格式文本或代码块", emptyAlert : "错误:请填写预格式文本或代码的内容。" }, codeBlock : { title : "添加代码块", selectLabel : "代码语言:", selectDefaultText : "请选择代码语言", otherLanguage : "其他语言", unselectedLanguageAlert : "错误:请选择代码所属的语言类型。", codeEmptyAlert : "错误:请填写代码内容。" }, htmlEntities : { title : "HTML 实体字符" }, help : { title : "使用帮助" } } } }; editormd.classNames = { tex : editormd.classPrefix + "tex" }; editormd.dialogZindex = 99999; editormd.$katex = null; editormd.$marked = null; editormd.$CodeMirror = null; editormd.$prettyPrint = null; var timer, flowchartTimer; editormd.prototype = editormd.fn = { state : { watching : false, loaded : false, preview : false, fullscreen : false }, /** * 构造函数/实例初始化 * Constructor / instance initialization * * @param {String} id 编辑器的ID * @param {Object} [options={}] 配置选项 Key/Value * @returns {editormd} 返回editormd的实例对象 */ init : function (id, options) { options = options || {}; if (typeof id === "object") { options = id; } var _this = this; var classPrefix = this.classPrefix = editormd.classPrefix; var settings = this.settings = $.extend(true, editormd.defaults, options); id = (typeof id === "object") ? settings.id : id; var editor = this.editor = $("#" + id); this.id = id; this.lang = settings.lang; var classNames = this.classNames = { textarea : { html : classPrefix + "html-textarea", markdown : classPrefix + "markdown-textarea" } }; settings.pluginPath = (settings.pluginPath === "") ? settings.path + "../plugins/" : settings.pluginPath; this.state.watching = (settings.watch) ? true : false; if ( !editor.hasClass("editormd") ) { editor.addClass("editormd"); } editor.css({ width : (typeof settings.width === "number") ? settings.width + "px" : settings.width, height : (typeof settings.height === "number") ? settings.height + "px" : settings.height }); if (settings.autoHeight) { editor.css("height", "auto"); } var markdownTextarea = this.markdownTextarea = editor.children("textarea"); if (markdownTextarea.length < 1) { editor.append("<textarea></textarea>"); markdownTextarea = this.markdownTextarea = editor.children("textarea"); } markdownTextarea.addClass(classNames.textarea.markdown).attr("placeholder", settings.placeholder); if (typeof markdownTextarea.attr("name") === "undefined" || markdownTextarea.attr("name") === "") { markdownTextarea.attr("name", (settings.name !== "") ? settings.name : id + "-markdown-doc"); } var appendElements = [ (!settings.readOnly) ? "<a href=\"javascript:;\" class=\"fa fa-close " + classPrefix + "preview-close-btn\"></a>" : "", ( (settings.saveHTMLToTextarea) ? "<textarea class=\"" + classNames.textarea.html + "\" name=\"" + id + "-html-code\"></textarea>" : "" ), "<div class=\"" + classPrefix + "preview\"><div class=\"markdown-body " + classPrefix + "preview-container\"></div></div>", "<div class=\"" + classPrefix + "container-mask\" style=\"display:block;\"></div>", "<div class=\"" + classPrefix + "mask\"></div>" ].join("\n"); editor.append(appendElements).addClass(classPrefix + "vertical"); if (settings.theme !== "") { editor.addClass(classPrefix + "theme-" + settings.theme); } this.mask = editor.children("." + classPrefix + "mask"); this.containerMask = editor.children("." + classPrefix + "container-mask"); if (settings.markdown !== "") { markdownTextarea.val(settings.markdown); } if (settings.appendMarkdown !== "") { markdownTextarea.val(markdownTextarea.val() + settings.appendMarkdown); } this.htmlTextarea = editor.children("." + classNames.textarea.html); this.preview = editor.children("." + classPrefix + "preview"); this.previewContainer = this.preview.children("." + classPrefix + "preview-container"); if (settings.previewTheme !== "") { this.preview.addClass(classPrefix + "preview-theme-" + settings.previewTheme); } if (typeof define === "function" && define.amd) { if (typeof katex !== "undefined") { editormd.$katex = katex; } if (settings.searchReplace && !settings.readOnly) { editormd.loadCSS(settings.path + "codemirror/addon/dialog/dialog"); editormd.loadCSS(settings.path + "codemirror/addon/search/matchesonscrollbar"); } } if ((typeof define === "function" && define.amd) || !settings.autoLoadModules) { if (typeof CodeMirror !== "undefined") { editormd.$CodeMirror = CodeMirror; } if (typeof marked !== "undefined") { editormd.$marked = marked; } this.setCodeMirror().setToolbar().loadedDisplay(); } else { this.loadQueues(); } return this; }, /** * 所需组件加载队列 * Required components loading queue * * @returns {editormd} 返回editormd的实例对象 */ loadQueues : function() { var _this = this; var settings = this.settings; var loadPath = settings.path; var loadFlowChartOrSequenceDiagram = function() { if (editormd.isIE8) { _this.loadedDisplay(); return ; } if (settings.flowChart || settings.sequenceDiagram) { editormd.loadScript(loadPath + "raphael.min", function() { editormd.loadScript(loadPath + "underscore.min", function() { if (!settings.flowChart && settings.sequenceDiagram) { editormd.loadScript(loadPath + "sequence-diagram.min", function() { _this.loadedDisplay(); }); } else if (settings.flowChart && !settings.sequenceDiagram) { editormd.loadScript(loadPath + "flowchart.min", function() { editormd.loadScript(loadPath + "jquery.flowchart.min", function() { _this.loadedDisplay(); }); }); } else if (settings.flowChart && settings.sequenceDiagram) { editormd.loadScript(loadPath + "flowchart.min", function() { editormd.loadScript(loadPath + "jquery.flowchart.min", function() { editormd.loadScript(loadPath + "sequence-diagram.min", function() { _this.loadedDisplay(); }); }); }); } }); }); } else { _this.loadedDisplay(); } }; editormd.loadCSS(loadPath + "codemirror/codemirror.min"); if (settings.searchReplace && !settings.readOnly) { editormd.loadCSS(loadPath + "codemirror/addon/dialog/dialog"); editormd.loadCSS(loadPath + "codemirror/addon/search/matchesonscrollbar"); } if (settings.codeFold) { editormd.loadCSS(loadPath + "codemirror/addon/fold/foldgutter"); } editormd.loadScript(loadPath + "codemirror/codemirror.min", function() { editormd.$CodeMirror = CodeMirror; editormd.loadScript(loadPath + "codemirror/modes.min", function() { editormd.loadScript(loadPath + "codemirror/addons.min", function() { _this.setCodeMirror(); if (settings.mode !== "gfm" && settings.mode !== "markdown") { _this.loadedDisplay(); return false; } _this.setToolbar(); editormd.loadScript(loadPath + "marked.min", function() { editormd.$marked = marked; if (settings.previewCodeHighlight) { editormd.loadScript(loadPath + "prettify.min", function() { loadFlowChartOrSequenceDiagram(); }); } else { loadFlowChartOrSequenceDiagram(); } }); }); }); }); return this; }, /** * 设置 Editor.md 的整体主题,主要是工具栏 * Setting Editor.md theme * * @returns {editormd} 返回editormd的实例对象 */ setTheme : function(theme) { var editor = this.editor; var oldTheme = this.settings.theme; var themePrefix = this.classPrefix + "theme-"; editor.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); this.settings.theme = theme; return this; }, /** * 设置 CodeMirror(编辑区)的主题 * Setting CodeMirror (Editor area) theme * * @returns {editormd} 返回editormd的实例对象 */ setEditorTheme : function(theme) { var settings = this.settings; settings.editorTheme = theme; if (theme !== "default") { editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); } this.cm.setOption("theme", theme); return this; }, /** * setEditorTheme() 的别名 * setEditorTheme() alias * * @returns {editormd} 返回editormd的实例对象 */ setCodeMirrorTheme : function (theme) { this.setEditorTheme(theme); return this; }, /** * 设置 Editor.md 的主题 * Setting Editor.md theme * * @returns {editormd} 返回editormd的实例对象 */ setPreviewTheme : function(theme) { var preview = this.preview; var oldTheme = this.settings.previewTheme; var themePrefix = this.classPrefix + "preview-theme-"; preview.removeClass(themePrefix + oldTheme).addClass(themePrefix + theme); this.settings.previewTheme = theme; return this; }, /** * 配置和初始化CodeMirror组件 * CodeMirror initialization * * @returns {editormd} 返回editormd的实例对象 */ setCodeMirror : function() { var settings = this.settings; var editor = this.editor; if (settings.editorTheme !== "default") { editormd.loadCSS(settings.path + "codemirror/theme/" + settings.editorTheme); } var codeMirrorConfig = { mode : settings.mode, theme : settings.editorTheme, tabSize : settings.tabSize, dragDrop : false, autofocus : settings.autoFocus, autoCloseTags : settings.autoCloseTags, readOnly : (settings.readOnly) ? "nocursor" : false, indentUnit : settings.indentUnit, lineNumbers : settings.lineNumbers, lineWrapping : settings.lineWrapping, extraKeys : { "Ctrl-Q": function(cm) { cm.foldCode(cm.getCursor()); } }, foldGutter : settings.codeFold, gutters : ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], matchBrackets : settings.matchBrackets, indentWithTabs : settings.indentWithTabs, styleActiveLine : settings.styleActiveLine, styleSelectedText : settings.styleSelectedText, autoCloseBrackets : settings.autoCloseBrackets, showTrailingSpace : settings.showTrailingSpace, highlightSelectionMatches : ( (!settings.matchWordHighlight) ? false : { showToken: (settings.matchWordHighlight === "onselected") ? false : /\w/ } ) }; this.codeEditor = this.cm = editormd.$CodeMirror.fromTextArea(this.markdownTextarea[0], codeMirrorConfig); this.codeMirror = this.cmElement = editor.children(".CodeMirror"); if (settings.value !== "") { this.cm.setValue(settings.value); } this.codeMirror.css({ fontSize : settings.fontSize, width : (!settings.watch) ? "100%" : "50%" }); if (settings.autoHeight) { this.codeMirror.css("height", "auto"); this.cm.setOption("viewportMargin", Infinity); } if (!settings.lineNumbers) { this.codeMirror.find(".CodeMirror-gutters").css("border-right", "none"); } return this; }, /** * 获取CodeMirror的配置选项 * Get CodeMirror setting options * * @returns {Mixed} return CodeMirror setting option value */ getCodeMirrorOption : function(key) { return this.cm.getOption(key); }, /** * 配置和重配置CodeMirror的选项 * CodeMirror setting options / resettings * * @returns {editormd} 返回editormd的实例对象 */ setCodeMirrorOption : function(key, value) { this.cm.setOption(key, value); return this; }, /** * 添加 CodeMirror 键盘快捷键 * Add CodeMirror keyboard shortcuts key map * * @returns {editormd} 返回editormd的实例对象 */ addKeyMap : function(map, bottom) { this.cm.addKeyMap(map, bottom); return this; }, /** * 移除 CodeMirror 键盘快捷键 * Remove CodeMirror keyboard shortcuts key map * * @returns {editormd} 返回editormd的实例对象 */ removeKeyMap : function(map) { this.cm.removeKeyMap(map); return this; }, /** * 跳转到指定的行 * Goto CodeMirror line * * @param {String|Intiger} line line number or "first"|"last" * @returns {editormd} 返回editormd的实例对象 */ gotoLine : function (line) { var settings = this.settings; if (!settings.gotoLine) { return this; } var cm = this.cm; var editor = this.editor; var count = cm.lineCount(); var preview = this.preview; if (typeof line === "string") { if(line === "last") { line = count; } if (line === "first") { line = 1; } } if (typeof line !== "number") { alert("Error: The line number must be an integer."); return this; } line = parseInt(line) - 1; if (line > count) { alert("Error: The line number range 1-" + count); return this; } cm.setCursor( {line : line, ch : 0} ); var scrollInfo = cm.getScrollInfo(); var clientHeight = scrollInfo.clientHeight; var coords = cm.charCoords({line : line, ch : 0}, "local"); cm.scrollTo(null, (coords.top + coords.bottom - clientHeight) / 2); if (settings.watch) { var cmScroll = this.codeMirror.find(".CodeMirror-scroll")[0]; var height = $(cmScroll).height(); var scrollTop = cmScroll.scrollTop; var percent = (scrollTop / cmScroll.scrollHeight); if (scrollTop === 0) { preview.scrollTop(0); } else if (scrollTop + height >= cmScroll.scrollHeight - 16) { preview.scrollTop(preview[0].scrollHeight); } else { preview.scrollTop(preview[0].scrollHeight * percent); } } cm.focus(); return this; }, /** * 扩展当前实例对象,可同时设置多个或者只设置一个 * Extend editormd instance object, can mutil setting. * * @returns {editormd} this(editormd instance object.) */ extend : function() { if (typeof arguments[1] !== "undefined") { if (typeof arguments[1] === "function") { arguments[1] = $.proxy(arguments[1], this); } this[arguments[0]] = arguments[1]; } if (typeof arguments[0] === "object" && typeof arguments[0].length === "undefined") { $.extend(true, this, arguments[0]); } return this; }, /** * 设置或扩展当前实例对象,单个设置 * Extend editormd instance object, one by one * * @param {String|Object} key option key * @param {String|Object} value option value * @returns {editormd} this(editormd instance object.) */ set : function (key, value) { if (typeof value !== "undefined" && typeof value === "function") { value = $.proxy(value, this); } this[key] = value; return this; }, /** * 重新配置 * Resetting editor options * * @param {String|Object} key option key * @param {String|Object} value option value * @returns {editormd} this(editormd instance object.) */ config : function(key, value) { var settings = this.settings; if (typeof key === "object") { settings = $.extend(true, settings, key); } if (typeof key === "string") { settings[key] = value; } this.settings = settings; this.recreate(); return this; }, /** * 注册事件处理方法 * Bind editor event handle * * @param {String} eventType event type * @param {Function} callback 回调函数 * @returns {editormd} this(editormd instance object.) */ on : function(eventType, callback) { var settings = this.settings; if (typeof settings["on" + eventType] !== "undefined") { settings["on" + eventType] = $.proxy(callback, this); } return this; }, /** * 解除事件处理方法 * Unbind editor event handle * * @param {String} eventType event type * @returns {editormd} this(editormd instance object.) */ off : function(eventType) { var settings = this.settings; if (typeof settings["on" + eventType] !== "undefined") { settings["on" + eventType] = function(){}; } return this; }, /** * 显示工具栏 * Display toolbar * * @param {Function} [callback=function(){}] 回调函数 * @returns {editormd} 返回editormd的实例对象 */ showToolbar : function(callback) { var settings = this.settings; if(settings.readOnly) { return this; } if (settings.toolbar && (this.toolbar.length < 1 || this.toolbar.find("." + this.classPrefix + "menu").html() === "") ) { this.setToolbar(); } settings.toolbar = true; this.toolbar.show(); this.resize(); $.proxy(callback || function(){}, this)(); return this; }, /** * 隐藏工具栏 * Hide toolbar * * @param {Function} [callback=function(){}] 回调函数 * @returns {editormd} this(editormd instance object.) */ hideToolbar : function(callback) { var settings = this.settings; settings.toolbar = false; this.toolbar.hide(); this.resize(); $.proxy(callback || function(){}, this)(); return this; }, /** * 页面滚动时工具栏的固定定位 * Set toolbar in window scroll auto fixed position * * @returns {editormd} 返回editormd的实例对象 */ setToolbarAutoFixed : function(fixed) { var state = this.state; var editor = this.editor; var toolbar = this.toolbar; var settings = this.settings; if (typeof fixed !== "undefined") { settings.toolbarAutoFixed = fixed; } var autoFixedHandle = function(){ var $window = $(window); var top = $window.scrollTop(); if (!settings.toolbarAutoFixed) { return false; } if (top - editor.offset().top > 10 && top < editor.height()) { toolbar.css({ position : "fixed", width : editor.width() + "px", left : ($window.width() - editor.width()) / 2 + "px" }); } else { toolbar.css({ position : "absolute", width : "100%", left : 0 }); } }; if (!state.fullscreen && !state.preview && settings.toolbar && settings.toolbarAutoFixed) { $(window).bind("scroll", autoFixedHandle); } return this; }, /** * 配置和初始化工具栏 * Set toolbar and Initialization * * @returns {editormd} 返回editormd的实例对象 */ setToolbar : function() { var settings = this.settings; if(settings.readOnly) { return this; } var editor = this.editor; var preview = this.preview; var classPrefix = this.classPrefix; var toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); if (settings.toolbar && toolbar.length < 1) { var toolbarHTML = "<div class=\"" + classPrefix + "toolbar\"><div class=\"" + classPrefix + "toolbar-container\"><ul class=\"" + classPrefix + "menu\"></ul></div></div>"; editor.append(toolbarHTML); toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar"); } if (!settings.toolbar) { toolbar.hide(); return this; } toolbar.show(); var icons = (typeof settings.toolbarIcons === "function") ? settings.toolbarIcons() : ((typeof settings.toolbarIcons === "string") ? editormd.toolbarModes[settings.toolbarIcons] : settings.toolbarIcons); var toolbarMenu = toolbar.find("." + this.classPrefix + "menu"), menu = ""; var pullRight = false; for (var i = 0, len = icons.length; i < len; i++) { var name = icons[i]; if (name === "||") { pullRight = true; } else if (name === "|") { menu += "<li class=\"divider\" unselectable=\"on\">|</li>"; } else { var isHeader = (/h(\d)/.test(name)); var index = name; if (name === "watch" && !settings.watch) { index = "unwatch"; } var title = settings.lang.toolbar[index]; var iconTexts = settings.toolbarIconTexts[index]; var iconClass = settings.toolbarIconsClass[index]; title = (typeof title === "undefined") ? "" : title; iconTexts = (typeof iconTexts === "undefined") ? "" : iconTexts; iconClass = (typeof iconClass === "undefined") ? "" : iconClass; var menuItem = pullRight ? "<li class=\"pull-right\">" : "<li>"; if (typeof settings.toolbarCustomIcons[name] !== "undefined" && typeof settings.toolbarCustomIcons[name] !== "function") { menuItem += settings.toolbarCustomIcons[name]; } else { menuItem += "<a href=\"javascript:;\" title=\"" + title + "\" unselectable=\"on\">"; menuItem += "<i class=\"fa " + iconClass + "\" name=\""+name+"\" unselectable=\"on\">"+((isHeader) ? name.toUpperCase() : ( (iconClass === "") ? iconTexts : "") ) + "</i>"; menuItem += "</a>"; } menuItem += "</li>"; menu = pullRight ? menuItem + menu : menu + menuItem; } } toolbarMenu.html(menu); toolbarMenu.find("[title=\"Lowercase\"]").attr("title", settings.lang.toolbar.lowercase); toolbarMenu.find("[title=\"ucwords\"]").attr("title", settings.lang.toolbar.ucwords); this.setToolbarHandler(); this.setToolbarAutoFixed(); return this; }, /** * 工具栏图标事件处理对象序列 * Get toolbar icons event handlers * * @param {Object} cm CodeMirror的实例对象 * @param {String} name 要获取的事件处理器名称 * @returns {Object} 返回处理对象序列 */ dialogLockScreen : function() { $.proxy(editormd.dialogLockScreen, this)(); return this; }, dialogShowMask : function(dialog) { $.proxy(editormd.dialogShowMask, this)(dialog); return this; }, getToolbarHandles : function(name) { var toolbarHandlers = this.toolbarHandlers = editormd.toolbarHandlers; return (name && typeof toolbarIconHandlers[name] !== "undefined") ? toolbarHandlers[name] : toolbarHandlers; }, /** * 工具栏图标事件处理器 * Bind toolbar icons event handle * * @returns {editormd} 返回editormd的实例对象 */ setToolbarHandler : function() { var _this = this; var settings = this.settings; if (!set