【jquery模仿net控件】简单的dropdownlist与datalist
来源:广州中睿信息技术有限公司官网
发布时间:2012/10/21 23:25:16 编辑:admin 阅读 465
各位大哥晚上好,好久不见。小弟实习了三个月了,由.net转成了java,工作期间正在努力学习。但是有一点非常痛苦,我不止一次听到一个声音,&rdquo.net真的很简单,我原来也学过。直接拖就是了.

各位大哥晚上好,好久不见。小弟实习了三个月了,由.net转成了java,工作期间正在努力学习。

但是有一点非常痛苦,我不止一次听到一个声音,”.net真的很简单,我原来也学过。直接拖就是了......“

啊!!!感觉好没有技术含量啊!莫法,小弟技术不行,无力辩驳什么。

并且就技术层次本身来说,不论我确实还有很多路要走,就不多说了。

起因


 

我们最近在做一个项目,其中核心模块需要用到类似于igoogle中那种小工具的功能,当时经过众人商议,

最后决定用jquery写控件。

控件!!!好机会啊!我发现项目需要的功能和.net中的datalist真的非常像,于是很想插进去.......

但是,我那浅薄的水平,以及我那悲剧的实习生头衔,在其他同事面前确实不大说得上话。

最后眼睁睁看着别人写了1more js代码,然后让我去读。

呵呵,不是那个前辈代码写的不好,相反我在他的代码中学了很多东西,当然是带着极其抵触的情绪在努力的看!

总觉得这也不好,那也不好,甚至有时候在抠人家命名规范的问题,总是想推翻一点加上自己的思路......

说到这里,我深刻的感觉团队合作,团队交流,团队协作真的很重要!

 你有一个想法,你要如何表达自己的思路,如何写出代码,如何让别人接受你的想法,接受你的代码,

甚至让别人帮助你充实你的想法,真的是一门大学问!

你若是做了一个东西,确实不错,但是你不表现的谦虚,其他同事必定不会买账,根本不会认同你的想法。

而且,一个你觉得很好的点子,在人家的分析后,肯定会发现很多问题,那就要看你如何获得人家的认同与帮助了!

 

项目过程


 

就那前辈的代码,我其实发现了一些问题,项目过程中他的代码也确实遇到了一点问题,主要原因就是代码除他之外,没人想去动。

然后站在设计模式的高度来看,他的代码可维护性,可扩展性有点问题,当然我设计模式看了一次也忘得车不多了。

最后在学习前辈的代码,再加上.net控件思路的高度,我自己花了点时间写了两个控件模拟.net中的dropdownlist与datalist。

再次交出代码,抛砖引玉,请各位大哥弄点更好的东西出来吧!!!

因为我也是才学js,代码写的不好,请各位大哥提点下吧!

Dropdownlist


 

一、效果图()

因为这个控件是练手的,我需要的是datalist,所以就算起一个探索作用,没有写太多。

其功能就算想模拟.net中的控件,根据不同数据源,生成不同的代码。

最主要是想把事件控制权交出来,让使用这个控件的人不用去关注控件本身,(这也是前辈的主要问题)

二、简单代码

 核心代码:

 

var item = function (value, text) {      this.attribute = {          id: '',          value: value ? value : '',          text: text ? text : '',          title: '',          selected: ''      };      this.htmlElement = null;      this.callBack = {          onClick: null      };  }    item.prototype.bindEvent = function () {      var sender = this;      //    alert(sender.dataSource);      var element = sender.htmlElement;      if (sender.callBack.onClick) {          element.unbind("click");          element.bind("click", function () {              sender.callBack.onClick.call(sender);          });      }  }    var dropDownList = function (id) {      this.attribute = {          id: id      };      this.style = {          width: '',          height: ''      };      this.callBack = {          onSelectedChanged: null,          onClick:null      };      this.htmlElement = null;      this.items = [];      this.selectedValue = '';      this.selectedItem = {};      this.dataSourceType = '';      this.dataSource = {}; //应该支持不同数据源      this.dataTextField = '';      this.dataValueField = '';      this.dataTitleField = '';  }    dropDownList.prototype.bindEvent = function () {      var sender = this;      //    alert(sender.dataSource);      var element = sender.htmlElement;      if (sender.callBack.onSelectedChanged) {          element.unbind("change");          element.bind("change", function () {              sender.callBack.onSelectedChanged.call(sender);          });      }      if (sender.callBack.onClick) {          element.unbind("click");          element.bind("click", function () {              sender.callBack.onClick.call(sender);          });      }  }  dropDownList.prototype.dataBind = function (element) {      var sender = this;      sender.htmlElement = $('<select id="' + sender["attribute"]["id"] + '"></select>');        $.each(sender.dataSource, function (itemKey, itemValue) {          //        alert(itemKey + ":" + itemValue);          var _item = new item();          _item["attribute"]['value'] = itemValue[sender['dataValueField']];          _item["attribute"]['text'] = itemValue[sender['dataTextField']];          _item["attribute"]['title'] = itemValue[sender['dataTitleField']];          sender.items.push(_item);          sender.insertItem(_item);      });      //呈现前,样式加载      sender.styleLoad();      element.append(sender.htmlElement);  }    dropDownList.prototype.styleLoad = function () {      var sender = this;      var element = sender.htmlElement;      $.each(sender["style"], function (styleKey, styleValue) {          //        alert(styleKey + ":" + styleValue);          if (styleValue) {              element.css(styleKey, styleValue);          }      });  }    dropDownList.prototype.insertItem = function (optionItem) {      var sender = this;      var element = sender.htmlElement;      var itemSender = optionItem;      //    alert(element["id"]);      var option = $('<option></option>');      var optrinAtrribute = optionItem["attribute"];      var id = optrinAtrribute["id"];      var value = optrinAtrribute["value"];      var text = optrinAtrribute["text"];      var title = optrinAtrribute["title"];      var selected = optrinAtrribute["selected"];      if (id && id.length > 0) {          option.attr("id", id);      }      if (value && value.length > 0) {          option.attr("value", value);      }      if (title && title.length > 0) {          option.attr("title", title);      }      if (selected && selected.length > 0) {          option.attr("selected", selected);      }      if (text && text.length > 0) {          option.text(text);      }      itemSender.htmlElement = option;      element.append(option);  }  

  

前端调用:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="http://www.w3.org/1999/xhtml">  <head>      <title></title>      <script src="scripts/jquery-1.4.1.js" type="text/javascript"></script>      <script src="js/dropDownList.js" type="text/javascript"></script>      <script type="text/javascript">          $(document).ready(function () {              var data = [];              for (var i = 0; i < 3; i++) {                  data[i] = {};                  data[i]["v"] = "value_" + i.toString();                  data[i]["t"] = "text_" + i.toString();              }                var $div = $("#divwl");              var drop1 = new dropDownList("drop1");                drop1.dataSource = data;              drop1.dataValueField = "v";              drop1.dataTextField = "t";              drop1.dataTitleField = "v";              drop1.dataBind($div);                for (var i = 0; i < 3; i++) {                  var v = "inertValue_" + i;                  var t = "insertText_" + i;                  var _item = new item(v, t);                  drop1.insertItem(_item);              }              drop1.style.width = '300px';              drop1.style.height = '50px';              drop1.style.background = 'green';              drop1.styleLoad();              var funClick = function () {                  var dropSender = this.htmlElement;                  var selectedValue = dropSender.val()                  var $div = $("#text");                  $div.html(selectedValue);              };              var funChange = function () {                  var dropSender = this.htmlElement;                  var selectedValue = dropSender.val()                  alert(selectedValue);              };                drop1.items[1].callBack.onClick = funClick;              drop1.items[1].bindEvent();                drop1.callBack.onSelectedChanged = funChange;              drop1.bindEvent();            });              </script>  </head>  <body>      <div id="divwl">      </div>      <div id="text"> </div>        </body>  </html>  

  

 

Datalist


 

 好了,开始进入本文重点,这也是项目真正需要的,这个版本没有完全完成,在得到大家意见后再改吧!

 一、效果图:

 所用数据源:

二、思路

 原来也读过.net 控件开发一书,对控件开发知识有个大概了解,所以做起来时候还是比较顺手。

① datalist首先提供了一个公共的模板,就是itemtemplate中可以写任何代码包括数据绑定代码,

然后依次循环调用,所以我觉得这个控件需要一个模板保存类似于.net中的html代码,以及数据绑定代码。

当然,我们不可能写在js代码中,于是出现了一下模板文件:

itemTemplate.spt:

<table>    <tr>      <td>        新闻ID      </td>      <td>        {%newsId%}      </td>    </tr>    <tr  >      <td >        新闻标题      </td>      <td>        {%newsName%}      </td>    </tr>    <tr  >      <td>        新闻摘要      </td>      <td>        <input  id="contentMore" value="详情" type="button"/>      </td>    </tr>    <tr  >      <td colspan="2" style=" display:none;" class="content">        {%newsContent%}      </td>    </tr>  </table>  <hr/>  

  {%newsName%} 是模拟Eval("")的写法,后期作为数据绑定使用

② 然后每次循环生成具体的模板js代码如下:itemTemplate.js

/// <reference path="../scripts/jquery-1.4.1.js" />    var itemTemplate = function () {      //源模板文本,现在为itemTemplate.spt      //可能是文本,可能是js文件,可能是字符串      //最终形成字符串传给htmlTemplateText      this.htmlTemplateText = "";      //最终会形成一独立html字符串,dom结构的标签      this.htmlElement = null;      this.idPrefix = "id_"; //id前缀      this.parentId = "";      this.id = "";      this.event = {          onClick: null,          onMousemove: null      };      //将要执行      //    this.evetElementSource = {};      this.elementEvent = null;  };  itemTemplate.prototype.getItemElement = function (elementKey) {      var sender = this;      var id = "#" + sender.id + " " + elementKey;      var element = $(id);      return element;  }  //elementKey #id、 .className、 htmlElement  itemTemplate.prototype.bindElementEvent = function (elementKey, eventType, funcName) {      var sender = this;      var id = "#" + sender.id + " " + elementKey;      var element = $(id);        if (funcName) {          element.unbind(eventType);          element.bind(eventType, function () {              funcName.call(sender);          });      }  }    //elementKey #id、 .className、 htmlElement  itemTemplate.prototype.bindAllElementEvent = function () {      var sender = this;      var itemElementEvents = sender.elementEvent;      //    alert(element+"=="+id);      //数据项元素事件绑定      $.each(itemElementEvents, function (eventObjKey, eventObj) {          var elementKey = eventObj.elementKey;          var eventType = eventObj.eventType;          var funcName = eventObj.funcName;          sender.bindElementEvent(elementKey, eventType, funcName);      });  }    itemTemplate.prototype.bindEvent = function () {      var sender = this;      var element = sender.htmlElement;      var events = sender.event;      $.each(events, function (eventKey, funcName) {          //        alert(funcKey + "---" + funcValue);          if (funcName) {              var _event = eventKey;              _event = _event.substring(2, _event.length);              _event = _event.toLowerCase();              element.unbind(_event);              element.bind(_event, function () {                  funcName.call(sender);              });          }      });  };    itemTemplate.prototype.load = function (itemIndex, itemDataSource) {      var sender = this;      var id = sender.parentId + "_" + sender.idPrefix + itemIndex;      sender.id = id;      var element = $("<div id='" + id + "'></div>");      var html = "";      var _templateText = sender.htmlTemplateText;      tempHtm = _templateText;      $.each(itemDataSource, function (i, item) {          var id = item;          var regStr = "/\\{%" + i + "%\\}/g";          var reg = eval(regStr);          tempHtm = tempHtm.replace(reg, item);      });      html = tempHtm;      element.append($(html))      sender.htmlElement = element;      sender.bindEvent();    };  

  

 技术细节便不说了,其主要采用正则表达式方式替换相应内容,所以完全根据我们提供的数据源而定:

③ 外层datalist代码:dataList.js

/// <reference path="../scripts/jquery-1.4.1.js" />    /*  思考:  1 如何给数据项某个html标签添加事件  因为我们并不知道生成的dom树是什么,所以模板里面的html标签无法绑定事件,暂时只能后期绑定    */  /* 控件生成流程    */    var dataList = function (id, templateUrl) {      this.attribute = {          id: id      };      this.style = {          width: "",          height: ""      };      this.itemEvent = {          onClick: null,          onDblclick: null,          onKeydown: null,          onKeypress: null,          onKeyup: null,          onMousedown: null,          onMousemove: null,          onMouseout: null,          onMouseover: null,          onMouseup: null      };      this.itemElementEvent = {};      //    this.itemElementEvent = {      //        one: {      //            elementKey: "",      //            eventType: "",      //            funcName: null      //        }      //    };        this.htmlElement = null;      this.templateUrl = templateUrl ? templateUrl : ""; //提供项目模板地址      this.htmlTemplateText = "";      this.items = [];      this.dataSource = {}; //应该支持不同数据源  };    dataList.prototype.init = function () {      var sender = this;      var templateUrl = sender.templateUrl;      if (!templateUrl || templateUrl.length == 0)          templateUrl = "itemTemplate/itemTemplate.spt";      this.htmlTemplateText = getAjaxStr(templateUrl);      var htmlElement = $("<div id='" + sender.attribute.id + "'></div>");      sender.htmlElement = htmlElement;  };    dataList.prototype.dataBind = function (element) {      this.init();      var sender = this;      var templateText = sender.htmlTemplateText;      var itemEvent = sender.itemEvent;      var itemElementEvents = sender.itemElementEvent;      //需要替换itemTemplate      var itemIndex = 0;      $.each(sender.dataSource, function (dataKey, dataValue) {          var _item = new itemTemplate();          _item.parentId = sender.attribute.id;          _item.htmlTemplateText = templateText;          _item.event = itemEvent;          _item.elementEvent = itemElementEvents;          //传递父ID ,当前模板编号,源模板,当前项数据项源,事件绑定源          _item.load(itemIndex, dataValue);          var _itemElement = _item.htmlElement;          sender.items.push(_item);          sender.insertDomItem(_itemElement);          itemIndex++;      });      //呈现前,样式加载      sender.styleLoad();      element.append(sender.htmlElement);      //模板中的html标签的事件绑定      var items = sender.items;      $.each(items, function (i, item) {          item.bindAllElementEvent();      });  };    dataList.prototype.styleLoad = function () {      var sender = this;      var element = sender.htmlElement;      $.each(sender.style, function (styleKey, styleValue) {          //                alert(styleKey + ":" + styleValue);          if (styleValue) {              //            alert(element);              element.css(styleKey, styleValue);          }      });  }    dataList.prototype.insertDomItem = function (domItem) {      var sender = this;      var element = sender.htmlElement;      element.append(domItem);  };  //dataList.prototype.bindItemEvent = function (domItem) {  //    var sender = this;  //    var element = sender.htmlElement;  //    element.append(domItem);  //};  //dataList.prototype.bindEvent = function () {  //    var sender = this;  //    var element = sender.htmlElement;  //    var events = sender["event"];  //    $.each(events, function (eventKey, funcName) {  //        //        alert(funcKey + "---" + funcValue);  //        if (funcName) {  //            var _event = eventKey;  //            _event = _event.substring(2, _event.length);  //            _event = _event.toLowerCase();  //            element.unbind(_event);  //            element.bind(_event, function () {  //                funcName.call(sender);  //            });  //        }  //    });  //};    //异步获取文件  function getAjaxStr(url) {      var templateStr = "";      $.ajax({          url: url,          async: false,          dataType: "html",          success: function (result) {              templateStr = result;              if (templateStr)                  return templateStr;          },          error: function (e) {              alert("模板加载错误:" + e.toString());          }      });      return templateStr;  }  

  

③ 前台调用界面代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="http://www.w3.org/1999/xhtml">  <head>      <title></title>      <script src="scripts/jquery-1.4.1.js" type="text/javascript"></script>      <script src="js/itemTemplate.js" type="text/javascript"></script>      <script src="js/dataList.js" type="text/javascript"></script>      <script type="text/javascript">          $(document).ready(function () {              var dataSource = {};              $.ajax({                  type: "post",                  url: "Ajax.aspx",                  type: "json",                  async: false,                  success: function (data) {                      dataSource = data;                  }              });              var $divHtml = $("#html");                  var $div = $("#wl");              var $div1 = $("#wl1");              var itemElementEvents = {                  contentClick: {                      elementKey: "#contentMore",                      eventType: "click",                      funcName: contentMoreClick                  }              };                var list = new dataList("divwl");              list.itemEvent.onMousemove = itemmousemove;              list.itemEvent.onMouseout = itemmouseout;                list.itemElementEvent = itemElementEvents;              list.style.width = "700px";              list.dataSource = dataSource;              list.dataBind($div);                    function contentMoreClick() {                  var sender = this;                  var newsContent = sender.getItemElement(".content");                  var contentMore = sender.getItemElement("#contentMore");                  if (newsContent.css("display") == "none") {                      contentMore.attr("value", "隐藏");                      newsContent.css("display", "");                  } else {                      contentMore.attr("value", "详情");                      newsContent.css("display", "none");                  }              }              function itemmousemove() {                  var sender = this;                  var $ee = sender.htmlElement;                  $ee.css("background", "Gray");              }              function itemmouseout() {                  var sender = this;                  var $ee = sender.htmlElement;                  $ee.css("background", "white");              }            });      </script>  </head>  <body>      <div id="html" style="display: block">      </div>      <div id="wl">      </div>      <div id="wl1">      </div>  </body>  </html>  

  大概代码如上,看一下调用界面基本知道如何使用的。

在此我有个没有解决的问题,请各位大哥帮下忙:

除模板之中的html dom 结构没有前期事件绑定外,其他生成的dom都是在展现前便绑定事件:

 

 //呈现前,样式加载      sender.styleLoad();      element.append(sender.htmlElement);      //模板中的html标签的事件绑定      var items = sender.items;      $.each(items, function (i, item) {          item.bindAllElementEvent();      });  

  其实这个代码最先是写在itemTemplate.js文件中的,在没有将dom append到页面中,但是因为dom结构没有生成,我无法通过除以上的方法找到

对应html标签,所有无法做事件绑定,这里把我弄模糊了。各位大哥有兴趣看了代码便和我说说吧,代码会跟进。

 

今天又更新了一点代码,有点变化,现在先弄上datalist嵌套的用法,具体的代码后面点看有没有需要弄出来

效果:其实就是新闻类型嵌套一个新闻列表

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="http://www.w3.org/1999/xhtml">  <head>      <title></title>      <script src="scripts/jquery-1.4.1.js" type="text/javascript"></script>      <script src="js/itemTemplate.js" type="text/javascript"></script>      <script src="js/dataList.js" type="text/javascript"></script>      <script type="text/javascript">          $(document).ready(function () {              var dataItems = {};              $.ajax({                  type: "post",                  url: "Ajax.aspx?sql=select top 5 * from Item where ItemKind=1 ",                  type: "json",                  async: false,                  success: function (data) {                      dataItems = data;                  }              });              var $div = $("#wl");              var listItem = new dataList("newsItem", "itemTemplate/items.spt");              var itemElementEvents = {                  loadItemNews: {                      elementKey: "#itemNews",                      eventType: "ready",                      funcName: elementDatabind                  }              };              listItem.itemElementEvent = itemElementEvents;                listItem.dataSource = dataItems;              listItem.dataBind($div);                function elementDatabind() {                  var sender = this;                  var $itemId = sender.getItemElement("#itemId");                  var $itemNews = sender.getItemElement("#itemNews");                  var listItemNews = new dataList("news", "itemTemplate/itemTemplate.spt");                  var _itemElementEvents = {                      contentClick: {                          elementKey: "#contentMore",                          eventType: "click",                          funcName: contentMoreClick                      }                  };                  var id = $itemId.html();                  var s = $itemNews.html();                  var dataNews = {};                  $.ajax({                      type: "post",                      url: "Ajax.aspx?sql=select top 3  newsId,newsName, newsContent from news where itemId='" + id + "' ",                      type: "json",                      async: false,                      success: function (data) {                          dataNews = data;                      }                  });                  listItemNews.itemEvent.onMousemove = itemmousemove;                  listItemNews.itemEvent.onMouseout = itemmouseout;                  listItemNews.itemElementEvent = _itemElementEvents;                    listItemNews.dataSource = dataNews;                  listItemNews.dataBind($itemNews);              }                function contentMoreClick() {                  var sender = this;                  var newsContent = sender.getItemElement(".content");                  var contentMore = sender.getItemElement("#contentMore");                  if (newsContent.css("display") == "none") {                      contentMore.attr("value", "隐藏");                      newsContent.css("display", "");                  } else {                      contentMore.attr("value", "详情");                      newsContent.css("display", "none");                  }              }              function itemmousemove() {                  var sender = this;                  var $ee = sender.htmlElement;                  $ee.css("background", "Gray");              }              function itemmouseout() {                  var sender = this;                  var $ee = sender.htmlElement;                  $ee.css("background", "white");              }            });      </script>  </head>  <body>      <div id="wl">      </div>  </body>  </html>  

  

等以后代码完善了,我在整理发出吧。

 

 

 

 

联系我们CONTACT 扫一扫
愿景:成为最专业的软件研发服务领航者
中睿信息技术有限公司 广州•深圳 Tel:020-38931912 务实 Pragmatic
广州:广州市天河区翰景路1号金星大厦18层中睿信息 Fax:020-38931912 专业 Professional
深圳:深圳市福田区车公庙有色金属大厦509~510 Tel:0755-25855012 诚信 Integrity
所有权声明:PMI, PMP, Project Management Professional, PMI-ACP, PMI-PBA和PMBOK是项目管理协会(Project Management Institute, Inc.)的注册标志。
版权所有:广州中睿信息技术有限公司 粤ICP备13082838号-2