diff --git a/index.html b/index.html index 3d4dcb6c2..43a02f247 100755 --- a/index.html +++ b/index.html @@ -707,7 +707,7 @@ } .badge-header{ height: 115px; - background-image:url("./img/bg-gr-v.png"), url("./img/work-desk.jpg"); + background-image:url("http://grapesjs.com/img/bg-gr-v.png"), url("http://grapesjs.com/img/work-desk.jpg"); background-position:left top, center center; background-attachment:scroll, fixed; overflow: hidden; diff --git a/src/rich_text_editor/config/config.js b/src/rich_text_editor/config/config.js index 239090956..3346a3f20 100644 --- a/src/rich_text_editor/config/config.js +++ b/src/rich_text_editor/config/config.js @@ -7,17 +7,26 @@ define(function () { command: 'bold', title: 'Bold', class: 'fa fa-bold', - group: 'format' },{ command: 'italic', title: 'Italic', class: 'fa fa-italic', - group: 'format' },{ command: 'underline', title: 'Underline', class: 'fa fa-underline', + },{ + command: 'strikethrough', + title: 'Strikethrough', + class: 'fa fa-strikethrough', group: 'format' - },], + }/*,{ + command: 'fontSize', + options: [ + {name: 'Huge', value: '100px'}, + {name: 'Normal', value: '14px'}, + {value: '5px'} + ] + }*/], }; }); \ No newline at end of file diff --git a/src/rich_text_editor/main.js b/src/rich_text_editor/main.js index c7d18449d..488071001 100644 --- a/src/rich_text_editor/main.js +++ b/src/rich_text_editor/main.js @@ -4,13 +4,22 @@ * * [getAll](#getall) * * [remove](#remove) * - * This module allows to customize the toolbar of the Rich Text Editor + * + * styleWithCSS + * removeFormat + * + * + * This module allows to customize the toolbar of the Rich Text Editor. It's highly recommended + * to keep this toolbar as small as possible, especially from styling commands (eg. 'fontSize') + * and leave this task to the Style Manager. + * * Before using methods you should get first the module from the editor instance, in this way: * * ```js * var rte = editor.RichTextEditor; * ``` * Complete list of commands + * https://developer.mozilla.org/it/docs/Web/API/Document/execCommand * http://www.quirksmode.org/dom/execCommand.html * @module RichTextEditor */ @@ -59,9 +68,10 @@ define(function(require) { }, /** - * Add new command to the toolbar - * @param {string} command Command name + * Add a new command to the toolbar * @param {string} command Command name + * @param {Object} opts Command options + * @return {Model} Added command * @example * var cm = rte.add('bold', { * title: 'Make bold', @@ -70,7 +80,7 @@ define(function(require) { * // With arguments * var cm = rte.add('fontSize', { * title: 'Font size', - * arguments: [ + * options: [ * {name: 'Big', value: 5}, * {name: 'Normal', value: 3}, * {name: 'Small', value: 1} @@ -83,6 +93,25 @@ define(function(require) { return commands.add(obj); }, + /** + * Get the command by its name + * @param {string} command Command name + * @return {Model} + * @example + * var cm = rte.get('fontSize'); + */ + get: function(command) { + return commands.where({command: command})[0]; + }, + + /** + * Returns the collection of commands + * @return {Collection} + */ + getAll: function(){ + return commands; + }, + /** * Triggered when the offset of the editro is changed * @private diff --git a/src/rich_text_editor/model/CommandButton.js b/src/rich_text_editor/model/CommandButton.js index ac2bed4d0..e02c07a9e 100644 --- a/src/rich_text_editor/model/CommandButton.js +++ b/src/rich_text_editor/model/CommandButton.js @@ -2,12 +2,20 @@ define(['backbone'], function (Backbone) { return Backbone.Model.extend({ + idAttribute: 'command', + defaults: { command: '', + type: '', title: '', class: '', - group: '', - arguments: [], + options: [], + }, + + initialize: function() { + var opts = this.get('options'); + if(opts.length) + this.set('type', 'select'); }, }); diff --git a/src/rich_text_editor/view/CommandButtonSelectView.js b/src/rich_text_editor/view/CommandButtonSelectView.js new file mode 100644 index 000000000..f7f0b6688 --- /dev/null +++ b/src/rich_text_editor/view/CommandButtonSelectView.js @@ -0,0 +1,34 @@ +define(['backbone'], + function (Backbone) { + return Backbone.View.extend({ + + initialize: function(o, config){ + this.config = config || {}; + this.className = this.config.stylePrefix + 'btn ' + this.model.get('class'); + }, + + getInput: function(){ + var m = this.model; + if(!this.input){ + var cmd = m.get('command'); + var input = ''; + this.input = $(input); + } + return this.input; + }, + + render: function() { + this.$el.addClass(this.className); + this.$el.html(this.getInput()); + return this; + } + }); +}); diff --git a/src/rich_text_editor/view/CommandButtonView.js b/src/rich_text_editor/view/CommandButtonView.js index 2590be200..eccd546d5 100644 --- a/src/rich_text_editor/view/CommandButtonView.js +++ b/src/rich_text_editor/view/CommandButtonView.js @@ -4,13 +4,13 @@ define(['backbone'], tagName: 'a', - initialize: function(o){ - this.config = o.config || {}; - this.className = this.config.stylePrefix + 'btn ' + this.model.get('class'); + initialize: function(o, config){ + this.config = config || {}; + this.className = this.config.stylePrefix + 'btn ' + this.model.get('class'); }, render: function() { - this.$el.attr('class', _.result( this, 'className' ) ); + this.$el.addClass(this.className); return this; } }); diff --git a/src/rich_text_editor/view/CommandButtonsView.js b/src/rich_text_editor/view/CommandButtonsView.js index b18b33569..a42f381c1 100644 --- a/src/rich_text_editor/view/CommandButtonsView.js +++ b/src/rich_text_editor/view/CommandButtonsView.js @@ -1,5 +1,5 @@ -define(['backbone','./CommandButtonView'], - function (Backbone, CommandButtonView) { +define(['backbone','./CommandButtonView', './CommandButtonSelectView'], + function (Backbone, CommandButtonView, CommandButtonSelectView) { return Backbone.View.extend({ attributes : { @@ -8,27 +8,63 @@ define(['backbone','./CommandButtonView'], initialize: function(o){ this.config = o.config || {}; - this.id = this.config.stylePrefix + this.config.toolbarId; + var pfx = this.config.stylePrefix || ''; + this.id = pfx + this.config.toolbarId; + this.listenTo(this.collection, 'add', this.addTo); this.$el.data('helper', 1); }, + /** + * Add new model to the collection + * @param {Model} model + * @private + * */ + addTo: function(model){ + this.add(model); + }, + + /** + * Render new model inside the view + * @param {Model} model + * @param {Object} fragment Fragment collection + * @private + * */ + add: function(model, fragment) { + var frag = fragment || null; + var viewObj = CommandButtonView; + + switch (model.get('type')) { + case 'select': + viewObj = CommandButtonSelectView; + break; + } + + var view = new viewObj({ + model: model, + attributes: { + 'title': model.get('title'), + 'data-edit': model.get('command'), + }, + }, this.config); + + var rendered = view.render().el; + + if(frag) + frag.appendChild(rendered); + else + this.$el.append(rendered); + }, + render: function() { - var fragment = document.createDocumentFragment(); + var frag = document.createDocumentFragment(); this.$el.empty(); - this.collection.each(function(item){ - var view = new CommandButtonView({ - model: item, - config: this.config, - attributes: { - 'title': item.get('title'), - 'data-edit': item.get('command'), - }, - }); - fragment.appendChild(view.render().el); - },this); - this.$el.append(fragment); - this.$el.attr('id', _.result( this, 'id' ) ); + this.collection.each(function(model){ + this.add(model, frag); + }, this); + + this.$el.append(frag); + this.$el.attr('id', this.id ); return this; } diff --git a/src/rich_text_editor/view/TextEditorView.js b/src/rich_text_editor/view/TextEditorView.js index 744358710..50bfa6461 100644 --- a/src/rich_text_editor/view/TextEditorView.js +++ b/src/rich_text_editor/view/TextEditorView.js @@ -23,13 +23,16 @@ define(['jquery'], options, toolbarBtnSelector, updateToolbar = function () { - if (options.activeToolbarClass) { + var actCls = options.activeToolbarClass; + if (actCls) { $(options.toolbarSelector).find(toolbarBtnSelector).each(function () { - var command = $(this).data(options.commandRole); - if (document.queryCommandState(command)) { - $(this).addClass(options.activeToolbarClass); + var el = $(this); + var command = el.data(options.commandRole); + var doc = editor.get(0).ownerDocument; + if (doc.queryCommandState(command)) { + el.addClass(actCls); } else { - $(this).removeClass(options.activeToolbarClass); + el.removeClass(actCls); } }); } @@ -38,7 +41,9 @@ define(['jquery'], var commandArr = commandWithArgs.split(' '), command = commandArr.shift(), args = commandArr.join(' ') + (valueArg || ''); - document.execCommand(command, 0, args); + //document.execCommand("insertHTML", false, ""+ document.getSelection()+""); + editor.get(0).ownerDocument.execCommand("styleWithCSS", false, true); + editor.get(0).ownerDocument.execCommand(command, 0, args); updateToolbar(); }, /* @@ -106,13 +111,24 @@ define(['jquery'], bindToolbar = function (toolbar, options) { toolbar.find(toolbarBtnSelector).unbind().click(function () { restoreSelection(); - editor.focus(); + //editor.focus(); // cause defocus on selects editor.get(0).ownerDocument.execCommand($(this).data(options.commandRole)); saveSelection(); }); toolbar.find('[data-toggle=dropdown]').click(restoreSelection); - - toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () { + var dName = '[data-' + options.commandRole + ']'; + toolbar.find('select'+dName).on('webkitspeechchange change', function(){ + var newValue = this.value; + restoreSelection(); + if (newValue) { + editor.focus(); + execCommand($(this).data(options.commandRole), newValue); + } + console.log('change isolated2 ', newValue); + saveSelection(); + }); + toolbar.find('input[type=text]'+dName,', select'+dName).on('webkitspeechchange change', function () { + console.log('on changed ', newValue); var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */ this.value = ''; restoreSelection(); @@ -122,8 +138,10 @@ define(['jquery'], } saveSelection(); }).on('focus', function () { + console.log('on focus '); var input = $(this); if (!input.data(options.selectionMarker)) { + console.log('i have no ', options.selectionMarker); markSelection(input, options.selectionColor); input.focus(); } @@ -161,7 +179,8 @@ define(['jquery'], return this; } options = $.extend({}, $.fn.wysiwyg.defaults, userOptions); - toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']'; + var dName = '[data-' + options.commandRole + ']'; + toolbarBtnSelector = 'a'+dName+',button'+dName+',input[type=button]'+dName+', select'+dName; //bindHotkeys(options.hotKeys); if (options.dragAndDropImages) { initFileDrops(); @@ -183,6 +202,7 @@ define(['jquery'], return this; }; $.fn.wysiwyg.defaults = { + /* hotKeys: { 'ctrl+b meta+b': 'bold', 'ctrl+i meta+i': 'italic', @@ -196,6 +216,7 @@ define(['jquery'], 'shift+tab': 'outdent', 'tab': 'indent' }, + */ toolbarSelector: '[data-role=editor-toolbar]', commandRole: 'edit', activeToolbarClass: 'btn-info', diff --git a/src/selector_manager/template/classTags.html b/src/selector_manager/template/classTags.html index 8ddbe35a6..32e0c7bb0 100644 --- a/src/selector_manager/template/classTags.html +++ b/src/selector_manager/template/classTags.html @@ -2,7 +2,7 @@