标签 ‘WEB UI’

Background JavaScript UI 库发布 2.0.8 版

十一月 3rd, 2009 由 Rock 发表

这次版本修正同时也改变了部分设计.

主要修改 :

1. 优化容器布局,使得在容器显示时才布局.

容器在显示时才布局,使得容器在一些情况下, 最常见的是在Resize后, 忽略对容器布局从而提高整个应用的性能.

由于在显示时才布局,所以一开始就隐藏的容器如果存在子项并不立即渲染,因为对于容器来说,子项的渲染处于容器的 布局过程中触发,所以很多时候要等到容器显示时子项才得以渲染.

这种行为对于非IE浏览器,几乎没什么弊端,因为对于非IE浏览器来说,DOM文档添加结点的操作响应是非常快速的,对于控件渲染时才把结点添加到DOM文档中这操作来说,几乎不影响用户的体验.

但IE浏览器就不同了,即便IE8也是如此,DOM文档添加结点这操作是非常昂贵的,所以在IE下,容器在显示时才布局的弊端就是引发用户操作的短暂停顿,这种方法并不够友好!

可以在IE和非IE浏览器下对比一下这个菜单中,IE下首次显示菜单的时候操作有些少的停顿.

2. 优化类生成函数,实现原型链继承方式,减少类创建时引起的内存消耗.

这个是当前版本中库结构最关键的更新.

先前考虑到类属性查找速度问题,库中类继承是采用属性复制而不是基于原型链的方式实现.

如原库中:

    var ClassA.prototype.key = 'value';

    继承采用:

    extend(ClassB.prototype, ClassA.prototype);

   当前版类继承方式采用:

   var ClassA = function() {};

   //桥接类
   var Bridge= function(){};

   Bridge.prototype = ClassA.prototype;

   ClassB.prototype = new Bridge();

第一种的利弊:

利:运行时查找基类属性可在类自身的原型上找到,并不存在基类形成的原型链.

弊:在类生成过程中复制父类属性会引起时间上的损耗.
并不是真正意义上的继承,即在修改基类原型属性时在子类没法体现出,所以对于类原型的扩展有很大的局限.

第二种利弊刚好与第一种相反,运行时查找属性要遍历原型链,最大可能直至基类原型;在类创建时须新增一个桥接类.

本次采用第二种主要是考虑到能在修改基类原型属性的情况下,在子类可体现出来,便于控件行为与属性的扩展.

3. 以扩展方式增加表格视图统计功能,可向每个视图添加多个统计行.

经建议增加表格统计功能.

4. 新增浮动导航条控件和浮动布局管理器.

新增一个浮动布局管理器,它是依赖浏览器来检测布局,无需设置容器的具体宽高,这点与以往的布局管理器不同,布局速度上更胜一畴. 库中并为该布局设计了一个浮动导航条控件.


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

七月 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

建立基本的页面框架 — 第一步小试牛刀

七月 21st, 2009 由 Rock 发表

可分为几个步骤:

  • 创建HTML页面
  • 创建Viewport
  • 利用BorderLayout布局viewport
  • 放置tab或其它控件

什么是viewport?
viewport从结构上可以看成一个层,它布满整个浏览器客户区,当浏览器宽高(size)改变时会自动适应.从这个意义上来说,与EXT的viewport功能是一致的.在库中一个viewport是一个DIV结点,绝对方式定位,放在body下.
viewport的作用就是,当宽高改变时,可通知内部的布局管理器重新布局子控件.众所周知,当用CSS改变一个元素的宽高时在JavaScript端是得不到任何通知的,例如将一个CSS类作用到一个元素时,你不作测试的话没法得知其高度已经改变,它不像事件监听那样,可以给元素添加事件监听器,当有动作发生时得到通知.除非所有元素都通过CSS布局,但这是不够灵活的,试想用CSS实现BorderLayout布局,并具有其特性,始终还得通过脚本控制CSS属性来实现,此时就会遇到一个问题,既然容器宽高已经改变,就得重新布局子控件,如上所说,CSS改变脚本得不会通知,要重新布局子控件就必须自定容器的事件机制,当通过脚本来改变容器宽高时(这里再次强调是通过脚本,而非直接设置CSS),容器就发送一个表明宽高已改变的事件,并通知布局管理器重新布局子控件.

了解了viewport,清楚为什么要用viewport,就开始搭建一个最简单的最常用到的页面框架,简单起见,元素不多,北面一个面板+tab,西面一面板和中间一个面板.

1.创建HTML页面
HTML页面是添加面板的HTML内容,具体可参见示例,这里不一一列出.

1.创建viewport,指定布局为border layout

  var viewport = new CViewport({layout:'border'});

2.利用布局viewport,这里主要创建北,西,中三个面板,并在北面板中添加一个tab控件

  //添加北,西,中面板
  //
  var northPanel = new CPanel({view : 'northPanel', maxH:70,height:70});
  var westPanel = new CPanel({view : 'westPanel', width:191, maxW:450});
  //card布局:容器里面的元素宽高与窗口一致.
  var centerPanel = new CPanel({view : 'centerPanel', layout:'card'});
  //在北面板中添加Tab控件
  //itemAutoConnect : true TabItem当选择时自动加载
  //contentPanel:存放TabItem内容面板的父容器,
  //当TabItem未指定Panel时,自动生成的Panel就被添加到该容器中.
  var tab = new CTab({
      id:'fr-tab', 
      itemAutoConnect:true,
      contentPanel:centerPanel, 
      array:[
       {title:'桌面 - DIV', panel:CC.$('deskPanel')},
       {title:'谷歌 - Google - IFRAME', src:'http://www.google.com'},
       {title:'百度 - Baidu - IFRAME', src:'http://www.baidu.com'},
       {title:'背光脚本', src:'http://www.bgscript.com'},
       {title:'通过Ajax载入内容', url:'http://www.bgscript.com/q?bg_q=changelog'}
  ]});
 
  northPanel.add(tab);
  //
  // dir:north,指明为北边容器,gap:1,空隙为1, split:true指明允许分隔条
  //
  viewport.add(northPanel, {dir:'north', gap:0})
             .add(westPanel, {dir:'west', gap:1, split:true})
	     .add(centerPanel, {dir:'center'});
  //集中渲染显示
  viewport.render();

3.利用tab加载IFRAME页面示例

  //选择第一项
  tab.select(0);

至此,一个最基本的页面框架已经建好了!

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

库JavaScript Tab控件应用文档

七月 20th, 2009 由 Rock 发表

说明:
Tab派生于选择容器类,由多个TabItem作为子项,TabItem有个panel作为显示页面,这个panel可以随意指定,在任意地方显示,除此以外,panel与Tab子项也没什么关系了.

依赖类文件:
如果打散发布,Tab类依赖以下文件类:
库:bglib.js
容器基类:container.js
Tab类:tab.js

Tab关键事件:
itemclick : 子项点击时触发
select : 子项选择前触发
selected : 子项选择后触发
close : 子项关闭前触发
closed : 子项关闭后触发

创建一个Tab:

  var tab = new CTab({showTo:document.body, autoRender:true});

添加TabItem项:

  tab.add(new CTabItem({title:'小强'}));

或通过数组添加子项:

  tab.fromArray([
    {title:'旺财'},
    {title:'小强', closeable:false}
  ]);

或在创建时通过指定array来添加子项:

  var tab = new CTab(
    showTo:document.body, 
    autoRender: true,
    array:[
    {title:'旺财'},
    {title:'小强'}
   ]);

或通过ajax json加载子项, 返回的json格式与array添加子项时格式一致:

  var tab = new CTab(
    showTo:document.body, 
    autoRender: true,
    autoConnect : true,
    url : 'http://www.bgscript/q?type=getTabItems'
   ]);

响应tab子项选择事件例子:

  tab.on('selected', function(item){
     alert('您选择了'+item.title+'项');
  });

响应tab子项关闭事件例子:

  tab.on('closed', function(item){
     alert('您关闭了'+item.title+'项');
  });

根据子项下标或子项ID选择子项:

  tab.select(0);
  tab.select('tabitemId');

结合子项panel例子,

<html>
<body>
  <div id="tab"></div>
  <div id="layer">
  <!-- 第一个tab子项的面板-->
  <div id="panel1">Tab 子项1的面板</div>
  <div id="panel2">Tab 子项2的面板</div>
  <div id="panel3">Tab 子项3的面板</div>
  </div>
</body>
<script>
  Event.ready(function(){
     var tab = new CTab(
        view:'tab' ,
        array:[
          {title:'子项1'}, panel:CC.$('panel1')},
          {title:'子项2'}, panel:CC.$('panel2')},
          {title:'子项3'}, panel:CC.$('panel3')}
        ]
     );
 
    tab.render();
  });
</script>
</html>

子项内容面板自动Ajax或IFRAME加载,只需在Tab控件中指定内容面板,设置itemAutoConnect即可:

   var contentPanel = new CPanel({view:'tabItemPanels'});
   var tab = new CTab({itemAutoConnect:true, contentPanel:contentPanel});
  //为Tab子项加多一个src属性,表明IFrame加载,url属性表示Ajax加载.
  tab.fromArray([
    {title:'Google', src:'http://www.google.com'},
    {title:'Bgscript', src:'http://www.bgscript.com'},
    {title:'Ajax Load', url:'http://www.bgscript.com/q?bg_q=changelog'}
  ]);

关于IFrame自动高度与滚动条问题
平时做WEB开发的时候,IFRAME在IE下自动高度通过CSS设置不了,(如果您有很好的方案,请告诉我,谢谢),不得不用脚本控制,如果IFRAME用多了控制就麻烦了. 在背光库中,解决方法是通过布局管理器来管理IFRAME的宽高,原理是当父容器宽高改变时更新子容器宽高.
就上面的例子,id为’layer’的DIV元素作为父容器, 引入CardLayout布局管理器,该布局管理器使得所有子控件在父容器宽高改变时同步自身宽高,使得子控件宽高始终与父容器保持一致.

   var contentPanel = new CPanel({view:'tabItemPanels', layout:'card'});
   var tab = new CTab({itemAutoConnect:true, contentPanel:contentPanel});
  //为Tab子项加多一个src属性,表明IFrame加载,url属性表示Ajax加载.
  tab.fromArray([
    {title:'Google', src:'http://www.google.com'},
    {title:'Bgscript', src:'http://www.bgscript.com'},
    {title:'Ajax Load', url:'http://www.bgscript.com/q?bg_q=changelog'}
  ]);

以后改变contentPanel宽高时,容器中的IFRAME就自动适应其高度.

查看演示:http://www.bgscript.com/bgjs/samples/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代码在线格式化

六月 9th, 2009 由 Bgser 发表



JavaScript在线格式化工具不少,但实用的不多,现在提供一个不错的JavaScript代码格式化工具,出自jsbeautifier.org,已把它集成到网站上,并用BackLight库重写了界面,
可点击这里查看效果,格式化想要的代码.

利用库实现126邮箱框架界面原型

五月 28th, 2009 由 Bgser 发表

背光JS库控件(Beta)预览

网易设计的界面是不错的,既花哨又具中国风,相信很多同学都喜欢.
Demo地址:http://www.bgscript.com/bgjs/samples/126/126.html

在Firefox下打开firebug可查看控件发出的各种事件.

前端UI实践:背光(Background) UI Framework, 控件展示效果.

背光JS库控件不限于126邮箱界面的实现,它可以在不改变其它库CSS的情况下,改写控件类的一些JavaScript便可实现其它库,诸如jQueryUI, Ext等控件展现效果.

主要特性有:

  • 既可用于一般的WEB页面开发,也可构建相对复杂的RIA应用
  • 以面向对象的组件开发方式,结构清晰,尽量重用现有代码
  • 可以基于布局管理器的容器布局,自由布置容器控件
  • 采用控件行为,结构与外观相分离的设计模式,而不单是通常意义的行为与外观相分离
  • 在熟悉JS的情况下,即使不大会CSS,也可以利用现有资源实现所想控件
  • 在现有的应用基础上,自由方便扩展并开发出新的应用
  • 控件与后台Ajax加载原生集成,只需一个URL就可以完成所愿
  • 多数控件的实现是基于事件驱动的

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库已实现的按钮.