Finish formatting logic + Add Media Manager buttons
This commit is contained in:
parent
aef1964553
commit
20411f6fb1
|
|
@ -17,6 +17,11 @@ class MarkdownEditor extends FormWidgetBase
|
|||
// Configurable properties
|
||||
//
|
||||
|
||||
/**
|
||||
* @var bool Display mode: split, tab.
|
||||
*/
|
||||
public $mode = 'tab';
|
||||
|
||||
//
|
||||
// Object properties
|
||||
//
|
||||
|
|
@ -31,7 +36,9 @@ class MarkdownEditor extends FormWidgetBase
|
|||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->fillFromConfig([]);
|
||||
$this->fillFromConfig([
|
||||
'mode',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -48,6 +55,7 @@ class MarkdownEditor extends FormWidgetBase
|
|||
*/
|
||||
public function prepareVars()
|
||||
{
|
||||
$this->vars['mode'] = $this->mode;
|
||||
$this->vars['stretch'] = $this->formField->stretch;
|
||||
$this->vars['size'] = $this->formField->size;
|
||||
$this->vars['name'] = $this->formField->getName();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
background: #fff;
|
||||
-webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.field-markdowneditor textarea {
|
||||
|
|
@ -18,35 +20,58 @@
|
|||
.field-markdowneditor.editor-focus {
|
||||
border: 1px solid #808c8d;
|
||||
}
|
||||
.field-markdowneditor.size-tiny .editor-write,
|
||||
.field-markdowneditor.size-tiny .editor-write {
|
||||
min-height: 50px;
|
||||
}
|
||||
.field-markdowneditor.size-tiny .editor-preview {
|
||||
height: 50px;
|
||||
}
|
||||
.field-markdowneditor.size-small .editor-write,
|
||||
.field-markdowneditor.size-small .editor-write {
|
||||
min-height: 100px;
|
||||
}
|
||||
.field-markdowneditor.size-small .editor-preview {
|
||||
height: 100px;
|
||||
}
|
||||
.field-markdowneditor.size-large .editor-write,
|
||||
.field-markdowneditor.size-large .editor-write {
|
||||
min-height: 200px;
|
||||
}
|
||||
.field-markdowneditor.size-large .editor-preview {
|
||||
height: 200px;
|
||||
}
|
||||
.field-markdowneditor.size-huge .editor-write,
|
||||
.field-markdowneditor.size-huge .editor-write {
|
||||
min-height: 250px;
|
||||
}
|
||||
.field-markdowneditor.size-huge .editor-preview {
|
||||
height: 250px;
|
||||
}
|
||||
.field-markdowneditor.size-giant .editor-write,
|
||||
.field-markdowneditor.size-giant .editor-write {
|
||||
min-height: 350px;
|
||||
}
|
||||
.field-markdowneditor.size-giant .editor-preview {
|
||||
height: 350px;
|
||||
}
|
||||
.field-markdowneditor .editor-write {
|
||||
position: relative;
|
||||
margin: 15px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview {
|
||||
padding: 15px;
|
||||
overflow: auto;
|
||||
}
|
||||
.field-markdowneditor .editor-preview-loader {
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
margin-top: 40px;
|
||||
background-image: url('../../../../../system/assets/ui/images/loader-transparent.svg');
|
||||
background-size: 20px 20px;
|
||||
background-position: 50% 50%;
|
||||
-webkit-animation: spin 1s linear infinite;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
.field-markdowneditor.mode-tab .editor-preview {
|
||||
overflow: auto;
|
||||
display: none;
|
||||
}
|
||||
.field-markdowneditor.mode-tab.is-preview .editor-write {
|
||||
|
|
@ -55,3 +80,119 @@
|
|||
.field-markdowneditor.mode-tab.is-preview .editor-preview {
|
||||
display: block;
|
||||
}
|
||||
.field-markdowneditor.mode-split .editor-preview {
|
||||
float: right;
|
||||
width: 50%;
|
||||
}
|
||||
.field-markdowneditor.mode-split .editor-write {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
.field-markdowneditor.mode-split .editor-write .editor-code {
|
||||
border-right: 2px solid #808C8D;
|
||||
}
|
||||
.field-markdowneditor.stretch,
|
||||
.field-markdowneditor.stretch .editor-toolbar {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.field-markdowneditor.stretch .editor-toolbar {
|
||||
height: auto;
|
||||
}
|
||||
.field-markdowneditor.stretch .editor-write,
|
||||
.field-markdowneditor.stretch .editor-preview {
|
||||
float: none;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin-top: 40px;
|
||||
}
|
||||
.field-markdowneditor.stretch .editor-write {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
.field-markdowneditor.is-fullscreen {
|
||||
z-index: 1020;
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.field-markdowneditor.is-fullscreen,
|
||||
.field-markdowneditor.is-fullscreen .editor-toolbar {
|
||||
border-radius: 0 !important;
|
||||
border: none;
|
||||
}
|
||||
.field-markdowneditor .editor-preview {
|
||||
color: #515c5d;
|
||||
font-family: "Helvetica", sans-serif;
|
||||
line-height: 180%;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h1,
|
||||
.field-markdowneditor .editor-preview h2,
|
||||
.field-markdowneditor .editor-preview h3,
|
||||
.field-markdowneditor .editor-preview h4,
|
||||
.field-markdowneditor .editor-preview h5,
|
||||
.field-markdowneditor .editor-preview h6 {
|
||||
margin-top: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h1:first-child,
|
||||
.field-markdowneditor .editor-preview h2:first-child,
|
||||
.field-markdowneditor .editor-preview h3:first-child,
|
||||
.field-markdowneditor .editor-preview h4:first-child,
|
||||
.field-markdowneditor .editor-preview h5:first-child,
|
||||
.field-markdowneditor .editor-preview h6:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.field-markdowneditor .editor-preview *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h1 {
|
||||
font-size: 30px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h2 {
|
||||
font-size: 26px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h4 {
|
||||
font-size: 22px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h5 {
|
||||
font-size: 20px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h6 {
|
||||
font-size: 18px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview p,
|
||||
.field-markdowneditor .editor-preview ol,
|
||||
.field-markdowneditor .editor-preview ul {
|
||||
font-size: 14px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview h1,
|
||||
.field-markdowneditor .editor-preview h2,
|
||||
.field-markdowneditor .editor-preview h3,
|
||||
.field-markdowneditor .editor-preview h4,
|
||||
.field-markdowneditor .editor-preview h5,
|
||||
.field-markdowneditor .editor-preview h6,
|
||||
.field-markdowneditor .editor-preview p,
|
||||
.field-markdowneditor .editor-preview ol,
|
||||
.field-markdowneditor .editor-preview ul {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.field-markdowneditor .editor-preview pre.prettyprint {
|
||||
border-width: 0;
|
||||
padding: 13px 16px;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
line-height: 130%;
|
||||
}
|
||||
.field-markdowneditor .editor-preview img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
this.$form = null
|
||||
this.$buttons = null
|
||||
this.$fixedButtons = null
|
||||
this.$indicator = null
|
||||
this.editorPadding = 15
|
||||
|
||||
$.oc.foundation.controlUtils.markDisposable(element)
|
||||
Base.call(this)
|
||||
|
|
@ -33,14 +35,17 @@
|
|||
this.$el.attr('id', 'element-' + Math.random().toString(36).substring(7))
|
||||
}
|
||||
|
||||
this.$el.addClass('mode-' + this.options.viewMode)
|
||||
this.$form = this.$el.closest('form')
|
||||
|
||||
this.createCodeContainer()
|
||||
this.createToolbar()
|
||||
this.createIndicator()
|
||||
this.setViewMode(this.options.viewMode)
|
||||
|
||||
this.$toolbar.on('click', '.btn, .md-dropdown-button', this.proxy(this.onClickToolbarButton))
|
||||
this.$form.on('oc.beforeRequest', this.proxy(this.onBeforeRequest))
|
||||
this.editor.on('change', this.proxy(this.onEditorChange))
|
||||
this.editor.getSession().on('changeScrollTop', this.proxy(this.onEditorScrollTop))
|
||||
|
||||
$('[data-control="tooltip"]', this.$toolbar).tooltip()
|
||||
$('[data-toggle="dropdown"]', this.$toolbar).dropdown()
|
||||
|
|
@ -48,8 +53,11 @@
|
|||
|
||||
MarkdownEditor.prototype.dispose = function() {
|
||||
this.$el.off('dispose-control', this.proxy(this.dispose))
|
||||
|
||||
this.$toolbar.off('click', '.btn, .md-dropdown-button', this.proxy(this.onClickToolbarButton))
|
||||
this.$form.off('oc.beforeRequest', this.proxy(this.onBeforeRequest))
|
||||
this.editor.off('change', this.proxy(this.onEditorChange))
|
||||
$(window).off('resize', this.proxy(this.updateFullscreen))
|
||||
|
||||
this.$el.removeData('oc.markdownEditor')
|
||||
|
||||
|
|
@ -63,31 +71,18 @@
|
|||
this.$form = null
|
||||
this.$buttons = null
|
||||
this.$fixedButtons = null
|
||||
this.$indicator = null
|
||||
|
||||
this.isSplitMode = false
|
||||
this.isPreview = false
|
||||
this.isFullscreen = false
|
||||
this.isSplitMode = null
|
||||
this.isPreview = null
|
||||
this.isFullscreen = null
|
||||
this.dataTrackInputTimer = null
|
||||
|
||||
this.options = null
|
||||
|
||||
BaseProto.dispose.call(this)
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.onClickToolbarButton = function(ev) {
|
||||
var $button = $(ev.target),
|
||||
action = $button.data('button-action'),
|
||||
template = $button.data('button-template')
|
||||
|
||||
$button.blur()
|
||||
|
||||
if (template) {
|
||||
this[action](template)
|
||||
}
|
||||
else {
|
||||
this[action]()
|
||||
}
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.createToolbar = function() {
|
||||
var self = this,
|
||||
$button,
|
||||
|
|
@ -152,6 +147,10 @@
|
|||
'data-button-action': childButton.action
|
||||
})
|
||||
|
||||
if (childButton.template) {
|
||||
$childButton.attr('data-button-template', childButton.template)
|
||||
}
|
||||
|
||||
if (childButton.cssClass) {
|
||||
$childButton.addClass(childButton.cssClass)
|
||||
}
|
||||
|
|
@ -187,8 +186,22 @@
|
|||
*/
|
||||
var editor = this.editor = ace.edit(this.$code.attr('id'))
|
||||
|
||||
// Fixes a weird notice about scrolling
|
||||
editor.$blockScrolling = Infinity
|
||||
|
||||
editor.getSession().setValue(this.$textarea.val())
|
||||
|
||||
/*
|
||||
* Set theme, anticipated languages should be preloaded
|
||||
*/
|
||||
assetManager.load({
|
||||
js:[
|
||||
this.options.vendorPath + '/theme-github.js'
|
||||
]
|
||||
}, function(){
|
||||
editor.setTheme('ace/theme/github')
|
||||
})
|
||||
|
||||
editor.getSession().setMode({ path: 'ace/mode/markdown' })
|
||||
editor.setHighlightActiveLine(false)
|
||||
editor.renderer.setShowGutter(false)
|
||||
|
|
@ -197,17 +210,88 @@
|
|||
editor.setFontSize(14)
|
||||
editor.on('blur', this.proxy(this.onBlur))
|
||||
editor.on('focus', this.proxy(this.onFocus))
|
||||
|
||||
// Set the vendor path for Ace's require path
|
||||
ace.require('ace/config').set('basePath', this.options.vendorPath)
|
||||
|
||||
editor.renderer.setPadding(this.editorPadding)
|
||||
editor.renderer.setScrollMargin(this.editorPadding, this.editorPadding, 0, 0)
|
||||
|
||||
setTimeout(function() {
|
||||
editor.resize()
|
||||
}, 100)
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.updatePreview = function() {
|
||||
//
|
||||
// Events
|
||||
//
|
||||
|
||||
MarkdownEditor.prototype.onClickToolbarButton = function(ev) {
|
||||
var $button = $(ev.target),
|
||||
action = $button.data('button-action'),
|
||||
template = $button.data('button-template')
|
||||
|
||||
$button.blur()
|
||||
|
||||
if (template) {
|
||||
this[action](template)
|
||||
}
|
||||
else {
|
||||
this[action]()
|
||||
}
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.onEditorScrollTop = function(scroll) {
|
||||
if (!this.isSplitMode) return
|
||||
|
||||
var canvasHeight = this.$preview.height(),
|
||||
editorHeight,
|
||||
previewHeight,
|
||||
scrollRatio
|
||||
|
||||
if (canvasHeight != this.$el.data('markdowneditor-canvas-height')) {
|
||||
|
||||
editorHeight =
|
||||
(this.editor.getSession().getScreenLength() *
|
||||
this.editor.renderer.lineHeight) -
|
||||
canvasHeight
|
||||
|
||||
previewHeight = this.$preview.get(0).scrollHeight - canvasHeight
|
||||
|
||||
scrollRatio = previewHeight / editorHeight
|
||||
|
||||
this.$el.data('markdowneditor-canvas-height', canvasHeight)
|
||||
this.$el.data('markdowneditor-scroll-ratio', scrollRatio)
|
||||
}
|
||||
else {
|
||||
scrollRatio = this.$el.data('markdowneditor-scroll-ratio')
|
||||
}
|
||||
|
||||
scroll += this.editorPadding
|
||||
this.$preview.scrollTop(scroll * scrollRatio)
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.onEditorChange = function() {
|
||||
this.$form.trigger('change')
|
||||
|
||||
var self = this
|
||||
|
||||
this.$el.request(this.options.refreshHandler, {
|
||||
success: function(data) {
|
||||
this.success(data)
|
||||
self.$preview.html(data.preview)
|
||||
if (!this.isSplitMode) return
|
||||
|
||||
if (this.loading) {
|
||||
if (this.dataTrackInputTimer === undefined) {
|
||||
this.dataTrackInputTimer = window.setInterval(function(){
|
||||
self.onEditorChange()
|
||||
}, 100)
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
window.clearTimeout(this.dataTrackInputTimer)
|
||||
this.dataTrackInputTimer = undefined
|
||||
|
||||
self.updatePreview()
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.onBeforeRequest = function() {
|
||||
|
|
@ -226,21 +310,171 @@
|
|||
this.$el.addClass('editor-focus')
|
||||
}
|
||||
|
||||
/*
|
||||
* Button actions
|
||||
*/
|
||||
//
|
||||
// Preview
|
||||
//
|
||||
|
||||
MarkdownEditor.prototype.updatePreview = function() {
|
||||
var self = this
|
||||
|
||||
this.loading = true
|
||||
this.showIndicator()
|
||||
|
||||
this.$el.request(this.options.refreshHandler, {
|
||||
success: function(data) {
|
||||
this.success(data)
|
||||
self.$preview.html(data.preview)
|
||||
self.initPreview()
|
||||
}
|
||||
}).done(function() {
|
||||
self.hideIndicator()
|
||||
self.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.initPreview = function() {
|
||||
$('pre', this.$preview).addClass('prettyprint')
|
||||
prettyPrint()
|
||||
}
|
||||
|
||||
//
|
||||
// Loader
|
||||
//
|
||||
|
||||
MarkdownEditor.prototype.createIndicator = function() {
|
||||
this.$indicator = $('<div class="editor-preview-loader"></div>')
|
||||
this.$el.prepend(this.$indicator)
|
||||
this.$indicator.css('display', 'none')
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.showIndicator = function() {
|
||||
this.$indicator.css('display', 'block')
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.hideIndicator = function() {
|
||||
this.$indicator.css('display', 'none')
|
||||
}
|
||||
|
||||
//
|
||||
// View mode
|
||||
//
|
||||
|
||||
MarkdownEditor.prototype.setViewMode = function(value) {
|
||||
this.isSplitMode = value == 'split'
|
||||
|
||||
$('[data-button-code="preview"]', this.$toolbar).toggle(!this.isSplitMode)
|
||||
|
||||
this.$el
|
||||
.removeClass('mode-tab mode-split')
|
||||
.addClass('mode-' + value)
|
||||
|
||||
if (this.isSplitMode) {
|
||||
this.updatePreview()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Full screen
|
||||
//
|
||||
|
||||
MarkdownEditor.prototype.setFullscreen = function(value) {
|
||||
this.isFullscreen = value
|
||||
this.$el.toggleClass('is-fullscreen', value)
|
||||
|
||||
if (value) {
|
||||
$('body, html').css('overflow', 'hidden')
|
||||
this.updateFullscreen()
|
||||
this.setViewMode('split')
|
||||
$(window).on('resize', this.proxy(this.updateFullscreen))
|
||||
}
|
||||
else {
|
||||
this.setViewMode(this.options.viewMode)
|
||||
|
||||
this.$preview.css('height', '')
|
||||
this.$write.css('height', '')
|
||||
$('body, html').css('overflow', '')
|
||||
|
||||
$(window).off('resize', this.proxy(this.updateFullscreen))
|
||||
this.editor.resize()
|
||||
}
|
||||
|
||||
$(window).trigger('oc.updateUi')
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.updateFullscreen = function() {
|
||||
if (!this.isFullscreen) return
|
||||
|
||||
var fullscreenCss = {
|
||||
height: $(document).height() - this.$toolbar.outerHeight()
|
||||
}
|
||||
|
||||
this.$preview.css(fullscreenCss)
|
||||
this.$write.css(fullscreenCss)
|
||||
this.editor.resize()
|
||||
}
|
||||
|
||||
//
|
||||
// Media Manager
|
||||
//
|
||||
|
||||
MarkdownEditor.prototype.launchMediaManager = function(onSuccess) {
|
||||
var self = this
|
||||
|
||||
new $.oc.mediaManager.popup({
|
||||
alias: 'ocmediamanager',
|
||||
cropAndInsertButton: true,
|
||||
onInsert: function(items) {
|
||||
if (!items.length) {
|
||||
alert('Please select image(s) to insert.')
|
||||
return
|
||||
}
|
||||
|
||||
if (items.length > 1) {
|
||||
alert('Please select a single item.')
|
||||
return
|
||||
}
|
||||
|
||||
var path, publicUrl
|
||||
for (var i=0, len=items.length; i<len; i++) {
|
||||
path = items[i].path
|
||||
publicUrl = items[i].publicUrl
|
||||
}
|
||||
|
||||
onSuccess(publicUrl)
|
||||
|
||||
this.hide()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// Button actions
|
||||
//
|
||||
|
||||
MarkdownEditor.prototype.toggleFullscreen = function() {
|
||||
this.setFullscreen(!this.isFullscreen)
|
||||
if (this.isPreview) {
|
||||
this.togglePreview()
|
||||
}
|
||||
|
||||
this.editor.focus()
|
||||
$('[data-button-code="fullscreen"]', this.$toolbar).toggleClass('active')
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.togglePreview = function() {
|
||||
if (!this.isPreview) {
|
||||
this.isPreview = !this.isPreview
|
||||
|
||||
if (this.isPreview) {
|
||||
this.updatePreview()
|
||||
}
|
||||
else {
|
||||
this.editor.focus()
|
||||
}
|
||||
|
||||
this.$el.toggleClass('is-preview', !this.isPreview)
|
||||
$('.btn', this.$buttons).prop('disabled', !this.isPreview)
|
||||
this.isPreview = !this.isPreview
|
||||
this.$el.toggleClass('is-preview', this.isPreview)
|
||||
$('.btn', this.$buttons).prop('disabled', this.isPreview)
|
||||
|
||||
$('[data-button-code="preview"]', this.$toolbar).toggleClass('active')
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.insertLine = function(template) {
|
||||
|
|
@ -258,10 +492,97 @@
|
|||
editor.focus()
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.formatInline = function(template) {
|
||||
var editor = this.editor,
|
||||
pos = this.editor.getCursorPosition(),
|
||||
text = editor.session.getTextRange(editor.selection.getRange()).trim()
|
||||
|
||||
if (!text.length) {
|
||||
editor.selection.selectWord()
|
||||
text = editor.session.getTextRange(editor.selection.getRange()).trim()
|
||||
}
|
||||
|
||||
editor.insert(template.replace('$1', text))
|
||||
editor.moveCursorToPosition(pos)
|
||||
|
||||
if (template.indexOf('$1') != -1) {
|
||||
editor.navigateRight(template.indexOf('$1'))
|
||||
}
|
||||
|
||||
editor.focus()
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.formatBlock = function(template) {
|
||||
var editor = this.editor,
|
||||
pos = this.editor.getCursorPosition(),
|
||||
text = editor.session.getTextRange(editor.selection.getRange()).trim()
|
||||
|
||||
if (!text.length) {
|
||||
editor.navigateTo(editor.getSelectionRange().start.row, 0)
|
||||
editor.selection.selectLineEnd()
|
||||
text = editor.session.getTextRange(editor.selection.getRange()).trim()
|
||||
}
|
||||
else {
|
||||
editor.insert('\n')
|
||||
}
|
||||
|
||||
editor.insert(template.replace('$1', text))
|
||||
editor.moveCursorToPosition(pos)
|
||||
|
||||
if (template.indexOf('$1') != -1) {
|
||||
editor.navigateRight(template.indexOf('$1'))
|
||||
}
|
||||
|
||||
editor.focus()
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.formatBlockMulti = function(template) {
|
||||
var editor = this.editor,
|
||||
pos = this.editor.getCursorPosition(),
|
||||
text = editor.session.getTextRange(editor.selection.getRange()).trim()
|
||||
|
||||
if (!text.length) {
|
||||
editor.navigateTo(editor.getSelectionRange().start.row, 0)
|
||||
editor.selection.selectLineEnd()
|
||||
}
|
||||
|
||||
var range = editor.selection.getRange()
|
||||
for (var i = range.start.row + 1; i < range.end.row + 2; i++) {
|
||||
editor.gotoLine(i);
|
||||
editor.insert(template.replace('$1', ''));
|
||||
}
|
||||
|
||||
editor.moveCursorToPosition(pos)
|
||||
editor.focus()
|
||||
}
|
||||
|
||||
MarkdownEditor.prototype.formatMediaManager = function(template) {
|
||||
var self = this,
|
||||
editor = this.editor,
|
||||
pos = this.editor.getCursorPosition(),
|
||||
text = editor.session.getTextRange(editor.selection.getRange()).trim()
|
||||
|
||||
if (!text.length) {
|
||||
editor.selection.selectWord()
|
||||
text = editor.session.getTextRange(editor.selection.getRange()).trim()
|
||||
}
|
||||
|
||||
this.launchMediaManager(function(path) {
|
||||
editor.insert(template.replace('$1', text).replace('$2', path));
|
||||
editor.moveCursorToPosition(pos)
|
||||
editor.focus()
|
||||
|
||||
if (!text.length && template.indexOf('$1') != -1) {
|
||||
editor.navigateRight(template.indexOf('$1'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
MarkdownEditor.DEFAULTS = {
|
||||
vendorPath: '/',
|
||||
refreshHandler: null,
|
||||
buttons: ['formatting', 'bold', 'italic', 'unorderedlist', 'orderedlist', 'link', 'horizontalrule'],
|
||||
viewMode: 'tab',
|
||||
refreshHandler: null
|
||||
viewMode: 'tab'
|
||||
}
|
||||
|
||||
// PLUGIN DEFINITION
|
||||
|
|
@ -307,49 +628,49 @@
|
|||
quote: {
|
||||
label: 'markdowneditor.quote',
|
||||
cssClass: 'oc-button oc-icon-quote-right',
|
||||
action: 'list.toggle',
|
||||
action: 'formatBlockMulti',
|
||||
template: '> $1'
|
||||
},
|
||||
code: {
|
||||
label: 'markdowneditor.code',
|
||||
cssClass: 'oc-button oc-icon-code',
|
||||
action: 'block.format',
|
||||
template: '```$1```'
|
||||
action: 'formatBlock',
|
||||
template: '\n```\n$1\n```\n'
|
||||
},
|
||||
header1: {
|
||||
label: 'markdowneditor.header1',
|
||||
cssClass: 'oc-button oc-icon-header',
|
||||
action: 'block.format',
|
||||
action: 'formatBlock',
|
||||
template: '# $1'
|
||||
},
|
||||
header2: {
|
||||
label: 'markdowneditor.header2',
|
||||
cssClass: 'oc-button oc-icon-header',
|
||||
action: 'block.format',
|
||||
action: 'formatBlock',
|
||||
template: '## $1'
|
||||
},
|
||||
header3: {
|
||||
label: 'markdowneditor.header3',
|
||||
cssClass: 'oc-button oc-icon-header',
|
||||
action: 'block.format',
|
||||
action: 'formatBlock',
|
||||
template: '### $1'
|
||||
},
|
||||
header4: {
|
||||
label: 'markdowneditor.header4',
|
||||
cssClass: 'oc-button oc-icon-header',
|
||||
action: 'block.format',
|
||||
action: 'formatBlock',
|
||||
template: '#### $1'
|
||||
},
|
||||
header5: {
|
||||
label: 'markdowneditor.header5',
|
||||
cssClass: 'oc-button oc-icon-header',
|
||||
action: 'block.format',
|
||||
action: 'formatBlock',
|
||||
template: '##### $1'
|
||||
},
|
||||
header6: {
|
||||
label: 'markdowneditor.header6',
|
||||
cssClass: 'oc-button oc-icon-header',
|
||||
action: 'block.format',
|
||||
action: 'formatBlock',
|
||||
template: '###### $1'
|
||||
}
|
||||
}
|
||||
|
|
@ -357,39 +678,57 @@
|
|||
bold: {
|
||||
label: 'markdowneditor.bold',
|
||||
icon: 'bold',
|
||||
action: 'inline.format',
|
||||
action: 'formatInline',
|
||||
template: '**$1**'
|
||||
},
|
||||
italic: {
|
||||
label: 'markdowneditor.italic',
|
||||
icon: 'italic',
|
||||
action: 'inline.format',
|
||||
action: 'formatInline',
|
||||
template: '*$1*'
|
||||
},
|
||||
unorderedlist: {
|
||||
label: 'markdowneditor.unorderedlist',
|
||||
icon: 'unorderedlist',
|
||||
action: 'list.toggle',
|
||||
action: 'formatBlockMulti',
|
||||
template: '* $1'
|
||||
},
|
||||
orderedlist: {
|
||||
label: 'markdowneditor.orderedlist',
|
||||
icon: 'orderedlist',
|
||||
action: 'list.toggle',
|
||||
action: 'formatBlockMulti',
|
||||
template: '1. $1'
|
||||
},
|
||||
link: {
|
||||
label: 'markdowneditor.link',
|
||||
icon: 'link',
|
||||
action: 'inline.format',
|
||||
action: 'formatInline',
|
||||
template: '[$1](http://)'
|
||||
},
|
||||
image: {
|
||||
label: 'markdowneditor.image',
|
||||
icon: 'image',
|
||||
action: 'formatInline',
|
||||
template: ''
|
||||
},
|
||||
horizontalrule: {
|
||||
label: 'markdowneditor.horizontalrule',
|
||||
icon: 'horizontalrule',
|
||||
action: 'insertLine',
|
||||
template: '\n\n---\n'
|
||||
},
|
||||
medialink: {
|
||||
label: 'mediamanager.insert_link',
|
||||
cssClass: 'oc-autumn-button oc-icon-link',
|
||||
action: 'formatMediaManager',
|
||||
template: '[$1]($2)'
|
||||
},
|
||||
mediaimage: {
|
||||
label: 'mediamanager.insert_image',
|
||||
cssClass: 'oc-autumn-button oc-icon-image',
|
||||
action: 'formatMediaManager',
|
||||
template: ''
|
||||
},
|
||||
fullscreen: {
|
||||
label: 'markdowneditor.fullscreen',
|
||||
icon: 'fullscreen',
|
||||
|
|
|
|||
|
|
@ -24,19 +24,24 @@
|
|||
&.editor-focus { border: 1px solid @color-form-field-border-focus; }
|
||||
|
||||
&.size-tiny {
|
||||
.editor-write, .editor-preview { height: @size-tiny; }
|
||||
.editor-write { min-height: @size-tiny; }
|
||||
.editor-preview { height: @size-tiny; }
|
||||
}
|
||||
&.size-small {
|
||||
.editor-write, .editor-preview { height: @size-small; }
|
||||
.editor-write { min-height: @size-small; }
|
||||
.editor-preview { height: @size-small; }
|
||||
}
|
||||
&.size-large {
|
||||
.editor-write, .editor-preview { height: @size-large; }
|
||||
.editor-write { min-height: @size-large; }
|
||||
.editor-preview { height: @size-large; }
|
||||
}
|
||||
&.size-huge {
|
||||
.editor-write, .editor-preview { height: @size-huge; }
|
||||
.editor-write { min-height: @size-huge; }
|
||||
.editor-preview { height: @size-huge; }
|
||||
}
|
||||
&.size-giant {
|
||||
.editor-write, .editor-preview { height: @size-giant; }
|
||||
.editor-write { min-height: @size-giant; }
|
||||
.editor-preview { height: @size-giant; }
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -45,7 +50,6 @@
|
|||
|
||||
.editor-write {
|
||||
position: relative;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -54,6 +58,21 @@
|
|||
|
||||
.editor-preview {
|
||||
padding: 15px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.editor-preview-loader {
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
margin-top: 40px; // Toolbar height
|
||||
background-image:url('../../../../../system/assets/ui/images/loader-transparent.svg');
|
||||
background-size: 20px 20px;
|
||||
background-position: 50% 50%;
|
||||
.animation(spin 1s linear infinite);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -63,7 +82,6 @@
|
|||
&.mode-tab {
|
||||
|
||||
.editor-preview {
|
||||
overflow: auto;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
@ -78,5 +96,130 @@
|
|||
// Mode: Split
|
||||
//
|
||||
|
||||
&.mode-split {}
|
||||
&.mode-split {
|
||||
.editor-preview {
|
||||
float: right;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.editor-write {
|
||||
float: left;
|
||||
width: 50%;
|
||||
|
||||
.editor-code {
|
||||
border-right: 2px solid #808C8D;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stretch
|
||||
&.stretch {
|
||||
&, .editor-toolbar {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.editor-toolbar {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.editor-write,
|
||||
.editor-preview {
|
||||
float: none;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.editor-write {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Full screen
|
||||
//
|
||||
|
||||
&.is-fullscreen {
|
||||
z-index: 1020;
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
&, .editor-toolbar {
|
||||
border-radius: 0 !important;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Default theme
|
||||
|
||||
.field-markdowneditor .editor-preview {
|
||||
color: #515c5d;
|
||||
font-family: "Helvetica", sans-serif;
|
||||
line-height: 180%;
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 20px;
|
||||
font-weight: bold;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
*:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
p, ol, ul {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, p, ol, ul {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
pre.prettyprint {
|
||||
border-width: 0;
|
||||
padding: 13px 16px;
|
||||
.border-radius(3px);
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,18 +4,20 @@
|
|||
<?php else: ?>
|
||||
<div
|
||||
id="<?= $this->getId() ?>"
|
||||
class="field-markdowneditor size-<?= $size ?> <?= $stretch?'layout-relative':'' ?>"
|
||||
class="field-markdowneditor size-<?= $size ?> <?= $stretch?'layout-relative stretch':'' ?>"
|
||||
data-control="markdowneditor"
|
||||
data-refresh-handler="<?= $this->getEventHandler('onRefresh') ?>"
|
||||
data-control="markdowneditor">
|
||||
data-view-mode="<?= $mode ?>"
|
||||
data-vendor-path="<?= URL::asset('/modules/backend/formwidgets/codeeditor/assets/vendor/ace') ?>">
|
||||
|
||||
<div class="layout control-toolbar editor-toolbar"></div>
|
||||
|
||||
<div class="editor-write">
|
||||
|
||||
<div class="editor-write layout-cell">
|
||||
<textarea name="<?= $name ?>" id="<?= $this->getId('textarea') ?>"><?= e($value) ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="editor-preview">
|
||||
</div>
|
||||
<div class="editor-preview layout-cell"></div>
|
||||
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@
|
|||
background-color: @color-toolbar-editor-btn-bg-hover;
|
||||
color: @color-toolbar-editor-btn-color-hover;
|
||||
}
|
||||
&.active,
|
||||
&:active {
|
||||
outline: none;
|
||||
background-color: @color-toolbar-editor-btn-bg-active;
|
||||
|
|
@ -173,6 +174,14 @@
|
|||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.btn.oc-autumn-button {
|
||||
color: #c03f31;
|
||||
|
||||
&:hover {
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue