条目渲染器和ClassFactory的总结

本文介绍如何在Flex中使用DataGridColumn的itemRenderer属性自定义DataGrid的单元格界面,并通过ClassFactory的properties属性实现实例化对象间的通信。
  游戏中时常要用到DataGrid 控件来显示二维结构的数据,为了更好的展示数据,往往需要给DataGrid 控件的单元格定制更丰富的界面,比如在一个DataGrid 的某列的单元格里添加图片、文本或下拉菜单等其他下层控件,这些下层控件我们往往需要用到DataGridColumn的 itemRenderer属性,把一个定义了这些下层控件的类、类路径或一个ClassFactory对象传到这个属性里,以得到一个自定义显示界面的列。
  ClassFactory和 DataGridColumn.itemRenderer 在里面的工作机制在这里不作重点介绍,需要介绍的则是如何使那些自定义的下层控件能与外界沟通,因为这些控件如果只能在定义它的类里面工作,就起不到更大的交互功能了。所以,如何让外界找到他们,会是一个很关键的环节。下面来看看我的做法:
  现在有已有一个DataGrid控件dg ,为了简化说明,as代码只为dg添加了一列。自定义有一个包含了需要在DataGrid控件的某列中显示的下层控件的mxml文件: MyDgColumn.mxml,一下是dg所在的mxml文件的<Script />代码片段:
[code]
<mx:Script>
……
var myDgColumn:DataGridColumn = new DataGridColumn;
var myDgFactory:ClassFactory = new ClassFactory("MyDgColumn");
myDgFactory.properties = {msg:"(*^_^*)"};
myDgColumn.itemRenderer = myDgFactory;
dg.columns = [myDgColumn];
……
</mx:Script>
[/code]

再看看 MyDgColumn.mxml 的代码:

[code]
<?xml version="1.0" encoding="utf-8"?>
<mx:LinkButton xmlns:mx="http://www.adobe.com/2006/mxml" width="30" height="20" label="按钮" click="{onClick(event)}">
<mx:Script>
<![CDATA[
import mx.events.MenuEvent;
public var msg:String = "";
private function onClick(event:MouseEvent):void{
trace(msg);
}
]]>
</mx:Script>
</mx:LinkButton>
[/code]

  运行后点击dg列上的按钮,即可发现能够获取到 MyDgColumn.mxml 中的msg属性,这就实现了一个简单的dg与dg内部控件的交互。通过这个就可以做更复杂的代码了。这里面ClassFactory 的 properties 属性起到了很关键的作用,通过它,当ClassFactory 对象被调用了 newInstance( ) 方法,就会把properties 中相应的属性值设置给 ClassFactory将要实例花的类对象里面,以便达到同一个类生产不同对象的目的。以下是flex 中 ClassFactory的 newInstance方法的实现:
[code]
/**
* Creates a new instance of the <code>generator</code> class,
* with the properties specified by <code>properties</code>.
*
* <p>This method implements the <code>newInstance()</code> method
* of the IFactory interface.</p>
*
* @return The new instance that was created.
*/
public function newInstance():*
{
var instance:Object = new generator();

if (properties != null)
{
for (var p:String in properties)
{
instance[p] = properties[p];
}
}
return instance;
}
[/code]
分析这段代码 (function (factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // Node / CommonJS factory(require('jquery')); } else { // Globals factory(jQuery); } })(function ($) { "use strict"; var Page = function (element, options) { var defaultOption = { pageIndex: 0, pageSize: 10, total: 0, pageBtnCount: 11, showFirstLastBtn: true, isChosen: false, firstBtnText: "首页", lastBtnText: "尾页", prevBtnText: "上一页", nextBtnText: "下一页", loadFirstPage: true, remote: { url: null, params: null, pageParams: null, success: null, beforeSend: null, complete: null, pageIndexName: 'pageIndex', pageSizeName: 'pageSize', totalName: 'total', traditional: false }, pageElementSort: ['$page', '$size', '$jump', '$info'], showInfo: false, infoFormat: '{start} ~ {end} of {total} entires', noInfoText: '0 entires', showJump: false, jumpBtnText: 'Go', showPageSizes: false, pageSizeItems: [5, 10, 15, 20], debug: false } this.$element = $(element); this.$page = $('<ul class="m-pagination-page"></ul>').hide(); this.$size = $('<div class="m-pagination-size"></div>').hide(); this.$jump = $('<div class="m-pagination-jump"></div>').hide(); this.$info = $('<div class="m-pagination-info"></div>').hide(); this.options = $.extend(true, {}, defaultOption, $.fn.pagination.defaults, options); if (options.pageElementSort) { this.options.pageElementSort = options.pageElementSort } else { if ($.fn.pagination.defaults && $.fn.pagination.defaults.pageElementSort) { this.options.pageElementSort = $.fn.pagination.defaults.pageElementSort; } else { this.options.pageElementSort = defaultOption.pageElementSort; } } this.options.pageSizeItems = options.pageSizeItems || (($.fn.pagination.defaults && $.fn.pagination.defaults.pageSizeItems) ? $.fn.pagination.defaults.pageSizeItems : defaultOption.pageSizeItems); this.total = this.options.total; this.currentUrl = this.options.remote.url; this.currentPageIndex = utility.convertInt(this.options.pageIndex); this.currentPageSize = utility.convertInt(this.options.pageSize); this.currentParams = utility.deserializeParams(this.options.remote.params) || {}; this.getLastPageNum = function () { return pagination.core.calLastPageNum(this.total, this.currentPageSize); } if (this.options.remote.success === null) { this.options.remote.success = this.options.remote.callback; } this.init(); } Page.prototype = { getPageIndex: function () { return this.currentPageIndex; }, getPageSize: function () { return this.currentPageSize; }, getParams: function () { return this.currentParams; }, setPageIndex: function (pageIndex) { if (pageIndex !== undefined && pageIndex !== null) { this.currentPageIndex = utility.convertInt(pageIndex); } }, setPageSize: function (pageSize) { if (pageSize !== undefined && pageSize !== null) { this.currentPageSize = utility.convertInt(pageSize); } }, setRemoteUrl: function (url) { if (url) { this.currentUrl = url; } }, setParams: function (params) { if (params) { this.currentParams = utility.deserializeParams(params); } }, render: function (total) { if (total !== undefined && total !== null) { this.total = utility.convertInt(total); } this.renderPagination(); this.debug('pagination rendered'); }, init: function () { this.initHtml(); this.initEvent(); if (this.currentUrl && this.options.loadFirstPage) { this.remote(); } else { this.renderPagination(); } this.debug('pagination inited'); }, initHtml: function () { //init size module var sizeHtml = $('<select class="pager-select" data-page-btn="size"></select>'); for (var i = 0; i < this.options.pageSizeItems.length; i++) { sizeHtml.append('<option value="' + this.options.pageSizeItems[i] + '" ' + (this.currentPageSize == this.options.pageSizeItems[i] ? "selected" : "") + ' >' + this.options.pageSizeItems[i] + '</option>') } sizeHtml.val(this.currentPageSize); this.$size.append(sizeHtml); //init jump module var jumpHtml = '<div class="m-pagination-group"><input data-page-btn="jump" id="data-page-txt" type="text"><button data-page-btn="jump" type="button">' + this.options.jumpBtnText + '</button></div>'; this.$jump.append(jumpHtml); var pageNumber = Math.ceil(this.options.total / this.options.pageSize); $("body").on('keydown', '#data-page-txt', function () { subString($(this)); }).on('keyup', '#data-page-txt', function () { subString($(this)); }); function subString(_this) { var value = _this.val(); if (!(value % 1 === 0) || value == 0) { _this.val(""); } if (value > pageNumber) { alert("该页码不存在"); _this.val(""); } } for (var i = 0; i < this.options.pageElementSort.length; i++) { this.$element.append(this[this.options.pageElementSort[i]]); } if (this.options.isChosen) { // 自定义下拉菜单 $(".pager-select").chosen({ // width: "100%" }); $(".pager-select").trigger("chosen:updated"); } }, initEvent: function () { this.$element .on('click', { page: this }, function (event) { if ($(event.target).is('button')) { if ($(event.target).data('pageBtn') == 'jump') { var $input = event.data.page.$element.find('input[data-page-btn=jump]'); event.data.page.jumpEventHandler($input.val(), event); } } else { if ($(event.target).data('pageIndex') !== undefined) eventHandler.call(event.data.page, event); } }).on('change', { page: this }, function (event) { var $this = $(event.target); if ($this.data('pageBtn') == 'jump') { event.data.page.jumpEventHandler($this.val(), event); } if ($this.data('pageBtn') == 'size') { eventHandler.call(event.data.page, event); } }).on('keypress', { page: this }, function (event) { if (event.keyCode == "13") { var $input = event.data.page.$element.find('input[data-page-btn=jump]') event.data.page.jumpEventHandler($input.val(), event); } }); }, jumpEventHandler: function (inputValue, event) { if (!inputValue) { this.$jump.removeClass('error'); } else if (!pagination.check.checkJumpPage(inputValue)) { this.$jump.addClass('error'); } else if (utility.convertInt(inputValue) > this.getLastPageNum()) { this.$jump.addClass('error'); } else { this.$jump.removeClass('error'); eventHandler.call(this, event); } }, doPagination: function () { if (this.currentUrl) { this.remote(); } else { this.renderPagination(); } }, remote: function () { if (typeof this.options.remote.pageParams === 'function') { var pageParams = this.options.remote.pageParams.call(this, { pageIndex: this.currentPageIndex, pageSize: this.currentPageSize }); this.currentParams = $.extend({}, this.currentParams, pageParams); } else { this.currentParams[this.options.remote.pageIndexName] = this.currentPageIndex; this.currentParams[this.options.remote.pageSizeName] = this.currentPageSize; } pagination.remote.getAjax(this, this.currentUrl, this.currentParams, this.ajaxCallBack, this.options.remote.beforeSend, this.options.remote.complete, this.options.remote.traditional); }, ajaxCallBack: function (result) { var total = utility.mapObjectNameRecursion(result, this.options.remote.totalName); if (total == null || total == undefined) throw new Error("the response of totalName : '" + this.options.remote.totalName + "' not found."); total = utility.convertInt(total); this.total = total; var lastPageNum = this.getLastPageNum(); if (this.currentPageIndex > 0 && lastPageNum - 1 < this.currentPageIndex) { this.setPageIndex(lastPageNum - 1); this.remote(); } else { if (typeof this.options.remote.success === 'function') this.options.remote.success(result); this.renderPagination(); } }, onEvent: function (eventName, pageIndex, pageSize) { if (pageIndex != null) this.currentPageIndex = utility.convertInt(pageIndex); if (pageSize != null) this.currentPageSize = utility.convertInt(pageSize); this.doPagination(); this.$element.trigger(eventName, { pageIndex: this.currentPageIndex, pageSize: this.currentPageSize }); this.debug('pagination ' + eventName); }, //生成分页 renderPagination: function () { var option = { showFirstLastBtn: this.options.showFirstLastBtn, firstBtnText: this.options.firstBtnText, prevBtnText: this.options.prevBtnText, nextBtnText: this.options.nextBtnText, lastBtnText: this.options.lastBtnText } var lastPageNum = this.getLastPageNum(); this.currentPageIndex = lastPageNum > 0 && this.currentPageIndex > lastPageNum - 1 ? lastPageNum - 1 : this.currentPageIndex; this.$page.empty().append(pagination.core.renderPages(this.currentPageIndex, this.currentPageSize, this.total, this.options.pageBtnCount, option)).show(); if (this.options.showPageSizes && lastPageNum !== 0) this.$size.show(); else this.$size.hide(); if (this.options.showJump && lastPageNum !== 0) this.$jump.show(); else this.$jump.hide(); this.$info.html(pagination.core.renderInfo(this.currentPageIndex, this.currentPageSize, this.total, this.options.infoFormat, this.options.noInfoText)); if (this.options.showInfo) this.$info.show(); else this.$info.hide(); }, //销毁分页 destroy: function () { this.$element.unbind().data("pagination", null).empty(); this.debug('pagination destroyed'); }, debug: function (message, data) { // if (this.options.debug && console) { // message && console.info(message + ' : pageIndex = ' + this.currentPageIndex + ' , pageSize = ' + this.currentPageSize + ' , total = ' + this.total); // data && console.info(data); // } } } var eventHandler = function (event) { var that = event.data.page; var $target = $(event.target); if (event.type === 'click' && $target.data('pageIndex') !== undefined && !$target.parent().hasClass('active')) { that.onEvent(pagination.event.pageClicked, $target.data("pageIndex"), null); } else if ((event.type === 'click' || event.type === 'keypress') && $target.data('pageBtn') === 'jump') { var pageIndexStr = that.$jump.find('input').val(); if (utility.convertInt(pageIndexStr) <= that.getLastPageNum()) { that.onEvent(pagination.event.jumpClicked, pageIndexStr - 1, null); that.$jump.find('input').val(null); } } else if (event.type === 'change' && $target.data('pageBtn') === 'size') { var newPageSize = that.$size.find('select').val(); var lastPageNum = pagination.core.calLastPageNum(that.total, newPageSize); if (lastPageNum > 0 && that.currentPageIndex > lastPageNum - 1) { that.currentPageIndex = lastPageNum - 1; } that.onEvent(pagination.event.pageSizeChanged, that.currentPageIndex, newPageSize); } }; var pagination = {}; pagination.event = { pageClicked: 'pageClicked', jumpClicked: 'jumpClicked', pageSizeChanged: 'pageSizeChanged' }; pagination.remote = { getAjax: function (pagination, url, data, success, beforeSend, complate, traditional) { $.ajax({ url: url, dataType: 'json', type: "POST", data: data, cache: false, traditional: traditional, contentType: 'application/Json', beforeSend: function (XMLHttpRequest) { if (typeof beforeSend === 'function') beforeSend.call(this, XMLHttpRequest); }, complete: function (XMLHttpRequest, textStatue) { if (typeof complate === 'function') complate.call(this, XMLHttpRequest, textStatue); }, success: function (result) { success.call(pagination, result); } }) } }; pagination.core = { /* options : { showFirstLastBtn firstBtnText: } */ renderPages: function (pageIndex, pageSize, total, pageBtnCount, options) { options = options || {}; var pageNumber = pageIndex + 1; var lastPageNumber = this.calLastPageNum(total, pageSize); var html = []; if (lastPageNumber <= pageBtnCount) { html = this.renderGroupPages(1, lastPageNumber, pageNumber); } else { var firstPage = this.renderPerPage(options.firstBtnText || 1, 0); var lastPage = this.renderPerPage(options.lastBtnText || lastPageNumber, lastPageNumber - 1); //button count of both sides var symmetryBtnCount = (pageBtnCount - 1 - 4) / 2; if (!options.showFirstLastBtn) symmetryBtnCount = symmetryBtnCount + 1; var frontBtnNum = (pageBtnCount + 1) / 2; var behindBtnNum = lastPageNumber - ((pageBtnCount + 1) / 2); var prevPage = this.renderPerPage(options.prevBtnText, pageIndex - 1); var nextPage = this.renderPerPage(options.nextBtnText, pageIndex + 1); symmetryBtnCount = symmetryBtnCount.toString().indexOf('.') == -1 ? symmetryBtnCount : symmetryBtnCount + 0.5; frontBtnNum = frontBtnNum.toString().indexOf('.') == -1 ? frontBtnNum : frontBtnNum + 0.5; behindBtnNum = behindBtnNum.toString().indexOf('.') == -1 ? behindBtnNum : behindBtnNum + 0.5; if (pageNumber < frontBtnNum) { if (options.showFirstLastBtn) { html = this.renderGroupPages(1, pageBtnCount - 2, pageNumber); html.push(nextPage); html.push(lastPage); } else { html = this.renderGroupPages(1, pageBtnCount - 1, pageNumber); html.push(nextPage); } } else if (pageNumber > behindBtnNum) { if (options.showFirstLastBtn) { html = this.renderGroupPages(lastPageNumber - pageBtnCount + 3, pageBtnCount - 2, pageNumber); html.unshift(prevPage); html.unshift(firstPage); } else { html = this.renderGroupPages(lastPageNumber - pageBtnCount + 2, pageBtnCount - 1, pageNumber); html.unshift(prevPage); } } else { if (options.showFirstLastBtn) { html = this.renderGroupPages(pageNumber - symmetryBtnCount, pageBtnCount - 4, pageNumber); html.unshift(prevPage); html.push(nextPage); html.unshift(firstPage); html.push(lastPage); } else { html = this.renderGroupPages(pageNumber - symmetryBtnCount, pageBtnCount - 2, pageNumber); html.unshift(prevPage); html.push(nextPage); } } } return html; }, renderGroupPages: function (beginPageNum, count, currentPage) { var html = []; for (var i = 0; i < count; i++) { var page = this.renderPerPage(beginPageNum, beginPageNum - 1); if (beginPageNum === currentPage) page.addClass("active"); html.push(page); beginPageNum++; } return html; }, renderPerPage: function (text, value) { return $("<li><a data-page-index='" + value + "'>" + text + "</a></li>"); }, renderInfo: function (currentPageIndex, currentPageSize, total, infoFormat, noInfoText) { if (total <= 0) { return noInfoText; } else { var startNum = (currentPageIndex * currentPageSize) + 1; var endNum = (currentPageIndex + 1) * currentPageSize; endNum = endNum >= total ? total : endNum; return infoFormat.replace('{start}', startNum).replace('{end}', endNum).replace('{total}', total); } }, //计算最大分页数 calLastPageNum: function (total, pageSize) { total = utility.convertInt(total); pageSize = utility.convertInt(pageSize); var i = total / pageSize; return utility.isDecimal(i) ? parseInt(i) + 1 : i; } }; pagination.check = { //校验跳转页数有效性 checkJumpPage: function (pageIndex) { var reg = /^\+?[1-9][0-9]*$/; return reg.test(pageIndex); } }; var utility = { //转换为int convertInt: function (i) { if (typeof i === 'number') { return i; } else { var j = parseInt(i); if (!isNaN(j)) { return j; } else { throw new Error("convertInt Type Error. Type is " + typeof i + ', value = ' + i); } } }, //返回是否小数 isDecimal: function (i) { return parseInt(i) !== i; }, //匹配对象名称(递归) mapObjectNameRecursion: function (object, name) { var obj = object; var arr = name.split('.'); for (var i = 0; i < arr.length; i++) { obj = utility.mapObjectName(obj, arr[i]); } return obj; }, //匹配对象名称 mapObjectName: function (object, name) { var value = null; for (var i in object) { //过滤原型属性 if (object.hasOwnProperty(i)) { if (i == name) { value = object[i]; break; } } } return value; }, deserializeParams: function (params) { var newParams = {}; if (typeof params === 'string') { var arr = params.split('&'); for (var i = 0; i < arr.length; i++) { var a = arr[i].split('='); newParams[a[0]] = decodeURIComponent(a[1]); } } else if (params instanceof Array) { for (var i = 0; i < params.length; i++) { newParams[params[i].name] = decodeURIComponent(params[i].value); } } else if (typeof params === 'object') { newParams = params; } return newParams; } } $.fn.pagination = function (option) { if (typeof option === 'undefined') { return $(this).data('pagination') || false; } else { var result; var args = arguments; this.each(function () { var $this = $(this); var data = $this.data('pagination'); if (!data && typeof option === 'string') { throw new Error('MricodePagination is uninitialized.'); } else if (data && typeof option === 'object') { throw new Error('MricodePagination is initialized.'); } //初始化 else if (!data && typeof option === 'object') { var options = typeof option == 'object' && option; var data_api_options = $this.data(); options = $.extend(options, data_api_options); $this.data('pagination', (data = new Page(this, options))); } else if (data && typeof option === 'string') { result = data[option].apply(data, Array.prototype.slice.call(args, 1)); } }); return typeof result === 'undefined' ? this : result; } } });
最新发布
10-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值