Skip to content

Instantly share code, notes, and snippets.

@nao-pon
Last active May 29, 2017 00:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nao-pon/a1de62eb499fe70e6705586fab7d5397 to your computer and use it in GitHub Desktop.
Save nao-pon/a1de62eb499fe70e6705586fab7d5397 to your computer and use it in GitHub Desktop.
Multiple editor setting for elFinder >= 2.1.25
commandsOptions : {
edit : {
binMimeRegex : /^image\/(?:jpeg|png)/,
editors : [
{
// Adobe Creative SDK Creative Tools Image Editor UI
// MIME types to accept
info : {
name : 'Creative Cloud'
},
mimes : ['image/jpeg', 'image/png'],
// HTML of this editor
html : '<div style="width:100%;height:300px;text-align:center;"><img/></div>',
// Initialization of editing node
init : function(id, file, content, fm) {
var node = $(this).children('img:first'),
spnr = $('<div/>')
.css({
position: 'absolute',
top: '50%',
textAlign: 'center',
width: '100%',
fontSize: '16pt'
})
.html(fm.i18n('ntfloadimg'))
.hide()
.appendTo(this);
node.data('mime', file.mime)
.attr('id', id+'-img')
.attr('src', content)
.css({'height':'', 'max-width':'100%', 'max-height':'100%', 'cursor':'pointer'})
.data('loading', function(done) {
var btns = node.closest('.elfinder-dialog').find('button,.elfinder-titlebar-button');
btns.prop('disabled', !done)[done? 'removeClass' : 'addClass']('ui-state-disabled');
node.css('opacity', done? '' : '0.3');
spnr[done? 'hide' : 'show']();
return node;
});
},
// Get data uri scheme
getContent : function() {
return $(this).children('img:first').attr('src');
},
// Launch Aviary Feather editor when dialog open
load : function(base) {
var self = this,
fm = this.fm,
node = $(base).children('img:first'),
elfNode = fm.getUI(),
dfrd = $.Deferred(),
init = function(onload) {
var getLang = function() {
var langMap = {
'jp' : 'ja',
'zh_TW' : 'zh_HANT',
'zh_CN' : 'zh_HANS'
};
return langMap[fm.lang]? langMap[fm.lang] : fm.lang;
};
node.on('click', launch).data('loading')();
featherEditor = new Aviary.Feather({
apiKey: 'YOUR API KEY',
onSave: function(imageID, newURL) {
featherEditor.showWaitIndicator();
node.on('load error', function() {
node.data('loading')(true);
})
.attr('crossorigin', 'anonymous')
.attr('src', newURL)
.data('loading')();
featherEditor.close();
},
onLoad: onload || function(){},
onClose: function() { $(container).hide(); },
appendTo: container.get(0),
maxSize: 2048,
language: getLang()
});
// return editor instance
dfrd.resolve(featherEditor);
},
launch = function() {
$(container).show();
featherEditor.launch({
image: node.attr('id'),
url: node.attr('src')
});
node.data('loading')(true);
},
featherEditor, container;
// Cancel editing with IE8
if (fm.UA.ltIE8) {
return dfrd.reject('IE8 does not supported.');
}
// load script then init
if (typeof Aviary === 'undefined') {
if (!(container = $('#elfinder-aviary-container')).length) {
container = $('<div id="elfinder-aviary-container" class="ui-front"/>').css({
position: 'fixed',
top: 0,
right: 0,
width: '100%',
height: $(window).height(),
overflow: 'auto'
}).hide().appendTo(elfNode.hasClass('elfinder-fullscreen')? elfNode : 'body');
// fit to window size
$(window).on('resize', function() {
container.css('height', $(window).height());
});
// bind switch fullscreen event
elfNode.on('resize', function(e, data) {
data && data.fullscreen && container.appendTo(data.fullscreen === 'on'? elfNode : 'body');
});
}
fm.loadScript(['https://dme0ih8comzn4.cloudfront.net/imaging/v3/editor.js'], function() {
init(launch);
});
} else {
container = $('#elfinder-aviary-container');
// always moves to last
container.appendTo(container.parent());
init();
launch();
}
return dfrd;
},
// Convert content url to data uri scheme to save content
save : function(base) {
var imgBase64 = function(node) {
var style = node.attr('style'),
img, canvas, ctx;
// reset css for getting image size
node.attr('style', '');
// img node
img = node.get(0);
// New Canvas
canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
// restore css
node.attr('style', style);
// Draw Image
canvas.getContext('2d').drawImage(img, 0, 0);
// To Base64
return canvas.toDataURL(node.data('mime'));
},
node = $(base).children('img:first');
if (node.attr('src').substr(0, 5) !== 'data:') {
node.attr('src', imgBase64(node));
}
}
},
{
// ACE Editor
// `mimes` is not set for support everything kind of text file
info : {
name : 'ACE Editor'
},
load : function(textarea) {
var self = this,
dfrd = $.Deferred(),
cdn = '//cdnjs.cloudflare.com/ajax/libs/ace/1.2.5',
init = function() {
if (typeof ace === 'undefined') {
this.fm.loadScript([
cdn+'/ace.js',
cdn+'/ext-modelist.js',
cdn+'/ext-settings_menu.js',
cdn+'/ext-language_tools.js'
], start);
} else {
start();
}
},
start = function() {
var editor, editorBase, mode,
ta = $(textarea),
taBase = ta.parent(),
dialog = taBase.parent(),
id = textarea.id + '_ace',
ext = self.file.name.replace(/^.+\.([^.]+)|(.+)$/, '$1$2').toLowerCase(),
// MIME/mode map
mimeMode = {
'text/x-php' : 'php',
'application/x-php' : 'php',
'text/html' : 'html',
'application/xhtml+xml' : 'html',
'text/javascript' : 'javascript',
'application/javascript' : 'javascript',
'text/css' : 'css',
'text/x-c' : 'c_cpp',
'text/x-csrc' : 'c_cpp',
'text/x-chdr' : 'c_cpp',
'text/x-c++' : 'c_cpp',
'text/x-c++src' : 'c_cpp',
'text/x-c++hdr' : 'c_cpp',
'text/x-shellscript' : 'sh',
'application/x-csh' : 'sh',
'text/x-python' : 'python',
'text/x-java' : 'java',
'text/x-java-source' : 'java',
'text/x-ruby' : 'ruby',
'text/x-perl' : 'perl',
'application/x-perl' : 'perl',
'text/x-sql' : 'sql',
'text/xml' : 'xml',
'application/docbook+xml' : 'xml',
'application/xml' : 'xml'
};
// set basePath of ace
ace.config.set('basePath', cdn);
// set base height
taBase.height(taBase.height());
// detect mode
mode = ace.require('ace/ext/modelist').getModeForPath('/' + self.file.name).name;
if (mode === 'text') {
if (mimeMode[self.file.mime]) {
mode = mimeMode[self.file.mime];
}
}
// show MIME:mode in title bar
taBase.prev().children('.elfinder-dialog-title').append(' (' + self.file.mime + ' : ' + mode.split(/[\/\\]/).pop() + ')');
// TextArea button and Setting button
$('<div class="ui-dialog-buttonset"/>').css('float', 'left')
.append(
$('<button>TextArea</button>')
.button()
.on('click', function(){
if (ta.data('ace')) {
ta.removeData('ace');
editorBase.hide();
ta.val(editor.session.getValue()).show().focus();
$(this).text('AceEditor');
} else {
ta.data('ace', true);
editorBase.show();
editor.setValue(ta.hide().val(), -1);
editor.focus();
$(this).text('TextArea');
}
})
)
.append(
$('<button>Ace editor setting</button>')
.button({
icons: {
primary: 'ui-icon-gear',
secondary: 'ui-icon-triangle-1-e'
},
text: false
})
.on('click', function(){
editor.showSettingsMenu();
})
)
.prependTo(taBase.next());
// Base node of Ace editor
editorBase = $('<div id="'+id+'" style="width:100%; height:100%;"/>').text(ta.val()).insertBefore(ta.hide());
// Ace editor configure
ta.data('ace', true);
editor = ace.edit(id);
ace.require('ace/ext/language_tools');
ace.require('ace/ext/settings_menu').init(editor);
editor.$blockScrolling = Infinity;
editor.setOptions({
theme: 'ace/theme/monokai',
mode: 'ace/mode/' + mode,
fontSize: '14px',
wrap: true,
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: false
});
editor.commands.addCommand({
name : "saveFile",
bindKey: {
win : 'Ctrl-s',
mac : 'Command-s'
},
exec: function(editor) {
self.doSave();
}
});
editor.commands.addCommand({
name : "closeEditor",
bindKey: {
win : 'Ctrl-w|Ctrl-q',
mac : 'Command-w|Command-q'
},
exec: function(editor) {
self.doCancel();
}
});
editor.resize();
dfrd.resolve(editor);
};
// init & start
init();
return dfrd;
},
close : function(textarea, instance) {
if (instance) {
instance.destroy();
$(textarea).show();
}
},
save : function(textarea, instance) {
instance && $(textarea).data('ace') && (textarea.value = instance.session.getValue());
},
focus : function(textarea, instance) {
instance && $(textarea).data('ace') && instance.focus();
},
resize : function(textarea, instance, e, data) {
instance && instance.resize();
}
},
{
// CodeMirror
// `mimes` is not set for support everything kind of text file
info : {
name : 'CodeMirror'
},
load : function(textarea) {
var cmUrl = '//cdnjs.cloudflare.com/ajax/libs/codemirror/5.26.0/',
dfrd = $.Deferred(),
self = this,
init = function() {
var ta = $(textarea),
base = ta.parent(),
editorBase;
// set base height
base.height(base.height());
// CodeMirror configure
editor = CodeMirror.fromTextArea(textarea, {
lineNumbers: true,
lineWrapping: true
});
// return editor instance
dfrd.resolve(editor);
// Auto mode set
var info, m, mode, spec;
if (! info) {
info = CodeMirror.findModeByMIME(self.file.mime);
}
if (! info && (m = self.file.name.match(/.+\.([^.]+)$/))) {
info = CodeMirror.findModeByExtension(m[1]);
}
if (info) {
CodeMirror.modeURL = cmUrl + 'mode/%N/%N.js';
mode = info.mode;
spec = info.mime;
editor.setOption('mode', spec);
CodeMirror.autoLoadMode(editor, mode);
// show MIME:mode in title bar
base.prev().children('.elfinder-dialog-title').append(' (' + spec + ' : ' + mode + ')');
}
// editor base node
editorBase = $(editor.getWrapperElement());
ta.data('cm', true);
// fit height to base
editorBase.height('100%');
// TextArea button and Setting button
$('<div class="ui-dialog-buttonset"/>').css('float', 'left')
.append(
$('<button>TextArea</button>')
.button()
.on('click', function(){
if (ta.data('cm')) {
ta.removeData('cm');
editorBase.hide();
ta.val(editor.getValue()).show().focus();
$(this).text('CodeMirror');
} else {
ta.data('cm', true);
editorBase.show();
editor.setValue(ta.hide().val());
editor.refresh();
editor.focus();
$(this).text('TextArea');
}
})
)
.prependTo(base.next());
};
// load script then init
if (typeof CodeMirror === 'undefined') {
this.fm.loadScript([
cmUrl + 'codemirror.min.js',
cmUrl + 'addon/mode/loadmode.js',
cmUrl + 'mode/meta.js'
], init);
this.fm.loadCss(cmUrl + 'codemirror.css');
} else {
init();
}
return dfrd;
},
close : function(textarea, instance) {
instance && instance.toTextArea();
},
save : function(textarea, instance) {
instance && $(textarea).data('cm') && (textarea.value = instance.getValue());
},
focus : function(textarea, instance) {
instance && $(textarea).data('cm') && instance.focus();
},
resize : function(textarea, instance, e, data) {
instance && instance.refresh();
}
},
{
// CKEditor for html file
info : {
name : 'CKEditor'
},
mimes : ['text/html'],
exts : ['htm', 'html', 'xhtml'],
load : function(textarea) {
var self = this,
dfrd = $.Deferred(),
init = function() {
var base = $(textarea).parent(),
dlg = base.closest('.elfinder-dialog'),
h = base.height();
// set base height
base.height(h);
// CKEditor configure
CKEDITOR.replace(textarea.id, {
startupFocus : true,
fullPage: true,
allowedContent: true,
on: {
'instanceReady' : function(e) {
var editor = e.editor;
editor.resize('100%', h);
// re-build on dom move
dlg.one('beforedommove.'+fm.namespace, function() {
editor.destroy();
}).one('dommove.'+fm.namespace, function() {
self.load(textarea).done(function(editor) {
self.instance = editor;
});
});
// return editor instance
dfrd.resolve(e.editor);
}
}
});
};
if (typeof CKEDITOR === 'undefined') {
$.getScript('//cdnjs.cloudflare.com/ajax/libs/ckeditor/4.6.0/ckeditor.js', init);
} else {
init();
}
return dfrd;
},
close : function(textarea, instance) {
instance && instance.destroy();
},
save : function(textarea, instance) {
instance && (textarea.value = instance.getData());
},
focus : function(textarea, instance) {
instance && instance.focus();
},
resize : function(textarea, instance, e, data) {
var self;
if (instance) {
if (instance.status === 'ready') {
instance.resize('100%', $(textarea).parent().height());
}
}
}
},
{
// TinyMCE for html file
info : {
name : 'TinyMCE'
},
mimes : ['text/html'],
exts : ['htm', 'html', 'xhtml'],
load : function(textarea) {
var self = this,
fm = this.fm,
dfrd = $.Deferred(),
init = function(loaded) {
var base = $(textarea).parent(),
dlg = base.closest('.elfinder-dialog'),
h = base.height(),
delta = base.outerHeight(true) - h;
// set base height
base.height(h);
// fit height function
textarea._setHeight = function(h) {
var base = $(this).parent(),
h = h || base.height(),
ctrH = 0,
areaH;
base.find('.mce-container-body:first').children('.mce-toolbar,.mce-toolbar-grp,.mce-statusbar').each(function() {
ctrH += $(this).outerHeight(true);
});
areaH = h - ctrH - delta;
base.find('.mce-edit-area iframe:first').height(areaH);
return areaH;
};
// TinyMCE configure
tinymce.init({
selector: '#' + textarea.id,
plugins: [
'fullpage' // require for getting full HTML
],
init_instance_callback : function(editor) {
// fit height on init
setTimeout(function() {
textarea._setHeight(h);
}, loaded? 0 : 500);
// re-build on dom move
dlg.one('beforedommove.'+fm.namespace, function() {
tinymce.execCommand('mceRemoveEditor', false, textarea.id);
}).one('dommove.'+fm.namespace, function() {
self.load(textarea).done(function(editor) {
self.instance = editor;
});
});
// return editor instance
dfrd.resolve(editor);
}
});
};
if (typeof tinymce === 'undefined') {
$.getScript('//cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.0/tinymce.min.js', init);
} else {
init(true);
}
return dfrd;
},
close : function(textarea, instance) {
instance && tinymce.execCommand('mceRemoveEditor', false, textarea.id);
},
save : function(textarea, instance) {
instance && instance.save();
},
focus : function(textarea, instance) {
instance && instance.focus();
},
resize : function(textarea, instance, e, data) {
// fit height to base node on dialog resize
textarea._setHeight();
}
}
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment