‘UI设计’ 所有文章

关于HTML语义,我也有看法

八月 29th, 2009 由 Rock 发表

目前的HTML语义方式主要靠标签去表达,但有历史局限性,众多的标签也是历史遗留问题,因为未出现CSS之前一个页面是由众多标签+属性,要说语义化,从现在标签使用的角度看来,我想没什么比那个时候的页面更具语义化了. 页面的语义化是必段的,但目前用标签来表达是个鸡肋,因为完全标签表达使整个页面显示累赘,难以维护, 而且,当出现一个新的特性对象时,不得不新创建一个标签,这点倒像英语词汇, 一旦属性多了起来, 如颜色,位置,大小等更具个性化的东西标签都难以充分表达.

记得以前看过一句与语义化相关的话,”不要让 CSS 使一个 HTML 元素看起来就像另一个 HTML 元素,比如用<div>来代替<p>标记标题”,我当时就觉得奇怪了,CSS能充分表达元素的外观甚至行为,CSS更能表示页面的语义化.理想角度看来,依靠CSS用最少量元素就能够很好表达页面,外观与内容能够很好的分离,感觉像P这些元素就像多余的!现在看来 — 上面也提过,造成目前还依赖标签表达是由局限性造成的.因为语义是主要给计算机识别的,而不是人!人不用去看这些标签和页面背后的东西,直接看页面最终效果就能一目了然, 但计算机还没这么智能,相信计算机能够直观上”看”得明在相当长一段时间是实现不了的了,而在计算机领域内语义又主要是给爬虫识别的,(这里的爬虫泛指一切信息收集并解析程序, 并不单单指收集,还包含解析),而当下最著明的爬虫就是搜索引擎的爬虫了.但目前的搜索引擎在数据收集分析时显然很笨,它只能从页面的标签上解析和关键字去了解这页面大概是干嘛的,很多与页面相关个性化的东西收集不到,因为这些东西隐藏在CSS样式之后,搜索引擎还没那么聪明,所以目前,我们只能够在保持页面结构清晰的前提下尽量用相关的标签去”提醒”爬虫留意页面的不同要素的内容,归根到底还是有人工干预了!

不过没办法,就像浏览器发展缓慢一样,严重跟不上其它技术的发展.

建立基本的页面框架 — 第二步丰富西部面板

七月 29th, 2009 由 Rock 发表

最近有点忙,打算上周写完这篇的,但近几天来几乎没碰过电脑了..非常难得少见的一次-_-!!

上次讲了创建页面框架最基本的一步:利用简单有效的BorderLayoutd布局管理器作为整体的客户区域中南西北中布局,总体框架出来了,但具体的面板内容还比较空虚(或许是寂寞更适合点^-^),这一节讲解怎么利用库来丰富页面框架中西部面板.

西部面板一般是放分组菜单,可同时加入多个分组,分组可以是一个树控件,或列表控件,宽度不大,把这些分组看成行状放置,可以用库的行布局管理器布局这些分组.

库中目前的行布局管理器共有两个,CRowLayout类和CRowLayout2类,它们对容器子控件布置方式不同之处主要体现在控件的position属性,前者是static布置,后者是absolute,各有各的优点,这里主要讲解一下第二个,即CRowLayout2布局管理器,因为它比较适合用来布置西部面板.

RowLayout2布局管理器

RowLayout2布局方式与BorderLayout极为相似,纯JavaScript计算方式布局子控件,同样有分隔条.RowLayout2把子控件由上而下布局,每个子控件宽度与容器宽度一致,它们高度与分隔条高度之和始终等于容器高度,除最下边一个行组控件没分隔条外,其它的组都允许有分隔条灵活控制分组高度,而且当容器宽度改变时,各分组将获得均等的高度份额.

利用RowLayout2布局管理器布局西部面板的分组

要指定面板布局管理器为RowLayout2只需设置容器面板的layout属性为’row2′即可,非常简单!

  //此时西部面板的布局设为RowLayout2
  var westPanel = new CPanel({view : 'westPanel', width:191, maxW:450, layout:'row2'});

布局管理器已经生成了,下面来为面部面板添加两个分组,为了好看点,这两个分组都用CTitlePanel类控件,即具有标题栏的面板,并且其内容可以收缩或展开.

  var firstTitlePanel = new CTitlePanel({title:'顶部面板' ,height:210});
  westPanel.add(firstTitlePanel, {split:true});

上面那个高度:120只是提示布局管理器最好用这个高度来设置控件高度,实际中RowLayout2布局管理器设定的并一定是这个,视布局取用的策略而定.
add方法的第二个参数是该控件用于布局管理器布局的配置信息,这里split:true向RowLayout2指明该分组有可拖动的分隔条.
添加了一个标题栏面板控件,再往这面板里面添加分组内容,这里加的是库中的一个组控件.

  //增加一个组控件
  var f = CUtil.createFolder({title:'My Folders', array:[
    {title:'收件箱',icon:'icoIbx'},
    {title:'发件箱',icon:'icoDft'},
    {title:'草稿箱',icon:'icoNote'},
    {title:'清除记录',icon:'icoDel',disabled:true},
    {title:'粉红色',icon:'icoDft'},
    {title:'蓝色',icon:'icoNote'},
    {title:'清除记录',icon:'icoDel'}
 ]});
 
  //指定组f的滚动面板为firstTitilePanel,
  //这样组内选择后的子项会自动滚动到可视范围内.
  f.scrollor = firstTitlePanel;
 
 //添加到标题栏面板中
firstTitlePanel.add(f);

第二个分组是一个树型控件,添加方式与上面一致,只是由组控件换成树型控件.

  var secondTitlePanel = new CTitlePanel({title:'树型面板' });
  westPanel.add(secondTitlePanel);
  //往标题栏面板中增加一个树型控件 
  //先要创建根结点
  var tree1Root = new CTreeItem({
     //nodes=true说明是一个有子结点的结点
    nodes: true
   });
 
  var tree = new CTree({
      root: tree1Root,
      title: '树根目录',
      //加上下面两句就可以利用ajax加载子结点了
      //url:'/q?bg_q=test_group', 
      //autoConnect:true
   });
 
   tree.scrollor = secondTitlePanel;
   secondTitlePanel.add(tree);

同样道理,无需额外的工作,就可以添加任意多个分组,这里就不一一列出了.

演示地址:http://www.bgscript.com/bgjs/samples/basicframe2.html

利用库制作EXTJS Tab控件

七月 12th, 2009 由 Rock 发表

上次用利库制作EXTJS 菜单后,试着实现EXT的Tab控件,
样式直接引入ext-all.css, 利用库代码实现也简单,准备好HTML模板后,派生背光JS库原有控件类。

//Ext TabItem类, 继承库CTabItem类
CC.create('CExtTabItem', CTabItem, {
  //鼠标悬停样式
  hoverCS: 'x-tab-strip-over',
  //视图html模板
  template: 'CExtTabItem',
  //取消父类默认的拖放功能 
  ondropable: false,
  draggable: false,
  //设置正确的图标结点
  iconNode: '_tle',
  //关闭结点
  closeNode: '_trigger',
  //当存在图标时视图的样式类
  iconCS: 'x-tab-with-icon'
});
 
//Ext Tab实现,继承库CTab类
CC.create('CExtTab', CTab, {
  //子项选择后样式
  selectedCS: 'x-tab-strip-active',
  //子项类
  ItemClass: CExtTabItem,
  template: 'CExtTab',
  //指定视图中容器结点
  container: '_bdy',
 
  //@override
  //重写以自定添加tab项的位置,
  //它并不像像类那样直接放在container结尾,
  //即调用container.appendChild,
  //而是根据ext的tab结构要放_anchor结点(参见模板HTML)之前.
  _addNode: function(itemView) {
    this.container.insertBefore(itemView, this.dom('_anchor'));
  }
});

查看演示:http://www.bgscript.com/bgjs/samples/ext/tab.html

JavaScript日期选择控件

七月 12th, 2009 由 Rock 发表

一个简单,轻量级的日期选择控件实现类,也是背光控件库的默认类,解释一下它的构成和功能。
它继承CPanel类,所以很容易获得阴影效果,在改变位置时阴影也会跟随。

该控件不对日期过滤作过多的处理,但预留了一个接口回调函数,利用该接口可以自定义对日期的过滤。

支持mm/dd/yy,yy-mm-dd等多种格式转换.
日期控件已与表单集成了,CDatepickerField类作为表单元素以提供日期选择,具体可查看演示。

应用也简单,例如

//生成日期选择控件实例
var d = new CDatepicker({value: '2012/12/1',showTo: document.body, autoRender:true});
 
//生成用于表单日期选择的日期选择文本域
var field = new CDatepickerField({showTo: document.body, width: 300, autoRender: true});

查看演示:http://www.bgscript.com/bgjs/samples/datepicker.html

JavaScript - Grid表格控件

七月 6th, 2009 由 Rock 发表

表格控件,
列置换,列宽变,列排序,分组等等.
可自由扩展,如增加列选择,编辑功能等.
查看演示:

http://www.bgscript.com/bgjs/samples/grid.html

JavaScript菜单与菜单外观,行为与HTML模板的灵活定制

六月 26th, 2009 由 Bgser 发表

有人说EXT JS的控件虽然花俏,功能强大,但就外观来说容易产生审美疲劳。效果不错,看久就腻了,不耐看,用户容易转移注意力。

在样式文件上换套主题是可以的,但我觉得这是换汤不换药,比如EXT的主题无论怎么变,界面还是一眼就能看出是不是用它做的。

我看了EXT源码,发现它把控件HTML,CSS类都直接与控件的代码实现连在一起,直接写进构造控件的方法中,所以直接基于原来控件设计功能一样但外观完全不一样的控件是很困难的。
例如,我想将google的菜单换成Ext的菜单,它们功能差不多,现在只有google菜单的实现,如果直接将google菜单换套主题变成Ext的菜单是不大可能的,因为它们HTML上的不同决定了更改主题形成效果的局限性。

基于这目标出发,在UI设计时把视图HTML部分,脚本控制部分与外观CSS部分分离,就可有效的达到这个目标.
最近在库原有菜单类的基础上,通过类继承写少量的代码,实现了EXT菜单,这个过程都是比较简单的.

演示地址:
默认菜单基类
继承并定制Ext菜单

通用Combobox(Select)以至一般控件的设计与实现

六月 14th, 2009 由 Bgser 发表

本文涉及到combobox设计与实现上的一些方法论,并提供了一个参考实现.

Combobox(以下简称combox),也就是通常的意义上的Select控件,最具代表的是html里的select元素,
它可以在有限的空间内提供多个选项给用户选择,这个与菜单十分相似,并作为表单元素将数据提交到服务器.
种种原因使得有时有必要自定义一个combox控件,来代替自带的select,来分析一下html的select有什么基本功能.

>与form集成,字段可提交

>控件禁用或禁用单个选项

>选择,可以指定选择任意项或不选

>键盘导航
支持键盘上下键导航选项,ENTER,ESC键关闭下拉并响应

>滚动
如果列表项过多而下拉空间有限,就应该出现滚动条,
并且在用户选择选项过程中,选项要相应的滚动到可视范围内

>下拉框下拉时定位到可视范围内

>下拉框上下文切换时自动消失
即点击combox外时下拉框自动消失

如果是自定义的combox控件,可扩展功能有

>可编辑或不可编辑

>控件自定事件

>ajax加载
根据响应动态加载项

>过滤
用户在输入过程中过滤条项并自动定位

>定制下拉框
下拉框弹出的内容是可定制的,根据实现需要定制,如一个列表,一颗树,一个表格等

>在定制下拉框后combox的基本行为保持不应
自定下拉框后不能改变控件应用的基本行为,如选择,键导航等

>多样式支持,如控件的hover,点击,下拉时都有不同外观效果,下拉框具有阴影等

如果自定义combox控件,以上的基本功能是要实现的,不同方式有不同实现,越灵活就越不简单,.
现在考虑一个在封闭式环境下的实现,
这所谓的封闭环境是指为特定的需求应用而实现,代码考虑不重用,在响应过程中不与外界进行通讯,功能与控件完全一体化,具有很强的针对性实现,
这种实现较为简单,根据需求可部分实现select功能,有时为了设计与实现上的便利,用到多种的hack.
例如在HTML模板上的设计,可将下拉框的HTML组织在控制自身里,
而不是将下拉框的加在BODY中,这种设计简单明了,下拉定位方便,但也造成下拉框不够通用,在样式控制方面也要一定的技巧.
这类封闭环境下的产物常见有的一些自动完成控件,拿来就可以用.

下面来考虑一个通用的,可扩的设计方案
这里所谓通用,是指一个集成的环境里面,不同应用是共享的,代码是可重用的,来对上面combox所有功能分析一下,给控件解耦,提取出一些独立的功能,并给出一个与combox无关的控件设计模型.

一个控件模型可由以下一个或多个模型的组合而成
1.事件模型(event model)
具有事件模型的控件有添加事件监听器,发送,和移除事件的能力.
给控件建立事件模型是很有意义的,外部可监听控件一些感兴趣的事件并利用事件进行通讯,如MVC模型的实现多是基于事件(消息)的驱动.
实现了事件模型的控件具有可扩性,因为事件可有多个监听器,或者说通常意义上的回调,这个当然与单个回调效果不一样了.
有必要说说HTML事件模型与自定的不同,HTML受限于HTML结点而不是控件的事件,并且外界并不能向结点发送事件.

2.选择模型(selection model)
具有选择模型的控件具有单选,多选,并给合键盘导航选择等功能.

3.加载模型(loading model)
加载模型使得控件有自动Ajax加载并组装数据的能力

4.装饰模型(decoration model)
装饰模型与前面的几个模型不同,前面的通常是控件自身就支持,或是控件组成的不可或缺部分,而装饰模型不是控件自身就有的,它显得可有可无,只起来装饰效果,
而装饰时充分利用了其它的几个模型,例如在加载的时候给控件装饰一个”加载中”图标,利用事件模型作监听,利用加载模型加载前触发,在加载后移除效果.

此外不同应用还可独立出不同的模型,这里就不多说了.

通用的控件建好模型后,利用这些设计一个通用而功能齐全的combox控件.
combox控件根据视图划分为触发部分和下拉部分,其中下拉部分作为一个外部控件引入.
为了支持下拉的灵活实现,并且要求不同实现要具有一致的行为,下拉部分这控件必须支持上面所说的几个模型.
这样一来,Combobox就具有了大部分功能,并且行为始终保持一致.

实现参考:

http://www.bgscript.com/bgjs/samples/combo.html

讲一下实现参考例子里的内容:
里面的combox的下拉控件都实现了以上几种模型,
下拉框作为selector引入到combox,
selector在里面的分别是组控件,树型控件和小视图分组控件,
它们在combox中都表现出一致的行为,不加修改就可放到combox中.
下拉时出现loading图标和树型控件的loading图标是装饰模型实现后引起的效果,
它监听由加载模型触发的open,final事件并作出相应的处理.

JavaScript - Button(圆角非圆角)按钮控件制作

五月 26th, 2009 由 Bgser 发表

Button(圆角非圆角)按钮控件制作

    HTML按钮不出乎几种组织方法:

  • 固定宽高,背景图片也是固定好的.
  • 这方法比较局限,宽高固定了,文字也得固定,不过用这种方法的一般文字也嵌进图片中.这种方法通过用于一般的快速开发的网页和一些图标按钮中.

  • 高度固定,长度不限.高度可用padding来扩充,设置按钮边框,背景采用一幅图片,图片repeat-x,如果是支持圆角的浏览器,再设置按钮的圆角样式.jQuery自带UI就用到该方法.
  • 采用滑动门技术,固定高度,宽度自动,但最大宽度有限制.
  • 这种比较自由,效果好看,HTML结点构成也够简洁,背景图只需一幅就够了,但局限也是有的,先是最大宽度有限制,
    其次,如果只用两个HTML元素构建的话(通常是A和span),滑动门那圆脚部分边框外就得与背景颜色相同,以覆盖父结点背景图,如果不考虑页页背景有多种颜色的话,这情境就不必考虑了.

  • 采用左,中,右的布局,固定高度,宽度自动,并且宽度没有限制,左边右边布局固定宽度,中间根据内容自动扩展.
  • 这种方法需要更多的HTML结点来组织,但够灵活,消除了上一点所说的圆解边框色背景局限.

  • 宽高都没限制,这种按钮需要更多的HTML结点,可用一个井字形TABLE或多个DIV再加padding构建,结构更接近一个窗口控件,背影图片要显示得好看的话难处理,实际上也少应用到.

按钮HTML的组织
第一种制作可直接到www.mycoolbutton.com在线生成,最后一种不作介绍,下面介绍采用滑动门技术和左,中,右的布局按钮的制作.
滑动门:在a标签里增加一个span标签,给a标签定义一个样式,让其显示图片的左半部分,再给span定义一个样式,宽度为圆角所占宽度让其显示图片的右半部分,当两个半边的图片重合起来就达到这个效果.
当然,不限于a标签或span,其它的也可以.
左中右布局:既可以用DIV实现,也可以用TABLE,个人更倾向于TABLE,一个TR,三个TD,因为对齐容易,也不用设置过多的padding,左右TD固定宽度或设padding以留空间,宽度与圆角宽一样,中间TD背景图repeat-x.

滑动门按钮HTML样例
<a class="sliperbutton" title="home" href="#"><span></span>My Button</a>
Table结构按钮HTML样例
<table cellspacing="0" cellpadding="0" border="0" class="g-btn" title="登 录">
  <tr>
     <td class="g-btn-l"></td>
      <td class="g-btn-c">
       <button class="g-btn-text" type="button">My Button</button>
      </td><td class="g-btn-r">
      </td>
   </tr>
</table>

按钮背景图的组织
滑动门结构背景图就只一能一张,如果图案越长图片大小就越大,这是避免不了的.

 /**
  * 背景图像由右往左,由上而下打印,不重复.
  * 这里圆角长度是15px.
  */
 .sliperbutton {
   background:url(buttonbk.gif) no-repeat right top;
   padding:4px 15px 0 0;
 }
 a.sliperbutton:hover{text-decoration:none;}
 
  /**
   * float:left使得行内元素span视作块元素,使得宽,高,padding,margin等设置有效.
   * 因为父层A的padding-top为4px,所以SPAN要往上作-4px偏移.
   */
 .sliperbutton span {
     background:url(buttonbk.gif) no-repeat left top;
     float:left;
     padding-right:15px;
     height:24px;
     margin-top:-4px;
  }

左中右结构的按钮也可以一幅图片,图片分为上下两部,上半部为左,右圆角,下半部分为中间repeat-x部分,整幅图片宽度取决于左圆角宽度+右圆角宽度.

 /**
  * display:inline-block; 将对象呈递为内联对象,
  * 但是对象的内容作为块对象呈递.
  */
 .g-btn{
   display:inline-block;
 }
.g-btn-l, .g-btn-r {
/**IE中这个必要,要不字体大小超过宽度就乱了.*/
 font-size:1px !important; 
 height:23px;
 width:4px;
}
 
.g-btn-l, g-btn-c, g-btn-r{
  background-image:url(btnbk.gif);
  background-repeat:no-repeat;
}
 
/**定位背景图*/
.g-btn-l {background-position:0 -48px;}
.g-btn-r {background-position:0 -55px;}
 
/**注意这里的repeat-x*/
.g-btn-c{
   background-position:0 -106px;
   background-repeat:repeat-x;
}

点击这里查看BackLight库已实现的按钮.