Commit e2525781 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Optimize initial rendering of inline examples.

Instead of launching the CodeMirror editor right away, only the toolbar
is created and the original highlighted <pre> is kept.  Only after
"preview" or "code" button is pressed will the <pre> be replaced with
CodeMirror editor and inline preview iframe.

This greatly speeds up the loading time of classes that have inline
examples.  This of course only applies to examples that don't start
off in preview mode - these will still slow the page down.

Most of the logic that was previously in InlineExamples controller is
now moved away to the components.  The controller only deals with the
high-level stuff like initializing the components when page loaded.

From look-and-feel side the editor component now has rounded corners
and looks almost like the normal <pre> code block.  When switching
from <pre> to editor, the text stays at the exact same position,
only the syntax highlighting colors change.

Having removed this slowness factor, inline examples are now also
enabled in IE.  The experience in IE is seriously crappy still...
parent 56c9405b
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -15,12 +15,8 @@ Ext.define("Docs.Syntax", {
        Ext.Array.forEach(Ext.query("pre > code", root.dom || root), function(code) {
            code = Ext.get(code);
            var pre = code.parent();
            // Disable inline examples in IE (too slow)
            if (!Docs.forceInlineExamples && Ext.isIE && pre.hasCls("inline-example")) {
                pre.removeCls("inline-example");
            }
            // Don't prettify inline examples, these are highlighted anyway
            if (!pre.hasCls("inline-example")) {
            // Don't prettify inline examples that have preview enabled.
            if (!(pre.hasCls("inline-example") && pre.hasCls("preview"))) {
                code.addCls("prettyprint");
            }
        });
+6 −64
Original line number Diff line number Diff line
@@ -3,39 +3,12 @@
 */
Ext.define('Docs.controller.InlineExamples', {
    extend: 'Ext.app.Controller',
    requires: [
        'Docs.view.examples.InlineWrap'
    ],

    init: function() {
        this.control({
            'inlineexample [cmpName=code]': {
                activate: function(cmp) {
                    this.activateTab(cmp, 'code');
                    var editor = cmp.up('inlineexample').editor;
                    // Weird bug on CodeMirror requires 2 refreshes...
                    editor.refresh();
                    editor.refresh();
                }
            },
            'inlineexample [cmpName=preview]': {
                activate: function(cmp) {
                    this.activateTab(cmp, 'preview');
                }
            },
            'inlineexample toolbar button[iconCls=code]': {
                click: function(cmp) {
                    cmp.up('inlineexample').showCode();
                }
            },
            'inlineexample toolbar button[iconCls=preview]': {
                click: function(cmp) {
                    cmp.up('inlineexample').showPreview();
                }
            },
            'inlineexample toolbar button[iconCls=copy]': {
                click: function(cmp) {
                    cmp.up('inlineexample').showCode();
                    cmp.up('inlineexample').editor.selectAll();
                }
            },
            'classoverview': {
                resize: this.createResizer('.class-overview'),
                afterload: this.replaceExampleDivs
@@ -59,41 +32,10 @@ Ext.define('Docs.controller.InlineExamples', {
        };
    },

    activateTab: function(cmp, buttonCls) {
        Ext.Array.each(cmp.up('inlineexample').query('toolbar button'), function(b) {
            b.removeCls('active');
        });
        Ext.Array.each(cmp.up('inlineexample').query('toolbar button[iconCls=' + buttonCls + ']'), function(b) {
            b.addCls('active');
        });
    },

    replaceExampleDivs: function() {
        Ext.Array.each(Ext.query('.inline-example'), function(inlineEg) {
            // Grab code from <pre> element and replace it with new empty <div>
            // Strip tags and replace HTML entities with their values
            var code = Ext.String.htmlDecode(Ext.util.Format.stripTags(inlineEg.innerHTML));
            var options = {};
            Ext.Array.forEach(inlineEg.className.split(/ +/), function(cls) {
                if (cls === "phone" || cls === "miniphone" || cls === "tablet") {
                    options.device = cls;
                }
                else if (cls === "ladscape" || cls === "portrait") {
                    options.orientation = cls;
                }
                else {
                    options[cls] = true;
                }
            });
            var div = document.createElement("div");
            inlineEg.parentNode.replaceChild(div, inlineEg);
            // Then render the example component inside the div
            var eg = Ext.create('Docs.view.examples.Inline', {
                height: 200,
                renderTo: div,
                value: code,
                options: options
            });
        Ext.Array.each(Ext.query('.inline-example'), function(pre) {
            Ext.create("Docs.view.examples.InlineWrap", pre);
        }, this);
    }

});
+34 −28
Original line number Diff line number Diff line
@@ -20,33 +20,6 @@ Ext.define('Docs.view.examples.Inline', {
    // Make too long examples scrollable
    maxCodeHeight: 400,

    dockedItems: [{
        xtype: 'toolbar',
        dock: 'top',
        height: 30,
        items: [
            {
                iconCls: 'code',
                padding: '0 2 0 0',
                margin: '0 3 0 0',
                text: 'Code Editor'
            },
            {
                padding: 0,
                margin: '0 3 0 0',
                iconCls: 'preview',
                text: 'Live Preview'
            },
            "->",
            {
                padding: 0,
                margin: 0,
                iconCls: 'copy',
                text: 'Select Code'
            }
        ]
    }],

    /**
     * @cfg {Object} options
     * A set of options for configuring the preview:
@@ -58,6 +31,11 @@ Ext.define('Docs.view.examples.Inline', {
     */
    options: {},

    /**
     * @cfg {Docs.view.examples.InlineToolbar} toolbar
     * The toolbar with buttons that controls this component.
     */

    initComponent: function() {
        this.options = Ext.apply({
            device: "phone",
@@ -79,7 +57,14 @@ Ext.define('Docs.view.examples.Inline', {
            })
        ];

        this.activeItem = this.options.preview ? 1 : 0;
        if (this.options.preview) {
            this.activeItem = 1;
            this.toolbar.activateButton("preview");
        }
        else {
            this.activeItem = 0;
            this.toolbar.activateButton("code");
        }

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

@@ -93,6 +78,22 @@ Ext.define('Docs.view.examples.Inline', {
            this.showPreview();
        }
        this.updateHeight();
        this.initToolbarEvents();
    },

    initToolbarEvents: function() {
        this.toolbar.on("buttonclick", function(name) {
            if (name === "code") {
                this.showCode();
            }
            else if (name === "preview") {
                this.showPreview();
            }
            else if (name === "copy") {
                this.showCode();
                this.editor.selectAll();
            }
        }, this);
    },

    /**
@@ -101,6 +102,10 @@ Ext.define('Docs.view.examples.Inline', {
    showCode: function() {
        this.layout.setActiveItem(0);
        this.updateHeight();
        this.toolbar.activateButton("code");
        // Weird bug on CodeMirror requires 2 refreshes...
        this.editor.refresh();
        this.editor.refresh();
    },

    /**
@@ -110,6 +115,7 @@ Ext.define('Docs.view.examples.Inline', {
        this.preview.update(this.editor.getValue());
        this.layout.setActiveItem(1);
        this.updateHeight();
        this.toolbar.activateButton("preview");
    },

    // Syncs the height with number of lines in code example.
+1 −2
Original line number Diff line number Diff line
@@ -3,10 +3,9 @@
 */
Ext.define('Docs.view.examples.InlineEditor', {
    extend: 'Ext.Panel',
    style: 'border: 0',
    bodyPadding: 2,
    bodyStyle: 'background: #f7f7f7',
    autoScroll: true,
    componentCls: 'inline-example-editor',

    initComponent: function() {
        this.addEvents(
+63 −0
Original line number Diff line number Diff line
/**
 * Toolbar for inline examples.
 */
Ext.define('Docs.view.examples.InlineToolbar', {
    extend: 'Ext.toolbar.Toolbar',
    componentCls: 'inline-example-tb',
    height: 30,

    initComponent: function() {
        this.addEvents(
            /**
             * @event
             * Fired when a button on toolbar clicked.
             * @param {String} name  Name of the button.
             * Possible values: "code", "preview", "copy"
             */
            "buttonclick"
        );

        this.items = [
            {
                iconCls: 'code',
                padding: '0 2 0 0',
                margin: '0 3 0 0',
                text: 'Code Editor',
                handler: this.createEventFirerer("code")
            },
            {
                padding: 0,
                margin: '0 3 0 0',
                iconCls: 'preview',
                text: 'Live Preview',
                handler: this.createEventFirerer("preview")
            },
            "->",
            {
                padding: 0,
                margin: 0,
                iconCls: 'copy',
                text: 'Select Code',
                handler: this.createEventFirerer("copy")
            }
        ];

        this.callParent(arguments);
    },

    createEventFirerer: function(name) {
        return Ext.Function.bind(function() {
            this.fireEvent("buttonclick", name);
        }, this);
    },

    activateButton: function(name) {
        Ext.Array.each(this.query('button'), function(b) {
            b.removeCls('active');
        });
        Ext.Array.each(this.query('button[iconCls=' + name + ']'), function(b) {
            b.addCls('active');
        });
    }

});
Loading