web开发中常常要实现“复制到剪切板”功能。这个功能很实用,但是由于安全问题,浏览器的限制越来越严,实现的方法也越来越有限了。Firefox 默认下不能直接通过Javascript操作剪切板,必须开启相关的设置才行。想只通过Javascript技术实现跨浏览器的剪切板是行不通的。现在常用的方法是利用JavaScript+Flash实现,普遍流传的办法是_clipboard.swf,这是国外最早实现的(著名的Clipboard Copy解决方案: http://www.jeffothy.com/weblog/clipboard-copy/)。但是很可惜,_clipboard.swf在新出来的flash10中无效,因为flash10中规定了只有在swf上进行了实际的操作(比如鼠标点击)才能启动剪切板。而_clipboard.swf方法的swf是隐藏的,通过JavaScript来操作flash的剪切板,显然没有对swf进行实际的用户操作。

  本文将介绍一个跨浏览器的库类 Zero Clipboard 。它利用 Flash 进行复制,所以只要浏览器装有 Flash 就可以运行,而且比 IE 的 document.execCommand("Copy") 更加灵活。

Zero Clipboard 的实现原理
Zero Clipboard 利用 Flash 进行复制,之前有 Clipboard Copy 解决方案,其利用的是一个隐藏的 Flash。但最新的 Flash Player 10 只允许在 Flash 上进行操作才能启动剪贴板。所以 Zero Clipboard 对此进行了改进,用了一个透明的 Flash ,让其漂浮在按钮之上,这样其实点击的不是按钮而是 Flash ,也就可以使用 Flash 的复制功能了。

如何使用 Zero Clipboard
首先下载 Zero Clipboard ,并解压缩。其中需要两个文件:ZeroClipboard.js 和 ZeroClipboard.swf ,将这两个文件放入到你的项目中。

Zero Clipboard项目主页:

http://code.google.com/p/zeroclipboard/

演示地址:
http://bowser.macminicolo.net/~jhuckaby/zeroclipboard/

核心功能
第一步,导入 ZeroClipboard.js 文件:

XML/HTML代码

  1. <script type="text/javascript" src="ZeroClipboard.js"></script>

再设置 ZeroClipboard.swf 文件的路径:

XML/HTML代码

  1. ZeroClipboard.setMoviePath( "ZeroClipboard.swf" );  

注意:以上 ZeroClipboard.js, ZeroClipboard.swf 两个文件的路径都需要替换为你项目中对应文件的路径。或者也可以是一个绝对路径。

然后就使用了:
复制代码 代码如下:

JavaScript代码

  1. var clip = new ZeroClipboard.Client(); // 新建一个对象
  2. clip.setHandCursor( true ); // 设置鼠标为手型
  3. clip.setText("哈哈"); // 设置要复制的文本。
  4. // 注册一个 button,参数为 id。点击这个 button 就会复制。
  5. //这个 button 不一定要求是一个 input 按钮,也可以是其他 DOM 元素。
  6. clip.glue("copy-botton"); // 和上一句位置不可调换

这样,这样基本功能实现了,点击按钮就可以复制设置好的文本了。你可能注意到了,待复制的文本是固定的,如果想要动态改变的怎么办,比如复制一个输入框中的内容。不用担心,下面会讲到的。

其他函数
Zero Clipboard 还提供了一些其他的函数,其中有一些非常有用。

reposition() 方法
因为按钮上漂浮有一个 Flash 按钮,所以当页面大小发生变化时,Flash 按钮可能会错位,这样就点不着了。 不要紧,Zero Clipboard 提供了一个 reposition() 方法,可以重新计算 Flash 按钮的位置。我们可以将它绑定到 resize 事件上。
复制代码 代码如下:

JavaScript代码

  1. bind(window, "resize", function(){   
  2. clip.reposition();   
  3. });  

bind 是一个跨浏览器的事件绑定函数。
=========================================================
这个想必大家都已知道。IE 的事件绑定函数是 attachEvent;而 Firefox, Safari 是 addEventListener;Opera 则两种都支持。下面进行封装。
复制代码 代码如下:

JavaScript代码

  1. /************************************
  2. * 添加事件绑定
  3. * @param obj : 要绑定事件的元素
  4. * @param type : 事件名称。不加 "on". 如 : "click" 而不是 "onclick".
  5. * @param fn : 事件处理函数
  6. ************************************/
  7. function bind( obj, type, fn ) {   
  8. if ( obj.attachEvent ) {   
  9. obj['e'+type+fn] = fn;   
  10. obj[type+fn] = function(){obj['e'+type+fn]( window.event );}   
  11. obj.attachEvent( 'on'+type, obj[type+fn] );   
  12. } else
  13. obj.addEventListener( type, fn, false );   
  14. }   

例如添加一个页面点击事件:
复制代码 代码如下:

JavaScript代码

  1. bind(document, "click", function() {   
  2. alert("Hello, World!!");   
  3. });   

=========================================================
hide() 和 show() 方法
这两个方法可以隐藏和显示 Flash 按钮 。其中 show() 方法会调用 reposition() 方法。

setCSSEffects() 方法
当鼠标移到按钮上或点击时,由于有 Flash 按钮的遮挡,所以像 css ":hover", ":active" 等伪类可能会失效。setCSSEffects() 方法就是解决这个问题。首先我们需要将伪类改成类,比如:
复制代码 代码如下:

JavaScript代码

  1. #copy-botton:hover{
  2. border-color:#FF6633;   
  3. }   
  4. // 可以改成下面的 ":hover" 改成 ".hover"
  5. #copy-botton.hover{
  6. border-color:#FF6633;   
  7. }   

我们可以调用 clip.setCSSEffects( true ); 这样 Zero Clipboard 会自动为我们处理:将类 .hover 当成伪类 :hover 。

getHTML() 方法
如果你想自己实例一个 Flash ,不用 Zero Clipboard 的附着方法,那么这个方法就可以帮上忙了。它接受两个参数,分别为 Flash 的宽度和高度。返回的是 Flash 对应的 HTML 代码。例如:

JavaScript代码

  1. var html = clip.getHTML( 150, 20 );  

你可以用 innerHTML 或直接 document.write(); 进行输出。
以下是我测试下输出的 HTML 代码:

XML/HTML代码

  1. <embed id="ZeroClipboardMovie_1" src="zeroclipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="150" height="20" name="ZeroClipboardMovie_1" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=150&height=20" wmode="transparent" />

IE 的 Flash JavaScript 通信接口上有一个 bug 。你必须插入一个 object 标签到一个已存在的 DOM 元素中。并且在写入 innerHTML 之前请确保该元素已经 appendChild 方法插入到 DOM 中。

Zero Clipboard 事件处理
Zero Clipboard 提供了一些事件,你可以自定义函数处理这些事件。Zero Clipboard 事件处理函数为 addEventListener(); 例如当 Flash 完全载入后会触发一个事件 "load" 。

JavaScript代码

  1. clip.addEventListener( "load", function(client) {   
  2. alert("Flash 加载完毕!");   
  3. });  

Zero Clipboard 会将 clip 对象作为参数传入。即上例中的 "client" 。
还有 "load" 也可以写成 "onLoad",其他的事件也可以这样。

其他事件还包括:

mouseOver 鼠标移上事件
mouseOut 鼠标移出事件
mouseDown 鼠标按下事件
mouseUp 鼠标松开事件
complete 复制成功事件
其中 mouseOver 事件和 complete 事件比较常用。
前面说过,如果需要动态改变待复制的内容,那 mouseOver 事件就可以派上用场了。例如需要动态复制一个 id 为 test 的输入框中的值,我们可以在鼠标 over 的时候重新设置值。

JavaScript代码

  1. clip.addEventListener( "mouseOver", function(client) {   
  2. var test = document.getElementById("test");   
  3. client.setText( test.value ); // 重新设置要复制的值
  4. });  

复制成功:

JavaScript代码

  1. clip.addEventListener( "complete", function(){   
  2. alert("复制成功!");   
  3. });  

好了,就介绍到这里吧。赶快自己试验下吧。

posted @ 2010-08-02 10:06 雨中漫步的太阳 阅读(925) 评论(0)  编辑

原文地址:http://www.cnblogs.com/Kevin-moon/archive/2009/04/24/1442469.html

前段时间仔细看过些关于多线程方面的资料,项目中用到线程的地方也不少,可是,当看了Jeffrey的一篇关于锁的文章后,发现自己虽然一直都在使用多线程,但是缺少了做多线程编程需要的思维!所以想从Jeffrey的Optex(锁)入手,来谈谈我从其中体会的东西。
在NET中,我们用的最多的锁机制就是lock,用起来很简单,短短几行程序就可以实现,例如:

//Lock 's Code
public class TestThreading
{
private System.Object lockThis = new System.Object();
public void Function()
    {
lock (lockThis)
        {
// Access thread-sensitive resources.
        }
    }
}

其实我们也明白,lock并不是锁,而是MS提供的一个简便式的写法,真正实现的是Monitor类中的Enter和Exit方法,既然提到了Monitor类也就说下有个需要注意的地方:
    Pulse和PulseAll方法,这两个方法就是把锁状态将要改变的消息通知给等待队列中的线程,不过这时如果等待队列中没有线程,那么该方法就会一直等待下去,直到有等待的线程进入队列,也就是说该方法可能造成类试死锁的情况出现。
上面的lock + 线程(Thread和ThreadPool) = 多线程编程(N%)!?
    对于该公式我曾经的N是80,现在是20。其中有很多东西影响我,让我从80->20,下面的Optex就是一个入口点。


//Optex 's Code
public sealed class Optex : IDisposable {
private Int32 m_Waiters = 0;
private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);
public Optex() { }
public void Dispose() {
if (m_WaiterLock != null)
      { 
         m_WaiterLock.Close(); 
         m_WaiterLock = null;
      } 
   }
public void Enter() {
      Thread.BeginCriticalRegion();
// Add ourself to the set of threads interested in the Optex
if (Interlocked.Increment(ref m_Waiters) == 1) {
// If we were the first thread to show interest, we got it.
return;
      }
// Another thread has the Optex, we need to wait for it
      m_WaiterLock.WaitOne();
// When WaitOne returns, this thread now has the Optex
   }
public void Exit() {
// Subtract ourself from the set of threads interested in the Optex
if (Interlocked.Decrement(ref m_Waiters) > 0) {
// Other threads are waiting, wake 1 of them
         m_WaiterLock.Release(1);
      }
      Thread.EndCriticalRegion();
   }
}

看完上面的代码,让我增加了两点认识:
1、Thread.BeginCriticalRegion()和Thread.EndCriticalRegion(); 
因为这段时间正好看了一本多线程编程的书,既然将上面方法认为是进入临界区和退出临界区,对于临界区而言,进入该区的数据,在没有退出之前,如果临界区外的程序需要使用它,那么就必须出于等待。所以觉得已经使用临界区,为什么还要使用Semaphore?!
可是,MS只是取了个相同的名字,做的事情完全不同,上面两个方法完全没有临界区的概念,它只是设置一个区域(Begin到End之间),表示该区域内发生线程中断或未处理的异常会影响整个应用程序域。

2、m_Waiters的作用

一开始以为在Enter的时候,直接写上:
            m_WaiterLock.WaitOne();

              Exit的时候,写上:
m_WaiterLock.Release(1);
这样就可以了。m_Waiters有什么意义?!
优化性能,Semaphore是内核对象,我们都知道,要尽量少的进入内核模式,因为这是很消耗性能,所以尽量少的使用内核对象。m_Waiters的意义就在这里,如果只有一个线程使用该锁对象的时候,是不需要去获取和释放的。 OK,上述的东西都是铺垫,铺完了也就进入主题了!
多线程的思维

 
div css xhtml xml Example Source Code Example Source Code [http://www.cnblogs.com/suyuan/]
namespace ThreadConcurrent.Lock
{
    public sealed class Optex : IDisposable
    {
        /// <summary>
        /// 琐的状态
        /// </summary>
        private Int32 m_LockState = c_lsFree;

        /// <summary>
        /// 自由状态
        /// </summary>
        private const Int32 c_lsFree = 0x00000000;
        
        /// <summary>
        /// 被拥有状态
        /// </summary>
        private const Int32 c_lsOwned = 0x00000001;
        
        /// <summary>
        /// 等待的线程数
        /// </summary>
        private const Int32 c_1Waiter = 0x00000002;

        private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);

        #region 构造函数

        /// <summary>
        /// 
        /// </summary>
        public Optex() { }

        #endregion

        /// <summary>
        /// 请求锁
        /// </summary>
        public void Enter()
        {
            Thread.BeginCriticalRegion();
            while (true)
            {
                Int32 ls = InterlockedOr(ref m_LockState, c_lsOwned);

                //自由状态
                if ((ls & c_lsOwned) == c_lsFree) return;

                // 增加等待的线程数
                if (IfThen(ref m_LockState, ls, ls + c_1Waiter))
                {
                    m_WaiterLock.WaitOne();
                }
            }
        }

        public void Exit()
        {
            // 释放琐
            Int32 ls = InterlockedAnd(ref m_LockState, ~c_lsOwned);

            //无等待的线程
            if (ls == c_lsOwned)
            {
            }
            else
            {
                ls &= ~c_lsOwned;
                if (IfThen(ref m_LockState, ls & ~c_lsOwned, ls - c_1Waiter))
                {
                    m_WaiterLock.Release(1);
                }
                else
                {
                }
            }
            Thread.EndCriticalRegion();
        }

        #region 原子化操作

        /// <summary>
        /// 与操作
        /// </summary>
        /// <param name="target"></param>
        /// <param name="with"></param>
        /// <returns></returns>
        private static Int32 InterlockedAnd(ref Int32 target, Int32 with)
        {
            Int32 i, j = target;
            do
            {
                i = j;
                j = Interlocked.CompareExchange(ref target, i & with, i);
            } while (i != j);
            return j;
        }

        /// <summary>
        /// 或操作
        /// </summary>
        /// <param name="target"></param>
        /// <param name="with"></param>
        /// <returns></returns>
        private static Int32 InterlockedOr(ref Int32 target, Int32 with)
        {
            Int32 i, j = target;
            do
            {
                i = j;
                j = Interlocked.CompareExchange(ref target, i | with, i);
            } while (i != j);
            return j;
        }

        #endregion

        private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then)
        {
            return (Interlocked.CompareExchange(ref val, @then, @if) == @if);
        }

        private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then, out Int32 prevVal)
        {
            prevVal = Interlocked.CompareExchange(ref val, @then, @if);
            return (prevVal == @if);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (m_WaiterLock != null)
            {
                m_WaiterLock.Close();
                m_WaiterLock = null;
            }
        }
    }
}
对于上面的这个代码,我晕眩了好一段时间,不过当我真正理解的时候,从晕眩中学到了做多线程编程应该具备的思维方式。 
首先从简单的理解开始谈,
1、原子化操作
     对于InterLocked类,曾经也知道,但是却用的很少,不过从该代码中知道,在多线程的编程中对共享数据的写入操作,一定要达到原子性。
至于如何做到这点,InterlockedAnd和InterlockedOr做了很好的诠释: 
While循环的目的就是保证target值以最新的值做与操作,如果传入的值在执行的过程被其他线程改变的话,那么是不会退出该循环的,
并会利用改变后的值重新做次与操作。


2、理解Enter和Exit
     这两个方法很难写出来解释,用图是最清晰的。

曾经的晕眩:
1、Enter方法中为什么存在循环,为什么不是执行完waitone就结束,必须m_lockState等于c_IsFree的时候才结束?
     线程的执行并不完全按照先前排好的顺序去执行,有时会发生一些特殊的情况来使改变线程的调度顺序,所以就可能会出现上图灰色部分的情况,则为了解决该可能发生的问题(概率很小)循环机制就出现了。
2、为什么在WaitOne和Release之前,除了增加和减少等待者外,还需要判断m_lockstate是否改变(进入Enter到执行Waitone前的这段时间)?
一般性的思维:

该程序的思维:

这样做的好处就是尽量少的操作内核对象,提高性能!
      多线程编程虽然复杂,但是我觉得很有意思和挑战性,而且随着硬件的发展,多线程编程会更加重要,既然已经上路就让我们走到尽头!
posted @ 2009-04-24 09:34 雨中漫步的太阳 阅读(59) 评论(0)  编辑
以验证码为例:

1. 不要把生成的随机验证码存储到 Session 里面。第一,我们并不能保证在负载均衡环境下,每次请求都会被路由到同一台机器上;第二,现在很多 IIS 都会启用 "Web 园",也就是说在一台机器上启用多个进程来并发处理用户请求,而 Session 默认情况下是无法跨进程共享的。这些问题都可能导致用户明明输入一个正确的验证码,却无法进行提交操作。虽然在 MSDN 上建议大家将 Session 信息写入 SqlServer,个人觉得还是部署一个 memcached 要好些,性能会好很多。

2. 使用 Cookie 保存验证码。首先,一定要注意将验证码数据进行加密,否则验证码就是一摆设 (相信很多写过蜘蛛抓取程序的人都会分析是否能直接从 Cookie 获取相应的数据 [lol]); 第二,不要滥用 Cookie,默认情况下,每个域在同一个客户端只能存储 20 个 Cookie,如果我们不注意分配使用,可能造成某些更重要的信息被删除,造成其他业务流程失败。

3. 很多用户习惯使用 FireFox、Maxthon 等多页面浏览器一次打开多个页面,而如果验证码采用同一个 name 的话,那么只有最后一个页面的验证码有效。等用户输入验证码进行提交操作时,就会频繁出现 "验证码错误"。我想这不但让用户觉得痛苦,对网站的好感也会大幅度降低。我在某网站下载电子图书的时候,就遇到这个问题,所有验证码必须重新刷新一次。解决办法可以是在某个 input.focus 时才显示验证码,从而确保其有效性。

posted @ 2008-01-11 15:57 雨中漫步的太阳 阅读(66) 评论(0)  编辑
object 返回包含的对象。 
offscreenBuffering 设置或获取对象在对用户可见之前是否要先在屏幕外绘制。 
offsetHeight 获取对象相对于版面或由父坐标 offsetParent 属性指定的父坐标的高度。 
offsetLeft 获取对象相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置。 
offsetParent 获取定义对象 offsetTop 和 offsetLeft 属性的容器对象的引用。 
offsetTop 获取对象相对于版面或由 offsetTop 属性指定的父坐标的计算顶端位置。 
offsetWidth 获取对象相对于版面或由父坐标 offsetParent 属性指定的父坐标的宽度。 
offsetX 设置或获取鼠标指针位置相对于触发事件的对象的 x 坐标。 
offsetY 设置或获取鼠标指针位置相对于触发事件的对象的 y 坐标。 
onLine 获取表明系统是否处于全局脱机模式的值。 
opener 设置或获取创建当前窗口的窗口的引用。 
outerHTML 设置或获取对象及其内容的 HTML 形式。 
outerText 设置或获取对象的文本。 
overflow 设置或获取表明当内容超出对象高度或宽度时如何管理对象内容的值。 
overflowX 设置或获取当内容超出对象宽度时如何管理对象内容。 
overflowY 设置或获取当内容超出对象高度时如何管理对象内容。 
ownerDocument 设置或获取结点关联的 document 对象。 
owningElement 获取 HTML 层次中的下个对象。 
padding 设置或获取要在对象和其边距或若存在的边框的话就是对象和其边框之间要插入的全部空间。 
paddingBottom 设置或获取要在对象下边框和内容之间插入的空间总量。 
paddingLeft 设置或获取要在对象左边框和内容之间插入的空间总量。 
paddingRight 设置或获取要在对象右边框和内容之间插入的空间总量。 
paddingTop 设置或获取对象上边框和内容之间插入的空间总量。 
pageBreakAfter 设置或获取表明对象后发生换页的字符串。 
pageBreakBefore 设置或获取表明对象前发生换页的字符串。 
palette 获取用于嵌入文档的调色板。 
parent 获取对象层次中的父窗口。 
parentElement 获取对象层次中的父对象。 
parentNode 获取文档层次中的父对象。 
parentStyleSheet 获取导入到当前样式表的样式表。 
parentTextEdit 获取文档层次中可用于创建包含原始对象的 TextRange 的容器对象。 
parentWindow 获取容器对象所在窗口的引用。 
pathname 设置或获取对象指定的文件名或路径。 
pixelBottom 设置或获取对象的下方位置。 
pixelHeight 设置或获取对象的高度。 
pixelLeft 设置或获取对象的左侧位置。 
pixelRight 设置或获取对象的右侧位置。 
pixelTop 设置或获取对象的上方位置。 
pixelWidth 设置或获取对象的宽度。 
platform 获取用户的操作系统名称。 
pluginspage 获取用于查看嵌入文档的插件 URL。 
port 设置或获取与 URL 关联的端口号码。 
posBottom 设置或获取以 bottom 标签属性指定的单位的对象下方位置。 
posHeight 设置或获取以 height 标签属性指定的单位的对象高度。 
position 设置或获取对象所使用的定位方式。 
posLeft 设置或获取以 left 标签属性指定的单位的对象左侧位置。 
posRight 设置或获取以 right 标签属性指定的单位的对象右侧位置。 
posTop 设置或获取以 top 标签属性指定的单位的对象上方位置。 
posWidth 设置或获取以 width 标签属性指定的单位的对象宽度。 
previousSibling 获取对此对象的上一个兄弟对象的引用。 
profile 设置或获取对象的属性和及这些属性的合法值所定义的一个或多个 URI。 
propertyName 设置或获取对象上发生更改的属性名称。 
protocol 设置或获取 URL 的协议部分。 
pseudoClass 获取标识 @page 规则应用到的页面的伪类的字符串。 
qualifier 设置或获取由数据源对象提供的数据成员的名称。 
readOnly 获取规则或样式表是定义在页面上还是导入的。 
readOnly 设置或获取表明对象内容是否为只读的值。 
readyState 获取对象的当前状态。 
readyState 获取对象的当前状态。 
readyState 获取对象的当前状态。 
reason 设置或获取数据源对象的数据传输结果。 
recordNumber 获取数据集中生成对象的原始记录。 
recordset 从数据源对象设置或获取对缺省数据集的引用。 
referrer 获取将用户引入当前页面的位置 URL。 
rel 设置或获取对象和链接目的的关系。 
repeat 获取 onkeydown 事件是否正在重复。 
returnValue 设置或获取从模式对话框返回的值。 
returnValue 设置或获取事件的返回值。 
rev 设置或获取对象和链接目的的关系。 
right 设置或获取围绕对象内容的矩形右边坐标。 
right 设置或获取对象相对于文档层次中下个已定位的对象的右边界的位置。 
rightMargin 设置或获取页面的整个主体的右边距,而不是缺省的边距。 
rowIndex 获取对象在表格的 rows 集合中的位置。 
rows 设置或获取对象中包含的水平行数。 
rows 设置或获取对象的框架高度。 
rowSpan 设置或获取单元格要跨越表格的多少行。 
rubyAlign 设置或获取由 rt 对象指定的注音文本的位置。 
rubyOverhang 设置或获取由 rt 对象指定的注音文本的位置。 
rubyPosition 设置或获取由 rt 对象指定的注音文本的位置。 
rules 设置或获取要显示哪些分隔线(内部边框)。 
saveType 当 oncontentsave 触发时获取剪贴板类型。 
scheme 设置或获取用于解释为对象指定的属性值的方案。 
scope 设置或获取对象的信息所应用的标格单元格组。 
scopeName 获取为该元素定义的命名空间。 
screenLeft 获取浏览器客户区左上角相对于屏幕左上角的 x 坐标。 
screenTop 获取浏览器客户区左上角相对于屏幕左上角的 y 坐标。 
screenX 设置或获取获取鼠标指针位置相对于用户屏幕的 x 坐标。 
screenY 设置或获取鼠标指针位置相对于用户屏幕的 y 坐标。 
scroll 设置或获取滚动是否关闭。 
scrollAmount 设置或获取介于每个字幕绘制序列之间的文本滚动像素数。 
scrollbar3dLightColor 设置或获取滚动条上滚动按钮和滚动滑块的左上颜色。 
scrollbarArrowColor 设置或获取滚动箭头标识的颜色。 
scrollbarBaseColor 设置或获取滚动条的主要颜色,其中包含滚动按钮和滚动滑块。 
scrollbarDarkShadowColor 设置或获取滚动条上滑槽的颜色。 
scrollbarFaceColor 设置或获取滚动条和滚动条的滚动箭头的颜色。 
scrollbarHighlightColor 设置或获取滚动框和滚动条滚动箭头的左上边缘颜色。 
scrollbarShadowColor 设置或获取滚动框和滚动条滚动箭头的右下边缘颜色。 
scrollbarTrackColor 设置或获取滚动条轨迹元素的颜色。 
scrollDelay 设置或获取字幕滚动的速度。 
scrollHeight 获取对象的滚动高度。 
scrolling 设置或获取框架是否可被滚动。 
scrollLeft 设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离。 
scrollTop 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离。 
scrollWidth 获取对象的滚动宽度。 
search 设置或获取 href 属性中跟在问号后面的部分。 
sectionRowIndex 获取对象位于 tBody, tHead, tFoot 或 rows 集合中的位置。 
SECURITY 获取表明 frame 或 iframe 的源文件是否应用了特定的安全限制的值。 
selected 设置或获取列表框中的选项是否为缺省项目。 
selectedIndex 设置或获取选中选项位于 select 对象中的位置。 
selector 获取标识 @page 规则应用到的页的字符串。 
selectorText 获取标识相应的样式表规则应用到的元素的字符串。 
self 获取对当前窗口或框架的引用。 
shape 设置或获取对象的形状。 
shiftKey 设置或获取 Shift 键的状态。 
shiftLeft 设置或获取左 Shift 键的状态。 
size 设置或获取该对象的字体大小。 
size 设置或获取 hr 对象的高度。 
size 设置或获取控件的大小。 
size 设置或获取列表中的行数。 
sourceIndex 获取对象在源序中的依次位置,即对象出现在 document 的 all 集合中的顺序。 
span 设置或获取组中的列数。 
specified 获取是否指定了该属性。 
src 设置或获取要播放的声音的 URL。 
src 获取包含有源代码或数据的外部文件的 URL。 
src 设置或获取要由对象装入的 URL。 
srcElement 设置或获取触发事件的对象。 
srcFilter 设置或获取触发 onfilterchange 事件的滤镜对象。 
srcUrn 获取触发事件的行为的统一资源名称(URN)。 
standby 设置或获取可用于实现对象的你自己的 standby 功能的字符串。 
start 设置或获取编号列表的起始编号。 
start 设置或获取视频剪辑文件应该开始播放的时间。 
status 设置或获取位于窗口底部状态栏的信息。 
status 设置或获取表明控件是否选中的值。 
STYLE 为该设置元素设置内嵌样式。 
styleFloat 设置或获取文本要绕排到对象的哪一侧。 
summary 设置或获取对象的描述和/或结构。 
systemLanguage 获取操作系统适用的缺省语言。 
tabIndex 设置或获取定义对象的 Tab 顺序的索引。 
tableLayout 设置或获取表明表格布局是否固定的字符串。 
tabStop 设置或获取元素行为是否可收到焦点并参与 Tab 序列。 
tagName 获取对象的标签名称。 
tagUrn 设置或获取在命名空间声明中指定的统一资源名称(URN)。 
target 设置或获取目标内容要显示于哪个窗口或框架。 
text 设置或获取范围内包含的文本。 
text 设置或获取文档主体的文本(前景)颜色。 
text 设置或获取对象文本的字符串形式。 
text 设置或获取由 option 标签指定的字符串。 
textAlign 设置或获取对象中的文本是左对齐、右对齐、居中对齐还是两端对齐。 
textAlignLast 设置或获取如何排列对象的最后一行或仅有的一行。 
textAutospace 设置或获取自动留空和文本的窄空间宽度调整。 
textDecoration 设置或获取对象中的文本是否有闪烁、删除线、上划线或下划线的样式。 
textDecorationBlink 设置或获取表明对象的 textDecoration 属性是否含有有“blink”的 Boolean 值。 
textDecorationLineThrough 设置或获取表明对象内的文本是否有删除线的 Boolean 值。 
textDecorationNone 设置或获取表明对象的 textDecoration 属性是否设置为 none 的 Boolean 值。 
textDecorationOverline 设置或获取表明对象中的文本是否有上划线的 Boolean 值。 
textDecorationUnderline 设置或获取对象中的文本是否有下划线的 Boolean 值。 
textIndent 设置或获取对象中文本的缩进。 
textJustify 设置或获取对象内的文本所使用的对齐类型。 
textKashidaSpace 设置或获取对象内文本对齐行时所使用空白扩展的 kashida 扩展的倍率。 
textOverflow 设置或获取表明是否显示省略号以表明文本溢出的值。 
textTransform 设置或获取对象中文本的渲染方式。 
textUnderlinePosition 设置或获取对象的 textDecoration 属性中设置的下划线的位置。 
tFoot 获取表格的 tFoot 对象。 
tHead 获取表格的 tHead 对象。 
title 设置或获取样式表的标题。 
title 设置或获取对象的咨询信息(工具提示)。 
toElement 设置或获取用户要将鼠标指针移动指向的对象的引用。 
top 设置或获取对象相对于文档层次中下个定位对象的上边界的位置。 
top 获取最顶层的祖先窗口。 
top 设置或获取围绕对象内容的矩形上边坐标。 
topMargin 设置或获取页面的上边距。 
trueSpeed 设置或获取字幕的位置是否使用 scrollDelay 和 scrollAmount 属性计算,已过的实际时间来自于时钟计时。 
type 设置或获取列表的样式。 
type 获取选中区的类型。 
type 获取样式表编写所用的样式表(CSS)语言。 
type 获取按钮的分类和缺省行为。 
type 从 event 对象中获取事件名称。 
type 设置或获取对象的 MIME 类型。 
type 获取样式表编写所用的样式表(CSS)语言。 
type 获取或初始设置对象所代表的 input 控件类型。 
type 设置或获取关联的脚本引擎的 MIME 类型。 
type 根据 MULTIPLE 属性的值获取 select 控件的类型。 
type 获取控件类型。 
type 设置或获取 value 标签属性指明的资源内容类型。 
typeDetail 获取选中区类型的名称。 
unicodeBidi 设置或获取关于双向法则的嵌入级别。 
uniqueID 获取为对象自动生成的唯一标识符。 
units 设置或获取 embed 对象的高度和宽度单位。 
UNSELECTABLE 指定该元素不可被选中。 
updateInterval 设置或获取屏幕的更新间隔。 
URL 设置或获取当前文档的 URL。 
URLUnencoded 获取文档的 URL,去除所有字符编码。 
urn 设置或获取目标文档的 URN。 
useMap 设置或获取用于客户端图像映射的 URL,通常带有一个书签扩展(#name)。 
userAgent 获取等同于 HTTP 用户代理请求头的字符串。 
userLanguage 获取操作系统的自然语言设置。 
vAlign 设置或获取标题是表格的上面还是下面。 
vAlign 设置或获取文本和其它内容在对象内的垂直方向上如何排列。 
value 获取或设置 textArea 元素字段中的文本。 
value 获取控件的缺省或选中值。 
value 设置或获取列表项目的值。 
value 设置或获取当表单控件提交时返回给服务器的值。 
value 设置或获取控件对象的显示值。当控件对象提交时此值将返回给服务器。 
value 设置或获取元素的输入参数值。 
value 当文本通过用户输入设置后获取 input 对象的文件名。 
value 设置或获取对象的值。 
valueType 设置或获取 value 标签属性的数据类型。 
vcard_name 设置或获取对象的 vCard 值,以便用于自动完成框。 
version 设置或获取管理当前文档的文档类型定义(DTD)版本。 
verticalAlign 设置或获取对象的垂直排列。 
viewInheritStyle 设置或获取表明文档片段是否继承主文档中设置的 CSS 样式的值。 
viewLink 设置或获取给主元素提供内容的 document 对象。 
viewMasterTab 设置或获取表明 viewlink 的主元素是否包含在主文档的 Tab 序列中的值。 
visibility 设置或获取对象的内容是否显示。 
vLink 设置或获取对象中已访问链接的颜色。 
vlinkColor 设置或获取用户已访问过的链接颜色。 
volume 设置或获取声音的音量设置。 
vspace 设置或获取对象的垂直边距。 
wheelDelta 设置或获取滚轮按钮滚动的距离和方向。 
whiteSpace 设置或获取对象中是否自动换行。 
width 获取屏幕的垂直分辨率。 
width 设置或获取对象的计算宽度。 
width 设置或获取对象的宽度。 
width 设置或获取对象的宽度。 
width 设置或获取可用于实现对象的你自己的 width 功能的字符串。 
wordBreak 设置或获取单词内的换行行为,特别是对象中出现多语言的情况。 
wordSpacing 设置或获取对象中单词间的附加空间总量。 
wordWrap 设置或获取当内容超过其容器边界时是否断词。 
wrap 设置或获取如何处理对象中的自动换行。 
writingMode 设置或获取对象内容的方向和绕排。 
x 设置或获取鼠标指针位置相对于父文档的 x 像素坐标。 
XMLDocument 获取对由对象引出的的 XML 文档对象模型(DOM)的引用。 
XMLNS 声明 HTML 文档中自定义标签的命名空间。 
XSLDocument 获取对 XSL 文档的顶层结点的引用。 
y 设置或获取鼠标指针位置相对于父文档的 y 像素坐标。 
zIndex 设置或获取定位对象的堆叠次序。 
zoom 设置或获取对象的放大比例。
posted @ 2008-01-11 15:31 雨中漫步的太阳 阅读(39) 评论(0)  编辑

  由于Linux的开放性,极大激发了程序员的创造力,使得以Linux为作业平台的新技术不断出现。Server Push(推技术)就是其中一例。它可在完全不增加成本的基础上,使网站达到最佳的性能。本文将对其进行详细介绍。

  一、环境配置

  为了在Linux下更充分领略Server Push的功能,在运行环境上,我们需进行一些选择。

  1.WWW服务器

  首先要在Linux上安装Apache,以便能自由编译功能模块,这样可以充分使用Server Push、FastCGI、EPerl和PHP等新的扩展功能。

  2.脚本支持

  笔者推荐用Perl或C语言来写CGI脚本,因为Perl已经是CGI脚本程序事实上的标准。而且在Perl 5中已经可以直接调用 C子程序而不需要任何声明。不管你用什么语言来写CGI脚本,解释器中应该有CGI.PM模块,笔者试用的版本是 5.004,这一模块的更新版大家可以从网上下载。

  二、程序实例及函数剖析

  好了,有了上面的工具,下面我们就来写一个Server Push程序来说明它的实现过程: 

!/usr/bin/perl
    
use CGI qw/:push -nph/;
    $
| = 1;
    
print multipart—init(-boundary=〉′--boundary′);
    
while (1) {
    
print multipart—start(-type=〉′text/plain′),
    ″The current 
time is ″,scalar(localtime),″″,
    multipart—end;
    
sleep 1;
    }

  
 
  程序第二行告诉CGI解释程序来调用支持Server Push 的功能模块(CGI.PM),在这个模块中预先定义了三个函数:multipart—init()、multipart—start()和multipart—end,只要在程序中有use CGI qw/:push -nph/声明,就可以直接使用这三个函数。

 multipart—init()函数的作用是声明一个文档类型,就像普通的CGI程序中的“Content-Type: text/html”声明,告诉服务器下面传送的是HTML文档,而multipart—init()这一函数声明的文件类型却是实现Server Push最根本的方法类型:    Content-Type: multipart/x-mixed-replace; boundary=′--boundary′

  如果你对HTTP的MIME类型有详细的了解,你就知道multipart 类型是一种复合类型,它的子类型是mixed,子类型的X参数,大家可以参看详细的MIME类型说明,这里最关键的是replace方法,它不停地用新接收的数据更新旧的数据,这就是 Server Push最大的技术内涵。boundary只是一个边界值,告诉浏览器从这儿开始,使用Server Push方法了。其实你完全可以这样理解,只要在脚本程序中声明了如multipart/x-mixed-replace 这样一个文档类型,服务器就和客户机建立了一个特别的连接。服务器就不断地把客户机请求的数据源源不断地推向了客户机。而传统的 Client PULL方法则是:

  1.Client 和Server建立连接;

  2.Client发送请求到Server;

  3.Server响应请求;

  4.Server 断开连接以响应下一请求。

  通过这两种方法的比较,大家可以看出Server Push优点主要在于服务器和客户机之间这种不间断的连接方式,使它不需要采用Client PULL的〈META http-equiv=refresh content=″n″〉这种方法来刷新页面,不仅更新速度快,而且不会产生闪动效果。

  如果你不用multipart—init()而直接在脚本程序中用以下语句也可以达到同样目的:print ″Content-Type: multipart/x-mixed-replace; boundary=′boundary′ ″。当系统不支持multipart—init()函数时,就可以直接这样声明。

 multipart—start() 这个函数是为服务器指定了传送一个确定的文档,如果不用这个函数,根据脚本程序的内容服务器可以直接把指定数据传送给客户机,当然客户机不能识别这种类型的文档可以忽略而不会产生错误。但如果你指明了具体的文档类型,如例程中的text/plain(纯文本类型),客户机就不再对文档加以分析,从而提高了处理速度,否则客户机只知道传送过来的是 multipart(复合型)而要重新对其分析。  

  至于multipart—end函数不需作详细说明,只是说明了一个 Push过程的结束。  

  为了使大家能更好地理解这三个函数详细的技术内容,笔者把这三个函数的实现过程介绍给大家:    sub multipart—init {
    my($self,@p) = self—or—default(@—);
    my($boundary,@other) = $self-〉rearrange([BOUNDARY],@p);
    $boundary = $boundary || ′------- =—aaaaaaaaaa0′;
    $self-〉{′separator′} = ″
--$boundary
″;
    $type = Server—Push($boundary);
    return $self-〉header(
    -nph =〉 1,
    -type =〉 $type,
    (map { split ″=″, $—, 2 } @other),
    ) . $self-〉multipart—end;
    }
    sub multipart—start {
    my($self,@p) = self—or—default(@—);
    my($type,@other) = $self-〉rearrange([TYPE],@p);
    $type = $type || ′text/html′;
    return $self-〉header(
    -type =〉 $type,
    (map { split ″=″, $—, 2 } @other),
    );
    }
    sub multipart—end {
    my($self,@p) = self—or—default(@—);
    return $self-〉{′separator′};
    }

 

  三、应用技巧

  使用Server Push的其它技巧,限于篇幅,笔者不再作过多的介绍。不过有时由于客户机在一段时间内没有对服务器发生请求,也就是若一段时间内没有新的内容向浏览器输入,可能发生连接超时现象,用下面的程序来处理一下就能很好地解决:    $message=1;
    $whilecount=1;
    do {
      主程序;
      $message++;
      }
    if ($whilecount == 30)
    {
    print ″〈SCRIPT〉$message〈/SCRIPT〉1512″;
    $whilecount = 0;
    }
    $whilecount++;
    sleep 1;

  这种技巧大家一看就明白了,正如很多 FTP软件的Loop一样,在空闲时发一个空信号,不让程序进入等待状态。这段程序每过30秒就给客户机输出一行〈SCRIPT〉$message〈/SCRIPT〉,而$message是数值1、2、3等,这一行在浏览器浏览时并不显示任何内容,让浏览者感觉不到。

posted @ 2008-01-10 08:43 雨中漫步的太阳 阅读(54) 评论(0)  编辑

JSON 为一种更轻、更友好的 Web services客户端的格式(多采用浏览器的形式或访问 REST风格 Web服务的Ajax应用程序的形式)

JSON和XML一样也是一种简单文本格式。相对于XML,它更加易读、更便于肉眼检查。在语法的层面上,JSON与其他格式的区别是在于分隔数据的字符,JSON中的分隔符限于单引号、小括号、中括号、大括号、冒号和逗号

JSON实例{"addressbook": {"name": "Mary Lebow",
    "address": {
        "street": "5 Main Street"
        "city": "San Diego, CA",
        "zip": 91912,
    },
    "phoneNumbers": [
        "619 332-3452",
        "664 223-4667"
    ]
}
}
乍看上去,使用JSON的数据分隔符的优点可能并不那么明显,但存在一个根本性的缘由:它们简化了数据访问。使用这些数据分隔符时, JavaScript引擎对数据结构(如字符串、数组、对象)的内部表示恰好与这些符号相同。

JSON的另一个优点是它的非冗长性。在XML中,打开和关闭标记是必需的,这样才能满足标记的依从性;而在JSON中,所有这些要求只需通过一个简单的括号即可满足。在包含有数以百计字段的数据交换中,传统的XML标记将会延长数据交换时间。目前还没有正式的研究表明JSON比XML有更高的线上传输效率;人们只是通过简单的字节数比较发现,对于等效的JSON和XML有效负载,前者总是小于后者。至于它们之间的差距有多大,特别是在新的XML压缩格式下它们的差距有多大,有待进一步的研究。

  这将开创一条比DOM技术更为便捷的数据访问途径。下面列举几个JavaScript代码片段来说明这一过程,这些代码片段会访问先前的JSON代码片段中的信息:

  • 访问JSON中的名称: addressbook.name
  • 访问JSON中的地址: addressbook.address.street
  • 访问JSON中的电话号码第一位:addressbook.address.phoneNumbers[0]


和许多好东西都具有两面性一样,JSON的非冗长性也不例外,为此JSON丢失了XML具有的一些特性。命名空间允许不同上下文中的相同的信息段彼此混合,然而,显然在JSON中已经找不到了命名空间。JSON与XML的另一个差别是属性的差异,由于JSON采用冒号赋值,这将导致当XML转化为JSON时,在标识符(XML CDATA)与实际属性值之间很难区分谁应该被当作文本考虑。

posted @ 2008-01-08 15:21 雨中漫步的太阳 阅读(3572) 评论(0)  编辑

prototype的Ajax.Updater可以用来更新一段html,但在更新带javascript的html时,需要注意几个问题

. 需要在Ajax.Updater添加参数 evalScripts : true

. javascript代码块要使用下面的形式
showHi = function() {
    alert('Hi');
}

而不能使用下面的形式
function showHi() {
    alert('Hi');
}

. 注意javascript代码块中不能使用 <!-- //--> 标记,否则 IE 会出错,firefox没问题。

posted @ 2008-01-08 14:43 雨中漫步的太阳 阅读(437) 评论(0)  编辑
posted @ 2008-01-05 20:01 雨中漫步的太阳 阅读(13) 评论(0)  编辑