JavaScript CSS修改學(xué)習(xí)第五章 給“上傳”添加樣式
在一個(gè)網(wǎng)站中可能我的輸入框式下面這樣的:

設(shè)計(jì)者可能想讓上傳部分也像這樣然后再添加一個(gè)select按鈕。但是當(dāng)我想把普通的輸入框改為上傳框時(shí)就根本不能工作。瀏覽器之間有很大的不同,給默認(rèn)按鈕添加樣式也幾乎不可能。

這很難成為設(shè)計(jì)的很好的上傳框,但是也是我們能做的最多的了。
注意到Safari的設(shè)計(jì)有些不同。Safari小組想關(guān)閉手動(dòng)輸入文件的功能,可能擔(dān)心這樣的溢出。這樣設(shè)計(jì)有個(gè)缺點(diǎn)就是用戶在選擇了一個(gè)文件之后不能取消上傳文件。
解決辦法
讀者Michael McGrady發(fā)明了一個(gè)不錯(cuò)的小技巧來(lái)解決給上傳按鈕添加樣式的問(wèn)題。這個(gè)頁(yè)面上的所有解決辦法都是他發(fā)明的,我只是添加了position:relative,一些注釋和測(cè)試,然后轉(zhuǎn)為JavaScript。
沒(méi)有使用這個(gè)技巧的時(shí)候:
使用了之后我想成為這樣:
現(xiàn)在看起來(lái)好多了不是么?
McGrady的方法很簡(jiǎn)單且優(yōu)雅:
1、設(shè)置一個(gè)普通的<input type="file">
,然后放置在包含postion:relative屬性的元素中。
2、同樣在父元素中,添加一個(gè)普通的<input>和一個(gè)圖片,給他們?cè)O(shè)置樣式。給他設(shè)置絕對(duì)位置讓這個(gè)普通的input能夠和<input type="file">重疊。
3、然后把<input type="file">的z-index設(shè)置為2,這樣他就能在普通的input上面顯示。
4、最后將<input type="file">的opacity設(shè)置為0。這樣<input type="file">就看不見(jiàn)了,下面的input/image就能顯現(xiàn)出來(lái),但是你還能點(diǎn)擊“瀏覽”按鈕。如果這個(gè)按鈕的位置在圖片上面,那么看起來(lái)好像點(diǎn)擊的就是圖片一樣。
注意你不能使用visibility:hidden,因?yàn)橐粋€(gè)真正的不可見(jiàn)元素是不能點(diǎn)擊的,我們需要一個(gè)能點(diǎn)擊的不可見(jiàn)元素。
至此,這個(gè)效果可以通過(guò)純CSS顯示了,但是還差一點(diǎn)
5、當(dāng)用戶選擇了一個(gè)文件之后,那個(gè)可見(jiàn)的假的輸入框應(yīng)該顯示選擇文件的路徑,就像正常的<input type="file">一樣。雖然只需要簡(jiǎn)單的把<input type="file">的內(nèi)容復(fù)制過(guò)來(lái),但是還是需要JavaScript的。
所以這個(gè)技術(shù)如果沒(méi)有JavaScript可能不能完全實(shí)現(xiàn)。我一會(huì)會(huì)解釋原因。我決定把整個(gè)這個(gè)想法寫(xiě)成JavaScript的。如果你想使用沒(méi)有文件名顯示的上傳框的話也可以使用純CSS方式,雖然這不是一個(gè)好辦法。
HTML/CSS結(jié)構(gòu)
我打算用下面的HTML/CSS結(jié)構(gòu):
div.fileinputs {
position: relative;
}
div.fakefile {
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
}
input.file {
position: relative;
text-align: right;
-moz-opacity:0 ;
filter:alpha(opacity: 0);
opacity: 0;
z-index: 2;
}
<div class="fileinputs">
<input type="file" class="file" />
<div class="fakefile">
<input />
<img src="search.gif" />
</div>
</div>
<div class="fileinputs">的位置是relative,這樣我們就能在里面放置一個(gè)絕對(duì)位置的層:假的輸入框。
<div class="fakefile">包含一個(gè)假的輸入框和一個(gè)按鈕,他的位置是絕對(duì)的,z-index值是1,這樣他就能在真正的上傳框下面顯示。
真正的上傳框也有位置屬性relavtive,這樣就能設(shè)置他的z-index值了??傊枰蟼骺蛟诩俚妮斎肟蛑巷@示。然后我們?cè)O(shè)置他的透明度為0,讓他不可見(jiàn)。
還需要注意text-align:right:因?yàn)镸ozilla不能設(shè)置上傳框的寬度,所以我們要保證瀏覽按鈕在DIV的右邊緣,假的按鈕也要在右邊,而且應(yīng)該在真的下面。
你還需要一些css代碼來(lái)設(shè)置寬度高度邊框等等,在這個(gè)例子中我沒(méi)有寫(xiě)。
為什么是JavaScript?
使用JavaScript的第一個(gè)原因就是要把文件路徑復(fù)制到假的文本框里。
第二,JavaScript會(huì)忽略掉沒(méi)有意義的HTML代碼:<div class="fakefile">,讓代碼保持干凈。
最后,對(duì)于一些舊的瀏覽器不能處理CSS,在Netscape和IE4里面文件輸入就不可訪問(wèn)。對(duì)于那些沒(méi)有CSS的瀏覽器,用戶會(huì)看到兩個(gè)輸入框,而且不能理解第二個(gè)是干嘛的。
Netscape 4的問(wèn)題
在Netscape 4里面用戶只能看見(jiàn)按鈕??赡苁且?yàn)閜osition:absolute的原因。
IE4的問(wèn)題
在IE4里面會(huì)有一個(gè)詭異的原來(lái)的“瀏覽”按鈕的影子,而且不能點(diǎn)擊。沒(méi)有解決辦法
Netscape 3的問(wèn)題
對(duì)于那些沒(méi)有CSS功能的瀏覽器。雖然可以使用,但是兩個(gè)輸入框會(huì)讓用戶郁悶。
解決辦法-JavaScript
這些問(wèn)題的解決辦法就是JavaScript:通過(guò)JavaScript生成輸入框和按鈕。現(xiàn)在最壞的情況就是JavaScript不能執(zhí)行,即使如此,用戶也能上傳文件。雖然不那么好看,但是還是能工作的。
所以原來(lái)復(fù)雜的HTML變成了:
<div class="fileinputs">
<input type="file" class="file">
</div>
我們通過(guò)JavaScript來(lái)添加其他元素。
代碼
var W3CDOM = (document.createElement && document.getElementsByTagName);
function initFileUploads() {
if (!W3CDOM) return;
var fakeFileUpload = document.createElement('div');
fakeFileUpload.className = 'fakefile';
fakeFileUpload.appendChild(document.createElement('input'));
var image = document.createElement('img');
image.src='pix/button_select.gif';
fakeFileUpload.appendChild(image);
var x = document.getElementsByTagName('input');
for (var i=0;i<x.length;i++) {
if (x[i].type != 'file') continue;
if (x[i].parentNode.className != 'fileinputs') continue;
x[i].className = 'file hidden';
var clone = fakeFileUpload.cloneNode(true);
x[i].parentNode.appendChild(clone);
x[i].relatedElement = clone.getElementsByTagName('input')[0];
x[i].onchange = x[i].onmouseout = function () {
this.relatedElement.value = this.value;
}
}
}
解釋
如果瀏覽器不支持W3C DOM,那么什么也不做。
var W3CDOM = (document.createElement && document.getElementsByTagName);
function initFileUploads() {
if (!W3CDOM) return;
創(chuàng)建<div class="fakefile">和他的內(nèi)容。需要的時(shí)候我們會(huì)復(fù)制它。
var fakeFileUpload = document.createElement('div');
fakeFileUpload.className = 'fakefile';
fakeFileUpload.appendChild(document.createElement('input'));
var image = document.createElement('img');
image.src='pix/button_select.gif';
fakeFileUpload.appendChild(image);
然后遍歷頁(yè)面上的所有input,如果不是<input type="file">則忽略。
var x = document.getElementsByTagName('input');
for (var i=0;i<x.length;i++) {
if (x[i].type != 'file') continue;
再做一次檢測(cè):如果<input type="file">的父元素沒(méi)有fileinputs的class,則忽略。
現(xiàn)在我們就找到了需要添加樣式的上傳框。首先我們添加一個(gè)hidden的類名。
復(fù)制假的輸入框然后添加在<input type="file">的父元素上。
x[i].parentNode.appendChild(clone);
現(xiàn)在我們就成功的添加了樣式。但是還沒(méi)有結(jié)束,我們希望用戶在輸入框內(nèi)看到文件路徑。
首先我們給<input type="file">創(chuàng)建一個(gè)屬性,指向假的輸入框:
這樣當(dāng)用戶改變了上傳文件的時(shí)候我們就能很輕松及時(shí)的訪問(wèn)到假的輸入框,然后復(fù)制路徑。
在這有個(gè)問(wèn)題,我們使用什么event呢?通常使用change事件,當(dāng)上傳文件改變的時(shí)候,假的輸入框的值也隨之改變。
但是Mozilla 1.6在上傳框上不支持這個(gè)事件(Firefox支持)。所以我在這里添加一個(gè)onmouseout的事件。(IE下同樣可以運(yùn)行,Safari不行)
this.relatedElement.value = this.value; 3 }
問(wèn)題和擴(kuò)展
還有一個(gè)問(wèn)題,用戶在選擇了一個(gè)文件之后就不能取消了。
假設(shè)用戶選擇了一個(gè)文件之后,突然不想上傳了。通常只需要?jiǎng)h除文件路徑就可以了。但是在我們的例子里卻很難,試一試,可以刪除但是通常與感覺(jué)相反。
所以我們希望用戶通過(guò)修改假的輸入框也能修改真正的上傳路徑。
允許選擇是可能的。當(dāng)用戶選擇了上傳文件的任何部分,我們就選擇整個(gè)假輸入框的全部?jī)?nèi)容。
[code] x[i].onselect = function () { 2 this.relatedElement.select(); 3 }
但是JavaScript的安全性不允許程序修改上傳路徑,所以我們不能通過(guò)讓用戶修改輸入框的內(nèi)容來(lái)修改真正的上傳路徑。所以我決定放棄onselect事件。
一種可行的辦法是:給假的輸入框添加一個(gè)清楚按鈕,當(dāng)用戶點(diǎn)擊之后就刪除掉原來(lái)的上傳框然后重新創(chuàng)建一個(gè)。這雖然笨重,但是能確實(shí)刪除用戶不想上傳的文件路徑。我不覺(jué)得這個(gè)一定可以工作,我也沒(méi)有寫(xiě)這部分代碼。
點(diǎn)擊事件的路徑
有讀者建議,去掉那些繁雜的CSS,徹底隱藏上傳框,然后把假的輸入框的click事件綁定在真正的上傳框上。非常棒的想法,而且比上面的簡(jiǎn)單的多。
[code] fakeField.onclick = function () { 2 realField.click() 3 }
這個(gè)click()方法允許你仿真一個(gè)表單項(xiàng)。復(fù)選框的點(diǎn)擊,單選框被選中等等。然而Mozilla和Opera不支持。我想知道為什么,因?yàn)樘砑舆@個(gè)方法最大的不安全性就在于彈出一個(gè)選擇文件的對(duì)話框而已。
所以我們也不能用這個(gè)簡(jiǎn)單的辦法。
翻譯地址:http://www.quirksmode.org/dom/inputfile.html
轉(zhuǎn)載請(qǐng)保留以下信息
作者:北玉(tw:@rehawk)
- javascript動(dòng)態(tài)添加樣式(行內(nèi)式/嵌入式/外鏈?zhǔn)降纫?guī)則)
- 再談javascript 動(dòng)態(tài)添加樣式規(guī)則 W3C校檢
- js實(shí)現(xiàn)class樣式的修改、添加及刪除的方法
- 通過(guò)js為元素添加多項(xiàng)樣式,瀏覽器全兼容寫(xiě)法
- JS函數(shù)實(shí)現(xiàn)動(dòng)態(tài)添加CSS樣式表文件
- Javascript 檢測(cè)、添加、移除樣式(className)函數(shù)代碼
- JavaScript動(dòng)態(tài)添加css樣式和script標(biāo)簽
相關(guān)文章
JavaScript學(xué)習(xí)筆記整理_用于模式匹配的String方法
下面小編就為大家?guī)?lái)一篇JavaScript學(xué)習(xí)筆記整理_用于模式匹配的String方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09Javascript實(shí)例教程(19) 使用HoTMetal(1)
Javascript實(shí)例教程(19) 使用HoTMetal(1)...2006-12-12JavaScript基礎(chǔ)之立即執(zhí)行函數(shù)
這篇文章主要介紹了如何理解JavaScript中的立即執(zhí)行函數(shù),幫助大家更好的學(xué)習(xí)JavaScript,感興趣的朋友可以了解下2021-11-11解決js正則匹配換行問(wèn)題實(shí)現(xiàn)代碼
js正則匹配換行過(guò)程中會(huì)出現(xiàn)很多的問(wèn)題,本文將提供詳細(xì)的解決方法,需要的朋友可以參考下2012-12-12JavaScript 學(xué)習(xí)筆記(十三)Dom創(chuàng)建表格
下面弄個(gè)實(shí)例,運(yùn)用Dom的知識(shí),實(shí)例操作。2010-01-01JavaScript中的toUTCString()方法使用詳解
這篇文章主要介紹了JavaScript中的toUTCString()方法使用詳解,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-06-06javascript學(xué)習(xí)筆記(一)基礎(chǔ)知識(shí)
本文是學(xué)習(xí)筆記系列的第一篇,跟以前一樣,介紹些基礎(chǔ)知識(shí),包括js基本概念、 JScript 的變量、js的數(shù)據(jù)類型、3.JScript 的運(yùn)算符、js流程控制、js函數(shù)。有需要的朋友可以參考下2014-09-09