docs: function(data, fm) { 
  			var self   = fm ? fm : this,
  				input  = data.input? data.input : false,
  				files  = !input ? self.uploads.checkFile(data, self) : false,
  				dfrd   = $.Deferred()
  					.fail(function(error) {
  						error && self.error(error);
  					}),
  				name = 'iframe-'+fm.namespace+(++self.iframeCnt),
  				form = $('<form action="'+self.uploadURL+'" method="post" enctype="multipart/form-data" encoding="multipart/form-data" target="'+name+'" style="display:none"><input type="hidden" name="cmd" value="upload" /></form>'),
  				msie = this.UA.IE,
  				// clear timeouts, close notification dialog, remove form/iframe
  				onload = function() {
  					abortto  && clearTimeout(abortto);
  					notifyto && clearTimeout(notifyto);
  					notify   && self.notify({type : 'upload', cnt : -cnt});
  					
  					setTimeout(function() {
  						msie && $('<iframe src="javascript:false;"/>').appendTo(form);
  						form.remove();
  						iframe.remove();
  					}, 100);
  				},
  				iframe = $('<iframe src="'+(msie ? 'javascript:false;' : 'about:blank')+'" name="'+name+'" style="position:absolute;left:-1000px;top:-1000px" />')
  					.on('load', function() {
  						iframe.off('load')
  							.on('load', function() {
  								onload();
  								// data will be processed in callback response or window onmessage
  								dfrd.resolve();
  							});
  							
  							// notify dialog
  							notifyto = setTimeout(function() {
  								notify = true;
  								self.notify({type : 'upload', cnt : cnt});
  							}, self.options.notifyDelay);
  							
  							// emulate abort on timeout
  							if (self.options.iframeTimeout > 0) {
  								abortto = setTimeout(function() {
  									onload();
  									dfrd.reject([errors.connect, errors.timeout]);
  								}, self.options.iframeTimeout);
  							}
  							
  							form.submit();
  					}),
  				target  = (data.target || self.cwd().hash),
  				names   = [],
  				dfds    = [],
  				renames = [],
  				hashes  = {},
  				cnt, notify, notifyto, abortto;
  
  			if (files && files.length) {
  				$.each(files, function(i, val) {
  					form.append('<input type="hidden" name="upload[]" value="'+val+'"/>');
  				});
  				cnt = 1;
  			} else if (input && $(input).is(':file') && $(input).val()) {
  				if (fm.options.overwriteUploadConfirm && fm.option('uploadOverwrite', target)) {
  					names = input.files? input.files : [{ name: $(input).val().replace(/^(?:.+[\\\/])?([^\\\/]+)$/, '$1') }];
  					//names = $.map(names, function(file){return file.name? { name: file.name } : null ;});
  					dfds.push(self.uploads.checkExists(names, target, self).done(
  						function(res, res2){
  							hashes = res2;
  							if (res === null) {
  								data.overwrite = 0;
  							} else{
  								renames = res;
  								cnt = $.grep(names, function(file){return !file._remove? true : false ;}).length;
  								if (cnt != names.length) {
  									cnt = 0;
  								}
  							}
  						}
  					));
  				}
  				cnt = input.files ? input.files.length : 1;
  				form.append(input);
  			} else {
  				return dfrd.reject();
  			}
  			
  			$.when.apply($, dfds).done(function() {
  				if (cnt < 1) {
  					return dfrd.reject();
  				}
  				form.append('<input type="hidden" name="'+(self.newAPI ? 'target' : 'current')+'" value="'+target+'"/>')
  					.append('<input type="hidden" name="html" value="1"/>')
  					.append('<input type="hidden" name="node" value="'+self.id+'"/>')
  					.append($(input).attr('name', 'upload[]'));
  				
  				if (renames.length > 0) {
  					$.each(renames, function(i, rename) {
  						form.append('<input type="hidden" name="renames[]" value="'+self.escape(rename)+'"/>');
  					});
  					form.append('<input type="hidden" name="suffix" value="'+fm.options.backupSuffix+'"/>');
  				}
  				if (hashes) {
  					$.each(renames, function(i, v) {
  						form.append('<input type="hidden" name="['+i+']" value="'+self.escape(v)+'"/>');
  					});
  				}
  				
  				if (data.overwrite === 0) {
  					form.append('<input type="hidden" name="overwrite" value="0"/>');
  				}
  				
  				$.each(self.options.onlyMimes||[], function(i, mime) {
  					form.append('<input type="hidden" name="mimes[]" value="'+self.escape(mime)+'"/>');
  				});
  				
  				$.each(self.customData, function(key, val) {
  					form.append('<input type="hidden" name="'+key+'" value="'+self.escape(val)+'"/>');
  				});
  				
  				form.appendTo('body');
  				iframe.appendTo('body');
  			});
  			
  			return dfrd;
  		}