Introduce MarkdownEditor base code

This commit is contained in:
Samuel Georges 2015-07-29 19:18:42 +10:00
parent 3f58cd70fc
commit d2da170864
6 changed files with 913 additions and 0 deletions

View File

@ -131,6 +131,10 @@ class ServiceProvider extends ModuleServiceProvider
'label' => 'Rich editor',
'code' => 'richeditor'
]);
$manager->registerFormWidget('Backend\FormWidgets\MarkdownEditor', [
'label' => 'Markdown editor',
'code' => 'markdown'
]);
$manager->registerFormWidget('Backend\FormWidgets\FileUpload', [
'label' => 'File uploader',
'code' => 'fileupload'

View File

@ -0,0 +1,66 @@
<?php namespace Backend\FormWidgets;
use Backend\Models\EditorPreferences;
use Backend\Classes\FormWidgetBase;
/**
* Code Editor
* Renders a code editor field.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class MarkdownEditor extends FormWidgetBase
{
//
// Configurable properties
//
//
// Object properties
//
/**
* {@inheritDoc}
*/
protected $defaultAlias = 'markdown';
/**
* {@inheritDoc}
*/
public function init()
{
$this->fillFromConfig([]);
}
/**
* {@inheritDoc}
*/
public function render()
{
$this->prepareVars();
return $this->makePartial('markdowneditor');
}
/**
* Prepares the widget data
*/
public function prepareVars()
{
$this->vars['stretch'] = $this->formField->stretch;
$this->vars['size'] = $this->formField->size;
$this->vars['name'] = $this->formField->getName();
$this->vars['value'] = $this->getLoadValue();
}
/**
* {@inheritDoc}
*/
public function loadAssets()
{
$this->addCss('css/markdowneditor.css', 'core');
$this->addJs('js/markdowneditor.js', 'core');
$this->addJs('/modules/backend/formwidgets/codeeditor/assets/js/build-min.js', 'core');
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,234 @@
+function ($) { "use strict";
var Base = $.oc.foundation.base,
BaseProto = Base.prototype
var MarkdownEditor = function (element, options) {
this.$el = $(element)
this.options = options || {}
this.$textarea = $('textarea:first', this.$el)
this.$toolbar = $('.editor-toolbar:first', this.$el)
this.$write = $('.editor-write:first', this.$el)
this.$preview = $('.editor-preview:first', this.$el)
this.$code = null
this.editor = null
this.$form = null
$.oc.foundation.controlUtils.markDisposable(element)
Base.call(this)
this.init()
}
MarkdownEditor.prototype = Object.create(BaseProto)
MarkdownEditor.prototype.constructor = MarkdownEditor
MarkdownEditor.prototype.init = function() {
this.$el.one('dispose-control', this.proxy(this.dispose))
/*
* Control must have an identifier
*/
if (!this.$el.attr('id')) {
this.$el.attr('id', 'element-' + Math.random().toString(36).substring(7))
}
/*
* Create code container
*/
this.$code = $('<div />')
.addClass('editor-code')
.attr('id', this.$el.attr('id') + '-code')
.css({
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0
})
.appendTo(this.$write)
/*
* Initialize ACE editor
*/
var editor = this.editor = ace.edit(this.$code.attr('id')),
options = this.options,
$form = this.$el.closest('form');
editor.getSession().setMode({ path: 'ace/mode/markdown' })
editor.setHighlightActiveLine(false)
editor.renderer.setShowGutter(false)
editor.renderer.setShowPrintMargin(false)
editor.getSession().setUseWrapMode(true)
editor.setFontSize(14)
editor.on('blur', this.proxy(this.onBlur))
editor.on('focus', this.proxy(this.onFocus))
}
MarkdownEditor.prototype.dispose = function() {
this.$el.off('dispose-control', this.proxy(this.dispose))
this.$el.removeData('oc.markdownEditor')
this.$el = null
// In some cases options could contain callbacks,
// so it's better to clean them up too.
this.options = null
BaseProto.dispose.call(this)
}
MarkdownEditor.prototype.onResize = function() {
this.editor.resize()
}
MarkdownEditor.prototype.onBlur = function() {
this.$el.removeClass('editor-focus')
}
MarkdownEditor.prototype.onFocus = function() {
this.$el.addClass('editor-focus')
}
MarkdownEditor.DEFAULTS = {
buttons: ['formatting', 'bold', 'italic', 'unorderedlist', 'orderedlist', 'link', 'horizontalrule'],
viewMode: 'tab'
}
// PLUGIN DEFINITION
// ============================
var old = $.fn.markdownEditor
$.fn.markdownEditor = function (option) {
var args = arguments;
return this.each(function () {
var $this = $(this)
var data = $this.data('oc.markdownEditor')
var options = $.extend({}, MarkdownEditor.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('oc.markdownEditor', (data = new MarkdownEditor(this, options)))
if (typeof option == 'string') data[option].apply(data, args)
})
}
$.fn.markdownEditor.Constructor = MarkdownEditor
$.fn.markdownEditor.noConflict = function () {
$.fn.markdownEditor = old
return this
}
$(document).render(function (){
$('[data-control="markdowneditor"]').markdownEditor()
})
// BUTTON DEFINITIONS
// =================
if ($.oc === undefined)
$.oc = {}
$.oc.markdownEditorButtons = {
formatting: {
label: 'markdowneditor.formatting',
icon: 'formatting',
dropdown: {
quote: {
label: 'markdowneditor.quote',
cssClass: 'oc-button oc-icon-quote-right',
action: 'list.toggle',
template: '> $1'
},
code: {
label: 'markdowneditor.code',
cssClass: 'oc-button oc-icon-code',
action: 'block.format',
template: '```$1```'
},
header1: {
label: 'markdowneditor.header1',
cssClass: 'oc-button oc-icon-header',
action: 'block.format',
template: '# $1'
},
header2: {
label: 'markdowneditor.header2',
cssClass: 'oc-button oc-icon-header',
action: 'block.format',
template: '## $1'
},
header3: {
label: 'markdowneditor.header3',
cssClass: 'oc-button oc-icon-header',
action: 'block.format',
template: '### $1'
},
header4: {
label: 'markdowneditor.header4',
cssClass: 'oc-button oc-icon-header',
action: 'block.format',
template: '#### $1'
},
header5: {
label: 'markdowneditor.header5',
cssClass: 'oc-button oc-icon-header',
action: 'block.format',
template: '##### $1'
},
header6: {
label: 'markdowneditor.header6',
cssClass: 'oc-button oc-icon-header',
action: 'block.format',
template: '###### $1'
}
}
},
bold: {
label: 'markdowneditor.bold',
icon: 'bold',
action: 'inline.format',
template: '**$1**'
},
italic: {
label: 'markdowneditor.italic',
icon: 'italic',
action: 'inline.format',
template: '*$1*'
},
unorderedlist: {
label: 'markdowneditor.unorderedlist',
icon: 'unorderedlist',
action: 'list.toggle',
template: '* $1'
},
orderedlist: {
label: 'markdowneditor.orderedlist',
icon: 'orderedlist',
action: 'list.toggle',
template: '1. $1'
},
link: {
label: 'markdowneditor.link',
icon: 'link',
action: 'inline.format',
template: '[$1](http://)'
},
horizontalrule: {
label: 'markdowneditor.horizontalrule',
icon: 'horizontalrule',
action: 'line.insert',
template: '---'
},
fullscreen: {
label: 'markdowneditor.fullscreen',
icon: 'fullscreen',
action: 'fullscreen.toggle'
},
preview: {
label: 'markdowneditor.preview',
cssClass: 'oc-button oc-icon-eye',
action: 'preview.toggle'
}
}
}(window.jQuery);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,101 @@
<?php if ($this->previewMode): ?>
<div class="form-control"><?= e($value) ?></div>
<?php else: ?>
<div
id="<?= $this->getId() ?>"
class="field-markdowneditor size-<?= $size ?> <?= $stretch?'layout-relative':'' ?>"
data-control="markdowneditor"
>
<div class="layout control-toolbar edita-toolbar">
<div class="layout-cell toolbar-item">
<div data-control="toolbar">
<div class="dropdown">
<a href="#" data-toggle="dropdown" class="btn tb-icon tb-formatting"></a>
<ul class="dropdown-menu" data-dropdown-title="Formatting">
<li><a href="#" rel="quote" tabindex="-1" class="oc-icon-quote-right">Quote</a></li>
<li><a href="#" rel="code" tabindex="-1" class="oc-icon-code">Code</a></li>
<li><a href="#" rel="header1" tabindex="-1" class="oc-icon-header">Header 1</a></li>
<li><a href="#" rel="header2" tabindex="-1" class="oc-icon-header">Header 2</a></li>
<li><a href="#" rel="header3" tabindex="-1" class="oc-icon-header">Header 3</a></li>
<li><a href="#" rel="header4" tabindex="-1" class="oc-icon-header">Header 4</a></li>
<li><a href="#" rel="header5" tabindex="-1" class="oc-icon-header">Header 5</a></li>
<li><a href="#" rel="header6" tabindex="-1" class="oc-icon-header">Header 6</a></li>
</ul>
</div>
<button type="button" class="btn tb-icon tb-bold"></button>
<button type="button" class="btn tb-icon tb-italic"></button>
<button type="button" class="btn tb-icon tb-unorderedlist"></button>
<button type="button" class="btn tb-icon tb-orderedlist"></button>
<button type="button" class="btn tb-icon tb-link"></button>
<button type="button" class="btn tb-icon tb-horizontalrule"></button>
</div>
</div>
<div class="layout-cell toolbar-item width-fix">
<button type="button" class="btn oc-icon-eye"></button>
<button type="button" class="btn oc-icon-expand"></button>
</div>
</div>
<!--
<div class="layout-cell toolbar-item width-fix">
<input placeholder="search..." type="text" name="" value="" class="form-control icon search growable" autocomplete="off"/>
</div>
<div class="layout control-toolbar edita-toolbar">
<div class="layout-cell toolbar-item">
<div data-control="toolbar">
<div class="btn-group">
<button type="button" class="btn btn-primary oc-icon-plus">Create post</button>
<button type="button" class="btn btn-primary oc-icon-copy">Copy</button>
<button type="button" class="btn btn-primary oc-icon-trash">Delete</button>
<button type="button" class="btn btn-primary oc-icon-magic">Publish</button>
<button type="button" class="btn btn-primary oc-icon-off">Unpublish</button>
<button type="button" class="btn btn-primary oc-icon-time">Timer</button>
<button type="button" class="btn btn-primary oc-icon-mail-reply-all">Send by email</button>
<button type="button" class="btn btn-primary oc-icon-hdd">Archive</button>
</div>
</div>
</div>
</div>
<ul class="editor-toolbar">
<li class="dropdown">
<a href="#" data-toggle="dropdown" class="md-icon md-formatting" rel="formatting" tabindex="-1"></a>
<ul class="dropdown-menu" data-dropdown-title="Formatting">
<li><a href="#" rel="quote" tabindex="-1" class="oc-icon-quote-right">Quote</a></li>
<li><a href="#" rel="code" tabindex="-1" class="oc-icon-code">Code</a></li>
<li><a href="#" rel="header1" tabindex="-1" class="oc-icon-header">Header 1</a></li>
<li><a href="#" rel="header2" tabindex="-1" class="oc-icon-header">Header 2</a></li>
<li><a href="#" rel="header3" tabindex="-1" class="oc-icon-header">Header 3</a></li>
<li><a href="#" rel="header4" tabindex="-1" class="oc-icon-header">Header 4</a></li>
<li><a href="#" rel="header5" tabindex="-1" class="oc-icon-header">Header 5</a></li>
<li><a href="#" rel="header6" tabindex="-1" class="oc-icon-header">Header 6</a></li>
</ul>
</li>
<li><a href="#" class="md-icon md-bold" rel="bold" tabindex="-1"></a></li>
<li><a href="#" class="md-icon md-italic" rel="italic" tabindex="-1"></a></li>
<li><a href="#" class="md-icon md-unorderedlist" rel="unorderedlist" tabindex="-1"></a></li>
<li><a href="#" class="md-icon md-orderedlist" rel="orderedlist" tabindex="-1"></a></li>
<li><a href="#" class="md-icon md-link" rel="link" tabindex="-1"></a></li>
<li><a href="#" class="md-icon md-horizontalrule" rel="horizontalrule" tabindex="-1"></a></li>
<li class="editor-btn-right"><a href="#" class="md-icon md-fullscreen editor-btn-fullscreen" rel="fullscreen" tabindex="-1"></a></li>
<li class="editor-btn-right"><a href="#" class="oc-button oc-icon-eye editor-btn-preview" rel="preview" tabindex="-1"></a></li>
</ul>
-->
<div class="editor-write">
<textarea name="<?= $name ?>" id="<?= $this->getId('textarea') ?>"><?= e($value) ?></textarea>
</div>
<div class="editor-preview">
</div>
</div>
<?php endif ?>