茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1523728 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
PIMG_00087.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

網頁設計 : [轉貼]通用Combobox(Select)以至一般控件的設計與實現

發表者 討論內容
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15763
[轉貼]通用Combobox(Select)以至一般控件的設計與實現

通用Combobox(Select)以至一般控件的設計與實現

2009年06月14日 由 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事件並作出相應的處理.

聲明: 轉載請註明轉自 背光腳本 - www.bgscript.com
原文出處:通用Combobox(Select)以至一般控件的设计与实现 » bgscript.com - JavaScript脚本编程与WEB应用开发 | JavaScript前端开发 WEB前端技术 用户体验

冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15763
[轉貼]BackLight實現 Select - Combox 控件

BackLight實現 Select - Combox 控件

2009年06月11日 由 Bgser

  • 支持鍵盤導航
  • 支持滾動跟進
  • 條目過濾
  • Ajax動態加載
  • 與Form集成,可直接提交
  • 與CSelectedContainer結合,可自定任意下拉框

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

聲明: 轉載請註明轉自 背光腳本 - www.bgscript.com
原文出處:BackLight实现 Select - Combox 控件 » bgscript.com - JavaScript脚本编程与WEB应用开发 | JavaScript前端开发 WEB前端技术 用户体验

冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15763
[分享]通用Combobox(Select)範例原始碼
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<title>CCombox
		</title>
		<script>
		  var CTemplate = {
		    BLANK_IMG: '../default/s.gif'
		  };
		</script>
		<script type="text/javascript" src="../bglib-all-debug.js"></script>
		<script type="text/javascript" src="../more/folderview.js"></script>
		<link rel="stylesheet" href="../default/global.css" type="text/css"/>
		<link rel="stylesheet" href="../default/ru_share.css" type="text/css"/>
		<link rel="stylesheet" href="resources/example.css" type="text/css"/>
		<style>
      .g-tree .g-panel-body, .g-folderview-wrap{border:1px solid #CCC;border-top:0;}
			.g-folderview-ctx dd{margin:5px;}
		</style>
	</head>
	<body lang="zh">
		<p>	下拉框作為selector引入到combox,
			<br/>	selector在裡面的分別是組控件,樹型控件和小視圖分組控件,
			<br/>	它們在combox中都表現出一致的行為,不加修改就可放到combox中.
			<br/>	下拉時出現loading圖標和樹型控件的loading圖標是裝飾模型實現後引起的效果,
			<br/>	它監聽由加載模型觸發的open,final事件並作出相應的處理.
			<br/>	在firebug下可察看事件
		</p>
		<div style="margin:20px 30px;position:relative;">	<h2>帶滾動條,默認下拉,可編輯</h2>
			<div id="def_combo">
			</div>	<h2>隨內容伸縮,下拉,可編輯</h2>
			<div id="auto_combo">
			</div>	<h2>禁用</h2>
			<div id="disable_combo">
			</div>	<h2>不可編輯</h2>
			<div id="unedit_combo">
			</div>	<h2>自定下拉控件和過濾方式</h2>
			<div id="tree_combo">
			</div>	<h2>自定下拉控件和過濾方式 + 滾動 + Ajax動態加載</h2>
			<div id="tree_ajax_combo">
			</div>	<h2>只要基於CSelectedContainer容器類的控件都可以</h2>
			<div id="other_combo">
			</div>
		</div>
	</body>
</html>
<script>
		Event.ready(function(){
			//
			// 默認下拉
			//
			var cb = new CCombox({showTo:'def_combo', autoRender:true,width:300,array:[
				{title:'粉綠色',icon:'icoIbx'},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoIbx'},
				{title:'清除記錄',icon:'icoDel' ,disabled:true},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoNote'},
				{title:'清除記錄',icon:'icoDel'},
				{title:'粉綠色',icon:'icoIbx'},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoDft'},
				{title:'清除記錄',icon:'icoDel' ,disabled:true},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoNote'},
				{title:'清除記錄',icon:'icoDel'}
			]});
			cb.select(2);
			cb.setScrollorHeight(150);
			cb = new CCombox({showTo:'auto_combo', autoRender:true,width:300,array:[
				{title:'粉綠色',icon:'icoIbx'},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoIbx'},
				{title:'清除記錄',icon:'icoDel' ,disabled:true},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoNote'},
				{title:'清除記錄',icon:'icoDel'},
				{title:'粉綠色',icon:'icoIbx'},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoDft'},
				{title:'清除記錄',icon:'icoDel' ,disabled:true},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoNote'},
				{title:'清除記錄',icon:'icoDel'}
			]});
			//不可編輯
			cb = new CCombox({showTo:'unedit_combo', autoRender:true,uneditable:true, width:300,array:[
				{title:'粉綠色',icon:'icoIbx'},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoIbx'},
				{title:'清除記錄',icon:'icoDel' ,disabled:true},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoNote'},
				{title:'清除記錄',icon:'icoDel'},
				{title:'粉綠色',icon:'icoIbx'},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoDft'},
				{title:'清除記錄',icon:'icoDel' ,disabled:true},
				{title:'粉紅色',icon:'icoDft'},
				{title:'藍色',icon:'icoNote'},
				{title:'清除記錄',icon:'icoDel'}
			]});
			//禁用
			cb = new CCombox({showTo:'disable_combo', disabled: true, autoRender:true,uneditable:true, width:300});
      // ----------------------------------
      // 下拉為樹
      //自定義過濾
			function treeFilter(matcher, caller){
			  var caller = caller || window, fn = arguments.callee;
			  if(this.children){
			  	var cm = true;
	        CC.each(this.children, (function(){
	            if(!matcher.call(caller,this) && !this.nodes){
	                this.display(0);
	                cm = false;
	                return;
	            }
	            this.display(1);
	            if(this.nodes && this.expanded)
	            	fn.call(this, matcher, caller);
	        }));
      	}
			}
		var tree = new CTree({title:'tree', showTo:document.body, hidden:true,filter:treeFilter});
			tree.root.fromArray([
				{title:'disabled item',nodes:true,disabled:true},
				{title:'B'},
				{title:'C',nodes:true}
			]);
			tree.root.$(2).fromArray([
				{title:'disabled A',nodes:true,disabled:true},
				{title:'B',disabled:true},
				{title:'items',nodes:true}
			]);
			tree.render();
		  //指定selector
			cb = new CCombox({showTo:'tree_combo', selector:tree, autoRender:true,width:350});
			tree = new CTree({title:'tree2', url:'/q?bg_q=test_group',
					 autoConnect:true, showTo:document.body, hidden:true,filter:treeFilter});
			tree.root.fromArray([
			  {title:'Back Light 點擊展開', nodes:true},
			  {title:'BCDEFJDFL;AJSDL'},
				{title:'disabled item',nodes:true,disabled:true},
				{title:'BCDEFJDFL;AJSDL'},
				{title:'C',nodes:true},
				{title:'item something',disabled:true},
				{title:'BCD人物事件'},
				{title:'CDEFASLDFJ', nodes:true},
				{title:'disabled item',nodes:true,disabled:true},
				{title:'AAAAAAAAAAAAAA'},
				{title:'WEB前端'}
			]);
			tree.root.$(2).fromArray([
				{title:'disabled A',nodes:true,disabled:true},
				{title:'B',disabled:true},
				{title:'items',nodes:true}
			]);
			tree.render();
			tree.root.expand();
		  //指定selector
			cb = new CCombox({showTo:'tree_ajax_combo',  autoRender:true,selector:tree, width:350});
			cb.setScrollorHeight(150);
			//
			// 其它基於CSelectedContainer容器的控件
			//
			var foldview = new CFolderView({
				showTo:document.body,
	      navKeyEvent : true,
	      hidden:true,
	      shadow:true,
	      title:'請選擇其中一項',
	      autoRender:true
			});
			//指定selector
			cb = new CCombox({showTo:'other_combo', selector:foldview,  autoRender:true,width:320});
			cb.selector.on('comboxshow', function(){
				//content loaded
				if(this.loaded){
					return;
				}
				//方便顯示loading..
				this.setHeight(100);
				this.on('load',(function(){
					this.style('height','');
					this.height = false;
				}));
				this.on('final',(function(){
					//更新數量
					this.setTitle(this.title);
				}));
				this.connect('http://www.bgscript.com/q?bg_q=foldview_data');
			});
		});
</script>
前一個主題 | 下一個主題 | 頁首 | | |



Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|