2012年1月6日

使用:

getElementByTagNames(selector,parentNode)有两个参数:
  1、selector:一个用逗号分隔的tag名称字符串。
  2、parentNode:一个可选的开始元素。如果存在则在该元素的子元素中查找这些tag,如果不存在则在整个文档中查找。
  这个函数根据要求的tag名称返回一个数组(而不是节点列表),按照他们在源代码中的出现顺序排列。对于这个排序需要浏览器支持 sourceIndex或者compareDocumentPosition。如果都不支持(Safari)那么就按照调用 getElementByTagNames()函数时候的tag名称的顺序。

实例1 :

var headerList = getElementsByTagNames('h1,h2,h3,h4');

现在headerList就是文档里包含H1-H4的数组,按照他们出现的顺序排序。

实例2:

var element = document.getElementById('test');
var formFieldList = getElementsByTagNames('input,select,textarea',element);

现在formFieldList就是包含在ID为test的元素下的所有子元素中的input,select,TEXTAREA的数组,并且按照他们出现的书序排列。

方法实现:
 

function  getElementsByTagNames(list, obj)  {
if (!obj) 
var  obj  = document;
var  tagNames  = list.split(',');
var  resultArray  = new  Array();
for (var  i = 0; i < tagNames.length; i++)  {
var  tags  = obj.getElementsByTagName(tagNames[i]);
for (var  j = 0; j < tags.length; j++)  {
resultArray.push(tags[j]);
}
}
var  testNode  = resultArray[0];
if (!testNode) 
return [];
if (testNode.sourceIndex)  {
resultArray.sort(function (a, b)  {
return a.sourceIndex  - b.sourceIndex;
});
}
else  if (testNode.compareDocumentPosition)  {
resultArray.sort(function (a, b)  {
return 3  - (a.compareDocumentPosition(b)  & 6);
});
}
return resultArray;
}

解释

function  getElementsByTagNames(list, obj) {
if (!obj) 
var  obj  = document;

首先定义开始元素obj,如果没有给出,那么默认就是document。

var tagNames = list.split(',');
var resultArray = new Array();

将这些tag名称以逗号分割。用一个数组来保存结果。

for (var  i = 0; i < tagNames.length; i++)  {
var  tags  = obj.getElementsByTagName(tagNames[i]);
for (var  j = 0; j < tags.length; j++)  {
resultArray.push(tags[j]);
}
}

现在我们遍历所有的tag名称,就用最简单的getElementByTagName()方法,然后把结果传入resultArray。这里的一个要点是,因为getElementByTagName返回的是节点列表,所以我就不能使用array.concat()来建立新的数组。把元素一个一个的压入是我能找到的最好的办法。

我们得到了一个所需的tag名称的元素的指针数组存储在resultArray中,但是这些元素还是按照我们所给的tag的顺序排列的。我们需要再排个序。

var testNode = resultArray[0];

现在我们开始排序。我们需要知道浏览器是否支持sourceIndex或者compareDocumentPosition,然后我们对于我们的得到的原始数据做一些检测

if (!testNode) return [];

如果这里没有第一个节点(也就是说结果里并没有我们需要的元素),就返回一个空数组。

背景:array.sort()

array.sort()方法有一个可选函数的参数。这个函数用来比较两个元素(通常称为a和b)。如果第一个应该在前那么这个函数就返回一个负数,如果第二个应该在前那么就返回一个正值。

sourceIndex

如果浏览器支持sourceIndex,我们就根据元素的sourceIndex来排序。sourceIndex是微软的一个非常有用的扩展,可以用来知道元素在源代码中的索引值。页面种的第一个元素(<HTML>)的索引值就是0,第二个(<head>)就是1,等等。 sourceIndex也是getElementByTagName(*)中的元素的索引值。

if (testNode.sourceIndex)  {
resultArray.sort(function (a, b)  {
return a.sourceIndex  - b.sourceIndex;
});
}

我们用第一个元素的sourceIndex值减去第二个元素的sourceIndex,如果是负值,那么第一个元素就排在前面,如果是正值,那么第二个元素排在前面。这就是sort()需要的。现在resultArray中的元素就是根据他们在文档中的位置来排序的。
  
compareDocumentPosition

  如果浏览器支持compareDocumentPosition,那么就用这个办法来排序。compareDocumentPosition是level3的核心方法,他可以比较两个节点在文档中的位置,然后返回一个值:
 
1 没有找到
  
2 在前
  
4 在后
 
8 包含
  
16 被包含
  
比如,如果一个标签被包含并且在另一个标签的后面,那么就返回16+4=20。

else if (testNode.compareDocumentPosition)  {
resultArray.sort(function (a, b)  {
return 3  - (a.compareDocumentPosition(b)  & 6);
});
}

  我们只对compareDocumentPosition的值中的2、4感兴趣:在前或者在后。所以我们将结果和6进行与运算,这样结果就会是2或者4(当然结果不能是6,因为一个元素不能即在一个元素之前又在一个元素之后)
  如果b在a之后则返回4,但是sort()需要一个负数。如果b在a之前则返回2,但是sort()需要一个正数。为了给sort()一个正确的结果我把他们用3来减。这样就得到1或者-1,这样sort()就能对元素进行正确的排序,resultArray中的元素也按照他们在文档种的出现顺序排列。

    return resultArray;
}

然后我们返回resultArray给调用它的函数。记住如果浏览器不支持sourceIndex或者compareDocumentPosition数组就没有排序。

翻译地址:http://www.quirksmode.org/dom/getElementsByTagNames.html
 

posted @ 2012-01-06 14:35 pifoo 阅读(1177) 评论(1) 编辑

2011年10月21日

javascript两行代码按指定格式输出日期时间,具体看代码:

// <summary>
//    格式化显示日期时间
// </summary>
// <param name="x">待显示的日期时间,例如new Date()</param>
// <param name="y">需要显示的格式,例如yyyy-MM-dd hh:mm:ss</param>
function date2str(x,y) {
    var z ={y:x.getFullYear(),M:x.getMonth()+1,d:x.getDate(),h:x.getHours(),m:x.getMinutes(),s:x.getSeconds()};
    return y.replace(/(y+|M+|d+|h+|m+|s+)/g,function(v) {return ((v.length>1?"0":"")+eval('z.'+v.slice(-1))).slice(-(v.length>2?v.length:2))});
}
alert(date2str(new Date(),"yy-M-d h:m:s"));
alert(date2str(new Date(),"yyyy-MM-d h:m:s"));

  

 

posted @ 2011-10-21 14:00 pifoo 阅读(441) 评论(0) 编辑

2011年5月28日

如果你是一名前端er,又想在移动设备上开发出自己的应用,那怎么实现呢?幸好,webkit内核的浏览器能帮助我们完成这一切。接触 webkit webApp的开发已经有一段时间了,现把一些技巧分享给大家 :

1. viewport:
也就是可视区域。对于桌面浏览器,我们都很清楚viewport是什么,就是出去了所有工具栏、状态栏、滚动条等等之后用于看网页的区域,
这是真正有效的区域。由于移动设备屏幕宽度不同于传统web,因此我们需要改变viewport;

实际上我们可以操作的属性有4 个:

width -             //  viewport 的宽度 (范围从200 到10,000,默认为980 像素)
height -            //  viewport 的高度 (范围从223 到10,000)

initial-scale -     //  初始的缩放比例 (范围从>0 到10)

minimum-scale -    //   允许用户缩放到的最小比例
maximum-scale -    //   允许用户缩放到的最大比例

user-scalable -    //   用户是否可以手动缩 (no,yes)

那么到底这些设置如何让Safari 知道?其实很简单,就一个meta,形如:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">	//编码
<meta id="viewport" name="viewport" content="width=320; initial-scale=1.0;maximum-scale=1.0; user-scalable=no;"/>
<meta name=”apple-mobile-web-app-capable” content=”yes” />  // 离线应用的另一个技巧		
<meta name=”apple-mobile-web-app-status-bar-style” content=black” />  // 隐藏状态栏		
<meta content="black" name="apple-mobile-web-app-status-bar-style" />	//指定的iphone中safari顶端的状态条的样式        
<meta content="telephone=no" name="format-detection" />		//告诉设备忽略将页面中的数字识别为电话号码		
<meta name="Author" contect="Mr.He"/ >  

在设置了initial-scale=1 之后,我们终于可以以1:1 的比例进行页面设计了。关于viewport,还有一个很重要的概念是:iphone 的safari 浏览器完全没有滚动条,而且不是简单的“隐藏滚动条”,是根本没有这个功能。iphone 的safari 浏览器实际上从一开始就完整显示了这个网页,然后用viewport 查看其中的一部分。当你用手指拖动时,其实拖的不是页面,而是viewport。浏览器行为的改变不止是滚动条,交互事件也跟普通桌面不一样。(请参考:指尖的下JS 系列文章)

2. link:
<link rel=”apple-touch-startup-image” href=”startup.png” /> // 设置开始页面图片
<link rel=”apple-touch-icon” href=”iphon_tetris_icon.png”/> // 在设置书签的时候可以显示好看的图标
<link rel="stylesheet" media="all and (orientation:portrait)" href="portrait.css">	// 肖像模式样式		
<link rel="stylesheet" media="all and (orientation:landscape)" href="landscape.css"   // 风景模式样式

//竖屏时使用的样式 
<style media="all and (orientation:portrait)" type="text/css">
#landscape { display: none; }
</style>

//横屏时使用的样式 
<style media="all and (orientation:landscape)" type="text/css">
#portrait { display: none; }
</style>	

3. 事件 : (请参考:指尖的下JS 系列文章)
// 手势事件
touchstart            //当手指接触屏幕时触发
touchmove           //当已经接触屏幕的手指开始移动后触发
touchend             //当手指离开屏幕时触发
touchcancel

// 触摸事件
gesturestart          //当两个手指接触屏幕时触发
gesturechange      //当两个手指接触屏幕后开始移动时触发
gestureend

// 屏幕旋转事件	
onorientationchange		

// 检测触摸屏幕的手指何时改变方向       
orientationchange		

// touch事件支持的相关属性
touches  		
targetTouches		
changedTouches				
clientX    // X coordinate of touch relative to the viewport (excludes scroll offset)		
clientY    // Y coordinate of touch relative to the viewport (excludes scroll offset)		
screenX    // Relative to the screen		
screenY     // Relative to the screen		
pageX     // Relative to the full page (includes scrolling)		
pageY     // Relative to the full page (includes scrolling)		
target     // Node the touch event originated from		
identifier     // An identifying number, unique to each touch event

4. 屏幕旋转事件:onorientationchange
添加屏幕旋转事件侦听,可随时发现屏幕旋转状态(左旋、右旋还是没旋)。例子:
// 判断屏幕是否旋转
function orientationChange() { 
	switch(window.orientation) { 
	  case 0:  
			alert("肖像模式 0,screen-width: " + screen.width + "; screen-height:" + screen.height); 
			break; 
	  case -90:  
			alert("左旋 -90,screen-width: " + screen.width + "; screen-height:" + screen.height); 
			break; 
	  case 90:    
			alert("右旋 90,screen-width: " + screen.width + "; screen-height:" + screen.height); 
			break; 
	  case 180:    
		  alert("风景模式 180,screen-width: " + screen.width + "; screen-height:" + screen.height); 
		  break; 
	};
}; // 添加事件监听 addEventListener('load', function(){ orientationChange(); window.onorientationchange = orientationChange; });

5. 隐藏地址栏 & 处理事件的时候,防止滚动条出现:
// 隐藏地址栏  & 处理事件的时候 ,防止滚动条出现
addEventListener('load', function(){ 
    	setTimeout(function(){ window.scrollTo(0, 1); }, 100); 
});

6. 双手指滑动事件:
// 双手指滑动事件
addEventListener('load',  function(){ window.onmousewheel = twoFingerScroll;}, 
     false				// 兼容各浏览器,表示在冒泡阶段调用事件处理程序 (true 捕获阶段)
); 
function twoFingerScroll(ev) { 
	var delta =ev.wheelDelta/120;              //对 delta 值进行判断(比如正负) ,而后执行相应操作 
	return true; 
}; 

7. 判断是否为iPhone:
// 判断是否为 iPhone : 
function isAppleMobile() { 
	return (navigator.platform.indexOf('iPad') != -1); 
}; 

8. localStorage:
 例子 :(注意数据名称  n  要用引号引起来)
 var v = localStorage.getItem('n') ? localStorage.getItem('n') : "";   // 如果名称是  n 的数据存在 ,则将其读出 ,赋予变量  v  。 
localStorage.setItem('n', v);    										// 写入名称为 n、值为  v  的数据 
localStorage.removeItem('n');   										// 删除名称为  n  的数据 	

9. 使用特殊链接:
 如果你关闭自动识别后 ,又希望某些电话号码能够链接到 iPhone 的拨号功能 ,那么可以通过这样来声明电话链接 ,
<a href="tel:12345654321">打电话给我</a>
<a href="sms:12345654321">发短信</a>
或用于单元格:
<td onclick="location.href='tel:122'">

10. 自动大写与自动修正
要关闭这两项功能,可以通过autocapitalize 与autocorrect 这两个选项:
<input type="text" autocapitalize="off" autocorrect="off" />

11. WebKit CSS:
①“盒模型”的具体描述性质的包围盒块内容,包括边界,填充等等。
-webkit-border-bottom-left-radius: radius;
-webkit-border-top-left-radius: horizontal_radius vertical_radius;
-webkit-border-radius: radius;      //容器圆角
-webkit-box-sizing: sizing_model; 边框常量值:border-box/content-box
-webkit-box-shadow: hoff voff blur color; //容器阴影(参数分别为:水平X 方向偏移量;垂直Y 方向偏移量;高斯模糊半径值;阴影颜色值)
-webkit-margin-bottom-collapse: collapse_behavior; 常量值:collapse/discard/separate
-webkit-margin-start: width;
-webkit-padding-start: width;
-webkit-border-image: url(borderimg.gif) 25 25 25 25 round/stretch round/stretch;
-webkit-appearance: push-button;   //内置的CSS 表现,暂时只支持push-button
②“视觉格式化模型”描述性质,确定了位置和大小的块元素。
direction: rtl
unicode-bidi: bidi-override; 常量:bidi-override/embed/normal
③“视觉效果”描述属性,调整的视觉效果块内容,包括溢出行为,调整行为,能见度,动画,变换,和过渡。
clip: rect(10px, 5px, 10px, 5px)
resize: auto; 常量:auto/both/horizontal/none/vertical
visibility: visible; 常量: collapse/hidden/visible
-webkit-transition: opacity 1s linear; 动画效果 ease/linear/ease-in/ease-out/ease-in-out
-webkit-backface-visibility: visibler; 常量:visible(默认值)/hidden
-webkit-box-reflect: right 1px; 镜向反转
-webkit-box-reflect: below 4px -webkit-gradient(linear, left top, left bottom,
from(transparent), color-stop(0.5, transparent), to(white));
-webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));;   //CSS 遮罩/蒙板效果
-webkit-mask-attachment: fixed; 常量:fixed/scroll
-webkit-perspective: value; 常量:none(默认)
-webkit-perspective-origin: left top;
-webkit-transform: rotate(5deg);
-webkit-transform-style: preserve-3d; 常量:flat/preserve-3d; (2D 与3D)
④“生成的内容,自动编号,并列出”描述属性,允许您更改内容的一个组成部分,创建自动编号的章节和标题,和操纵的风格清单的内容。
content: “Item” counter(section) ” “;
This resets the counter.
First section
>two section
three section
counter-increment: section 1;
counter-reset: section;
⑤“分页媒体”描述性能与外观的属性,控制印刷版本的网页,如分页符的行为。
page-break-after: auto; 常量:always/auto/avoid/left/right
page-break-before: auto; 常量:always/auto/avoid/left/right
page-break-inside: auto; 常量:auto/avoid
⑥“颜色和背景”描述属性控制背景下的块级元素和颜色的文本内容的组成部分。
-webkit-background-clip: content; 常量:border/content/padding/text
-webkit-background-origin: padding; 常量:border/content/padding/text
-webkit-background-size: 55px; 常量:length/length_x/length_y
⑦ “字型”的具体描述性质的文字字体的选择范围内的一个因素。报告还描述属性用于下载字体定义。
unicode-range: U+00-FF, U+980-9FF;
⑧“文本”描述属性的特定文字样式,间距和自动滚屏。
text-shadow: #00FFFC 10px 10px 5px;
text-transform: capitalize; 常量:capitalize/lowercase/none/uppercase
word-wrap: break-word; 常量:break-word/normal
-webkit-marquee: right large infinite normal 10s; 常量:direction(方向) increment(迭代次数) repetition(重复) style(样式) speed(速度);
-webkit-marquee-direction: ahead/auto/backwards/down/forwards/left/reverse/right/up
-webkit-marquee-incrementt: 1-n/infinite(无穷次)
-webkit-marquee-speed: fast/normal/slow
-webkit-marquee-style: alternate/none/scroll/slide
-webkit-text-fill-color: #ff6600; 常量:capitalize, lowercase, none, uppercase
-webkit-text-security: circle; 常量:circle/disc/none/square
-webkit-text-size-adjust: none; 常量:auto/none;
-webkit-text-stroke: 15px #fff;
-webkit-line-break: after-white-space; 常量:normal/after-white-space
-webkit-appearance: caps-lock-indicator;
-webkit-nbsp-mode: space; 常量: normal/space
-webkit-rtl-ordering: logical; 常量:visual/logical
-webkit-user-drag: element; 常量:element/auto/none
-webkit-user-modify: read- only; 常量:read-write-plaintext-only/read-write/read-only
-webkit-user-select: text; 常量:text/auto/none
⑨“表格”描述的布局和设计性能表的具体内容。
-webkit-border-horizontal-spacing: 2px;
-webkit-border-vertical-spacing: 2px;
-webkit-column-break-after: right; 常量:always/auto/avoid/left/right
-webkit-column-break-before: right; 常量:always/auto/avoid/left/right
–webkit-column-break-inside: logical; 常量:avoid/auto
-webkit-column-count: 3; //分栏
-webkit-column-rule: 1px solid #fff;
style:dashed,dotted,double,groove,hidden,inset,none,outset,ridge,solid
⑩“用户界面”描述属性,涉及到用户界面元素在浏览器中,如滚动文字区,滚动条,等等。报告还描述属性,范围以外的网页内容,如光标的标注样式和显示当您按住触摸触摸
目标,如在iPhone上的链接。
-webkit-box-align: baseline,center,end,start,stretch 常量:baseline/center/end/start/stretch
-webkit-box-direction: normal;常量:normal/reverse
-webkit-box-flex: flex_valuet
-webkit-box-flex-group: group_number
-webkit-box-lines: multiple; 常量:multiple/single
-webkit-box-ordinal-group: group_number
-webkit-box-orient: block-axis; 常量:block-axis/horizontal/inline-axis/vertical/orientation
–webkit-box-pack: alignment; 常量:center/end/justify/start

12. 动画过渡
这是 Webkit 中最具创新力的特性:使用过渡函数定义动画。
-webkit-animation: title infinite ease-in-out 3s;
animation 有这几个属性:
-webkit-animation-name: //属性名,就是我们定义的keyframes
-webkit-animation-duration:3s //持续时间
-webkit-animation-timing-function: //过渡类型:ease/ linear(线性) /ease-in(慢到快)/ease-out(快到慢) /ease-in-out(慢到快再到慢) /cubic-bezier
-webkit-animation-delay:10ms //动画延迟(默认0)
-webkit-animation-iteration-count: //循环次数(默认1),infinite 为无限
-webkit-animation-direction: //动画方式:normal(默认 正向播放); alternate(交替方向,第偶数次正向播放,第奇数次反向播放)
这些同样是可以简写的。但真正让我觉的很爽的是keyframes,它能定义一个动画的转变过程供调用,过程为0%到100%或from(0%)到to(100%)。简单点说,只要你有想法,你想让元素在这个过程中以什么样的方式改变都是很简单的。
-webkit-transform: 类型(缩放scale/旋转rotate/倾斜skew/位移translate)
scale(num,num) 放大倍率。scaleX 和 scaleY(3),可以简写为:scale(* , *)
rotate(*deg) 转动角度。rotateX 和 rotateY,可以简写为:rotate(* , *)
Skew(*deg) 倾斜角度。skewX 和skewY,可简写为:skew(* , *)
translate(*,*) 坐标移动。translateX 和translateY,可简写为:translate(* , *)。
实现模拟弹出消息框(Alert)的例子:
①定义过渡(在<style type="text/css">段中描述keyframes):
@-webkit-keyframes DivZoom
{
0% { -webkit-transform: scale(0.01) }
60% { -webkit-transform: scale(1.05) }
80% { -webkit-transform: scale(0.95) }
100% { -webkit-transform: scale(1.00) }
}
.sZoom { -webkit-animation: DivZoom 0.5s ease-in-out }
(很容易看懂,将元素从缩小的0.01 倍--很小但不能为0 倍,放大到1.05 倍,再缩小到0.95倍,最后到1 倍即正常大小。整个过渡过程事件为0.5 秒,动画方式为ease-in-out,即慢到快再到慢,默认只进行1 次过渡。这正是大家经常看到的 iPhone 弹出的提示信息的动画效果!)
②定义元素(在<body>段中):
<div id="layerH" style="-webkit-border-radius:12px; border:2px solid #FFF;-webkit-box-shadow: 0px 2px 4px #888;position: absolute; left: 24px; top: 106px;
width: 256px; height: 268px; padding-left: 8px; padding-right: 8px;color: #FFFFFF; text-shadow: 1px 1px 1px #000; text-align: center;background-color: RGBA(32,48,96,0.9); background-image:url('BG-Msg.png'); background-repeat:no-repeat; z-index: 1; visibility: hidden; "> <p><span style="font-size: 16pt; font-weight: bold">使用说明</span></p> <hr noshade size="1"> <div id="HelpText" style="height: 120px">说明文字</div> <hr noshade size="1"> <form name="formV" method="POST"> <input type="button" value="确认" name="B1" style="width: 100%; height: 40px; font-size: 14pt; ont-weight: bold; color: #FFFFFF; text-shadow: 0px -1px 1px #000;" onclick=" layerH.style.visibility='hidden'"> </form> </div>
③启动动画(在 javascript 定义的函数中)
function pHelp()
{
layerH.style.visibility = 'visible'
layerH.style.cssText = "-webkit-animation-delay: " + Math.random() + "ms"
layerH.className = 'sZoom'
}
(这个启动函数就很好理解了。但是为什么要使用-webkit-animation-delay 这句呢?因为当一个元素过渡显示完成后,若其样式没有变化,下一次将无法进行过渡动画显示。我们巧妙的利用其动画延迟时间定义,使其有所变化,就避免了上述问题。其中使用随机数函数Math.random(),产生一个大于0 小于1 的随机数。当然,延迟零点几毫秒,用户是不会察觉的。)

补充:
1. 锁定 viewport
ontouchmove="event.preventDefault()" //锁定viewport,任何屏幕操作不移动用户界面(弹出键盘除外)。
2. 被点击元素的外观变化,可以使用样式来设定:
-webkit-tap-highlight-color: 颜色

3. 侦测iPhone/iPod
开发特定设备的移动网站,首先要做的就是设备侦测了。下面是使用Javascript侦测iPhone/iPod的UA,然后转向到专属的URL。

if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) {
  if (document.cookie.indexOf("iphone_redirect=false") == -1) {
    window.location = "http://m.example.com";
  }
}
虽然Javascript是可以在水果设备上运行的,但是用户还是可以禁用。它也会造成客户端刷新和额外的数据传输,所以下面是服务器端侦测和转向:
if(strstr($_SERVER['HTTP_USER_AGENT'],'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'],'iPod')) {
  header('Location: http://yoursite.com/iphone');
  exit();
}
4. 阻止旋转屏幕时自动调整字体大小
html, body, form, fieldset, p, div, h1, h2, h3, h4, h5, h6 {-webkit-text-size-adjust:none;}
5. iPhone才识别的CSS
如果不想设备侦测,可以用CSS媒体查询来专为iPhone/iPod定义样式。
@media screen and (max-device-width: 480px) {}
6. 缩小图片
网站的大图通常宽度都超过480像素,如果用前面的代码限制了缩放,这些图片在iPhone版显示显然会超过屏幕。好在iPhone机能还够,我们可以用CSS让iPhone自动将大图片缩小显示。
@media screen and (max-device-width: 480px){
  img{max-width:100%;height:auto;}
}
7. 模拟:hover伪类
因为iPhone并没有鼠标指针,所以没有hover事件。那么CSS :hover伪类就没用了。但是iPhone有Touch事件,onTouchStart 类似 onMouseOver,onTouchEnd 类似 onMouseOut。所以我们可以用它来模拟hover。使用Javascript:
var myLinks = document.getElementsByTagName('a');
for(var i = 0; i < myLinks.length; i++){
  myLinks[i].addEventListener(’touchstart’, function(){this.className = “hover”;}, false);
  myLinks[i].addEventListener(’touchend’, function(){this.className = “”;}, false);
}
然后用CSS增加hover效果:
a:hover, a.hover { /* 你的hover效果 */ }
这样设计一个链接,感觉可以更像按钮。并且,这个模拟可以用在任何元素上。


posted @ 2011-05-28 13:47 pifoo 阅读(10211) 评论(8) 编辑

2011年5月23日

水果公司的那些small and cute的设备给我们提供了前所未有的用户体验。当用户在iphone和ipad上运指如飞
的时候,那些使用objective-c写出优秀应用的开发人员们心里一定充满了成就感,因为正是他们(而不是水果
)让iOS的世界变的丰富多彩。然而对于我们这些以web为自己事业核心的程序员来说,这种让人欲罢不能的多
触式体验似乎跟我们关系不大,因为浏览器那一小块地方就是我们和用户的全部交集了。而许多网站为了让iOS
的用户能够在多触式体验下使用自己的服务,都专门花钱开发objective-c的本地程序作为自己web service的客
户端。 
    其实,对于一个web程序员或者一个网站来说,如果你的需求仅仅是让iPhone/iPad用户能够正常使用你的
服务,那现有的html4页面完全能够满足(也许需要一点点重构,但是很容易);如果再往上一点,你需要让你
的web客户端看起来像是用objective-c实现的一样,也并非不可能,只需要将我们熟悉的javascript搬到iOS设
备上来就行。 
    本文从一个多触式网页开发初学者的角度,首先简单介绍一下iOS上的浏览器(这里主要指Safari)所支持的
多触式事件模型,然后将触控(Touch)这种简单的动作升级为手势(Gestrue),最后将javascript + html + 
css构建的应用脱离浏览器,放到iOS设备的屏幕上成为一个本地link并和植物大战僵尸放到一起。 
    iOS上的Safari也支持click 和mouseover等传统的交互事件,只是不推荐在iOS的浏览器应用上使用click和
mouseover,因为这两个事件是为了支持鼠标点击而设计出来的。Click事件在iOS上会有半秒左右的延迟,原
因是iOS要highlight接收到click的element。而mouseover/out等事件则会被手指的点击触发。所以,在iOS上
,应当抛弃传统的交互事件模型而接受一个新的事件模型。Touch事件和更高级的Gesture事件,能让你的网页
交互起来像native应用一样。 
    处理Touch事件能让你跟踪用户的每一根手指的位置。你可以绑定以下四种Touch事件:

touchstart:  // 手指放到屏幕上的时候触发 
touchmove:  // 手指在屏幕上移动的时候触发 
touchend:  // 手指从屏幕上拿起的时候触发 
touchcancel:  // 系统取消touch事件的时候触发。至于系统什么时候会取消,不详。。

Gesture事件则是对touch事件的更高级的封装,主要处理手指slide、rotate、scale等动作,将在下一篇文章
详述。 
    在开始描述touch事件之前,需要先描述一下多触式系统中特有的touch对象(android和iOS乃至nokia最新
的meego系统都模拟了类似的对象,这里只针对iOS,因为我只有iPad可用于测试。。)。这个对象封装一次
屏幕触摸,一般来自于手指。它在touch事件触发的时候产生,可以通过touch event handler的event对象取到
(一般是通过event.changedTouches属性)。这个对象包括一些重要的属性: 

client / clientY:// 触摸点相对于浏览器窗口viewport的位置 
pageX / pageY:// 触摸点相对于页面的位置 
screenX /screenY:// 触摸点相对于屏幕的位置 
identifier: // touch对象的unique ID 

CSS代码

.spirit {              /* 方块的class名称*/
         position: absolute;
         width: 50px;
         height: 50px;
         background-color: red;
}

然后,在body下定义一个接收事件的容器,这里body的height必须是100%才能占满整个viewport: 

Html

<body style=”height: 100%;margin:0;padding:0”>

<div id=”canvas”  style=”position: relative;width:100%;height: 100%;”></div>

</body>

定义touchstart的事件处理函数,并绑定事件:

Javascript代码

// define global variable

var canvas = document.getElementById(“canvas”),
       spirit, startX, startY;
    // touch start listener

function touchStart(event) {
         event.preventDefault();
         if (spirit ||! event.touches.length) return;
         var touch = event.touches[0];
         startX = touch.pageX;
         startY = touch.pageY;
         spirit = document.createElement(“div”);
         spirit.className = “spirit”;
         spirit.style.left = startX;
         spirit.style.top = startY;
         canvas.appendChild(spirit);
}

// add touch start listener
canvas.addEventListener(“touchstart”, touchStart, false);

首先,我们将方块spirit作为一个全局对象,因为我们现在要测试单根手指所以屏幕上最好只有一个物体在移动

(等会有多触实例)。在touchStart这个事件处理函数中,我们也首先判断了是否已经产生了spirit,也就是是
否已经有一个手指放到屏幕上,如果是,直接返回。 
    和传统的event listener一样,多触式系统也会产生一个event对象,只不过这个对象要多出一些属性,比如
这里的event.touches,这个数组对象获得屏幕上所有的touch。注意这里的event.preventDefault(),在传统的
事件处理函数中,这个方法阻止事件的默认动作,触摸事件的默认动作是滚屏,我们不想屏幕动来动去的,所
以先调用一下这个函数。我们取第一个touch,将其pageX/Y作为spirit创建时的初始位置。接下来,我们创建
一个div,并且设置className,left,top三个属性。最后,我们把spirit对象appendChild到容器中。这样,
当第一根手指放下的时候,一个红色的,50px见方的方块就放到屏幕上了。 
    然后,我们要开始处理手指在屏幕上移动的事件: 

Javascript代码

function touchMove(event) {
         event.preventDefault();
         if (!spirit || !event.touches.length) return;
         var touch = event.touches[0],
              x = touch.pageX – startX,
              y = touch.pageY – startY;
         spirit.style.webkitTransform = 'translate(' + x + 'px, ' + y + 'px)';     
}

Canvas.addEventListener(“touchmove”, touchMove, false);

在touch move listener中,我们使用webkit特有的css属性:webkitTransform来移动方块,这个属性具体怎么用请google之。建议构造面向iOS设备的网页的时候尽量使用webkit自己的特性,不但炫,更可以直接利用硬件来提高性能。 

    最后,我们处理touchend事件。手指提起的时候方块从屏幕上移除。

function touchEnd(event) {
         If (!spirit) return;
         canvas.removeChild(spirit);
         spirit = null;
}

canvas.addEventListener(“touchend”, touchEnd, false);

在你的ipad或者iphone上测试一下以上代码。如果不出意外的话,一个完整的多触式web程序就诞生了。。 
这种事件处理模式虽然能够满足我们开发多触式网页应用的需求,但是start – move – end的流程有点繁琐,
能不能封装一些常用的动作让我们用一个event handler就能解决问题呢。没错,Gesture事件就是为了这个目
的设计出来的,它封装了手指的scale, slide, rotate等常用的动作。不过,下一章我们再来讨论这个问题。。 
附件是一个更加复杂一些的例子,每根手指放下的时候都会产生一个不同颜色的方块,手指动的时候方块跟着
动,手指提起的时候方块消失,请下载查看试用。 
通过附件所包含的实例,我们可以看出一些较为隐蔽的特性。首先,这里我们没有再使用event.touches取所有
touch的对象,而是使用event.changedTouches这个数组,用来取得所有跟本次事件相关的touch。但是,这
里我发现一个奇怪的特性,不知道是我的ipad有问题还是本来就是这样,就是在有多根手指放在屏幕上的时候
,如果提起一根手指,touchend事件的changedTouches中会包含所有手指的touch对象,然后,其他几根留
在屏幕上的手指会重新触发touchstart,并刷新所有的touch对象(identifier都不一样了)。如果这是一个所有
设备都有的特性,那么将给编程者带来一些不便,不知道水果为啥要这么处理。 
对touch event的介绍我们点到为止,这里给大家推荐两篇文档: 
1. Safari dom additions reference 
2. Safari web content guide
对于有志于开发多触式网页应用的程序员来说,apple的developer站点是一个应该经常光顾的地方。

附件:ios-multi.rar

posted @ 2011-05-23 00:06 pifoo 阅读(8812) 评论(7) 编辑

2011年5月22日

这篇文章将描述多触式网页开发中对手势(Gesture)事件的处理。 
    水果设备中的Gesture,广义的说包括手指点击(click),轻拂(flick),双击(double-click),两只手指的分开、闭合(scale)、转动(rotate)等一切手指能在屏幕上做的事情。iOS上设计了了一系列手势来模拟和扩展鼠标操作,比如手指放下后迅速提起会触发click事件,手指向上滑动,停止,会触发body的onscroll事件等等。但是,狭义的Gesture事件,也就是能够addEventListener的GestureEvent对象,却并不是一个非常强大的存在,它只在有两根或多根手指放在屏幕上的时候触发,并且只包含手指分开比例(scale)和手指转动角度(rotation)信息。对于其他各种常用的手势,我们必须利用别的事件来处理。 
    下面从单根手指的事件开始说起。。。 
    我们先来考虑一个最简单的手势,手指放下后迅速提起,这个手势做出来后会发生什么?大家当然会想到click,其实在click发生以前,还有很多事情发生,请看下图: 

这里先解释一下什么是clickable element,就是一个绑定了click, mousedown, mouseup, mousemove事件
的任何html element(注意,没有绑定事件处理的element不算clickable element)。从这张图可以看出,手
指提起的一刹那,首先触发的并不是click事件,而是mouseover和mousemove。然后,系统会判断接收到事
件的element的内容是否被改变,如果内容被改变,接下来的事件都不会触发,如果没有改变,会按照
mousedown,mouseup,click的顺序触发事件。什么?你问mouseout在哪?这个事件的处理,比较尴尬,
上面说的一系列事件都完了以后,如果你再点击一个clickable element,就会触发上一个clickable element的
mouseout事件了。。。比较纠结,建议不要在多触版网页上使用mouseout。 
    那么,如果手指放下后不提起又会发生什么呢?什么都不会发生,没有任何事件会被触发。但是,如果对象
是一个img并且有alt属性的话,这个动作将会显示img的alt字符串。如果是一个link的话,这个动作会显示“在
新窗口打开连接”选项,但是,不会有任何用户定义事件触发。 
    最后一种关于单根手指的事件,是放下后滑动手指。注意,在滑动的过程当中,不会触发除touchmove以外
的任何事件(请不要试图在这时处理mousemove)。手指在滑动的时候,整个page应该会跟着移动,除非你
preventDefault了body的touchmove。当手指停下来后,page的onscroll将会触发。除此之外,没有什么我
们熟悉的事情会发生。

posted @ 2011-05-22 23:46 pifoo 阅读(1940) 评论(0) 编辑
    这篇文章着重介绍多触式设备上特有的gesture event(android和iOS对这个事件的封装大同小异)。这个
事件是对touch event的更高层的封装,和touch一样,它同样包括gesturestart,gesturechange,
gestureend三个事件回调: 
gesturestart    // 当有两根或多根手指放到屏幕上的时候触发 
gesturechange    // 当有两根或多根手指在屏幕上,并且有手指移动的时候触发 
gestureend    // 当倒数第二根手指提起的时候触发,结束gesture 

    事件处理函数中会得到一个GestureEvent类型的参数,它包含了手指的scale(两根移动过程中分开的比例
)信息和rotation(两根手指间连线转动的角度)信息。 
    当两根或以上的手指在屏幕上活动的时候,我们可以做出一些较为复杂的手势。这将涉及到普通的mouse事
件,touch事件和gesture事件,情况比较复杂。touch已经在第一篇文章里详细介绍,这里就简单带过。 
    我们还是先看看当分别将两根手指放到屏幕上的时候,会触发哪些事件吧: 
1、第一根手指放下,触发touchstart,除此之外什么都不会发生(请参照第二篇文章,手指提起才会触发
mouse的各事件) 
2、第二根手指放下,触发gesturestart 
3、触发第二根手指的touchstart 
4、立即触发gesturechange 
5、手指移动,持续触发gesturechange,就像鼠标在屏幕上移动的时候不停触发mousemove一样 
6、第二根手指提起,触发gestureend,以后将不会再触发gesturechange 
7、触发第二根手指的touchend 
8、触发touchstart!注意,和第一篇文章里介绍的一样,多根手指在屏幕上,提起一根,会刷新一次全局
touch!重新触发第一根手指的touchstart,这点和苹果官方网站上介绍的不同。 
9、提起第一根手指,触发touchend 
    Gesture事件的处理和Touch类似,我们一般会在gesturechange的时候利用GestureEvent对象中的信息来
做一些事情: 
var angle = event.rotation; 
var scale = event.scale; 

    这样能够取得scale和rotation信息,然后我们可以: 
e.target.style.webkitTransform = 'scale(' + e.scale + startScale + ') rotate(' + e.rotation + 
startRotation + 'deg)'; 


    这段代码能让element随着你的两根手指的运动而转动、伸展。以下是一段测试代码,请用
ipad/iphone/android打开: http://wanglingshu.com/wp-content/uploads/ios-gesture.html 
    还有一件要说明的事情是,对于复杂手势,是否会触发某些鼠标事件?确实有,不过我只找到了一个。不管
你的两根手指在屏幕上伸缩还是转动,都不会有任何鼠标事件触发,但当你的两根手指同时朝上或者朝下移动
的时候,则会触发某些事件。请看下图:

两根手指同时向上或向下滚动,如果target element是一个scrollable element(也就是绑定了mousewheel的
element)的话,将会触发mousewheel事件。如果不是scrollable element,则当手指停止移动的时候,会触
发onscoll。这里请和第二篇文章的body scroll区别一下,如果你要滚动body,只需要一根手指轻轻拂动屏幕
,但是你要滚动一个内部div或者iframe,则需要动用两根手指。     这也是多触式设备一个不太方便的地方。而对于我们开发者来说,这种不方便被放大了。。。因为从用户体
验角度来说,要求用户使用两根手指滚动一个内部element显然是不合适的,而要实现像滚动body一样用一根
手指优雅地滚动,我们必须利用touchevent,在它的回调函数中用代码来实现scroll。这里介绍一个段很不错的
多触式滚动组件:iscroll-4 
http://cubiq.org/scrolling-div-on-iphone-ipod-touch 
    用起来很简单,new一个iScroll对象,传入需要滚动的inner element作为参数就行了。 

posted @ 2011-05-22 23:39 pifoo 阅读(2123) 评论(0) 编辑

简单实现带缩略图的jQuery幻灯片效果(可自动播放)

有图有真相

代码如下:

JS

var n,interval=null;					//	n:指定 或 标记当前播放的图片
function time(index) {	
	n = index;
	interval = setInterval("play()", 2000); 
}

function play(){		
	var count = $(".v_con > span").length;
	n ++ ;
	if(n > count){
		n = 0;
	}
	$(".v_con > span img").removeClass("cur");
	$(".v_con > span img").eq(n).addClass("cur");
	
	var src = $(".v_con > span img").eq(n).attr("src");
	$(".max_img > img").attr("src",src).fadeIn(1500);
}

$(function(){
	time(0);	//	调用time(),默认从第一个图片开始自动播放
	$(".v_con > span").hover(function(){
		n=$(".v_con > span").index($(this))-1;	//	得到当前图片的索引
		play();		//	展示当前图片
		if(interval){
			clearInterval(interval); 
		} 
	},function(){
		time(n);	//	从当前图片 继续 播放
	});
});

Html

<div class="container" style="margin:0 auto; margin-left:auto;margin-right:auto;">
			<div class="slide">
				<ul>
					<!--显示大图-->
					<li class="max_img">
						<img width="480" height="275" src="http://www.cnblogs.com/http://www.cnblogs.com/Public/images/data/01.jpg" />
					</li>
				</ul>
				<div class="thumbnail">
					<!--缩略图-->
					<!--span class="prev" >上一页</span-->
					<div class="v_show">
						<div class="v_con">
							<span >
								<img class="cur" width="95" height="70" src="http://www.cnblogs.com/http://www.cnblogs.com/Public/images/data/01.jpg" />
							</span>
							<span>
								<img width="95" height="70" src="http://www.cnblogs.com/http://www.cnblogs.com/Public/images/data/02.jpg" />
							</span>
							<span>
								<img width="95" height="70" src="http://www.cnblogs.com/http://www.cnblogs.com/Public/images/data/05.jpg" />
							</span>
							<span>
								<img width="95" height="70" src="http://www.cnblogs.com/http://www.cnblogs.com/Public/images/data/02.jpg" />
							</span>
						</div>
					</div>
					<!--span class="next">下一页</span-->
				</div><!--thumbnail end-->
			</div>
		</div>

CSS

/* style */
.container {width:552px;height:304px; margin:0 auto; }

.slide { width:550px;height:auto;border:1px dotted #CCC; padding:10px; text-align:left;background:url("../images/slide/bg.jpg") repeat-x;}
.slide ul li{border:1px solid #CCC;padding:10px;background:#FFF;text-align:center;}
.slide ul li img{border:1px solid #EEE;}

.thumbnail{height:110px;margin-top:10px;}
/*
.prev,.next {text-indent:-9999px; cursor:pointer;display:block;width:24px;height:110px;float:left; }
.prev{background:url("../images/slide/bg_l_1.gif") no-repeat;}
.next{background:url("../images/slide/bg_r_1.gif") no-repeat;}
*/
.v_show{height:110px;width:480px;float:left;background:url("../images/slide/bg_c.gif") repeat-x 0 -1px;overflow:hidden; position:relative;padding-left:15px; }
.v_show .v_con{width:2500px;text-align:left;position:absolute;left:7px; bottom:10px;}
.v_show span{display:inline-block;width:120px;height:76px;margin-top:16px 0 0; cursor:pointer; text-align:center; background:#EEE;text-align:center; }
.v_show span img{padding:3px; border:1px solid #CCC;background:#FFF; }
.v_show span img:hover,.v_show span img.cur{border:border:1px solid #FFF;background:#e80000;}
posted @ 2011-05-22 10:15 pifoo 阅读(2208) 评论(0) 编辑

2011年5月21日

摘要: JSON 是一种比较方便的数据形式 具体的大家可以参考http://baike.baidu.com/view/136475.htm还挺详细的。今天用JQuery 写了一个JSON的东西,用了 $.getJSON方法,获得JSON数据和解析 都挺方便简单的。从http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=? 这个地址得到JSON数据 并且分析里面的结构,生成图片和相关链接等:JS:$(function(){ var u阅读全文
posted @ 2011-05-21 18:10 pifoo 阅读(2808) 评论(0) 编辑
摘要: 使用PHP+MYSQL时遇到过字符乱问题,解决方法:在mysql_connect后面加一句SET NAMES UTF8,即可使得UTF8的数据库消除乱码,对于GBK的数据库则使用SET NAMES GBK,代码如下:1 $mysql_mylink = mysql_connect($mysql_host, $mysql_user, $mysql_pass); 2 mysql_query("SET NAMES 'GBK'"); 数据库字符集为utf-8连接语句用这个1 mysql_query("SET NAMES 'UTF8'"阅读全文
posted @ 2011-05-21 17:49 pifoo 阅读(251) 评论(0) 编辑

公告

导航