Browse Source

Add setCustomRte on top API for setting a custom RTE inside the editor

pull/72/head
Artur Arseniev 9 years ago
parent
commit
20adf69cdf
  1. 2
      bower.json
  2. 16
      dist/grapes.min.js
  3. 2
      index.html
  4. 2
      package.json
  5. 115
      src/demo.js
  6. 61
      src/dom_components/view/ComponentTextView.js
  7. 33
      src/editor/main.js
  8. 66
      src/rich_text_editor/main.js

2
bower.json

@ -1,7 +1,7 @@
{
"name": "grapesjs",
"description": "Open source Web Template Editor",
"version": "0.3.72",
"version": "0.4.0",
"author": "Artur Arseniev",
"homepage": "http://grapesjs.com",
"main": [

16
dist/grapes.min.js

File diff suppressed because one or more lines are too long

2
index.html

@ -6,6 +6,8 @@
<link rel="stylesheet" href="styles/css/main.css">
<link rel="stylesheet" href="node_modules/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="node_modules/codemirror/theme/hopscotch.css">
<script src="private/ckeditor/ckeditor.js"></script>
<!-- <script src="private/tinymce/tinymce.min.js"></script> -->
</head>
<style>
body, html{ height: 100%; margin: 0;}

2
package.json

@ -1,7 +1,7 @@
{
"name": "grapesjs",
"description": "Open source Web Template Editor",
"version": "0.3.72",
"version": "0.4.0",
"author": "Artur Arseniev",
"license": "BSD-3-Clause",
"homepage": "http://grapesjs.com",

115
src/demo.js

@ -330,88 +330,51 @@ require(['config/require-config'], function() {
window.editor = editor;
// Test custom blocks
/*
var bm = editor.BlockManager;
bm.get('b1').set({
content: {
classes: ['blk-row'],
droppable: ['.blk-cell'],
components: [{
classes: ['blk-cell', 'blk1'],
}]
}
});
bm.get('b2').set({
content: '<div class="blk-row" data-gjs-droppable=".blk-cell" data-gjs-draggable="*:not(#wrapper)"><div data-gjs-draggable=".blk-row" class="blk-cell blk2"></div><div data-gjs-draggable=".blk-row" class="blk-cell blk2"></div></div>',
});
bm.get('b3').set({
content: {
classes: ['blk-row'],
droppable: ['.blk-cell'],
components: [{
classes: ['blk-cell', 'blk3'],
},{
classes: ['blk-cell', 'blk3'],
},{
classes: ['blk-cell', 'blk3'],
}]
}
});
bm.get('b4').set({
content: {
classes: ['blk-row'],
droppable: ['.blk-cell'],
components: [{
classes: ['blk-cell', 'blk37l'],
},{
classes: ['blk-cell', 'blk37r'],
}]
}
});
bm.get('map').set({
content: {
type: 'map',
draggable: ['*:not(#wrapper)'],
style: {height: '350px'}
},
});
*/
/*
// Test toolbar commands
var cmd = editor.Commands;
cmd.add('tlb-delete', {
run: function(ed){
var sel = ed.getSelected();
if(!sel)
return;
sel.destroy();
ed.Canvas.getToolbarEl().style.display = 'none';
editor.setCustomRte({
enable: function(el, rte) {
//rte.status == 'destroyed'
el.contentEditable = true;
// Jumps on enter, bug: https://dev.ckeditor.com/ticket/9136
//toolbar.$el.empty(); // try to hide all inside
rteToolbar = editor.RichTextEditor.getToolbarEl();
rteToolbar.innerHTML = '';
rte = CKEDITOR.inline(el, {
startupFocus: true,
enterMode: CKEDITOR.ENTER_BR,
removePlugins: 'liststyle,tabletools,scayt,menubutton,contextmenu,resize',
extraPlugins: 'sharedspace',
sharedSpaces: {
top: rteToolbar,
}
});
// Make click event propogate
rte.on('contentDom', function() {
var editable = rte.editable();
editable.attachListener( editable, 'click', function() {
el.click();
});
});
//rte.focus();
return rte;
},
});
cmd.add('tlb-clone', {
run: function(ed){
var sel = ed.getSelected();
var collection = sel.collection;
var index = collection.indexOf(sel);
collection.add(sel.clone(), {at: index + 1});
disable: function(el, rte) {
el.contentEditable = false;
rte.focusManager.blur(true);
rte.destroy(true);
rte = null;
},
});
cmd.add('tlb-move', {
run: function(ed){
var sel = ed.getSelected();
ed.editor.stopDefault();
var cmdMove = cmd.get('move-comp');
cmdMove.onEndMoveFromModel = function() {
ed.editor.runDefault();
};
cmdMove.initSorterFromModel(sel);
ed.Canvas.getToolbarEl().style.display = 'none';
focus: function (el, rte) {
//el.contentEditable = true;
rte.focus();
},
});
*/
*/
});
});

61
src/dom_components/view/ComponentTextView.js

@ -8,30 +8,13 @@ define(['backbone', './ComponentView'],
'change': 'parseRender',
},
initialize: function(o){
initialize: function(o) {
ComponentView.prototype.initialize.apply(this, arguments);
_.bindAll(this,'disableEditing');
this.listenTo(this.model, 'focus active', this.enableEditing);
this.rte = this.config.rte || '';
},
/**
* Parse content and re-render it
* @private
*/
parseRender: function(){
var comps = this.model.get('components');
var opts = {silent: true};
// Avoid re-render on reset with silent option
comps.reset(null, opts);
comps.add(this.$el.html(), opts);
this.model.set('content', '');
this.render();
// As the reset was in silent mode I need to notify
// the navigator about the change
comps.trigger('resetNavigator');
this.activeRte = null;
this.em = this.config.em;
},
/**
@ -39,9 +22,11 @@ define(['backbone', './ComponentView'],
* @param {Event} e
* @private
* */
enableEditing: function(e){
if(this.rte)
this.rte.attach(this);
enableEditing: function(e) {
if(this.rte) {
this.activeRte = this.rte.attach(this, this.activeRte);
this.rte.focus(this, this.activeRte);
}
this.toggleEvents(1);
},
@ -50,11 +35,14 @@ define(['backbone', './ComponentView'],
* @param {Event}
* @private
* */
disableEditing: function(e){
if(this.rte)
this.rte.detach(this);
disableEditing: function(e) {
if(this.rte) {
this.rte.detach(this, this.activeRte);
}
if(!this.rte.customRte) {
this.parseRender();
}
this.toggleEvents();
this.parseRender();
},
/**
@ -66,6 +54,25 @@ define(['backbone', './ComponentView'],
e.stopPropagation();
},
/**
* Parse content and re-render it
* @private
*/
parseRender: function(){
var comps = this.model.get('components');
var opts = {silent: true};
// Avoid re-render on reset with silent option
comps.reset(null, opts);
comps.add(this.$el.html(), opts);
this.model.set('content', '');
this.render();
// As the reset was in silent mode I need to notify
// the navigator about the change
comps.trigger('resetNavigator');
},
/**
* Enable/Disable events
* @param {Boolean} enable

33
src/editor/main.js

@ -373,6 +373,39 @@ define(function (require){
em.refreshCanvas();
},
/**
* Replace the built-in Rich Text Editor with a custom one.
* @param {Object} obj Custom RTE Interface
* @example
* editor.setCustomRte({
* // Function for enabling custom RTE
* // el is the HTMLElement of the double clicked Text Component
* // rte is the same instance you have returned the first time you call
* // enable(). This is useful if need to check if the RTE is already enabled so
* // ion this case you'll need to return the RTE and the end of the function
* enable: function(el, rte) {
* rte = new MyCustomRte(el, {}); // this depends on the Custom RTE API
* ...
* return rte; // return the RTE instance
* },
*
* // Disable the editor, called for example when you unfocus the Text Component
* disable: function(el, rte) {
* rte.blur(); // this depends on the Custom RTE API
* }
*
* // Called when the Text Component is focused again. If you returned the RTE instance
* // from the enable function, the enable won't be called again instead will call focus,
* // in this case to avoid double binding of the editor
* focus: function (el, rte) {
* rte.focus(); // this depends on the Custom RTE API
* }
* });
*/
setCustomRte: function (obj) {
this.RichTextEditor.customRte = obj;
},
/**
* Attach event
* @param {string} event Event name

66
src/rich_text_editor/main.js

@ -30,9 +30,12 @@ define(function(require) {
CommandButtons = require('./model/CommandButtons'),
CommandButtonsView = require('./view/CommandButtonsView');
var tlbPfx, toolbar, commands;
var mainSelf;
return {
customRte: null,
/**
* Name of the module
* @type {String}
@ -46,6 +49,7 @@ define(function(require) {
* @private
*/
init: function(config) {
mainSelf = this;
c = config || {};
for (var name in defaults) {
if (!(name in c))
@ -114,10 +118,11 @@ define(function(require) {
* Triggered when the offset of the editro is changed
* @private
*/
udpatePosition: function(){
udpatePosition: function() {
var u = 'px';
var canvas = c.em.get('Canvas');
var pos = canvas.getTargetToElementDim(toolbar.el, this.lastEl, 1);
//console.log(toolbar.el, this.lastEl, pos);
var toolbarStyle = toolbar.el.style;
toolbarStyle.top = pos.top + u;
toolbarStyle.left = pos.left + u;
@ -126,20 +131,31 @@ define(function(require) {
/**
* Bind rich text editor to the element
* @param {View} view
* @param {Object} rte The instance of already defined RTE
* @private
* */
attach: function(view){
view.$el.wysiwyg({}).focus();
attach: function(view, rte) {
this.lastEl = view.el;
var customRte = this.customRte;
// If a custom RTE is defined
if (customRte) {
// No RTE instance was provided
if(!rte || rte.status == 'destroyed') {
rte = customRte.enable(view.el, rte);
}
} else {
view.$el.wysiwyg({}).focus();
}
this.show();
if(c.em){
this.udpatePosition();
//this.udpatePosition();
if(c.em) {
setTimeout(this.udpatePosition.bind(this), 0);
c.em.off('change:canvasOffset', this.udpatePosition, this);
c.em.on('change:canvasOffset', this.udpatePosition, this);
// Update position on scrolling
c.em.off('canvasScroll', this.udpatePosition, this);
c.em.on('canvasScroll', this.udpatePosition, this);
@ -147,32 +163,58 @@ define(function(require) {
//Avoid closing edit mode clicking on toolbar
toolbar.$el.on('mousedown', this.disableProp);
return rte;
},
/**
* Unbind rich text editor from the element
* @param {View} view
* @param {Object} rte The instance of already defined RTE
* @private
* */
detach: function(view){
view.$el.wysiwyg('destroy');
detach: function(view, rte) {
var customRte = this.customRte;
if (customRte) {
view.model.set('content', view.el.innerHTML);
customRte.disable(view.el, rte);
} else {
view.$el.wysiwyg('destroy');
}
this.hide();
toolbar.$el.off('mousedown', this.disableProp);
},
/**
* Unbind rich text editor from the element
* @param {View} view
* @param {Object} rte The instance of already defined RTE
* @private
* */
focus: function(view, rte) {
var customRte = this.customRte;
if (customRte) {
customRte.focus(view.el, rte);
} else {
this.attach(view);
}
},
/**
* Show the toolbar
* @private
* */
show: function(){
toolbar.el.style.display = "block";
show: function() {
var toolbarStyle = toolbar.el.style;
toolbarStyle.top = 0;
toolbarStyle.left = 0;
toolbarStyle.display = "block";
},
/**
* Hide the toolbar
* @private
* */
hide: function(){
hide: function() {
toolbar.el.style.display = "none";
},
@ -180,7 +222,7 @@ define(function(require) {
* Isolate the disable propagation method
* @private
* */
disableProp: function(e){
disableProp: function(e) {
e.stopPropagation();
},

Loading…
Cancel
Save