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 相关文章推荐
setAttribute 与 class冲突解决
Feb 17 Javascript
JavaScrip单线程引擎工作原理分析
Sep 04 Javascript
jQuery.prototype.init选择器构造函数源码思路分析
Feb 05 Javascript
关于JavaScript中string 的replace
Apr 12 Javascript
固定背景实现的背景滚动特效示例分享
May 19 Javascript
javascript版的in_array函数(判断数组中是否存在特定值)
May 09 Javascript
jQuery实现仿Alipay支付宝首页全屏焦点图切换特效
May 04 Javascript
聊一聊jQuery插件uploadify使用方法
Aug 24 Javascript
JQuery.dataTables表格插件添加跳转到指定页
Jun 09 jQuery
JavaScript实现选中文字提示新浪微博分享效果
Jun 15 Javascript
Angular2环境搭建具体操作步骤(推荐)
Aug 04 Javascript
微信小程序 扭蛋抽奖机css3动画实现详解
Jul 19 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中的string类型使用说明
2010/07/27 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
thinkPHP3.2使用RBAC实现权限管理的实现
2019/08/27 PHP
Javascript 自定义类型方法小结
2010/03/02 Javascript
javascript自定义函数参数传递为字符串格式
2014/07/29 Javascript
JS实现title标题栏文字不间断滚动显示效果
2016/09/07 Javascript
jquery 判断div show的状态实例
2016/12/03 Javascript
javascript 数组去重复(在线去重工具)
2016/12/17 Javascript
微信小程序 action-sheet 反馈上拉菜单简单实例
2017/05/11 Javascript
浅谈vue-cli加载不到dev-server.js的解决办法
2017/11/24 Javascript
微信小程序实现下拉菜单切换效果
2020/03/30 Javascript
你不知道的Vue技巧之--开发一个可以通过方法调用的组件(推荐)
2019/04/15 Javascript
详解webpack打包vue项目之后生成的dist文件该怎么启动运行
2019/09/06 Javascript
JS在Array数组中按指定位置删除或添加元素对象方法示例
2019/11/19 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
2020/02/13 Javascript
微信小程序转化为uni-app项目的方法示例
2020/05/22 Javascript
[01:08:32]DOTA2-DPC中国联赛 正赛 DLG vs PHOENIX BO3 第二场 1月18日
2021/03/11 DOTA
深入理解Javascript中的this关键字
2015/03/27 Python
python读写ini配置文件方法实例分析
2015/06/30 Python
Python在信息学竞赛中的运用及Python的基本用法(详解)
2017/08/15 Python
Python callable()函数用法实例分析
2018/03/17 Python
pytorch训练imagenet分类的方法
2018/07/27 Python
Python 中Django安装和使用教程详解
2019/07/03 Python
基于Python3.7.1无法导入Numpy的解决方式
2020/03/09 Python
美国著名的婴儿学步鞋老品牌:Robeez
2016/08/20 全球购物
华为消费者德国官方网站:HUAWEI德国
2020/11/03 全球购物
C++:局部变量能否和全局变量重名
2014/03/03 面试题
总裁助理岗位职责
2014/02/17 职场文书
工厂门卫的岗位职责
2014/07/27 职场文书
国家领导干部党的群众路线教育实践活动批评与自我批评材料
2014/09/23 职场文书
自主招生推荐信格式模板
2015/03/24 职场文书
趣味运动会新闻稿
2015/07/17 职场文书
python实现ROA算子边缘检测算法
2021/04/05 Python
Redis调用Lua脚本及使用场景快速掌握
2022/03/16 Redis
排查Tomcat进程假死的问题
2022/05/06 Servers
Vue2项目中对百度地图的封装使用详解
2022/06/16 Vue.js