`
crabdave
  • 浏览: 1281648 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Ext.ux.form.BrowseButton组件的使用(上传浏览按钮) 示例

阅读更多

Ext.ux.form.BrowseButton组件的使用(上传浏览按钮) 示例

 效果:

 

 创建调用HTML:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />
 <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
 <script type="text/javascript" src="extjs/ext-all.js"></script>
<script type="text/javascript" src="./Ext.ux.form.BrowseButton.js"></script>
<script type="text/javascript" src="./ScreenshotPanel.js"></script>

<style type="text/css">

</style>
<script>
Ext.onReady(function(){
             Ext.QuickTips.init();
             
              new Ext.ux.ScreenshotsPanel({
               renderTo : document.body,
                title: 'Screenshot Adder - Debug = false, meaning Browse butons are hidden.',
                frame: true,
                debug: false
             });
            });
</script>
</head>
<body>

</body>
</html>

 

 ScreenshotsPanel.js文件源码:

/**
 * @class Ext.ux.ScreenshotPanel
 * @extends Ext.Panel
 * Renders a browse button for demonstration purposes.
 * @constructor
 * @param {Object} config The config object
 */
Ext.ux.ScreenshotsPanel = Ext.extend(Ext.Panel, {
 /*
  * Config options
  */
 /**
  * For whether to draw the panel (and it's BrowseButtons) in debug mode.
  * @type Boolean
  */
 debug: false,
 
 
 /*
  * Private properties
  */
 /**
  * Panel for displaying the files that have selected for upload.
  * @type Ext.Panel
  */
 filePanel: null,
 /**
  * Form for uploading screenshot images.
  * Is only instantiated if a screenshot is selected to upload.
  * @type Ext.form.BasicForm
  */
 addScreenshotForm: null,
 
 
 /*
  * Protected methods
  */
 /**
  * @see Ext.Panel.initConfiguration
  */
 initComponent: function(){
  var browseButtonBaseConfig = {
   xtype: 'browsebutton',
   handler: this.onAddScreenshot,
   scope: this,
   tooltip: 'Click to upload a new screenshot.',
   inputFileName: 'screenshot',
   debug: this.debug // set to true to see the "Browse" overlay
  };
  this.filePanel = new Ext.Panel({
   frame: true,
   title: 'selected files',
   buttonAlign: 'center',
   buttons: [{
    text: 'Upload (does not work and will fail)',
    handler: this.uploadScreenshots,
    scope: this
   }]
  });
  Ext.apply(this, {
   tbar: [
    new Ext.ux.form.BrowseButton(Ext.apply({
     text: 'tbar - explicit'
    }, browseButtonBaseConfig)),
    Ext.apply({
     text: 'tbar - xtype'
    }, browseButtonBaseConfig)
   ],
   items: [
    new Ext.ux.form.BrowseButton(Ext.apply({
     text: 'items - explicit'
    }, browseButtonBaseConfig)),
    Ext.apply({
     text: 'items - xtype'
    }, browseButtonBaseConfig),
    this.filePanel
   ],
   buttons: [
    new Ext.ux.form.BrowseButton(Ext.apply({
     text: 'buttons - explicit'
    }, browseButtonBaseConfig)),
    Ext.apply({
     text: 'buttons - xtype'
    }, browseButtonBaseConfig) // doesn't work correctly as Ext uses the config object to instaniate an Ext.Button
   ]
  });
  Ext.ux.ScreenshotsPanel.superclass.initComponent.call(this);
 },
 
 
 /*
  * Private methods
  */
 /**
  * Handler for the add screenshot button.
  * @param {Ext.ux.form.BrowseButton} browseButton The browse button where "Add Screenshot" was clicked.
  * @private
  */
 onAddScreenshot: function(browseButton){
  if (!this.addScreenshotForm) { // if the form hasn't been created
   var addScreenshotFormEl = this.filePanel.body.createChild({
    tag: 'form',
    style: 'display:none'
   });
   this.addScreenshotForm = new Ext.form.BasicForm(addScreenshotFormEl, {
    url: '/AddScreenshot',
    fileUpload: true
   });
  }
  var inputFileEl = browseButton.detachInputFile();
  inputFileEl.appendTo(this.addScreenshotForm.getEl());
  this.filePanel.body.createChild({
   tag: 'div',
   html: inputFileEl.dom.value
  });
 },
 
 /**
  * Handler for the upload screenshots button
  */
 uploadScreenshots: function(){
  this.addScreenshotForm.submit({
   params: {
    extraParam1: 'value1'
   },
   success: this.onAddScreenshotSuccess,
   failure: this.onAddScreenshotFailure,
   scope: this,
   waitTitle: 'Uploading Screenshot',
   waitMsg: 'Your screenshot is being uploaded...'
  });
 },
 
 /**
  * Callback for when a screenshot has been successfully added.
  * @param {Ext.form.BasicForm} form the form for which the uploading occurred.
  * @param {Ext.form.Action} action the action of the form submit
  * @private
  */
 onAddScreenshotSuccess: function(form, action){
  // remove the file input element so that it doesn't get uploaded again with the next screenshot
  var inputFileEl = this.addScreenshotForm.getEl().child('input');
  inputFileEl.remove();
  Ext.Msg.show({
   title: 'Screenshot Upload Success',
   msg: 'Your screenshot was successfully uploaded.',
   buttons: Ext.Msg.OK,
   minWidth: 300
  });
 },
 
 /**
  * Callback for when a screenshot has not been successfully added.
  * @param {Ext.form.BasicForm} form the form for which the uploading occurred.
  * @param {Ext.form.Action} action the action of the form submit
  * @private
  */
 onAddScreenshotFailure: function(form, action){
  // remove the file input element so that it doesn't get uploaded again with the next screenshot
  var inputFileEl = this.addScreenshotForm.getEl().child('input');
  inputFileEl.remove();
  var errorMessageTemplate = new Ext.XTemplate('<p>Your screenshot was not uploaded.  The server reported the following errors:</p>', '<tpl for="errors">', '<p>- {.}</p>', '</tpl>');
  Ext.Msg.show({
   title: 'Screenshot Upload Failed',
   msg: errorMessageTemplate.applyTemplate(action.result),
   buttons: Ext.Msg.OK,
   minWidth: 300
  });
 }
});

 

 Ext.ux.form.BrowseButton.js文件源码:

Ext.namespace('Ext.ux.form');

/**
 * @class Ext.ux.form.BrowseButton
 * @extends Ext.Button
 * Ext.Button that provides a customizable file browse button.
 * Clicking this button, pops up a file dialog box for a user to select the file to upload.
 * This is accomplished by having a transparent <input type="file"> box above the Ext.Button.
 * When a user thinks he or she is clicking the Ext.Button, they're actually clicking the hidden input "Browse..." box.
 * Note: this class can be instantiated explicitly or with xtypes anywhere a regular Ext.Button can be except in 2 scenarios:
 * - Panel.addButton method both as an instantiated object or as an xtype config object.
 * - Panel.buttons config object as an xtype config object.
 * These scenarios fail because Ext explicitly creates an Ext.Button in these cases.
 * Browser compatibility:
 * Internet Explorer 6:
 * - no issues
 * Internet Explorer 7:
 * - no issues
 * Firefox 2 - Windows:
 * - pointer cursor doesn't display when hovering over the button.
 * Safari 3 - Windows:
 * - no issues.
 * @author loeppky - based on the work done by MaximGB in Ext.ux.UploadDialog (http://extjs.com/forum/showthread.php?t=21558)
 * The follow the curosr float div idea also came from MaximGB.
 * @see http://extjs.com/forum/showthread.php?t=29032
 * @constructor
 * Create a new BrowseButton.
 * @param {Object} config Configuration options
 */
Ext.ux.form.BrowseButton = Ext.extend(Ext.Button, {
 /*
  * Config options:
  */
 /**
  * @cfg {String} inputFileName
  * Name to use for the hidden input file DOM element.  Deaults to "file".
  */
 inputFileName: 'file',
 /**
  * @cfg {Boolean} debug
  * Toggle for turning on debug mode.
  * Debug mode doesn't make clipEl transparent so that one can see how effectively it covers the Ext.Button.
  * In addition, clipEl is given a green background and floatEl a red background to see how well they are positioned.
  */
 debug: false,
 
 
 /*
  * Private constants:
  */
 /**
  * @property FLOAT_EL_WIDTH
  * @type Number
  * The width (in pixels) of floatEl.
  * It should be less than the width of the IE "Browse" button's width (65 pixels), since IE doesn't let you resize it.
  * We define this width so we can quickly center floatEl at the mouse cursor without having to make any function calls.
  * @private
  */
 FLOAT_EL_WIDTH: 60,
 
 /**
  * @property FLOAT_EL_HEIGHT
  * @type Number
  * The heigh (in pixels) of floatEl.
  * It should be less than the height of the "Browse" button's height.
  * We define this height so we can quickly center floatEl at the mouse cursor without having to make any function calls.
  * @private
  */
 FLOAT_EL_HEIGHT: 18,
 
 
 /*
  * Private properties:
  */
 /**
  * @property buttonCt
  * @type Ext.Element
  * Element that contains the actual Button DOM element.
  * We store a reference to it, so we can easily grab its size for sizing the clipEl.
  * @private
  */
 buttonCt: null,
 /**
  * @property clipEl
  * @type Ext.Element
  * Element that contains the floatEl.
  * This element is positioned to fill the area of Ext.Button and has overflow turned off.
  * This keeps floadEl tight to the Ext.Button, and prevents it from masking surrounding elements.
  * @private
  */
 clipEl: null,
 /**
  * @property floatEl
  * @type Ext.Element
  * Element that contains the inputFileEl.
  * This element is size to be less than or equal to the size of the input file "Browse" button.
  * It is then positioned wherever the user moves the cursor, so that their click always clicks the input file "Browse" button.
  * Overflow is turned off to preven inputFileEl from masking surrounding elements.
  * @private
  */
 floatEl: null,
 /**
  * @property inputFileEl
  * @type Ext.Element
  * Element for the hiden file input.
  * @private
  */
 inputFileEl: null,
 /**
  * @property originalHandler
  * @type Function
  * The handler originally defined for the Ext.Button during construction using the "handler" config option.
  * We need to null out the "handler" property so that it is only called when a file is selected.
  * @private
  */
 originalHandler: null,
 /**
  * @property originalScope
  * @type Object
  * The scope originally defined for the Ext.Button during construction using the "scope" config option.
  * While the "scope" property doesn't need to be nulled, to be consistent with originalHandler, we do.
  * @private
  */
 originalScope: null,
 
 
 /*
  * Protected Ext.Button overrides
  */
 /**
  * @see Ext.Button.initComponent
  */
 initComponent: function(){
  Ext.ux.form.BrowseButton.superclass.initComponent.call(this);
  // Store references to the original handler and scope before nulling them.
  // This is done so that this class can control when the handler is called.
  // There are some cases where the hidden file input browse button doesn't completely cover the Ext.Button.
  // The handler shouldn't be called in these cases.  It should only be called if a new file is selected on the file system. 
  this.originalHandler = this.handler || null;
  this.originalScope = this.scope || window;
  this.handler = null;
  this.scope = null;
 },
 
 /**
  * @see Ext.Button.onRender
  */
 onRender: function(ct, position){
  Ext.ux.form.BrowseButton.superclass.onRender.call(this, ct, position); // render the Ext.Button
  this.buttonCt = this.el.child('.x-btn-center em');
  this.buttonCt.position('relative'); // this is important!
  var styleCfg = {
   position: 'absolute',
   overflow: 'hidden',
   top: '0px', // default
   left: '0px' // default
  };
  // browser specifics for better overlay tightness
  if (Ext.isIE) {
   Ext.apply(styleCfg, {
    left: '-3px',
    top: '-3px'
   });
  } else if (Ext.isGecko) {
   Ext.apply(styleCfg, {
    left: '-3px',
    top: '-3px'
   });
  } else if (Ext.isSafari) {
   Ext.apply(styleCfg, {
    left: '-4px',
    top: '-2px'
   });
  }
  this.clipEl = this.buttonCt.createChild({
   tag: 'div',
   style: styleCfg
  });
  this.setClipSize();
  this.clipEl.on({
   'mousemove': this.onButtonMouseMove,
   'mouseover': this.onButtonMouseMove,
   scope: this
  });
  
  this.floatEl = this.clipEl.createChild({
   tag: 'div',
   style: {
    position: 'absolute',
    width: this.FLOAT_EL_WIDTH + 'px',
    height: this.FLOAT_EL_HEIGHT + 'px',
    overflow: 'hidden'
   }
  });
  
  
  if (this.debug) {
   this.clipEl.applyStyles({
    'background-color': 'green'
   });
   this.floatEl.applyStyles({
    'background-color': 'red'
   });
  } else {
   this.clipEl.setOpacity(0.0);
  }
  
  this.createInputFile();
 },
 
 
 /*
  * Private helper methods:
  */
 /**
  * Sets the size of clipEl so that is covering as much of the button as possible.
  * @private
  */
 setClipSize: function(){
  if (this.clipEl) {
   var width = this.buttonCt.getWidth();
   var height = this.buttonCt.getHeight();
   if (Ext.isIE) {
    width = width + 5;
    height = height + 5;
   } else if (Ext.isGecko) {
    width = width + 6;
    height = height + 6;
   } else if (Ext.isSafari) {
    width = width + 6;
    height = height + 6;
   }
   this.clipEl.setSize(width, height);
  }
 },
 
 /**
  * Creates the input file element and adds it to inputFileCt.
  * The created input file elementis sized, positioned, and styled appropriately.
  * Event handlers for the element are set up, and a tooltip is applied if defined in the original config.
  * @private
  */
 createInputFile: function(){
 
  this.inputFileEl = this.floatEl.createChild({
   tag: 'input',
   type: 'file',
   size: 1, // must be > 0. It's value doesn't really matter due to our masking div (inputFileCt). 
   name: this.inputFileName || Ext.id(this.el),
   // Use the same pointer as an Ext.Button would use.  This doesn't work in Firefox.
   // This positioning right-aligns the input file to ensure that the "Browse" button is visible.
   style: {
    position: 'absolute',
    cursor: 'pointer',
    right: '0px',
    top: '0px'
   }
  });
  this.inputFileEl = this.inputFileEl.child('input') || this.inputFileEl;
  
  // setup events
  this.inputFileEl.on({
   'click': this.onInputFileClick,
   'change': this.onInputFileChange,
   scope: this
  });
  
  // add a tooltip
  if (this.tooltip) {
   if (typeof this.tooltip == 'object') {
    Ext.QuickTips.register(Ext.apply({
     target: this.inputFileEl
    }, this.tooltip));
   } else {
    this.inputFileEl.dom[this.tooltipType] = this.tooltip;
   }
  }
 },
 
 /**
  * Handler when the cursor moves over the clipEl.
  * The floatEl gets centered to the cursor location.
  * @param {Event} e mouse event.
  * @private
  */
 onButtonMouseMove: function(e){
  var xy = e.getXY();
  xy[0] -= this.FLOAT_EL_WIDTH / 2;
  xy[1] -= this.FLOAT_EL_HEIGHT / 2;
  this.floatEl.setXY(xy);
 },
 
 /**
  * Handler when inputFileEl's "Browse..." button is clicked.
  * @param {Event} e click event.
  * @private
  */
 onInputFileClick: function(e){
  e.stopPropagation();
 },
 
 /**
  * Handler when inputFileEl changes value (i.e. a new file is selected).
  * @private
  */
 onInputFileChange: function(){
  if (this.originalHandler) {
   this.originalHandler.call(this.originalScope, this);
  }
 },
 
 
 /*
  * Public methods:
  */
 /**
  * Detaches the input file associated with this BrowseButton so that it can be used for other purposed (e.g. uplaoding).
  * The returned input file has all listeners and tooltips applied to it by this class removed.
  * @param {Boolean} whether to create a new input file element for this BrowseButton after detaching.
  * True will prevent creation.  Defaults to false.
  * @return {Ext.Element} the detached input file element.
  */
 detachInputFile: function(noCreate){
  var result = this.inputFileEl;
  
  if (typeof this.tooltip == 'object') {
   Ext.QuickTips.unregister(this.inputFileEl);
  } else {
   this.inputFileEl.dom[this.tooltipType] = null;
  }
  this.inputFileEl.removeAllListeners();
  this.inputFileEl = null;
  
  if (!noCreate) {
   this.createInputFile();
  }
  return result;
 },
 
 /**
  * @return {Ext.Element} the input file element attached to this BrowseButton.
  */
 getInputFile: function(){
  return this.inputFileEl;
 },
 
 /**
  * @see Ext.Button.disable
  */
 disable: function(){
  Ext.ux.form.BrowseButton.superclass.disable.call(this);
  this.inputFileEl.dom.disabled = true;
 },
 
 /**
  * @see Ext.Button.enable
  */
 enable: function(){
  Ext.ux.form.BrowseButton.superclass.enable.call(this);
  this.inputFileEl.dom.disabled = false;
 }
});

Ext.reg('browsebutton', Ext.ux.form.BrowseButton);

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics