app/assets/javascripts/bootstrap-markdown.js in rails-bootstrap-markdown-1.0.0 vs app/assets/javascripts/bootstrap-markdown.js in rails-bootstrap-markdown-2.6.0

- old
+ new

@@ -1,10 +1,10 @@ /* =================================================== - * bootstrap-markdown.js v2.1.0 + * bootstrap-markdown.js v2.6.0 * http://github.com/toopay/bootstrap-markdown * =================================================== - * Copyright 2013 Taufan Aditya + * Copyright 2013-2014 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 * @@ -15,34 +15,32 @@ * 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. * ========================================================== */ -//= require markdown -//= require to-markdown - !function ($) { "use strict"; // jshint ;_; /* MARKDOWN CLASS DEFINITION * ========================== */ var Markdown = function (element, options) { // Class Properties - this.$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.$oldContent = null - this.$isPreview = false - this.$editor = null - this.$textarea = null - this.$handler = [] - this.$callback = [] - this.$nextTab = [] + this.$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(), 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 = { @@ -85,35 +83,41 @@ for (z=0;z<buttons.length;z++) { var button = buttons[z], buttonToggle = '', 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' + tabIndex = button.tabIndex ? button.tabIndex : '-1', + hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '', + hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' ('+hotkey+')' : '' if (button.toggle == true) { buttonToggle = ' data-toggle="button"' } // Attach the button object - btnGroupContainer.append('<button class="' + btnGroupContainer.append('<button type="button" class="' +btnClass +' btn-default btn-sm" title="' - +button.title + +this.__localize(button.title) + +hotkeyCaption +'" tabindex="' +tabIndex +'" data-provider="' +ns +'" data-handler="' +buttonHandler + +'" data-hotkey="' + +hotkey +'"' +buttonToggle +'><span class="' - +button.icon + +buttonIcon +'"></span> ' - +btnText + +this.__localize(btnText) +'</button>') // Register handler and callback handler.push(buttonHandler) callback.push(button.callback) @@ -131,16 +135,19 @@ var 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) - this.$textarea.css('resize','none') + 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)) if (this.eventSupported('keydown')) { this.$textarea.on('keydown', $.proxy(this.keydown, this)) } @@ -159,19 +166,56 @@ // Trigger the focusin $(e.currentTarget).focus() callbackHandler(this) + // Trigger onChange for each button handle + this.change(this); + // Unless it was the save handler, // focusin the textarea if (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') + } + + this.$isFullscreen = mode; + $textarea.focus() + } + , showEditor: function() { var instance = this, textarea, ns = this.$ns, container = this.$element, @@ -193,20 +237,40 @@ // Create the panel var editorHeader = $('<div/>', { 'class': 'md-header btn-toolbar' }) - // Build the main buttons - if (options.buttons.length > 0) { - editorHeader = this.__buildButtons(options.buttons, editorHeader) + // Merge the main & additional button groups together + var allBtnGroups = [] + if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]) + if (options.additionalButtons.length > 0) allBtnGroups = allBtnGroups.concat(options.additionalButtons[0]) + + // Reduce and/or reorder the button groups + if (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 additional buttons - if (options.additionalButtons.length > 0) { - editorHeader = this.__buildButtons(options.additionalButtons, editorHeader) + // Build the buttons + if (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 textarea if (container.is('textarea')) { container.before(editor) @@ -237,41 +301,66 @@ // Set editor to blocked the original container container.replaceWith(editor) } - // Create the footer if savable - if (options.savable) { - var editorFooter = $('<div/>', { + var editorFooter = $('<div/>', { 'class': 'md-footer' }), - saveHandler = 'cmdSave' + createFooter = false, + footer = '' + // Create the footer if savable + if (options.savable) { + createFooter = true; + var saveHandler = 'cmdSave' // Register handler and callback handler.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> Save</button>') + +'"><i class="icon icon-white icon-ok"></i> ' + +this.__localize('Save') + +'</button>') - editor.append(editorFooter) + } - // Set width/height - $.each(['height','width'],function(k,attr){ - if (options[attr] != 'inherit') { - if (jQuery.isNumeric(options[attr])) { - editor.css(attr,options[attr]+'px') - } else { - editor.addClass(options[attr]) - } + footer = typeof options.footer === 'function' ? options.footer(this) : options.footer + + if ($.trim(footer) !== '') { + createFooter = true; + editorFooter.append(footer); + } + + if (createFooter) editor.append(editorFooter) + + // Set width + if (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 height + if (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) + } + } + // Reference this.$editor = editor this.$textarea = textarea this.$editable = editable this.$oldContent = this.getContent() @@ -280,45 +369,108 @@ // Set editor attributes, data short-hand API and listener this.$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="switch-theme" title="Switch themes"><span class="'+this.__getIcon(options.fullscreen.icons.switchTheme)+'"></span></a>\ + <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) + }) + + this.$editor.on('click', '.switch-theme', function(e) { + e.preventDefault() + instance.$editor.toggleClass('theme-dark') + }) + } + + // hide hidden buttons from options + this.hideButtons(options.hiddenButtons) + + // disable disabled buttons from options + this.disableButtons(options.disabledButtons) + // Trigger the onShow hook options.onShow(this) return this } + , parseContent: function() { + var content, + callbackContent = this.$options.onPreview(this) // Try to get the content from callback + + if (typeof callbackContent == 'string') { + // Set the content based by callback content + content = callbackContent + } else { + // Set the content + var val = this.$textarea.val(); + 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, - callbackContent = options.onPreview(this), // Try to get the content from callback container = this.$textarea, afterContainer = container.next(), replacementContainer = $('<div/>',{'class':'md-preview','data-provider':'markdown-preview'}), content // Give flag that tell the editor enter preview mode this.$isPreview = true // Disable all buttons this.disableButtons('all').enableButtons('cmdPreview') - if (typeof callbackContent == 'string') { - // Set the content based by callback content - content = callbackContent - } else { - // Set the content - content = (typeof markdown == 'object') ? markdown.toHTML(container.val()) : container.val() - } + content = this.parseContent() // Build preview element replacementContainer.html(content) if (afterContainer && afterContainer.attr('class') == 'md-footer') { @@ -327,16 +479,31 @@ } else { // Otherwise, just append it after textarea container.parent().append(replacementContainer) } + // Set the preview element dimensions + replacementContainer.css({ + width: container.outerWidth() + 'px', + height: container.outerHeight() + 'px' + }) + + if (this.$options.resize) { + replacementContainer.css('resize',this.$options.resize) + } + // Hide the last-active textarea container.hide() // Attach the editor instances replacementContainer.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 mode @@ -348,10 +515,12 @@ // Remove the preview container container.remove() // Enable all buttons this.enableButtons('all') + // Disable configured disabled buttons + this.disableButtons(this.$options.disabledButtons) // Back to the editor this.$textarea.show() this.__setListener() @@ -475,11 +644,11 @@ if (typeof start == 'string') { var that = this this.$nextTab.push(function(){ return that.findSelection(start) }) - } else if (typeof start == 'numeric' && typeof end == 'numeric') { + } else if (typeof start == 'number' && typeof end == 'number') { var oldSelection = this.getSelection() this.setSelection(start,end) this.$nextTab.push(this.getSelection()) @@ -487,49 +656,85 @@ } return } - , enableButtons: function(name) { - var alter = function (el) { - el.removeAttr('disabled') + , __parseButtonNameParam: function(nameParam) { + var buttons = [] + + if (typeof nameParam == 'string') { + buttons.push(nameParam) + } else { + buttons = nameParam } - this.__alterButtons(name,alter) + return buttons + } - return this + , 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 alter = function (el) { - el.attr('disabled','disabled') - } + var buttons = this.__parseButtonNameParam(name), + that = this - this.__alterButtons(name,alter) + $.each(buttons, function(i, v) { + that.__alterButtons(buttons[i], function (el) { + el.attr('disabled','disabled') + }); + }) - return this + 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 } - , keydown: function (e) { - this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]) - this.keyup(e) - } - - , keypress: function (e) { - if (this.suppressKeyPressRepeat) return - this.keyup(e) - } - , keyup: function (e) { var blocked = false switch(e.keyCode) { case 40: // down arrow case 38: // up arrow @@ -566,11 +771,14 @@ } break case 13: // enter + blocked = false + break case 27: // escape + if (this.$isFullscreen) this.setFullscreen(false) blocked = false break default: blocked = false @@ -578,12 +786,19 @@ if (blocked) { e.stopPropagation() e.preventDefault() } - } + this.$options.onChange(this) + } + + , change: function(e) { + this.$options.onChange(this); + return this; + } + , focus: function (e) { var options = this.$options, isHideable = options.hideable, editor = this.$editor @@ -603,10 +818,13 @@ attachedMarkdown.blur() } } }) + // Trigger the onFocus hook + options.onFocus(this); + return this } , blur: function (e) { var options = this.$options, @@ -661,33 +879,40 @@ , 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', /* Buttons Properties */ buttons: [ [{ name: 'groupFont', data: [{ name: 'cmdBold', + hotkey: 'Ctrl+B', title: 'Bold', - icon: 'glyphicon glyphicon-bold', + icon: { glyph: 'glyphicon glyphicon-bold', fa: 'fa fa-bold', 'fa-3': 'icon-bold' }, callback: function(e){ // Give/remove ** surround the selection var chunk, cursor, selected = e.getSelection(), content = e.getContent() if (selected.length == 0) { // Give extra word - chunk = 'strong text' + chunk = e.__localize('strong text') } else { chunk = selected.text } // transform selection and set the cursor into chunked text @@ -705,18 +930,19 @@ e.setSelection(cursor,cursor+chunk.length) } },{ name: 'cmdItalic', title: 'Italic', - icon: 'glyphicon glyphicon-italic', + hotkey: 'Ctrl+I', + icon: { glyph: 'glyphicon glyphicon-italic', fa: 'fa fa-italic', 'fa-3': 'icon-italic' }, callback: function(e){ // Give/remove * surround the selection var chunk, cursor, selected = e.getSelection(), content = e.getContent() if (selected.length == 0) { // Give extra word - chunk = 'emphasized text' + chunk = e.__localize('emphasized text') } else { chunk = selected.text } // transform selection and set the cursor into chunked text @@ -734,34 +960,35 @@ e.setSelection(cursor,cursor+chunk.length) } },{ name: 'cmdHeading', title: 'Heading', - icon: 'glyphicon glyphicon-font', + hotkey: 'Ctrl+H', + icon: { glyph: 'glyphicon glyphicon-header', fa: 'fa fa-font', 'fa-3': 'icon-font' }, callback: function(e){ // Append/remove ### surround the selection var chunk, cursor, selected = e.getSelection(), content = e.getContent(), pointer, prevChar if (selected.length == 0) { // Give extra word - chunk = 'heading text' + chunk = e.__localize('heading text') } else { - chunk = selected.text + chunk = selected.text + '\n'; } // transform selection and set the cursor into chunked text if ((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 (prevChar = content.substr(selected.start-1,1), !!prevChar && prevChar != '\n') { - e.replaceSelection('\n\n### '+chunk+'\n') + } 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 element - e.replaceSelection('### '+chunk+'\n') + e.replaceSelection('### '+chunk) cursor = selected.start+4 } // Set the cursor e.setSelection(cursor,cursor+chunk.length) @@ -770,25 +997,26 @@ },{ name: 'groupLink', data: [{ name: 'cmdUrl', title: 'URL/Link', - icon: 'glyphicon glyphicon-globe', + 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 link var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link if (selected.length == 0) { // Give extra word - chunk = 'enter link description here' + chunk = e.__localize('enter link description here') } else { chunk = selected.text } - link = prompt('Insert Hyperlink','http://') + link = prompt(e.__localize('Insert Hyperlink'),'http://') - if (link != null) { + if (link != null && link != '' && link != 'http://') { // transform selection and set the cursor into chunked text e.replaceSelection('['+chunk+']('+link+')') cursor = selected.start+1 // Set the cursor @@ -796,56 +1024,58 @@ } } },{ name: 'cmdImage', title: 'Image', - icon: 'glyphicon glyphicon-picture', + 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 link var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link if (selected.length == 0) { // Give extra word - chunk = 'enter image description here' + chunk = e.__localize('enter image description here') } else { chunk = selected.text } - link = prompt('Insert Image Hyperlink','http://') + link = prompt(e.__localize('Insert Image Hyperlink'),'http://') if (link != null) { // transform selection and set the cursor into chunked text - e.replaceSelection('!['+chunk+']('+link+' "enter image title here")') + e.replaceSelection('!['+chunk+']('+link+' "'+e.__localize('enter image title here')+'")') cursor = selected.start+2 // Set the next tab - e.setNextTab('enter image title here') + e.setNextTab(e.__localize('enter image title here')) // Set the cursor e.setSelection(cursor,cursor+chunk.length) } } }] },{ name: 'groupMisc', data: [{ name: 'cmdList', - title: 'List', - icon: 'glyphicon glyphicon-list', + 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 selection var chunk, cursor, selected = e.getSelection(), content = e.getContent() // transform selection and set the cursor into chunked text if (selected.length == 0) { // Give extra word - chunk = 'list text here' + chunk = e.__localize('list text here') e.replaceSelection('- '+chunk) - // Set the cursor cursor = selected.start+2 + } else { if (selected.text.indexOf('\n') < 0) { chunk = selected.text e.replaceSelection('- '+chunk) @@ -867,25 +1097,149 @@ // Set the cursor cursor = selected.start+4 } } + // Set the cursor + e.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 selection + var chunk, cursor, selected = e.getSelection(), content = e.getContent() + // transform selection and set the cursor into chunked text + if (selected.length == 0) { + // Give extra word + chunk = e.__localize('list text here') + e.replaceSelection('1. '+chunk) + // Set the cursor + cursor = selected.start+3 + + } else { + if (selected.text.indexOf('\n') < 0) { + chunk = selected.text + + e.replaceSelection('1. '+chunk) + + // Set the cursor + cursor = 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 cursor + cursor = selected.start+5 + } + } + // Set the cursor e.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 selection + var chunk, cursor, selected = e.getSelection(), content = e.getContent() + + if (selected.length == 0) { + // Give extra word + chunk = e.__localize('code text here') + } else { + chunk = selected.text + } + + // transform selection and set the cursor into chunked text + 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 { + e.replaceSelection('`'+chunk+'`') + cursor = selected.start+1 + } + + // Set the cursor + e.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 selection + var chunk, cursor, selected = e.getSelection(), content = e.getContent() + + // transform selection and set the cursor into chunked text + if (selected.length == 0) { + // Give extra word + chunk = e.__localize('quote here') + e.replaceSelection('> '+chunk) + // Set the cursor + cursor = selected.start+2 + + } else { + if (selected.text.indexOf('\n') < 0) { + chunk = selected.text + + e.replaceSelection('> '+chunk) + + // Set the cursor + cursor = 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 cursor + cursor = selected.start+4 + } + } + + // Set the cursor + e.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: 'glyphicon glyphicon-search', + 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 flag var isPreview = e.$isPreview,content if (isPreview == false) { @@ -897,16 +1251,43 @@ } }] }] ], additionalButtons:[], // Place to hook more buttons by code + reorderButtonGroups:[], + hiddenButtons:[], // Default hidden buttons + disabledButtons:[], // Default disabled buttons + footer: '', + 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' + }, + switchTheme: { + fa: 'fa fa-adjust', + glyph: 'glyphicon glyphicon-adjust', + 'fa-3': 'icon-adjust' + } + } + }, /* Events hook */ onShow: function (e) {}, onPreview: function (e) {}, onSave: function (e) {}, - onBlur: function (e) {} + onBlur: function (e) {}, + onFocus: function (e) {}, + onChange: function(e) {}, + onFullscreen: function(e) {} } $.fn.markdown.Constructor = Markdown @@ -925,11 +1306,12 @@ if ($this.data('markdown')) { $this.data('markdown').showEditor() return } - $this.markdown($this.data()) + + $this.markdown() } var analyzeMarkdown = function(e) { var blurred = false, el, @@ -991,6 +1373,6 @@ $('textarea[data-provide="markdown"]').each(function(){ initMarkdown($(this)) }) }) -}(window.jQuery); \ No newline at end of file +}(window.jQuery);