Revision | 27 (tree) |
---|---|
Time | 2010-05-01 15:37:40 |
Author | takahashikzn |
データ構造を変更。
@@ -1,47 +1,80 @@ | ||
1 | 1 | <html> |
2 | 2 | |
3 | 3 | <head> |
4 | +<script src="./Utils.js"></script> | |
4 | 5 | <script src="./NarrowDownSelectionList.js"></script> |
5 | 6 | </head> |
6 | 7 | |
7 | 8 | <body> |
8 | -<div id="sample"></div> | |
9 | +<form method="post" action="http://localhost:8080/"> | |
10 | + <div id="sample"></div> | |
11 | + <input type="submit" value="確認" /> | |
12 | +</form> | |
9 | 13 | </body> |
10 | 14 | |
11 | 15 | <script> |
12 | 16 | var ndsl = new NarrowDownSelectionList(document); |
13 | 17 | |
14 | - ndsl.setParamName("test"); | |
15 | 18 | ndsl.setListItems({ |
16 | 19 | "グループA": { |
20 | + "@": { "name": "lvl1", "value": "A" }, | |
17 | 21 | "グループA-1": { |
18 | - "グループA-1-0": "A10", | |
19 | - "グループA-1-1": "A11", | |
20 | - "グループA-1-2": "A12" | |
22 | + "@": { "name": "lvl2", "value": "A1" }, | |
23 | + "グループA-1-0": { | |
24 | + "@": { "name": "lvl3", "value": "A10" } | |
25 | + }, | |
26 | + "グループA-1-1": { | |
27 | + "@": { "name": "lvl3", "value": "A11" } | |
28 | + }, | |
29 | + "グループA-1-2": { | |
30 | + "@": { "name": "lvl3", "value": "A12" } | |
31 | + } | |
21 | 32 | }, |
22 | 33 | "グループA-2": { |
23 | - "グループA-2-0": "A20", | |
24 | - "グループA-2-1": "A21", | |
25 | - "グループA-2-2": "A22" | |
34 | + "@": { "name": "lvl2", "value": "A2" }, | |
35 | + "グループA-2-0": { | |
36 | + "@": { "name": "lvl3", "value": "A20" } | |
37 | + }, | |
38 | + "グループA-2-1": { | |
39 | + "@": { "name": "lvl3", "value": "A21" } | |
40 | + }, | |
41 | + "グループA-2-2": { | |
42 | + "@": { "name": "lvl3", "value": "A22" } | |
43 | + } | |
26 | 44 | } |
27 | 45 | }, |
28 | - | |
46 | + | |
29 | 47 | "グループB": { |
48 | + "@": { "name": "lvl1", "value": "B" }, | |
30 | 49 | "グループB-1": { |
31 | - "グループB-1-0": "B10", | |
32 | - "グループB-1-1": "B11", | |
33 | - "グループB-1-2": "B12" | |
50 | + "@": { "name": "lvl2", "value": "B1" }, | |
51 | + "グループB-1-0": { | |
52 | + "@": { "name": "lvl3", "value": "B10" } | |
53 | + }, | |
54 | + "グループB-1-1": { | |
55 | + "@": { "name": "lvl3", "value": "B11" } | |
56 | + }, | |
57 | + "グループB-1-2": { | |
58 | + "@": { "name": "lvl3", "value": "B12" } | |
59 | + } | |
34 | 60 | }, |
35 | 61 | "グループB-2": { |
36 | - "グループB-2-0": "B20", | |
37 | - "グループB-2-1": "B21", | |
38 | - "グループB-2-2": "B22" | |
62 | + "@": { "name": "lvl2", "value": "B2" }, | |
63 | + "グループB-2-0": { | |
64 | + "@": { "name": "lvl3", "value": "B20" } | |
65 | + }, | |
66 | + "グループB-2-1": { | |
67 | + "@": { "name": "lvl3", "value": "B21" } | |
68 | + }, | |
69 | + "グループB-2-2": { | |
70 | + "@": { "name": "lvl3", "value": "B22" } | |
71 | + } | |
39 | 72 | } |
40 | 73 | } |
41 | 74 | }); |
42 | 75 | |
43 | - // 初期値を復元する場合はこちら | |
44 | - // ndsl.setInitialValue("A21"); | |
76 | + // 初期値を復元する場合はこちら | |
77 | + //ndsl.setInitialValue("A21"); | |
45 | 78 | |
46 | 79 | var select = ndsl.createNarrowDownSelectListElement(); |
47 | 80 | document.getElementById("sample").appendChild(select); |
@@ -0,0 +1,86 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2010 root42 Inc. All rights reserved. | |
3 | + */ | |
4 | + | |
5 | +/** | |
6 | + * R42フレームワーク | |
7 | + * | |
8 | + * 汎用ユーティリティ。 | |
9 | + * | |
10 | + * @author root42 Inc. | |
11 | + * @version $Id: Utils.js 2625 2010-01-22 09:31:50Z kaz $ | |
12 | + */ | |
13 | + | |
14 | +var Utils = {}; | |
15 | + | |
16 | + | |
17 | +/** | |
18 | + * 指定したノードへイベントリスナーを追加します。 | |
19 | + * | |
20 | + * <p> | |
21 | + * この関数は、ノードのハンドラへ関数を直接セットします。 | |
22 | + * この関数を呼び出し後、明示的にハンドラをnullにすると | |
23 | + * この関数で行った処理はすべて無効となりますので注意が必要です。 | |
24 | + * </p> | |
25 | + * | |
26 | + * <p> | |
27 | + * 例えば、 | |
28 | + * <pre> | |
29 | + * Utils.addEventListener(node, "change", function() { ... }); | |
30 | + * </pre> | |
31 | + * とした後で、 | |
32 | + * <pre> | |
33 | + * node.onchange = function() { ... }; | |
34 | + * </pre> | |
35 | + * としてしまうと、addEventListenerでセットしたハンドラは無効になります。 | |
36 | + * </p> | |
37 | + * | |
38 | + * @param node | |
39 | + * ノード | |
40 | + * @param eventName | |
41 | + * イベント名("click", "change", "mouseover", ...) | |
42 | + * @param listener | |
43 | + * イベントリスナー関数 | |
44 | + * @throws Error いずれかの引数が<code>null</code>の場合 | |
45 | + */ | |
46 | +Utils.addEventListener = /* void */ function( | |
47 | + /* Node */ node, /* String */ eventName, /* Function */ listener) { | |
48 | + | |
49 | + if (eventName == null) { | |
50 | + throw new Error("eventName is null"); | |
51 | + } else if (listener == null) { | |
52 | + throw new Error("listener is null"); | |
53 | + } | |
54 | + | |
55 | + /* String */ var listenersName = "__listeners__"; | |
56 | + /* String */ var handlerName = "on" + eventName; | |
57 | + | |
58 | + // 専用関数未セット | |
59 | + if (node[handlerName] == null) { | |
60 | + node[handlerName] = /* void */ function() { | |
61 | + for (/* int */ var i = 0; i < this[handlerName][listenersName].length; i++) { | |
62 | + this[handlerName][listenersName][i](); | |
63 | + } | |
64 | + }; | |
65 | + | |
66 | + node[handlerName][listenersName] = [ listener ]; | |
67 | + } | |
68 | + | |
69 | + // 通常の関数がセット済み | |
70 | + else if (node[handlerName][listenersName] == null) { | |
71 | + /* Function */ var oldHandler = node[handlerName]; | |
72 | + | |
73 | + node[handlerName] = /* void */ function() { | |
74 | + for (/* int */ var i = 0; i < this[handlerName][listenersName].length; i++) { | |
75 | + this[handlerName][listenersName][i](); | |
76 | + } | |
77 | + }; | |
78 | + | |
79 | + node[handlerName][listenersName] = [ oldHandler, listener ]; | |
80 | + } | |
81 | + | |
82 | + // 専用関数がセット済み | |
83 | + else { | |
84 | + node[handlerName][listenersName].push(listener); | |
85 | + } | |
86 | +}; |
@@ -1,5 +1,5 @@ | ||
1 | -/** | |
2 | - * Copyright (C) 2009 root42 Inc. All rights reserved. | |
1 | +/* | |
2 | + * Copyright (C) 2010 root42 Inc. All rights reserved. | |
3 | 3 | */ |
4 | 4 | |
5 | 5 | /** |
@@ -8,7 +8,6 @@ | ||
8 | 8 | * 絞り込み選択リスト。 |
9 | 9 | * |
10 | 10 | * @author root42 Inc. |
11 | - * @since 1.0 | |
12 | 11 | * @version $Id$ |
13 | 12 | */ |
14 | 13 | function NarrowDownSelectionList(/* Document */ document) { |
@@ -22,9 +21,6 @@ | ||
22 | 21 | /** listItemOfLevels */ |
23 | 22 | /* Map<String, Object> */ self.listItems = {}; |
24 | 23 | |
25 | - /** paramName */ | |
26 | - /* String */ self.paramName = null; | |
27 | - | |
28 | 24 | /** initialvalue */ |
29 | 25 | /* String */ self.initialValue = null; |
30 | 26 |
@@ -45,15 +41,6 @@ | ||
45 | 41 | }; |
46 | 42 | |
47 | 43 | /** |
48 | - * パラメータ名を設定する。 | |
49 | - * | |
50 | - * @param paramName パラメータ名 | |
51 | - */ | |
52 | - self.setParamName = /* void */ function(/* String */ paramName) { | |
53 | - self.paramName = paramName; | |
54 | - }; | |
55 | - | |
56 | - /** | |
57 | 44 | * 初期値を設定する。 |
58 | 45 | * |
59 | 46 | * @param initialValue 初期値 |
@@ -105,6 +92,22 @@ | ||
105 | 92 | }; |
106 | 93 | |
107 | 94 | /** |
95 | + * @param listItemValue リスト要素 | |
96 | + * @return リスト要素の値 | |
97 | + */ | |
98 | + /* private Function */ getValueOf = /* String */ function(/* Map<String, Object> */ listItemValue) { | |
99 | + return listItemValue[NarrowDownSelectionList.METADATA_KEY].value; | |
100 | + } | |
101 | + | |
102 | + /** | |
103 | + * @param listItemValue リスト要素 | |
104 | + * @return リスト要素の値 | |
105 | + */ | |
106 | + /* private Function */ getNameOf = /* String */ function(/* Map<String, Object> */ listItemValue) { | |
107 | + return listItemValue[NarrowDownSelectionList.METADATA_KEY].name; | |
108 | + } | |
109 | + | |
110 | + /** | |
108 | 111 | * 空のSelect要素を作成する。 |
109 | 112 | * |
110 | 113 | * @return 空のSelect要素。 |
@@ -111,7 +114,7 @@ | ||
111 | 114 | */ |
112 | 115 | /* private Function */ var createEmptySelect = /* Selectd */ function() { |
113 | 116 | /* Select */ var selectElem = self.document.createElement("select"); |
114 | - | |
117 | + | |
115 | 118 | // 先頭に空選択肢を入れる |
116 | 119 | selectElem.appendChild(createOption(NarrowDownSelectionList.EMPTY_VALUE, "")); |
117 | 120 |
@@ -130,14 +133,14 @@ | ||
130 | 133 | selectElem.listItems = listItems; |
131 | 134 | |
132 | 135 | for (/* String */ var listItemKey in listItems) { |
136 | + if (NarrowDownSelectionList.METADATA_KEY == listItemKey) { | |
137 | + continue; | |
138 | + } | |
139 | + | |
133 | 140 | /* Object */ var listItemValue = listItems[listItemKey]; |
134 | 141 | |
135 | - if (typeof(listItemValue) == "object") { | |
136 | - listItemValue = ""; | |
137 | - } | |
138 | - | |
139 | 142 | selectElem.appendChild( |
140 | - createOption(listItemKey, listItemValue)); | |
143 | + createOption(listItemKey, getValueOf(listItemValue))); | |
141 | 144 | } |
142 | 145 | |
143 | 146 | // 選択肢が一つしかない場合、選択状態にする |
@@ -149,6 +152,24 @@ | ||
149 | 152 | selectElem.onchange(); |
150 | 153 | } |
151 | 154 | } |
155 | + | |
156 | + // 入力値を決定したとき、input.nameの値を変更する | |
157 | + Utils.addEventListener(selectElem, "change", /* void */ function() { | |
158 | + /* String */ var selectedValue = selectElem.value; | |
159 | + | |
160 | + // select.listItemsでないとダメ | |
161 | + for (/* String */ var listItemKey in selectElem.listItems) { | |
162 | + if (NarrowDownSelectionList.METADATA_KEY == listItemKey) { | |
163 | + continue; | |
164 | + } | |
165 | + | |
166 | + /* Map<String, String> */ var listItem = selectElem.listItems[listItemKey]; | |
167 | + if (selectedValue == getValueOf(listItem)) { | |
168 | + selectElem.name = getNameOf(listItem); | |
169 | + return; | |
170 | + } | |
171 | + } | |
172 | + }); | |
152 | 173 | }; |
153 | 174 | |
154 | 175 | return selectElem; |
@@ -161,9 +182,13 @@ | ||
161 | 182 | * @return 絞り込みリストの最大深さ。最低で1。 |
162 | 183 | */ |
163 | 184 | /* private Function */ var countMaxDepth = /* int */ function(/* Map<String, Object> */ listItems) { |
164 | - /* int */ var maxDepth = 1; | |
185 | + /* int */ var maxDepth = 0; | |
165 | 186 | |
166 | 187 | for (/* String */ var listItemKey in listItems) { |
188 | + if (NarrowDownSelectionList.METADATA_KEY == listItemKey) { | |
189 | + continue; | |
190 | + } | |
191 | + | |
167 | 192 | (function() { |
168 | 193 | /* Object */ var listItemValue = listItems[listItemKey]; |
169 | 194 |
@@ -199,11 +224,15 @@ | ||
199 | 224 | /* Function */ var searchSelectedKeys = function(/* Map<String, Object> */ listItems) { |
200 | 225 | |
201 | 226 | for (/* String */ var listItemKey in listItems) { |
227 | + if (NarrowDownSelectionList.METADATA_KEY == listItemKey) { | |
228 | + continue; | |
229 | + } | |
230 | + | |
202 | 231 | selectedItemKeys.push(listItemKey); |
203 | 232 | |
204 | 233 | /* Object */ var listItemValue = listItems[listItemKey]; |
205 | 234 | |
206 | - if (listItemValue == initialValue) { | |
235 | + if (listItemValue[NarrowDownSelectionList.METADATA_KEY].value == initialValue) { | |
207 | 236 | // 大域脱出する |
208 | 237 | throw 0; |
209 | 238 | } else if (typeof(listItemValue) == "object") { |
@@ -285,7 +314,7 @@ | ||
285 | 314 | /* int */ var depth = i; |
286 | 315 | /* Select */ var narrowDownSelect = createEmptySelect(); |
287 | 316 | |
288 | - narrowDownSelect.onchange= /* void */ function() { | |
317 | + Utils.addEventListener(narrowDownSelect, "change", /* void */ function() { | |
289 | 318 | if (self.warnIncompleteInput) { |
290 | 319 | doWarnIncompleteInput(); |
291 | 320 | } |
@@ -302,7 +331,7 @@ | ||
302 | 331 | // 次のSelectへイベントを伝播させる |
303 | 332 | nextDepthNarrowDownSelect.onchange(); |
304 | 333 | } |
305 | - }; | |
334 | + }); | |
306 | 335 | |
307 | 336 | narrowDownSelects.push(narrowDownSelect); |
308 | 337 |
@@ -319,9 +348,6 @@ | ||
319 | 348 | // メッセージ領域をセット |
320 | 349 | div.appendChild(msgSection); |
321 | 350 | |
322 | - // パラメータ名をセット | |
323 | - narrowDownSelects[narrowDownSelects.length - 1].name = self.paramName; | |
324 | - | |
325 | 351 | // トップレベルを初期化する |
326 | 352 | narrowDownSelects[0].setOptions(self.listItems); |
327 | 353 |
@@ -348,4 +374,5 @@ | ||
348 | 374 | (function() { |
349 | 375 | NarrowDownSelectionList.EMPTY_VALUE = " "; |
350 | 376 | NarrowDownSelectionList.WARN_INCOMPLETE_INPUT = " 最後まで選択して下さい"; |
377 | + NarrowDownSelectionList.METADATA_KEY = "@"; | |
351 | 378 | })(); |