| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112 | //{"duration":8,"time":"2012-02-25T10:55:01","success":false,"cycleCount":6,"flushCount":5,"calcCount":7,"orphans":0,"layouts":[{"allDone":true,"done":true,"id":"autocomponent-1193","type":"autocomponent","name":"headercontainer-1115<autocomponent>","blocks":[],"boxParent":null,"isBoxParent":null,"triggers":[],"orphan":false,"heightModel":"configured","widthModel":"calculated","children":[],"duration":0,"totalTime":0,"count":1},{"allDone":false,"done":false,"id":"gridcolumn-1194","type":"gridcolumn","name":"headercontainer-1115<gridcolumn>","blocks":[],"boxParent":null,"isBoxParent":null,"triggers":[{"name":"gridview-1118.height","prop":"height","value":null,"dirty":false,"missing":true,"setBy":"??"},{"name":"gridcolumn-1116.height","prop":"height","value":22,"dirty":false,"missing":false,"setBy":"gridcolumn-1116<columncomponent>"},{"name":"headercontainer-1115.contentWidth","prop":"contentWidth","value":335,"dirty":false,"missing":false,"setBy":"headercontainer-1115<gridcolumn>"},{"name":"headercontainer-1115.height","prop":"height","value":0,"dirty":false,"missing":false,"setBy":"headercontainer-1115<autocomponent>"},{"name":"headercontainer-1115.width","prop":"width","value":335,"dirty":false,"missing":false,"setBy":"headercontainer-1115<autocomponent>"},{"name":"numbercolumn-1117.height","prop":"height","value":22,"dirty":false,"missing":false,"setBy":"numbercolumn-1117<columncomponent>"}],"orphan":false,"heightModel":"configured","widthModel":"calculated","children":[{"allDone":true,"done":true,"id":"columncomponent-1195","type":"columncomponent","name":"gridcolumn-1116<columncomponent>","blocks":[],"boxParent":null,"isBoxParent":true,"triggers":[{"name":"gridcolumn-1116.containerChildrenDone:dom","prop":"containerChildrenDone","value":true,"dirty":false,"missing":false,"setBy":"??"},{"name":"gridcolumn-1116.width:dom","prop":"width","value":168,"dirty":false,"missing":false,"setBy":"headercontainer-1115<gridcolumn>"}],"orphan":false,"heightModel":"shrinkWrap (calculatedFromShrinkWrap)","widthModel":"calculated","children":[],"duration":0,"totalTime":0,"count":2},{"allDone":true,"done":true,"id":"columncomponent-1197","type":"columncomponent","name":"numbercolumn-1117<columncomponent>","blocks":[],"boxParent":null,"isBoxParent":true,"triggers":[{"name":"numbercolumn-1117.containerChildrenDone:dom","prop":"containerChildrenDone","value":true,"dirty":false,"missing":false,"setBy":"??"},{"name":"numbercolumn-1117.width:dom","prop":"width","value":167,"dirty":false,"missing":false,"setBy":"headercontainer-1115<gridcolumn>"}],"orphan":false,"heightModel":"shrinkWrap (calculatedFromShrinkWrap)","widthModel":"calculated","children":[],"duration":2,"totalTime":2,"count":2}],"duration":4,"totalTime":6,"count":2}],"statsById":{"columncomponent-1195":{"duration":0,"count":2},"columncomponent-1197":{"duration":2,"count":2},"autocomponent-1193":{"duration":0,"count":1},"gridcolumn-1194":{"duration":4,"count":2}},"statsByType":{"columncomponent":{"duration":2,"layoutCount":2,"count":4},"autocomponent":{"duration":0,"layoutCount":1,"count":1},"gridcolumn":{"duration":4,"layoutCount":1,"count":2}},"flushTime":1,"flushInvalidateTime":1,"flushInvalidateCount":1,"flushLayoutStats":{"completeLayout":{"count":2,"time":0}},"totalTime":8,"num":5}Ext.Loader.setConfig({    enabled: true});Ext.Loader.setPath({    'Ext.ux': '../ux/',    'PageAnalyzer': './'});Ext.require([    'Ext.data.*',    'Ext.tree.*',    'Ext.container.Viewport',    'Ext.layout.container.Border',    'Ext.History',    'Ext.tab.Panel',    'Ext.grid.column.Action',    'Ext.form.field.TextArea',    'Ext.form.field.Number',    'Ext.toolbar.TextItem',    'Ext.layout.container.Table',    'PageAnalyzer.models.LayoutTreeNode',    'PageAnalyzer.models.ComponentTreeNode',    'PageAnalyzer.Console',    'PageAnalyzer.Summary',    'Ext.ux.IFrame',    'Ext.state.Manager',    'Ext.state.CookieProvider']);Ext.define('PageAnalyzer.MainForm', {    statsGatherCount: 0,    layoutTpl: [        '<tpl if="isBoxParent">',            '<img class="x-tree-icon" src="resources/images/boxParent.gif">',        '</tpl>',        '{name:this.encode}',        {            encode: function (value) {                return Ext.htmlEncode(value);            }        }    ],    runTpl: [        'Run #{num} ({time:this.date})',        {            date: function (value) {                return Ext.Date.format(value, "Y-m-d H:i:s");            }        }    ],    triggerTpl: [        '<div class="pgan-{[values.missing ? "missing" : "available"]}-value">',            '{name} (={[String(values.value) || "?"]}) - dirty: {dirty} - setBy: {setBy:this.encode}',        '</div>',        {            encode: function (value) {                return Ext.htmlEncode(value);            }        }    ],    constructor: function (config) {        Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));        var me = this;        Ext.apply(me, config);        me.noCharts = me.getOption('nocharts');        me.runNumber = 0;        me.viewport = Ext.widget(me.createViewport());        me.target = me.targetFrame.getWin();        me.reloadBtn = me.viewport.down('#reloadBtn');        me.stateText = me.viewport.down('#stateText');        if (me.target) {            setInterval(function() {                me.updateConnectedState();            }, 100);        } else {            me.reloadBtn.setDisabled(true);        }        Ext.History.init(function () {            Ext.History.on({                change: 'onHistoryChange',                scope: me            });            me.onHistoryChange(Ext.History.getToken());        });    },    roundTimestamp: function(num) {        return Math.round(num * 100) / 100;    },    createLayoutTree: function() {        var me = this,            store = new Ext.data.TreeStore({                proxy: 'memory',                model: 'PageAnalyzer.models.LayoutTreeNode'            }),            tree = {                xtype: 'treepanel',                store: store,                rootVisible: false,                useArrows: true,                title: 'Layouts',                region: 'center',                viewConfig: {                    getRowClass: function (record) {                        return 'pgan-' + record.data.type;                    }                },                columns: [                    {                        xtype: 'treecolumn',                        text: 'Layout',                        flex: 1,                        hideable: false,                        draggable: false,                        dataIndex: 'text'                    },                    {                        text: 'Triggers',                        width: 200,                        dataIndex: 'triggers'                    },                    {                        text: 'Blocks',                        width: 125,                        hidden: true,                        dataIndex: 'blocks',                        id: 'blocksCol'                    },                    {                        text: 'Width',                        width: 90,                        dataIndex: 'widthModel'                    },                    {                        text: 'Height',                        width: 90,                        dataIndex: 'heightModel'                    },                    {                        text: 'Box Parent',                        width: 100,                        hidden: true,                        dataIndex: 'boxParent',                        id: 'boxParentCol'                    },                    {                        text: 'Time',                        width: 70,                        dataIndex: 'duration',                        id: 'durationCol',                        renderer: me.roundTimestamp                    },                    {                        text: 'Calls',                        width: 50,                        dataIndex: 'count',                        id: 'countCol'                    },                    {                        text: 'Avg Time',                        width: 70,                        id: 'avgCol',                        renderer: function(value, metadata, rec) {                            return me.roundTimestamp(rec.data.duration / rec.data.count);                        }                    },                    {                        text: 'Tot Time',                        width: 70,                        dataIndex: 'totalTime',                        id: 'totalTimeCol',                        renderer: me.roundTimestamp                    },                    {                        menuDisabled: true,                        sortable: false,                        xtype: 'actioncolumn',                        hideable: false,                        width: 40,                        items: [{                            icon: 'resources/images/delete.gif',                            iconCls: 'pgan-delete-row',                            tooltip: 'Delete this run',                            handler: this.onDeleteLayoutRun,                            scope: this                        }, {                            icon: 'resources/images/info.gif',                            iconCls: 'pgan-show-row-data',                            tooltip: 'Show raw data for this run',                            handler: this.onShowLayoutRunRawData,                            scope: this                        }]                    }                ]            };        this.layoutTree = Ext.widget(tree);        this.layoutTree.getSelectionModel().on({            selectionchange: this.onLayoutSelectionChange,            scope: this        });        return this.layoutTree;    },    createComponentTree: function() {        var me = this,            store = new Ext.data.TreeStore({                proxy: 'memory',                model: 'PageAnalyzer.models.ComponentTreeNode'            }),            compTree = {                xtype: 'treepanel',                store: store,                rootVisible: false,                useArrows: true,                title: 'Components',                region: 'center',                viewConfig: {                    getRowClass: function (record) {                        var data = record.data;                        if (data.isComponent) {                           return 'pgan-component';                        } else {                           return 'pgan-noncomponent';                        }                    }                },                columns: [                    {                        xtype: 'treecolumn',                        text: 'Component',                        flex: 1,                        hideable: false,                        draggable: false,                        width: 450,                        dataIndex: 'text'                    },                    {                        text: 'Width',                        width: 90,                        hidden: true,                        dataIndex: 'width'                    },                    {                        text: 'Height',                        width: 90,                        hidden: true,                        dataIndex: 'height'                    },                    {                        text: 'X',                        width: 90,                        hidden: true,                        dataIndex: 'x'                    },                    {                        text: 'Y',                        width: 90,                        hidden: true,                        dataIndex: 'y'                    },                    {                        text: 'CSS Class',                        width: 100,                        dataIndex: 'cssClass',                        id: 'cssClass'                    },                    {                        text: 'XType',                        width: 100,                        dataIndex: 'xtype',                        id: 'xtypeCol'                    },                    {                        text: 'Rendered',                        width: 100,                        dataIndex: 'rendered',                        id: 'renderedCol',                        hidden: true                    },                    {                        text: 'Hidden',                        width: 100,                        dataIndex: 'hidden',                        id: 'hiddenCol',                        hidden: true                    },                    {                        text: 'IsContainer',                        width: 100,                        dataIndex: 'isContainer',                        id: 'isContainerCol',                        hidden: true                    },                    {                        menuDisabled: true,                        sortable: false,                        xtype: 'actioncolumn',                        hideable: false,                        width: 20,                        items: [{                            icon: 'resources/images/info.gif',                            iconCls: 'pgan-display-comp-spec',                            tooltip: 'Display Component Test Spec',                            handler: this.onDisplayLayoutSpec,                            scope: this                        }]                    }                ]            };        me.componentTree = Ext.widget(compTree);        return me.componentTree;    },    createPerfPanel: function() {        this.perfPanel = this.noCharts ? null : (Ext.widget({            xtype: 'panel',            title: 'Performance',            layout: 'fit',            border: false,            tbar: [                {                    text: 'Clear',                    handler: this.onClearStats,                    scope: this                }            ],            items: [                new PageAnalyzer.Console({                    itemId: 'perfcon'                })            ]        }));        return this.perfPanel;    },    createLayoutPanel: function() {        var me = this;        me.layoutPanel = Ext.widget({            xtype: 'panel',            title: 'Layout',            layout: 'border',            tbar: [                {                    text: 'Load Run',                    iconCls: 'pgan-load-run',                    handler: me.onLoadRun,                    scope: me                },                {                    text: 'Show All Triggers',                    enableToggle: true,                    handler: me.onShowAllTriggers,                    scope: me                },                {                    text: 'Clear',                    handler: me.onClearLayouts,                    scope: me                },                '->',                {                    text: 'Capture Layout Spec',                    handler: me.onDisplayLayoutSpec,                    scope: me                }            ],            items: [                me.createLayoutTree(),                this.typeSummary = (this.noCharts ? null : new PageAnalyzer.Summary({                    title: 'Summaries',                    region: 'south',                    height: '50%',                    collapsible: true,                    split: true                }))            ]        });        return me.layoutPanel;    },    createComponentPanel: function() {        var me = this;        me.componentPanel = Ext.widget({            xtype: 'panel',            title: 'Components',            layout: 'border',            tbar: [                {                    text: 'Generate Component Tree',                    handler: me.loadComponentTree,                    scope: me                }            ],            items: [                me.createComponentTree()            ]        });        return me.componentPanel;    },    createTestPagePanel: function() {        return this.targetFrame = Ext.create("Ext.ux.IFrame", {            title: 'Page Under Test',            hideMode: 'offsets'        });    },    createViewport: function() {        this.build = 1;        var me = this,            ret = {                xtype: 'viewport',                layout: 'fit',                items: [                {                    xtype: 'panel',                    layout: 'fit',                    tbar: {                        items: [                            {                                xtype: 'tbtext',                                itemId: 'stateText',                                tdAttrs: {                                    width: '100px'                                }                            },                            {                                xtype: 'tbtext',                                text: 'Test URL:',                                itemId: 'titleLbl',                                tdAttrs: {                                    width: '100px'                                }                            },                            me.targetUrlField = Ext.widget({                                xtype: 'textfield',                                itemId: 'targetUrl',                                stateId: 'targetUrlField',                                selectOnFocus: true,                                flex: 1,                                enableKeyEvents: true,                                listeners: {                                    keypress: function(f, e) {                                        if (e.getKey() === 13) {                                            me.onLoadPage();                                        }                                    }                                }                            }),                            {                                text: 'Load',                                itemId: 'reloadBtn',                                iconCls: 'pgan-refresh',                                handler: me.onLoadPage,                                scope: me,                                tdAttrs: {                                    width: '100px'                                }                            },                            me.noCharts ? null : {                                xtype: 'numberfield',                                fieldLabel: 'Build',                                style: 'margin-right: 10px;',                                labelWidth: 30,                                width: 100,                                value: me.build,                                listeners: {                                    change: function (field) {                                        me.build = field.getValue();                                    }                                }                            },                            me.noCharts ? null : {                                text: 'Update Stats',                                handler: me.onGatherStats,                                scope: me                            },                            me.noCharts ? null : {                                text: 'Reset',                                handler: this.onResetStats,                                scope: this                            }                        ]                    },                    items: [                        Ext.create('Ext.tab.Panel', {                            items:[                                me.createTestPagePanel(),                                me.createLayoutPanel(),                                me.createComponentPanel(),                                me.createPerfPanel()                            ]                        })                    ]                }            ]        };        return ret;    },    addLayoutChildren: function (parent, children) {        var n = children.length,            triggersTpl = Ext.XTemplate.getTpl(this, 'triggerTpl'),            textTpl = Ext.XTemplate.getTpl(this, 'layoutTpl'),            child, data, i, j, k, node, triggers;        for (i = 0; i < n; ++i) {            child = children[i];            triggers = [];            for (j = 0, k = child.triggers.length; j < k; ++j) {                triggers.push(triggersTpl.apply(child.triggers[j]));            }            data = {                text: textTpl.apply(child),                iconCls: 'pgan-layout' +                    (child.allDone ? '' : (child.done ? '-partial' : '-not')) + '-done',                leaf: !child.children.length,                triggers: triggers.join(''),                blocks: child.blocks.join('<br>'),                boxParent: child.boxParent,                isBoxParent: child.isBoxParent,                heightModel: child.heightModel,                widthModel: child.widthModel,                type: 'layout',                duration: child.duration,                totalTime: child.totalTime,                count: child.count            };            if (data.boxParent) {                this.showBoxParentCol = true;            }            if (data.blocks) {                this.showBlocksCol = true;            }            node = new PageAnalyzer.models.LayoutTreeNode(data);            parent.appendChild(node);            this.addLayoutChildren(node, child.children);        }    },    addLayoutRuns: function (run) {        if (typeof run == 'string') {            run = Ext.decode(run);        }        if (Ext.isArray(run)) {            Ext.each(run, this.addLayoutRuns, this);            return;        }        if (typeof run.time == 'string') {            run.time = Ext.Date.parse(run.time, "Y-m-d\\TH:i:s");        }        if (typeof run.duration == 'string') {            run.duration = parseInt(run.duration, 10);        }        //run.success = 0;        run.num = ++this.runNumber;        var node = new PageAnalyzer.models.LayoutTreeNode({            text: Ext.XTemplate.getTpl(this, 'runTpl').apply(run),            iconCls: 'pgan-' + (run.success ? 'good' : 'failed') + '-layout-run',            type: 'layoutrun',            duration: run.duration,            totalTime: run.totalTime,            count: 1        });        this.showBoxParentCol = this.showBlocksCol = false;        node.rawData = run;        node.appendChild(new PageAnalyzer.models.LayoutTreeNode({            text: 'Flush',            leaf: true,            duration: run.flushTime,            totalTime: run.flushTime,            count: run.flushCount        }));        node.appendChild(new PageAnalyzer.models.LayoutTreeNode({            text: 'Invalidate',            leaf: true,            duration: run.flushInvalidateTime,            totalTime: run.flushInvalidateTime,            count: run.flushInvalidateCount        }));        Ext.Object.each(run.flushLayoutStats, function(name, val) {            node.appendChild(new PageAnalyzer.models.LayoutTreeNode({                text: (name == 'notifyOwner')                    ? 'AfterLayout'                    : Ext.String.capitalize(name),                leaf: true,                duration: val.time,                totalTime: val.time,                count: val.count            }));        });        this.addLayoutChildren(node, run.layouts);        this.layoutTree.getRootNode().appendChild(node);        Ext.suspendLayouts();        if (this.showBoxParentCol) {            this.layoutTree.down('#boxParentCol').show();        }        if (this.showBlocksCol) {            this.layoutTree.down('#blocksCol').show();        }        Ext.resumeLayouts(true);    },    getOption: function (opt) {        var s = window.location.search;        var re = new RegExp('(?:^|[&?])' + opt + '(?:[=]([^&]*))?(?:$|[&])', 'i');        var m = re.exec(s);        return m ? (m[1] === undefined ? true : m[1]) : false;    },    onDeleteLayoutRun: function (view, recordIndex, cellIndex, item, e, record) {        record.parentNode.removeChild(record);    },    onHistoryChange: function (token) {        this.targetUrlField.setValue(token);    },    onLayoutSelectionChange: function(selModel, records) {        var run;        if (records.length) {            run = records[0];            while (run && run.data.type != 'layoutrun') {                run = run.parentNode;            }            this.typeSummary.loadTypeSummary(run.rawData.statsByType);        }    },    onShowLayoutRunRawData: function(view, recordIndex, cellIndex, item, e, record) {        var text = Ext.JSON.encodeValue(record.rawData, '\n');        Ext.widget({            xtype: 'window',            modal: true,            title: 'Raw data for ' + record.data.text,            //closeAction: 'close',            autoShow: true,            layout: 'fit',            width: 500,            height: 400,            defaultFocus: 'rawData',            items: [{                xtype: 'textarea',                value: text,                itemId: 'rawData',                readOnly: true,                selectOnFocus: true            }]        }).show();        //this.rawDataTextArea.setValue(text);    },    onLoadRun: function() {        var me = this;        var window = new Ext.Window({            title: 'Load Run',            width: 400,            height: 320,            layout: 'fit',            modal: true,            items: [{                xtype: 'textarea'            }],            buttons: [{                text: 'OK',                handler: function() {                    var text = window.down('textarea').getValue();                    window.destroy();                    me.addLayoutRuns(text);                }            }, {                text: 'cancel',                handler: function() {                    window.destroy();                }            }]        });        window.show();    },    getCompNodeForComp: function(comp, refName) {        return new PageAnalyzer.models.ComponentTreeNode({            text: comp.id + (comp.itemId ? ' (' + comp.itemId  + ')' : ''),            compId: comp.id || comp.itemId,            xtype: comp.xtype,            refName: refName || '',            rendered: comp.rendered,            hidden: comp.hidden,            isContainer: comp.isContainer,            isElement: false,            isComponent: true,            iconCls: 'pgan-' +                ((comp.rendered && !comp.hidden) ? 'rendered' : 'unrendered') +                (comp.isContainer ? '-container' : '-component')        });    },    getCompNodeForElem: function(el, root, refName) {        root = root ? root.el : el;        return new PageAnalyzer.models.ComponentTreeNode({            text: refName,            width: el.getWidth(),            height: el.getHeight(),            x: root ? (el.getX() - root.getX()) : el.getX(),            y: root ? (el.getY() - root.getY()) : el.getY(),            cssClass: el.dom ? el.dom.className : undefined,            refName: refName,            isContainer: false,            isComponent: false,            isElement: true,            hidden: !el.isVisible(true),            iconCls: el.isVisible(true) ? 'pgan-visible-element' : 'pgan-hidden-element'        });    },    getComponentTreeNodes: function(comps) {        var me = this,            compNodes = [],            refName = '';        if (!Ext.isArray(comps)) {            comps = [comps];        }        Ext.each(comps, function(comp) {            var container = comp.ownerCt,                node = me.getCompNodeForComp(comp, refName),                items = new PageAnalyzer.models.ComponentTreeNode({                    refName: 'items',                    iconCls: 'pgan-' + (comp.rendered ? 'rendered' : 'unrendered') + '-container',                    text: 'items',                    isComponent: false                }),                dockedItems = new PageAnalyzer.models.ComponentTreeNode({                    refName: 'dockedItems',                    iconCls: 'pgan-' + (comp.rendered ? 'rendered' : 'unrendered') + '-container',                    text: 'dockedItems',                    isComponent: false                }),                children;            node.comp = comp;            Ext.Object.each(comp, function(name, val){                if (name != 'container' &&                    name != 'renderTo' &&                    name != 'constrainTo' &&                    name != 'focusEl' &&                    val &&                    val.dom &&                    val.dom != me.target.document) {                    var child = me.getCompNodeForElem(val, container, name);                    node.appendChild(child);                }            });            if (comp.items && comp.items.items && comp.items.items.length) {                children = me.getComponentTreeNodes(comp.items.items);                Ext.each(children, function(child) {                    items.appendChild(child);                });                node.appendChild(items);            }            if (comp.dockedItems && comp.dockedItems.items && comp.dockedItems.items.length) {                children = me.getComponentTreeNodes(comp.dockedItems.items);                Ext.each(children, function(child) {                    dockedItems.appendChild(child);                });                node.appendChild(dockedItems);            }            compNodes.push(node);        });        return compNodes;    },    loadComponentTree: function() {        var me = this,            all = me.getTopLevelComponents(),            nodes = me.getComponentTreeNodes(all),            root = me.componentTree.getRootNode();        root.removeAll();        Ext.each(nodes, function(node){            root.appendChild(node);        });    },    getTopLevelComponents: function () {        var me = this,            all = me.target.Ext.ComponentManager.all.getArray(),            top = [];        Ext.each(all, function(comp){            if(!comp.ownerCt) {                top.push(comp);            }        });        return top;    },    onDisplayLayoutSpec: function (view, recordIndex, cellIndex, item, e, record) {        var testSpec = record.getJasmineSpec(),            window = new Ext.Window({                title: 'Component Test Spec',                width: 400,                height: 320,                layout: 'fit',                modal: true,                maximizable: true,                items: [{                    xtype: 'textarea',                    value: testSpec,                    selectOnFocus: true                }],                buttons: [{                    text: 'OK',                    handler: function() {                        window.destroy();                    }                }]            });        window.show();    },    onClearLayouts: function() {        this.layoutTree.getRootNode().removeAll();    },    onShowAllTriggers: function (button) {        var comp = this.layoutTree;        if (button.pressed) {            comp.addCls('pgan-show-all-triggers');        } else {            comp.removeCls('pgan-show-all-triggers');        }        comp.updateLayout();    },    updateLayoutRuns: function() {        var me = this,            target = me.target,            runs = target._layoutRuns;        if (runs && runs.length) {            target._layoutRuns = [];            me.addLayoutRuns(runs);        }    },    onGatherStats: function() {        var me = this,            target = me.target,            perf = target.Ext.Perf,            con = me.viewport.down('#perfcon');        // Only gather page startup stats at each reload, not on each gather        if (!me.statsGatherCount) {            perf.get("Initialize").enter().leave(target.Ext._afterReadytime - target.Ext._beforeReadyTime);            if (target.Ext._endTime) {                perf.get("Load").enter().leave(target.Ext._endTime - target.Ext._startTime);                perf.get("WaitForReady").enter().leave(target.Ext._readyTime - target.Ext._endTime);            } else {                perf.get("BeforeReady").enter().leave(target.Ext._readyTime - target.Ext._startTime);            }        }        perf.updateGC();        me.statsGatherCount++;        var data = perf.getData(),            accCfg = perf.currentConfig;        con.addSample({            env: 'x',            build: me.build,            test: target.location.pathname,            data: data        });        if (accCfg) {            con.setAccumulators(accCfg);        }    },    onClearStats: function() {        this.viewport.down('#perfcon').clearSamples();        this.onResetStats();    },    onResetStats: function(){        this.target.Ext.Perf.reset();    },    getHrefMinusHash: function() {        var href = location.href.replace(Ext.History.getHash(), '');        return href;    },    //-------------------------------------------------------------------------    // Target page mgmt    states: {        // the target page has not loaded Ext        disconnected: {            text: 'Disconnected',            style: {                fontWeight: 'bold',                color: 'red'            }        },        // the target page is loaded and has Ext.isReady        loaded: {            text: 'Loaded',            style: {                fontWeight: 'bold',                color: 'orange'            }        },        // the target page is loading the layout hooks        hooking: {            text: 'Loading hooks',            style: {                fontWeight: 'bold',                color: 'yellow'            }        },        ready: {            text: 'Ready',            style: {                fontWeight: 'bold',                color: 'green'            }        }    },    getState: function() {        var states = this.states,            target = this.target;        if (target && target.Ext && target.Ext.isReady) {            if (target._layoutRuns && target.Ext._readyTime) {                return states.ready;            }            if (target._hooking) {                return states.hooking;            }            return states.loaded;        }        return states.disconnected;    },    injectScript: function (scriptSrc) {        var me = this,            url = me.getHrefMinusHash().replace(/\/[^/]+$/, '/' + scriptSrc),            target = me.targetFrame.getDoc(),            head = target.head || target.getElementsByTagName('head')[0];        var script = target.createElement('script');        script.src = url;        script.type = 'text/javascript';        head.appendChild(script);    },    injectHooks: function() {        var me = this,            target = me.target,            perfConsole = me.viewport.down('#perfcon'),            accumulatorConfigs = perfConsole && perfConsole.getAccumulators();        Ext.log('injecting script hooks');        target._hooking = 3;        if (accumulatorConfigs) {            target._accumulatorCfg = accumulatorConfigs;        }        me.injectScript('hooks.js');    },    onLoadPage: function() {        var me = this,            target = me.targetFrame,            doc = target.getDoc(),            targetUrl = me.targetUrlField.getValue();        if (targetUrl && targetUrl != '' && doc) {            // add a query parameter the target page url so it will pause at onReady so that            // we can inject our code and resume it to capture the initial layout run            // by setting a global override flag (in updateConnectedState):            Ext.log('resetting target document state');            me.target._layoutRuns = null;            me.target._syncComplete = false;            if (me.target.Ext) {                me.target.Ext._readyTime = 0;            }            me.reloading = true;            var hasPound = targetUrl.indexOf('#'),                hasQuest = targetUrl.indexOf('?') ,                qParm = (hasQuest > 0 ? '&' : '?') + 'ext-pauseReadyFire';            if (targetUrl != Ext.History.getToken()) {                Ext.History.add(targetUrl);            }            if (hasPound > 0) {                targetUrl = targetUrl.substring(0, hasPound) + qParm + targetUrl.substring(hasPound + 1);            } else {                targetUrl += qParm;            }            Ext.log('reloading target document');            me.targetFrame.load(targetUrl);            me.currUrl = targetUrl;            me.updateConnectedState();            me.statsGatherCount = 0;        } else {            me.targetFrame.load('about:blank');        }    },    updateConnectedState: function() {        var me = this,            states = me.states,            state = me.getState();        if (me.lastState != state) {            me.lastState = state;            me.stateText.el.setStyle(state.style);            me.stateText.setText(state.text);        }        if (state == states.loaded) {            me.injectHooks();        } else if (state == states.ready) {            if (me.reloading) {                Ext.log('firing ready event in target document');                me.reloading = false;                me.target.Ext._continueFireReady = true;                me.target.Ext.EventManager.readyEvent.fire();            }            me.updateLayoutRuns();        }    }});(function() {    function run () {        Ext.QuickTips.init();        new PageAnalyzer.MainForm({            targetHref: window.opener                ? window.opener.location.href                : null        });    }    Ext.onReady(run);})();
 |