Commit 502d57a1 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Refactor InlinePreview and -Editor into components.

This greatly simplifies the Inline component, delegating the actual
preview showing and code editing to other classes.  More over the
InlineExamples controller no more deals with the iframe and many
other details directly.

Removed CSS-loading from both iframe files - for now it's not used.
Also removed error alert - writing the error message to document.body
should be enough, plus it's less obtrusive.

Inside touchIframe.html wrapping the code inside Ext.setup().
For start it will make most examples work.
parent 5dcc857b
Loading
Loading
Loading
Loading
+10 −56
Original line number Diff line number Diff line
@@ -6,30 +6,13 @@ Ext.define('Docs.controller.InlineExamples', {

    init: function() {
        this.control({
            'inlineexample': {
                afterlayout: function(cmp) {
                    if (!cmp.codeEditor) {
                        var codeBody = cmp.getComponent(0).body;

                        cmp.codeEditor = CodeMirror(codeBody, {
                            mode:  "javascript",
                            indentUnit: 4,
                            onChange: function(e) {
                                cmp.updateHeight();
                            }
                        });
                    }
                }
            },
            'inlineexample [cmpName=code]': {
                activate: function(cmp) {
                    this.activateTab(cmp, 'code');
                    var inlineEg = cmp.up('inlineexample');
                    if (inlineEg && inlineEg.codeEditor) {
                    var editor = cmp.up('inlineexample').editor;
                    // Weird bug on CodeMirror requires 2 refreshes...
                        inlineEg.codeEditor.refresh();
                        inlineEg.codeEditor.refresh();
                    }
                    editor.refresh();
                    editor.refresh();
                }
            },
            'inlineexample [cmpName=preview]': {
@@ -44,18 +27,13 @@ Ext.define('Docs.controller.InlineExamples', {
            },
            'inlineexample toolbar button[iconCls=preview]': {
                click: function(cmp) {
                    cmp.up('inlineexample').showPreview(function() {
                        this.refreshPreview(cmp.up('inlineexample'));
                    }, this);
                    cmp.up('inlineexample').showPreview();
                }
            },
            'inlineexample toolbar button[iconCls=copy]': {
                click: function(cmp) {
                    cmp.up('inlineexample').showCode();
                    var editor = cmp.up('inlineexample').codeEditor;
                    var lastLine = editor.lineCount() - 1;
                    var lastCh = editor.getLine(lastLine).length;
                    editor.setSelection({line: 0, ch: 0}, {line: lastLine, ch: lastCh});
                    cmp.up('inlineexample').editor.selectAll();
                }
            },
            'classoverview': {
@@ -73,9 +51,9 @@ Ext.define('Docs.controller.InlineExamples', {
    createResizer: function(container) {
        return function() {
            Ext.Array.each(Ext.ComponentQuery.query(container + ' .inlineexample'), function(c) {
                if (c.codeEditor && c.isVisible()) {
                if (c.editor && c.isVisible()) {
                    c.doLayout();
                    c.codeEditor.refresh();
                    c.editor.refresh();
                }
            });
        };
@@ -101,32 +79,8 @@ Ext.define('Docs.controller.InlineExamples', {
            var eg = Ext.create('Docs.view.examples.Inline', {
                height: 200,
                renderTo: div,
                listeners: {
                    afterrender: function(cmp) {
                        this.updateExample(cmp, code);
                    },
                    scope: this
                }
                value: code
            });
        }, this);
    },

    // Updates code inside example component
    updateExample: function(example, code) {
        example.codeEditor.setValue(code);
        var activeItem = example.layout.getActiveItem();
        if (activeItem.cmpName == 'preview') {
            example.showPreview(function() {
                this.refreshPreview(example);
            }, this);
    }
        example.updateHeight();
    },

    // Refreshes the preview of example
    refreshPreview: function(example) {
        var iframe = document.getElementById(example.getIframeId());
        iframe.contentWindow.refreshPage(example.codeEditor.getValue(), '');
    }

});
+34 −64
Original line number Diff line number Diff line
@@ -4,6 +4,10 @@
Ext.define('Docs.view.examples.Inline', {
    extend: 'Ext.Panel',
    alias: 'widget.inlineexample',
    requires: [
        'Docs.view.examples.InlineEditor',
        'Docs.view.examples.InlinePreview'
    ],

    componentCls: 'inline-example-cmp',
    layout: 'card',
@@ -16,10 +20,6 @@ Ext.define('Docs.view.examples.Inline', {
    // Make too long examples scrollable
    maxHeight: 400,

    statics: {
        iframeId: 0
    },

    dockedItems: [{
        xtype: 'toolbar',
        dock: 'left',
@@ -47,30 +47,37 @@ Ext.define('Docs.view.examples.Inline', {
        ]
    }],

    defaults: {
        border: 0
    },

    initComponent: function() {
        this.items = [
            {
            this.editor = Ext.create('Docs.view.examples.InlineEditor', {
                cmpName: 'code',
                style: 'border: 0',
                bodyPadding: 2,
                bodyStyle: 'background: #f7f7f7',
                autoScroll: true
            },
            {
                bodyPadding: '0 10',
                cmpName: 'preview',
                html: this.getHtml()
                value: this.value,
                listeners: {
                    change: this.updateHeight,
                    scope: this
                }
            }),
            this.preview = Ext.create('Docs.view.examples.InlinePreview', {
                cmpName: 'preview'
            })
        ];

        this.activeItem = Docs.touchExamplesUi ? 1 : 0;

        this.on("afterrender", this.init, this);

        this.callParent(arguments);
    },

    // Updates code inside example component
    init: function() {
        var activeItem = this.layout.getActiveItem();
        if (activeItem.cmpName === 'preview') {
            this.showPreview();
        }
        this.updateHeight();
    },

    /**
     * Activates the code card.
     */
@@ -79,58 +86,21 @@ Ext.define('Docs.view.examples.Inline', {
    },

    /**
     * Activates the code preview card.
     * @param {Function} callback  Called when iframe is ready.
     * @param {Object} scope
     * Activates the preview card.
     */
    showPreview: function(callback, scope) {
        var iframe = document.getElementById(this.getIframeId());
        // Something is not quite ready when onload fires.
        // I'm unsure what I should wait for. So I'm currently adding just this nasty delay.
        // 1 ms works in Chrome, Firefox wants something bigger. Works in IE too.
        iframe.onload = function() {
            Ext.Function.defer(callback, 100, scope);
        };
        iframe.src = Docs.touchExamplesUi ? "touchIframe.html" : "extIframe.html";
    showPreview: function() {
        this.preview.update(this.editor.getValue());
        this.layout.setActiveItem(1);
        this.previewInitialized = true;
    },

    getHtml: function() {
    // Syncs the height with number of lines in code example.
    updateHeight: function() {
        if (Docs.touchExamplesUi) {
            var tpl = new Ext.XTemplate(
                '<div class="touchExample phone landscape">',
                    '<iframe id="{id}" style="width: 480px; height: 320px; border: 0;"></iframe>',
                '</div>'
            );
            this.setHeight(320+50);
        }
        else {
            var tpl = new Ext.XTemplate(
                '<iframe id="{id}" style="width: 100%; height: 100%; border: 0"></iframe>'
            );
        }
        return tpl.apply({id: this.getIframeId()});
    },

    /**
     * Returns iframe ID for this inline example component.
     * @return {String}
     */
    getIframeId: function() {
        if (!this.iframeId) {
            this.statics().iframeId += 1;
            this.iframeId = "egIframe" + this.statics().iframeId;
        }
        return this.iframeId;
    },

    /**
     * Syncs the height with number of lines in code example.
     */
    updateHeight: function() {
        var el = this.el.down('.CodeMirror-lines');
        if (el) {
            this.setHeight(Docs.touchExamplesUi ? 320+50 : el.getHeight() + 5);
            var editorHeight = this.editor.getHeight();
            editorHeight && this.setHeight(editorHeight + 5);
        }
    }

+69 −0
Original line number Diff line number Diff line
/**
 * Runs the CodeMirror editor.
 */
Ext.define('Docs.view.examples.InlineEditor', {
    extend: 'Ext.Panel',
    style: 'border: 0',
    bodyPadding: 2,
    bodyStyle: 'background: #f7f7f7',
    autoScroll: true,

    initComponent: function() {
        this.addEvents(
            /**
             * @event
             * Fired when CodeMirror onChange is called.
             */
            "change"
        );
        this.on("afterlayout", this.initCodeMirror, this);
        this.callParent(arguments);
    },

    initCodeMirror: function(cmp) {
        if (!this.codemirror) {
            this.codemirror = CodeMirror(this.body, {
                mode:  "javascript",
                indentUnit: 4,
                value: this.value,
                onChange: Ext.Function.bind(function(e) {
                    this.fireEvent("change");
                }, this)
            });
        }
    },

    /**
     * Refreshes the editor.
     */
    refresh: function() {
        this.codemirror.refresh();
    },

    /**
     * Returns the current code in editor.
     * @return {String}
     */
    getValue: function() {
        return this.codemirror ? this.codemirror.getValue() : this.value;
    },

    /**
     * Returns the height of embedded CodeMirror editor.
     * @return {Number}
     */
    getHeight: function() {
        var el = this.el.down('.CodeMirror-lines');
        return el ? el.getHeight() : undefined;
    },

    /**
     * Selects all text currently in editor.
     */
    selectAll: function() {
        var lastLine = this.codemirror.lineCount() - 1;
        var lastCh = this.codemirror.getLine(lastLine).length;
        this.codemirror.setSelection({line: 0, ch: 0}, {line: lastLine, ch: lastCh});
    }

});
+60 −0
Original line number Diff line number Diff line
/**
 * Demonstrates an example inside iframe.
 */
Ext.define('Docs.view.examples.InlinePreview', {
    extend: 'Ext.Panel',
    bodyPadding: '0 10',

    statics: {
        iframeId: 0
    },

    initComponent: function() {
        this.html = this.getHtml();

        this.callParent(arguments);
    },

    getHtml: function() {
        if (Docs.touchExamplesUi) {
            var tpl = new Ext.XTemplate(
                '<div class="touchExample phone landscape">',
                    '<iframe id="{id}" style="width: 480px; height: 320px; border: 0;"></iframe>',
                '</div>'
            );
        }
        else {
            var tpl = new Ext.XTemplate(
                '<iframe id="{id}" style="width: 100%; height: 100%; border: 0"></iframe>'
            );
        }
        return tpl.apply({id: this.getIframeId()});
    },

    /**
     * Updates the live example inside iframe with new code.
     * @param {String} javascript  The code to run inside iframe.
     */
    update: function(javascript) {
        var iframe = document.getElementById(this.getIframeId());
        // Something is not quite ready when onload fires.
        // I'm unsure what I should wait for. So I'm currently adding just this nasty delay.
        // 1 ms works in Chrome, Firefox wants something bigger. Works in IE too.
        iframe.onload = function() {
            Ext.Function.defer(function() {
                iframe.contentWindow.refreshPage(javascript);
            }, 100);
        };
        iframe.src = Docs.touchExamplesUi ? "touchIframe.html" : "extIframe.html";
    },

    // Returns iframe ID for this inline example component.
    getIframeId: function() {
        if (!this.iframeId) {
            this.statics().iframeId += 1;
            this.iframeId = "egIframe" + this.statics().iframeId;
        }
        return this.iframeId;
    }

});
+1 −4
Original line number Diff line number Diff line
@@ -7,15 +7,12 @@
    <script type="text/javascript" src="extjs/ext-all.js"></script>
    <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">

    <style id="iframeCSS" type="text/css"></style>
    <script type="text/javascript">
        var refreshPage = function(code, css) {
        var refreshPage = function(code) {
            try {
                document.body.innerHTML = '';
                eval(code);
                Ext.get('iframeCSS').update(css);
            } catch (e) {
                alert(e);
                document.body.innerHTML = e;
            }
        }
Loading