JavaScript DOM 学习第二章 编辑文本

 更新时间:2010年02月19日 13:15:13   作者:  
在这一章我会给出一个在CMS里非常有用的更新页面的代码。在任一段落点击鼠标你就可以修改了。完成以后点击按钮,修改的文本就显示了。
例子
这个页面就是个例子。点击一个段落,编辑,然后点Ready。你的修改就会呈现。

问题
遇到的第一个问题是:我想用文本框作为编辑区域。一开始我却把内容放不进文本框去。读者发现Mozilla的一个警告说是只有在文本框放置到文档之后才能设置它的value。
另外,在Mozilla下面内容包装的不是很好。我试了好几种wrap参数,但是结果都不是很好。
最严重的问题就是把修改后的内容发回服务器,这是几乎所有的CMS系统都要做的。读者给了我很多高明巧妙的建议。然而因为不能通过JavaScript完成,所以我也不能提供解决办法。所以也请您不要发邮件告诉你找到了办法:那也许可行,但是我只想要纯JavaScript的不需要服务器端代码的方法。

脚本
复制代码 代码如下:

var editing = false;

if (document.getElementById && document.createElement) {
    var butt = document.createElement('BUTTON');
    var buttext = document.createTextNode('Ready!');
    butt.appendChild(buttext);
    butt.onclick = saveEdit;
}

function catchIt(e) {
    if (editing) return;
    if (!document.getElementById || !document.createElement) return;
    if (!e) var obj = window.event.srcElement;
    else var obj = e.target;
    while (obj.nodeType != 1) {
        obj = obj.parentNode;
    }
    if (obj.tagName == 'TEXTAREA' || obj.tagName == 'A') return;
    while (obj.nodeName != 'P' && obj.nodeName != 'HTML') {
        obj = obj.parentNode;
    }
    if (obj.nodeName == 'HTML') return;
    var x = obj.innerHTML;
    var y = document.createElement('TEXTAREA');
    var z = obj.parentNode;
    z.insertBefore(y,obj);
    z.insertBefore(butt,obj);
    z.removeChild(obj);
    y.value = x;
    y.focus();
    editing = true;
}

function saveEdit() {
    var area = document.getElementsByTagName('TEXTAREA')[0];
    var y = document.createElement('P');
    var z = area.parentNode;
    y.innerHTML = area.value;
    z.insertBefore(y,area);
    z.removeChild(area);
    z.removeChild(document.getElementsByTagName('button')[0]);
    editing = false;
}

document.onclick = catchIt;

解释
我们设置一个editing标志为false。这用来显示用户是否正在编辑段落。当然初始是没有。

var editing=false;

创建一个按钮
然后我们创建一个Radey按钮,后面会需要很多次。这需要一些高级脚本技术,所以先做一些对象检测:

复制代码 代码如下:
if (document.getElementById && document.createElement) {

如果是现代浏览器,则创建按钮:

复制代码 代码如下:
var butt = document.createElement('BUTTON');

他的文本是:

复制代码 代码如下:
var buttext = document.createTextNode('Ready!');

把这个文本添加到按钮上:

复制代码 代码如下:
butt.appendChild(buttext);

然后添加一个onclick事件处理程序:

复制代码 代码如下:
butt.onclick = saveEdit; 2 }

现在按钮就存储在butt里面,需要的时候我们就可以直接引用。

将P转为文本框
稍后我们会为整个页面定义一个onclick事件。所有的这些事件都会发送到catchIt()函数。


复制代码 代码如下:
function catchIt(e){



首先检测用户是否正常编辑段落,如果是,结束函数:

复制代码 代码如下:
if (editing) return;

然后是支持性检测:

复制代码 代码如下:
if (!document.getElementById || !document.createElement) return;

然后寻找事件的源:

复制代码 代码如下:
if (!e) var obj = window.event.srcElement; 2 else var obj = e.target;

现在我们有了事件的源,但是有个问题是Mozilla会认为文本节点是源(而不是我们需要的P节点)。所以如果节点不是标签(nodeType不是1),我们需要向上遍历DOM树:

复制代码 代码如下:
while (obj.nodeType != 1) { 2 obj = obj.parentNode; 3 }

现在我们以一个标签结束。如果这是一个文本框的标签那么用户点击之后就可以编辑了。如果是一个链接的标签那么用户点击之后应该还是作为一个链接来反映的。这两种情况下我们就不需要这个函数了:

复制代码 代码如下:
if (obj.tagName == 'TEXTAREA' || obj.tagName == 'A') return;

我们需要再一次的向上遍历DOM树直到找到P标签或者HTML标签:

复制代码 代码如下:
while (obj.nodeName != 'P' && obj.nodeName != 'HTML') { 2 obj = obj.parentNode; 3 }

如果是HTML标签那么表示用户在段落之外点击的,就结束函数:

复制代码 代码如下:
if (obj.nodeName == 'HTML') return;

经过这个检测我们最终确定用户点击的是我们想要编辑的段落。然后保存段落的innerHTML:

复制代码 代码如下:
var x = obj.innerHTML;

创建一个新的TEXTAREA然后保存:

复制代码 代码如下:
var y = document.createElement('TEXTAREA');

然后找到段落的父节点:

复制代码 代码如下:
var z = obj.parentNode;

现在就成了这样:

            z
            |
  ---------------------------------------
  |    |      |      |   |
 [more] y(TEXTAREA) butt(BUTTON) P  [more]

然后删除段落。现在看起来就好像是文本框和按钮代替了之前的段落。

直到现在,插入文本框之后,我们才能把段落的innerHTML放置在文本框内。Mozilla里面不支持在插入之前给文本框内添加内容。

	y.value = x;

为了用户方便给文本框焦点:

	y.focus();

然后设置editing为true。

	editing = true;
}
将文本框转换为P
当用户点击Ready按钮,就应该反过来了。这个由saveEdit()函数来完成。
function saveEdit() {得到TEXTAREA(这里假设整个页面只有一个TEXTAREA):
    var area = document.getElementsByTagName('TEXTAREA')[0]创建一个新的段落并保存:
复制代码 代码如下:
var y = document.createElement('P');

找到文本框的父元素:新的段落需要添加到那去:
复制代码 代码如下:
var z = area.parentNode;

将文本框的值存储在新的段落里:
复制代码 代码如下:
y.innerHTML = area.value;

然后把新的段落插入在文本框之前:
复制代码 代码如下:
z.insertBefore(y,area);

移除文本框:
复制代码 代码如下:
z.removeChild(area);

移除Ready按钮(同样的,假设页面只有一个按钮):
复制代码 代码如下:
z.removeChild(document.getElementsByTagName('button')[0]);

然后设置editing为false:用户停止编辑:
复制代码 代码如下:
editing = false; 2 }

事件
在函数之外,设置一个整个页面的onclick事件:
复制代码 代码如下:
document.onclick = catchIt;

翻译地址:http://www.quirksmode.org/dom/cms.html
转载请保留以下信息
作者:北玉(tw:@rehawk)

相关文章

  • 网页编辑器ckeditor和ckfinder配置步骤分享

    网页编辑器ckeditor和ckfinder配置步骤分享

    ckeditor+ckfinder配置用法,现在ckeditor是互联网上应用比较广泛的网页编辑器了,这里介绍下配置方法,需要的朋友可以参考下
    2012-05-05
  • 浅谈 javascript 事件处理

    浅谈 javascript 事件处理

    本文向大家简单介绍了javascript的事件处理机制,从事件源,事件操作到事件处理程序都做了简单介绍,并给出了部分示例,这里推荐给大家。
    2015-01-01
  • 详解Javascript 装载和执行

    详解Javascript 装载和执行

    本文主要详细介绍了Javascript 装载和执行,并附上了详细示例,给有需要的小伙伴们参考下吧
    2014-11-11
  • javascript scrollTop正解使用方法

    javascript scrollTop正解使用方法

    本文讲了javascript scrollTop在各种浏览器中使用的不同显示效果及正确使用方法示例
    2013-11-11
  • JavaScript中的Math.atan2()方法使用详解

    JavaScript中的Math.atan2()方法使用详解

    这篇文章主要介绍了JavaScript中的Math.atan2()方法使用详解,是JS入门学习中的基础知识,需要的朋友可以参考下
    2015-06-06
  • Javascript的时间戳和php的时间戳转换注意事项

    Javascript的时间戳和php的时间戳转换注意事项

    需要注意的是js的时间戳是13位,php的时间戳是10位,转换函数如下,感兴趣的朋友可以参考下哈
    2013-04-04
  • JavaScript中的lastIndexOf()方法使用详解

    JavaScript中的lastIndexOf()方法使用详解

    这篇文章主要介绍了JavaScript中的lastIndexOf()方法使用详解,是JS入门学习中的基础知识,需要的朋友可以参考下
    2015-06-06
  • 深入学习JavaScript中的bom

    深入学习JavaScript中的bom

    Bom:浏览器对象模型提供了独立于内容而与浏览器窗口进行交互的对象。描述了与浏览器进行交互的方法和接口,可以对浏览器窗口进行访问和操作,下面我们来一起学习一下吧
    2019-05-05
  • JavaScript显式数据类型转换详解

    JavaScript显式数据类型转换详解

    这篇文章主要介绍了JavaScript显式数据类型转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • JavaScript从原型到原型链深入理解

    JavaScript从原型到原型链深入理解

    这篇文章主要介绍了从原型与原型链开始讲起,如果你想知道构造函数的实例的原型,原型的原型,原型的原型的原型是什么,就来看看这篇文章吧。下面小编就来带大家一起学习一下
    2019-06-06

最新评论