This post shows how to use TinyMCE 4.1 WYSIWYG text editor in a Rails 4 application for editing content in a textarea field.
TinyMCE is a powerful online WYSIWYG editor with many plugins.
If you want to insert an image by selecting it from images stored on server or upload an image to server, then you need to have a file manager with tinyMCE. TinyMCE comes with a file manager which is not free.
elFinder is an open-source file manager which can be easily integrated with tinyMCE 4.1. elFinder needs a backend (connector) on Rails for reading/storing files from/on server.
The phallstrom/el_finder gem (https://github.com/phallstrom/el_finder) will be used as a backend.
We have two options for installing tinyMCE in Rails 4 application:
- download it from http://tinymce.com
- save files in public/js inside your Rails application.
or use tinymce-rails gem (https://github.com/spohlenz/tinymce-rails) which integrates TinyMCE editor with the Rails asset pipeline.
Gemfile:
gem 'tinymce-rails', '4.1.6'
https://github.com/Studio-42/elFinder
Read the instructions to install elFinder: https://github.com/Studio-42/elFinder/wiki. Instructions to integrate elFinder with TinyMCE 4.x - https://github.com/Studio-42/elFinder/wiki/Integration-with-TinyMCE-4.x.
To add elFinder to our Rails project:
- Download archive from github
- unzip the archive and copy files to 'public/elfinder'
Download and install ImageMagick for your platform.
https://github.com/phallstrom/el_finder gem is used to provide server side functionality for elFinder.
Gemfile:
gem 'el_finder', '1.1.12'
create folder where files will be stored, say, 'public/files'.
routes for elfinder
# routes.rb
get '/elfinder_manager', to: 'elfinder#index'
match 'elfinder' => 'elfinder#elfinder', via: [:get, :post]
create controller which will process files for the file manager.
app/controllers/elfinder_controller.rb:
require 'el_finder/action'
class ElfinderController < ApplicationController
skip_before_filter :verify_authenticity_token, :only => ['elfinder']
def index
render :layout => false
end
def elfinder
rootpath = File.join(Rails.public_path, 'uploads')
rooturl = '/uploads'
h, r = ElFinder::Connector.new(
:root => rootpath,
:url => rooturl,
:perms => {
/^(Welcome|README)$/ => {:read => true, :write => false, :rm => false},
'.' => {:read => true, :write => true, :rm => true}, # '.' is the proper way to specify the home/root directory.
#/^test$/ => {:read => true, :write => true, :rm => false},
#'logo.png' => {:read => true},
#/\.png$/ => {:read => false} # This will cause 'logo.png' to be unreadable.
# Permissions err on the safe side. Once false, always false.
},
:extractors => {
'application/zip' => ['unzip', '-qq', '-o'], # Each argument will be shellescaped (also true for archivers)
'application/x-gzip' => ['tar', '-xzf'],
},
:archivers => {
'application/zip' => ['.zip', 'zip', '-qr9'], # Note first argument is archive extension
'application/x-gzip' => ['.tgz', 'tar', '-czf'],
},
:thumbs => true
).run(params)
headers.merge!(h)
if r.empty?
(render :nothing => true) and return
end
render :json => r, :layout => false
end
end
change settings in ElFinder::Connector.new appropriately.
create a view for elfinder file manager.
app/views/elfinder/index.html.erb:
<!DOCTYPE html>
<html>
<head>
<title>File Manager</title>
<link rel="stylesheet" type="text/css" media="screen" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
<script type="text/javascript" src="/elfinder/js/elfinder.min.js"></script>
<script src="/elfinder/js/proxy/elFinderSupportVer1.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" src="/elfinder/js/i18n/elfinder.de.js"></script><!-- optional -->
<link rel="stylesheet" type="text/css" media="screen" href="/elfinder/css/elfinder.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="/elfinder/css/theme.css">
</head>
<body>
<div id="elfinder"></div>
<script type="text/javascript">
var FileBrowserDialogue = {
init: function() {
// Here goes your code for setting your custom things onLoad.
},
mySubmit: function (URL) {
// pass selected file path to TinyMCE
parent.tinymce.activeEditor.windowManager.getParams().setUrl(URL);
// close popup window
parent.tinymce.activeEditor.windowManager.close();
}
}
$().ready(function() {
var elf = $('#elfinder').elfinder({
// set your elFinder options here
url: '/elfinder', // connector URL
transport : new elFinderSupportVer1(),
getFileCallback: function(file) { // editor callback
// file.url - commandsOptions.getfile.onlyURL = false (default)
// file - commandsOptions.getfile.onlyURL = true
FileBrowserDialogue.mySubmit(file); // pass selected file path to TinyMCE
}
}).elfinder('instance');
});
</script>
</body>
</html>
Here is some explanation of the code above:
include jQuery and jQuery UI
<link rel="stylesheet" type="text/css" media="screen" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
include elFinder js script:
<script type="text/javascript" src="/elfinder/js/elfinder.min.js"></script>
include proxy js script so our connector works with elFinder
<script src="/elfinder/js/proxy/elFinderSupportVer1.js" type="text/javascript" charset="utf-8"></script>
(OPTIONAL) include necessary locale for elFinder, for example,
<script type="text/javascript" src="/elfinder/js/i18n/elfinder.de.js"></script>
include elFinder css files
<link rel="stylesheet" type="text/css" media="screen" href="/elfinder/css/elfinder.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="/elfinder/css/theme.css">
integrate elFinder file manager with TinyMCE
<script type="text/javascript" charset="utf-8">
$().ready(function() {
var elf = $('#elfinder').elfinder({
url: '/elfinder',
transport : new elFinderSupportVer1(),
lang: 'en' // language (OPTIONAL)
}).elfinder('instance');
});
</script>
create a view in your Rails app where you want to have online editor.
In this example it is 'app/views/pages/edit.html.haml'.
<script type="text/javascript" src="/js/tinymce/tinymce.min.js"></script>
<script type="text/javascript" src="/js/tinymce/jquery.tinymce.min.js"></script>
:javascript
tinymce.init({
selector: "textarea",
plugins: [
"advlist autolink lists link image charmap print preview anchor",
"searchreplace visualblocks code fullscreen",
"insertdatetime media table contextmenu paste"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
file_browser_callback : elFinderBrowser
});
function elFinderBrowser (field_name, url, type, win) {
tinymce.activeEditor.windowManager.open({
file: '/elfinder_manager',// use an absolute path!
title: 'elFinder 2.0',
width: 900,
height: 450,
resizable: 'yes'
}, {
setUrl: function (url) {
win.document.getElementById(field_name).value = url;
}
});
return false;
}
%form(method="post" action="somepage")
%textarea(name="content" style="width:100%")
content here