| Summary: 创建一个可复用的AJAX对话框--一个完成好的例子 |
| Author: Jack Slocum (译者:Frank Cheung) |
| Published: 2007-2-3 14:07:45 |
| Ext Version: yui-ext 0.33 |
Languages: Chinese
|
Contents |
案例介绍随同官方0.33的发布,在礼拜二我贴出了一个新的Image Chooser的范例。本文中,我们将会深入了解chooser的重要代码,希望你能更好地理解如何将多个组件组合成新组件,一个适合你自身程序的组件。
先看看它的界面:
观看例子
它是怎么运作的?下列代码只是显示一个对话框。这个例子我是收集好图片然后插入到一个页面。你也可以填到form字段中,或插入到你喜欢的Rich-text editor,或是其它怎样,任君选择。
var choose = function(btn){ if(!chooser){ chooser = new ImageChooser({ url:'get-images.php', width:515, height:400 }); } chooser.show(btn.getEl(), insertImage); }; btn = new YAHOO.ext.Button('buttons', { text: "Insert Image", handler: choose });
后台是一个读取某个目录下图片的PHP文件,返回一个包含可用图片信息的JSON 。
“as your type”是由JSONVIEW类提供的一个客户端缩略图的排序、分类。稍后我们会继续讨论,先看看dialog。
创建对话框我选择了一个有 BorderLayout的BasicDialog。尽管BorderLayout用在这里有点大材小用,但这能够有机会示范一下LayoutDialog类。
Dialog可以通过autoCreate的选项,允许不存在标记(xhtml makeup)的情况下,被创建起来。
var dlg = new YAHOO.ext.LayoutDialog(config.id || YAHOO.util.Dom.generateId(), { autoCreate: true, minWidth: 400, minHeight: 300, syncHeightBeforeShow: true, shadow: true, fixedcenter: true, center: { autoScroll: false }, east: { split: true, initialSize: 150, minSize: 150, maxSize: 250 } }); dlg.setTitle('Choose an Image'); dlg.getEl().addClass('ychooser-dlg');
按钮注意setDefaultButton()的调用。这强迫默认的按钮在dialong中出现。为使一些快捷键能用起来,这个dialog必须带焦点。当dialog显示时,,默认的方式定义的按钮就带有焦点,因此,不需要特别设置焦点,ESC键就能工作起来。ok按钮是禁止的,因为如果用户没选好图片,是不能够插入图片的。
dlg.setDefaultButton(dlg.addButton('Cancel', dlg.hide, dlg)); this.ok = dlg.addButton('OK', this.doCallback, this); this.ok.disable();
加入Toolbar首先我们创建一个YAHOO.ext.Toolbar的实例,渲染为dialog body元素中的一个div。
然后我们动态创建一些Toolbar的控制项,并绑定一些事件。
this.sortSelect = this.dlg.body.createChild({ tag:'select', children: [ {tag: 'option', value:'name', selected: 'true', html:'Name'}, {tag: 'option', value:'size', html:'File Size'}, {tag: 'option', value:'lastmod', html:'Last Modified'} ] }); this.sortSelect.on('change', this.sortImages, this, true); this.txtFilter = this.dlg.body.createChild({ tag:'input', type:'text', size:'12' });
bufferedListener()是属于0.33版Observable和Element的新东东。它绑定一个事件,通过一定的延迟,缓冲多个触发。这里我们设置500毫秒。也就是说当用户输入时,过了半秒才触发事件。
this.txtFilter.bufferedListener('keyup', this.filter, this, 500);
接着加入东西到Toolbar,和加点用户提示文本。
this.tb.add('Filter:', this.txtFilter.dom, 'separator', 'Sort By:', this.sortSelect.dom);
初始化布局正如我开始所述,一个布局是很简单。首先我们为主区域增加一个主ContentPanel,然后传入toolbar以便让panel/layout 知道那里可以调整大小。使用beginUpdate()和endUpdate(),让layout准备进行一系列的更新,并增加内容的同时保持 layout相互之间的计算。
var layout = dlg.getLayout(); layout.beginUpdate(); var vp = layout.add('center', new YAHOO.ext.ContentPanel(YAHOO.util.Dom.generateId(), { autoCreate : true, toolbar: this.tb, fitToFrame:true })); var dp = layout.add('east', new YAHOO.ext.ContentPanel(YAHOO.util.Dom.generateId(), { autoCreate : true, fitToFrame:true })); layout.endUpdate();
创建DomHelper.Templates这里的模版用于渲染服务器返回的JSON数据。“thumbTemplate”用于渲染由JsonView提供的缩略图;“detailsTemplate”用于渲染你单击后显示详细的内容。两者都经过编译达到最高性能。
this.thumbTemplate = new YAHOO.ext.Template( '<div class="thumb-wrap" id="{name}">' + '<div class="thumb"><img src="{url}" title="{name}"></div>' + '<span>{shortName}</span></div>' ); this.thumbTemplate.compile(); this.detailsTemplate = new YAHOO.ext.Template( '<div class="details"><img src="{url}"><div class="details-info">' + '<b>Image Name:</b>' + '<span>{name}</span>' + '<b>Size:</b>' + '<span>{sizeString}</span>' + '<b>Last Modified:</b>' + '<span>{dateString}</span></div></div>' ); this.detailsTemplate.compile();
创建YAHOO.ext.JsonView我反复唠叨着这个类有多cool,终于有机会在这里大展身手了。
首先,我们创建JsonView实例,传入一个模版给它。选项“singleSelect:true”告知层我们想激活选区并且是某一时间内只激活一个。
this.view = new YAHOO.ext.JsonView(viewBody, this.thumbTemplate, { singleSelect: true, jsonRoot: 'images', emptyText : 'No images match the specified filter' });
接着我们加入事件处理器(event handler)。留意我们又使用bufferedListener(),默认250毫秒的缓冲
this.view.bufferedListener('selectionchange', this.showDetails, this); this.view.on('dblclick', this.doCallback, this, true); this.view.on('loadexception', this.onLoadException, this, true);
如果没有匹配的结果,就指定一个取消选区的文本。
this.view.on('beforeselect', function(view){ return view.getCount() > 0; // returning false cancels the selection });
执行prepareDate()来自定义渲染每个JSON结果
this.view.prepareData = function(data){ data.shortName = data.name.ellipse(15); data.sizeString = formatSize(data.size); data.dateString = new Date(data.lastmod).format("m/d/Y g:i a"); lookup[data.name] = data; return data; };
要在客户端排序和分类Json数据,很是简单!
您只要精通键入这短短三行的代码,便可完成分类(filter)。附加bufferdListener()事件到txtFilter字段然后输入这两行语句。JsonView会自动处理filters之间的排序和创建一个快照snapshot来使得filter更干净。
var filter = this.txtFilter.dom.value; this.view.filter('name', filter);
排序也不难
var p = this.sortSelect.dom.value; this.view.sort(p, p != 'name' ? 'desc' : 'asc');
更多高级应用,请参与jsonview类的文档
接下来呢?这个dialog可以干更多的事情。例如在左边放颗树,又或者用于上传文件。有空的话,我会增加此类功能如果你觉得这是有益的事情。