1. #1
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,498
    Vote Rating
    46
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default A Field class which does not have to be rendered in a FormLayout

    A Field class which does not have to be rendered in a FormLayout


    This extension to Ext.form.Field wraps itself in all the correct DOM elements, and creates its label regardless of what layout it is in.

    It hides the whole thing on hide, and clean up after itself on destroy.

    So no need for extra form layout Containers just to get Fields renderning properly.

    Code:
    Ext.ux.SelfLabelingTextField = Ext.extend(Ext.form.TextField, {
    
        margins: '0 0 5 0', // to keep things right when using Box layouts
    
        actionMode: 'itemCt',
    
        onRender: function() {
            Ext.ux.SelfLabelingTextField.superclass.onRender.apply(this, arguments);
            this.resizeEl = this.el.wrap({
                cls: 'x-form-element'
            });
            this.positionEl = this.itemCt = this.resizeEl.wrap({
                cls: 'x-form-item '
            });
    
    //      If we are hiding labels, then we're done!
            if (!Ext.isDefined(this.hideLabels)) {
                this.hideLabels = this.getParentProperty("hideLabels");
            }
            if (this.hideLabels) {
                this.resizeEl.setStyle('padding-left', '0px');
                return;
            }
    
    //      Collect info we need to render the label.
            if (!Ext.isDefined(this.labelWidth)) {
                this.labelWidth = this.getParentProperty("labelWidth") || 100;
            }
            if (!Ext.isDefined(this.labelSeparator)) {
                this.labelSeparator = this.getParentProperty("labelSeparator");
            }
            if (!Ext.isDefined(this.labelPad)) {
                this.labelPad = this.getParentProperty("labelPad");
            }
            this.resizeEl.setStyle('padding-left', (this.labelWidth + (this.labelPad || 5)) + 'px');
            this.itemCt.insertFirst({
                tag: 'label',
                cls: 'x-form-item-label',
                style: {
                    width: this.labelWidth + 'px'
                },
                html: this.fieldLabel + (this.labelSeparator || ':')
            });
        },
    
    //  private
    //  Pulls a named property down from the first ancestor Container it's found in
        getParentProperty: function(propName) {
            for (var p = this.ownerCt; p; p = p.ownerCt) {
                if (p[propName]) {
                    return p[propName];
                }
            }
        },
    
    //  private
    //  Ensure the input field is sized to fit in the content area of the resizeEl (to the right of its padding-left)
        onResize: function() {
            Ext.ux.SelfLabelingTextField.superclass.onResize.apply(this, arguments);
            this.el.setWidth(this.resizeEl.getWidth(true));
        },
    
    //  private
    //  Ensure that we clean up on destroy.
        onDestroy: function() {
            Ext.ux.SelfLabelingTextField.superclass.onDestroy.apply(this, arguments);
            this.itemCt.remove();
        }
    });
    Ext.reg('selfLabelingTextfield', Ext.ux.SelfLabelingTextField);

  2. #2
    Sencha - Community Support Team SamuraiJack1's Avatar
    Join Date
    May 2008
    Posts
    550
    Vote Rating
    3
    SamuraiJack1 will become famous soon enough

      0  

    Default


    At last.. A long awaited extension.

  3. #3
    Sencha - Community Support Team Condor's Avatar
    Join Date
    Mar 2007
    Location
    The Netherlands
    Posts
    24,246
    Vote Rating
    87
    Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of

      0  

    Default


    Could be useful, but you should rewrite this as a plugin so you don't have to create a descendant for every field class you want to use.

  4. #4
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,498
    Vote Rating
    46
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Quote Originally Posted by Condor View Post
    Could be useful, but you should rewrite this as a plugin so you don't have to create a descendant for every field class you want to use.
    Yes, I'll look into that. It leaves TriggerFields high and dry.

    I was doing this at the same time as I was doing my self replicating Field.

    For the same example in fact. I'm getting togeter a vbox example with a self replicating "To" field. The vbox layout automatically manages the height of the mail body regardless of how many input fields there are above it. The current anchoring.js demo uses a "magic number" to anchor the body in a fixed position.

    Mailto fields are often TriggerFields, so this will be essential I think.

  5. #5
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,498
    Vote Rating
    46
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Here:

    Code:
    Ext.ux.FieldLabeller = (function(){
    
    //  Pulls a named property down from the first ancestor Container it's found in
        function getParentProperty(propName) {
            for (var p = this.ownerCt; p; p = p.ownerCt) {
                if (p[propName]) {
                    return p[propName];
                }
            }
        }
    
        return {
    
    //      Add behaviour at important points in the Field's lifecycle.
            init: function(f) {
                f.onRender = f.onRender.createSequence(this.onRender);
                f.onResize = f.onResize.createSequence(this.onResize);
                f.onDestroy = f.onDestroy.createSequence(this.onDestroy);
            },
        
            onRender: function() {
    //          Do nothing if being rendered by a form layout
                if (this.ownerCt) {
                	if (this.ownerCt.layout instanceof Ext.layout.FormLayout) {
                    	return;
                    }
                    if (this.nextSibling()) {
    		            this.margins = '0 0 5 0';
                    }
                }
    
                this.resizeEl = this.el.wrap({
                    cls: 'x-form-element'
                });
                this.positionEl = this.itemCt = this.resizeEl.wrap({
                    cls: 'x-form-item '
                });
                this.actionMode = 'itemCt';
        
    //          If we are hiding labels, then we're done!
                if (!Ext.isDefined(this.hideLabels)) {
                    this.hideLabels = getParentProperty.call(this, "hideLabels");
                }
                if (this.hideLabels) {
                    this.resizeEl.setStyle('padding-left', '0px');
                    return;
                }
        
    //          Collect info we need to render the label.
                if (!Ext.isDefined(this.labelWidth)) {
                    this.labelWidth = getParentProperty.call(this, "labelWidth") || 100;
                }
                if (!Ext.isDefined(this.labelSeparator)) {
                    this.labelSeparator = getParentProperty.call(this, "labelSeparator");
                }
                if (!Ext.isDefined(this.labelPad)) {
                    this.labelPad = getParentProperty.call(this, "labelPad");
                }
                if (!Ext.isDefined(this.labelAlign)) {
                    this.labelAlign = getParentProperty.call(this, "labelAlign") || 'left';
                }
                this.itemCt.addClass('x-form-label-' + this.labelAlign);
    
                if(this.labelAlign == 'top'){
                    this.labelWidth = 'auto';
                    this.resizeEl.setStyle('padding-left', '0px');
                } else {
                    this.labelWidth += 'px';
                    this.resizeEl.setStyle('padding-left', (this.labelWidth + (this.labelPad || 5)) + 'px');
                }
    
                this.label = this.itemCt.insertFirst({
                    tag: 'label',
                    cls: 'x-form-item-label',
                    style: {
                        width: this.labelWidth
                    },
                    html: this.fieldLabel + (this.labelSeparator || ':')
                });
            },
        
    //      private
    //      Ensure the input field is sized to fit in the content area of the resizeEl (to the right of its padding-left)
            onResize: function() {
                this.el.setWidth(this.resizeEl.getWidth(true));
                if (this.el.dom.tagName.toLowerCase() == 'textarea') {
                    var h = this.resizeEl.getHeight(true);
                    if (this.labelAlign == 'top') {
                    	h -= this.label.getHeight();
                    }
                    this.el.setHeight(h);
                }
            },
    
    //      private
    //      Ensure that we clean up on destroy.
            onDestroy: function() {
                this.itemCt.remove();
            }
        };
    })();

  6. #6
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,498
    Vote Rating
    46
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Drop the following file into examples/form as vbox-form.html

    It's a nice demo of plugin code and vbox behaviour.

    I'm going to suggest it be added to SVN as an example.

    Code:
    <html>
    <head>
        <title>Vbox</title>
        <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css"/>
    
        <!-- GC -->
        <!-- LIBS -->
        <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
        <!-- ENDLIBS -->
    
        <script type="text/javascript" src="../../ext-all-debug.js"></script>
    
        <script type="text/javascript" src="vbox-form.js"></script>
        <link rel="stylesheet" type="text/css" href="forms.css"/>
    
        <!-- Common Styles for the examples -->
        <link rel="stylesheet" type="text/css" href="../shared/examples.css"/>
    </head>
    <body>
    <script type="text/javascript" src="../shared/examples.js"></script>
    <!-- EXAMPLES -->
    <h1>vbox Layout with Forms</h1>
    <p>The <code><b>align:'stretch'</b></code> config of the vbox layout manager ensures
    all child items are 100% of the container width.</p>
    <p>The <code><b>flex</b></code> config of child items of a vbox layout specifies what share of the vertical
    space to allocate for that child item.</p>
    <p>The js is not minified so it is readable. See <a href="vbox-form.js">vbox-form.js</a>.</p>
    </body>
    </html>
    with this as vbox-form.js:

    Code:
    Ext.Container.prototype.bufferResize = false;
    
    Ext.ux.FieldLabeller = (function(){
    
    //  Pulls a named property down from the first ancestor Container it's found in
        function getParentProperty(propName) {
            for (var p = this.ownerCt; p; p = p.ownerCt) {
                if (p[propName]) {
                    return p[propName];
                }
            }
        }
    
        return {
    
    //      Add behaviour at important points in the Field's lifecycle.
            init: function(f) {
                f.onRender = f.onRender.createSequence(this.onRender);
                f.onResize = f.onResize.createSequence(this.onResize);
                f.onDestroy = f.onDestroy.createSequence(this.onDestroy);
            },
        
            onRender: function() {
    //          Do nothing if being rendered by a form layout
                if (this.ownerCt) {
                	if (this.ownerCt.layout instanceof Ext.layout.FormLayout) {
                    	return;
                    }
                    if (this.nextSibling()) {
    		            this.margins = '0 0 5 0';
                    }
                }
    
                this.resizeEl = this.el.wrap({
                    cls: 'x-form-element'
                });
                this.positionEl = this.itemCt = this.resizeEl.wrap({
                    cls: 'x-form-item '
                });
                this.actionMode = 'itemCt';
        
    //          If we are hiding labels, then we're done!
                if (!Ext.isDefined(this.hideLabels)) {
                    this.hideLabels = getParentProperty.call(this, "hideLabels");
                }
                if (this.hideLabels) {
                    this.resizeEl.setStyle('padding-left', '0px');
                    return;
                }
        
    //          Collect info we need to render the label.
                if (!Ext.isDefined(this.labelWidth)) {
                    this.labelWidth = getParentProperty.call(this, "labelWidth") || 100;
                }
                if (!Ext.isDefined(this.labelSeparator)) {
                    this.labelSeparator = getParentProperty.call(this, "labelSeparator");
                }
                if (!Ext.isDefined(this.labelPad)) {
                    this.labelPad = getParentProperty.call(this, "labelPad");
                }
                if (!Ext.isDefined(this.labelAlign)) {
                    this.labelAlign = getParentProperty.call(this, "labelAlign") || 'left';
                }
                this.itemCt.addClass('x-form-label-' + this.labelAlign);
    
                if(this.labelAlign == 'top'){
                    this.labelWidth = 'auto';
                    this.resizeEl.setStyle('padding-left', '0px');
                } else {
                    this.labelWidth += 'px';
                    this.resizeEl.setStyle('padding-left', (this.labelWidth + (this.labelPad || 5)) + 'px');
                }
    
                this.label = this.itemCt.insertFirst({
                    tag: 'label',
                    cls: 'x-form-item-label',
                    style: {
                        width: this.labelWidth
                    },
                    html: this.fieldLabel + (this.labelSeparator || ':')
                });
            },
        
    //      private
    //      Ensure the input field is sized to fit in the content area of the resizeEl (to the right of its padding-left)
            onResize: function() {
                this.el.setWidth(this.resizeEl.getWidth(true));
                if (this.el.dom.tagName.toLowerCase() == 'textarea') {
                    var h = this.resizeEl.getHeight(true);
                    if (this.labelAlign == 'top') {
                    	h -= this.label.getHeight();
                    }
                    this.el.setHeight(h);
                }
            },
    
    //      private
    //      Ensure that we clean up on destroy.
            onDestroy: function() {
                this.itemCt.remove();
            }
        };
    })();
    
    Ext.ux.FieldReplicator = {
        init: function(f) {
            f.replicator = this;
            f.enableKeyEvents = true;
            f.on('change', this.onChange, this);
            f.onKeyDown = f.onKeyDown.createInterceptor(this.onKeyDown);
        },
    
    //  If tabbing out and the change event will be fired, flag that
    //  the change handler must focus the correct sibling Field.
        onKeyDown: function(e) {
            if ((e.getKey() == Ext.EventObject.TAB) && (String(this.startValue) !== String(this.getValue()))) {
            	if (e.shiftKey) {
    	            this.focusPrev = true;
            	} else {
    	            this.focusNext = true;
    	        }
            }
        },
    
    //  Handle the field either being changed to blank or from blank.
        onChange: function(f, n, o) {
            var c = f.ownerCt, l,
                ps = f.previousSibling(),
                ns = f.nextSibling();
            if (Ext.isEmpty(n)) {
                if (!Ext.isEmpty(o)) {
    //              The Field has been blanked, and it is not the only one left, remove it
                    if ((ps && (ps.replicator === this)) || (ns && (ns.replicator === this))) {
                        l = f.findParentBy(function(p) {
                            return !Ext.isDefined(p.ownerCt);
                        });
                        c.remove(f);
                        l.doLayout();
                    }
                }
            } else {
                if (Ext.isEmpty(o)) {
    //              Field filled, insert a clone as the next sibling
                    ns = new f.constructor(f.cloneConfig());
                    c.insert(c.items.indexOf(f) + 1, ns);
                    c.doLayout();
                    l = f.findParentBy(function(p) {
                        return !Ext.isDefined(p.ownerCt);
                    });
                    l.doLayout();
                }
            }
            if (f.focusPrev) {
                delete f.focusPrev;
                ps.focus(false, true);
            } else  if (f.focusNext) {
                delete f.focusNext;
                ns.focus(false, true);
            }
        }
    };
    
    Ext.onReady(function() {
        var form = new Ext.form.FormPanel({
            baseCls: 'x-plain',
            labelWidth: 55,
            url:'save-form.php',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            defaults: {
                xtype: 'textfield',
                anchor: '100%'  // anchor width by percentage
            },
    
            items: [{
                plugins: [ Ext.ux.FieldReplicator, Ext.ux.FieldLabeller ],
                fieldLabel: 'Send To',
                name: 'to'
            },{
                plugins: [ Ext.ux.FieldLabeller ],
                fieldLabel: 'Subject',
                name: 'subject'
            }, {
                plugins: [ Ext.ux.FieldLabeller ],
                xtype: 'textarea',
                labelAlign: 'top',
                fieldLabel: 'Message text',
                hideLabel: true,
                name: 'msg',
                flex: 1
            }]
        });
    
        var window = new Ext.Window({
            title: 'Resize Me',
            width: 500,
            height: 300,
            minWidth: 300,
            minHeight: 200,
            layout: 'fit',
            plain: true,
            bodyStyle: 'padding:5px;',
            buttonAlign: 'center',
            items: form,
            buttons: [{
                text: 'Send'
            },{
                text: 'Cancel'
            }]
        });
        window.show();
    });

  7. #7
    Sencha - Community Support Team Condor's Avatar
    Join Date
    Mar 2007
    Location
    The Netherlands
    Posts
    24,246
    Vote Rating
    87
    Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of

      0  

    Default


    Nice, but you are completely ignoring the labelAlign setting.

  8. #8
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,498
    Vote Rating
    46
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    <grumble...>

    The impossible we do at once, miracles take a little longer...



    I'll see what I can come up with.

  9. #9
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,498
    Vote Rating
    46
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    OK, try this:

    Code:
    Ext.Container.prototype.bufferResize = false;
    
    Ext.ux.FieldLabeller = (function(){
    
    //  Pulls a named property down from the first ancestor Container it's found in
        function getParentProperty(propName) {
            for (var p = this.ownerCt; p; p = p.ownerCt) {
                if (p[propName]) {
                    return p[propName];
                }
            }
        }
    
        return {
    
    //      Add behaviour at important points in the Field's lifecycle.
            init: function(f) {
                f.onRender = f.onRender.createSequence(this.onRender);
                f.onResize = f.onResize.createSequence(this.onResize);
                f.onDestroy = f.onDestroy.createSequence(this.onDestroy);
            },
        
            onRender: function() {
    //          Do nothing if being rendered by a form layout
                if (this.ownerCt) {
                	if (this.ownerCt.layout instanceof Ext.layout.FormLayout) {
                    	return;
                    }
                    if (this.nextSibling()) {
    		            this.margins = '0 0 5 0';
                    }
                }
    
                this.resizeEl = this.el.wrap({
                    cls: 'x-form-element'
                });
                this.positionEl = this.itemCt = this.resizeEl.wrap({
                    cls: 'x-form-item '
                });
                this.actionMode = 'itemCt';
        
    //          If we are hiding labels, then we're done!
                if (!Ext.isDefined(this.hideLabels)) {
                    this.hideLabels = getParentProperty.call(this, "hideLabels");
                }
                if (this.hideLabels) {
                    this.resizeEl.setStyle('padding-left', '0px');
                    return;
                }
        
    //          Collect info we need to render the label.
                if (!Ext.isDefined(this.labelWidth)) {
                    this.labelWidth = getParentProperty.call(this, "labelWidth") || 100;
                }
                if (!Ext.isDefined(this.labelSeparator)) {
                    this.labelSeparator = getParentProperty.call(this, "labelSeparator");
                }
                if (!Ext.isDefined(this.labelPad)) {
                    this.labelPad = getParentProperty.call(this, "labelPad");
                }
                if (!Ext.isDefined(this.labelAlign)) {
                    this.labelAlign = getParentProperty.call(this, "labelAlign") || 'left';
                }
                this.itemCt.addClass('x-form-label-' + this.labelAlign);
    
                if(this.labelAlign == 'top'){
                    this.labelWidth = 'auto';
                    this.resizeEl.setStyle('padding-left', '0px');
                } else {
                    this.labelWidth += 'px';
                    this.resizeEl.setStyle('padding-left', (this.labelWidth + (this.labelPad || 5)) + 'px');
                }
    
                this.label = this.itemCt.insertFirst({
                    tag: 'label',
                    cls: 'x-form-item-label',
                    style: {
                        width: this.labelWidth
                    },
                    html: this.fieldLabel + (this.labelSeparator || ':')
                });
            },
        
    //      private
    //      Ensure the input field is sized to fit in the content area of the resizeEl (to the right of its padding-left)
            onResize: function() {
                this.el.setWidth(this.resizeEl.getWidth(true));
                if (this.el.dom.tagName.toLowerCase() == 'textarea') {
                    var h = this.resizeEl.getHeight(true);
                    if (this.labelAlign == 'top') {
                    	h -= this.label.getHeight();
                    }
                    this.el.setHeight(h);
                }
            },
    
    //      private
    //      Ensure that we clean up on destroy.
            onDestroy: function() {
                this.itemCt.remove();
            }
        };
    })();
    
    Ext.ux.FieldReplicator = {
        init: function(f) {
            f.replicator = this;
            f.enableKeyEvents = true;
            f.on('change', this.onChange, this);
            f.onKeyDown = f.onKeyDown.createInterceptor(this.onKeyDown);
        },
    
    //  If tabbing out and the change event will be fired, flag that
    //  the change handler must focus whatever Field ends up as the nextSibling.
        onKeyDown: function(e) {
            if ((e.getKey() == Ext.EventObject.TAB) && !e.shiftKey && (String(this.startValue) !== String(this.getValue()))) {
                this.focusNext = true;
            }
        },
    
    //  Handle the field either being changed to blank or from blank.
        onChange: function(f, n, o) {
            var c = f.ownerCt, l,
                ps = f.previousSibling(),
                ns = f.nextSibling();
            if (Ext.isEmpty(n)) {
                if (!Ext.isEmpty(o)) {
    //              The Field has been blanked, and it is not the only one left, remove it
                    if ((ps && (ps.replicator === this)) || (ns && (ns.replicator === this))) {
                        l = f.findParentBy(function(p) {
                            return !Ext.isDefined(p.ownerCt);
                        });
                        c.remove(f);
                        l.doLayout();
                    }
                }
            } else {
                if (Ext.isEmpty(o)) {
    //              Field filled, insert a clone as the next sibling
                    ns = new f.constructor(f.cloneConfig());
                    c.insert(c.items.indexOf(f) + 1, ns);
                    c.doLayout();
                    l = f.findParentBy(function(p) {
                        return !Ext.isDefined(p.ownerCt);
                    });
                    l.doLayout();
                }
            }
            if (f.focusNext) {
                delete f.focusNext;
                ns.focus(false, true);
            }
        }
    };
    
    Ext.onReady(function() {
        var form = new Ext.form.FormPanel({
            baseCls: 'x-plain',
            labelWidth: 55,
            url:'save-form.php',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            defaults: {
                xtype: 'textfield',
                anchor: '100%'  // anchor width by percentage
            },
    
            items: [{
                plugins: [ Ext.ux.FieldReplicator, Ext.ux.FieldLabeller ],
                fieldLabel: 'Send To',
                name: 'to'
            },{
                plugins: [ Ext.ux.FieldLabeller ],
                fieldLabel: 'Subject',
                name: 'subject'
            }, {
                plugins: [ Ext.ux.FieldLabeller ],
                xtype: 'textarea',
                labelAlign: 'top',
                fieldLabel: 'Message text',
                hideLabel: true,
                name: 'msg',
                flex: 1
            }]
        });
    
        var window = new Ext.Window({
            title: 'Resize Me',
            width: 500,
            height: 300,
            minWidth: 300,
            minHeight: 200,
            layout: 'fit',
            plain: true,
            bodyStyle: 'padding:5px;',
            buttonAlign: 'center',
            items: form,
            buttons: [{
                text: 'Send'
            },{
                text: 'Cancel'
            }]
        });
        window.show();
    });

Thread Participants: 2

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..."