现在的位置: 首页 > easyui > Layout > panel > 正文
jQuery Easyui 源码分析之panel组件(未完)
2014年04月02日 panel, 源码分析 ⁄ 共 3117字 评论数 8 ⁄ 被围观 11,009 views+
文章目录
[隐藏]

在jQuery EasyUI的几个布局组件中,panel组件是基石类组件,直接使用的比较少,但是像layout,accordion,tabs这样上层布局组件均完全依赖panel组件,即便是datagrid,combo等非布局类组件也对panel组件有一定程度的依赖。所以对panel组件的透彻理解程度,直接决定了各位对EasyUI的认识深度。本篇文章将就panel的DOM结构,实现思路等给出分析,最后也会给出一份加有详细注释的code。

panel在框架中位置

我依赖谁

panel组件是基石组件,不依赖任何组件,一笔雕凿吧……

谁依赖我

layout; accordion; combo; tabs; window.

panel组件dom结构

大家都知道,EasyUI的组件都是依赖某个dom生成的,一般我称这个dom为“宿主DOM”,那么panel组件基于宿主dom到底会生成怎样的一个复杂dom结构呢,我们来看看:

  1. <!-- panel组件最外层的容器,样式'panel'是固有的,'myCls'是利用'cls'属性定义的样式 -->
  2. <!-- 这个外层DIV容器没有任何特殊之处,block级元素,静态定位,是一个最普通的块级元素了 -->
  3. <div class="panel myCls">
  4. <!-- panel组件的header部分,'panel-header'是固有样式,'myHeaderCls'是利用'headerCls'属性定义的样式 -->
  5. <!-- header容器也是block级元素,不过其定位方式relative,即相对定位 -->
  6. <!-- 需要注意的是,如果'title'属性为空,panel组件是不会生成header部分的 -->
  7. <div class="panel-header myHeaderCls">
  8. <!-- 文字标题部分 -->
  9. <div class="panel-title panel-with-icon">面板标题</div>
  10. <!-- 用户自定义的工具列表,多个工具,会产生多个这样的DIV -->
  11. <div class="panel-icon icon-save"></div>
  12. <!-- 标题栏自带的工具列表,例如关闭,收起,展开,最小化,最大化这些按钮都在这个节点里面 -->
  13. <div class="panel-tool"></div>
  14. </div>
  15. <!-- panel组件的body部分,'panel-body'是固有样式,'myBodyCls'是利用'bodyCls'属性定义的样式 -->
  16. <!-- body容器也是block级元素,定位方式为静态定位 -->
  17. <!-- 需要注意的是,body容器是panel组件的宿主dom,panel组件的所有dom结构都是从这个节点延伸出去的 -->
  18. <div id="p" class="panel-body myBodyCls" style="width: 472px; height: 142px;" title="" data-options="iconCls:'icon-save'"></div>
  19. </div>

通过panel组件的dom结构,我们很容易看出来:jQuery EasyUI的panel组件实质就是一个默认为“静态块级元素”,其内部生成了“标题部”和“主体部分”,然后“标题部分”默认提供了一些如“最大化”、“最小化”、“展开”、“收起”、“关闭”等功能,而“主体部分”则纯粹是用于展示内容的一个静态块级元素。

panel组件的属性

id属性

该属性算是panel组件的唯一标识,不过并不是必须属性,默认值也是为null,这个属性跟宿主dom的id属性到底是什么关系,如果在"data-options"里面定义的id和宿主dom的id有冲突,最终又会怎么样?为此,我尝试了一下,得出这个结论:

1.宿主dom未定义id属性的话,使用data-options属性定义的id属性并不会写入到宿主dom中,不过通过panel的options方法获取到的id属性是data-options里面定义的id;

2.宿主dom定义id属性的话,使用data-options属性定义的id属性并不会改变宿主dom的id属性,通过panel的options方法获取到的id属性是宿主dom的id值。

title属性

该属性是panel组件的标题,没有什么不好理解的,用于显示在"header部分"的文字标题标题里。值得注意的是,不设置title属性或者title为空的话,panel组件将不会拼装“header部分”。

那么会不会有时候我们不想要文字标题,但是又想要"header部分"的工具条呢?岂不是矛盾了,没关系,设置title为一个空格字符串就可以了,哈哈,猥琐的一笔啊。

iconCls属性

该属性是用于定义panel组件header部分文字标题前要显示的小图标的,图标大小为16x16,引用的样式一般定义在"themes/icon.css"文件里面。

width属性

该属性用于定义"panel组件DOM结构"最外层容器的宽度,对应于“panel组件dom结构”一节的:

  1. <div class="panel myCls">...</div>

需要注意的是,这里的宽度是指box模型里面的:
“左边距 + 左边框 + 左补白 + 宽度 + 左补白 + 左边框 + 左边距”

height属性

该属性用于定义"panel组件DOM结构"最外层容器的高度,类似于width属性,其是指:
“上边距 + 上边框 + 上补白 + 宽度 + 下补白 + 下边框 + 下边距”

left属性

该属性用于定义"panel组件DOM结构"最外层容器css属性里的left值,例如我定义了left属性为100的话,panel组件最外层容器将会产生以下style属性:

...

css里面的left属性到底什么时候才会起作用,请各位看官好好去查查资料,针对静态定位,相对定位,绝对定位三种典型,left和top是如何表现的。

这里我多嘴一下,当css的position属性没有指定或者为"static"的时候,left和top的设置都是不起作用的。而默认的panel最外层容器,恰恰未定义position,也就是说默认情况下,你再怎么设置panel组件的left和top值也不会发生任何偏移的。

关于left和top的话,我似乎说多了,实在不是EasyUI的范畴,只是有很多同学经常会问这个问题,所以提出来说一下,希望以后问这种傻乎乎的问题的人能越来越少……

top属性

该属性用于定义"panel组件DOM结构"最外层容器css属性里的top值,跟left属性基本雷同了,这里就不吐重复的口水了。请大家细读“left属性”一节。

cls属性

该属性用于给"panel组件DOM结构"最外层容器的class属性增加一个样式,注意只是增加,并不覆盖原有样式,比如在前面的panel组件dom结构中,我们就是定义了cls属性值为myCls,当然了,你必须定义myCls样式才会有意义。

headerCls属性

跟cls属性类似,该属性用于给"panel组件DOM结构"header部对应分容器的class属性增加一个样式,也只是增加,比如在前面的panel组件dom结构中,我们就是定义了headerCls属性值为myHeaderCls。

bodyCls属性

跟cls属性类似,该属性用于给"panel组件DOM结构"body部分对应容器的class属性增加一个样式,也只是增加,比如在前面的panel组件dom结构中,我们就是定义了bodyCls属性值为myBodyCls。

style属性
fit属性

目前有 8 条留言 其中:访客:4 条, 博主:3 条 引用: 1

  1. 英子 : 2014年04月22日08:58:47  -49楼 @回复 回复

    请教一个问题,在设置dialog的loadingMessage属性,加载页面时,设置的loadmingMessage没有起作用,还是显示“Loading…”,不知为何?


    • 管理员
      世纪之光 : 2014年04月22日19:25:49  地下1层 @回复 回复

      你是如何设置loadingMessage的呢,是不是有多个地方设置,覆盖了?

      • 英子 : 2014年04月23日08:49:08  地下2层 @回复 回复

        我使用easyui1.3.5版本,在dialog初始化时设置的loadingMessage,我在官方的例子中也测试了一下,同样显示默认值“Loading…”,下面是我测试的例子,但在panel和window中设置该属性生效,只有dialog中不起作用,请高手帮忙?


        • 管理员
          世纪之光 : 2014年04月23日13:30:40  地下3层 @回复 回复

          看了下dialog的源码,内部生成panel的时候没有从宿主DOM获取属性,只是写死了border doSize bodyCls这三个属性,所以设置loadingMessage无效。
          要想可以设置的话,可以修改源码,让内部panel的属性也从宿主DOM获取

          • 英子 : 2014年04月23日14:07:58  地下4层 @回复 回复

            接触easyui时间不长,还望赐教,具体如何修改?


            • 管理员
              世纪之光 : 2014年04月23日19:11:52  地下5层 @回复 回复

              接触时间不长自己也可以多看看代码,这是我改的src/jquery.dialog.js的代码,你自己跟原版的比对一下看看吧,改了哪些地方,为什么这样改:

              1
              2
              3
              4
              5
              6
              7
              8
              9
              10
              11
              12
              13
              14
              15
              16
              17
              18
              19
              20
              21
              22
              23
              24
              25
              26
              27
              28
              29
              30
              31
              32
              33
              34
              35
              36
              37
              38
              39
              40
              41
              42
              43
              44
              45
              46
              47
              48
              49
              50
              51
              52
              53
              54
              55
              56
              57
              58
              59
              60
              61
              62
              63
              64
              65
              66
              67
              68
              69
              70
              71
              72
              73
              74
              75
              76
              77
              78
              79
              80
              81
              82
              83
              84
              85
              86
              87
              88
              89
              90
              91
              92
              93
              94
              95
              96
              97
              98
              99
              100
              101
              102
              103
              104
              105
              106
              107
              108
              109
              110
              111
              112
              113
              114
              115
              116
              117
              118
              119
              120
              121
              122
              123
              124
              125
              126
              127
              128
              129
              130
              131
              132
              133
              134
              135
              136
              137
              138
              139
              140
              141
              142
              143
              144
              145
              146
              147
              148
              149
              150
              151
              152
              153
              154
              155
              156
              157
              158
              159
              160
              161
              162
              163
              164
              165
              166
              167
              168
              169
              170
              171
              172
              173
              174
              175
              176
              177
              178
              179
              180
              181
              182
              183
              184
              185
              186
              187
              188
              189
              190
              191
              192
              193
              194
              195
              196
              197
              198
              199
              200
              201
              202
              203
              204
              205
              206
              207
              208
              209
              210
              211
              
              /**
               * dialog - jQuery EasyUI
               * 
               * Copyright (c) 2009-2013 www.jeasyui.com. All rights reserved.
               *
               * Licensed under the GPL or commercial licenses
               * To use it on other terms please contact us: info@jeasyui.com
               * http://www.gnu.org/licenses/gpl.txt
               * http://www.jeasyui.com/license_commercial.php
               * 
               * Dependencies:
               * 	 window
               *   linkbutton
               * 
               */
              (function($){
              	/**
              	 * wrap dialog and return content panel.
              	 */
              	function wrapDialog(target){
                      var state = $.data(target,'dialog');
                      var opts = state.options;
              		var cp = document.createElement('div');
              		while(target.firstChild){
              			cp.appendChild(target.firstChild);
              		}
              		target.appendChild(cp);
               
              		var contentPanel = $(cp);
              		contentPanel.attr('style', $(target).attr('style'));
              		$(target).removeAttr('style').css('overflow', 'hidden');
              //		contentPanel.panel({
              //			border:false,
              //			doSize:false,
              //			bodyCls:'dialog-content'
              //		});
                      contentPanel.panel($.extend({}, {
                          loadingMessage:opts.loadingMessage
                      },{
                          border:false,
                          doSize:false,
                          bodyCls:'dialog-content'
                      }));
              		return contentPanel;
              	}
               
              	/**
              	 * build the dialog
              	 */
              	function buildDialog(target){
              		var opts = $.data(target, 'dialog').options;
              		var contentPanel = $.data(target, 'dialog').contentPanel;
               
              		if (opts.toolbar){
              			if ($.isArray(opts.toolbar)){
              				$(target).find('div.dialog-toolbar').remove();
              				var toolbar = $('<div class="dialog-toolbar"><table cellspacing="0" cellpadding="0"><tr></tr></table></div>').prependTo(target);
              				var tr = toolbar.find('tr');
              				for(var i=0; i<opts.toolbar.length; i++){
              					var btn = opts.toolbar[i];
              					if (btn == '-'){
              						$('<td><div class="dialog-tool-separator"></div></td>').appendTo(tr);
              					} else {
              						var td = $('<td></td>').appendTo(tr);
              						var tool = $('<a href="javascript:void(0)" rel="nofollow"></a>').appendTo(td);
              						tool[0].onclick = eval(btn.handler || function(){});
              						tool.linkbutton($.extend({}, btn, {
              							plain:true
              						}));
              					}
              				}
              			} else {
              				$(opts.toolbar).addClass('dialog-toolbar').prependTo(target);
              				$(opts.toolbar).show();
              			}
              		} else {
              			$(target).find('div.dialog-toolbar').remove();
              		}
               
              		if (opts.buttons){
              			if ($.isArray(opts.buttons)){
              				$(target).find('div.dialog-button').remove();
              				var buttons = $('<div class="dialog-button"></div>').appendTo(target);
              				for(var i=0; i<opts.buttons.length; i++){
              					var p = opts.buttons[i];
              					var button = $('<a href="javascript:void(0)" rel="nofollow"></a>').appendTo(buttons);
              					if (p.handler) button[0].onclick = p.handler;
              					button.linkbutton(p);
              				}
              			} else {
              				$(opts.buttons).addClass('dialog-button').appendTo(target);
              				$(opts.buttons).show();
              			}
              		} else {
              			$(target).find('div.dialog-button').remove();
              		}
               
              		var tmpHref = opts.href;
              		var tmpContent = opts.content;
              		opts.href = null;
              		opts.content = null;
               
              		contentPanel.panel({
              			closed: opts.closed,
              			cache: opts.cache,
              			href: tmpHref,
              			content: tmpContent,
              			onLoad: function(){
              				if (opts.height == 'auto'){
              					$(target).window('resize');
              				}
              				opts.onLoad.apply(target, arguments);
              			}
              		});
               
              		$(target).window($.extend({}, opts, {
              			onOpen:function(){
              				if (contentPanel.panel('options').closed){
              					contentPanel.panel('open');
              				}
              				if (opts.onOpen) opts.onOpen.call(target);
              			},
              			onResize:function(width, height){
              				var wbody = $(target);
              				contentPanel.panel('panel').show();
              				contentPanel.panel('resize', {
              					width: wbody.width(),
              					height: (height=='auto') ? 'auto' :
              						wbody.height()
              						- wbody.children('div.dialog-toolbar')._outerHeight()
              						- wbody.children('div.dialog-button')._outerHeight()
              				});
               
              				if (opts.onResize) opts.onResize.call(target, width, height);
              			}
              		}));
               
              		opts.href = tmpHref;
              		opts.content = tmpContent;
              	}
               
              	function refresh(target, href){
              		var contentPanel = $.data(target, 'dialog').contentPanel;
              		contentPanel.panel('refresh', href);
              	}
               
              	$.fn.dialog = function(options, param){
              		if (typeof options == 'string'){
              			var method = $.fn.dialog.methods[options];
              			if (method){
              				return method(this, param);
              			} else {
              				return this.window(options, param);
              			}
              		}
               
              		options = options || {};
              		return this.each(function(){
              			var state = $.data(this, 'dialog');
              			if (state){
              				$.extend(state.options, options);
              			} else {
              				$.data(this, 'dialog', {
              					options: $.extend({}, $.fn.dialog.defaults, $.fn.dialog.parseOptions(this), options)
              				});
                              $.data(this, 'dialog').contentPanel = wrapDialog(this);
              			}
              			buildDialog(this);
              		});
              	};
               
              	$.fn.dialog.methods = {
              		options: function(jq){
              			var dopts = $.data(jq[0], 'dialog').options;
              			var popts = jq.panel('options');
              			$.extend(dopts, {
              				closed: popts.closed,
              				collapsed: popts.collapsed,
              				minimized: popts.minimized,
              				maximized: popts.maximized
              			});
              			var contentPanel = $.data(jq[0], 'dialog').contentPanel;
               
              			return dopts;
              		},
              		dialog: function(jq){
              			return jq.window('window');
              		},
              		refresh: function(jq, href){
              			return jq.each(function(){
              				refresh(this, href);
              			});
              		}
              	};
               
              	$.fn.dialog.parseOptions = function(target){
              		return $.extend({}, $.fn.window.parseOptions(target), $.parser.parseOptions(target,['toolbar','buttons']));
              	};
               
              	// Inherited from $.fn.window.defaults.
              	$.fn.dialog.defaults = $.extend({}, $.fn.window.defaults, {
              		title: 'New Dialog',
              		collapsible: false,
              		minimizable: false,
              		maximizable: false,
              		resizable: false,
               
              		toolbar:null,
              		buttons:null
              	});
              })(jQuery);
              • 英子 : 2014年04月24日08:35:21  地下6层 @回复 回复

                谢谢!

给我留言

留言无头像?


×