393 lines
12 KiB
JavaScript
393 lines
12 KiB
JavaScript
|
//>>built
|
||
|
require({cache:{
|
||
|
'url:dojox/form/resources/Uploader.html':"<span class=\"dijit dijitReset dijitInline\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdojoAttachEvent=\"ondijitclick:_onClick\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdojoAttachPoint=\"titleNode,focusNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" dojoAttachPoint=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">●</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdojoAttachPoint=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><!--no need to have this for Uploader \n\t<input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\n\t\tdojoAttachPoint=\"valueNode\"\n/--></span>\n"}});
|
||
|
define("dojox/form/Uploader", [
|
||
|
"dojo/_base/kernel",
|
||
|
"dojo/_base/declare",
|
||
|
"dojo/_base/lang",
|
||
|
"dojo/_base/array",
|
||
|
"dojo/_base/connect",
|
||
|
"dojo/_base/window",
|
||
|
"dojo/dom-style",
|
||
|
"dojo/dom-geometry",
|
||
|
"dojo/dom-attr",
|
||
|
"dojo/dom-construct",
|
||
|
"dojo/dom-form",
|
||
|
"dijit",
|
||
|
"dijit/form/Button",
|
||
|
"dojox/form/uploader/Base",
|
||
|
"dojo/i18n!./nls/Uploader",
|
||
|
"dojo/text!./resources/Uploader.html"
|
||
|
],function(kernel, declare, lang, array, connect, win, domStyle, domGeometry, domAttr, domConstruct, domForm, dijit, Button, uploader, res, template){
|
||
|
|
||
|
kernel.experimental("dojox.form.Uploader");
|
||
|
//
|
||
|
// TODO:
|
||
|
// i18n
|
||
|
// label via innerHTML
|
||
|
// Doc and or test what can be extended.
|
||
|
// Doc custom file events
|
||
|
// Use new FileReader() for thumbnails
|
||
|
// flashFieldName should default to Flash
|
||
|
// get('value'); and set warning
|
||
|
// Make it so URL can change (current set to Flash on build)
|
||
|
//
|
||
|
|
||
|
/*=====
|
||
|
uploader = dojox.form.uploader.Base;
|
||
|
WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin;
|
||
|
=====*/
|
||
|
declare("dojox.form.Uploader", [uploader, Button], {
|
||
|
//
|
||
|
// Version: 1.6
|
||
|
//
|
||
|
// summary:
|
||
|
// A widget that creates a stylable file-input button, with optional multi-file selection,
|
||
|
// using only HTML elements. Non-HTML5 browsers have fallback options of Flash or an iframe.
|
||
|
//
|
||
|
// description:
|
||
|
// A bare-bones, stylable file-input button, with optional multi-file selection. The list
|
||
|
// of files is not displayed, that is for you to handle by connecting to the onChange
|
||
|
// event, or use the dojox.form.uploader.FileList.
|
||
|
//
|
||
|
// Uploader without plugins does not have any ability to upload - it is for use in forms
|
||
|
// where you handle the upload either by a standard POST or with Ajax using an iFrame. This
|
||
|
// class is for convenience of multiple files only. No progress events are available.
|
||
|
//
|
||
|
// If the browser supports a file-input with the "multiple" attribute, that will be used.
|
||
|
// If the browser does not support "multiple" (ergo, IE) multiple inputs are used,
|
||
|
// one for each selection.
|
||
|
//
|
||
|
//
|
||
|
// uploadOnSelect: Boolean
|
||
|
// If true, uploads imediately after a file has been selected. If false,
|
||
|
// waits for upload() to be called.
|
||
|
uploadOnSelect:false,
|
||
|
// tabIndex: Number|String
|
||
|
// The tab order in the DOM.
|
||
|
tabIndex:0,
|
||
|
// multiple: Boolean
|
||
|
// If true and flash mode, multiple files may be selected from the dialog.
|
||
|
multiple:false,
|
||
|
//
|
||
|
// label: String
|
||
|
// The text used in the button that when clicked, opens a system Browse Dialog.
|
||
|
label:res.label,
|
||
|
//
|
||
|
// url: String
|
||
|
// The url targeted for upload. An absolute URL is preferred. Relative URLs are
|
||
|
// changed to absolute.
|
||
|
url:"",
|
||
|
//
|
||
|
// name: String
|
||
|
// The name attribute needs to end with square brackets: [] as this is the standard way
|
||
|
// of handling an attribute "array". This requires a slightly different technique on the
|
||
|
// server.
|
||
|
name:"uploadedfile",
|
||
|
//
|
||
|
// flashFieldName: String
|
||
|
// If set, this will be the name of the field of the flash uploaded files that the server
|
||
|
// is expecting. If not set, "Flash" is appended to the "name" property.
|
||
|
flashFieldName:"",
|
||
|
//
|
||
|
// uploadType: String [readonly]
|
||
|
// The type of uploader being used. As an alternative to determining the upload type on the
|
||
|
// server based on the fieldName, this property could be sent to the server to help
|
||
|
// determine what type of parsing should be used.
|
||
|
uploadType:"form",
|
||
|
//
|
||
|
// showInput: String [const]
|
||
|
// Position to show an input which shows selected filename(s). Possible
|
||
|
// values are "before", "after", which specifies where the input should
|
||
|
// be placed with reference to the containerNode which contains the
|
||
|
// label). By default, this is empty string (no such input will be
|
||
|
// shown). Specify showInput="before" to mimic the look&feel of a
|
||
|
// native file input element.
|
||
|
showInput: "",
|
||
|
|
||
|
_nameIndex:0,
|
||
|
|
||
|
templateString: template,
|
||
|
|
||
|
baseClass: 'dijitUploader '+Button.prototype.baseClass,
|
||
|
|
||
|
postMixInProperties: function(){
|
||
|
this._inputs = [];
|
||
|
this._cons = [];
|
||
|
this.inherited(arguments);
|
||
|
},
|
||
|
buildRendering: function(){
|
||
|
console.warn("buildRendering", this.id)
|
||
|
this.inherited(arguments);
|
||
|
domStyle.set(this.domNode, {
|
||
|
overflow:"hidden",
|
||
|
position:"relative"
|
||
|
});
|
||
|
this._buildDisplay();
|
||
|
//change the button node not occupy tabIndex: the real file input
|
||
|
//will have tabIndex set
|
||
|
domAttr.set(this.titleNode, 'tabIndex', -1);
|
||
|
},
|
||
|
_buildDisplay: function(){
|
||
|
if(this.showInput){
|
||
|
this.displayInput = dojo.create('input', {
|
||
|
'class':'dijitUploadDisplayInput',
|
||
|
'tabIndex':-1, 'autocomplete':'off'},
|
||
|
this.containerNode, this.showInput);
|
||
|
//schedule the attachpoint to be cleaned up on destroy
|
||
|
this._attachPoints.push('displayInput');
|
||
|
this.connect(this,'onChange', function(files){
|
||
|
var i=0,l=files.length, f, r=[];
|
||
|
while((f=files[i++])){
|
||
|
if(f && f.name){
|
||
|
r.push(f.name);
|
||
|
}
|
||
|
}
|
||
|
this.displayInput.value = r.join(', ');
|
||
|
});
|
||
|
this.connect(this,'reset', function(){
|
||
|
this.displayInput.value = '';
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
|
||
|
startup: function(){
|
||
|
if(this._buildInitialized){
|
||
|
return;
|
||
|
}
|
||
|
this._buildInitialized = true;
|
||
|
this._getButtonStyle(this.domNode);
|
||
|
this._setButtonStyle();
|
||
|
this.inherited(arguments);
|
||
|
},
|
||
|
|
||
|
/*************************
|
||
|
* Public Events *
|
||
|
*************************/
|
||
|
|
||
|
onChange: function(/* Array */fileArray){
|
||
|
// summary:
|
||
|
// stub to connect
|
||
|
// Fires when files are selected
|
||
|
// Event is an array of last files selected
|
||
|
},
|
||
|
|
||
|
onBegin: function(/* Array */dataArray){
|
||
|
// summary:
|
||
|
// Fires when upload begins
|
||
|
},
|
||
|
|
||
|
onProgress: function(/* Object */customEvent){
|
||
|
// summary:
|
||
|
// Stub to connect
|
||
|
// Fires on upload progress. Event is a normalized object of common properties
|
||
|
// from HTML5 uploaders and the Flash uploader. Will not fire for IFrame.
|
||
|
// customEvent:
|
||
|
// bytesLoaded: Number
|
||
|
// Amount of bytes uploaded so far of entire payload (all files)
|
||
|
// bytesTotal: Number
|
||
|
// Amount of bytes of entire payload (all files)
|
||
|
// type: String
|
||
|
// Type of event (progress or load)
|
||
|
// timeStamp: Number
|
||
|
// Timestamp of when event occurred
|
||
|
},
|
||
|
|
||
|
onComplete: function(/* Object */customEvent){
|
||
|
// summary:
|
||
|
// stub to connect
|
||
|
// Fires when all files have uploaded
|
||
|
// Event is an array of all files
|
||
|
this.reset();
|
||
|
},
|
||
|
|
||
|
onCancel: function(){
|
||
|
// summary:
|
||
|
// Stub to connect
|
||
|
// Fires when dialog box has been closed
|
||
|
// without a file selection
|
||
|
},
|
||
|
|
||
|
onAbort: function(){
|
||
|
// summary:
|
||
|
// Stub to connect
|
||
|
// Fires when upload in progress was canceled
|
||
|
},
|
||
|
|
||
|
onError: function(/* Object or String */evtObject){
|
||
|
// summary:
|
||
|
// Fires on errors
|
||
|
//
|
||
|
//FIXME: Unsure of a standard form of error events
|
||
|
},
|
||
|
|
||
|
/*************************
|
||
|
* Public Methods *
|
||
|
*************************/
|
||
|
|
||
|
upload: function(/*Object ? */formData){
|
||
|
// summary:
|
||
|
// When called, begins file upload. Only supported with plugins.
|
||
|
},
|
||
|
|
||
|
submit: function(/* form Node ? */form){
|
||
|
// summary:
|
||
|
// If Uploader is in a form, and other data should be sent along with the files, use
|
||
|
// this instead of form submit.
|
||
|
form = !!form ? form.tagName ? form : this.getForm() : this.getForm();
|
||
|
var data = domForm.toObject(form);
|
||
|
this.upload(data);
|
||
|
},
|
||
|
|
||
|
reset: function(){
|
||
|
// summary
|
||
|
// Resets entire input, clearing all files.
|
||
|
// NOTE:
|
||
|
// Removing individual files is not yet supported, because the HTML5 uploaders can't
|
||
|
// be edited.
|
||
|
// TODO:
|
||
|
// Add this ability by effectively, not uploading them
|
||
|
//
|
||
|
delete this._files;
|
||
|
this._disconnectButton();
|
||
|
array.forEach(this._inputs, domConstruct.destroy, dojo);
|
||
|
this._inputs = [];
|
||
|
this._nameIndex = 0;
|
||
|
this._createInput();
|
||
|
},
|
||
|
|
||
|
getFileList: function(){
|
||
|
// summary:
|
||
|
// Returns a list of selected files.
|
||
|
//
|
||
|
var fileArray = [];
|
||
|
if(this.supports("multiple")){
|
||
|
array.forEach(this._files, function(f, i){
|
||
|
fileArray.push({
|
||
|
index:i,
|
||
|
name:f.name,
|
||
|
size:f.size,
|
||
|
type:f.type
|
||
|
});
|
||
|
}, this);
|
||
|
}else{
|
||
|
array.forEach(this._inputs, function(n, i){
|
||
|
if(n.value){
|
||
|
fileArray.push({
|
||
|
index:i,
|
||
|
name:n.value.substring(n.value.lastIndexOf("\\")+1),
|
||
|
size:0,
|
||
|
type:n.value.substring(n.value.lastIndexOf(".")+1)
|
||
|
});
|
||
|
}
|
||
|
}, this);
|
||
|
|
||
|
}
|
||
|
return fileArray; // Array
|
||
|
},
|
||
|
|
||
|
/*********************************************
|
||
|
* Private Property. Get off my lawn. *
|
||
|
*********************************************/
|
||
|
|
||
|
_getValueAttr: function(){
|
||
|
// summary:
|
||
|
// Internal. To get disabled use: uploader.get("disabled");
|
||
|
return this.getFileList();
|
||
|
},
|
||
|
|
||
|
_setValueAttr: function(disabled){
|
||
|
console.error("Uploader value is read only");
|
||
|
},
|
||
|
|
||
|
_setDisabledAttr: function(disabled){
|
||
|
// summary:
|
||
|
// Internal. To set disabled use: uploader.set("disabled", true);
|
||
|
if(this._disabled == disabled){ return; }
|
||
|
this.inherited(arguments);
|
||
|
domStyle.set(this.inputNode, "display", disabled ? "none" : "");
|
||
|
},
|
||
|
|
||
|
_getButtonStyle: function(node){
|
||
|
this.btnSize = {w:domStyle.get(node,'width'), h:domStyle.get(node,'height')};
|
||
|
},
|
||
|
|
||
|
_setButtonStyle: function(){
|
||
|
this.inputNodeFontSize = Math.max(2, Math.max(Math.ceil(this.btnSize.w / 60), Math.ceil(this.btnSize.h / 15)));
|
||
|
this._createInput();
|
||
|
},
|
||
|
|
||
|
_createInput: function(){
|
||
|
if(this._inputs.length){
|
||
|
domStyle.set(this.inputNode, {
|
||
|
top:"500px"
|
||
|
});
|
||
|
this._disconnectButton();
|
||
|
this._nameIndex++;
|
||
|
}
|
||
|
|
||
|
var name;
|
||
|
if(this.supports("multiple")){
|
||
|
// FF3.5+, WebKit
|
||
|
name = this.name+"s[]";
|
||
|
}else{
|
||
|
// <=IE8
|
||
|
name = this.name + (this.multiple ? this._nameIndex : "");
|
||
|
}
|
||
|
// reset focusNode to the inputNode, so when the button is clicked,
|
||
|
// the focus is properly moved to the input element
|
||
|
this.focusNode = this.inputNode = domConstruct.create("input", {type:"file", name:name}, this.domNode, "first");
|
||
|
if(this.supports("multiple") && this.multiple){
|
||
|
domAttr.set(this.inputNode, "multiple", true);
|
||
|
}
|
||
|
this._inputs.push(this.inputNode);
|
||
|
|
||
|
domStyle.set(this.inputNode, {
|
||
|
position:"absolute",
|
||
|
fontSize:this.inputNodeFontSize+"em",
|
||
|
top:"-3px",
|
||
|
right:"-3px",
|
||
|
opacity:0
|
||
|
});
|
||
|
this._connectButton();
|
||
|
},
|
||
|
|
||
|
_connectButton: function(){
|
||
|
this._cons.push(connect.connect(this.inputNode, "change", this, function(evt){
|
||
|
this._files = this.inputNode.files;
|
||
|
this.onChange(this.getFileList(evt));
|
||
|
if(!this.supports("multiple") && this.multiple) this._createInput();
|
||
|
}));
|
||
|
|
||
|
if(this.tabIndex > -1){
|
||
|
this.inputNode.tabIndex = this.tabIndex;
|
||
|
|
||
|
this._cons.push(connect.connect(this.inputNode, "focus", this, function(){
|
||
|
this.titleNode.style.outline= "1px dashed #ccc";
|
||
|
}));
|
||
|
this._cons.push(connect.connect(this.inputNode, "blur", this, function(){
|
||
|
this.titleNode.style.outline = "";
|
||
|
}));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_disconnectButton: function(){
|
||
|
array.forEach(this._cons, connect.disconnect);
|
||
|
this._cons.splice(0,this._cons.length);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
dojox.form.UploaderOrg = dojox.form.Uploader;
|
||
|
var extensions = [dojox.form.UploaderOrg];
|
||
|
dojox.form.addUploaderPlugin = function(plug){
|
||
|
// summary:
|
||
|
// Handle Uploader plugins. When the dojox.form.addUploaderPlugin() function is called,
|
||
|
// the dojox.form.Uploader is recreated using the new plugin (mixin).
|
||
|
//
|
||
|
extensions.push(plug);
|
||
|
declare("dojox.form.Uploader", extensions, {});
|
||
|
}
|
||
|
|
||
|
return dojox.form.Uploader;
|
||
|
});
|