以前我在Quirksmode网站见过这种代码,后来又在24 Ways网站看到了一个更具Web 2.0风格的方案。这次我将为大家展示两种使用jQuery实现相同功能(甚至更好)的方法。
目标
一个用AJAX(或AHAH)技术设计的页面,访问者无需离开就可以在看到的(x)HTML 页面上编辑内容。
方案
点击需要编辑的文本,变幻出一个带有保存和取消按钮的textarea。修改的部分将通过AHAH传送至服务器端的一个PHP脚本文件,用来更新数据库(MySQL或普通文件)。
演示
在这第一个演示中,我使用了一个id为“editinplace”的div元素。当鼠标划过这里时,背景颜色将变成浅黄色。点击文本将启动一些DOM操作,div元素被一个textarea元素取代–内中包含原先的文本。
点击保存按钮将向服务器端的PHP脚本文件发送新的HTML内容,并重新输出收到的新文本内容(通过 $_POST)。
在真实应用环境下,你还应当添加一个安全性检测,然后才能更新数据库并返回更新后的页面内容,同事告知jQuery执行成功的信息。
但在这个例子中,所有的修改都是成功的,发送给PHP脚本的信息将原封不动的返回到jQuery代码,显示到一个普通的警告窗口里。
解释
开头部分说了很多次了,如果你不想使用jQuery提供的document.ready函数,尽可以选择你自己中意的init()函数。
$(document).ready(function(){ setClickable(); });
页面上第一个被执行的就是这个setClickable()函数。它的任务就是做以下内容:
查找包含id为“editinplace”的div元素,然后告诉jQuery在这些div被点击时执行某些操作。
function setClickable() { $('#editInPlace').click(function() {
读取div内部的HTML代码的任务将交给jQuery的html()函数来完成。这些HTML将会额外添加若干代码以组成textarea里的保存和取消按钮。
var textarea = '<div><textarea rows="10" cols="60">'+$(this).html()+'</textarea>'; var button = '<div><input type="button" value="SAVE" class="saveButton" /> OR <input type="button" value="CANCEL" class="cancelButton" /></div></div>'; var revert = $(this).html();
同样还是这些在div内部找到的HTML代码将会赋值给一个叫做“revert”的变量。这个变量将用来在取消按钮被按下的事件中输出原始文本。
var revert = $( this ). html ( );
jQuery的DOM函数“after”用来将新生的textarea HTML代码放置在我们指定的div元素后。我在后面紧跟着连锁上了一个remove()方法 来移除div元素以节省代码。
$(this).after(textarea+button).remove();
在使用jQuery的时候,我通过对象名来定位保存和取消按钮对象。我指示jQuery在任一按钮按下时触发最后一个函数“saveChanges”。我告诉了jQuery在div元素被点击时做什么事情,但我没有在最后加上分号因为我希望在这个div操作语句后面连锁其他方法。
$('.saveButton').click(function(){saveChanges(this, false);}); $('.cancelButton').click(function(){saveChanges(this, revert);}); })
我再连锁了一个简单的mouseover和mouseout事件,告诉jQuery在鼠标指针掠过我们指定的div元素(id=editInPlace)的时候添加和移除一个对象。
.mouseover(function() { $(this).addClass("editable"); }) .mouseout(function() { $(this).removeClass("editable"); }); };//end of function setClickable
函数“saveChanges”将以按钮对象做为第一个参数,而cancel参数则取两种值,false或者保存在revert变量中的html代码内容。
function saveChanges(obj, cancel) {
如果cancel为假,则函数将保存更改并使用html格式发送给服务器端的php脚本。我在这里使用了jQuery内置的一个DOM函数实现对textarea内容的提取操作:parent()和siblings()。
if(!cancel) { var t = $(obj).parent().siblings(0).val();
DOM基础超出了本系列教程的范围,但在这个应用中我只是告诉了jQuery“对象(保存按钮)有一个父元素(div)。。。去找到它。那个元素拥有一个或多个DOM树同级对象。。。我只想找到其中的第一个。然后提取那个对象的所有内容。”
(稍等。。。如果你对DOM风格的代码不是很熟悉的话,前面我的注释可能并不好理解。我还是建议你之前google一下“DOM java script”或者其他相关的信息。)
这些html赋值给了t变量,现在要通过POST方法把它发送给test2.php。
$.post("test2.php",{ content: t },function(txt){ alert( txt); }); }
如果cancel有一个值,那么必然是保存在revert变量中的原始html内容。所以,在这个时候我希望变量t变为原始html内容。
else { var t = cancel; }
下一步是通过jQuery提供的DOM函数放置一个新的div元素,id为“editInPlace”,在这之后包含了textarea元素。。。然后删除掉这个div元素。
$(obj).parent().parent().after('<div id="editInPlace">'+t+'</div>').remove()
在果壳中,这将告诉jQuery“在DOM树中上跃两次。将HTML代码附在到达位置的对象之后,然后移除那个对象。”
最后,我们再次调用setClickable函数并关闭saveChange()函数。重调setClickable()函数的含义是重新设置onMouseover,onMouseout,和onClick事件到初始状态。
setClickable(); }
第二个示例
第二个方法非常类似但也有点复杂。
没有用到庞大的单独div元素,这个示例将每个段落p标签变换成单独的可编辑区域。
这里的难度在于你如何在向服务器端脚本发送数据时指定正确的段落p标签。
在这里我通过为每个p标签编号并将这个编号一同发送给服务器端的php脚本的方式解决了问题。你会在alert窗口中看到php脚本是如何“知道”哪个p标签里的内容被修改的。
已知的问题
现实的应用中,你在使用类似的功能时首先需要验证更改的内容的合法性,然后才能将数据发送到服务器端。显然在这里我们刻意把这些内容忽略掉了。