From 0dcf2826017e9e623359af95a3834264e86f3a48 Mon Sep 17 00:00:00 2001 From: Nishanth Vijayan Date: Mon, 7 Mar 2016 22:56:40 +0530 Subject: [PATCH] Update bootstrap-markdown to v2.10.0.Fixes markdown editors bug #811. --- .../stylesheets/bootstrap-markdown.min.css | 2 +- .../assets/javascripts/bootstrap-markdown.js | 1093 +++++++++-------- 2 files changed, 609 insertions(+), 486 deletions(-) diff --git a/app/assets/stylesheets/bootstrap-markdown.min.css b/app/assets/stylesheets/bootstrap-markdown.min.css index ac71e895..388b2f5f 100644 --- a/app/assets/stylesheets/bootstrap-markdown.min.css +++ b/app/assets/stylesheets/bootstrap-markdown.min.css @@ -1 +1 @@ -.md-editor{display:block;border:1px solid #ddd}.md-editor>.md-header,.md-editor .md-footer{display:block;padding:6px 4px;background:#fff}.md-editor>.md-header{margin: 0;}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:14px;outline:0;outline:thin dotted \9;margin:0;display:block;padding:0;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#eee}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6)} \ No newline at end of file +.md-editor{display:block;border:1px solid #ddd}.md-editor .md-footer,.md-editor>.md-header{display:block;padding:6px 4px;background:#f5f5f5}.md-editor>.md-header{margin:0}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:14px;outline:0;margin:0;display:block;padding:0;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#eee}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.md-editor .md-controls{float:right;padding:3px}.md-editor .md-controls .md-control{right:5px;color:#bebebe;padding:3px 3px 3px 10px}.md-editor .md-controls .md-control:hover{color:#333}.md-editor.md-fullscreen-mode{width:100%;height:100%;position:fixed;top:0;left:0;z-index:99999;padding:60px 30px 15px;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-footer{display:none}.md-editor.md-fullscreen-mode .md-input,.md-editor.md-fullscreen-mode .md-preview{margin:0 auto!important;height:100%!important;font-size:20px!important;padding:20px!important;color:#999;line-height:1.6em!important;resize:none!important;box-shadow:none!important;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-preview{color:#333;overflow:auto}.md-editor.md-fullscreen-mode .md-input:focus,.md-editor.md-fullscreen-mode .md-input:hover{color:#333;background:#fff!important}.md-editor.md-fullscreen-mode .md-header{background:0 0;text-align:center;position:fixed;width:100%;top:20px}.md-editor.md-fullscreen-mode .btn-group{float:none}.md-editor.md-fullscreen-mode .btn{border:0;background:0 0;color:#b3b3b3}.md-editor.md-fullscreen-mode .btn.active,.md-editor.md-fullscreen-mode .btn:active,.md-editor.md-fullscreen-mode .btn:focus,.md-editor.md-fullscreen-mode .btn:hover{box-shadow:none;color:#333}.md-editor.md-fullscreen-mode .md-fullscreen-controls{position:absolute;top:20px;right:20px;text-align:right;z-index:1002;display:block}.md-editor.md-fullscreen-mode .md-fullscreen-controls a{color:#b3b3b3;clear:right;margin:10px;width:30px;height:30px;text-align:center}.md-editor.md-fullscreen-mode .md-fullscreen-controls a:hover{color:#333;text-decoration:none}.md-editor.md-fullscreen-mode .md-editor{height:100%!important;position:relative}.md-editor .md-fullscreen-controls{display:none}.md-nooverflow{overflow:hidden;position:fixed;width:100%} \ No newline at end of file diff --git a/vendor/assets/javascripts/bootstrap-markdown.js b/vendor/assets/javascripts/bootstrap-markdown.js index 2256df64..ae8075b6 100644 --- a/vendor/assets/javascripts/bootstrap-markdown.js +++ b/vendor/assets/javascripts/bootstrap-markdown.js @@ -1,8 +1,8 @@ /* =================================================== - * bootstrap-markdown.js v2.5.0 + * bootstrap-markdown.js v2.10.0 * http://github.com/toopay/bootstrap-markdown * =================================================== - * Copyright 2013 Taufan Aditya + * Copyright 2013-2016 Taufan Aditya * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,141 +17,167 @@ * limitations under the License. * ========================================================== */ -!function ($) { - +(function(factory){ + if (typeof define === "function" && define.amd) { + //RequireJS + define(["jquery"], factory); + } else if (typeof exports === 'object') { + //Backbone.js + factory(require('jquery')); + } else { + //Jquery plugin + factory(jQuery); + } +}(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.$element.data(), this.$element.data('options')) - this.$oldContent = null - this.$isPreview = false - this.$editor = null - this.$textarea = null - this.$handler = [] - this.$callback = [] - this.$nextTab = [] + // @TODO : remove this BC on next major release + // @see : https://github.com/toopay/bootstrap-markdown/issues/109 + var 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 - this.showEditor() - } + // 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.$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 + var handler = this.$handler, isAll = (name == 'all'),that = this; $.each(handler,function(k,v) { - var halt = true + var halt = true; if (isAll) { - halt = false + halt = false; } else { - halt = v.indexOf(name) < 0 + halt = v.indexOf(name) < 0; } - if (halt == false) { - alter(that.$editor.find('button[data-handler="'+v+'"]')) + 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 + callback = this.$callback; for (i=0;i', { 'class': 'btn-group' - }) + }); for (z=0;z'); + 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 = $(''); + buttonIconContainer.addClass(buttonIcon); + buttonIconContainer.prependTo(buttonContainer); // Attach the button object - btnGroupContainer.append('') + btnGroupContainer.append(buttonContainer); // Register handler and callback - handler.push(buttonHandler) - callback.push(button.callback) + handler.push(buttonHandler); + callback.push(button.callback); } // Attach the button group into container dom - container.append(btnGroupContainer) + container.append(btnGroupContainer); } } - return container + return container; } , __setListener: function() { // Set size and resizable Properties - var hasRows = typeof this.$textarea.attr('rows') != 'undefined', + 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 + rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows; - this.$textarea.attr('rows',rowsVal) + this.$textarea.attr('rows',rowsVal); if (this.$options.resize) { - this.$textarea.css('resize',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)) + this.$textarea.on({ + 'focus' : $.proxy(this.focus, this), + 'keyup' : $.proxy(this.keyup, this), + 'change' : $.proxy(this.change, this), + 'select' : $.proxy(this.select, this) + }); if (this.eventSupported('keydown')) { - this.$textarea.on('keydown', $.proxy(this.keydown, this)) + this.$textarea.on('keydown', $.proxy(this.keydown, this)); + } + + if (this.eventSupported('keypress')) { + this.$textarea.on('keypress', $.proxy(this.keypress, this)) } // Re-attach markdown data - this.$textarea.data('markdown',this) + this.$textarea.data('markdown',this); } , __handle: function(e) { @@ -160,12 +186,12 @@ callback = this.$callback, handlerName = target.attr('data-handler'), callbackIndex = handler.indexOf(handlerName), - callbackHandler = callback[callbackIndex] + callbackHandler = callback[callbackIndex]; // Trigger the focusin - $(e.currentTarget).focus() + $(e.currentTarget).focus(); - callbackHandler(this) + callbackHandler(this); // Trigger onChange for each button handle this.change(this); @@ -173,15 +199,15 @@ // Unless it was the save handler, // focusin the textarea if (handlerName.indexOf('cmdSave') < 0) { - this.$textarea.focus() + this.$textarea.focus(); } - e.preventDefault() + e.preventDefault(); } , __localize: function(string) { var messages = $.fn.markdown.messages, - language = this.$options.language + language = this.$options.language; if ( typeof messages !== 'undefined' && typeof messages[language] !== 'undefined' && @@ -192,6 +218,30 @@ 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.$options.onFullscreenExit(this); + + if (this.$isPreview == true) this.hidePreview().showPreview() + } + + this.$isFullscreen = mode; + $textarea.focus(); + } + , showEditor: function() { var instance = this, textarea, @@ -206,201 +256,259 @@ editor = $( '
', { 'class': 'md-editor', click: function() { - instance.focus() + instance.focus(); } - }) + }); // Prepare the editor - if (this.$editor == null) { + if (this.$editor === null) { // Create the panel var editorHeader = $('
', { 'class': 'md-header btn-toolbar' - }) + }); // 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]) + var 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 group + var 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 group + if(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 groups if (options.reorderButtonGroups.length > 0) { allBtnGroups = allBtnGroups .filter(function(btnGroup) { - return options.reorderButtonGroups.indexOf(btnGroup.name) > -1 + 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 - }) + 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 buttons if (allBtnGroups.length > 0) { - editorHeader = this.__buildButtons([allBtnGroups], editorHeader) + editorHeader = this.__buildButtons([allBtnGroups], editorHeader); } - editor.append(editorHeader) + if (options.fullscreen.enable) { + editorHeader.append('
').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) - textarea = container - textarea.addClass('md-input') - editor.append(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) + currentContent = $.trim(rawContent); // This is some arbitrary content that could be edited textarea = $('