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,182
    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
    427
    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

  7. #7
    Ext JS Premium Member prophet's Avatar
    Join Date
    Mar 2007
    Location
    Greenwich, CT
    Posts
    187
    Vote Rating
    0
    prophet is on a distinguished road

      0  

    Default


    Very nice! Thank you!

    Question: Is there a way to make the editor take up the rest of the empty vertical space in the window?
    Even though the height is set to 100%, it seems to default to 150px -- I can make it larger by giving it an exact pixel value, but I'd rather keep the re-size functionality of the containing window.
    Brad Baumann

  8. #8
    Sencha - Services Team Stju's Avatar
    Join Date
    Dec 2008
    Location
    Redwood city, California
    Posts
    288
    Vote Rating
    3
    Stju is on a distinguished road

      0  

    Default


    Nice component!
    Any way to paste some code dynamically at cursor position in already rendered CodeMirror panel?

  9. #9
    Ext JS Premium Member prophet's Avatar
    Join Date
    Mar 2007
    Location
    Greenwich, CT
    Posts
    187
    Vote Rating
    0
    prophet is on a distinguished road

      0  

    Default


    Check out the methods exposed in the codeEditor object:
    Ext.getCmp('CodeMirrorCmpID').codeEditor
    Brad Baumann

  10. #10
    Sencha - Services Team Stju's Avatar
    Join Date
    Dec 2008
    Location
    Redwood city, California
    Posts
    288
    Vote Rating
    3
    Stju is on a distinguished road

      0  

    Default


    Had today time to work around this component..
    so here are few additional methods:
    Code:
        getValue: function() {
            return this.codeMirrorEditor.getCode();
        },
    
        setValue: function(text) {
            this.codeMirrorEditor.setCode(text);
        },
    
        setValueAtCursor: function(text) {
            var cursorPosition = this.codeMirrorEditor.cursorPosition();
            var handleForCursorLine = this.codeMirrorEditor.cursorLine();
            this.codeMirrorEditor.insertIntoLine(handleForCursorLine, cursorPosition.character, text);
        }

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..." hd porno faketaxi