通过 Javascript 实现的 CSS 浏览器选择符(CSS Browser Selector)

CSS 在不同浏览器下的最终显示效果是不同的,因此,出现了很多根据不同浏览器作相应处理的 HACK 技术,本文介绍的是通过 Javascript 检测浏览器和操作平台类型,然后设置特定选择符。设置样式时,通过 CSS 的包含选择符,我们很容易就能根据不同浏览器作出不同处理。

通过 Javascript 实现的 CSS 浏览器选择符(CSS Browser Selector) – 示例

 
<script type="text/javascript">
// 说明 : 通过 Javascript 实现的 CSS 浏览器选择符(CSS Browser Selector)
// 整理 : CodeBit.cn ( http://www.codebit.cn )
 
// CSS Browser Selector   v0.2.5
// Documentation:         http://rafael.adm.br/css_browser_selector
// License:               http://creativecommons.org/licenses/by/2.5/
// Author:                Rafael Lima (http://rafael.adm.br)
// Contributors:          http://rafael.adm.br/css_browser_selector#contributors
var css_browser_selector = function() {
	var 
		ua=navigator.userAgent.toLowerCase(),
		is=function(t){ return ua.indexOf(t) != -1; },
		h=document.getElementsByTagName('html')[0],
		b=(!(/opera|webtv/i.test(ua))&&/msie (d)/.test(ua))?('ie ie'+RegExp.$1):is('gecko/')? 'gecko':is('opera/9')?'opera opera9':/opera (d)/.test(ua)?'opera opera'+RegExp.$1:is('konqueror')?'konqueror':is('applewebkit/')?'webkit safari':is('mozilla/')?'gecko':'',
		os=(is('x11')||is('linux'))?' linux':is('mac')?' mac':is('win')?' win':'';
	var c=b+os+' js';
	h.className += h.className?' '+c:c;
}();
</script>

其原理是:先用 js 检测浏览器类型和操作系统平台,然后给最高节点 “HTML” 赋上对应的 class ,然后在设置样式时,我们就可以通过 css 的包含选择符,根据不同浏览器作出不同处理了。

当 eval 返回的 json 值时,提示 Error: Invalid Label

我们经常会在服务器端返回 json 格式的值,这样可以直接在脚本中当作完整的对象来使用,但是,许多新手通常都会遇到一个错误提示: Invalid Label ,这个问题通常会让人苦恼不堪,因为明明正确的 json 格式,却提示错误。

假如你从服务器端返回的是 json 格式的字符串:

 
{
	siteName : "CodeBit.cn",
	siteUrl : "http://www.CodeBit.cn"
}

当你在脚本中用 eval 的方式运行:

 
var result = eval(o.responseText);
alert(result.siteName);

这时会提示 : Error: Invalid Label

实际上,我们的 json 格式并没有错误,只是在 eval 的时候,要把你的 json 值用 “()” 括号括起来:

 
var result = eval("(" + o.responseText + ")");
alert(result.siteName);

呵呵,这个往往最容易忽略,但是一旦有错误,往往也最让人头痛:)

用 CSS 实现图片替换文字(Image replacement)

不论是对浏览者还是对搜索引擎,文字都是最佳的页面内容展示方式,但是,由于字体等原因的限制,纯文字的展示渐渐无法满足爱美的设计师的要求。

于是,出现了通过 CSS 来实现用图片替换文字的方法,这种方式既能实现页面上各种丰富的效果,又能满足搜索引擎优化的需要。因此,深受网页设计师的喜爱,本文介绍了几种常见的图文替换技术。

Fahrner Image Replacement (FIR)

这是最早出现的图文替换技术,是由 Todd Fahrner 提出的,非常容易理解:

HTML 代码:

 
<h2>
	<span>Hello World</span>
</h2>

CSS 代码

 
<style type="text/css">
h2 {
	background:url(hello_world.gif) no-repeat;
	width: 150px;
	height: 35px;
}
span {
	display: none;
}
</style>

代码非常明白:先将图片应用在 H2 的背景中,然后将 SPAN 的标签隐藏。但是这种方式有个问题,就是当图片无法显示时,将导致这个区域没有任何内容。同时,使用 display:none 的方式隐藏的内容,将被许多主流屏幕阅读器忽略,从而造成可用性问题,因此,应该尽量避免使用。

Phark 的方法

这种技术是由 Mike Rundle 提出的,好处是不需要额外的标签:

HTML 代码:

 
<h2>
Hello World
</h2>

CSS 代码

 
<style type="text/css">
h2 {
	text-indent: -5000px;
	background:url(hello_world.gif) no-repeat;
	width: 150px;
	height:35px;
}
</style>

代码也非常简单,通过文本缩进,将文字隐藏,但是,当图片无法显示时,依然存在 FIR 的问题。

Gilder/Levin 的方法

这种技术是由 Tom Gilder 和 Levin Alexander 共同提出的,这也许是一个最完善的图文替换技术了:

HTML 代码:

 
<h2>
	<span></span>Hello World
</h2>

CSS 代码

 
<style type="text/css">
h2 {
	width: 150px;
	height: 35px;
	position: relative;
}
h2 span {
	background: url(hello_world.gif) no-repeat;
	position: absolute;
	width: 100%;
	height: 100%;
}
</style>

首先,将 H2 的 position 设为 relative ,这样将使 H2 里面的元素定位以 H2 为参照,然后将 SPAN 元素绝对定位,撑满整个 H2 区域,同时将背景图应用在 SPAN 标签里面;这种方法的原理是将 SPAN 标签覆盖在文字内容上面,一旦 SPAN 里面的背景图无法显示,将显示下层的文字内容,不影响正常使用。但是,此方法也有一个缺陷,就是背景图不能透明,否则将透出下面的文字。

用 Javascript 验证表单(form)中多选框(checkbox)值

和单选框一样,许多新手在用 Javascript 验证表单(form)中多选框(checkbox)的值时,都会遇到问题,原因是 checkbox 和普通的文本框在获取值的时候有很大不同,本文介绍了一个较为通用的获取 checkbox 值的方法,希望对新手有用。

用 Javascript 验证表单(form)中多选框(checkbox)值 – 示例

 
<script type="text/javascript">
 
// 说明: 用 Javascript 验证表单(form)中多选框(checkbox)的值
// 作者: CodeBit.cn  ( http://www.CodeBit.cn )
 
function getCheckboxValue(checkbox)
{
	if (!checkbox.length && checkbox.type.toLowerCase() == 'checkbox')
	{ return (checkbox.checked)?checkbox.value:'';  }
	
	if (checkbox[0].tagName.toLowerCase() != 'input' || 
		checkbox[0].type.toLowerCase() != 'checkbox')
	{ return ''; }
 
	var val = [];
	var len = checkbox.length;
	for(i=0; i<len; i++)
	{
		if (checkbox[i].checked)
		{
			val[val.length] = checkbox[i].value;
		}
	}
	
	return (val.length)?val:'';
}
 
</script>

和 radio 一样,都是 name 相同,值有多个,在获取 checkbox 值的时候,我们不能按照普通文本框 .value 的方式,而是要判断哪个被选中了。

当一组 checkbox 有多个选项时,我们可以通过循环,以 checkbox[i] 的方式判断某个选项是否被选中来返回值,但是当一组 checkbox 只有一个选项时,获取值的方式又有变化,代码中以 (checkbox.checked)?checkbox.value:”; 的方式直接判断是否选中,然后返回对应值。

上面的代码传入的参数是 checkbox 对象,如:

var checkboxTest = document.forms[‘testForm’].elements[‘checkboxTest’];
if (getCheckboxValue(checkboxTest) == ”)
{ …… }

根据判断结果执行你想要的操作。

用 Javascript 验证表单(form)中的单选(radio)值

在用 Javascript 验证表单(form)中的单选框(radio)是否选中时,很多新手都会遇到问题,原因是 radio 和普通的文本框在获取值的时候有很大不同,本文介绍了一个较为通用的获取 radio 值的方法,希望对新手有用。

用 Javascript 验证表单(form)中的单选(radio)值 – 示例

 
<script type="text/javascript">
 
// 说明: 用 Javascript 验证表单(form)中的单选(radio)值
// 作者: CodeBit.cn  ( http://www.CodeBit.cn )
 
function getRadioValue(radio)
{
	if (!radio.length && radio.type.toLowerCase() == 'radio') 
	{ return (radio.checked)?radio.value:'';  }
 
	if (radio[0].tagName.toLowerCase() != 'input' || 
		radio[0].type.toLowerCase() != 'radio')
	{ return ''; }
 
	var len = radio.length;
	for(i=0; i<len; i++)
	{
		if (radio[i].checked)
		{
			return radio[i].value;
		}
	}
	return '';
}
 
</script>

radio 和 checkbox 一样,都是 name 相同,值有多个,在获取 radio 值的时候,我们不能按照普通文本框 .value 的方式,而是要判断哪个被选中了。

当一组 radio 有多个选项时,我们可以通过循环,以 radio[i] 的方式判断某个选项是否被选中来返回值,但是当一组 radio 只有一个选项时,获取值的方式又有变化,代码中以 return (radio.checked)?radio.value:”; 这样的方式直接判断是否选中,然后返回对应值。

上面的代码传入的参数是 radio 对象,如:

var radioTest = document.forms[‘testForm’].elements[‘radioTest’];
if (getRadioValue(radioTest) == ”)
{ …… }

根据判断结果执行你想要的操作。

CSS Hack 汇总快查

由于浏览器之间存在兼容性问题,在制作网页的时候,为了使页面能在不同浏览器中显示相对一致或者其他原因,网页制作人员总结了种种 Hack 方法;在解决兼容性问题之前,这些方法还经常会用到。

屏蔽IE浏览器(也就是IE下不显示)

 
*:lang(zh) select {font:12px  !important;} /*FF,OP可见,特别提醒:由于Opera最近的升级,目前此句只为FF所识别*/
select:empty {font:12px  !important;} /*safari可见*/
这里select是选择符,根据情况更换。第二句是MAC上safari浏览器独有的。

仅IE7与IE5.0可以识别

 
*+html  select {…}
当面临需要只针对IE7与IE5.0做样式的时候就可以采用这个HACK。

仅IE7可以识别

 
*+html  select {…!important;}
当面临需要只针对IE7做样式的时候就可以采用这个HACK。

IE6及IE6以下识别

 
* html  select {…}
这个地方要特别注意很多博客都写成了是IE6的HACK其实IE5.x同样可以识别这个HACK。其它浏览器不识别。
html/**/ >body  select {…}
这句与上一句的作用相同。

仅IE6不识别,屏蔽IE6

 
select { display /*屏蔽IE6*/:none;}
这里主要是通过CSS注释分开一个属性与值,注释在冒号前。

仅IE6与IE5不识别,屏蔽IE6与IE5

 
select/**/ { display /*IE6,IE5不识别*/:none;}
这里与上面一句不同的是在选择符与花括号之间多了一个CSS注释。不屏蔽IE5.5

仅IE5不识别,屏蔽IE5

 
select/*IE5不识别*/ {…}
这一句是在上一句中去掉了属性区的注释。只有IE5不识别,IE5.5可以识别。

盒模型解决方法

 
selct {width:IE5.x宽度; voice-family :""}""; voice-family:inherit; width:正确宽度;}
盒模型的清除方法不是通过!important来处理的。这点要明确。

清除浮动

 
select:after {content:"."; display:block; height:0; clear:both; visibility:hidden;}
在Firefox中,当子级都为浮动时,那么父级的高度就无法完全的包住整个子级,那么这时用这个清除浮动的HACK来对父级做一次定义,那么就可以解决这个问题。

截字省略号

 
select { -o-text-overflow:ellipsis; text-overflow:ellipsis; white-space:nowrap; overflow:hidden; }
这个是在越出长度后会自行的截掉多出部分的文字,并以省略号结尾,很好的一个技术。只是目前Firefox并不支持。

只有Opera识别

 
@media all and (min-width: 0px){ select {……} }
针对Opera浏览器做单独的设定。

以上都是写CSS中的一些HACK,这些都是用来解决局部的兼容性问题,如果希望把兼容性的内容也分离出来,不妨试一下下面的几种过滤器。这些过滤器有的是写在CSS中通过过滤器导入特别的样式,也有的是写在HTML中的通过条件来链接或是导入需要的补丁样式。

IE5.x的过滤器,只有IE5.x可见

 
@media tty {
i{content:"";/*" "*/}} @import 'ie5win.css'; /*";}
}/* */

IE5/MAC的过滤器,一般用不着

 
/**//*/
    @import "ie5mac.css";
/**/

IE的if条件Hack

 
<!--[if IE]> Only IE <![endif]-->
所有的IE可识别
<!--[if IE 5.0]> Only IE 5.0 <![endif]-->
只有IE5.0可以识别
<!--[if gt IE 5.0]> Only IE 5.0+ <![endif]-->
IE5.0包换IE5.5都可以识别
<!--[if lt IE 6]> Only IE 6- <![endif]-->
仅IE6可识别
<!--[if gte IE 6]> Only IE 6/+ <![endif]-->
IE6以及IE6以下的IE5.x都可识别
<!--[if lte IE 7]> Only IE 7/- <![endif]-->
仅IE7可识别

原文网址:http://andymao.com/andy/post/76.html

不增加额外元素实现清除浮动( 闭合浮动元素 Clear Floats )

浮动(Float)是页面布局中经常用到的技巧,但是,同时也出现了很多由于浮动引发的问题;父元素不能闭合具有浮动属性的子元素,是这些问题中最常见且最让新手头痛的一个。

清除浮动常见的做法是加一个额外的标签,然后给这个标签加上 clear:both 的设置,追求完美的人当然不乐意这种方式,于是,便有了本文将要介绍的:不增加额外元素实现清除浮动的方法。

 
<style type="text/css">
 
/*
说明:不增加额外元素实现清除浮动( 闭合浮动元素 Clear Floats )
整理: CodeBit.cn ( http://www.CodeBit.cn )
*/
 
.clearfix:after {
    content: "."; 
    display: block; 
    height: 0; 
    clear: both; 
    visibility: hidden;
}
 
.clearfix {display: inline-block;}
 
/* Hides from IE-mac */
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide from IE-mac */
 
</style>

使用时,给需要清除浮动的元素增加一个 clearfix 的 class 即可。

滑动式折叠菜单 - Slashdot’s Menu

折叠菜单让你在尽可能小的地方放置尽可能多的内容,同时加大了操作的简便性,因此,深受前台设计师的喜爱。随着大家对动画效果的钟爱,折叠菜单也开始“动”起来了,本文介绍的就是 DimX 制作的滑动式折叠菜单效果-Slashdot’s Menu。

滑动式折叠菜单 - Slashdot’s Menu – 示例

 
<script type="text/javascript">
function SDMenu(id) {
	if (!document.getElementById || !document.getElementsByTagName)
		return false;
	this.menu = document.getElementById(id);
	this.submenus = this.menu.getElementsByTagName("div");
	this.remember = true;
	this.speed = 3;
	this.markCurrent = true;
	this.oneSmOnly = false;
}
SDMenu.prototype.init = function() {
	var mainInstance = this;
	for (var i = 0; i < this.submenus.length; i++)
		this.submenus[i].getElementsByTagName("span")[0].onclick = function() {
			mainInstance.toggleMenu(this.parentNode);
		};
	if (this.markCurrent) {
		var links = this.menu.getElementsByTagName("a");
		for (var i = 0; i < links.length; i++)
			if (links[i].href == document.location.href) {
				links[i].className = "current";
				break;
			}
	}
	if (this.remember) {
		var regex = new RegExp("sdmenu_" + encodeURIComponent(this.menu.id) + "=([01]+)");
		var match = regex.exec(document.cookie);
		if (match) {
			var states = match[1].split("");
			for (var i = 0; i < states.length; i++)
				this.submenus[i].className = (states[i] == 0 ? "collapsed" : "");
		}
	}
};
SDMenu.prototype.toggleMenu = function(submenu) {
	if (submenu.className == "collapsed")
		this.expandMenu(submenu);
	else
		this.collapseMenu(submenu);
};
SDMenu.prototype.expandMenu = function(submenu) {
	var fullHeight = submenu.getElementsByTagName("span")[0].offsetHeight;
	var links = submenu.getElementsByTagName("a");
	for (var i = 0; i < links.length; i++)
		fullHeight += links[i].offsetHeight;
	var moveBy = Math.round(this.speed * links.length);
	
	var mainInstance = this;
	var intId = setInterval(function() {
		var curHeight = submenu.offsetHeight;
		var newHeight = curHeight + moveBy;
		if (newHeight < fullHeight)
			submenu.style.height = newHeight + "px";
		else {
			clearInterval(intId);
			submenu.style.height = "";
			submenu.className = "";
			mainInstance.memorize();
		}
	}, 30);
	this.collapseOthers(submenu);
};
SDMenu.prototype.collapseMenu = function(submenu) {
	var minHeight = submenu.getElementsByTagName("span")[0].offsetHeight;
	var moveBy = Math.round(this.speed * submenu.getElementsByTagName("a").length);
	var mainInstance = this;
	var intId = setInterval(function() {
		var curHeight = submenu.offsetHeight;
		var newHeight = curHeight - moveBy;
		if (newHeight > minHeight)
			submenu.style.height = newHeight + "px";
		else {
			clearInterval(intId);
			submenu.style.height = "";
			submenu.className = "collapsed";
			mainInstance.memorize();
		}
	}, 30);
};
SDMenu.prototype.collapseOthers = function(submenu) {
	if (this.oneSmOnly) {
		for (var i = 0; i < this.submenus.length; i++)
			if (this.submenus[i] != submenu && this.submenus[i].className != "collapsed")
				this.collapseMenu(this.submenus[i]);
	}
};
SDMenu.prototype.expandAll = function() {
	var oldOneSmOnly = this.oneSmOnly;
	this.oneSmOnly = false;
	for (var i = 0; i < this.submenus.length; i++)
		if (this.submenus[i].className == "collapsed")
			this.expandMenu(this.submenus[i]);
	this.oneSmOnly = oldOneSmOnly;
};
SDMenu.prototype.collapseAll = function() {
	for (var i = 0; i < this.submenus.length; i++)
		if (this.submenus[i].className != "collapsed")
			this.collapseMenu(this.submenus[i]);
};
SDMenu.prototype.memorize = function() {
	if (this.remember) {
		var states = new Array();
		for (var i = 0; i < this.submenus.length; i++)
			states.push(this.submenus[i].className == "collapsed" ? 0 : 1);
		var d = new Date();
		d.setTime(d.getTime() + (30 * 24 * 60 * 60 * 1000));
		document.cookie = "sdmenu_" + encodeURIComponent(this.menu.id) + "=" + states.join("") + "; expires=" + d.toGMTString() + "; path=/";
	}
};
</script>

调用方式

 
var myMenu = new SDMenu("main_menu"); // 菜单ID
 
// 默认参数
myMenu.speed = 3;                     // 折叠速度
myMenu.remember = true;               // 是否记录状态
myMenu.oneSmOnly = false;             // 一次只有一个菜单打开
myMenu.markCurrent = true;            // 是否高亮当前菜单
 
myMenu.init();
 
// 附加方法
var firstSubmenu = myMenu.submenus[0];
myMenu.expandMenu(firstSubmenu);      // 打开一个菜单
myMenu.collapseMenu(firstSubmenu);    // 关闭一个菜单
myMenu.toggleMenu(firstSubmenu);      // 当菜单关闭时打开,当菜单打开时关闭
 
myMenu.expandAll();                   // 打开所有菜单
myMenu.collapseAll();                 // 关闭所有菜单

获取 $_SERVER[“REQUEST_URI”] 值的通用解决方案

在 PHP 众多预定义服务器变量中,$_SERVER["REQUEST_URI"] 算是经常用到的,但是这个变量只有 apache 才支持,因此,我们需要一个更加通用的方式来获取 REQUEST_URI 的值,本文就是结束这一问题的解决方案。

 
<?php
 
// 说明:获取 _SERVER['REQUEST_URI'] 值的通用解决方案
// 来源:drupal-5.1 bootstrap.inc
// 整理:CodeBit.cn ( http://www.CodeBit.cn )
 
function request_uri()
{
	if (isset($_SERVER['REQUEST_URI']))
	{
		$uri = $_SERVER['REQUEST_URI'];
	}
	else
	{
		if (isset($_SERVER['argv']))
		{
			$uri = $_SERVER['PHP_SELF'] .'?'. $_SERVER['argv'][0];
		}
		else
		{
			$uri = $_SERVER['PHP_SELF'] .'?'. $_SERVER['QUERY_STRING'];
		}
	}
	return $uri;
}
 
?>

用 Javascript 实现只能输入数字的文本框

在制作表单(Form)的时候,我们通常会给表单元素添加一些输入规则,比如邮件地址、数字等,我们会在特定的时候执行验证,如果验证不通过,会给出一定的提示信息,本文介绍的是用 Javascript 实现只能输入数字的文本框:

用 Javascript 实现只能输入数字的文本框 – 示例

执行验证可以有以下几种方式:
1. 在输入的时候验证,这种验证有一定的特殊性,比如只能输入数字或者只能输入英文字符这样的规则才能应用,如果是 email 验证就不行。

2. 在输入完成时验证,即在 onblur 事件发生时验证。这个适用范围很广,基本上验证都可以使用。

3. 在提交表单时执行验证,即表单的 onsubmit 事件中执行验证。可以一次验证所有元素,适用范围最广。

三种方式第一种实时性最高,输入的时候就验证,第二种次之,在输入完成后验证,第三中最慢,必须在提交时验证,不过每种都有自己的好处和局限性,在应用中可以根据实际情况选用。

本文验证方式是只能输入数字,带有一定的特殊性,可以选用第一种:

 
<script type="text/javascript">
 
// 说明 : 用 Javascript 实现只能输入数字的文本框
// 整理 : CodeBit.cn ( http://www.CodeBit.cn )
 
function checkNumber(e)
{
	var key = window.event ? e.keyCode : e.which;
	var keychar = String.fromCharCode(key);
	var el = document.getElementById('test');
	var msg = document.getElementById('msg');
	reg = /d/;
	var result = reg.test(keychar);
	if(!result) 
	{
		el.className = "warn";
		msg.innerHTML = "只能输入数字";
		return false;
	}
	else
	{
		el.className = "";
		msg.innerHTML = "";
		return true;
	}
}
 
</script>
 
<div id="test">
	请输入数字:<input type="text" onkeypress="return checkNumber(event);" />
	<span id="msg"></span>
</div>

当我们在此元素中输入时,检测用户按键,如果不是数字键,就显示提示信息,实时性较强,当然,我们也可以采用另外两种方式。