天天看點

Javascript Infinite Level Select 無限級關聯下拉菜單

Overview

  • 多級關聯,支援Ajax動态擷取資料并緩存資料,動态生成下級select菜單,設定動态生成"option"第一個條目作為提示項,自動選擇唯一選項的菜單,設定回調函數在onChange事件觸發時擷取下拉菜單相關資訊。 詳細功能及設定請見DEMO。

Requirement

  • jQuery v1.6+

License

  • Dual licensed under the MIT and GPL licenses:

    http://www.opensource.org/licenses/mit-license.php

    http://www.gnu.org/licenses/gpl.html

Author

  • waiting AT xiaozhong.biz

Update

  • See changes

Download

  • linkagesel.zip 包括js用戶端所有資料及postgres資料庫表資料
  • GitHub Repository

Settings

  • 調用方式:var linkageSel = new LinkageSel(opts);
  • opts參數清單:
    參數名 類型 預設值 可選 注釋
    data Object null 指定本地資料源。至少要指定data、url、ajax其中一個的值,data可以和ajax配合使用
    url String url位址,一次性遠端獲得所有資料
    ajax String ajax遠端獲得下級菜單資料
    autoBind Boolean true 自動生成下級select菜單
    autoHide Boolean true 自動隐藏下級菜單.若false,則可配合level固定值使用
    hideWidth Boolean true 如果設定自動隐藏下級菜單,則是否同時隐藏其占位寬度 true:'display:none'||false: 'visibility:hidden'
    autoLink Boolean true 如果隻有唯一選項則選中并關聯下級
    defVal Integer|Array true 預設選擇項,指定多級菜單預設選項需要使用數組方式,并且按照層級順序排列
    head String|Number|false 請選擇 作為下拉菜單第一選擇名稱自動添加, 空字元('')有效。若false則不自動添加
    level Integer 20 限定層級防止死循環
    loaderImg String images/ui-anim_basic_16x16.gif loader動态圖示
    root Integer|Array 根所在位置,決定擷取資料入口.不适用于ajax模式
    select String|Array jQuery選擇器字元串或者jQuery選擇器字元串數組
    selClass String LinkageSel 應用于所有下拉菜單的class屬性,包括預先生成的對象
    selStyle String margin-left:1px; 應用于下拉菜單的style屬性
    minWidth Integer 120 下拉菜單最小寬度
    maxWidth Integer 300 下拉菜單最大寬度
    fixWidth Integer 下拉菜單固定,此設定将覆寫minWidth、maxWidth的效果
    onChange Function 菜單選擇變化時回調函數
    mvcQuery Boolean false

    置true後ajax請求會生成符合MVC格式的URI, 比如 http://linkagesel.xiaozhong.biz/district/get_nodes/0URI第一個分段district為controller控制器名,第二分段get_nodes為方法名,第三分段為節點的id值

    此時 ajax值需要設定為MVC格式, 比如 ajax: 'district/get_nodes'

    dataReader Object {id: 'id', name: 'name', cell: 'cell'} 自定義資料結構中鍵名, 比如 {id: 'gid', name: 'value', cell: 'subcell'}
  • 執行個體方法:
    方法名 參數及其類型 傳回值類型 可鍊式操作 注釋
    changeValues

    parm1:Integer|Array

    parm2: Boolean[option=false]

    Object 手動改變選單值,可選觸發onchange使用者自定義回調函數
    getSelectedValue idx:Integer String 傳回select的值。不帶參數獲得關聯select中'最後一個'有選擇select菜單的選擇值; 如果大于等于0則 傳回第 idx 個菜單(從0開始)選擇值,如果都無有選擇(一般是初始化後)則傳回 null
    getSelectedArr Array 傳回數組包含所有select選擇值
    getSelectedData

    key: String

    idx: Interger[option] 空則傳回目前最後一個有選擇項選單的選項項值對象

    Object 傳回第idx級(從0開始)菜單所選項目的對應資料的對象
    getSelectedDataArr key: String[option] Array 獲得所有有選擇菜單的資料對象或對象值,遇到第一個未選擇的停止。 對于傳回值,如果指定key則傳回 data[key] 對應值: int|str|null; 如果未指定key傳回資料對象data: obj|null
    onChange callback: Function; 選項變化時回調函數,callback内的this被綁定到目前執行個體對象(可見Demo2)
    reset 回複到初始狀态
    resetAll 回複到初始狀态,包括預設選擇項及初始資料

Demo

SyntaxHighlighter文法高亮比較耗資源,重複重新整理頁面可能會導緻記憶體占用攀高

加載:

?

1 2 3 4

<

script

src

=

"js/jquery.js"

></

script

>

<

script

src

=

"js/comm.js"

></

script

>

<

script

src

=

"js/linkagesel-min.js"

></

script

>

資料結構:

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

<script>

var

data = {

"key"

: {

"name"

: nameValue,

"otherAttr"

: otherAttrVal,

"cell"

: { ... },

};

</script>

key為條目的索引值,也等于 <option value=

"VALUE"

> </option> 中的 value 值,必須有

name為條目的顯示值,即 <optio> name<option> ,必須有

otherAttr其他屬性,比如code,price,但不能為cell,        可選

cell為下級菜單包含的資料内容,包含同樣的key/name/cell格式, 可選

比如:

var

data1 = {

1: {name:

'蔬菜'

,

cell: {

10: {name:

'菠菜'

, price: 4 },

11: {name:

'茄子'

, price: 5}

}

};

蔬菜|-->菠菜 (id等于1, price為4)

|-->茄子 (id等于10, price為5)

Demo1:開始一個簡單的

獲得最後一個有效選項value

獲得最後一個有效選項屬性 ?

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

<script>

$(document).ready(

function

(){

var

data1 = {

1: {name:

'蔬菜'

, cell: { 10: {name:

'菠菜'

, price: 4 }, 11: {name:

'茄子'

, price: 5} }

},

3: {name:

'水果'

,

cell: {

20: {name:

'蘋果'

, cell: {201: {name:

'紅富士'

, price: 20}  } } ,

21: {name:

'桃'

,

cell: {

210: {name:

'猕猴桃'

, price: 30},

211: {name:

'油桃'

, price: 31},

212: {name:

'蟠桃'

, priece: 32} }

}

}

},

9: {name:

'糧食'

,

cell: {

30: {name:

'水稻'

,    cell: { 301: {name:

'大米'

, cell: {3001: {name:

'五常香米'

, price: 50}} } }   }

}

}

};

var

opts = {

data: data1,

select:

'#demo1'

};

var

linkageSel1 =

new

LinkageSel(opts);

$(

'#getSelectedValue'

).click(

function

() {

var

v = linkageSel.getSelectedValue();

alert(v);

});

$(

'#getSelectedData'

).click(

function

() {

var

name = linkageSel.getSelectedData(

'name'

),

price = linkageSel.getSelectedData(

'price'

);

alert(

'名稱:'

+ name +

' 價格:'

+ price);

});

});

</script>

Demo2:省市地三級關聯, 本地加載資料。onChange時擷取相關屬性

獲得各級菜單所選值 ?

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

<select id=

"demo2"

></select>

位址:<input type=

"text"

value=

"tip"

id=

"tip"

size=

"50"

/>

<input type=

"button"

title=

"獲得各級菜單所選值"

value=

"button3"

id=

"getValueArr2"

/>

<script src=

"js/district-all.js"

></script>

<script>

var

opts = {

data: districtData,    

// districtData為district-all.js中定義的變量

selStyle:

'margin-left: 3px;'

,

select: 

'#demo2'

};

var

linkageSel2 =

new

LinkageSel(opts);

districtData = opts =

null

;

// 如果資料量大最好在建立LinkageSel執行個體之後清空

$(

'#getValueArr2'

).click(

function

() {

var

arr = linkageSel2.getSelectedArr();

alert(arr.join(

','

));

});

linkageSel2.onChange(

function

() {

var

input = $(

'#tip'

),

d =

this

.getSelectedDataArr(

'name'

),   

// 所有有標明菜單的name. this === linkageSel2

zip =

this

.getSelectedData(

'zip'

),     

// 最末標明菜單的zip資料值

arr = [];

for

(

var

i = 0, len = d.length; i < len; i++) {

arr.push(d[i]);

}

zip = zip ?

' 郵編:'

+ zip :

''

;

input.val(arr.join(

' '

) + zip);

});

</script>

Demo3:省市地三級關聯, Ajax動态擷取下級資料

?

1 2 3 4 5 6 7 8 9 10

<script>

var

opts = {

ajax:

'district_crud.php?aj=15'

,

selStyle:

'margin-left: 3px;'

,

select:

'#demo3'

};

var

linkageSel3 =

new

LinkageSel(opts);

</script>

Demo4:1級資料JS中指派, Ajax動态擷取2、3級資料

?

1 2 3 4 5 6 7 8 9 10 11 12

<script>

var

data4 = {2: {name:

'北京市'

}, 4:{name:

'河北省'

} };

var

opts4 = {

data: data4,

ajax:

'district_crud.php?aj=15'

,   

// ajax與data配合擷取未定義的下級資料

selStyle:

'margin-left: 3px;'

,

select:

'#demo4'

};

new

LinkageSel(opts4);

</script>

Demo5:指定預設選項

?

1 2 3 4 5 6 7 8 9 10 11 12

<script src=

"js/district-all.js"

></script>

<script>

var

opts5 = {

data: districtData,        

// districtData為district-all.js中定義的變量

selStyle:

'margin-left: 3px;'

,

select:  [

'#demo5'

],       

// select的值可以是個數組

defVal: [4]

};

var

linkageSel5 =

new

LinkageSel(opts5);

</script>

Demo6:指定預設選項, 靜态動态混合select

?

1 2 3 4 5 6 7 8 9 10 11

<select id=

"demo61"

></select> <select id=

"demo62"

></select>

<script>

var

opts6 = {

data: districtData,

select:  [

'#demo61'

,

'#demo62'

],     

// 2個靜态,剩餘的動态生成

defVal: 4

};

var

linkageSel6 =

new

LinkageSel(opts6);

</script>

Demo7:指定多個預設選項, 動态生成select

?

1 2 3 4 5 6 7 8 9 10 11 12

<select id=

"demo7"

></select>

<script>

var

opts7 = {

data: districtData,

selStyle:

'margin-left: 3px;'

,

select: 

'#demo7'

,     

// 隻有一個

defVal: [5, 256]       

// 可是兩個喲

};

var

linkageSel7 =

new

LinkageSel(opts7);

</script>

Demo8:定義資料入口

山西省: ?

1 2 3 4 5 6 7 8 9 10 11 12

山西省:<select id=

"demo8"

></select>

<script>

var

opts8 = {

data: districtData,

root: 5,               

// 資料入口

selStyle:

'margin-left: 3px;'

,

select: 

'#demo8'

};

var

linkageSel8 =

new

LinkageSel(opts8);

</script>

Demo9:指定資料入口, 多個預設選項

山西省: ?

1 2 3 4 5 6 7 8 9 10 11 12 13

山西省:<select id=

"demo9"

></select>

<script>

var

opts9 = {

data: districtData,

root: 5,               

// 資料入口

selStyle:

'margin-left: 3px;'

,

select: 

'#demo9'

,     

defVal: [256, 257]     

// 兩個喲

};

var

linkageSel9 =

new

LinkageSel(opts9);

</script>

Demo10:指定深層資料入口, 預設選項

山西省 太原市: ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14

山西省:<select id=

"demo10"

></select>

<script>

var

opts10 = {

data: districtData,

root: [5, 256],            

// 深層資料入口

selStyle:

'margin-left: 3px;'

,

select: 

'#demo9'

,     

defVal: 257

};

var

linkageSel10 =

new

LinkageSel(opts10);

</script>

Demo11:固定寬度

?

1 2 3 4 5 6 7 8 9 10 11 12 13

<select id=

"demo11"

></select>

<script>

var

opts11 = {

data: districtData,

selStyle:

'margin-left: 3px;'

,

select:

'#demo11'

,

fixWidth: 200,         

// 固定寬度

head:

'想好了選哪個麼'

// 自定義

};

var

linkageSel11 =

new

LinkageSel(opts11);

</script>

Demo12:不使用提示條目

?

1 2 3 4 5 6 7 8 9 10 11

<select id=

"demo12"

></select>

<script>

var

opts12 = {

data: districtData,

select:

'#demo12'

,

head:

false

// 不使用自動生成提示作為菜單第一項

};

var

linkageSel12 =

new

LinkageSel(opts12);

</script>

Demo13:一次性遠端擷取資料,不适合大資料量情況

?

1 2 3 4 5 6 7 8 9 10

<select id=

"demo13"

> </select>

<script>

var

opts13 = {

select:

'#demo13'

,

url:

'exampledata.php'

};

var

linkageSel13 =

new

LinkageSel(opts13);

</script>

Demo14:1級菜單資料JS檔案加載, Ajax動态擷取2、3級資料

?

1 2 3 4 5 6 7 8 9 10 11 12

<script src=

"js/district-level1.js"

></script>

<script>

var

opts14 = {

data: districtData1,       

//  注意變量名

ajax:

'district_crud.php?aj=15'

,   

// ajax與data配合擷取未定義的下級資料

selStyle:

'margin-left: 3px;'

,

select:

'#demo14'

};

var

linkageSel14 =

new

LinkageSel(opts14);

</script>

Demo15:1級菜單資料JS檔案加載, Ajax動态擷取2、3級資料。手動設定值,可用于編輯頁面的自動標明

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

<body>

<button type=

"button"

onclick=

"javascript: ls15.changeValues([23, 2244])"

>changeValues</button>

</body>

<script src=

"js/district-level1.js"

></script>

<script>

var

ls15;  

// must outside of ready() !

$(document).ready(

function

(){

var

opts15 = {

data: districtData1,       

//  注意變量名

ajax:

'district_crud.php?aj=15'

,   

// ajax與data配合擷取未定義的下級資料

selStyle:

'margin-left: 3px;'

,

select:

'#demo15'

};

window.ls15 =

new

LinkageSel(opts15);

});

</script>

Demo16:自定義資料key名

?

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

<script>

$(document).ready(

function

(){

var

data16 = {

1: {gid: 1, value:

'IBM'

,

sub: {

10: {gid: 10, value:

'X3650'

},

11: {gid: 11, value:

'X3860'

}

}

},

3: {gid: 3, value:

'HP'

,

sub: {

20: {gid: 20, value:

'360'

} ,

21: {gid: 21, value:

'380'

}

}

},

9: {gid: 9, value:

'DELL'

,

sub: {

29: {gid: 29, value:

'R710'

}

30: {gid: 30, value:

'R720'

}

}

}

};

var

opts = {

data: data16,

select:

"[name='demo16']"

,

dataReader: {id:

'gid'

, name:

'value'

, cell:

'sub'

}

// self defined data key name

};

var

ls16 =

new

LinkageSel(opts);

});

</script>

Demo17:ajax擷取資料且多個預設值. 注意與demo7的差別

?

1 2 3 4 5 6 7 8 9 10 11 12 13

<select id=

"demo17"

></select>

<script>

var

opts17 = {

//data: districtData,   // demo7

ajax:

'district_crud.php?aj=15'

,

selStyle:

'margin-left: 3px;'

,

select: 

'#demo17'

,

defVal: [5, 256, 257]

};

var

linkageSel17 =

new

LinkageSel(opts17);

</script>

Demo18:不使用提示條目,指定預設值

?

1 2 3 4 5 6 7 8 9 10 11 12

<select id=

"demo18"

></select>

<script>

var

opts18 = {

data: districtData,

select:

'#demo18'

,

defVal: [5, 256, 257],

head:

false

// 不使用自動生成提示作為菜單第一項

};

var

linkageSel18 =

new

LinkageSel(opts18);

</script>

js