• 2008-09-21

    编写运行按钮程序笔记 - [web前端]

     

    概要:

    • FF中nodevalue对textarea的不同,节点的访问。
    • FF中实现把内容复制到剪切板
    • FF中实现innerText方法
    • Mozilla__defineGetter__、__defineSetter__方法追加定义

     

    在论坛中我们经常遇到诸如下图的运行按钮

    运行按钮

    如今想要在页面中也实现这样的功能,编写了一段js代码

     

    1.runCode()函数

     

    function runCode(obj)
    {
         var code=obj.form.elements[0].value;
         /* x=obj.parentNode.childNodes;
         for(i=0;i<x.length;i++)
         {
             if(x[i].nodeName=="TEXTAREA")
             {code=x[i].firstChild.nodeValue;
              break;
             }
         }*/
         newWindow= window.open('', "_blank", '');
         newWindow.document.open('text/html', 'replace');
         newWindow.opener = null;//防止更改原页
         newWindow.document.write(code);
         newWindow.document.close();
    }

    首先是获得textarea中的内容,我开始时使用的getElementsById但是当页面中有多个textarea时,要一个一个的传入id就会比较麻烦。想到了this关键字,使用核心Dom方法,有了如下代码:
    x=obj.parentNode.childNodes;
    for(i=0;i<x.length;i++)
    {
    if(x[i].nodeName=="TEXTAREA")
    {code=x[i].firstChild.nodeValue;
    break;
    }
    }

    在IE中运行正确,可在FF中问题就来了。通过nodeValue获得是textarea中的默认内容,无法获得其现行值。
    随改变方向,使用了:obj.form.elements[0].value;利用textarea的value属性。
    剩下的就简单了,利用open方法打开页面,装入代码,然后关闭。

     

    2.copyCode()函数

     

    function copyCode(obj)
    {
        var copyText=obj.form.elements[0].value;
        if (window.clipboardData)
        {
            window.clipboardData.setData("Text", copyText)
        }
        else
        {
            var flashcopier = 'flashcopier';
            if(!document.getElementById(flashcopier))
            {
              var divholder = document.createElement('div');
              divholder.id = flashcopier;
              document.body.appendChild(divholder);
            }
            document.getElementById(flashcopier).innerHTML = '';
            var divinfo = '<embed src="http://rong179.blogbus.com/files/12219139100.swf" FlashVars="clipboard='+encodeURIComponent(copyText)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
            document.getElementById(flashcopier).innerHTML = divinfo;
    }
    //alert('copy成功!');
    }

    在IE中很容易实现,在FF中实现就不是那么容易了,搜索了一下解决方法:
    借助阿里妈妈的复制广告代码到剪贴板的功能,利用一个flash文件实现

     

    3.ShowRunCode()函数

     

    if(navigator.appName.indexOf("Explorer")==-1)
    {HTMLElement.prototype.__defineGetter__
    (
    "innerText",
    function ()
    {
    var anyString = "";

    var childS = this.childNodes;
    for(var i=0; i<childS.length; i++)
    {
    if(childS[i].nodeType==1)
    anyString += childS[i].tagName=="BR" ? '\n' :childS[i].innerText;
    else if(childS[i].nodeType==3)
    anyString += childS[i].nodeValue.replace(/\n/g,"");
    }

    return anyString;
    }
    )
    }
    //替换code代码window.onload=
    function showRunCode()
    {
        var x=document.getElementsByTagName("code");
        for(var i=0;i<x.length;i++)
        {

        //var text=navigator.appName.indexOf("Explorer") > -1?x[i].innerText:x[i].textContent;
        x[i].innerHTML='<form id="code"  method="post" action=""><textarea name="code" id="codetext" cols="70" rows="10">'+x[i].innerText+'</textarea><input type="button" name="start" value="运行代码" onClick="runCode(this)" class="button2" /><input type="button" name="copy" value="复制代码" onClick="copyCode(this)" class="button2" /><span>提示:您可以先修改部分代码再运行</span></form>'
        }
    }

    有 了上面的两个函数,在页面中调用就over了。但是在写日志的时候,每次要加入代码,还得添加form ,textarea那样的标签,太麻烦了。所以就写了这个函数,只要把代码放在<code></code>之间,就搞定了。就像 论坛上的[html][/html],不过比它还是麻烦些,要在页面源码中加入标签。
    主要应用innerText,和innerHtml方法。
    问题又来了,众所周知innerText在FF中不支持的,FF有个方法:textContent。可以实现,但是,textContent有些缺点,比如会把空格,换行符省略掉。尤其是对<br>的处理,使得在页面显示时会显得很乱。
    好在FF中有__defineGetter__、__defineSetter__方法来追加定义。
    最后就是加载了,让页面在载入是执行fresh函数,你肯定会想到onload事件,不错。但是,在实际页面中由于onload要在页面完全装入后才会执 行,而页面有些内容,可能会加载很慢,使得fresh函数会隔很长时间才执行,影响效果。所以,用到了img的onerror事件,在页面靠前的位置插入 如下代码
    <img src="" onerror="fresh()" style="display:none;" />
    就能保证在图像载入出错时,完成函数的加载。

     

    最终效果:


    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <meta http-equiv="Description" content="运行、复制按钮的实现" />
    <meta content="all" name="robots" />
    <meta name="author" content="rong179,rong179@yahoo.cn" />
    <meta name="copyright" content="http://rong179.blogbus.com" />
    <title>运行、复制按钮的实现</title>
    </head>
    <body>
    <div id="container">
    <img src="http://rong179.blogbus.com/files/12218497280.png" />
    </div>
    </body>
    </html>
Top