[483] | 1 | define([ |
---|
| 2 | "dojo/_base/kernel", |
---|
| 3 | "dojo/_base/declare", |
---|
| 4 | "dojo/_base/lang", |
---|
| 5 | "dojo/_base/array", |
---|
| 6 | "dojo/_base/connect", |
---|
| 7 | "dojo/_base/window", |
---|
| 8 | "dojo/_base/sniff", |
---|
| 9 | "dojo/query", |
---|
| 10 | "dojo/dom", |
---|
| 11 | "dojo/dom-style", |
---|
| 12 | "dojo/dom-geometry", |
---|
| 13 | "dojo/dom-attr", |
---|
| 14 | "dojo/dom-class", |
---|
| 15 | "dojo/dom-construct", |
---|
| 16 | "dojo/dom-form", |
---|
| 17 | "dojo/_base/config", |
---|
| 18 | "dijit/_base/manager", |
---|
| 19 | "dojo/io/iframe", |
---|
| 20 | "dojo/_base/Color", |
---|
| 21 | "dojo/_base/unload", |
---|
| 22 | "dijit/_Widget", |
---|
| 23 | "dijit/_TemplatedMixin", |
---|
| 24 | "dijit/_Contained", |
---|
| 25 | "dojox/embed/Flash", |
---|
| 26 | "dojox/embed/flashVars", |
---|
| 27 | "dojox/html/styles" |
---|
| 28 | ],function(kernel, declare, lang, array, connect, win, has, query, dom, domStyle, domGeometry, domAttr, domClass, domConstruct, domForm, config, manager, ioIframe, Color, unloadUtils, Widget, TemplatedMixin, Contained, embedFlash, embedFlashVars, htmlStyles){ |
---|
| 29 | |
---|
| 30 | kernel.deprecated("dojox.form.FileUploader", "Use dojox.form.Uploader", "2.0"); |
---|
| 31 | |
---|
| 32 | // Usage Notes: |
---|
| 33 | // To center text vertically, use vertical-align:middle; |
---|
| 34 | // which emulates a boxModel button. Using line-height to center text |
---|
| 35 | // can cause height problems in IE6 |
---|
| 36 | |
---|
| 37 | return declare("dojox.form.FileUploader", [Widget, TemplatedMixin, Contained], { |
---|
| 38 | // version: |
---|
| 39 | // 1.5 (deprecated) |
---|
| 40 | // summary: |
---|
| 41 | // Handles File Uploading to a server (PHP script included for testing) |
---|
| 42 | // |
---|
| 43 | // FileUploader is now a WIDGET. You do not have to pass a button |
---|
| 44 | // in. Passing a button is still supported until version 1.5 to maintain |
---|
| 45 | // backwards compatibility, but it is not recommended. Just create your |
---|
| 46 | // uploader like any other widget. |
---|
| 47 | // description: |
---|
| 48 | // If the correct version of Flash Player is available (> 9.0) , a SWF |
---|
| 49 | // is used. If Flash Player is not installed or is outdated, a typical |
---|
| 50 | // html fileInput is used. This process can be overridden with |
---|
| 51 | // force:"flash" or force:"html". |
---|
| 52 | // |
---|
| 53 | // FileUploader works with Flash 10. |
---|
| 54 | // |
---|
| 55 | // The button styles are now recreated in Flash, so there is no longer |
---|
| 56 | // using an invisible Flash movie with wmode=transparent. This way the Flash button |
---|
| 57 | // is actually placed inline with the DOM, not floating above it and constantly |
---|
| 58 | // resetting its position. The "Windows Firefox clickable bug" should be fixed (and |
---|
| 59 | // hopefully some Linux problems). |
---|
| 60 | // |
---|
| 61 | // The HTML button is created in a new way and it is now inline as is the |
---|
| 62 | // FLash button. Styling is much easier and more versatile. |
---|
| 63 | // |
---|
| 64 | // ###Dependencies |
---|
| 65 | // |
---|
| 66 | // FileUploader no longer uses FileInput.css. It now uses FileUploader.css |
---|
| 67 | // See requires for JavaScript dependencies. |
---|
| 68 | // |
---|
| 69 | // ###NEW FEATURES |
---|
| 70 | // |
---|
| 71 | // There are a ton of features and fixes in this version: |
---|
| 72 | // |
---|
| 73 | // - Disabled: Can be toggled with widget.set("disabled", true|false) |
---|
| 74 | // - Submit: A convenience method has been added for if the uploader is in a form. |
---|
| 75 | // Instead of submitting the form, call uploader.submit(theForm), and the |
---|
| 76 | // Uploader will handle all of the form values and post the data. |
---|
| 77 | // - Selected List: If passing the ID of a container, the Uploaders will populate it |
---|
| 78 | // with the selected files. |
---|
| 79 | // - Deleting Files: You can now delete pending files. |
---|
| 80 | // - Progress Built in: showProgress:true will change the button to a progress |
---|
| 81 | // bar on upload. |
---|
| 82 | // - Progress Attach: Passing progressWidgetId will tell the Uploader of a progress |
---|
| 83 | // widget. If the Progress widget is initially hidden, it will change to |
---|
| 84 | // visible and then restored after upload. |
---|
| 85 | // - A11Y: The Flash button can be accessed with the TAB key. (The HTML cannot due |
---|
| 86 | // to browser limitations) |
---|
| 87 | // - Deferred Uploading: (Flash only) throttles the upload to one file at a time |
---|
| 88 | // |
---|
| 89 | // ###CDN USERS |
---|
| 90 | // |
---|
| 91 | // FileUpload now works with the CDN but with limitations. The SWF must |
---|
| 92 | // be from the same domain as the HTML page. 'swfPath' has been exposed |
---|
| 93 | // so that you may link to that file (could of course be the same SWF in |
---|
| 94 | // dojox resource folder). The SWF will *NOT* work from the |
---|
| 95 | // CDN server. This would require a special XML file that would allow |
---|
| 96 | // access to your server, and the logistics to that is impossible. |
---|
| 97 | // |
---|
| 98 | // ###LIMITATIONS |
---|
| 99 | // |
---|
| 100 | // - This is not designed to be a part of a form, it contains its own. (See submit()) |
---|
| 101 | // - Currently does not in a Dialog box or a Tab where it is not initially visible, |
---|
| 102 | // - The default style inherits font sizes - but a parent container should have a font size |
---|
| 103 | // set somewhere of the results could be inconsistent. |
---|
| 104 | // |
---|
| 105 | // ###OPERA USERS |
---|
| 106 | // |
---|
| 107 | // It works better than the 1.3 version. fileInputs apperantly can't have opacity |
---|
| 108 | // set to zero. The Flash uploader works but files are auto-uploaded. Must be a |
---|
| 109 | // flashVar problem. |
---|
| 110 | // |
---|
| 111 | // ###Safari Bug note: |
---|
| 112 | // |
---|
| 113 | // The bug is in the way Safari handles the connection: |
---|
| 114 | // https://bugs.webkit.org/show_bug.cgi?id=5760 |
---|
| 115 | // I added this to the virtual host in the Apache conf file, and now it |
---|
| 116 | // works like a charm: |
---|
| 117 | // | BrowserMatch Safari nokeepalive |
---|
| 118 | |
---|
| 119 | swfPath: config.uploaderPath || require.toUrl("dojox/form/resources/fileuploader.swf"), |
---|
| 120 | |
---|
| 121 | |
---|
| 122 | templateString:'<div><div dojoAttachPoint="progNode"><div dojoAttachPoint="progTextNode"></div></div><div dojoAttachPoint="insideNode" class="uploaderInsideNode"></div></div>', |
---|
| 123 | |
---|
| 124 | // uploadUrl: String |
---|
| 125 | // The url targeted for upload. An absolute URL is preferred. Relative URLs are |
---|
| 126 | // changed to absolute. |
---|
| 127 | uploadUrl: "", |
---|
| 128 | |
---|
| 129 | // isDebug: Boolean |
---|
| 130 | // If true, outputs traces from the SWF to console. What exactly gets passed |
---|
| 131 | // is very relative, and depends upon what traces have been left in the DEFT SWF. |
---|
| 132 | isDebug:false, |
---|
| 133 | |
---|
| 134 | // devMode: Boolean |
---|
| 135 | // Re-implemented. devMode increases the logging, adding style tracing from the SWF. |
---|
| 136 | devMode:false, |
---|
| 137 | |
---|
| 138 | /*===== |
---|
| 139 | // id: String |
---|
| 140 | // The object id, just like any other widget in Dojo. However, this id |
---|
| 141 | // is also used as a reference for the SWF |
---|
| 142 | id: "", |
---|
| 143 | =====*/ |
---|
| 144 | |
---|
| 145 | // baseClass: String |
---|
| 146 | // The name of the class that will style the button in a "normal" state. |
---|
| 147 | // If baseClass is not defined, 'class' will be used. |
---|
| 148 | // NOTE: By default the uploader will be styled like a dijit buttons and |
---|
| 149 | // adhere to the the themes. Tundra, Soria, and Nihilo are supported. |
---|
| 150 | // You can cascade the existing style by using 'class' or 'style'. If you |
---|
| 151 | // overwrite baseClass, you should overwrite the remaing state classes |
---|
| 152 | // that follow) as well. |
---|
| 153 | baseClass:"dojoxUploaderNorm", |
---|
| 154 | |
---|
| 155 | // hoverClass: String |
---|
| 156 | // The name of the class that will style the button in a "hover" state. A specific |
---|
| 157 | // class should be made to do this. Do not rely on a target like button:hover{...} |
---|
| 158 | hoverClass:"dojoxUploaderHover", |
---|
| 159 | |
---|
| 160 | // activeClass: String |
---|
| 161 | // The name of the class that will style the button in a "press" state. A specific |
---|
| 162 | // class should be made to do this. Do not rely on a target like button:active{...} |
---|
| 163 | activeClass:"dojoxUploaderActive", |
---|
| 164 | |
---|
| 165 | // disabledClass: String |
---|
| 166 | // The name of the class that will style the button when its disabled. |
---|
| 167 | disabledClass:"dojoxUploaderDisabled", |
---|
| 168 | |
---|
| 169 | // force: String |
---|
| 170 | // Use "flash" to always use Flash (and hopefully force the user to download the plugin |
---|
| 171 | // if they don't have it). Use "html" to always use the HTML uploader. An empty string |
---|
| 172 | // (default) will check for the right version of Flash and use HTML if not available. |
---|
| 173 | force:"", |
---|
| 174 | |
---|
| 175 | // uploaderType: [readonly] String |
---|
| 176 | // Internal. What type of uploader is being used: "flash" or "html" |
---|
| 177 | uploaderType:"", |
---|
| 178 | |
---|
| 179 | // flashObject: [readonly] dojox.embed.Flash |
---|
| 180 | // The object that creates the SWF embed object. Mostly Internal. |
---|
| 181 | flashObject: null, |
---|
| 182 | |
---|
| 183 | // flashMovie: [readonly] Function |
---|
| 184 | // The SWF. Mostly Internal. |
---|
| 185 | flashMovie: null, |
---|
| 186 | |
---|
| 187 | // insideNode: [readonly] HTMLNode |
---|
| 188 | // The div that holds the SWF and form/fileInput |
---|
| 189 | insideNode: null, |
---|
| 190 | |
---|
| 191 | // deferredUploading: Number (1 - X) |
---|
| 192 | // (Flash only) throttles the upload to a certain amount of files at a time. |
---|
| 193 | // By default, Flash uploads file one at a time to the server, but in parallel. |
---|
| 194 | // Firefox will try to queue all files at once, leading to problems. Set this |
---|
| 195 | // to the amount to upload in parallel at a time. |
---|
| 196 | // Generally, 1 should work fine, but you can experiment with queuing more than |
---|
| 197 | // one at a time. |
---|
| 198 | // This is of course ignored if selectMultipleFiles equals false. |
---|
| 199 | deferredUploading: 1, |
---|
| 200 | |
---|
| 201 | // fileListId: String |
---|
| 202 | // The id of a dom node to be used as a container for the pending file list. |
---|
| 203 | fileListId:"", |
---|
| 204 | |
---|
| 205 | // uploadOnChange: Boolean |
---|
| 206 | // If true, uploads immediately after a file has been selected. If false, |
---|
| 207 | // waits for upload() to be called. |
---|
| 208 | uploadOnChange: false, |
---|
| 209 | |
---|
| 210 | // selectMultipleFiles: Boolean |
---|
| 211 | // If true and flash mode, multiple files may be selected from the dialog. |
---|
| 212 | // If html mode, files are not uploaded until upload() is called. The references |
---|
| 213 | // to each file is incremented:uploadedfile0, uploadedfile1, uploadedfile2... etc. |
---|
| 214 | selectMultipleFiles: true, |
---|
| 215 | |
---|
| 216 | // htmlFieldName: String |
---|
| 217 | // The name of the field of the fileInput that the server is expecting |
---|
| 218 | htmlFieldName:"uploadedfile", |
---|
| 219 | |
---|
| 220 | // flashFieldName: String |
---|
| 221 | // The name of the field of the flash uploaded files that the server is expecting |
---|
| 222 | flashFieldName:"flashUploadFiles", |
---|
| 223 | |
---|
| 224 | // fileMask: Array[ Array[Description, FileTypes], Array[...]...] |
---|
| 225 | // (an array, or an array of arrays) |
---|
| 226 | // Restrict file selection to certain file types |
---|
| 227 | // Empty array defaults to "All Files" |
---|
| 228 | // |
---|
| 229 | // example: |
---|
| 230 | // |
---|
| 231 | // | fileMask = ["Images", "*.jpg;*.jpeg;*.gif;*.png"] |
---|
| 232 | // or |
---|
| 233 | // | fileMask = [ |
---|
| 234 | // | ["Jpeg File", "*.jpg;*.jpeg"], |
---|
| 235 | // | ["GIF File", "*.gif"], |
---|
| 236 | // | ["PNG File", "*.png"], |
---|
| 237 | // | ["All Images", "*.jpg;*.jpeg;*.gif;*.png"], |
---|
| 238 | // | ] |
---|
| 239 | // |
---|
| 240 | // NOTE: MacType is not supported, as it does not work very well. |
---|
| 241 | // fileMask will work on a Mac, but differently than |
---|
| 242 | // Windows. |
---|
| 243 | fileMask: null, |
---|
| 244 | |
---|
| 245 | // minFlashVersion: Number |
---|
| 246 | // The minimum of version of Flash player to target. 0 would always install Flash, 100 |
---|
| 247 | // would never install it. The Flash Player has supported multiple uploads since |
---|
| 248 | // version 8, so it could go as low as that safely. |
---|
| 249 | minFlashVersion:9, |
---|
| 250 | |
---|
| 251 | // tabIndex: Number|String |
---|
| 252 | // The tab order in the DOM. Only supported by Flash. HTML Uploaders have security |
---|
| 253 | // protection to prevent you from tabbing to the uploader. Stupid. |
---|
| 254 | tabIndex:-1, |
---|
| 255 | |
---|
| 256 | // showProgress: Boolean |
---|
| 257 | // If true, the button changes to a progress bar during upload. |
---|
| 258 | showProgress:false, |
---|
| 259 | |
---|
| 260 | // progressMessage: String |
---|
| 261 | // The message shown while the button is changed to a progress bar |
---|
| 262 | progressMessage:"Loading", |
---|
| 263 | |
---|
| 264 | // progressBackgroundUrl: String|Uri |
---|
| 265 | // The background image to use for the button-progress |
---|
| 266 | progressBackgroundUrl:require.toUrl("dijit/themes/tundra/images/buttonActive.png"), |
---|
| 267 | |
---|
| 268 | // progressBackgroundColor: String|Number |
---|
| 269 | // The background color to use for the button-progress |
---|
| 270 | progressBackgroundColor:"#ededed", |
---|
| 271 | |
---|
| 272 | // progressWidgetId:String |
---|
| 273 | // The widget id of a Dijit Progress bar. The Uploader will bind to it and update it |
---|
| 274 | // automatically. |
---|
| 275 | progressWidgetId:"", |
---|
| 276 | |
---|
| 277 | // skipServerCheck: Boolean |
---|
| 278 | // If true, will not verify that the server was sent the correct format. |
---|
| 279 | // This can be safely set to true. The purpose of the server side check |
---|
| 280 | // is mainly to show the dev if they've implemented the different returns |
---|
| 281 | // correctly. |
---|
| 282 | skipServerCheck:false, |
---|
| 283 | |
---|
| 284 | // serverTimeout:Number (milliseconds) |
---|
| 285 | // The amount of time given to the uploaded file |
---|
| 286 | // to wait for a server response. After this amount |
---|
| 287 | // of time, the onComplete is fired but with a 'server timeout' |
---|
| 288 | // error in the returned item. |
---|
| 289 | serverTimeout: 5000, |
---|
| 290 | |
---|
| 291 | |
---|
| 292 | log: function(){ |
---|
| 293 | // summary: |
---|
| 294 | // Due to the excessive logging necessary to make this code happen, |
---|
| 295 | // It's easier to turn it on and off here in one place. |
---|
| 296 | // Also helpful if there are multiple uploaders on one page. |
---|
| 297 | if(this.isDebug){ |
---|
| 298 | console["log"](Array.prototype.slice.call(arguments).join(" ")); |
---|
| 299 | } |
---|
| 300 | }, |
---|
| 301 | |
---|
| 302 | constructor: function(){ |
---|
| 303 | this._subs = []; |
---|
| 304 | }, |
---|
| 305 | |
---|
| 306 | postMixInProperties: function(){ |
---|
| 307 | // internal stuff: |
---|
| 308 | this.fileList = []; |
---|
| 309 | this._cons = []; |
---|
| 310 | this.fileMask = this.fileMask || []; |
---|
| 311 | this.fileInputs = []; |
---|
| 312 | this.fileCount = 0; |
---|
| 313 | this.flashReady = false; |
---|
| 314 | this._disabled = false; |
---|
| 315 | this.force = this.force.toLowerCase(); // Pete FTW. |
---|
| 316 | this.uploaderType = ((embedFlash.available >= this.minFlashVersion || this.force=="flash") && this.force != "html") ? "flash" : "html"; |
---|
| 317 | this.deferredUploading = this.deferredUploading===true ? 1 : this.deferredUploading; |
---|
| 318 | |
---|
| 319 | this._refNode = this.srcNodeRef; |
---|
| 320 | |
---|
| 321 | this.getButtonStyle(); |
---|
| 322 | }, |
---|
| 323 | |
---|
| 324 | startup: function(){ |
---|
| 325 | }, |
---|
| 326 | |
---|
| 327 | postCreate: function(){ |
---|
| 328 | this.inherited(arguments); |
---|
| 329 | |
---|
| 330 | // internal stuff: |
---|
| 331 | this.setButtonStyle(); |
---|
| 332 | var createMethod; |
---|
| 333 | if(this.uploaderType == "flash"){ |
---|
| 334 | createMethod = "createFlashUploader"; |
---|
| 335 | }else{ |
---|
| 336 | this.uploaderType = "html"; |
---|
| 337 | createMethod = "createHtmlUploader"; |
---|
| 338 | |
---|
| 339 | } |
---|
| 340 | |
---|
| 341 | this[createMethod](); |
---|
| 342 | |
---|
| 343 | if(this.fileListId){ |
---|
| 344 | this.connect(dom.byId(this.fileListId), "click", function(evt){ |
---|
| 345 | var p = evt.target.parentNode.parentNode.parentNode; // in a table |
---|
| 346 | if(p.id && p.id.indexOf("file_")>-1){ |
---|
| 347 | this.removeFile(p.id.split("file_")[1]); |
---|
| 348 | } |
---|
| 349 | }); |
---|
| 350 | } |
---|
| 351 | |
---|
| 352 | // cleaning up solves memory leak issues in the HTML version |
---|
| 353 | unloadUtils.addOnUnload(this, this.destroy); |
---|
| 354 | }, |
---|
| 355 | |
---|
| 356 | getHiddenNode: function(/*DomNode*/ node){ |
---|
| 357 | // summary: |
---|
| 358 | // Internal. |
---|
| 359 | // If a parent node is styled as display:none, |
---|
| 360 | // returns that node. This node will be temporarilly |
---|
| 361 | // changed to display:block. Note if the node is in |
---|
| 362 | // a widget that has an onShow event, this is |
---|
| 363 | // overridden. |
---|
| 364 | |
---|
| 365 | if(!node){ return null; } |
---|
| 366 | var hidden = null; |
---|
| 367 | var p = node.parentNode; |
---|
| 368 | while(p && p.tagName.toLowerCase() != "body"){ |
---|
| 369 | var d = domStyle.get(p, "display"); |
---|
| 370 | if(d == "none"){ |
---|
| 371 | hidden = p; |
---|
| 372 | break; |
---|
| 373 | } |
---|
| 374 | p = p.parentNode; |
---|
| 375 | } |
---|
| 376 | return hidden; |
---|
| 377 | }, |
---|
| 378 | |
---|
| 379 | getButtonStyle: function(){ |
---|
| 380 | // summary: |
---|
| 381 | // Internal. |
---|
| 382 | // Get necessary style information from srcRefNode and |
---|
| 383 | // assigned styles |
---|
| 384 | // |
---|
| 385 | |
---|
| 386 | |
---|
| 387 | // TODO: |
---|
| 388 | // To call this from postCreate.... |
---|
| 389 | // could do the style stuff initially, but if hidden they will be bad sizes |
---|
| 390 | // could then redo the sizes |
---|
| 391 | // alt is to create a genuine button and copy THAT instead of how doing now |
---|
| 392 | |
---|
| 393 | var refNode = this.srcNodeRef; |
---|
| 394 | this._hiddenNode = this.getHiddenNode(refNode); |
---|
| 395 | if(this._hiddenNode){ |
---|
| 396 | domStyle.set(this._hiddenNode, "display", "block"); |
---|
| 397 | } |
---|
| 398 | |
---|
| 399 | if(!refNode && this.button && this.button.domNode){ |
---|
| 400 | // backwards compat for a Dijit button |
---|
| 401 | var isDijitButton = true; |
---|
| 402 | var cls = this.button.domNode.className + " dijitButtonNode"; |
---|
| 403 | var txt = this.getText(query(".dijitButtonText", this.button.domNode)[0]); |
---|
| 404 | var domTxt = '<button id="'+this.button.id+'" class="'+cls+'">'+txt+'</button>'; |
---|
| 405 | refNode = domConstruct.place(domTxt, this.button.domNode, "after"); /// Pete doesn't like this? |
---|
| 406 | this.srcNodeRef = refNode; |
---|
| 407 | this.button.destroy(); |
---|
| 408 | |
---|
| 409 | this.baseClass = "dijitButton"; |
---|
| 410 | this.hoverClass = "dijitButtonHover"; |
---|
| 411 | this.pressClass = "dijitButtonActive"; |
---|
| 412 | this.disabledClass = "dijitButtonDisabled"; |
---|
| 413 | |
---|
| 414 | }else if(!this.srcNodeRef && this.button){ |
---|
| 415 | refNode = this.button; |
---|
| 416 | } |
---|
| 417 | |
---|
| 418 | if(domAttr.get(refNode, "class")){ |
---|
| 419 | this.baseClass += " " + domAttr.get(refNode, "class"); |
---|
| 420 | } |
---|
| 421 | domAttr.set(refNode, "class", this.baseClass); |
---|
| 422 | |
---|
| 423 | |
---|
| 424 | this.norm = this.getStyle(refNode); |
---|
| 425 | this.width = this.norm.w; |
---|
| 426 | this.height = this.norm.h; |
---|
| 427 | |
---|
| 428 | if(this.uploaderType == "flash"){ |
---|
| 429 | |
---|
| 430 | this.over = this.getTempNodeStyle(refNode, this.baseClass+" "+this.hoverClass, isDijitButton); |
---|
| 431 | this.down = this.getTempNodeStyle(refNode, this.baseClass+" "+this.activeClass, isDijitButton); |
---|
| 432 | this.dsbl = this.getTempNodeStyle(refNode, this.baseClass+" "+this.disabledClass, isDijitButton); |
---|
| 433 | |
---|
| 434 | this.fhtml = { |
---|
| 435 | cn:this.getText(refNode), |
---|
| 436 | nr:this.norm, |
---|
| 437 | ov:this.over, |
---|
| 438 | dn:this.down, |
---|
| 439 | ds:this.dsbl |
---|
| 440 | }; |
---|
| 441 | }else{ |
---|
| 442 | this.fhtml = { |
---|
| 443 | cn:this.getText(refNode), |
---|
| 444 | nr:this.norm |
---|
| 445 | } |
---|
| 446 | if(this.norm.va == "middle"){ |
---|
| 447 | this.norm.lh = this.norm.h; |
---|
| 448 | } |
---|
| 449 | } |
---|
| 450 | |
---|
| 451 | if(this.devMode){ |
---|
| 452 | this.log("classes - base:", this.baseClass, " hover:", this.hoverClass, "active:", this.activeClass); |
---|
| 453 | this.log("fhtml:", this.fhtml) |
---|
| 454 | this.log("norm:", this.norm) |
---|
| 455 | this.log("over:", this.over) |
---|
| 456 | this.log("down:", this.down) |
---|
| 457 | } |
---|
| 458 | }, |
---|
| 459 | |
---|
| 460 | setButtonStyle: function(){ |
---|
| 461 | // summary: |
---|
| 462 | // Internal. |
---|
| 463 | // Set up internal dom nodes for button construction. |
---|
| 464 | |
---|
| 465 | domStyle.set(this.domNode, { |
---|
| 466 | width:this.fhtml.nr.w+"px", |
---|
| 467 | height:(this.fhtml.nr.h)+"px", |
---|
| 468 | padding:"0px", |
---|
| 469 | lineHeight: "normal", |
---|
| 470 | position:"relative" |
---|
| 471 | }); |
---|
| 472 | if(this.uploaderType == "html" && this.norm.va == "middle"){ |
---|
| 473 | domStyle.set(this.domNode, "lineHeight", this.norm.lh + "px"); |
---|
| 474 | } |
---|
| 475 | if(this.showProgress){ |
---|
| 476 | this.progTextNode.innerHTML = this.progressMessage; |
---|
| 477 | domStyle.set(this.progTextNode, { |
---|
| 478 | width:this.fhtml.nr.w+"px", |
---|
| 479 | height:(this.fhtml.nr.h+0)+"px", |
---|
| 480 | padding:"0px", |
---|
| 481 | margin:"0px", |
---|
| 482 | left:"0px", |
---|
| 483 | lineHeight:(this.fhtml.nr.h+0)+"px", |
---|
| 484 | position:"absolute" |
---|
| 485 | }); |
---|
| 486 | domStyle.set(this.progNode, { |
---|
| 487 | width:this.fhtml.nr.w+"px", |
---|
| 488 | height:(this.fhtml.nr.h+0)+"px", |
---|
| 489 | padding:"0px", |
---|
| 490 | margin:"0px", |
---|
| 491 | left:"0px", |
---|
| 492 | position:"absolute", |
---|
| 493 | display:"none", |
---|
| 494 | backgroundImage:"url("+this.progressBackgroundUrl+")", |
---|
| 495 | backgroundPosition:"bottom", |
---|
| 496 | backgroundRepeat:"repeat-x", |
---|
| 497 | backgroundColor:this.progressBackgroundColor |
---|
| 498 | }); |
---|
| 499 | }else{ |
---|
| 500 | domConstruct.destroy(this.progNode); |
---|
| 501 | } |
---|
| 502 | domStyle.set(this.insideNode,{ |
---|
| 503 | position:"absolute", |
---|
| 504 | top:"0px", |
---|
| 505 | left:"0px", |
---|
| 506 | display:"" |
---|
| 507 | }); |
---|
| 508 | domClass.add(this.domNode, this.srcNodeRef.className); |
---|
| 509 | if(this.fhtml.nr.d.indexOf("inline")>-1){ |
---|
| 510 | domClass.add(this.domNode, "dijitInline"); |
---|
| 511 | } |
---|
| 512 | |
---|
| 513 | try{ |
---|
| 514 | this.insideNode.innerHTML = this.fhtml.cn; |
---|
| 515 | }catch(e){ |
---|
| 516 | // You have got to be kidding me. IE does us he favor of checking that |
---|
| 517 | // we aren't inserting the improper type of content with innerHTML into |
---|
| 518 | // an inline element. Alert us with an "Unknown Runtime Error". You can't |
---|
| 519 | // MAKE this stuff up. |
---|
| 520 | |
---|
| 521 | if(this.uploaderType == "flash"){ |
---|
| 522 | this.insideNode = this.insideNode.parentNode.removeChild(this.insideNode); |
---|
| 523 | win.body().appendChild(this.insideNode); |
---|
| 524 | this.insideNode.innerHTML = this.fhtml.cn; |
---|
| 525 | var c = connect.connect(this, "onReady", this, function(){ connect.disconnect(c); |
---|
| 526 | this.insideNode = this.insideNode.parentNode.removeChild(this.insideNode); |
---|
| 527 | this.domNode.appendChild(this.insideNode); |
---|
| 528 | }); |
---|
| 529 | }else{ |
---|
| 530 | this.insideNode.appendChild(document.createTextNode(this.fhtml.cn)); |
---|
| 531 | } |
---|
| 532 | } |
---|
| 533 | if(this._hiddenNode){ |
---|
| 534 | domStyle.set(this._hiddenNode, "display", "none"); |
---|
| 535 | } |
---|
| 536 | }, |
---|
| 537 | |
---|
| 538 | |
---|
| 539 | /************************* |
---|
| 540 | * Public Events * |
---|
| 541 | *************************/ |
---|
| 542 | |
---|
| 543 | // The following events are inherited from _Widget and still may be connected: |
---|
| 544 | // onClick |
---|
| 545 | // onMouseUp |
---|
| 546 | // onMouseDown |
---|
| 547 | // onMouseOver |
---|
| 548 | // onMouseOut |
---|
| 549 | |
---|
| 550 | onChange: function(dataArray){ |
---|
| 551 | // summary: |
---|
| 552 | // stub to connect |
---|
| 553 | // Fires when files are selected |
---|
| 554 | // Event is an array of last files selected |
---|
| 555 | }, |
---|
| 556 | |
---|
| 557 | onProgress: function(dataArray){ |
---|
| 558 | // summary: |
---|
| 559 | // Stub to connect |
---|
| 560 | // Fires as progress returns from SWF |
---|
| 561 | // Event is an array of all files uploading |
---|
| 562 | // Can be connected to for HTML uploader, |
---|
| 563 | // but will not return anything. |
---|
| 564 | }, |
---|
| 565 | |
---|
| 566 | onComplete: function(dataArray){ |
---|
| 567 | // summary: |
---|
| 568 | // stub to connect |
---|
| 569 | // Fires when all files have uploaded |
---|
| 570 | // Event is an array of all files |
---|
| 571 | }, |
---|
| 572 | |
---|
| 573 | onCancel: function(){ |
---|
| 574 | // summary: |
---|
| 575 | // Stub to connect |
---|
| 576 | // Fires when dialog box has been closed |
---|
| 577 | // without a file selection |
---|
| 578 | }, |
---|
| 579 | |
---|
| 580 | onError: function(/*Object or String*/ evtObject){ |
---|
| 581 | // summary: |
---|
| 582 | // Fires on errors |
---|
| 583 | |
---|
| 584 | // FIXME: Unsure of a standard form for receiving errors |
---|
| 585 | }, |
---|
| 586 | |
---|
| 587 | onReady: function(/*dojox.form.FileUploader*/ uploader){ |
---|
| 588 | // summary: |
---|
| 589 | // Stub - Fired when embedFlash has created the |
---|
| 590 | // Flash object, but it has not necessarilly finished |
---|
| 591 | // downloading, and is ready to be communicated with. |
---|
| 592 | }, |
---|
| 593 | |
---|
| 594 | onLoad: function(/*dojox.form.FileUploader*/ uploader){ |
---|
| 595 | // summary: |
---|
| 596 | // Stub - SWF has been downloaded 100%. |
---|
| 597 | }, |
---|
| 598 | |
---|
| 599 | /************************* |
---|
| 600 | * Public Methods * |
---|
| 601 | *************************/ |
---|
| 602 | submit: function(/*form node ?*/ form){ |
---|
| 603 | // summary: |
---|
| 604 | // If FileUploader is in a form, and other data should be sent |
---|
| 605 | // along with the files, use this instead of form submit. |
---|
| 606 | |
---|
| 607 | var data = form ? domForm.toObject(form) : null; |
---|
| 608 | this.upload(data); |
---|
| 609 | return false; // Boolean |
---|
| 610 | }, |
---|
| 611 | upload: function(/*Object ? */ data){ |
---|
| 612 | // summary: |
---|
| 613 | // When called, begins file upload |
---|
| 614 | // data: Object |
---|
| 615 | // postData to be sent to server |
---|
| 616 | |
---|
| 617 | if(!this.fileList.length){ |
---|
| 618 | return false; |
---|
| 619 | } |
---|
| 620 | if(!this.uploadUrl){ |
---|
| 621 | console.warn("uploadUrl not provided. Aborting."); |
---|
| 622 | return false; |
---|
| 623 | } |
---|
| 624 | if(!this.showProgress){ |
---|
| 625 | this.set("disabled", true); |
---|
| 626 | } |
---|
| 627 | |
---|
| 628 | if(this.progressWidgetId){ |
---|
| 629 | |
---|
| 630 | var node = manager.byId(this.progressWidgetId).domNode; |
---|
| 631 | if(domStyle.get(node, "display") == "none"){ |
---|
| 632 | this.restoreProgDisplay = "none"; |
---|
| 633 | domStyle.set(node, "display", "block"); |
---|
| 634 | } |
---|
| 635 | if(domStyle.get(node, "visibility") == "hidden"){ |
---|
| 636 | this.restoreProgDisplay = "hidden"; |
---|
| 637 | domStyle.set(node, "visibility", "visible"); |
---|
| 638 | } |
---|
| 639 | } |
---|
| 640 | |
---|
| 641 | if(data && !data.target){ |
---|
| 642 | this.postData = data; |
---|
| 643 | } |
---|
| 644 | this.log("upload type:", this.uploaderType, " - postData:", this.postData); |
---|
| 645 | |
---|
| 646 | for(var i = 0; i < this.fileList.length; i++){ |
---|
| 647 | var f = this.fileList[i]; |
---|
| 648 | f.bytesLoaded = 0; |
---|
| 649 | f.bytesTotal = f.size || 100000; |
---|
| 650 | f.percent = 0; |
---|
| 651 | } |
---|
| 652 | if(this.uploaderType == "flash"){ |
---|
| 653 | this.uploadFlash(); |
---|
| 654 | }else{ |
---|
| 655 | this.uploadHTML(); |
---|
| 656 | } |
---|
| 657 | // prevent form submit |
---|
| 658 | return false; |
---|
| 659 | }, |
---|
| 660 | removeFile: function(/*String*/ name, /*Boolean*/ noListEdit){ |
---|
| 661 | // summary: |
---|
| 662 | // Removes a file from the pending file list. |
---|
| 663 | // Removes pending data from the Flash movie |
---|
| 664 | // and fileInputes from the HTML uploader. |
---|
| 665 | // If a file container node is bound, the file |
---|
| 666 | // will also be removed. |
---|
| 667 | // name: String |
---|
| 668 | // The name of the file to be removed. Typically the file name, |
---|
| 669 | // such as: picture01.png |
---|
| 670 | // noListEdit: Boolean |
---|
| 671 | // Internal. If true don't remove files from list. |
---|
| 672 | |
---|
| 673 | var i; |
---|
| 674 | for(i = 0; i < this.fileList.length; i++){ |
---|
| 675 | if(this.fileList[i].name == name){ |
---|
| 676 | if(!noListEdit){ // if onComplete, don't do this |
---|
| 677 | this.fileList.splice(i,1); |
---|
| 678 | } |
---|
| 679 | break; |
---|
| 680 | } |
---|
| 681 | } |
---|
| 682 | if(this.uploaderType == "flash"){ |
---|
| 683 | this.flashMovie.removeFile(name); |
---|
| 684 | }else if(!noListEdit){ |
---|
| 685 | domConstruct.destroy(this.fileInputs[i]); |
---|
| 686 | this.fileInputs.splice(i,1); |
---|
| 687 | this._renumberInputs(); |
---|
| 688 | } |
---|
| 689 | if(this.fileListId){ |
---|
| 690 | domConstruct.destroy("file_"+name); |
---|
| 691 | } |
---|
| 692 | }, |
---|
| 693 | |
---|
| 694 | destroy: function(){ |
---|
| 695 | // summary: |
---|
| 696 | // Destroys uploader button |
---|
| 697 | if(this.uploaderType == "flash" && !this.flashMovie){ |
---|
| 698 | this._cons.push(connect.connect(this, "onLoad", this, "destroy")); |
---|
| 699 | return; |
---|
| 700 | } |
---|
| 701 | array.forEach(this._subs, connect.unsubscribe, dojo); |
---|
| 702 | array.forEach(this._cons, connect.disconnect, dojo); |
---|
| 703 | if(this.scrollConnect){ |
---|
| 704 | connect.disconnect(this.scrollConnect); |
---|
| 705 | } |
---|
| 706 | if(this.uploaderType == "flash"){ |
---|
| 707 | this.flashObject.destroy(); |
---|
| 708 | delete this.flashObject; |
---|
| 709 | }else{ |
---|
| 710 | domConstruct.destroy(this._fileInput); |
---|
| 711 | domConstruct.destroy(this._formNode); |
---|
| 712 | } |
---|
| 713 | this.inherited(arguments); |
---|
| 714 | }, |
---|
| 715 | |
---|
| 716 | /************************* |
---|
| 717 | * Private Events * |
---|
| 718 | *************************/ |
---|
| 719 | _displayProgress: function(/*Boolean or Number */ display){ |
---|
| 720 | // summary: |
---|
| 721 | // Shows and updates the built-in progress bar. |
---|
| 722 | |
---|
| 723 | if(display === true){ |
---|
| 724 | if(this.uploaderType == "flash"){ |
---|
| 725 | domStyle.set(this.insideNode,"top", "-2500px"); |
---|
| 726 | }else{ |
---|
| 727 | domStyle.set(this.insideNode,"display", "none"); |
---|
| 728 | } |
---|
| 729 | domStyle.set(this.progNode,"display",""); |
---|
| 730 | }else if(display === false){ |
---|
| 731 | domStyle.set(this.insideNode,{ |
---|
| 732 | display: "", |
---|
| 733 | top: "0" |
---|
| 734 | }); |
---|
| 735 | domStyle.set(this.progNode,"display","none"); |
---|
| 736 | }else{ |
---|
| 737 | var w = display * this.fhtml.nr.w; |
---|
| 738 | domStyle.set(this.progNode, "width", w + "px"); |
---|
| 739 | } |
---|
| 740 | }, |
---|
| 741 | _animateProgress: function(){ |
---|
| 742 | // summary: |
---|
| 743 | // Internal. Animated the built-in progress bar |
---|
| 744 | this._displayProgress(true); |
---|
| 745 | var _uploadDone = false; |
---|
| 746 | var c = connect.connect(this, "_complete", function(){ |
---|
| 747 | connect.disconnect(c); |
---|
| 748 | _uploadDone = true; |
---|
| 749 | }); |
---|
| 750 | var w = 0; |
---|
| 751 | var interval = setInterval(lang.hitch(this, function(){ |
---|
| 752 | w+=5; |
---|
| 753 | if(w>this.fhtml.nr.w){ |
---|
| 754 | w = 0; |
---|
| 755 | _uploadDone = true; |
---|
| 756 | } |
---|
| 757 | this._displayProgress(w/this.fhtml.nr.w); |
---|
| 758 | |
---|
| 759 | if(_uploadDone){ |
---|
| 760 | clearInterval(interval); |
---|
| 761 | setTimeout(lang.hitch(this, function(){ |
---|
| 762 | this._displayProgress(false); |
---|
| 763 | }), 500); |
---|
| 764 | } |
---|
| 765 | |
---|
| 766 | }),50); |
---|
| 767 | }, |
---|
| 768 | |
---|
| 769 | _error: function(evt){ |
---|
| 770 | //var type = evtObject.type ? evtObject.type.toUpperCase() : "ERROR"; |
---|
| 771 | //var msg = evtObject.msg ? evtObject.msg : evtObject; |
---|
| 772 | if(typeof(evt)=="string"){ |
---|
| 773 | evt = new Error(evt); |
---|
| 774 | } |
---|
| 775 | this.onError(evt); |
---|
| 776 | }, |
---|
| 777 | |
---|
| 778 | _addToFileList: function(){ |
---|
| 779 | // summary: |
---|
| 780 | // Internal only. If there is a file list, adds a file to it. |
---|
| 781 | // If you need to use a function such as this, connect to |
---|
| 782 | // onChange and update outside of this widget. |
---|
| 783 | |
---|
| 784 | if(this.fileListId){ |
---|
| 785 | var str = ''; |
---|
| 786 | array.forEach(this.fileList, function(d){ |
---|
| 787 | // have to use tables because of IE. Grumble. |
---|
| 788 | str += '<table id="file_'+d.name+'" class="fileToUpload"><tr><td class="fileToUploadClose"></td><td class="fileToUploadName">'+d.name+'</td><td class="fileToUploadSize">'+(d.size ? Math.ceil(d.size*.001) +"kb" : "")+'</td></tr></table>' |
---|
| 789 | }, this); |
---|
| 790 | dom.byId(this.fileListId).innerHTML = str; |
---|
| 791 | } |
---|
| 792 | }, |
---|
| 793 | |
---|
| 794 | _change: function(dataArray){ |
---|
| 795 | // summary: |
---|
| 796 | // Internal. Updates uploader selection |
---|
| 797 | if(has("ie")){ |
---|
| 798 | //IE6 uses the entire path in the name, which isn't terrible, but much different |
---|
| 799 | // than everything else |
---|
| 800 | array.forEach(dataArray, function(f){ |
---|
| 801 | f.name = f.name.split("\\")[f.name.split("\\").length-1]; |
---|
| 802 | }); |
---|
| 803 | } |
---|
| 804 | if(this.selectMultipleFiles){ |
---|
| 805 | this.fileList = this.fileList.concat(dataArray); |
---|
| 806 | }else{ |
---|
| 807 | if(this.fileList[0]){ |
---|
| 808 | this.removeFile(this.fileList[0].name, true); |
---|
| 809 | } |
---|
| 810 | this.fileList = dataArray; |
---|
| 811 | } |
---|
| 812 | this._addToFileList(); |
---|
| 813 | this.onChange(dataArray); |
---|
| 814 | if(this.uploadOnChange){ |
---|
| 815 | if(this.uploaderType == "html"){ |
---|
| 816 | this._buildFileInput(); |
---|
| 817 | } |
---|
| 818 | this.upload(); |
---|
| 819 | }else if(this.uploaderType == "html" && this.selectMultipleFiles){ |
---|
| 820 | this._buildFileInput(); |
---|
| 821 | this._connectInput(); |
---|
| 822 | } |
---|
| 823 | }, |
---|
| 824 | |
---|
| 825 | _complete: function(dataArray){ |
---|
| 826 | // summary: |
---|
| 827 | // Internal. Handles tasks after files have finished uploading |
---|
| 828 | |
---|
| 829 | dataArray = lang.isArray(dataArray) ? dataArray : [dataArray]; |
---|
| 830 | |
---|
| 831 | // Yes. Yes I do have to do three loops here. ugh. |
---|
| 832 | // |
---|
| 833 | // Check if one of the files had an error |
---|
| 834 | array.forEach(dataArray, function(f){ |
---|
| 835 | if(f.ERROR){ this._error(f.ERROR); } |
---|
| 836 | }, this); |
---|
| 837 | |
---|
| 838 | // Have to be set them all too 100%, because |
---|
| 839 | // onProgress does not always fire |
---|
| 840 | array.forEach(this.fileList, function(f){ |
---|
| 841 | f.bytesLoaded = 1; |
---|
| 842 | f.bytesTotal = 1; |
---|
| 843 | f.percent = 100; |
---|
| 844 | this._progress(f); |
---|
| 845 | }, this); |
---|
| 846 | // we're done. remove files. |
---|
| 847 | array.forEach(this.fileList, function(f){ |
---|
| 848 | this.removeFile(f.name, true); |
---|
| 849 | }, this); |
---|
| 850 | |
---|
| 851 | this.onComplete(dataArray); |
---|
| 852 | |
---|
| 853 | this.fileList = []; |
---|
| 854 | this._resetHTML(); |
---|
| 855 | this.set("disabled", false); |
---|
| 856 | |
---|
| 857 | |
---|
| 858 | if(this.restoreProgDisplay){ |
---|
| 859 | // using timeout so prog shows on screen for at least a short time |
---|
| 860 | setTimeout(lang.hitch(this, function(){ |
---|
| 861 | domStyle.set(manager.byId(this.progressWidgetId).domNode, |
---|
| 862 | this.restoreProgDisplay == "none" ? "display" : "visibility", |
---|
| 863 | this.restoreProgDisplay |
---|
| 864 | ); |
---|
| 865 | }), 500); |
---|
| 866 | } |
---|
| 867 | |
---|
| 868 | }, |
---|
| 869 | |
---|
| 870 | _progress: function(dataObject){ |
---|
| 871 | // summary: |
---|
| 872 | // Internal. Calculate progress |
---|
| 873 | var total = 0; |
---|
| 874 | var loaded = 0; |
---|
| 875 | for(var i = 0; i < this.fileList.length; i++){ |
---|
| 876 | var f = this.fileList[i]; |
---|
| 877 | if(f.name == dataObject.name){ |
---|
| 878 | f.bytesLoaded = dataObject.bytesLoaded; |
---|
| 879 | f.bytesTotal = dataObject.bytesTotal; |
---|
| 880 | f.percent = Math.ceil(f.bytesLoaded / f.bytesTotal * 100); |
---|
| 881 | this.log(f.name, "percent:", f.percent) |
---|
| 882 | } |
---|
| 883 | loaded += Math.ceil(.001 * f.bytesLoaded); |
---|
| 884 | total += Math.ceil(.001 * f.bytesTotal); |
---|
| 885 | } |
---|
| 886 | var percent = Math.ceil(loaded / total * 100); |
---|
| 887 | if(this.progressWidgetId){ |
---|
| 888 | manager.byId(this.progressWidgetId).update({progress:percent+"%"}); |
---|
| 889 | } |
---|
| 890 | if(this.showProgress){ |
---|
| 891 | this._displayProgress(percent * .01); |
---|
| 892 | } |
---|
| 893 | this.onProgress(this.fileList); |
---|
| 894 | |
---|
| 895 | }, |
---|
| 896 | _getDisabledAttr: function(){ |
---|
| 897 | // summary: |
---|
| 898 | // Internal. To get disabled use: widget.get("disabled"); |
---|
| 899 | return this._disabled; |
---|
| 900 | }, |
---|
| 901 | |
---|
| 902 | _setDisabledAttr: function(disabled){ |
---|
| 903 | // summary: |
---|
| 904 | // Internal. To set disabled use: widget.set("disabled", true | false); |
---|
| 905 | if(this._disabled == disabled){ return; } |
---|
| 906 | |
---|
| 907 | if(this.uploaderType == "flash"){ |
---|
| 908 | if(!this.flashReady){ |
---|
| 909 | var _fc = connect.connect(this, "onLoad", this, function(){ |
---|
| 910 | connect.disconnect(_fc); |
---|
| 911 | this._setDisabledAttr(disabled); |
---|
| 912 | }); |
---|
| 913 | return; |
---|
| 914 | } |
---|
| 915 | this._disabled = disabled; |
---|
| 916 | this.flashMovie.doDisable(disabled); |
---|
| 917 | }else{ |
---|
| 918 | this._disabled = disabled; |
---|
| 919 | domStyle.set(this._fileInput, "display", this._disabled ? "none" : ""); |
---|
| 920 | } |
---|
| 921 | domClass.toggle(this.domNode, this.disabledClass, disabled); |
---|
| 922 | }, |
---|
| 923 | |
---|
| 924 | _onFlashBlur: function(){ |
---|
| 925 | // summary: |
---|
| 926 | // Internal. Detects when Flash movies reliquishes focus. |
---|
| 927 | // We have to find all the tabIndexes in the doc and figure |
---|
| 928 | // out whom to give focus to next. |
---|
| 929 | this.flashMovie.blur(); |
---|
| 930 | if(!this.nextFocusObject && this.tabIndex){ |
---|
| 931 | var nodes = query("[tabIndex]"); |
---|
| 932 | for(var i = 0; i<nodes.length; i++){ |
---|
| 933 | if(nodes[i].tabIndex >= Number(this.tabIndex)+1){ |
---|
| 934 | this.nextFocusObject = nodes[i]; |
---|
| 935 | break; |
---|
| 936 | } |
---|
| 937 | } |
---|
| 938 | } |
---|
| 939 | this.nextFocusObject.focus(); |
---|
| 940 | }, |
---|
| 941 | _disconnect: function(){ |
---|
| 942 | // summary: |
---|
| 943 | // Internal. Disconnects fileInput in favor of new one. |
---|
| 944 | array.forEach(this._cons, connect.disconnect, dojo); |
---|
| 945 | }, |
---|
| 946 | |
---|
| 947 | /************************* |
---|
| 948 | * HTML * |
---|
| 949 | *************************/ |
---|
| 950 | uploadHTML: function(){ |
---|
| 951 | // summary: |
---|
| 952 | // Internal. You could use this, but you should use upload() or submit(); |
---|
| 953 | // which can also handle the post data. |
---|
| 954 | |
---|
| 955 | // NOTE on deferredUploading: |
---|
| 956 | // This is not enabled for HTML. Workaround would be to force |
---|
| 957 | // singleFile uploads. |
---|
| 958 | // TODO: |
---|
| 959 | // Investigate removing fileInputs and resending form |
---|
| 960 | // multiple times adding each fileInput |
---|
| 961 | // |
---|
| 962 | if(this.selectMultipleFiles){ |
---|
| 963 | domConstruct.destroy(this._fileInput); |
---|
| 964 | } |
---|
| 965 | this._setHtmlPostData(); |
---|
| 966 | if(this.showProgress){ |
---|
| 967 | this._animateProgress(); |
---|
| 968 | } |
---|
| 969 | var dfd = ioIframe.send({ |
---|
| 970 | url: this.uploadUrl.toString(), |
---|
| 971 | form: this._formNode, |
---|
| 972 | handleAs: "json", |
---|
| 973 | error: lang.hitch(this, function(err){ |
---|
| 974 | this._error("HTML Upload Error:" + err.message); |
---|
| 975 | }), |
---|
| 976 | load: lang.hitch(this, function(data, ioArgs, widgetRef){ |
---|
| 977 | this._complete(data); |
---|
| 978 | }) |
---|
| 979 | }); |
---|
| 980 | }, |
---|
| 981 | |
---|
| 982 | createHtmlUploader: function(){ |
---|
| 983 | // summary: |
---|
| 984 | // Internal. Fires of methods to build HTML Uploader. |
---|
| 985 | this._buildForm(); |
---|
| 986 | this._setFormStyle(); |
---|
| 987 | this._buildFileInput(); |
---|
| 988 | this._connectInput(); |
---|
| 989 | this._styleContent(); |
---|
| 990 | domStyle.set(this.insideNode, "visibility", "visible"); |
---|
| 991 | this.onReady(); |
---|
| 992 | }, |
---|
| 993 | |
---|
| 994 | _connectInput: function(){ |
---|
| 995 | // summary: |
---|
| 996 | // Internal. HTML Uploader connections. These get disconnected |
---|
| 997 | // after upload or if multi upload. |
---|
| 998 | this._disconnect(); |
---|
| 999 | this._cons.push(connect.connect(this._fileInput, "mouseover", this, function(evt){ |
---|
| 1000 | domClass.add(this.domNode, this.hoverClass); |
---|
| 1001 | this.onMouseOver(evt); |
---|
| 1002 | })); |
---|
| 1003 | this._cons.push(connect.connect(this._fileInput, "mouseout", this, function(evt){ |
---|
| 1004 | setTimeout(lang.hitch(this, function(){ |
---|
| 1005 | domClass.remove(this.domNode, this.activeClass); |
---|
| 1006 | domClass.remove(this.domNode, this.hoverClass); |
---|
| 1007 | this.onMouseOut(evt); |
---|
| 1008 | this._checkHtmlCancel("off"); |
---|
| 1009 | }), 0); |
---|
| 1010 | })); |
---|
| 1011 | this._cons.push(connect.connect(this._fileInput, "mousedown", this, function(evt){ |
---|
| 1012 | domClass.add(this.domNode, this.activeClass); |
---|
| 1013 | domClass.remove(this.domNode, this.hoverClass); |
---|
| 1014 | this.onMouseDown(evt); |
---|
| 1015 | })); |
---|
| 1016 | this._cons.push(connect.connect(this._fileInput, "mouseup", this, function(evt){ |
---|
| 1017 | domClass.remove(this.domNode, this.activeClass); |
---|
| 1018 | this.onMouseUp(evt); |
---|
| 1019 | this.onClick(evt); |
---|
| 1020 | this._checkHtmlCancel("up"); |
---|
| 1021 | })); |
---|
| 1022 | this._cons.push(connect.connect(this._fileInput, "change", this, function(){ |
---|
| 1023 | this._checkHtmlCancel("change"); |
---|
| 1024 | this._change([{ |
---|
| 1025 | name: this._fileInput.value, |
---|
| 1026 | type: "", |
---|
| 1027 | size: 0 |
---|
| 1028 | }]); |
---|
| 1029 | })); |
---|
| 1030 | if(this.tabIndex>=0){ |
---|
| 1031 | domAttr.set(this.domNode, "tabIndex", this.tabIndex); |
---|
| 1032 | } |
---|
| 1033 | }, |
---|
| 1034 | |
---|
| 1035 | _checkHtmlCancel: function(mouseType){ |
---|
| 1036 | // summary: |
---|
| 1037 | // Internal. Check if the dialog was opened and canceled without file selection. |
---|
| 1038 | if(mouseType == "change"){ |
---|
| 1039 | this.dialogIsOpen = false; |
---|
| 1040 | } |
---|
| 1041 | if(mouseType == "up"){ |
---|
| 1042 | this.dialogIsOpen = true; |
---|
| 1043 | } |
---|
| 1044 | if(mouseType == "off"){ |
---|
| 1045 | if(this.dialogIsOpen){ |
---|
| 1046 | this.onCancel(); |
---|
| 1047 | } |
---|
| 1048 | this.dialogIsOpen = false; |
---|
| 1049 | } |
---|
| 1050 | }, |
---|
| 1051 | |
---|
| 1052 | _styleContent: function(){ |
---|
| 1053 | // summary: |
---|
| 1054 | // Internal.Apply style to node |
---|
| 1055 | var o = this.fhtml.nr; |
---|
| 1056 | |
---|
| 1057 | domStyle.set(this.insideNode, { |
---|
| 1058 | width:o.w+"px", |
---|
| 1059 | height:o.va == "middle"?o.h+"px":"auto", |
---|
| 1060 | textAlign:o.ta, |
---|
| 1061 | paddingTop:o.p[0]+"px", |
---|
| 1062 | paddingRight:o.p[1]+"px", |
---|
| 1063 | paddingBottom:o.p[2]+"px", |
---|
| 1064 | paddingLeft:o.p[3]+"px" |
---|
| 1065 | }); |
---|
| 1066 | |
---|
| 1067 | try{ |
---|
| 1068 | domStyle.set(this.insideNode, "lineHeight", "inherit"); |
---|
| 1069 | }catch(e){ |
---|
| 1070 | // There are certain cases where IE refuses to set lineHeight. |
---|
| 1071 | // For the life of me I cannot figure out the combination of |
---|
| 1072 | // styles that IE doesn't like. Steaming... Pile... |
---|
| 1073 | } |
---|
| 1074 | |
---|
| 1075 | }, |
---|
| 1076 | _resetHTML: function(){ |
---|
| 1077 | // summary: |
---|
| 1078 | // Internal. After upload, this is called to clear the form and build a new |
---|
| 1079 | // fileInput. |
---|
| 1080 | if(this.uploaderType == "html" && this._formNode){ |
---|
| 1081 | this.fileInputs = []; |
---|
| 1082 | query("*", this._formNode).forEach(function(n){ |
---|
| 1083 | domConstruct.destroy(n); |
---|
| 1084 | }); |
---|
| 1085 | this.fileCount = 0; |
---|
| 1086 | this._buildFileInput(); |
---|
| 1087 | this._connectInput(); |
---|
| 1088 | } |
---|
| 1089 | }, |
---|
| 1090 | _buildForm: function(){ |
---|
| 1091 | // summary: |
---|
| 1092 | // Build the form that holds the fileInput |
---|
| 1093 | |
---|
| 1094 | if(this._formNode){ return; } |
---|
| 1095 | |
---|
| 1096 | if(has("ie") < 9 || (has("ie") && has("quirks"))){ |
---|
| 1097 | this._formNode = document.createElement('<form enctype="multipart/form-data" method="post">'); |
---|
| 1098 | this._formNode.encoding = "multipart/form-data"; |
---|
| 1099 | this._formNode.id = manager.getUniqueId("FileUploaderForm"); // needed for dynamic style |
---|
| 1100 | this.domNode.appendChild(this._formNode); |
---|
| 1101 | }else{ |
---|
| 1102 | this._formNode = domConstruct.create('form', { |
---|
| 1103 | enctype:"multipart/form-data", |
---|
| 1104 | method:"post", |
---|
| 1105 | id:manager.getUniqueId("FileUploaderForm") |
---|
| 1106 | }, this.domNode); |
---|
| 1107 | } |
---|
| 1108 | }, |
---|
| 1109 | |
---|
| 1110 | _buildFileInput: function(){ |
---|
| 1111 | // summary: |
---|
| 1112 | // Build the fileInput field |
---|
| 1113 | |
---|
| 1114 | if(this._fileInput){ |
---|
| 1115 | this._disconnect(); |
---|
| 1116 | // FIXME: |
---|
| 1117 | // Just hiding it which works, but we lose |
---|
| 1118 | // reference to it and can't remove it from |
---|
| 1119 | // the upload list. |
---|
| 1120 | this._fileInput.id = this._fileInput.id + this.fileCount; |
---|
| 1121 | domStyle.set(this._fileInput, "display", "none"); |
---|
| 1122 | } |
---|
| 1123 | this._fileInput = document.createElement('input'); |
---|
| 1124 | this.fileInputs.push(this._fileInput); |
---|
| 1125 | // server will need to know this variable: |
---|
| 1126 | var nm = this.htmlFieldName; |
---|
| 1127 | var _id = this.id; |
---|
| 1128 | if(this.selectMultipleFiles){ |
---|
| 1129 | nm += this.fileCount; |
---|
| 1130 | _id += this.fileCount; |
---|
| 1131 | this.fileCount++; |
---|
| 1132 | } |
---|
| 1133 | |
---|
| 1134 | domAttr.set(this._fileInput, { |
---|
| 1135 | id:this.id, |
---|
| 1136 | name:nm, |
---|
| 1137 | type:"file" |
---|
| 1138 | }); |
---|
| 1139 | |
---|
| 1140 | domClass.add(this._fileInput, "dijitFileInputReal"); |
---|
| 1141 | this._formNode.appendChild(this._fileInput); |
---|
| 1142 | var real = domGeometry.getMarginBox(this._fileInput); |
---|
| 1143 | domStyle.set(this._fileInput, { |
---|
| 1144 | position:"relative", |
---|
| 1145 | left:(this.fhtml.nr.w - real.w) + "px", |
---|
| 1146 | opacity:0 |
---|
| 1147 | }); |
---|
| 1148 | }, |
---|
| 1149 | |
---|
| 1150 | _renumberInputs: function(){ |
---|
| 1151 | if(!this.selectMultipleFiles){ return; } |
---|
| 1152 | var nm; |
---|
| 1153 | this.fileCount = 0; |
---|
| 1154 | array.forEach(this.fileInputs, function(inp){ |
---|
| 1155 | nm = this.htmlFieldName + this.fileCount; |
---|
| 1156 | this.fileCount++; |
---|
| 1157 | domAttr.set(inp, "name", nm); |
---|
| 1158 | }, this); |
---|
| 1159 | }, |
---|
| 1160 | |
---|
| 1161 | _setFormStyle: function(){ |
---|
| 1162 | // summary: |
---|
| 1163 | // Apply a dynamic style to the form and input |
---|
| 1164 | var size = Math.max(2, Math.max(Math.ceil(this.fhtml.nr.w / 60), Math.ceil(this.fhtml.nr.h / 15))); |
---|
| 1165 | // Now create a style associated with the form ID |
---|
| 1166 | htmlStyles.insertCssRule("#" + this._formNode.id + " input", "font-size:" + size + "em"); |
---|
| 1167 | domStyle.set(this.domNode, { |
---|
| 1168 | overflow:"hidden", |
---|
| 1169 | position:"relative" |
---|
| 1170 | }); |
---|
| 1171 | domStyle.set(this.insideNode, "position", "absolute"); |
---|
| 1172 | }, |
---|
| 1173 | |
---|
| 1174 | _setHtmlPostData: function(){ |
---|
| 1175 | // summary: |
---|
| 1176 | // Internal.Apply postData to hidden fields in form |
---|
| 1177 | if(this.postData){ |
---|
| 1178 | for(var nm in this.postData){ |
---|
| 1179 | domConstruct.create("input", { |
---|
| 1180 | type: "hidden", |
---|
| 1181 | name: nm, |
---|
| 1182 | value: this.postData[nm] |
---|
| 1183 | }, this._formNode); |
---|
| 1184 | } |
---|
| 1185 | } |
---|
| 1186 | }, |
---|
| 1187 | |
---|
| 1188 | /************************* |
---|
| 1189 | * FLASH * |
---|
| 1190 | *************************/ |
---|
| 1191 | uploadFlash: function(){ |
---|
| 1192 | // summary: |
---|
| 1193 | // Internal. You should use upload() or submit(); |
---|
| 1194 | try{ |
---|
| 1195 | if(this.showProgress){ |
---|
| 1196 | this._displayProgress(true); |
---|
| 1197 | var c = connect.connect(this, "_complete", this, function(){ |
---|
| 1198 | connect.disconnect(c); |
---|
| 1199 | this._displayProgress(false); |
---|
| 1200 | }); |
---|
| 1201 | } |
---|
| 1202 | |
---|
| 1203 | var o = {}; |
---|
| 1204 | for(var nm in this.postData){ |
---|
| 1205 | o[nm] = this.postData[nm]; |
---|
| 1206 | } |
---|
| 1207 | this.flashMovie.doUpload(o); |
---|
| 1208 | |
---|
| 1209 | }catch(err){ |
---|
| 1210 | this._error("FileUploader - Sorry, the SWF failed to initialize." + err); |
---|
| 1211 | } |
---|
| 1212 | }, |
---|
| 1213 | |
---|
| 1214 | createFlashUploader: function(){ |
---|
| 1215 | // summary: |
---|
| 1216 | // Internal. Creates Flash Uploader |
---|
| 1217 | this.uploadUrl = this.uploadUrl.toString(); |
---|
| 1218 | if(this.uploadUrl){ |
---|
| 1219 | if(this.uploadUrl.toLowerCase().indexOf("http")<0 && this.uploadUrl.indexOf("/")!=0){ |
---|
| 1220 | // Appears to be a relative path. Attempt to |
---|
| 1221 | // convert it to absolute, so it will better |
---|
| 1222 | // target the SWF. |
---|
| 1223 | var loc = window.location.href.split("/"); |
---|
| 1224 | loc.pop(); |
---|
| 1225 | loc = loc.join("/")+"/"; |
---|
| 1226 | this.uploadUrl = loc+this.uploadUrl; |
---|
| 1227 | this.log("SWF Fixed - Relative loc:", loc, " abs loc:", this.uploadUrl); |
---|
| 1228 | }else{ |
---|
| 1229 | this.log("SWF URL unmodified:", this.uploadUrl) |
---|
| 1230 | } |
---|
| 1231 | }else{ |
---|
| 1232 | console.warn("Warning: no uploadUrl provided."); |
---|
| 1233 | } |
---|
| 1234 | |
---|
| 1235 | var w = this.fhtml.nr.w; |
---|
| 1236 | var h = this.fhtml.nr.h; |
---|
| 1237 | |
---|
| 1238 | var args = { |
---|
| 1239 | expressInstall:true, |
---|
| 1240 | path: this.swfPath.uri || this.swfPath, |
---|
| 1241 | width: w, |
---|
| 1242 | height: h, |
---|
| 1243 | allowScriptAccess:"always", |
---|
| 1244 | allowNetworking:"all", |
---|
| 1245 | vars: { |
---|
| 1246 | uploadDataFieldName: this.flashFieldName, |
---|
| 1247 | uploadUrl: this.uploadUrl, |
---|
| 1248 | uploadOnSelect: this.uploadOnChange, |
---|
| 1249 | deferredUploading:this.deferredUploading || 0, |
---|
| 1250 | selectMultipleFiles: this.selectMultipleFiles, |
---|
| 1251 | id: this.id, |
---|
| 1252 | isDebug: this.isDebug, |
---|
| 1253 | devMode:this.devMode, |
---|
| 1254 | flashButton:embedFlashVars.serialize("fh", this.fhtml), |
---|
| 1255 | fileMask:embedFlashVars.serialize("fm", this.fileMask), |
---|
| 1256 | noReturnCheck: this.skipServerCheck, |
---|
| 1257 | serverTimeout:this.serverTimeout |
---|
| 1258 | }, |
---|
| 1259 | params: { |
---|
| 1260 | scale:"noscale", |
---|
| 1261 | wmode:"opaque", |
---|
| 1262 | allowScriptAccess:"always", |
---|
| 1263 | allowNetworking:"all" |
---|
| 1264 | } |
---|
| 1265 | |
---|
| 1266 | }; |
---|
| 1267 | |
---|
| 1268 | this.flashObject = new embedFlash(args, this.insideNode); |
---|
| 1269 | this.flashObject.onError = lang.hitch(function(msg){ |
---|
| 1270 | this._error("Flash Error: " + msg); |
---|
| 1271 | }); |
---|
| 1272 | this.flashObject.onReady = lang.hitch(this, function(){ |
---|
| 1273 | domStyle.set(this.insideNode, "visibility", "visible"); |
---|
| 1274 | this.log("FileUploader flash object ready"); |
---|
| 1275 | this.onReady(this); |
---|
| 1276 | }); |
---|
| 1277 | this.flashObject.onLoad = lang.hitch(this, function(mov){ |
---|
| 1278 | this.flashMovie = mov; |
---|
| 1279 | this.flashReady = true; |
---|
| 1280 | |
---|
| 1281 | this.onLoad(this); |
---|
| 1282 | }); |
---|
| 1283 | this._connectFlash(); |
---|
| 1284 | |
---|
| 1285 | }, |
---|
| 1286 | |
---|
| 1287 | _connectFlash: function(){ |
---|
| 1288 | // summary: |
---|
| 1289 | // Subscribing to published topics coming from the |
---|
| 1290 | // Flash uploader. |
---|
| 1291 | // |
---|
| 1292 | // Sacrificing some readability for compactness. this.id |
---|
| 1293 | // will be on the beginning of the topic, so more than |
---|
| 1294 | // one uploader can be on a page and can have unique calls. |
---|
| 1295 | |
---|
| 1296 | this._doSub("/filesSelected", "_change"); |
---|
| 1297 | this._doSub("/filesUploaded", "_complete"); |
---|
| 1298 | this._doSub("/filesProgress", "_progress"); |
---|
| 1299 | this._doSub("/filesError", "_error"); |
---|
| 1300 | this._doSub("/filesCanceled", "onCancel"); |
---|
| 1301 | this._doSub("/stageBlur", "_onFlashBlur"); |
---|
| 1302 | this._doSub("/up", "onMouseUp"); |
---|
| 1303 | this._doSub("/down", "onMouseDown"); |
---|
| 1304 | this._doSub("/over", "onMouseOver"); |
---|
| 1305 | this._doSub("/out", "onMouseOut"); |
---|
| 1306 | |
---|
| 1307 | this.connect(this.domNode, "focus", function(){ |
---|
| 1308 | // TODO: some kind of indicator that the Flash button is in focus |
---|
| 1309 | this.flashMovie.focus(); |
---|
| 1310 | this.flashMovie.doFocus(); |
---|
| 1311 | }); |
---|
| 1312 | if(this.tabIndex>=0){ |
---|
| 1313 | domAttr.set(this.domNode, "tabIndex", this.tabIndex); |
---|
| 1314 | } |
---|
| 1315 | }, |
---|
| 1316 | |
---|
| 1317 | _doSub: function(subStr, funcStr){ |
---|
| 1318 | // summary: |
---|
| 1319 | // Internal. Shortcut for subscribes to Flash movie |
---|
| 1320 | this._subs.push(connect.subscribe(this.id + subStr, this, funcStr)); |
---|
| 1321 | }, |
---|
| 1322 | |
---|
| 1323 | /************************************* |
---|
| 1324 | * DOM INSPECTION METHODS * |
---|
| 1325 | *************************************/ |
---|
| 1326 | |
---|
| 1327 | urlencode: function(url){ |
---|
| 1328 | // Using symbols in place of URL chars that will break in Flash serialization. |
---|
| 1329 | if(!url || url == "none"){ |
---|
| 1330 | return false; |
---|
| 1331 | } |
---|
| 1332 | return url.replace(/:/g,"||").replace(/\./g,"^^").replace("url(", "").replace(")","").replace(/'/g,"").replace(/"/g,""); |
---|
| 1333 | }, |
---|
| 1334 | |
---|
| 1335 | isButton: function(node){ |
---|
| 1336 | // testing if button for styling purposes |
---|
| 1337 | var tn = node.tagName.toLowerCase(); |
---|
| 1338 | return tn == "button" || tn == "input"; |
---|
| 1339 | }, |
---|
| 1340 | |
---|
| 1341 | getTextStyle: function(node){ |
---|
| 1342 | // getting font info |
---|
| 1343 | var o = {}; |
---|
| 1344 | o.ff = domStyle.get(node, "fontFamily"); |
---|
| 1345 | if(o.ff){ |
---|
| 1346 | o.ff = o.ff.replace(", ", ","); // remove spaces. IE in Flash no likee |
---|
| 1347 | o.ff = o.ff.replace(/\"|\'/g, ""); |
---|
| 1348 | o.ff = o.ff == "sans-serif" ? "Arial" : o.ff; // Flash doesn't know what sans-serif is |
---|
| 1349 | o.fw = domStyle.get(node, "fontWeight"); |
---|
| 1350 | o.fi = domStyle.get(node, "fontStyle"); |
---|
| 1351 | o.fs = parseInt(domStyle.get(node, "fontSize"), 10); |
---|
| 1352 | if(domStyle.get(node, "fontSize").indexOf("%") > -1){ |
---|
| 1353 | // IE doesn't convert % to px. For god sakes. |
---|
| 1354 | var n = node; |
---|
| 1355 | while(n.tagName){ |
---|
| 1356 | if(domStyle.get(n, "fontSize").indexOf("%") == -1){ |
---|
| 1357 | o.fs = parseInt(domStyle.get(n, "fontSize"), 10); |
---|
| 1358 | break; |
---|
| 1359 | } |
---|
| 1360 | if(n.tagName.toLowerCase()=="body"){ |
---|
| 1361 | // if everyting is %, the the font size is 16px * the % |
---|
| 1362 | o.fs = 16 * .01 * parseInt(domStyle.get(n, "fontSize"), 10); |
---|
| 1363 | } |
---|
| 1364 | n = n.parentNode; |
---|
| 1365 | } |
---|
| 1366 | } |
---|
| 1367 | o.fc = new Color(domStyle.get(node, "color")).toHex(); |
---|
| 1368 | o.fc = parseInt(o.fc.substring(1,Infinity),16); |
---|
| 1369 | } |
---|
| 1370 | o.lh = domStyle.get(node, "lineHeight"); |
---|
| 1371 | o.ta = domStyle.get(node, "textAlign"); |
---|
| 1372 | o.ta = o.ta == "start" || !o.ta ? "left" : o.ta; |
---|
| 1373 | o.va = this.isButton(node) ? "middle" : o.lh == o.h ? "middle" : domStyle.get(node, "verticalAlign"); |
---|
| 1374 | return o; |
---|
| 1375 | }, |
---|
| 1376 | |
---|
| 1377 | getText: function(node){ |
---|
| 1378 | // Get the text of the button. It's possible to use HTML in the Flash Button, |
---|
| 1379 | // but the results are not spectacular. |
---|
| 1380 | var cn = lang.trim(node.innerHTML); |
---|
| 1381 | if(cn.indexOf("<") >- 1){ |
---|
| 1382 | cn = escape(cn); |
---|
| 1383 | } |
---|
| 1384 | return cn; |
---|
| 1385 | }, |
---|
| 1386 | |
---|
| 1387 | getStyle: function(node){ |
---|
| 1388 | // getting the style of a node. Using very abbreviated characters which the |
---|
| 1389 | // Flash movie understands. |
---|
| 1390 | var o = {}; |
---|
| 1391 | var dim = domGeometry.getContentBox(node); |
---|
| 1392 | var pad = domGeometry.getPadExtents(node); |
---|
| 1393 | o.p = [pad.t, pad.w-pad.l, pad.h-pad.t, pad.l]; |
---|
| 1394 | o.w = dim.w + pad.w; |
---|
| 1395 | o.h = dim.h + pad.h; |
---|
| 1396 | o.d = domStyle.get(node, "display"); |
---|
| 1397 | var clr = new Color(domStyle.get(node, "backgroundColor")); |
---|
| 1398 | // if no color, Safari sets #000000 and alpha=0 since we don't support alpha, |
---|
| 1399 | // it makes black - make it white |
---|
| 1400 | o.bc = clr.a == 0 ? "#ffffff" : clr.toHex(); |
---|
| 1401 | o.bc = parseInt(o.bc.substring(1,Infinity),16); |
---|
| 1402 | var url = this.urlencode(domStyle.get(node, "backgroundImage")); |
---|
| 1403 | if(url){ |
---|
| 1404 | o.bi = { |
---|
| 1405 | url:url, |
---|
| 1406 | rp:domStyle.get(node, "backgroundRepeat"), |
---|
| 1407 | pos: escape(domStyle.get(node, "backgroundPosition")) |
---|
| 1408 | }; |
---|
| 1409 | if(!o.bi.pos){ |
---|
| 1410 | // IE does Xpx and Ypx, not "X% Y%" |
---|
| 1411 | var rx = domStyle.get(node, "backgroundPositionX"); |
---|
| 1412 | var ry = domStyle.get(node, "backgroundPositionY"); |
---|
| 1413 | rx = (rx == "left") ? "0%" : (rx == "right") ? "100%" : rx; |
---|
| 1414 | ry = (ry == "top") ? "0%" : (ry == "bottom") ? "100%" : ry; |
---|
| 1415 | o.bi.pos = escape(rx+" "+ry); |
---|
| 1416 | } |
---|
| 1417 | } |
---|
| 1418 | return lang.mixin(o, this.getTextStyle(node)); |
---|
| 1419 | }, |
---|
| 1420 | |
---|
| 1421 | getTempNodeStyle: function(node, _class, isDijitButton){ |
---|
| 1422 | // This sets up a temp node to get the style of the hover, active, and disabled states |
---|
| 1423 | var temp, style; |
---|
| 1424 | if(isDijitButton){ |
---|
| 1425 | // backwards compat until dojo 1.5 |
---|
| 1426 | temp = domConstruct.place("<"+node.tagName+"><span>"+node.innerHTML+"</span></"+node.tagName+">", node.parentNode); //+" "+_class+" |
---|
| 1427 | var first = temp.firstChild; |
---|
| 1428 | domClass.add(first, node.className); |
---|
| 1429 | domClass.add(temp, _class); |
---|
| 1430 | style = this.getStyle(first); |
---|
| 1431 | }else{ |
---|
| 1432 | temp = domConstruct.place("<"+node.tagName+">"+node.innerHTML+"</"+node.tagName+">", node.parentNode); |
---|
| 1433 | domClass.add(temp, node.className); |
---|
| 1434 | domClass.add(temp, _class); |
---|
| 1435 | temp.id = node.id; |
---|
| 1436 | style = this.getStyle(temp); |
---|
| 1437 | } |
---|
| 1438 | // dev note: comment out this line to see what the |
---|
| 1439 | // button states look like to the FileUploader |
---|
| 1440 | domConstruct.destroy(temp); |
---|
| 1441 | return style; |
---|
| 1442 | } |
---|
| 1443 | }); |
---|
| 1444 | |
---|
| 1445 | }); |
---|