Hybrid View

  1. #1
    Sencha User
    Join Date
    Oct 2007
    Posts
    8
    Vote Rating
    -1
    qulys is on a distinguished road

      0  

    Lightbulb Ext.ux.panel.CodeMirror

    Ext.ux.panel.CodeMirror


    Hi,

    This is my CodeMirror implementation.
    It extends panel, so you can have a toolbar.
    It has JSLINT included so you can verify your code by pressing a button.
    Also I have modified original themes to use a dark color aproach.
    It only works with codeMirror 0.63 , higher versions are buggy...

    Extension code:
    HTML Code:
    /*global Ext,  JSLINT, CodeMirror  */
    
    /**
     * @class Ext.ux.panel.CodeMirror
     * @extends Ext.Panel
     * Converts a panel into a code mirror editor with toolbar
     * @constructor
     * 
     * @author Dan Ungureanu - ungureanu.web@gmail.com / http://www.devweb.ro
     * @version 0.1
     */
    
     // Define a set of code type configurations
    Ext.ns('Ext.ux.panel.CodeMirrorConfig');
    Ext.apply(Ext.ux.panel.CodeMirrorConfig, {
        cssPath: "CodeMirror-0.63/css/",
        jsPath: "CodeMirror-0.63/js/"
    });
    Ext.apply(Ext.ux.panel.CodeMirrorConfig, {
        parser: {
            defo: { // js code
                parserfile: ["tokenizejavascript.js", "parsejavascript.js"],
                stylesheet: Ext.ux.panel.CodeMirrorConfig.cssPath + "jscolors.css"
            },
            css: {
                parserfile: ["parsecss.js"],
                stylesheet: Ext.ux.panel.CodeMirrorConfig.cssPath + "csscolors.css"
            },
            js: {
                parserfile: ["tokenizejavascript.js", "parsejavascript.js"],
                stylesheet: Ext.ux.panel.CodeMirrorConfig.cssPath + "jscolors.css"
            },
            php: {
                parserfile: ["tokenizephp.js", "parsephp.js"],
                stylesheet: Ext.ux.panel.CodeMirrorConfig.cssPath + "phpcolors.css"
            },
            html: {
                parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js", "tokenizephp.js", "parsephp.js", "parsephphtmlmixed.js"],
                stylesheet: [Ext.ux.panel.CodeMirrorConfig.cssPath + "xmlcolors.css", Ext.ux.panel.CodeMirrorConfig.cssPath + "jscolors.css", Ext.ux.panel.CodeMirrorConfig.cssPath + "csscolors.css", Ext.ux.panel.CodeMirrorConfig.cssPath + "phpcolors.css"]
                
            },
            mixed: {
                parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js", "tokenizephp.js", "parsephp.js", "parsephphtmlmixed.js"],
                stylesheet: [Ext.ux.panel.CodeMirrorConfig.cssPath + "xmlcolors.css", Ext.ux.panel.CodeMirrorConfig.cssPath + "jscolors.css", Ext.ux.panel.CodeMirrorConfig.cssPath + "csscolors.css", Ext.ux.panel.CodeMirrorConfig.cssPath + "phpcolors.css"]
                
            }
        }
    });
    
    Ext.ns('Ext.ux.panel.CodeMirror');
    Ext.ux.panel.CodeMirror = Ext.extend(Ext.Panel, {
        
    
        sourceCode: '/* Default code */',
        initComponent: function() {
            // this property is used to determine if the source content changes
            this.contentChanged = false;
            var oThis = this;
            this.debugWindow = new Ext.Window({
                title: 'Debug',
                width: 500,
                layout: 'border',
                closeAction: 'hide',
                height: 160,
                items: [new Ext.grid.GridPanel({
                    layout: 'fit',
                    region: 'center',
                    border: false,
                    listeners: {
                        rowclick: function(grid) {
                            var oData = grid.getSelectionModel().getSelected().data;
                            oThis.codeMirrorEditor.jumpToLine(oData.line);
                        }
                    },
                    store: new Ext.data.ArrayStore({
                        fields: [{
                            name: 'line'
                        }, {
                            name: 'character'
                        }, {
                            name: 'reason'
                        }]
                    }),
                    columns: [{
                        id: 'line',
                        header: 'Line',
                        width: 60,
                        sortable: true,
                        dataIndex: 'line'
                    }, {
                        id: 'character',
                        header: 'Character',
                        width: 60,
                        sortable: true,
                        dataIndex: 'character'
                    }, {
                        header: 'Description',
                        width: 240,
                        sortable: true,
                        dataIndex: 'reason'
                    }],
                    stripeRows: true
                })]
            });
            
            Ext.apply(this, {
                items: [{
                    xtype: 'textarea',
                    readOnly: false,
                    hidden: true,
                    value: this.sourceCode
                }],
                tbar: [{
                    text: 'Save',
                    handler: this.triggerOnSave,
                    scope: this
                }, {
                    text: 'Undo',
                    handler: function() {
                        this.codeMirrorEditor.undo();
                    },
                    scope: this
                }, {
                    text: 'Redo',
                    handler: function() {
                        this.codeMirrorEditor.redo();
                    },
                    scope: this
                }, {
                    text: 'Indent',
                    handler: function() {
                        this.codeMirrorEditor.reindent();
                    },
                    scope: this
                }, {
                    itemId: 'spellChecker',
                    disabled: true,
                    text: 'JS Lint',
                    handler: function() {
                        try {
                            var bValidates = JSLINT(this.findByType('textarea')[0].getValue());
                            
                            var oStore = this.debugWindow.findByType('grid')[0].getStore();
                            if (!bValidates) {
                                var aErrorData = [];
                                
                                for (var err in JSLINT.errors) {
                                    if (JSLINT.errors.hasOwnProperty(err) && (JSLINT.errors[err] !== null)) {
                                        aErrorData.push([JSLINT.errors[err].line, JSLINT.errors[err].character, JSLINT.errors[err].reason]);
                                    }
                                }
                                
                                oStore.loadData(aErrorData, false);
                                this.debugWindow.show();
                                
                            }
                            else {
                            
                                oStore.loadData([[1, 1, 'Congratulation! No errors found.']], false);
                                this.debugWindow.show();
                            }
                        }catch(e){}
                        
                    },
                    scope: this
                }]
            });
            
            Ext.ux.panel.CodeMirror.superclass.initComponent.apply(this, arguments);
        },
        
        triggerOnSave: function(){
            this.setTitleClass(true);
            var sNewCode = this.codeMirrorEditor.getCode();
            
            Ext.state.Manager.set("edcmr_"+this.itemId+'_lnmbr', this.codeMirrorEditor.currentLine());
            
            this.oldSourceCode = sNewCode;
            this.onSave(arguments[0] || false);
        },
        
        onRender: function() {
            this.oldSourceCode = this.sourceCode;
            Ext.ux.panel.CodeMirror.superclass.onRender.apply(this, arguments);
            // trigger editor on afterlayout
            this.on('afterlayout', this.triggerCodeEditor, this, {
                single: true
            });
            
        },
        
        /** @private */
        triggerCodeEditor: function() {
            //this.codeMirrorEditor;
            var oThis = this;
            var oCmp = this.findByType('textarea')[0];
            var editorConfig = Ext.applyIf(this.codeMirror || {}, {
               height: "100%",
               width: "100%",
               lineNumbers: true,
               textWrapping: false,
               content: oCmp.getValue(),
               indentUnit: 4,
               tabMode: 'shift',
               readOnly: oCmp.readOnly,
               path: Ext.ux.panel.CodeMirrorConfig.jsPath,
               autoMatchParens: true,
               initCallback: function(editor) {
                   editor.win.document.body.lastChild.scrollIntoView();
                   try {
                       var iLineNmbr = ((Ext.state.Manager.get("edcmr_" + oThis.itemId + '_lnmbr') !== undefined) ? Ext.state.Manager.get("edcmr_" + oThis.itemId + '_lnmbr') : 1);
                       //console.log(iLineNmbr);
                       editor.jumpToLine(iLineNmbr);
                   }catch(e){
                       //console.error(e);
                   }
               },
               onChange: function() {
                   var sCode = oThis.codeMirrorEditor.getCode();
                   oCmp.setValue(sCode);
                   
                   if(oThis.oldSourceCode == sCode){
                       oThis.setTitleClass(true);
                   }else{
                       oThis.setTitleClass();
                   }
                   
               }
           });
            
            var sParserType = oThis.parser || 'defo';
            editorConfig = Ext.applyIf(editorConfig, Ext.ux.panel.CodeMirrorConfig.parser[sParserType]);
            
            this.codeMirrorEditor = new CodeMirror.fromTextArea( Ext.getDom(oCmp.id).id, editorConfig);
            
            // Disable spell check button for non-js content
            if (sParserType == 'js' || sParserType == 'css') {
                this.getTopToolbar().getComponent('spellChecker').enable();
            }
        },
        
        setTitleClass: function(){
            //var tabEl = Ext.get(this.ownerCt.getTabEl( this ));
            if(arguments[0] === true){// remove class
                //tabEl.removeClass( "tab-changes" );
                this.contentChanged = false;
            }else{//add class
                //tabEl.addClass( "tab-changes" );
                this.contentChanged = true;
            }
        }
    });
    
    
    Ext.reg('uxCodeMirrorPanel', Ext.ux.panel.CodeMirror);
    Example:
    HTML Code:
    {
            xtype: 'uxCodeMirrorPanel',
            title: 'JS example',
            closable: true,
            listeners: {
                render: function(){
                    this.doLayout();
                }
            },
            sourceCode: '/* paste here somme js code */',
            //layout: 'fit',
            parser: 'js',
            onSave: function() {
                // save logic here
                // this.codeMirrorEditor gets you access to original code mirror object :)
            },
            codeMirror: {
                height: '100%',
                width: '100%'
            }
        }
    I also attached a working example to unpack and drop into your ext30 examples folder.
    Attached Images
    Attached Files

  2. #2
    Sencha - Architect Dev Team aconran's Avatar
    Join Date
    Mar 2007
    Posts
    9,168
    Vote Rating
    119
    aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold

      0  

    Default


    Nice work, this is a neat ux.
    Aaron Conran
    @aconran
    Sencha Architect Development Team

  3. #3
    Ext User
    Join Date
    Mar 2010
    Posts
    8
    Vote Rating
    0
    knowledgeVirtue is on a distinguished road

      0  

    Default


    Hi,

    I'm having issue populating value to codemirror editor. Based on combox value i have to fill codemirror editor. But by using Ext.getCmp('codemirrorid').setValue(x) or Ext.getCmp('codemirrorid').setCode(x) doesn't work. Can you help me how to populate the editor?

  4. #4
    Sencha User wemerson.januario's Avatar
    Join Date
    Nov 2008
    Location
    Brazil, Goias, Goiânia
    Posts
    426
    Vote Rating
    6
    wemerson.januario is on a distinguished road

      0  

    Default


    nice work. I will test
    Wemerson Januario
    Twitter:
    @wemersonjanuar
    Skype:
    wemerson.januario
    Email: wemerson.januario@gmail.com
    Fone:
    62 9106-6689
    From: Goiânia, Brazil
    Desenvolvedor ExtJS/ ExtJS Developer

  5. #5
    Sencha User asp3ctus's Avatar
    Join Date
    Jan 2010
    Location
    Russia
    Posts
    28
    Vote Rating
    0
    asp3ctus is on a distinguished road

      0  

    Default


    What kinda bugs did you find with a later version of CodeMirror ?
    I have tried git version ... and to me it worked the same .....
    But i din't test it much

    Thanks, great stuff!!

  6. #6
    Ext User
    Join Date
    May 2010
    Posts
    2
    Vote Rating
    0
    revresxunil is on a distinguished road

      0  

    Default


    Great plugin!! Works great for my research based web portal project.

    I had initial problems with the location in which I uploaded the files but modifying the plugin file with exact locations of codemirror fixed it.

    Long live open source.

    Mike

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..."