1. #1
    Sencha User
    Join Date
    Dec 2008
    Location
    The Netherlands
    Posts
    61
    Vote Rating
    0
    daanlib is on a distinguished road

      0  

    Default TinyMCE form field

    TinyMCE form field


    Edit: this first post is no longer of relevance, please see below!

    Althought I love Ext JS, the HTLMEditor form field is not very nice, so I took a stab at adapting the existing TinyMCE form control (not made by me) for use with Ext JS 4 (and TinyMCE 3.4). Because I can imagine there are more people working on this I have posted my code so far on my website (click).

    Some of the stuff works already (there is a working TinyMCE editor instance visible in an Ext layout, using Ext windows). There are some major bugs though: I get lots of "Uncaught TypeError: Cannot call method 'call' of undefined" errors in the Chrome developers tools and for some reason the width of the editor is way to small. Also labels do not appear to work. I suspect some more testing will show more bugs, but at least I made a start.

    I know the code quality is quite bad, but I only focussed on adapting the existing implementation, not on completely rewriting it. Feel free to change stuff and post the changes back in this thread.

    I encourage anyone to add to this work to make this a solid ux

  2. #2
    Sencha User
    Join Date
    Dec 2008
    Location
    The Netherlands
    Posts
    61
    Vote Rating
    0
    daanlib is on a distinguished road

      0  

    Default


    Ok, forget that first post, I completely rewrote the ux to get it working with the fieldLabel. This is a very basic implementation that extends Ext.form.field.TextArea, but does not do any validation, nor does is fire events (I think 90% of the uses of this type of field do not need any validation, nor do they need events to be fired).

    The code:
    PHP Code:
    if(window.tinymce) {
        
    Ext.define("EC.common.tinymce.WindowManager", {
            
    extendtinymce.WindowManager,
        
            
    constructor: function(cfg) {
                
    tinymce.WindowManager.call(thiscfg.editor);
            },
            
            
    alert: function(txtcbs) {
                
    Ext.MessageBox.alert(""txt, function() {
                    if (!
    Ext.isEmpty(cb)) {
                        
    cb.call(this);
                    }
                }, 
    s);
            },
            
            
    confirm: function(txtcbs) {
                
    Ext.MessageBox.confirm(""txt, function(btn) {
                    if (!
    Ext.isEmpty(cb)) {
                        
    cb.call(thisbtn == "yes");
                    }
                }, 
    s);
            },
            
            
    open: function(sp) {
                
    || {};
                
    || {};
        
                if(!
    s.type) {
                    
    this.bookmark this.editor.selection.getBookmark('simple');
                }
        
                
    s.width parseInt(s.width || 320);
                
    s.height parseInt(s.height || 240) + (tinymce.isIE 0);
                
    s.min_width parseInt(s.min_width || 150);
                
    s.min_height parseInt(s.min_height || 100);
                
    s.max_width parseInt(s.max_width || 2000);
                
    s.max_height parseInt(s.max_height || 2000);
                
    s.movable true;
                
    s.resizable true;
                
    p.mce_width s.width;
                
    p.mce_height s.height;
                
    p.mce_inline true;
        
                
    this.features s;
                
    this.params p;
        
                var 
    win Ext.create("Ext.window.Window", {
                    
    titles.name,
                    
    widths.width,
                    
    heights.height,
                    
    minWidths.min_width,
                    
    minHeights.min_height,
                    
    resizabletrue,
                    
    maximizables.maximizable,
                    
    minimizables.minimizable,
                    
    modaltrue,
                    
    statefulfalse,
                    
    constraintrue,
                    
    layout"fit",
                    
    items: [
                        
    Ext.create("Ext.Component", {
                            
    autoEl: {
                                
    tag'iframe',
                                
    srcs.url || s.file
                            
    },
                            
    style 'border-width: 0px;'
                        
    })
                    ]
                });
        
                
    p.mce_window_id win.getId();
        
                
    win.show(null, function() {
                    if (
    s.left && s.top)
                        
    win.setPagePosition(s.lefts.top);
                    var 
    pos win.getPosition();
                    
    s.left pos[0];
                    
    s.top pos[1];
                    
    this.onOpen.dispatch(thissp);
                }, 
    this);
        
                return 
    win;
            },
            
            
    close: function(win) {
                
    // Probably not inline
                
    if (!win.tinyMCEPopup || !win.tinyMCEPopup.id) {
                    
    tinymce.WindowManager.prototype.close.call(thiswin);
                    return;
                }
        
                var 
    Ext.getCmp(win.tinyMCEPopup.id);
                if (
    w) {
                    
    this.onClose.dispatch(this);
                    
    w.close();
                }
            },
            
            
    setTitle: function(winti) {
                if (!
    win.tinyMCEPopup || !win.tinyMCEPopup.id) {
                    
    tinymce.WindowManager.prototype.setTitle.call(thiswinti);
                    return;
                }
        
                var 
    Ext.getCmp(win.tinyMCEPopup.id);
                if (
    ww.setTitle(ti);
            },
            
            
    resizeBy: function(dwdhid) {
                var 
    Ext.getCmp(id);
                if (
    w) {
                    var 
    size w.getSize();
                    
    w.setSize(size.width dwsize.height dh);
                }
            },
            
            
    focus: function(id) {
                var 
    Ext.getCmp(id);
                if (
    ww.setActive(true);
            }
        });
        
        
    Ext.define("EC.common.tinymce.Editor", {
            
    extend:'Ext.form.field.TextArea',
            
            
    alias'widget.TinyMCEEditor',
            
    alternateClassName'Ext.form.TinyMCEEditor',
            
            
    statics: {
                
    tinyMCEInitializedfalse,
                
                
    //settings for each TinyMCE instance, override before instantiating any TinyMCE editor to change there.
                
    globalSettings: {
                    
    accessibility_focusfalse,
                    
    language"en",
                    
    mode"none",
                    
    skin "o2k7",
                    
    theme"advanced",
                    
    theme_advanced_resizingfalse
                
    },
                
                
    setGlobalSettings: function(settings) {
                    
    Ext.apply(this.globalSettingssettings);
                }
            },
            
            
    config: {
                
    height300
            
    },
            
            
    constructor: function(config) {
                
    //override default tinyMCESettings
                
    config.tinyMCESettings Ext.Object.merge(this.statics().globalSettingsconfig.tinyMCESettings);
                
                
    this.callParent([config]);
                
                return 
    this;
            },
            
            
    afterRender: function() {
                
    this.callParent(arguments);
                
                
    this.tinyMCESettings.height this.height 11;
                
                
    this.editor = new tinymce.Editor(this.inputEl.idthis.tinyMCESettings);
                
    this.editor.render();
                
    tinyMCE.add(this.editor);
                
                
    this.editor.onPostRender.add(Ext.Function.bind(function(editorcontrolManager) {
                    
    editor.windowManager Ext.create("EC.common.tinymce.WindowManager", {
                        
    editorthis.editor
                    
    });
                }, 
    this));
                
                
    window.this.editor;
            },
            
            
    getValue: function() {
                return 
    this.editor.getContent();
            },
            
            
    setValue: function(val) {
                if(
    this.editor && this.editor.initialized) {
                    
    this.editor.setContent(val);
                } else {
                    
    Ext.Function.createDelayed(function() {
                        
    this.setValue(val);
                    }, 
    200this)();
                }
            },
            
            
    getSubmitData: function() {
                var 
    ret = {};
                
    ret[this.getName()] = this.getValue();
                return 
    ret;
            },
            
            
    onDestroy: function() {
                
    this.editor.remove();
                
    this.editor.destroy();
                
    this.callParent(arguments);
            }
        });

    (the big if() around it is not needed)

    usage:
    PHP Code:
    <!doctype html>
    <
    html>
        <
    head>
            <
    link rel="stylesheet" href="ext-4.0.2a/resources/css/ext-all.css">
            
            <
    script src="ext-4.0.2a/ext-all-debug.js"></script>
            <script src="tinymce/jscripts/tiny_mce/tiny_mce_src.js"></script>
            
            <script src="EC.common.tinymce.WindowManager.js"></script>
            <script src="EC.common.tinymce.Editor.js"></script>
            <script>
                Ext.onReady(function() {
                    EC.common.tinymce.Editor.setGlobalSettings({
                        
                    });
                    
                    var win = Ext.create("Ext.window.Window", {
                        height: 700,
                        width: 800,
                        layout: 'fit',
                        items: [
                            {
                                xtype: "form",
                                defaultType: 'textfield',
                                id: "test",
                                items: [
                                    {
                                        fieldLabel: "hallo test 1",
                                        value: "hoi"
                                    }, {
                                        xtype: "TinyMCEEditor",
                                        fieldLabel: "test",
                                        name: "testName",
                                        tinyMCESettings: {
                                            plugins: "pagebreak,style,layer,table,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
                                            theme_advanced_buttons1: "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect",
                                            theme_advanced_buttons2: "formatselect,fontselect,fontsizeselect,code",
                                            //theme_advanced_buttons2: "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
                                            //theme_advanced_buttons3: "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|",
                                            //theme_advanced_buttons4: "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak",
                                            theme_advanced_toolbar_location: "top",
                                            theme_advanced_toolbar_align: "left",
                                            theme_advanced_statusbar_location: "bottom",
                                            extended_valid_elements: "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
                                            template_external_list_url: "example_template_list.js"
                        
                                        },
                                        value: "<h1>Demo</h1><p>Ext.ux.TinyMCE works...</p>",
                                        width: 500,
                                        height: 300
                                    }, {
                                        fieldLabel: "hallo test 2",
                                        value: "hoi"
                                    }
                                ]
                            }
                        ],
                        buttons: [{
                            text: "alert content",
                            handler: function() {
                                alert(Ext.getCmp("test").getValues()["testName"]);
                            }
                        }]
                    });
                    
                    window.a = Ext.getCmp("test");
                    
                    win.show();
                    
                });
            </script>
        </head>
        <body>
            
        </body>
    </body> 
    as you can see, you can set globalsettings by calling EC.common.tinymce.Editor.setGlobalSettings(). These settings will be applied to all tinymce instances and can be overridden by configuration per instance.

    Of course any help is still appreciated :)

  3. #3
    Sencha User hexawing's Avatar
    Join Date
    Nov 2009
    Posts
    73
    Vote Rating
    0
    hexawing is on a distinguished road

      0  

    Default


    Great work! thx!

  4. #4
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    Germany
    Posts
    691
    Vote Rating
    25
    Dumbledore will become famous soon enough Dumbledore will become famous soon enough

      0  

    Default


    wow - really nice!

  5. #5
    Sencha User
    Join Date
    Jul 2011
    Posts
    2
    Vote Rating
    0
    yonas.yanfa is on a distinguished road

      0  

    Thumbs up daanlib

    daanlib


    daanlib,

    Thanks for posting your work here. I'd like to add your work to my site. We're getting ready to offer all sorts of TinyMCE plugins, enhancements, and integrations for our clients.

    If this is OK with you, please let me know which license you are using here and the name and email address to use for attribution.

    Cheers,
    Yonas
    --
    TinymceSupport.com - Support, Consulting, and Development

  6. #6
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,197
    Vote Rating
    482
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    First off, thanks for working on this control. Extjs.HtmlEditor is quite troublesome, so I look forward to getting this to work.

    Several issues I encountered:

    Running your sample (and using it in my app): If you cut/paste the text into the editor, the editor becomes unresponsive. I can click buttons, but I cannot select, add any more text.
    (not a problem in IE, locks in FF and Chrome)

    The control will not follow my anchor settings. If I resize the form, I cannot get your control to resize along with the other controls. I have it set inside a tabPanel and it will not grow with the panel.

    Regards,
    Scott.

  7. #7
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    Germany
    Posts
    691
    Vote Rating
    25
    Dumbledore will become famous soon enough Dumbledore will become famous soon enough

      0  

    Default


    for correct resizing:

    Code:
    [...]
            afterRender: function() {
                var me = this;
                this.callParent(arguments);
    
                this.tinyMCESettings.height = this.height - 11;
    
                this.editor = new tinymce.Editor(this.inputEl.id, this.tinyMCESettings);
                this.editor.render();
                tinyMCE.add(this.editor);
    
                this.editor.onPostRender.add(Ext.Function.bind(function(editor, controlManager) {
                    editor.windowManager = Ext.create("Ext.ux.tinymce.WindowManager", {
                        editor: this.editor
                    });
    
                    this.tableEl = Ext.get(this.editor.id + "_tbl");
                    this.iframeEl = Ext.get(this.editor.id + "_ifr");
    
                }, this));
    
                window.b = this.editor;
    
                this.on('resize', this.onResize, this);
            },
    
    [...]
    
    
            /**
             *
             * @param component
             * @param adjWidth
             * @param adjHeight
             */
            onResize : function(component, adjWidth, adjHeight){
                var width;
                var bodyWidth = component.bodyEl.getWidth();
    
                if (component.iframeEl){
                    width = bodyWidth - component.iframeEl.getBorderWidth('lr') - 2;
                    component.iframeEl.setWidth(width);
                }
                if (component.tableEl){
                    width = bodyWidth - component.tableEl.getBorderWidth('lr') - 2;
                    component.tableEl.setWidth(width);
                }
            }
    this will run fine in my case...

  8. #8
    Sencha User
    Join Date
    May 2010
    Posts
    172
    Vote Rating
    1
    Dmoney is on a distinguished road

      0  

    Default


    @Dumbledore

    Your resizing solution seems to work. but once I implement the changes the window for the html view no longer works.

    I get this error in firebug

    v.editor.settings is undefined

  9. #9
    Sencha User
    Join Date
    May 2010
    Posts
    172
    Vote Rating
    1
    Dmoney is on a distinguished road

      0  

    Default


    It was my code not yours causing the problem. Works like a charm now, thanks!

  10. #10
    Sencha User
    Join Date
    May 2010
    Posts
    172
    Vote Rating
    1
    Dmoney is on a distinguished road

      0  

    Default


    This plugin works great, and I'm thrilled to be able to replace the htmlEditor with tinyMCE. but now I'm trying to add some functionality and I've hit a roadblock I'm hoping someone can give me some advice. I've added a button to the editor that opens up a window like this :

    var view = Ext.widget('pickerWindow');

    when a selection is made in the window I want it to add my variable text to the editor like this:

    var ed = tinyMCE.get('content');
    ed.selection.setContent(myContent);

    But I get the error that ed is undefined. how can I reference the tinyMCE editor from my window?

    If I use firebug it shows that the textArea does not have the id I specified "content" instead it has "ext-gen1145"

    So the following works but how is that id generated is it subject to change?
    var ed = tinyMCE.get('ext-gen1145');
    ed.selection.setContent(myContent);