KajaSheen
12 Feb 2008, 1:48 PM
For all the folks who don't want to or can't use AJAX file upload in their application finally there is a replacement for TextField type: 'file'. I use regular form submit, there is no handling for any other type yet.
I used a TwinTriggerField and used the technique from http://www.shauninman.com/ (http://www.shauninman.com/archive/2007/09/10/styling_file_inputs_with_css_and_the_dom) with a little twist. The input will be made opaque and hovered over the triggerfield.
The inputs are configured with the {name} option.
The following vars are submitted with the form:
{name}: the file name, stripped from path info
{name}FILE: the uploaded file
{name}Keep: when the field is initialized with a value it thinks that one is trying to update a file. When just other properties as the name are changed my backend must know that there is no upload, that is when {name}Keep equals 1.
Also when initialized with a value the trigger to reset will go back to the initial value instead of empty field.
When canceling the file a new hidden input for the file will be created, which is the only way to reset the field, because JS doesn't allow to change the value of input[type:file].
Tested on Win FF, IE 7 and IE 6... Will check Mac sometimes this week,
[EDIT] Added the .zip with my example code. Unpack in your "ext/examples/form" folder so the images and stuff are found...
JS Code
/*
* Ext JS Library 2.0
* Copyright(c) 2006-2007, Ext JS, LLC.
* [email protected]
*
* http://extjs.com/license
*/
Ext.ux.FileSelector = Ext.extend(Ext.form.TwinTriggerField, {
initComponent : function(){
Ext.ux.FileSelector.superclass.initComponent.call(this);
this.triggerConfig = {
tag:'span', cls:'x-form-twin-triggers', cn:[
{tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
{tag:'span', cls:'ux-cabinet', cn:[
{tag: "img", id: this.id + "Selector", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class},
{tag: "div", id: this.id + "Wrapper", cls: "ux-input-file-wrapper", cn: [
{tag: "input", name: this.name + "FILE", type: "file", cls: "ux-file", id: this.id + "File"}
]}
]},
{tag: "input", name: this.name + "Keep", type: "checkbox", cls:"x-hidden", id: this.id + "Keep", value: 1}
]};
var v = this.getRawValue();
if(v.length > 0){
this.hasValue = true;
this.uxInitialValue = v;
}
this.on("render", this.uxStylizeTrigger, this);
},
uxInitialValue: false,
name: 'file',
readOnly: true,
validationEvent:false,
validateOnBlur:false,
trigger1Class:'x-form-clear-trigger',
trigger2Class:'x-form-search-trigger',
hideTrigger1:true,
width:250,
hasValue : false,
paramName : false,
onTrigger1Click : function(){
if(this.hasValue){
this.triggers[0].hide();
this.hasValue = false;
if(this.uxInitialValue) {
var keep = Ext.get(this.id + "Keep");
keep.dom.checked = true;
this.setValue(this.uxInitialValue);
} else {
this.setValue('');
}
var input = Ext.get(this.id + "File");
input.remove();
var wrapper = Ext.get(this.id + "Wrapper");
Ext.DomHelper.append(wrapper, {tag: "input", name: this.name + "FILE", type: "file", cls: "ux-file", id: this.id + "File"});
var input_new = Ext.get(this.id + "File");
input_new.on("change", this.uxHandleFile, this);
}
},
onTrigger2Click : function(){
this.hasValue = true;
this.triggers[0].show();
var keep = Ext.get(this.id + "Keep");
keep.dom.checked = false;
},
uxHandleFile : function() {
var input = Ext.get(this.id + "File");
//if this is unix style structure replace / with \
var filePath = input.dom.value.replace(/\//g, '\\');
//extract the filename from the value
var indexPos = filePath.lastIndexOf('\\');
var fileName = filePath.substring(indexPos + 1);
this.setValue(fileName);
search = /(zip|tar|gz)$/i;
if(search.test(fileName)) {
//alert('archive');
//createArchiveCheck(input);
}
this.onTrigger2Click();
},
uxStylizeTrigger : function(){
if(this.hasValue) {
var keep = Ext.get(this.id + "Keep");
keep.dom.checked = true;
}
var trigger = Ext.get(this.id + "Selector");
var wrapper = Ext.get(this.id + "Wrapper");
var input = Ext.get(this.id + "File");
input.on("change", this.uxHandleFile, this);
trigger.file = wrapper;
trigger.on("mousemove", function(e) {
var pageX = e.xy[0];
var pageY = e.xy[1];
ox = this.getX();
oy = this.getY();
var x = pageX - ox;
var y = pageY - oy;
var w = this.file.getWidth();
var h = this.file.getHeight();
this.file.setTop(y - (h / 2) - 5 + 'px');
this.file.setLeft(x - (w - 15) + 'px');
});
}
});
I used a TwinTriggerField and used the technique from http://www.shauninman.com/ (http://www.shauninman.com/archive/2007/09/10/styling_file_inputs_with_css_and_the_dom) with a little twist. The input will be made opaque and hovered over the triggerfield.
The inputs are configured with the {name} option.
The following vars are submitted with the form:
{name}: the file name, stripped from path info
{name}FILE: the uploaded file
{name}Keep: when the field is initialized with a value it thinks that one is trying to update a file. When just other properties as the name are changed my backend must know that there is no upload, that is when {name}Keep equals 1.
Also when initialized with a value the trigger to reset will go back to the initial value instead of empty field.
When canceling the file a new hidden input for the file will be created, which is the only way to reset the field, because JS doesn't allow to change the value of input[type:file].
Tested on Win FF, IE 7 and IE 6... Will check Mac sometimes this week,
[EDIT] Added the .zip with my example code. Unpack in your "ext/examples/form" folder so the images and stuff are found...
JS Code
/*
* Ext JS Library 2.0
* Copyright(c) 2006-2007, Ext JS, LLC.
* [email protected]
*
* http://extjs.com/license
*/
Ext.ux.FileSelector = Ext.extend(Ext.form.TwinTriggerField, {
initComponent : function(){
Ext.ux.FileSelector.superclass.initComponent.call(this);
this.triggerConfig = {
tag:'span', cls:'x-form-twin-triggers', cn:[
{tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
{tag:'span', cls:'ux-cabinet', cn:[
{tag: "img", id: this.id + "Selector", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class},
{tag: "div", id: this.id + "Wrapper", cls: "ux-input-file-wrapper", cn: [
{tag: "input", name: this.name + "FILE", type: "file", cls: "ux-file", id: this.id + "File"}
]}
]},
{tag: "input", name: this.name + "Keep", type: "checkbox", cls:"x-hidden", id: this.id + "Keep", value: 1}
]};
var v = this.getRawValue();
if(v.length > 0){
this.hasValue = true;
this.uxInitialValue = v;
}
this.on("render", this.uxStylizeTrigger, this);
},
uxInitialValue: false,
name: 'file',
readOnly: true,
validationEvent:false,
validateOnBlur:false,
trigger1Class:'x-form-clear-trigger',
trigger2Class:'x-form-search-trigger',
hideTrigger1:true,
width:250,
hasValue : false,
paramName : false,
onTrigger1Click : function(){
if(this.hasValue){
this.triggers[0].hide();
this.hasValue = false;
if(this.uxInitialValue) {
var keep = Ext.get(this.id + "Keep");
keep.dom.checked = true;
this.setValue(this.uxInitialValue);
} else {
this.setValue('');
}
var input = Ext.get(this.id + "File");
input.remove();
var wrapper = Ext.get(this.id + "Wrapper");
Ext.DomHelper.append(wrapper, {tag: "input", name: this.name + "FILE", type: "file", cls: "ux-file", id: this.id + "File"});
var input_new = Ext.get(this.id + "File");
input_new.on("change", this.uxHandleFile, this);
}
},
onTrigger2Click : function(){
this.hasValue = true;
this.triggers[0].show();
var keep = Ext.get(this.id + "Keep");
keep.dom.checked = false;
},
uxHandleFile : function() {
var input = Ext.get(this.id + "File");
//if this is unix style structure replace / with \
var filePath = input.dom.value.replace(/\//g, '\\');
//extract the filename from the value
var indexPos = filePath.lastIndexOf('\\');
var fileName = filePath.substring(indexPos + 1);
this.setValue(fileName);
search = /(zip|tar|gz)$/i;
if(search.test(fileName)) {
//alert('archive');
//createArchiveCheck(input);
}
this.onTrigger2Click();
},
uxStylizeTrigger : function(){
if(this.hasValue) {
var keep = Ext.get(this.id + "Keep");
keep.dom.checked = true;
}
var trigger = Ext.get(this.id + "Selector");
var wrapper = Ext.get(this.id + "Wrapper");
var input = Ext.get(this.id + "File");
input.on("change", this.uxHandleFile, this);
trigger.file = wrapper;
trigger.on("mousemove", function(e) {
var pageX = e.xy[0];
var pageY = e.xy[1];
ox = this.getX();
oy = this.getY();
var x = pageX - ox;
var y = pageY - oy;
var w = this.file.getWidth();
var h = this.file.getHeight();
this.file.setTop(y - (h / 2) - 5 + 'px');
this.file.setLeft(x - (w - 15) + 'px');
});
}
});