前端开发者学堂 - fedev.cn

自定义表单——美化你的文件载入框

发布于 大漠

表单的制作常常给我们带来无比的烦恼,比如说表单中的“input[type="radio"]、input[type="checkbox"]、select和input[type="file"]”之类,我们都无法直接通过样式来达到设计的设计要求,如果为了实现设计的设计的优美效果,我们必须通过CSS和js来实现。前面我们在《自定义表单——jQuery制作个性化Checkbox》一文中一起学习了通过jQuery和CSS3来美化表单中的“input[type="radio"]”和“input[type="checkbox"]”。今天在浏览外国bog时发现Shaun Inman在《style file inputs with css and the dom》教程中使用js和CSS来实现“<input type="file"/>”表单元素。特意整理了一下与大家一起分享。让大家在今年的表单制作中能通过这种方法让你在Web页面制作中使“input[type="file"]”样式修改不在是那么的头疼。

下面我们一起来学习如何让“input[type="file"]”实现下图那种效果:

上图中很明显的告诉我们,前面的是“input[type="file"]”的默认效果,下面的是我们需要实现的效果。要实现下图的效果,我们首先需要从设计师的设计中切出下图:

现在我们知道我们的目标了,下面开始我们一起来学习如何实现上图展示的“input[type="file"]”表单元素效果。

一、HTML Markup

			<form action="" class="form" method="post">
				<label for="" class="cabinet">
					<input type="file" class="file" />
				</label>
			</form>
		

我们给表单元素“<input type="file" />”定义了一个类名“file”,并且在他的外面包裹了一个名叫“cabinet”的“<label>”标签。注:为了配合后面的“SI.Files.js”中的对象,我们最好在这里的包裹元素,以及其“input[type="file"]”元素和包裹他的“label”元素和他们定义的“class”类名都保持不变。当然要是你js比较厉害的话,你要根据你自己的需求去改变也无仿,只要能让他帮你实现功能就OK了。古话说的,不管白猫和黑猫只要能抓到老鼠的就是好猫。

二、CSS Code

			.siFiles  label.cabinet {
				width: 79px;
				height: 22px;
				background: url("images/btn-choose-file.gif") 0 0 no-repeat;
				display: block;
				overflow: hidden;
				cursor: pointer;
			}
			
			.siFiles  input.file {
				position: relative;
				height: 100%;
				width: auto;
				opacity: 0;
				-moz-opacity: 0;
				filter: alpha(opacity=0); 
				filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);
			}
		

我们通过上面的CSS样式来帮助我们实现表单元素的美化。当然大家并不一定要按照上面的样式一尘不变,你完全可以根据你自己的设计需求去写你自己需要的样式,我这里只是为了实现上图展示的效果写的一个简单的样式。

三、javaScript Code

下面也是我们今天这个教程中最关键的部分——美化“input[type="file"]”表单元素功能所需的js代码。说实在的,这部分代码我好多没有看懂,但照搬我还是会的。所以我直接从Shaun Inman写的《style file inputs with css and the dom》教程中把代码扣下来放在本站,让大家更好的阅读和学习:

			// STYLING FILE INPUTS 1.0 | Shaun Inman  | 2007-09-07
			if (!window.SI) { var SI = {}; };
			SI.Files =
			{
				bodyClass : 'siFiles',
				fileClass : 'file',
				wrapClass : 'cabinet',
				
				fini : false,
				able : false,
				init : function()
				{
					this.fini = true;
					
					var ie = 0 //@cc_on + @_jscript_version
					if (window.opera || (ie && ie < 5.5) || !document.getElementsByTagName) { return; } // no support for opacity or the DOM
					this.able = true;
					
					var body = document.getElementsByTagName('body')[0];
					body.className += (body.className != '' ? ' ' : '') + this.bodyClass;
				},
				
				stylize : function(elem)
				{
					if (!this.fini) { this.init(); };
					if (!this.able) { return; };
					
					elem.parentNode.file = elem;
					elem.parentNode.onmousemove = function(e)
					{
						if (typeof e == 'undefined') e = window.event;
						if (typeof e.pageY == 'undefined' &&  typeof e.clientX == 'number' && document.documentElement)
						{
							e.pageX = e.clientX + document.documentElement.scrollLeft;
							e.pageY = e.clientY + document.documentElement.scrollTop;
						};

						var ox = oy = 0;
						var elem = this;
						if (elem.offsetParent)
						{
							ox = elem.offsetLeft;
							oy = elem.offsetTop;
							while (elem = elem.offsetParent)
							{
								ox += elem.offsetLeft;
								oy += elem.offsetTop;
							};
						};

						var x = e.pageX - ox;
						var y = e.pageY - oy;
						var w = this.file.offsetWidth;
						var h = this.file.offsetHeight;

						this.file.style.top		= y - (h / 2)  + 'px';
						this.file.style.left	= x - (w - 30) + 'px';
					};
				},
				
				stylizeById : function(id)
				{
					this.stylize(document.getElementById(id));
				},
				
				stylizeAll : function()
				{
					if (!this.fini) { this.init(); };
					if (!this.able) { return; };
					
					var inputs = document.getElementsByTagName('input');
					for (var i = 0; i < inputs.length; i++)
					{
						var input = inputs[i];
						if (input.type == 'file' && input.className.indexOf(this.fileClass) != -1 && input.parentNode.className.indexOf(this.wrapClass) != -1)
						{
							this.stylize(input);
						};
					};
				}
			};
		

如果要是你和我一样不懂js的话也不用害怕,你只需要把上面的代码完全copy下来,保存成一个文件,我在此处将其保存在项目的“js”目录下,并且使命名为“si.files.js”。js代码扣下来以后,我们需要在项目中引用这个js:

			<script type="text/javascript" src="js/si.files.js"></script>
		

当然大家在引用的时候需要注意您的路径,这一点不用我说应该知道吧。

“si.files.js”载入进来后并没有完成,我们还需要调用它:

			<script type="text/javascript">
				SI.Files.stylizeAll();
			</script>			
		

这一部分怎么调用对于老手来说不用讲了,就慢碰到和我不懂一点js的人,你只要把这段代码放在刚才那个“si.files.js”后面就OK了。上面这个“si.files.js”还提供了两种调用的方法:

1、元素的ID名:

			<script type="text/javascript">
				SI.Files.stylizeById('input-id');
			</script>			
		

这里的“input-id”指的就是你HTML Markup中“input[tpye="file"]”元素的ID名。

2、元素的节点:

			<script type="text/javascript">
				SI.Files.stylize(HTMLInputNode);
			</script>			
		

四、工作原理

首先我们通一样式对其进行了外观的包装,让其达到设计图的要求。我们的包装元素“label”和其背景图片的尺寸刚好匹配了按钮的图像设置。接着我们把“input[type="file"]”元素也就是我们所说的文件输入框本身的透明度设置为“0”,让他产生一种假像的“隐藏”效果,但他仍然是可以点击的。不过这里有一点非常重要“大家不能为了说让“input[type="file"]”达到隐藏效果,直接将其设置为“display:none”和“visibility:hidden”。如果你真的是这样设置,那么你将带来灾难性的后果,你做的一切将是无效的。这一点大家一定要记住了。”最后在通过“si.files.js”实现文件输入框的功能效果。

五、浏览器的兼容性

这种实现方法能在“IE6+”、“Firefox1.5+”、“Safari2+”、“chrome”、“opera”下正常工作。

那么通过上面几步我们就解了一个让我们头痛的表单元素美化工作。有关于上面的代码,大家可以直接到这里下载

不知道大家整明白没有,我只知道一个所以然,因为我不太懂js,但我在本地按上面的方法执行下来,已经达到前面图片展示的效果。如果你要是js知道的,你可以完全整明白,要是和我一样js不懂,就把整个js复制下来按上面的操作一步一步做吧。如果你还是不清楚,你可以直接浏览Shaun Inman写的教程——《style file inputs with css and the dom》。

那么到此有关于使用js和CSS来美化“input[type="file"]”就说到这里了,在结束之前再次感谢Shaun Inman给我们带来这么好的教程《style file inputs with css and the dom》,同时希望大家能喜欢,并且能有所值。如果您有更好的解决方法,也可以和我们一起分享。

如需转载烦请注明出处:W3CPLUS

Zoom Kobe XIII ZK13