Blame | Letzte Änderung | Log anzeigen | RSS feed
/* ===================================================* bootstrap-markdown.js v2.9.0* http://github.com/toopay/bootstrap-markdown* ===================================================* Copyright 2013-2015 Taufan Aditya** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.* ========================================================== */!function ($) {"use strict"; // jshint ;_;/* MARKDOWN CLASS DEFINITION* ========================== */var Markdown = function (element, options) {// @TODO : remove this BC on next major release// @see : https://github.com/toopay/bootstrap-markdown/issues/109var opts = ['autofocus', 'savable', 'hideable', 'width','height', 'resize', 'iconlibrary', 'language','footer', 'fullscreen', 'hiddenButtons', 'disabledButtons'];$.each(opts,function(_, opt){if (typeof $(element).data(opt) !== 'undefined') {options = typeof options == 'object' ? options : {}options[opt] = $(element).data(opt)}});// End BC// Class Propertiesthis.$ns = 'bootstrap-markdown';this.$element = $(element);this.$editable = {el:null, type:null,attrKeys:[], attrValues:[], content:null};this.$options = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data('options'));this.$oldContent = null;this.$isPreview = false;this.$isFullscreen = false;this.$editor = null;this.$textarea = null;this.$handler = [];this.$callback = [];this.$nextTab = [];this.showEditor();};Markdown.prototype = {constructor: Markdown, __alterButtons: function(name,alter) {var handler = this.$handler, isAll = (name == 'all'),that = this;$.each(handler,function(k,v) {var halt = true;if (isAll) {halt = false;} else {halt = v.indexOf(name) < 0;}if (halt === false) {alter(that.$editor.find('button[data-handler="'+v+'"]'));}});}, __buildButtons: function(buttonsArray, container) {var i,ns = this.$ns,handler = this.$handler,callback = this.$callback;for (i=0;i<buttonsArray.length;i++) {// Build each group containervar y, btnGroups = buttonsArray[i];for (y=0;y<btnGroups.length;y++) {// Build each button groupvar z,buttons = btnGroups[y].data,btnGroupContainer = $('<div/>', {'class': 'btn-group'});for (z=0;z<buttons.length;z++) {var button = buttons[z],buttonContainer, buttonIconContainer,buttonHandler = ns+'-'+button.name,buttonIcon = this.__getIcon(button.icon),btnText = button.btnText ? button.btnText : '',btnClass = button.btnClass ? button.btnClass : 'btn',tabIndex = button.tabIndex ? button.tabIndex : '-1',hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '',hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' ('+hotkey+')' : '';// Construct the button objectbuttonContainer = $('<button></button>');buttonContainer.text(' ' + this.__localize(btnText)).addClass('btn-default btn-sm').addClass(btnClass);if(btnClass.match(/btn\-(primary|success|info|warning|danger|link)/)){buttonContainer.removeClass('btn-default');}buttonContainer.attr({'type': 'button','title': this.__localize(button.title) + hotkeyCaption,'tabindex': tabIndex,'data-provider': ns,'data-handler': buttonHandler,'data-hotkey': hotkey});if (button.toggle === true){buttonContainer.attr('data-toggle', 'button');}buttonIconContainer = $('<span/>');buttonIconContainer.addClass(buttonIcon);buttonIconContainer.prependTo(buttonContainer);// Attach the button objectbtnGroupContainer.append(buttonContainer);// Register handler and callbackhandler.push(buttonHandler);callback.push(button.callback);}// Attach the button group into container domcontainer.append(btnGroupContainer);}}return container;}, __setListener: function() {// Set size and resizable Propertiesvar hasRows = typeof this.$textarea.attr('rows') !== 'undefined',maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5',rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows;this.$textarea.attr('rows',rowsVal);if (this.$options.resize) {this.$textarea.css('resize',this.$options.resize);}this.$textarea.on('focus', $.proxy(this.focus, this)).on('keypress', $.proxy(this.keypress, this)).on('keyup', $.proxy(this.keyup, this)).on('change', $.proxy(this.change, this)).on('select', $.proxy(this.select, this));if (this.eventSupported('keydown')) {this.$textarea.on('keydown', $.proxy(this.keydown, this));}// Re-attach markdown datathis.$textarea.data('markdown',this);}, __handle: function(e) {var target = $(e.currentTarget),handler = this.$handler,callback = this.$callback,handlerName = target.attr('data-handler'),callbackIndex = handler.indexOf(handlerName),callbackHandler = callback[callbackIndex];// Trigger the focusin$(e.currentTarget).focus();callbackHandler(this);// Trigger onChange for each button handlethis.change(this);// Unless it was the save handler,// focusin the textareaif (handlerName.indexOf('cmdSave') < 0) {this.$textarea.focus();}e.preventDefault();}, __localize: function(string) {var messages = $.fn.markdown.messages,language = this.$options.language;if (typeof messages !== 'undefined' &&typeof messages[language] !== 'undefined' &&typeof messages[language][string] !== 'undefined') {return messages[language][string];}return string;}, __getIcon: function(src) {return typeof src == 'object' ? src[this.$options.iconlibrary] : src;}, setFullscreen: function(mode) {var $editor = this.$editor,$textarea = this.$textarea;if (mode === true) {$editor.addClass('md-fullscreen-mode');$('body').addClass('md-nooverflow');this.$options.onFullscreen(this);} else {$editor.removeClass('md-fullscreen-mode');$('body').removeClass('md-nooverflow');if (this.$isPreview == true) this.hidePreview().showPreview()}this.$isFullscreen = mode;$textarea.focus();}, showEditor: function() {var instance = this,textarea,ns = this.$ns,container = this.$element,originalHeigth = container.css('height'),originalWidth = container.css('width'),editable = this.$editable,handler = this.$handler,callback = this.$callback,options = this.$options,editor = $( '<div/>', {'class': 'md-editor',click: function() {instance.focus();}});// Prepare the editorif (this.$editor === null) {// Create the panelvar editorHeader = $('<div/>', {'class': 'md-header btn-toolbar'});// Merge the main & additional button groups togethervar allBtnGroups = [];if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]);if (options.additionalButtons.length > 0) {// iterate the additional button groups$.each(options.additionalButtons[0], function(idx, buttonGroup){// see if the group name of the addional group matches an existing groupvar matchingGroups = $.grep(allBtnGroups, function(allButtonGroup, allIdx){return allButtonGroup.name === buttonGroup.name;});// if it matches add the addional buttons to that group, if not just add it to the all buttons groupif(matchingGroups.length > 0) {matchingGroups[0].data = matchingGroups[0].data.concat(buttonGroup.data);} else {allBtnGroups.push(options.additionalButtons[0][idx]);}});}// Reduce and/or reorder the button groupsif (options.reorderButtonGroups.length > 0) {allBtnGroups = allBtnGroups.filter(function(btnGroup) {return options.reorderButtonGroups.indexOf(btnGroup.name) > -1;}).sort(function(a, b) {if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1;if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1;return 0;});}// Build the buttonsif (allBtnGroups.length > 0) {editorHeader = this.__buildButtons([allBtnGroups], editorHeader);}if (options.fullscreen.enable) {editorHeader.append('<div class="md-controls"><a class="md-control md-control-fullscreen" href="#"><span class="'+this.__getIcon(options.fullscreen.icons.fullscreenOn)+'"></span></a></div>').on('click', '.md-control-fullscreen', function(e) {e.preventDefault();instance.setFullscreen(true);});}editor.append(editorHeader);// Wrap the textareaif (container.is('textarea')) {container.before(editor);textarea = container;textarea.addClass('md-input');editor.append(textarea);} else {var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(),currentContent = $.trim(rawContent);// This is some arbitrary content that could be editedtextarea = $('<textarea/>', {'class': 'md-input','val' : currentContent});editor.append(textarea);// Save the editableeditable.el = container;editable.type = container.prop('tagName').toLowerCase();editable.content = container.html();$(container[0].attributes).each(function(){editable.attrKeys.push(this.nodeName);editable.attrValues.push(this.nodeValue);});// Set editor to blocked the original containercontainer.replaceWith(editor);}var editorFooter = $('<div/>', {'class': 'md-footer'}),createFooter = false,footer = '';// Create the footer if savableif (options.savable) {createFooter = true;var saveHandler = 'cmdSave';// Register handler and callbackhandler.push(saveHandler);callback.push(options.onSave);editorFooter.append('<button class="btn btn-success" data-provider="'+ ns+ '" data-handler="'+ saveHandler+ '"><i class="icon icon-white icon-ok"></i> '+ this.__localize('Save')+ '</button>');}footer = typeof options.footer === 'function' ? options.footer(this) : options.footer;if ($.trim(footer) !== '') {createFooter = true;editorFooter.append(footer);}if (createFooter) editor.append(editorFooter);// Set widthif (options.width && options.width !== 'inherit') {if (jQuery.isNumeric(options.width)) {editor.css('display', 'table');textarea.css('width', options.width + 'px');} else {editor.addClass(options.width);}}// Set heightif (options.height && options.height !== 'inherit') {if (jQuery.isNumeric(options.height)) {var height = options.height;if (editorHeader) height = Math.max(0, height - editorHeader.outerHeight());if (editorFooter) height = Math.max(0, height - editorFooter.outerHeight());textarea.css('height', height + 'px');} else {editor.addClass(options.height);}}// Referencethis.$editor = editor;this.$textarea = textarea;this.$editable = editable;this.$oldContent = this.getContent();this.__setListener();// Set editor attributes, data short-hand API and listenerthis.$editor.attr('id',(new Date()).getTime());this.$editor.on('click', '[data-provider="bootstrap-markdown"]', $.proxy(this.__handle, this));if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {this.$editor.addClass('md-editor-disabled');this.disableButtons('all');}if (this.eventSupported('keydown') && typeof jQuery.hotkeys === 'object') {editorHeader.find('[data-provider="bootstrap-markdown"]').each(function() {var $button = $(this),hotkey = $button.attr('data-hotkey');if (hotkey.toLowerCase() !== '') {textarea.bind('keydown', hotkey, function() {$button.trigger('click');return false;});}});}if (options.initialstate === 'preview') {this.showPreview();} else if (options.initialstate === 'fullscreen' && options.fullscreen.enable) {this.setFullscreen(true);}} else {this.$editor.show();}if (options.autofocus) {this.$textarea.focus();this.$editor.addClass('active');}if (options.fullscreen.enable && options.fullscreen !== false) {this.$editor.append('<div class="md-fullscreen-controls">'+ '<a href="#" class="exit-fullscreen" title="Exit fullscreen"><span class="' + this.__getIcon(options.fullscreen.icons.fullscreenOff) + '">'+ '</span></a>'+ '</div>');this.$editor.on('click', '.exit-fullscreen', function(e) {e.preventDefault();instance.setFullscreen(false);});}// hide hidden buttons from optionsthis.hideButtons(options.hiddenButtons);// disable disabled buttons from optionsthis.disableButtons(options.disabledButtons);// Trigger the onShow hookoptions.onShow(this);return this;}, parseContent: function(val) {var content;// parse with supported markdown parservar val = val || this.$textarea.val();if (this.$options.parser) {content = this.$options.parser(val);} else if (typeof markdown == 'object') {content = markdown.toHTML(val);} else if (typeof marked == 'function') {content = marked(val);} else {content = val;}return content;}, showPreview: function() {var options = this.$options,container = this.$textarea,afterContainer = container.next(),replacementContainer = $('<div/>',{'class':'md-preview','data-provider':'markdown-preview'}),content,callbackContent;if (this.$isPreview == true) {// Avoid sequenced element creation on missused scenario// @see https://github.com/toopay/bootstrap-markdown/issues/170return this;}// Give flag that tell the editor enter preview modethis.$isPreview = true;// Disable all buttonsthis.disableButtons('all').enableButtons('cmdPreview');// Try to get the content from callbackcallbackContent = options.onPreview(this);// Set the content based from the callback content if string otherwise parse value from textareacontent = typeof callbackContent == 'string' ? callbackContent : this.parseContent();// Build preview elementreplacementContainer.html(content);if (afterContainer && afterContainer.attr('class') == 'md-footer') {// If there is footer element, insert the preview container before itreplacementContainer.insertBefore(afterContainer);} else {// Otherwise, just append it after textareacontainer.parent().append(replacementContainer);}// Set the preview element dimensionsreplacementContainer.css({width: container.outerWidth() + 'px',height: container.outerHeight() + 'px'});if (this.$options.resize) {replacementContainer.css('resize',this.$options.resize);}// Hide the last-active textareacontainer.hide();// Attach the editor instancesreplacementContainer.data('markdown',this);if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {this.$editor.addClass('md-editor-disabled');this.disableButtons('all');}return this;}, hidePreview: function() {// Give flag that tell the editor quit preview modethis.$isPreview = false;// Obtain the preview containervar container = this.$editor.find('div[data-provider="markdown-preview"]');// Remove the preview containercontainer.remove();// Enable all buttonsthis.enableButtons('all');// Disable configured disabled buttonsthis.disableButtons(this.$options.disabledButtons);// Back to the editorthis.$textarea.show();this.__setListener();return this;}, isDirty: function() {return this.$oldContent != this.getContent();}, getContent: function() {return this.$textarea.val();}, setContent: function(content) {this.$textarea.val(content);return this;}, findSelection: function(chunk) {var content = this.getContent(), startChunkPosition;if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) {var oldSelection = this.getSelection(), selection;this.setSelection(startChunkPosition,startChunkPosition+chunk.length);selection = this.getSelection();this.setSelection(oldSelection.start,oldSelection.end);return selection;} else {return null;}}, getSelection: function() {var e = this.$textarea[0];return (('selectionStart' in e && function() {var l = e.selectionEnd - e.selectionStart;return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) };}) ||/* browser not supported */function() {return null;})();}, setSelection: function(start,end) {var e = this.$textarea[0];return (('selectionStart' in e && function() {e.selectionStart = start;e.selectionEnd = end;return;}) ||/* browser not supported */function() {return null;})();}, replaceSelection: function(text) {var e = this.$textarea[0];return (('selectionStart' in e && function() {e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length);// Set cursor to the last replacement ende.selectionStart = e.value.length;return this;}) ||/* browser not supported */function() {e.value += text;return jQuery(e);})();}, getNextTab: function() {// Shift the nextTabif (this.$nextTab.length === 0) {return null;} else {var nextTab, tab = this.$nextTab.shift();if (typeof tab == 'function') {nextTab = tab();} else if (typeof tab == 'object' && tab.length > 0) {nextTab = tab;}return nextTab;}}, setNextTab: function(start,end) {// Push new selection into nextTab collectionsif (typeof start == 'string') {var that = this;this.$nextTab.push(function(){return that.findSelection(start);});} else if (typeof start == 'number' && typeof end == 'number') {var oldSelection = this.getSelection();this.setSelection(start,end);this.$nextTab.push(this.getSelection());this.setSelection(oldSelection.start,oldSelection.end);}return;}, __parseButtonNameParam: function (names) {return typeof names == 'string' ?names.split(' ') :names;}, enableButtons: function(name) {var buttons = this.__parseButtonNameParam(name),that = this;$.each(buttons, function(i, v) {that.__alterButtons(buttons[i], function (el) {el.removeAttr('disabled');});});return this;}, disableButtons: function(name) {var buttons = this.__parseButtonNameParam(name),that = this;$.each(buttons, function(i, v) {that.__alterButtons(buttons[i], function (el) {el.attr('disabled','disabled');});});return this;}, hideButtons: function(name) {var buttons = this.__parseButtonNameParam(name),that = this;$.each(buttons, function(i, v) {that.__alterButtons(buttons[i], function (el) {el.addClass('hidden');});});return this;}, showButtons: function(name) {var buttons = this.__parseButtonNameParam(name),that = this;$.each(buttons, function(i, v) {that.__alterButtons(buttons[i], function (el) {el.removeClass('hidden');});});return this;}, eventSupported: function(eventName) {var isSupported = eventName in this.$element;if (!isSupported) {this.$element.setAttribute(eventName, 'return;');isSupported = typeof this.$element[eventName] === 'function';}return isSupported;}, keyup: function (e) {var blocked = false;switch(e.keyCode) {case 40: // down arrowcase 38: // up arrowcase 16: // shiftcase 17: // ctrlcase 18: // altbreak;case 9: // tabvar nextTab;if (nextTab = this.getNextTab(),nextTab !== null) {// Get the nextTab if existsvar that = this;setTimeout(function(){that.setSelection(nextTab.start,nextTab.end);},500);blocked = true;} else {// The next tab memory contains nothing...// check the cursor position to determine tab actionvar cursor = this.getSelection();if (cursor.start == cursor.end && cursor.end == this.getContent().length) {// The cursor already reach the end of the contentblocked = false;} else {// Put the cursor to the endthis.setSelection(this.getContent().length,this.getContent().length);blocked = true;}}break;case 13: // enterblocked = false;break;case 27: // escapeif (this.$isFullscreen) this.setFullscreen(false);blocked = false;break;default:blocked = false;}if (blocked) {e.stopPropagation();e.preventDefault();}this.$options.onChange(this);}, change: function(e) {this.$options.onChange(this);return this;}, select: function (e) {this.$options.onSelect(this);return this;}, focus: function (e) {var options = this.$options,isHideable = options.hideable,editor = this.$editor;editor.addClass('active');// Blur other markdown(s)$(document).find('.md-editor').each(function(){if ($(this).attr('id') !== editor.attr('id')) {var attachedMarkdown;if (attachedMarkdown = $(this).find('textarea').data('markdown'),attachedMarkdown === null) {attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown');}if (attachedMarkdown) {attachedMarkdown.blur();}}});// Trigger the onFocus hookoptions.onFocus(this);return this;}, blur: function (e) {var options = this.$options,isHideable = options.hideable,editor = this.$editor,editable = this.$editable;if (editor.hasClass('active') || this.$element.parent().length === 0) {editor.removeClass('active');if (isHideable) {// Check for editable elementsif (editable.el !== null) {// Build the original elementvar oldElement = $('<'+editable.type+'/>'),content = this.getContent(),currentContent = this.parseContent(content);$(editable.attrKeys).each(function(k,v) {oldElement.attr(editable.attrKeys[k],editable.attrValues[k]);});// Get the editor contentoldElement.html(currentContent);editor.replaceWith(oldElement);} else {editor.hide();}}// Trigger the onBlur hookoptions.onBlur(this);}return this;}};/* MARKDOWN PLUGIN DEFINITION* ========================== */var old = $.fn.markdown;$.fn.markdown = function (option) {return this.each(function () {var $this = $(this), data = $this.data('markdown'), options = typeof option == 'object' && option;if (!data) $this.data('markdown', (data = new Markdown(this, options)))})};$.fn.markdown.messages = {};$.fn.markdown.defaults = {/* Editor Properties */autofocus: false,hideable: false,savable: false,width: 'inherit',height: 'inherit',resize: 'none',iconlibrary: 'glyph',language: 'en',initialstate: 'editor',parser: null,/* Buttons Properties */buttons: [[{name: 'groupFont',data: [{name: 'cmdBold',hotkey: 'Ctrl+B',title: 'Bold',icon: { glyph: 'glyphicon glyphicon-bold', fa: 'fa fa-bold', 'fa-3': 'icon-bold' },callback: function(e){// Give/remove ** surround the selectionvar chunk, cursor, selected = e.getSelection(), content = e.getContent();if (selected.length === 0) {// Give extra wordchunk = e.__localize('strong text');} else {chunk = selected.text;}// transform selection and set the cursor into chunked textif (content.substr(selected.start-2,2) === '**'&& content.substr(selected.end,2) === '**' ) {e.setSelection(selected.start-2,selected.end+2);e.replaceSelection(chunk);cursor = selected.start-2;} else {e.replaceSelection('**'+chunk+'**');cursor = selected.start+2;}// Set the cursore.setSelection(cursor,cursor+chunk.length);}},{name: 'cmdItalic',title: 'Italic',hotkey: 'Ctrl+I',icon: { glyph: 'glyphicon glyphicon-italic', fa: 'fa fa-italic', 'fa-3': 'icon-italic' },callback: function(e){// Give/remove * surround the selectionvar chunk, cursor, selected = e.getSelection(), content = e.getContent();if (selected.length === 0) {// Give extra wordchunk = e.__localize('emphasized text');} else {chunk = selected.text;}// transform selection and set the cursor into chunked textif (content.substr(selected.start-1,1) === '_'&& content.substr(selected.end,1) === '_' ) {e.setSelection(selected.start-1,selected.end+1);e.replaceSelection(chunk);cursor = selected.start-1;} else {e.replaceSelection('_'+chunk+'_');cursor = selected.start+1;}// Set the cursore.setSelection(cursor,cursor+chunk.length);}},{name: 'cmdHeading',title: 'Heading',hotkey: 'Ctrl+H',icon: { glyph: 'glyphicon glyphicon-header', fa: 'fa fa-header', 'fa-3': 'icon-font' },callback: function(e){// Append/remove ### surround the selectionvar chunk, cursor, selected = e.getSelection(), content = e.getContent(), pointer, prevChar;if (selected.length === 0) {// Give extra wordchunk = e.__localize('heading text');} else {chunk = selected.text + '\n';}// transform selection and set the cursor into chunked textif ((pointer = 4, content.substr(selected.start-pointer,pointer) === '### ')|| (pointer = 3, content.substr(selected.start-pointer,pointer) === '###')) {e.setSelection(selected.start-pointer,selected.end);e.replaceSelection(chunk);cursor = selected.start-pointer;} else if (selected.start > 0 && (prevChar = content.substr(selected.start-1,1), !!prevChar && prevChar != '\n')) {e.replaceSelection('\n\n### '+chunk);cursor = selected.start+6;} else {// Empty string before elemente.replaceSelection('### '+chunk);cursor = selected.start+4;}// Set the cursore.setSelection(cursor,cursor+chunk.length);}}]},{name: 'groupLink',data: [{name: 'cmdUrl',title: 'URL/Link',hotkey: 'Ctrl+L',icon: { glyph: 'glyphicon glyphicon-link', fa: 'fa fa-link', 'fa-3': 'icon-link' },callback: function(e){// Give [] surround the selection and prepend the linkvar chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;if (selected.length === 0) {// Give extra wordchunk = e.__localize('enter link description here');} else {chunk = selected.text;}link = prompt(e.__localize('Insert Hyperlink'),'http://');if (link !== null && link !== '' && link !== 'http://' && link.substr(0,4) === 'http') {var sanitizedLink = $('<div>'+link+'</div>').text();// transform selection and set the cursor into chunked texte.replaceSelection('['+chunk+']('+sanitizedLink+')');cursor = selected.start+1;// Set the cursore.setSelection(cursor,cursor+chunk.length);}}},{name: 'cmdImage',title: 'Image',hotkey: 'Ctrl+G',icon: { glyph: 'glyphicon glyphicon-picture', fa: 'fa fa-picture-o', 'fa-3': 'icon-picture' },callback: function(e){// Give ![] surround the selection and prepend the image linkvar chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;if (selected.length === 0) {// Give extra wordchunk = e.__localize('enter image description here');} else {chunk = selected.text;}link = prompt(e.__localize('Insert Image Hyperlink'),'http://');if (link !== null && link !== '' && link !== 'http://' && link.substr(0,4) === 'http') {var sanitizedLink = $('<div>'+link+'</div>').text();// transform selection and set the cursor into chunked texte.replaceSelection('+'")');cursor = selected.start+2;// Set the next tabe.setNextTab(e.__localize('enter image title here'));// Set the cursore.setSelection(cursor,cursor+chunk.length);}}}]},{name: 'groupMisc',data: [{name: 'cmdList',hotkey: 'Ctrl+U',title: 'Unordered List',icon: { glyph: 'glyphicon glyphicon-list', fa: 'fa fa-list', 'fa-3': 'icon-list-ul' },callback: function(e){// Prepend/Give - surround the selectionvar chunk, cursor, selected = e.getSelection(), content = e.getContent();// transform selection and set the cursor into chunked textif (selected.length === 0) {// Give extra wordchunk = e.__localize('list text here');e.replaceSelection('- '+chunk);// Set the cursorcursor = selected.start+2;} else {if (selected.text.indexOf('\n') < 0) {chunk = selected.text;e.replaceSelection('- '+chunk);// Set the cursorcursor = selected.start+2;} else {var list = [];list = selected.text.split('\n');chunk = list[0];$.each(list,function(k,v) {list[k] = '- '+v;});e.replaceSelection('\n\n'+list.join('\n'));// Set the cursorcursor = selected.start+4;}}// Set the cursore.setSelection(cursor,cursor+chunk.length);}},{name: 'cmdListO',hotkey: 'Ctrl+O',title: 'Ordered List',icon: { glyph: 'glyphicon glyphicon-th-list', fa: 'fa fa-list-ol', 'fa-3': 'icon-list-ol' },callback: function(e) {// Prepend/Give - surround the selectionvar chunk, cursor, selected = e.getSelection(), content = e.getContent();// transform selection and set the cursor into chunked textif (selected.length === 0) {// Give extra wordchunk = e.__localize('list text here');e.replaceSelection('1. '+chunk);// Set the cursorcursor = selected.start+3;} else {if (selected.text.indexOf('\n') < 0) {chunk = selected.text;e.replaceSelection('1. '+chunk);// Set the cursorcursor = selected.start+3;} else {var list = [];list = selected.text.split('\n');chunk = list[0];$.each(list,function(k,v) {list[k] = '1. '+v;});e.replaceSelection('\n\n'+list.join('\n'));// Set the cursorcursor = selected.start+5;}}// Set the cursore.setSelection(cursor,cursor+chunk.length);}},{name: 'cmdCode',hotkey: 'Ctrl+K',title: 'Code',icon: { glyph: 'glyphicon glyphicon-asterisk', fa: 'fa fa-code', 'fa-3': 'icon-code' },callback: function(e) {// Give/remove ** surround the selectionvar chunk, cursor, selected = e.getSelection(), content = e.getContent();if (selected.length === 0) {// Give extra wordchunk = e.__localize('code text here');} else {chunk = selected.text;}// transform selection and set the cursor into chunked textif (content.substr(selected.start-4,4) === '```\n'&& content.substr(selected.end,4) === '\n```') {e.setSelection(selected.start-4, selected.end+4);e.replaceSelection(chunk);cursor = selected.start-4;} else if (content.substr(selected.start-1,1) === '`'&& content.substr(selected.end,1) === '`') {e.setSelection(selected.start-1,selected.end+1);e.replaceSelection(chunk);cursor = selected.start-1;} else if (content.indexOf('\n') > -1) {e.replaceSelection('```\n'+chunk+'\n```');cursor = selected.start+4;} else {e.replaceSelection('`'+chunk+'`');cursor = selected.start+1;}// Set the cursore.setSelection(cursor,cursor+chunk.length);}},{name: 'cmdQuote',hotkey: 'Ctrl+Q',title: 'Quote',icon: { glyph: 'glyphicon glyphicon-comment', fa: 'fa fa-quote-left', 'fa-3': 'icon-quote-left' },callback: function(e) {// Prepend/Give - surround the selectionvar chunk, cursor, selected = e.getSelection(), content = e.getContent();// transform selection and set the cursor into chunked textif (selected.length === 0) {// Give extra wordchunk = e.__localize('quote here');e.replaceSelection('> '+chunk);// Set the cursorcursor = selected.start+2;} else {if (selected.text.indexOf('\n') < 0) {chunk = selected.text;e.replaceSelection('> '+chunk);// Set the cursorcursor = selected.start+2;} else {var list = [];list = selected.text.split('\n');chunk = list[0];$.each(list,function(k,v) {list[k] = '> '+v;});e.replaceSelection('\n\n'+list.join('\n'));// Set the cursorcursor = selected.start+4;}}// Set the cursore.setSelection(cursor,cursor+chunk.length);}}]},{name: 'groupUtil',data: [{name: 'cmdPreview',toggle: true,hotkey: 'Ctrl+P',title: 'Preview',btnText: 'Preview',btnClass: 'btn btn-primary btn-sm',icon: { glyph: 'glyphicon glyphicon-search', fa: 'fa fa-search', 'fa-3': 'icon-search' },callback: function(e){// Check the preview mode and toggle based on this flagvar isPreview = e.$isPreview,content;if (isPreview === false) {// Give flag that tell the editor enter preview modee.showPreview();} else {e.hidePreview();}}}]}]],additionalButtons:[], // Place to hook more buttons by codereorderButtonGroups:[],hiddenButtons:[], // Default hidden buttonsdisabledButtons:[], // Default disabled buttonsfooter: '',fullscreen: {enable: true,icons: {fullscreenOn: {fa: 'fa fa-expand',glyph: 'glyphicon glyphicon-fullscreen','fa-3': 'icon-resize-full'},fullscreenOff: {fa: 'fa fa-compress',glyph: 'glyphicon glyphicon-fullscreen','fa-3': 'icon-resize-small'}}},/* Events hook */onShow: function (e) {},onPreview: function (e) {},onSave: function (e) {},onBlur: function (e) {},onFocus: function (e) {},onChange: function(e) {},onFullscreen: function(e) {},onSelect: function (e) {}};$.fn.markdown.Constructor = Markdown;/* MARKDOWN NO CONFLICT* ==================== */$.fn.markdown.noConflict = function () {$.fn.markdown = old;return this;};/* MARKDOWN GLOBAL FUNCTION & DATA-API* ==================================== */var initMarkdown = function(el) {var $this = el;if ($this.data('markdown')) {$this.data('markdown').showEditor();return;}$this.markdown()};var blurNonFocused = function(e) {var $activeElement = $(document.activeElement);// Blur event$(document).find('.md-editor').each(function(){var $this = $(this),focused = $activeElement.closest('.md-editor')[0] === this,attachedMarkdown = $this.find('textarea').data('markdown') ||$this.find('div[data-provider="markdown-preview"]').data('markdown');if (attachedMarkdown && !focused) {attachedMarkdown.blur();}})};$(document).on('click.markdown.data-api', '[data-provide="markdown-editable"]', function (e) {initMarkdown($(this));e.preventDefault();}).on('click focusin', function (e) {blurNonFocused(e);}).ready(function(){$('textarea[data-provide="markdown"]').each(function(){initMarkdown($(this));})});}(window.jQuery);