<!--if(window.Event){// 修正Event的DOM /* IE5 MacIE5 Mozilla Konqueror2.2 Opera5 event yes yes yes yes yes event.returnValue yes yes no no no event.cancelBubble yes yes no no no event.srcElement yes yes no no no event.fromElement yes yes no no no */ Event.prototype.__defineSetter__("returnValue",function(b){// if(!b)this.preventDefault(); return b; }); Event.prototype.__defineSetter__("cancelBubble",function(b){// 设置或者检索当前事件句柄的层次冒泡 if(b)this.stopPropagation(); return b; }); Event.prototype.__defineGetter__("srcElement",function(){ var node=this.target; while(node.nodeType!=1)node=node.parentNode; return node; }); Event.prototype.__defineGetter__("fromElement",function(){// 返回鼠标移出的源节点 var node; if(this.type=="mouseover") node=this.relatedTarget; else if(this.type=="mouseout") node=this.target; if(!node)return; while(node.nodeType!=1)node=node.parentNode; return node; }); Event.prototype.__defineGetter__("toElement",function(){// 返回鼠标移入的源节点 var node; if(this.type=="mouseout") node=this.relatedTarget; else if(this.type=="mouseover") node=this.target; if(!node)return; while(node.nodeType!=1)node=node.parentNode; return node; }); Event.prototype.__defineGetter__("offsetX",function(){ return this.layerX; }); Event.prototype.__defineGetter__("offsetY",function(){ return this.layerY; }); }if(window.Document){// 修正Document的DOM /* IE5 MacIE5 Mozilla Konqueror2.2 Opera5 document.documentElement yes yes yes yes no document.activeElement yes null no no no */ }if(window.Node){// 修正Node的DOM /* IE5 MacIE5 Mozilla Konqueror2.2 Opera5 Node.contains yes yes no no yes Node.replaceNode yes no no no no Node.removeNode yes no no no no Node.children yes yes no no no Node.hasChildNodes yes yes yes yes no Node.childNodes yes yes yes yes no Node.swapNode yes no no no no Node.currentStyle yes yes no no no */ Node.prototype.replaceNode=function(Node){// 替换指定节点 this.parentNode.replaceChild(Node,this); } Node.prototype.removeNode=function(removeChildren){// 删除指定节点 if(removeChildren) return this.parentNode.removeChild(this); else{ var range=document.createRange(); range.selectNodeContents(this); return this.parentNode.replaceChild(range.extractContents(),this); } } Node.prototype.swapNode=function(Node){// 交换节点 var nextSibling=this.nextSibling; var parentNode=this.parentNode; node.parentNode.replaceChild(this,Node); parentNode.insertBefore(node,nextSibling); } }if(window.HTMLElement){ HTMLElement.prototype.__defineGetter__("all",function(){ var a=this.getElementsByTagName("*"); var node=this; a.tags=function(sTagName){ return node.getElementsByTagName(sTagName); } return a; }); HTMLElement.prototype.__defineGetter__("parentElement",function(){ if(this.parentNode==this.ownerDocument)return null; return this.parentNode; }); HTMLElement.prototype.__defineGetter__("children",function(){ var tmp=[]; var j=0; var n; for(var i=0;i<this.childNodes.length;i++){ n=this.childNodes[i]; if(n.nodeType==1){ tmp[j++]=n; if(n.name){ if(!tmp[n.name]) tmp[n.name]=[]; tmp[n.name][tmp[n.name].length]=n; } if(n.id) tmp[n.id]=n; } } return tmp; }); HTMLElement.prototype.__defineGetter__("currentStyle", function(){ return this.ownerDocument.defaultView.getComputedStyle(this,null); }); HTMLElement.prototype.__defineSetter__("outerHTML",function(sHTML){ var r=this.ownerDocument.createRange(); r.setStartBefore(this); var df=r.createContextualFragment(sHTML); this.parentNode.replaceChild(df,this); return sHTML; }); HTMLElement.prototype.__defineGetter__("outerHTML",function(){ var attr; var attrs=this.attributes; var str="<"+this.tagName; for(var i=0;i<attrs.length;i++){ attr=attrs[i]; if(attr.specified) str+=" "+attr.name+'="'+attr.value+'"'; } if(!this.canHaveChildren) return str+">"; return str+">"+this.innerHTML+"</"+this.tagName+">"; }); HTMLElement.prototype.__defineGetter__("canHaveChildren",function(){ switch(this.tagName.toLowerCase()){ case "area": case "base": case "basefont": case "col": case "frame": case "hr": case "img": case "br": case "input": case "isindex": case "link": case "meta": case "param": return false; } return true; }); HTMLElement.prototype.__defineSetter__("innerText",function(sText){ var parsedText=document.createTextNode(sText); this.innerHTML=parsedText; return parsedText; }); HTMLElement.prototype.__defineGetter__("innerText",function(){ var r=this.ownerDocument.createRange(); r.selectNodeContents(this); return r.toString(); }); HTMLElement.prototype.__defineSetter__("outerText",function(sText){ var parsedText=document.createTextNode(sText); this.outerHTML=parsedText; return parsedText; }); HTMLElement.prototype.__defineGetter__("outerText",function(){ var r=this.ownerDocument.createRange(); r.selectNodeContents(this); return r.toString(); }); HTMLElement.prototype.attachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); fHandler._ieEmuEventHandler=function(e){ window.event=e; return fHandler(); } this.addEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); } HTMLElement.prototype.detachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); if(typeof(fHandler._ieEmuEventHandler)=="function") this.removeEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); else this.removeEventListener(shortTypeName,fHandler,true); } HTMLElement.prototype.contains=function(Node){// 是否包含某节点 do if(Node==this)return true; while(Node=Node.parentNode); return false; } HTMLElement.prototype.insertAdjacentElement=function(where,parsedNode){ switch(where){ case "beforeBegin": this.parentNode.insertBefore(parsedNode,this); break; case "afterBegin": this.insertBefore(parsedNode,this.firstChild); break; case "beforeEnd": this.appendChild(parsedNode); break; case "afterEnd": if(this.nextSibling) this.parentNode.insertBefore(parsedNode,this.nextSibling); else this.parentNode.appendChild(parsedNode); break; } } HTMLElement.prototype.insertAdjacentHTML=function(where,htmlStr){ var r=this.ownerDocument.createRange(); r.setStartBefore(this); var parsedHTML=r.createContextualFragment(htmlStr); this.insertAdjacentElement(where,parsedHTML); } HTMLElement.prototype.insertAdjacentText=function(where,txtStr){ var parsedText=document.createTextNode(txtStr); this.insertAdjacentElement(where,parsedText); } HTMLElement.prototype.attachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); fHandler._ieEmuEventHandler=function(e){ window.event=e; return fHandler(); } this.addEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); } HTMLElement.prototype.detachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); if(typeof(fHandler._ieEmuEventHandler)=="function") this.removeEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); else this.removeEventListener(shortTypeName,fHandler,true); } }//--></script>?>
View Details在FireFox下编写事件处理函数是很麻烦的事. 因为FireFox并没有 window.event . 如果要得到 event 对象,就必须要声明时间处理函数的第一个参数为event. 所以为了兼容IE与FireFox,一般的事件处理方法为:btn.onclick=handle_btn_click;function handle_btn_click(evt){ if(evt==null)evt=window.event;//IE //处理事件.}对于简单的程序,这不算麻烦. 但对于一些复杂的程序,某写函数根本就不是直接与事件挂钩的.如果要把event传进该参数,那么所有的方法都要把event传来传去..这简直就是噩梦. 下面介绍一个解决这个麻烦事的方法,与原理. JScript中,函数的调用是有一个 func.caller 这个属性的.例如 function A(){ B();}function B(){ alert(B.caller);}如果B被A调用,那么B.caller就是A 另外,函数有一个arguments属性. 这个属性可以遍历函数当前执行的参数:function myalert(){ var arr=[]; for(var i=0;i arr[i]=myalert.arguments[i]; alert(arr.join("-"));}alert("hello","world",1,2,3)就能显示 hello-world-1-2-3(arguments的个数与调用方有关,而与函数的参数定义没有任何关系) 根据这两个属性,我们可以得到第一个函数的event对象:btn.onclick=handle_click;function handle_click(){ showcontent();}function showcontent(){ var evt=SearchEvent(); if(evt&&evt.shiftKey)//如果是基于事件的调用,并且shift被按下 window.open(global_helpurl); else location.href=global_helpurl;}function SearchEvent(){ func=SearchEvent.caller; while(func!=null) { var arg0=func.arguments[0]; if(arg0) { if(arg0.constructor==Event) // 如果就是event 对象 return arg0; } func=func.caller; } return null;}这个例子使用了SearchEvent来搜索event对象. 其中 'Event' 是 FireFox 的 event.constructor .在该例子运行时,SearchEvent.caller就是showcontent,但是showcontent.arguments[0]是空.所以 func=func.caller 时,func变为handle_click .handle_click 被 FireFox 调用, 虽然没有定义参数,但是被调用时,第一个参数就是event,所以handle_click.arguments[0]就是event ! 针对上面的知识,我们可以结合 prototype.__defineGetter__ 来实现 window.event 在 FireFox 下的实现: 下面给出一个简单的代码.. 有兴趣的可以补充 if(window.addEventListener){ FixPrototypeForGecko();}function FixPrototypeForGecko(){ HTMLElement.prototype.__defineGetter__("runtimeStyle",element_prototype_get_runtimeStyle); window.constructor.prototype.__defineGetter__("event",window_prototype_get_event); Event.prototype.__defineGetter__("srcElement",event_prototype_get_srcElement);}function element_prototype_get_runtimeStyle(){ //return style instead… return […]
View Details简介 如果你经常网上冲浪,这样参差不齐的多栏布局,是不是很眼熟啊? 类似的布局,似乎一夜之间出现在国内外大大小小的网站上,比如 Pinterest (貌似是最早使用这种布局的网站了),Mark之,蘑菇街,点点网,以及淘宝最新上线的“哇哦” 等等,倒是很流行哈~ 在淘宝即将上线的众多产品中,你还会大量看到这样的形式呢。 这种布局适合于小数据块,每个数据块内容相近且没有侧重。通常,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。所以,我们给这样的布局起了一个形象的名字 — 瀑布流式布局。 几种实现方式 随着越来越多设计师爱用这种布局,我们作为前端,要尽可能满足视觉/交互设计师的需求。所以,我们整理了下这种布局的几种实现方式,有三种: 1) 传统多列浮动。即 蘑菇街和哇哦 采用的方式,如下图所示: 各列固定宽度,并且左浮动; 一列中的数据块为一组,列中的每个数据块依次排列即可; 更多数据加载时,需要分别插入到不同的列上; 线上例子。 优点: 布局简单,应该说没啥特别的难点; 不用明确知道数据块高度,当数据块中有图片时,就不需要指定图片高度。 缺点: 列数固定,扩展不易,当浏览器窗口大小变化时,只能固定的x列,如果要添加一列,很难调整数据块的排列; 滚动加载更多数据时,还要指定插入到第几列中,还是不方便。 2) CSS3 定义。W3C 中有讲述关于多列布局的文档,排列出来的样子: 由 chrome/ff 浏览器直接渲染出来,可以指定容器的列个数,列间距,列中间边框,列宽度来实现;
1 |
#container { -webkit-column-count: 5; /*-webkit-column-gap: 10px; -webkit-column-rule: 5px solid #333; -webkit-column-width: 210px;*/ -moz-column-count: 5; /*-moz-column-gap: 20px; -moz-column-rule: 5px solid #333; -moz-column-width: 210px;*/ column-count: 5; /*column-gap: 10px; column-rule: 5px solid #333; column-width: 210px;*/ } |
column-count 为列数; column-gap 为每列间隔距离; column-rule 为间隔边线大小; column-width 为每列宽度; 当只设置 column-width 时,浏览器窗口小于一列宽度时,列中内容自动隐藏; 当只设置 column-count 时,平均计算每列宽度,列内内容超出则隐藏; 都设了 column-count 和column-width,浏览器会根据 count 计算宽度和 width 比较,取大的那个值作为每列宽度,然后当窗口缩小时,width 的值为每列最小宽度。这边其实很简单,简易自己尝试下,详细可参考 https://developer.mozilla.org/en/CSS3_Columns 中的说明。 线上例子。 优点: 直接 CSS 定义,最方便了; 扩展方便,直接往容器里添加内容即可。 缺点: 只有高级浏览器中才能使用; 还有一个缺点,他的数据块排列是从上到下排列到一定高度后,再把剩余元素依次添加到下一列,这个本质上就不一样了; 鉴于这两个主要缺点,注定了该方法只能局限于高端浏览器,而且,更适合于文字多栏排列。 3) 绝对定位。即 Pinterest ,Mark之,KISSY 采用的方式: 可谓是最优的一种方案,方便添加数据内容,窗口变化,列数/数据块都会自动调整; 线上例子。 缺点: 需要实现知道数据块高度,如果其中包含图片,需要知道图片高度; JS 动态计算数据块位置,当窗口缩放频繁,可能会狂耗性能。 KISSY.Waterfall 实现思路 KISSY 的 Waterfall 组件主要包含两个部分,一个是对现有数据块进行排列计算各自所在的位置; 二是下拉滚动时,触发加载数据操作,并把数据添加到目标容器中。 […]
View Details1、event代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等。event对象只在事件发生的过程中才有效。event的某些属性只对特定的事件有意义。比如,fromElement 和 toElement 属性只对 onmouseover 和 onmouseout 事件有意义。 2、属性: altKey, button, cancelBubble, clientX, clientY, ctrlKey, fromElement, keyCode, offsetX, offsetY, propertyName, returnValue, screenX, screenY, shiftKey, srcElement, srcFilter, toElement, type, x, y 3、属性详细说明: 属性名 描述 值 说明 altKey 检查alt键的状态 当alt键按下时,值为True否则为False 只读 shiftKey 检查shift键的状态 当shift键按下时,值为True否则为False 只读 ctrlKey 检查ctrl键的状态 当ctrl键按下时,值为True否则为False 只读 例:(点击按钮时显示那几个特殊键按下的状态) <input type="button" value="点击" onClick="showState()"/> <script> function show(){ alert("altKey:"+window.event.altKey +"\nshiftKey:"+window.event.shiftKey +"\nctrlKey:"+window.event.ctrlKey); }</script> keyCode 检测键盘事件相对应的内码 可读写,可以是任何一个Unicode键盘内码。如果没有引发键盘事件,则该值为0 例:(按回车键让下一组件得到焦点,相当按Tab键) <input type="text" onKeyDown="nextBlur()"/> <input type="text"/> <script> function nextBlur(){ if(window.event.keyCode==13)//回车键的 code window.event.keyCode=9;//Tab键的code } </script> srcElement 返回触发事件的元素 Object 只读 例:(点击按钮时显示按钮的name值) <input type="button" value="闽" name="福建" onClick="show()"/> […]
View Details在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。 不带参数的启动方式 如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread,如下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using System; using System.Threading; namespace StartThread { class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun)); nonParameterThread.Start(); } /// <summary> /// 不带参数的启动方法 /// </summary> public void NonParameterRun() { for (int i = 0; i < 10; i++) { Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(interval); //让线程暂停 } } } } |
程序的运行效果我们不用运行也会知道,那就是在循环中将系统当前时间的毫秒部分输出出来,在每次输出之后会将当前线程暂停一下,直到10次之后运行完毕,终止线程的执行。 在上面的代码中我们是通过定义全局变量的方法来指定线程暂停间隔,按照这种方法,假如要运行10个线程,每个线程的暂停间隔不一样的话,就需要定义10个全局变量,虽然最终不影响系统的运行效果,但是总觉得不是太爽。 有没有比较简单一点的办法呢?有!那就是使用带参数的启动方法。 带参数的启动方法 如果要在实例化线程时要带一些参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要 ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。 为什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类)等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在启动方法中进行相应的类型转换。 下面就是一个例子,在启动线程时指定了线程的暂停间隔,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun)); parameterThread.Name = "Thread A:"; parameterThread.Start(30); } /// <summary> /// 带参数的启动方法 /// </summary> /// <param name="ms">让线程在运行过程中的休眠间隔</param> public void ParameterRun(object ms) { int j = 10; int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常 for (int i = 0; i < 10; i++) { Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(j);//让线程暂停 } } } } |
在这个方法里,我们在启动线程时顺便指定了线程的暂停间隔,也就是这句: parameterThread.Start(30); 线程启动时运行的方法是public void ParameterRun(object ms),这个值为30的int类型变量被装箱成object,所以在方法中还需要将它转换成int类型,这个可以通过拆箱或者其它办法解决。 假如我们要启动两个线程,每个线程的暂停间隔不一样,启动代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun)); parameterThread.Name = "Thread A:"; parameterThread.Start(30); //启动第二个线程 parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun)); parameterThread.Name = "Thread B:"; parameterThread.Start(60); } /// <summary> /// 带参数的启动方法 /// </summary> /// <param name="ms">让线程在运行过程中的休眠间隔</param> public void ParameterRun(object ms) { int j = 10; int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常 for (int i = 0; i < 10; i++) { Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(j);//让线程暂停 } } } } |
对上面的代码做一点说明,就是线程启动之后,线程的实例不必再存在,例如在上面的代码中我用的是同一个实例实例化了两个线程,并且这两个线程运行很正常。 继续探索 上面解决了一个问题,如果在启动线程时需要参数如何解决,如果针对上面的问题继续发掘,比如:在启动线程时不但要指定线程的暂停间隔,还需要指定循环次数(在上面的所有例子中都是执行10次的),这个问题该如何解决呢? 有两种办法可以解决: 首先可以继续在ParameterizedThreadStart这里做文章,因为这里可以使用一个Object类型的参数,那么可以通过数组或者一个类来解决(因为它们都是Object的子类)。我在做某个系统时确实采用数组处理过这种情况,这样就要求在线程启动方法中必须清楚知道数组中每个参数的用途,不是太方便。 这里说说重新定义一个实体类来解决的方法,代码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class MyThreadParameter { private int interval; private int loopCount; /// <summary> /// 循环次数 /// </summary> public int LoopCount { get { return loopCount; } } /// <summary> /// 线程的暂停间隔 /// </summary> public int Interval { get { return interval; } } /// <summary> /// 构造函数 /// </summary> /// <param name="interval">线程的暂停间隔</param> /// <param name="loopCount">循环次数</param> public MyThreadParameter(int interval, int loopCount) { this.interval = interval; this.loopCount = loopCount; } } class Program { int interval = 200; static void Main(string[] args) { Program p = new Program(); Thread parameterThread = new Thread(new ParameterizedThreadStart(p.MyParameterRun)); parameterThread.Name = "Thread A:"; MyThreadParameter paramter = new MyThreadParameter(50, 20); parameterThread.Start(paramter); } /// <summary> /// 带多个参数的启动方法 /// </summary> /// <param name="ms">方法参数</param> public void MyParameterRun(object ms) { MyThreadParameter parameter = ms as MyThreadParameter;//类型转换 if (parameter != null) { for (int i = 0; i < parameter.LoopCount; i++) { Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(parameter.Interval);//让线程暂停 } } } } } |
第二种方法和上面方法有些相似,也是需要引入外部类,并且将Thread实例放在引入的类中,这种情况适合于在线程中处理的业务逻辑比较复杂的情况。在前不久处理的一个项目中我用过这种情况,它是用来实现双向数据传输的。 如果实现上面的效果,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class MyThreadParameter { private int interval; private int loopCount; private Thread thread; /// <summary> /// 构造函数 /// </summary> /// <param name="interval">线程的暂停间隔</param> /// <param name="loopCount">循环次数</param> public MyThreadParameter(int interval, int loopCount) { this.interval = interval; this.loopCount = loopCount; thread = new Thread(new ThreadStart(Run)); } public void Start() { if (thread != null) { thread.Start(); } } private void Run() { for (int i = 0; i < loopCount; i++) { Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(interval);//让线程暂停 } } } class Program { static void Main(string[] args) { MyThreadParameter parameterThread = new MyThreadParameter(30, 50); parameterThread.Start(); } } } |
上面的代码的运行效果和前面的代码运行效果类似,只不过是将业务处理代码放在一个单独的类MyThreadParameter中,使得MyThreadParameter看起来也像一个Thread,实际上维护的还是其内部的Thread,在一些大型系统中这样做的好处是便于维护。 总结:在本篇主要讲述如何启动线程的问题,在启动时可能会遇到无需参数、需要多个参数的情况,在这里讲述了如何解决这些问题的思路。在.net类库中虽然存在着庞大的类库,但是并不是总会有合适的类来解决我们所遇到的问题,但是只要肯动脑筋总会想到合适的办法。
View Details你知道世界上有多少种浏览器吗?除了我们熟知的IE, Firefox, Opera, Safari四大浏览器之外,世界上还有近百种浏览器。 几天前,浏览器家族有刚诞生了一位小王子,就是Google推出的Chrome浏览器。由于Chrome出生名门,尽管他还是个小家伙,没有人敢小看他。以后,咱们常说浏览器的“四大才子”就得改称为“五朵金花”了。 在网站前端开发中,浏览器兼容性问题本已让我们手忙脚乱,Chrome的出世不知道又要给我们添多少乱子。浏览器兼容性是前端开发框架要解决的第一个问题,要解决兼容性问题就得首先准确判断出浏览器的类型及其版本。 JavaScript是前端开发的主要语言,我们可以通过编写JavaScript程序来判断浏览器的类型及版本。JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来分辨,另一种是通过分析浏览器的userAgent属性来判断的。在许多情况下,值判断出浏览器类型之后,还需判断浏览器版本才能处理兼容性问题,而判断浏览器的版本一般只能通过分析浏览器的userAgent才能知道。 我们先来分析一下各种浏览器的特征及其userAgent。 IE 只有IE支持创建ActiveX控件,因此她有一个其他浏览器没有的东西,就是ActiveXObject函数。只要判断window对象存在ActiveXObject函数,就可以明确判断出当前浏览器是IE。而IE各个版本典型的userAgent如下: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2) Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Mozilla/4.0 (compatible; MSIE 5.0; Windows NT) 其中,版本号是MSIE之后的数字。 Firefox Firefox中的DOM元素都有一个getBoxObjectFor函数,用来获取该DOM元素的位置和大小(IE对应的中是getBoundingClientRect函数)。这是Firefox独有的,判断它即可知道是当前浏览器是Firefox。Firefox几个版本的userAgent大致如下: Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1 Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3 Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12 其中,版本号是Firefox之后的数字。 Opera Opera提供了专门的浏览器标志,就是window.opera属性。Opera典型的userAgent如下: Opera/9.27 (Windows NT 5.2; U; zh-cn) […]
View Details下面是我整理的一些userAgent大家先看看格式 //Firefox 1.0.XMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7//Firefox 1.XMozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20051111 Firefox/1.5Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.8) Gecko/20060109 Firefox/1.5 (pigfoot) Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.2) Gecko/20060308 Firefox/1.5.0.2Mozilla/5.0 (Windows; U; […]
View Details虽然基于浏览器的操作系统还未“雄霸天下”,但对Web开发者来说2011年无疑是“风景不错”的一年。这是一个适合Web开发的“美好时代”,有很多有史以来最好的开发工具可供使用,下面我们将介绍五款2011年最受欢迎的Web开发工具: 1.jQuery和jQuery Mobile jQuery是一款免费且开放源代码的JavaScript代码库,而jQuery Mobile是jQuery在手机和平板上的版本。jQuery Mobile不仅能给主流移动平台带来jQuery核心库,还能发布一个完整统一的jQuery移动UI框架,支持全球主流的手机、平板、电子阅读器、台式电脑等平台。据微软关于jQuery的调查显示,jQuery在受访网站中的使用率已从2010年12月的27%上升到2011年12月的42%。 2.CSS3 PIE CSS3 PIE(“Progressive Internet Explorer”的缩写)工具可以让IE6至IE8的所有版本实现大多数的CSS3修饰特性,如圆角、阴影、渐变等等。通过这个工具,开发者可以在线修改想要的效果,并即时生成css代码。 3.Bootstrap 今年8月,Twitter推出了一个名为Bootstrap的开发工具包,将Web应用开发与部署变得更为简单快捷。Bootstrap包是一个简单的程序库,同时提供优雅的HTML和CSS规范。Bootstrap使用了一些最新的Web浏览器技术,向开发者提供时尚的排版、样式、按钮、表格、网格、导航等服务,而且占用资源很小,用gzip压缩后只有6K左右。 4.LESS LESS是一个CSS开发管理的强大工具,拓展了CSS的变量、运算符、include、嵌套规则等语法。LESS从Ruby的LESS library衍生而来,免费开源,实现了和CSS的无缝结合。此外,LESS可以配置成自动最小化所生成的CSS文件,不仅可以节省带宽,还可以改善最终用户的体验。 5.Chrome开发人员工具 火狐即将死亡的预言或许被夸大其词了,但可以肯定的是Chrome正在侵蚀越来越大的市场份额,其中最主要的一个原因是Web开发人员喜欢Chrome捆绑自带的开发人员工具。 Chrome开发人员工具主要基于WebKit网络检查器(开放源代码WebKit项目的一部分),可让Web开发人员随时随地对网页的CSS、HTML和JavaScript进行实时编辑、调试以及监控。该工具不仅能帮助诊断、修复在网页加载、脚本执行以及页面呈现中出现的问题,还可帮助最大限度地了解网页或网络应用程序对CPU以及内存的使用情况。 原文出处:ReadWriteWeb 译文出处:雷锋网
View DetailsJeremy Keith在 Fronteers 2010 上的主题演讲 下载PPT(PDF) http://adactio.com/extras/slides/designofhtml5.pdf 观看视频 http://fronteers.nl/congres/2010/sessions/the-design-of-html5-jeremy-keith 今天我想跟大家谈一谈HTML 5的设计。主要分两个方面:一方面,当然了,就是HTML 5。我可以站在这儿只讲HTML 5,但我并不打算这样做,因为如果你想了解HTML 5的话,你可以Google,可以看书,甚至可以看规范。 实际上,确实有人会谈到规范的内容。史蒂夫·福克纳(Steve Faulkner)会讲HTML 5与可访问性。而保罗·艾里什(Paul Irish)则会讲HTML 5提供的各种API。因此,我今天站在这里,不会光讲一讲HTML 5就算完事了。 说老实话,在正式开始之前,我想先交待清楚我所说的HTML 5到底是什么意思。这话听起来有点搞笑:这会子你一直在说HTML 5,难道我们还不知道什么是HTML 5吗?大家知道,有一个规范,它的名字叫HTML 5。我所说的HTML 5,指的就是这个规范。但问题是,有些人所说的HTML 5,指的不仅仅是这个规范,还有别的意思。比如说,用HTML 5来代指CSS3就是一种常见的叫法。我可不是这样的。我所说的HTML 5,不包含CSS3,就是HTML 5。 类似的术语问题以前也有过。Ajax本来是一种含义明确的技术,但过了不久,它的含义就变成了“用JavaScript来做一切好玩的东西”。这就是Ajax,对不对?今天,HTML 5也面临同样的问题,它本来指的是一个特定的规范,但如今含义却成了“在Web上做一切好玩的事。”我说的不是这种HTML 5,不是这种涵盖了最近刚刚出现的各种新东东的HTML 5。我说的仅仅是规范本身:HTML 5。 刚才已经说了,我今天想要讲的内容不多,也没有打算介绍HTML 5都包含什么。今天我要讲的是它的另一方面,即HTML 5的设计。换句话说,我要讲的不是规范里都包含什么,而是规范里为什么会包含它们,以及在设计这个规范的时候,设计者们是怎么看待这些东西的。 设计原理 设计原理本质上是一种信念、一种想法、一个概念,是你行动的支柱。不管你是制定规范,还是制造一种有形的物品,或者编写软件,甚至发明编程语言。你都能找到背后的一个或者多个设计原理,多人协作的任何成果都是例证。不仅仅Web开发领域是这样。纵观人类历史,像国家和社会这样大规模的构建活动背后,同样也有设计原理。 就拿美国为例吧,美国的设计原理都写在了《独立宣言》中了。 我们认为这些真理是不言而喻的,人人生而平等,造物主赋予了每个人不可剥夺的权利,包括生存、自由和追求幸福。 这里有一句口号:生存、自由和追求幸福。这是被写进宪法中的核心理念,它关系到我们所有人的一切,也就是我们构建自己社会的原则。 还有一个例子,就是卡尔·马克思(Karl Marx),他的著作在20世纪曾被奉为建设社会主义的圭臬。其基本思想大致可以归结为下面这条设计原理: 各尽所能,各取所需。 这其实就是一种经济体系背后的设计原理。 还有一个例子,比前面两个的历史更久远一些,不过大同小异: 人人为我,我为人人。 这个极为简单的设计原理,是两千年前的拿撒勒犹太人耶稣基督提出来的。而这条原则成为了后来许多宗教的核心教义。原理与实践有时候并不是同步的。 下面是小说中的一个例子。英国小说家乔治·奥威尔(George Orwell)笔下的《动物庄园》,就是在一条设计原理的基础上构建起来的虚拟社会。这条设计原理是: 四条腿的都是好人,两条腿的都是坏蛋! 《动物庄园》中有意思的是,随着社会的变迁——变得越来越坏,这条设计原理也跟着发生了改变,变成了“四条腿的都是好人,两条腿的就更好了。”最关键的是,即使是在虚构的作品里,设计原理都是存在的。 还有一套虚构的作品是以三条设计原理为基础构建起来的,那就是美国著名小说家艾萨克·阿西莫夫(Issac Asimov)的机器人经典系列。阿西莫夫发明了机器人学这个术语,并提出了机器人学三大法则,然后在这三个简单的设计原理基础上创作了一系列经典作品——大约有50本书。无论作品的情节如何变化,实际上都是从不同的角度来阐释这三大设计原理。我想,在座各位对机器人三大法则都不应该陌生。 机器人不得伤害人类,或袖手旁观人类受伤害。 机器人必须服从人类命令,除非命令违反第一法则。 机器人必须自卫,只要不违背第一和第二法则。 这些恐怕是第一次出现在小说中的针对软件的设计原理了。虽然基于这三个设计原理的软件运行在虚构的机器人的“正电子脑”中,但我想这应该是软件设计原理的事实开端。从此以后,我们才看到大量优秀软件背后的设计原理。 蒂姆·伯纳斯-李(Tim Berners-Lee),Web的发明者,在W3C的网站上发表过一份文档,其中有一个URL给出了他自己的一套设计原理。这些设计原理并不那么容易理解,不仅多,而且随着时时间推移,他还会不断补充、修改和删除。不过我还是觉得把自己认同的设计原理写出来放在某个地方真是个不错的主意。 实际上,CSS的发明人之一伯特·波斯(Bert Bos),也在W3C的网站上放着一份文档,其中讲的都是基本的设计原理,比如怎样设计并构建一种格式,无论是CSS还是其他格式。推荐大家看一看。 只要你在W3C的站点中随便找一找,就可以发现非常多的这种设计原理,包括蒂姆·伯纳斯-李个人的。当然,你还会看到他从软件工程学校里借用的一些口号:分权(decentalisation)、容忍(tolerance)、简易(simplicity)、模块化(modularity)。这些都是在他发明新格式的时候,头脑中无时无刻不在想的那些关键词。 在座各位对蒂姆·伯纳斯-李的贡献都是非常熟悉的,因为大家每天都在用。他发明了Web,与罗伯特·卡里奥(Robert Cailliau)共同发明了Web,而且在发明Web的同时,也发明了我们每天都在Web上使用的语言。当然,这门语言就是HTML:超文本标记语言。 HTML HTML最早是从2.0版开始的。从来就没有1.0版。如果有人告诉你说,他最早是从HTML 1.0开始使用HTML的,那他绝对是在忽悠你。从前确实有一个名叫HTML Tags的文档,其中的部分标签一直用到现在,但那个文档并非官方的规范。 使用标签、尖括号、p或h1,等等,并不是蒂姆·伯纳斯-李首创的想法。当时的SGML里就有了这些概念,而且当时的CERN(Conseil Europeen pour la Recherche Nucleaire,欧洲核子研究委员会)也在使用SGML的一个特定的版本。也就是说,即便在那个时代,他也没有白手起家;这一点在HTML后来的发展过程中也体现了出来:继往开来、承前启后,而不是另立门户、从头开始。 换句话说,这篇名为HTML Tags的文档可以算作HTML的第一个版本,但它却不是一个正式的版本。第一个正式版本,HTML 2.0,也不是出自W3C之手。HTML 2.0是由IETF,因特网工程任务组(Internet Engineering Task Force)制定的。在W3C成立之前,IETF已经发布了不少标准。但从第三个版本开始往后,W3C,万维网联盟(World Wide Web Consortium)开始接手,并负责后续版本的制定工作。 20世纪九十年代HTML有过几次快速的发展。众所周知,在那个时代要想构建网站,可是一项十分复杂的工程。浏览器大战曾令人头疼不已。市场竞争的结果就是各家浏览器里都塞满了各种专有的特性,都试图在专有特性上胜人一筹。当时的混乱程度不堪回首,HTML到底还重不重要,或者它作为Web格式的前景如何,谁都说不清楚。 […]
View Details所有的开发人员都应该注意了,你们绝对应该看看这篇文章,帮助你快速创建HTML5/CSS3的开发框架。可能你也看到过其它的框架,但是你应该看看这些框架,因为你以前可能没用过他们中的大部分。看看最新的实用HTML5和CSS3框架吧!希望你们喜欢! 1.HTML5boilerplate H5BP带给你非常漂亮的文档,一个网站优化的编译脚本,还有一个自定义的boilerplate编译器。除此之外,我们还支持lighttd,Google App Engine和NodeJS以及优化的服务器配置(包括Apache,Nginx,和IIS),并且已经把boilerplate的大小减少了50%。 源码 演示 2.The M project 跨平台的手机开发HTML5 javascript框架。特性包括:MVC HTML5,Javascript-所有的开发周期,离线支持(自动缓存),富客户端UI,本地和远程数据支持并且远程存储,国际化(i18n),开源(MIT license),基于NodeJS的编译工具(叫做Espresso)。 源码 演示 3.Gravity 一个基于SASS的框架用于创建功能强大的,易于管理的HTML5网站。能够帮助你快速的创建你创意的原型,并且能让你的开发更简单。 源码 演示 4.Popcorn.js 一个HTML5视频的事件框架,提供一个简单的API来同步互动和身临其境的内容。Popcorn.js使用本地本地HTMLMediaElement属性,方法和事件。转化成一个简单实用的API,并且提供了一个插件系统用于方便社区开发。 源码 演示 5.Roots 一个基于HTML5 boilerplate开发的wordpress主题,blueprint CSS(或者960.gs)和Starkers,能够帮助你快速在创建博客和文字站点。 源码 演示 6.Baker 2.0 一个HTML5 ebook框架用来在ipad和iphone上使用Web标准来发布内容。 源码 演示 7.CSS3-action-framework CSS3的类库用于收集最好的CSS3效果。现在支持CSS3的浏览器正在增加;CSS3在许多案例都可以像javascript一样使用,提供更好的用户体验 源码 演示 8.52frarmework 第一个用enavu network开发的HTML5/CSS3框架 源码 演示 9.G5 Framework 基于F布局。特性包括:CSS&SEO,PHP active class, HTML5 placeholder fallback,粘合的页脚,HTML5基线,光滑的滚动到顶端和非常干净的组织。 源码 演示 10.Inuit.CSS 由Harry Roberts创建。这个框架用于使用较少的代码实现稍小的屏幕。支持IE6+。 源码 演示 文章出自:gbin1.com
View Details