具有极佳用户体验的无刷新实时在线编辑功能的实现——Web系统开发实例

实时在线编辑,Ajax交互,.net技术,Web系统开发,信息管理系统

随着Ajax技术的发展和成熟,要进行页面无刷新的数据交互已经并不是什么困难的事情。然而,如何使用该技术与web系统更好的融合并提升用户体验仍然是一个值得探讨的话题。完全从头编写和开发前端的Ajax交互的js脚本,似乎工作量和难度都较大,编写相应的js脚本时还需要考虑到浏览器兼容性问题,开发和测试过程都很容易影响到项目的进度。网上可用的Ajax套件也不少,比如基于jquery的ajax控件或基于Yahoo UI的扩展包yui-ext都可以实现这样的功能。由于以上工具包都实现了完整的ajax交互并且还附带一些其它常规的脚本控制功能而显得较为庞大,对于需要开发一些轻量级的、要具备较高效率的系统来说似乎是“杀鸡焉用牛刀”了。

我们这里所要介绍的是基于.net技术的页面无刷新实时交互功能的实现,其实在.net框架下只需使用少量的脚本便可以实现页面的无刷新交互功能,无需其它的ajax控件的支持。

以信息管理系统中对作者信息的在线实时编辑为例来进行说明,示例图片如图1,我们需要实时修改的是第4条信息中的名为“张学荣”的作者信息。

我们想要实现的效果是:双击该信息的单元格,该单元格出现可编辑的文本框,内容可任意修改,修改完成后在页面其它地方单击即触发该单元格中信息的提交。在系统后台接收修改后的信息,修改数据库中相应的数据,反馈到前台,前台该单元格中的信息更新为修改后的数据,整个过程页面无需刷新。

这里涉及到前后台的配合,在.net框架下,要实现无刷新的信息提交,需要对前台页面和后台程序进行一些设置。以.net2.0版本为例,需要在前台页面相应的文本单元格中绑定数据并添加处理脚本:
<td align="center" id='Aut<%# Eval("ID") %>' ondblclick='OnlineEdit(this,"Aut",<%# Eval("ID") %>)' title='<%# Eval("Author")%>'><%# TextManage.TrimString(Eval("Author").ToString(),4) %></td>

这里对单元格进行了编号,添加了"Aut"前缀并绑定文章ID值以方便脚本读取和功能区分。脚本响应了鼠标双击事件,即ondblclick触发脚本OnlineEdit,其参数分别是当前单元格对象、编辑对象标识名称、当前信息ID值。OnlineEdit的脚本代码如下:

  function OnlineEdit(obj, act, id)
  {
  var tag;
  if(obj.firstChild!=null)
  tag = obj.firstChild.tagName;
  if ((typeof(tag) != "undefined" && tag.toLowerCase() == "input")||flag)
  {
  return;
  }
  var org = obj.innerHTML;
  var val = obj.getAttribute("title");
  var txt = document.createElement("INPUT");
  txt.value = (val == 'N/A') ? '' : val;
  txt.style.width = (obj.clientWidth-6) + "px" ;
  obj.innerHTML = "";
  obj.appendChild(txt);
  txt.focus();
  txt.onkeypress = function(e)
  {
  var evt = Utils.fixEvent(e);
  var obj = Utils.srcElement(e);
  if (evt.keyCode == 13)
  {
  obj.blur();
  return false;
  }
  if (evt.keyCode == 27)
  {
  obj.parentNode.innerHTML = org;
  }
  }
  txt.onblur = function(e)
  {
  var arg=encodeURIComponent(Utils.trim(txt.value))+"$"+act+id;
  EditOnline(arg);
  }
}

简单叙述一下以上脚本的功能:通过当前对象获取原始完整信息,然后在该单元格中绘制一个文本框,文本框的内容即为原始信息(如图2)。对该单元格监听事件onkeypress,即键盘按下事件,如果发现用户按下ESC则返回原始信息取消编辑,若用户按下回车键则触发onblur事件。这里的onblur事件即失去焦点事件,用于提交信息,提交前对信息进行编码,最后通过EditOnline方法向后台异步提交。提交完成服务器返回信息后再调用回调函数EditOnCallback,这也是写入前台页面中的,代码如下:

function EditOnCallback(result)
    {
        var obj=document.getElementById(CurID);
        if(result!="Error")
        {
            obj.removeAttribute("title");
            obj.setAttribute("title",result);
            var w = obj.clientWidth||obj.offsetWidth;
            if(result.length>w/18)
                obj.innerHTML=result.substring(0,w/18)+"...";
            else
                obj.innerHTML=result;
            flag=false;
        }
        else
            obj.innerHTML="<font color='red'>更新失败!</font>";
    }

该函数的作用是获取服务器返回的更新后的信息,判断信息长度,根据要求截断后显示在用户所编辑的单元格中。

为了让前后台能异步交互,就需要在程序页面需要在原有的页面类的基础上再继承ICallbackEventHandler类,这个类的作用就是处理异步信息的提交。除此以外,在后台页面还需要手工编写一些其它的代码:

public void RaiseCallbackEvent(string Id)
    {
          try
          {
              string content = "";
              int index = Id.IndexOf("$");
              if (index != -1)
              {
                  content =System.Web.HttpUtility.UrlDecode(Id.Substring(0, index));
                  Id = Id.Substring(index+1);
              }
              ArticleInfo info =   SysManage.ReadArticleInfo(Convert.ToInt32(Id.Substring(3)));
              using (DataProvider provider = new DataProvider())
              {
    if (Id.IndexOf("Aut") != -1)
                  {
                      info.Author = content;
                      SysManage.ModifyArticle(info, provider);
                      this.a = content;
                  }
   }
          }
          catch (Exception e)
          {
              this.a = "Error";
          }
      }

以上均为异步提交函数的重写代码,这里的实现逻辑是,通过前台提交的数据以"$"符号分隔,符号前为更新的信息内容(由于内容经过前台转码,因此这里需要解码),后为更新的文章ID值。根据该ID值和数据信息更新数据库,然后将更新后的信息内容通过参数this.a返回,如果出错则返回Error。

另外,为了使前后台的数据能通过脚本交互,还需要在前台注入脚本代码,如下:

string str1 = "<script language=\"javascript\">\n//<!--\nfunction EditOnline(Id) \n{ \nif(!flag){\n CurID=Id.substring(Id.indexOf(\"$\")+1);\n flag=true;\n document.getElementById(CurID).innerHTML=\"<font color='Green'>提交中…</font>\";\n " + this.Page.ClientScript.GetCallbackEventReference(this, "Id", "EditOnCallback", null) + ";\n} \n return false;\n}\n//-->\n</script>";
Page.ClientScript.RegisterClientScriptBlock(base.GetType(), "OnlineEdit", str1);

该代码一方面与OnlineEdit(obj, act, id)脚本对接实现信息的提交,另一方面也同时处理正在提交过程中的提交事件,这里显示的是提交状态信息“提交中…”,为了防止信息编辑和提交过程中的逻辑冲突,这里用到了一个起互斥锁作用的变量flag。至此,在线实时编辑信息的功能便完成了,类似的方式还可以实现其它项目的编辑、数据的删除、状态更改等。

(注:本文为 [风影网络工作室] 原创文章,未经书面许可,严禁转载和复制本站的任何信息,违者必究)