【jquery模仿net控件】简单的dropdownlist与datalist

来源:互联网 发布:js实现视频播放 编辑:程序博客网 时间:2024/05/01 09:15

各位大哥晚上好,好久不见。小弟实习了三个月了,由.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、 htmlElementitemTemplate.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、 htmlElementitemTemplate.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>

  

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