最近在研究上传的问题,html5支持ajax上传文件,不支持html5的可以用iframe替换(flash这个cpu/mem老虎请靠边站),但如果真的要在项目中应用,绝对不可以直接用 <input type="file" name="upload" />就完事了,必须要美化,美化的作用,1,使得所有浏览器下,看起来一样,2,提供一个一致的入口,方便操作。
看看原生态的input=file在各个浏览器下的造型:
上图为我的debian系统下,Firefox, Opera, Chrome浏览下的file样式,最后一个IE是虚拟机里的表现。
丑陋不堪,而且严重的不统一。除IE浏览器外,其他浏览器下,单击按钮任何一个地方都可以弹出选择文件对话框,
而IE必须要单击到“浏览”按钮才可以触发。
美化的原理:将input到一个div框里,div设置position为relative,input设置position为absolute,opacity设置为0,这样input表现为全透明,不可见,但覆盖在文字之上,div里的其他文字可以显示出来,而单击div,依然会触发上传事件。
html代码:
<divclass="u-file-c u-file-btn"> <inputtype="file"name="attach"/>请选择上传文件 </div>
CSS代码:
.u-file-btn { position: relative; direction:ltr; height:18px; line-height:18px; margin-right:10px; padding:3px0; text-align: center; width:105px; background:#880000; color:#FFF;}
.u-file-btn input{ cursor: pointer; text-align: right; z-index:10; position: absolute; top:0px; right:0px; opacity:0.5; filter:Alpha(opacity:50);}
为了调试得到最佳效果,暂时先设置透明度为 50%,以方便调试。
看看各个浏览器的截图:
Firefox和Opera比较相似,而Chrome后面跟了一堆文字,但是文件也可以单击,最糟糕的是IE,IE虽然看上去像Firefox,但IE下的文本框部分不可以单击,只有按钮才可以单击触发上传事件,如果按钮的大小刚刚好和 “浏览” 两个字所在的按钮一样,则没有问题,但有时候往往需要写多一点的文字,这时候,只有单击按钮最右部分才可以起作用,下面看看怎么解决这个问题。
IE下使用 size/ width 都不可以使 “浏览” 按钮变大 ,只有一种办法可以,就是font-size,而根据一个现有的ajaxupload控件,font-size并不是可以随便设置一个很大的值,最后确定的font-size为118px工作的很好。
设置下input的字体大小:
.u-file-btn input{ cursor: pointer; text-align: right; z-index:10; font-size:118px;/* font-size: 118px 工作正常 */ position: absolute; top:0px; right:0px; opacity:0.5; filter:Alpha(opacity:50);}
这时候,Chrome下已经看不到input框了,因为chrome的最右边是文字部分,而且有很多空白,所以放大文字后,基本看不到input了,Firefox、Oprea、IE都可以看到。
好现在只需要把外层div的overflow的部分hide掉,还有opacity调整为0,最终的CSS代码为:
.u-file-btn { position: relative; direction:ltr; height:18px; overflow:hidden; line-height:18px; margin-right:10px; padding:3px0; text-align: center; width:105px; background:#880000; color:#FFF;}
.u-file-btn input{ cursor: pointer; text-align: right; z-index:10; font-size:118px;/* font-size: 118px 工作正常 */ position: absolute; top:0px; right:0px; opacity:0; filter:Alpha(opacity:0);}
到这里基本就算完成了,但是实际上,为了兼容不同的情况,input外层div的class: u-file-btn不是在页面加载的时候就写上去的,而是用js动态赋予的,这个时候,firefox/chrome下没有问题,而Opera和IE出现了异常:
页面html的代码:( 需要jquery )
<body> <divclass="u-file-c"> <inputtype="file"name="attach"/>选择上传文件 </div> <scripttype="text/javascript"> $(document).ready(function(){ $('.u-file-c').addClass('u-file-btn'); }); </script> </body>
这样一来,font-size就完全失去了作用了。经过大量测试发现,document.ready事件之后,也就是页面渲染完毕后,再赋值font-size并不能实际改变input的大小,就算改变,也会变得很怪异,而如果是采用js动态生成的input按钮,这样插入页面后,显示正常。
比如采用 document.appendChild('input')这样的方法。
修改成动态添加input元素:
<body> <divclass="u-file-c"> </div> <scripttype="text/javascript"> $(document).ready(function(){ $('.u-file-c').addClass('u-file-btn').html('<input type="file" name="attach" />选择上传文件'); }); </script> </body>
上面的代码采用动态添加input方法,IE和Opera恢复正常,
但通常我不会把这个东西完整的抽象成插件,我的习惯在现有的和html代码上用js添加内容,这样做的好处是,没js代码依然可以正常运行,而且html代码可以实现比较复杂的页面布局,如果完全采用js来生成表单很多地方不方便,
最后的代码可以是这样:
<body> <divclass="u-file-c"> <inputtype="file"name="attach"/>选择上传文件 </div> <scripttype="text/javascript"> $(document).ready(function(){ $('.u-file-c').addClass('u-file-btn'); $('.u-file-c').each(function(i, el){ $(this).html($(this).html()); }) }); </script></body>
这样工作完全正常,也没有影响以前的布局。