JavaScript DOM 学习第二章 编辑文本


Posted in Javascript onFebruary 19, 2010

例子
这个页面就是个例子。点击一个段落,编辑,然后点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)
Javascript 相关文章推荐
JQuery 常用方法基础教程
Feb 06 Javascript
js中reverse函数的用法详解
Dec 26 Javascript
jQuery瀑布流插件Wookmark使用实例
Apr 02 Javascript
node.js+Ajax实现获取HTTP服务器返回数据
Nov 26 Javascript
C++中的string类的用法小结
Aug 07 Javascript
JavaScript九九乘法口诀表的简单实现
Oct 04 Javascript
jquery实现折叠菜单效果【推荐】
Mar 08 Javascript
JavaScript中运算符规则和隐式类型转换示例详解
Sep 06 Javascript
vue+jquery+lodash实现滑动时顶部悬浮固定效果
Apr 28 jQuery
JavaScript常见JSON操作实例分析
Aug 08 Javascript
实例分析编写vue组件方法
Feb 12 Javascript
vue 实现弹窗关闭后刷新效果
Apr 08 Vue.js
JavaScript DOM学习第一章 W3C DOM简介
Feb 19 #Javascript
JavaScript 题型问答有答案参考
Feb 17 #Javascript
JavaScript 学习技巧
Feb 17 #Javascript
JavaScript Timer实现代码
Feb 17 #Javascript
两个比较有用的Javascript工具函数代码
Feb 17 #Javascript
类似GMAIL的Ajax信息反馈显示
Feb 16 #Javascript
JavaScript 10件让人费解的事情
Feb 15 #Javascript
You might like
一个php作的文本留言本的例子(一)
2006/10/09 PHP
从C/C++迁移到PHP——判断字符类型的函数
2006/10/09 PHP
深入探讨<br />和 \r\n两者有什么区别??
2013/06/05 PHP
PHP向浏览器输出内容的4个函数总结
2014/11/17 PHP
thinkPHP5.0框架独立配置与动态配置方法
2017/03/17 PHP
laravel5 Eloquent 实现事务方式
2019/10/21 PHP
纯CSS3实现质感细腻丝滑按钮
2021/03/09 HTML / CSS
新鲜出炉的js tips提示效果
2011/04/03 Javascript
让人期待的2011年度最佳 jQuery 插件分享
2012/03/16 Javascript
javascript判断是否按回车键并解决浏览器之间的差异
2014/05/13 Javascript
使用angular写一个hello world
2015/01/23 Javascript
使用jquery清空、复位整个输入域
2015/04/02 Javascript
JavaScript数据结构与算法之栈与队列
2016/01/29 Javascript
JavaScript+CSS实现的可折叠二级菜单实例
2016/02/29 Javascript
javascript实现下雪效果【实例代码】
2016/05/03 Javascript
JS实现密码框的显示密码和隐藏密码功能示例
2016/12/26 Javascript
Koa项目搭建过程详细记录
2018/04/12 Javascript
vue中vee validate表单校验的几种基本使用
2018/06/25 Javascript
Vue通过Blob对象实现导出Excel功能示例代码
2020/07/31 Javascript
vue 判断两个时间插件结束时间必选大于开始时间的代码
2020/11/04 Javascript
Django自定义分页与bootstrap分页结合
2021/02/22 Python
Python内置模块turtle绘图详解
2017/12/09 Python
python thrift搭建服务端和客户端测试程序
2018/01/17 Python
mac安装pytorch及系统的numpy更新方法
2018/07/26 Python
python使用tornado实现简单爬虫
2018/07/28 Python
示例详解Python3 or Python2 两者之间的差异
2018/08/23 Python
python使用response.read()接收json数据的实例
2018/12/19 Python
python 叠加等边三角形的绘制的实现
2019/08/14 Python
python无序链表删除重复项的方法
2020/01/17 Python
Python ConfigParser模块的使用示例
2020/10/12 Python
GitHub上值得推荐的8个python 项目
2020/10/30 Python
基于html5 canvas实现漫天飞雪效果实例
2014/09/10 HTML / CSS
俄罗斯最大的消费电子连锁零售商:Mvideo
2017/06/25 全球购物
北美最大的参茸药食商城:德成行
2020/12/06 全球购物
关于对大人不礼貌的检讨书
2014/09/29 职场文书
任命通知范文
2015/04/21 职场文书