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 struts 验证唯一标识(公用方法)
Mar 27 Javascript
JQuery Tips相关(1)----关于$.Ready()
Aug 14 Javascript
获取当前月(季度/年)的最后一天(set相关操作及应用)
Dec 27 Javascript
jquery获取select,option所有的value和text的实例
Mar 06 Javascript
vue中七牛插件使用的实例代码
Jul 28 Javascript
vue实现手机号码抽奖上下滚动动画示例
Oct 18 Javascript
vue的传参方式汇总和router使用技巧
May 22 Javascript
详解angular脏检查原理及伪代码实现
Jun 08 Javascript
在小程序中集成redux/immutable/thunk第三方库的方法
Aug 12 Javascript
javascript将扁平的数据转为树形结构的高效率算法
Feb 27 Javascript
uin-app+mockjs实现本地数据模拟
Aug 26 Javascript
js实现模拟购物商城案例
May 18 Javascript
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/11/19 PHP
PHP常见字符串处理函数用法示例【转换,转义,截取,比较,查找,反转,切割】
2016/12/24 PHP
javascript 密码强弱度检测万能插件
2009/02/25 Javascript
用jquery ajax获取网站Alexa排名的代码
2009/12/12 Javascript
腾讯UED 漂亮的提示信息效果代码
2011/09/12 Javascript
javascript学习笔记(十九) 节点的操作实现代码
2012/06/20 Javascript
jQuery源码中的chunker 正则过滤符分析
2012/07/31 Javascript
js获取html文件的思路及示例
2013/09/17 Javascript
JavaScript的setAttribute兼容性问题解决方法
2013/11/11 Javascript
使表格的标题列可左右拉伸jquery插件封装
2014/11/24 Javascript
jQuery选择器之基本选择器与层次选择器
2015/03/03 Javascript
JavaScript Window浏览器对象模型方法与属性汇总
2015/04/20 Javascript
js实现滑动触屏事件监听的方法
2015/05/05 Javascript
Bootstrap每天必学之响应式导航、轮播图
2016/04/25 Javascript
纯css下拉菜单 无需js
2016/08/15 Javascript
微信小程序 教程之wxapp视图容器 swiper
2016/10/19 Javascript
Vue数据驱动模拟实现4
2017/01/12 Javascript
详解解决使用axios发送json后台接收不到的问题
2018/06/27 Javascript
基于vue cli 通过命令行传参实现多环境配置
2018/07/12 Javascript
Bootstrap 模态框自定义点击和关闭事件详解
2018/08/10 Javascript
vue-cli3.0 脚手架搭建项目的过程详解
2018/10/19 Javascript
layui-table获得当前行的上/下一行数据的例子
2019/09/24 Javascript
element日历calendar组件上月、今天、下月、日历块点击事件及模板源码
2020/07/27 Javascript
[51:29]Alliance vs TNC 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
利用Hyperic调用Python实现进程守护
2018/01/02 Python
Pycharm新建模板默认添加个人信息的实例
2019/07/15 Python
python操作redis数据库的三种方法
2020/09/10 Python
python实现定时发送邮件
2020/12/23 Python
美国领先的精品家居照明和装饰产品在线零售商:LightsOnline.com
2018/01/23 全球购物
萨克斯第五大道英国:Saks Fifth Avenue英国
2019/04/01 全球购物
旅游管理专业生自荐信范文
2014/01/02 职场文书
开会迟到检讨书
2014/02/03 职场文书
建筑施工安全责任书
2014/07/24 职场文书
艺术节开幕词
2015/01/28 职场文书
处罚决定书范文
2015/06/24 职场文书
Python中递归以及递归遍历目录详解
2021/10/24 Python