1. #1
    Sencha User
    Join Date
    Jul 2007
    Location
    London
    Posts
    25
    Vote Rating
    0
    mattbennett is on a distinguished road

      0  

    Default [2.2] FileUploadField reset + proposed solution

    [2.2] FileUploadField reset + proposed solution


    Hi all,

    I have discovered that Ext.form.FileUploadField from the samples at [1] does not reset correctly when its parent form is reset. The FileUploadField does not define its own reset() function, and simply inherits one from Ext.form.TextField, meaning that the underlying <input type=file> remains unchanged. The upshot is that the 'change' event is not fired if you select the same file again after having reset the form.

    Below is a modified version of FileUploadForm which implements a reset() function. Since browsers do not allow the value of an <input type=file> element to be changed, the reset function removes the existing <input> and replaces it with an exact copy. This works in all the browsers I'm able to test (FF3, FF2, Safari3 & Opera9 on OS X, XP; IE6, IE7 on XP).

    In this example I've also added mouse listeners to the fileinput element, so that the fake icon button appears to represent the mouse actions.

    Changes from the original are in bold.

    Code:
    Ext.form.FileUploadField = Ext.extend(Ext.form.TextField,  {
    	/**
    	 * @cfg {String} buttonText The button text to display on the upload button (defaults to
    	 * 'Browse...').  Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
    	 * value will be used instead if available.
    	 */
    	buttonText: 'Browse...',
    	/**
    	 * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
    	 * text field (defaults to false).  If true, all inherited TextField members will still be available.
    	 */
    	buttonOnly: false,
    	/**
    	 * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
    	 * (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.
    	 */
    	buttonOffset: 3,
    	/**
    	 * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
    	 */
    
    	// private
    	readOnly: true,
    	
    	/**
    	 * @hide 
    	 * @method autoSize
    	 */
    	autoSize: Ext.emptyFn,
    	
    	// private
    	initComponent: function(){
    		Ext.form.FileUploadField.superclass.initComponent.call(this);
    		
    		this.addEvents(
    			/**
    			 * @event fileselected
    			 * Fires when the underlying file input field's value has changed from the user
    			 * selecting a new file from the system file selection dialog.
    			 * @param {Ext.form.FileUploadField} this
    			 * @param {String} value The file value returned by the underlying file input field
    			 */
    			'fileselected'
    		);
    	},
    	
    	// private
    	onRender : function(ct, position){
    		Ext.form.FileUploadField.superclass.onRender.call(this, ct, position);
    		
    		this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
    		this.el.addClass('x-form-file-text');
    		this.el.dom.removeAttribute('name');
    		
    		this.createFileInput();
    		
    		var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
    			text: this.buttonText
    		});
    		this.button = new Ext.Button(Ext.apply(btnCfg, {
    			renderTo: this.wrap,
    			cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
    		}));
    		
    		if(this.buttonOnly){
    			this.el.hide();
    			this.wrap.setWidth(this.button.getEl().getWidth());
    		}
    		
    		this.addFileListener();
    	},
    	
    	//private
    	createFileInput : function() {
    		this.fileInput = this.wrap.createChild({
    			id: this.getFileInputId(),
    			name: this.name||this.getId(),
    			cls: 'x-form-file',
    			tag: 'input', 
    			type: 'file',
    			size: 1
    		});
    	},
    	
    	//private
    	addFileListener : function() {
    		this.fileInput.on('change', function(){
    			var v = this.fileInput.dom.value;
    			this.setValue(v);
    			this.fireEvent('fileselected', this, v);
    		}, this);
    
    		//make the fake icon button represent the mouse state on the transparent fileInput
    		this.fileInput.on({
    			'mouseover' : function() { this.button.addClass(['x-btn-over','x-btn-focus']) },
    			'mouseout'  : function() { this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click']) },
    			'mousedown' : function() { this.button.addClass('x-btn-click') },
    			'mouseup'   : function() { this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click']) },
    			scope : this
    		})
    
    	},
    	
    	// private
    	getFileInputId: function(){
    		return this.id+'-file';
    	},
    
        
    	// private
    	onResize : function(w, h){
    		Ext.form.FileUploadField.superclass.onResize.call(this, w, h);
    	
    		this.wrap.setWidth(w);
            
    		if(!this.buttonOnly){
    			var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
    			this.el.setWidth(w);
    		}
    	},
        
    	// private
    	preFocus : Ext.emptyFn,
        
    	// private
    	getResizeEl : function(){
    		return this.wrap;
    	},
    
    	// private
    	getPositionEl : function(){
    		return this.wrap;
    	},
    
    	// private
    	alignErrorIcon : function(){
    		this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
    	},
        
    	//private
    	reset : function(){
    		
    		this.fileInput.remove();
    		
    		this.createFileInput();
    		this.addFileListener();
    		
    		Ext.form.FileUploadField.superclass.reset.call(this);
    	}
        
    });
    Ext.reg('fileuploadfield', Ext.form.FileUploadField);

    There is perhaps a more elegant way to do the replace; I tried with DomHelper but I couldn't get the events all tied back up that way.


    Matt.




    [1] http://extjs.com/deploy/dev/examples...le-upload.html
    Last edited by mattbennett; 10 Sep 2008 at 4:59 AM. Reason: added mouse listeners to fileinput element

  2. #2
    Ext User
    Join Date
    Dec 2007
    Posts
    67
    Vote Rating
    0
    jit is on a distinguished road

      0  

    Thumbs up


    Thanks for your post Matt. I noticed the same problem and am glad to find your fix.

    - Jit

  3. #3
    Ext User
    Join Date
    Jul 2008
    Posts
    50
    Vote Rating
    0
    afei is on a distinguished road

      0  

    Default


    how to add multi file by FileUploadField just like gmail.

    it seems the FileUploadField just can add a file

  4. #4
    Sencha - Community Support Team mystix's Avatar
    Join Date
    Mar 2007
    Location
    Singapore
    Posts
    6,236
    Vote Rating
    5
    mystix will become famous soon enough

      0  

    Default


    Quote Originally Posted by afei View Post
    how to add multi file by FileUploadField just like gmail.

    it seems the FileUploadField just can add a file
    please post requests for help in the Help forum.
    please refrain from making identical posts in various forums too: http://extjs.com/forum/showthread.php?t=48024

  5. #5
    Ext User
    Join Date
    Jan 2008
    Posts
    20
    Vote Rating
    0
    dsonet is on a distinguished road

      0  

    Wink improved again

    improved again


    Code:
    /*
     * Ext JS Library 2.2
     * Copyright(c) 2006-2008, Ext JS, LLC.
     * licensing@extjs.com
     * 
     * http://extjs.com/license
     */
    
    
    var FileUploadField = Ext.form.FileUploadField = Ext.extend(Ext.form.TextField,  {
        /**
         * @cfg {String} buttonText The button text to display on the upload button (defaults to
         * 'Browse...').  Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
         * value will be used instead if available.
         */
        buttonText: 'Browse...',
        /**
         * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
         * text field (defaults to false).  If true, all inherited TextField members will still be available.
         */
        buttonOnly: false,
        /**
         * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
         * (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.
         */
        buttonOffset: 3,
        /**
         * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
         */
    
        // private
        readOnly: true,
        
        /**
         * @hide 
         * @method autoSize
         */
        autoSize: Ext.emptyFn,
        
        // private
        initComponent: function(){
            FileUploadField.superclass.initComponent.call(this);
            
            this.addEvents(
                /**
                 * @event fileselected
                 * Fires when the underlying file input field's value has changed from the user
                 * selecting a new file from the system file selection dialog.
                 * @param {Ext.form.FileUploadField} this
                 * @param {String} value The file value returned by the underlying file input field
                 */
                'fileselected'
            );
        },
        
        // private
        onRender : function(ct, position){
            FileUploadField.superclass.onRender.call(this, ct, position);
            
            this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
            this.el.addClass('x-form-file-text');
            this.el.dom.removeAttribute('name');
            
            this.createFileInput();
            
            var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
                text: this.buttonText
            });
            this.button = new Ext.Button(Ext.apply(btnCfg, {
                renderTo: this.wrap,
                cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
            }));
            
            if(this.buttonOnly){
                this.el.hide();
                this.wrap.setWidth(this.button.getEl().getWidth());
            }
    		this.addFileListener();
        },
        getName : function(){
            return this.rendered && this.fileInput.dom.name ? this.fileInput.dom.name : (this.hiddenName || '');
        },
        // private
        getFileInputId: function(){
            return this.id+'-file';
        },
        // private
        onResize : function(w, h){
            FileUploadField.superclass.onResize.call(this, w, h);
            
            this.wrap.setWidth(w);
            
            if(!this.buttonOnly){
                var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
                this.el.setWidth(w);
            }
        },
        
        // private
        preFocus : Ext.emptyFn,
        
        // private
        getResizeEl : function(){
            return this.wrap;
        },
    
        // private
        getPositionEl : function(){
            return this.wrap;
        },
    
        // private
        alignErrorIcon : function(){
            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
        },
    	createFileInput : function()
    	{
    		this.fileInput = this.wrap.createChild({
                id: this.getFileInputId(),
                name: this.name || this.getId(),
                cls: 'x-form-file',
                tag: 'input', 
                type: 'file',
                size: 1
            });
    		if(this.disabled)
    		{
    			this.fileInput.dom.disabled = true;
    		}
    	},
    	addFileListener : function()
    	{
    		//make the fake icon button represent the mouse state on the transparent fileInput
    		this.fileInput.on({
    			'change': function(){
    				var v = this.fileInput.dom.value;
    				this.setValue(v);
    				this.fireEvent('fileselected', this, v);
    			},
    			'mouseover' : function() {this.button.addClass(['x-btn-over', 'x-btn-focus']) },
    			'mouseout'  : function() { this.button.removeClass(['x-btn-over', 'x-btn-focus','x-btn-click']) },
    			'mousedown' : function() { this.button.addClass('x-btn-click') },
    			'mouseup'   : function() { this.button.removeClass(['x-btn-over', 'x-btn-focus', 'x-btn-click']) },
    			scope : this
    		});
    	},
    	//private
    	reset : function(){
    		Ext.destroy(this.fileInput);
    		
    		this.createFileInput();
    		this.addFileListener();
    		
    		FileUploadField.superclass.reset.call(this);
    	},
    	onDestroy : function(){
            if(this.fileInput){
                Ext.destroy(this.fileInput);
            }
    		if(this.button)
    		{
    			this.button.destroy();
    		}
            FileUploadField.superclass.onDestroy.call(this);
        },
    	onEnable: function()
    	{
    		FileUploadField.superclass.onEnable.call(this);
    		this.fileInput.dom.disabled = false;
    		this.button.enable();
    	},
    	onDisable: function()
    	{
    		FileUploadField.superclass.onEnable.call(this);
    		this.fileInput.dom.disabled = true;
    		this.button.disable();
    	}
        
    });
    Ext.reg('fileuploadfield', FileUploadField);

  6. #6
    Ext User wolverline's Avatar
    Join Date
    Oct 2008
    Location
    Timbuktu, Mali
    Posts
    11
    Vote Rating
    0
    wolverline is on a distinguished road

      0  

    Default Eh??

    Eh??


    Did you improve this souce code?

    Your posting causes confusion, here.



    Quote Originally Posted by dsonet View Post
    Code:
    /*
     * Ext JS Library 2.2
     * Copyright(c) 2006-2008, Ext JS, LLC.
     * licensing@extjs.com
     * 
     * http://extjs.com/license
     */
    
    
    var FileUploadField = Ext.form.FileUploadField = Ext.extend(Ext.form.TextField,  {
        /**
         * @cfg {String} buttonText The button text to display on the upload button (defaults to
         * 'Browse...').  Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
         * value will be used instead if available.
         */
        buttonText: 'Browse...',
        /**
         * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
         * text field (defaults to false).  If true, all inherited TextField members will still be available.
         */
        buttonOnly: false,
        /**
         * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
         * (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.
         */
        buttonOffset: 3,
        /**
         * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
         */
    
        // private
        readOnly: true,
        
        /**
         * @hide 
         * @method autoSize
         */
        autoSize: Ext.emptyFn,
        
        // private
        initComponent: function(){
            FileUploadField.superclass.initComponent.call(this);
            
            this.addEvents(
                /**
                 * @event fileselected
                 * Fires when the underlying file input field's value has changed from the user
                 * selecting a new file from the system file selection dialog.
                 * @param {Ext.form.FileUploadField} this
                 * @param {String} value The file value returned by the underlying file input field
                 */
                'fileselected'
            );
        },
        
        // private
        onRender : function(ct, position){
            FileUploadField.superclass.onRender.call(this, ct, position);
            
            this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
            this.el.addClass('x-form-file-text');
            this.el.dom.removeAttribute('name');
            
            this.createFileInput();
            
            var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
                text: this.buttonText
            });
            this.button = new Ext.Button(Ext.apply(btnCfg, {
                renderTo: this.wrap,
                cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
            }));
            
            if(this.buttonOnly){
                this.el.hide();
                this.wrap.setWidth(this.button.getEl().getWidth());
            }
            this.addFileListener();
        },
        getName : function(){
            return this.rendered && this.fileInput.dom.name ? this.fileInput.dom.name : (this.hiddenName || '');
        },
        // private
        getFileInputId: function(){
            return this.id+'-file';
        },
        // private
        onResize : function(w, h){
            FileUploadField.superclass.onResize.call(this, w, h);
            
            this.wrap.setWidth(w);
            
            if(!this.buttonOnly){
                var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
                this.el.setWidth(w);
            }
        },
        
        // private
        preFocus : Ext.emptyFn,
        
        // private
        getResizeEl : function(){
            return this.wrap;
        },
    
        // private
        getPositionEl : function(){
            return this.wrap;
        },
    
        // private
        alignErrorIcon : function(){
            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
        },
        createFileInput : function()
        {
            this.fileInput = this.wrap.createChild({
                id: this.getFileInputId(),
                name: this.name || this.getId(),
                cls: 'x-form-file',
                tag: 'input', 
                type: 'file',
                size: 1
            });
            if(this.disabled)
            {
                this.fileInput.dom.disabled = true;
            }
        },
        addFileListener : function()
        {
            //make the fake icon button represent the mouse state on the transparent fileInput
            this.fileInput.on({
                'change': function(){
                    var v = this.fileInput.dom.value;
                    this.setValue(v);
                    this.fireEvent('fileselected', this, v);
                },
                'mouseover' : function() {this.button.addClass(['x-btn-over', 'x-btn-focus']) },
                'mouseout'  : function() { this.button.removeClass(['x-btn-over', 'x-btn-focus','x-btn-click']) },
                'mousedown' : function() { this.button.addClass('x-btn-click') },
                'mouseup'   : function() { this.button.removeClass(['x-btn-over', 'x-btn-focus', 'x-btn-click']) },
                scope : this
            });
        },
        //private
        reset : function(){
            Ext.destroy(this.fileInput);
            
            this.createFileInput();
            this.addFileListener();
            
            FileUploadField.superclass.reset.call(this);
        },
        onDestroy : function(){
            if(this.fileInput){
                Ext.destroy(this.fileInput);
            }
            if(this.button)
            {
                this.button.destroy();
            }
            FileUploadField.superclass.onDestroy.call(this);
        },
        onEnable: function()
        {
            FileUploadField.superclass.onEnable.call(this);
            this.fileInput.dom.disabled = false;
            this.button.enable();
        },
        onDisable: function()
        {
            FileUploadField.superclass.onEnable.call(this);
            this.fileInput.dom.disabled = true;
            this.button.disable();
        }
        
    });
    Ext.reg('fileuploadfield', FileUploadField);

  7. #7
    Sencha Premium Member
    Join Date
    Mar 2007
    Posts
    170
    Vote Rating
    1
    mike1993 is on a distinguished road

      0  

    Thumbs up


    Big Thanks!
    I was was just about to start working on reset issue an viola! Thanks!

  8. #8
    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

      1  

    Default


    Now the same thing as an override:
    Code:
    Ext.override(Ext.form.FileUploadField, {
    	onRender : function(ct, position){
    		Ext.form.FileUploadField.superclass.onRender.call(this, ct, position);
    		this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
    		this.el.addClass('x-form-file-text');
    		this.el.dom.removeAttribute('name');
    		this.createFileInput();
    		var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
    			text: this.buttonText
    		});
    		this.button = new Ext.Button(Ext.apply(btnCfg, {
    			renderTo: this.wrap,
    			cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
    		}));
    		if(this.buttonOnly){
    			this.el.hide();
    			this.wrap.setWidth(this.button.getEl().getWidth());
    		}
    		this.addFileListener();
    	},
    	createFileInput : function() {
    		this.fileInput = this.wrap.createChild({
    			id: this.getFileInputId(),
    			name: this.name||this.getId(),
    			cls: 'x-form-file',
    			tag: 'input',
    			type: 'file',
    			size: 1
    		});
    	},
    	addFileListener : function() {
    		this.fileInput.on({
    			change: function(){
    				var v = this.fileInput.dom.value;
    				this.setValue(v);
    				this.fireEvent('fileselected', this, v);
    			},
    			mouseover: function() {
    				this.button.addClass(['x-btn-over','x-btn-focus'])
    			},
    			mouseout: function(){
    				this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click'])
    			},
    			mousedown: function(){
    				this.button.addClass('x-btn-click')
    			},
    			mouseup: function(){
    				this.button.removeClass(['x-btn-over','x-btn-focus','x-btn-click'])
    			},
    			scope : this
    		});
    	},
    	reset : function(){
    		this.fileInput.removeAllListeners();
    		this.fileInput.remove();
    		this.createFileInput();
    		this.addFileListener();
    		Ext.form.FileUploadField.superclass.reset.call(this);
    	}
    });
    ps. I did add a call to removeAllListeners to avoid event leaks.

  9. #9
    Ext User
    Join Date
    Sep 2008
    Posts
    10
    Vote Rating
    0
    alladin-it is on a distinguished road

      0  

    Thumbs up Code works fine

    Code works fine


    dsonet code works fine! thanx a lot. I use it the reset the fileupload alone (not over the form - reset function)

  10. #10
    Sencha User
    Join Date
    May 2008
    Posts
    70
    Vote Rating
    0
    pdchapin is on a distinguished road

      0  

    Default


    Am I to understand that this is the simplest way to reset a FileUploadField so I can use the same form to collect additional files to upload?

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