最近在研究上傳的問題,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>
這樣工作完全正常,也沒有影響以前的布局。