Skip to content
This repository was archived by the owner on Jun 19, 2024. It is now read-only.

Commit ec7b12a

Browse files
author
clivezhg
authored
Merge pull request #3 from clivezhg/cli_work
Version 1.0.0
2 parents 9b13eed + 34fff8e commit ec7b12a

File tree

4 files changed

+77
-70
lines changed

4 files changed

+77
-70
lines changed

README.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ Suppose your HTML is like this:
3535
And your data:
3636
```js
3737
var mydata = [
38-
{id:1, name:"USA", inc:[
39-
{name:"west", inc:[
40-
{id:111, name:"California", inc:[
41-
{id:1111, name:"Los Angeles", inc:[
42-
{id:11111, name:"Hollywood"}
38+
{id:1, text:"USA", inc:[
39+
{text:"west", inc:[
40+
{id:111, text:"California", inc:[
41+
{id:1111, text:"Los Angeles", inc:[
42+
{id:11111, text:"Hollywood"}
4343
]},
44-
{id:1112, name:"San Diego"}
44+
{id:1112, text:"San Diego"}
4545
]},
46-
{id:112, name:"Oregon"},
47-
]},
46+
{id:112, text:"Oregon"}
47+
]}
4848
]},
49-
{id:2, name:"India"},
50-
{id:3, name:"中国"}
49+
{id:2, text:"India"},
50+
{id:3, text:"中国"}
5151
];
5252
```
5353
And you call Select2-to-Tree like the following:
@@ -56,10 +56,10 @@ $("#sel_1").select2ToTree({treeData: {dataArr:mydata}, maximumSelectionLength: 3
5656
```
5757
"`{treeData: {dataArr:mydata}`" is for Select2-to-Tree, "`maximumSelectionLength: 3`" is for Select2 (and you can set the other Select2 arguments if needed)
5858

59-
About the data structure: "`id`" will be used as option value, "`name`" will be used as option label, and "`inc`" will be used to specify sub-level options. If your data structure is not like this, you can set arguments in "`treeData`" to change the default behavior, e.g., `treeData: {dataArr: mydata, valFld: "value", labelFld: "text", incFld: "sub"}`:
59+
About the data structure: "`id`" will be used as option value, "`text`" will be used as option label, and "`inc`" will be used to specify sub-level options. If your data structure is not like this, you can set arguments in "`treeData`" to change the default behavior, e.g., `treeData: {dataArr: mydata, valFld: "value", labelFld: "name", incFld: "sub"}`:
6060
- `dataArr`, an array containing the data.
6161
- `valFld`, the option value field, it's "`id`" by default. (if the value is empty, the corresponding option will be unselectable, see the "west" option in the example)
62-
- `labelFld`, the option label field, it's "`name`" by default.
62+
- `labelFld`, the option label field, it's "`text`" by default.
6363
- `incFld`, the sub options field, it's "`inc`" by default.
6464
- `dftVal`, the default value.
6565

@@ -87,6 +87,11 @@ Then, you call Select2-to-Tree (the "`treeData`" argument of Select-to-Tree is n
8787
$("#sel_2").select2ToTree();
8888
```
8989

90+
Constraints
91+
-----------
92+
- AJAX data source is not supported.
93+
- It is a little slower than plain Select2, because there are extra operations to do. Anyway, according to my test (you can check "Example 3" in "example/example.html", click the "India -> north"), 1500 options is basically acceptable, which is enough in most of the real world cases.
94+
9095
Copyright and license
9196
---------------------
9297
The license is available within the repository in the [LICENSE][license] file.

example/example.html

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ <h3>Example 1</h3>
1515
</select>
1616
<script>
1717
var mydata = [
18-
{id:1, name:"USA", inc:[
19-
{name:"west", inc:[
20-
{id:111, name:"California", inc:[
21-
{id:1111, name:"Los Angeles", inc:[
22-
{id:11111, name:"Hollywood"}
18+
{id:1, text:"USA", inc:[
19+
{text:"west", inc:[
20+
{id:111, text:"California", inc:[
21+
{id:1111, text:"Los Angeles", inc:[
22+
{id:11111, text:"Hollywood"}
2323
]},
24-
{id:1112, name:"San Diego"}
24+
{id:1112, text:"San Diego"}
2525
]},
26-
{id:112, name:"Oregon"},
27-
]},
26+
{id:112, text:"Oregon"}
27+
]}
2828
]},
29-
{id:2, name:"India"},
30-
{id:3, name:"中国"}
29+
{id:2, text:"India"},
30+
{id:3, text:"中国"}
3131
];
3232
$("#sel_1").select2ToTree({treeData: {dataArr: mydata}, maximumSelectionLength: 3});
3333
</script>
3434

35-
<br><br><br>
35+
<br>
3636

3737
<h3>Example 2</h3>
3838
<select id="sel_2" style="width:8em">
@@ -46,5 +46,20 @@ <h3>Example 2</h3>
4646
<script>
4747
$("#sel_2").select2ToTree();
4848
</script>
49+
50+
<br>
51+
52+
<h3>Example 3</h3>
53+
<select id="sel_3" style="width:16em" multiple>
54+
</select>
55+
<script>
56+
var ind = mydata[1];
57+
ind.inc = [{text:"north", inc:[]}];
58+
var inc = ind.inc[0].inc;
59+
for (var i = 1; i <= 1500; i++) {
60+
inc.push({ id: 1000000+i, text: "india city "+i });
61+
}
62+
$("#sel_3").select2ToTree({treeData: {dataArr: mydata}, maximumSelectionLength: 3});
63+
</script>
4964
</body>
5065
</html>

src/select2totree.css

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
* Select2-to-Tree CSS 0.8.0
2+
* Select2-to-Tree CSS 1.0.0
33
* https://github.com/clivezhg/select2-to-tree
44
*/
55
.s2-to-tree * {
@@ -42,49 +42,49 @@
4242
.s2-to-tree li.select2-results__option.non-leaf .expand-collapse:hover {
4343
color: red;
4444
}
45-
.s2-to-tree li.select2-results__option.non-leaf .expand-collapse::before {
45+
.s2-to-tree li.select2-results__option.non-leaf .expand-collapse:before { /* IE8 doesn't support :: */
4646
content: "+";
4747
position: absolute;
4848
left: -0.35em;
49+
top: 0.1em;
4950
font-size: larger;
5051
cursor: pointer;
5152
}
52-
.s2-to-tree li.select2-results__option.non-leaf.opened .expand-collapse::before {
53+
.s2-to-tree li.select2-results__option.non-leaf.opened .expand-collapse:before {
5354
content: "−";
5455
}
5556

5657
.s2-to-tree .item-label {
5758
display: inline-block;
5859
margin-left: 0.5em;
5960
padding: 3px;
60-
width: calc(100% - 11px);
61+
width: calc(100% - 11px); /* IE8 will fit the content */
6162
}
6263

6364
.s2-to-tree li.select2-results__option {
6465
position: relative;
6566
padding: 0px;
66-
height: 1.6em;
67+
height: auto;
6768
overflow-y: hidden;
68-
transition: height 0.18s;
6969
}
7070

7171
.s2-to-tree li.select2-results__option[data-pup] {
72-
height: 0px;
72+
display: none;
7373
}
7474
.s2-to-tree li.select2-results__option[data-pup].showme {
75-
height: 1.6em;
75+
display: block;
7676
overflow-y: visible;
7777
}
7878

79-
.s2-to-tree.select2-container--default .select2-results__option--highlighted[aria-selected] > span.item-label {
79+
.s2-to-tree.select2-container .select2-results__option--highlighted[aria-selected] > span.item-label {
8080
background-color: #5897fb;
8181
color: white;
8282
}
83-
.s2-to-tree.select2-container--default li.select2-results__option[aria-selected="true"] > span.item-label {
83+
.s2-to-tree.select2-container li.select2-results__option[aria-selected="true"] > span.item-label {
8484
background-color: #ddd;
8585
}
86-
.s2-to-tree.select2-container--default li.select2-results__option--highlighted[aria-selected],
87-
.s2-to-tree.select2-container--default li.select2-results__option[aria-selected="true"] {
86+
.s2-to-tree.select2-container li.select2-results__option--highlighted[aria-selected],
87+
.s2-to-tree.select2-container li.select2-results__option[aria-selected="true"] {
8888
background-color: inherit;
8989
color: inherit;
9090
}
@@ -95,6 +95,6 @@
9595
}
9696

9797
.s2-to-tree.searching-result li.select2-results__option {
98-
height: 1.6em;
98+
height: auto;
9999
display: block;
100100
}

src/select2totree.js

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
/*!
2-
* Select2-to-Tree 0.8.0
2+
* Select2-to-Tree 1.0.0
33
* https://github.com/clivezhg/select2-to-tree
44
*/
55
(function ($) {
66
$.fn.select2ToTree = function (options) {
7-
var defaults = {
8-
theme: "default"
9-
};
10-
var opts = $.extend(defaults, options);
7+
var opts = $.extend({}, options);
8+
119
if (opts.treeData) {
1210
buildSelect(opts.treeData, this);
1311
}
12+
1413
opts.templateResult = function (data, container) {
1514
var $iteme = $("<span class='item-label'></span>").text(data.text);
1615
if (data.element) {
@@ -21,43 +20,31 @@
2120
container.setAttribute("data-pup", ele.getAttribute("data-pup"));
2221
}
2322
if ($(container).hasClass("non-leaf")) {
24-
return $('<span class="expand-collapse"></span>' + $("<div></div").append($iteme).html());
23+
return $('<span class="expand-collapse" onmouseup="expColMouseupHandler(event);"></span>' + $("<div></div").append($iteme).html());
2524
}
2625
}
2726
return $iteme;
2827
};
2928

30-
var expandCollapseTime = 0;
29+
window.expColMouseupHandler = function (evt) {
30+
toggleSubOptions(evt.target || evt.srcElement);
31+
/* prevent Select2 from doing "select2:selecting","select2:unselecting","select2:closing" */
32+
evt.stopPropagation ? evt.stopPropagation() : evt.cancelBubble = true;
33+
evt.preventDefault ? evt.preventDefault() : evt.returnValue = false;
34+
}
3135

3236
var s2inst = this.select2(opts);
33-
s2inst.on("select2:selecting select2:unselecting", function (evt) {
34-
if (Date.now() - expandCollapseTime < 160) {
35-
evt.preventDefault();
36-
}
37-
});
38-
39-
s2inst.on("select2:closing", function (evt) { // If the clicked is the selected, no 'selecting' will be fired, and 'closing' will be raised
40-
if (Date.now() - expandCollapseTime < 160) {
41-
evt.preventDefault();
42-
}
43-
});
4437

4538
s2inst.on("select2:open", function (evt) {
4639
var s2data = s2inst.data("select2");
47-
// The 'click' event will be after 'select2:selecting'
4840
s2data.$dropdown.addClass("s2-to-tree");
4941
s2data.$dropdown.find(".searching-result").removeClass("searching-result");
50-
s2data.$dropdown.off("mousedown", ".expand-collapse", mousedownHandler);
51-
s2data.$dropdown.on("mousedown", ".expand-collapse", mousedownHandler);
5242
var $allsch = s2data.$dropdown.find(".select2-search__field").add( s2data.$container.find(".select2-search__field") );
5343
$allsch.off("input", inputHandler);
5444
$allsch.on("input", inputHandler);
5545
});
56-
function mousedownHandler(evt) {
57-
toggleSubOptions(evt.target);
58-
evt.stopPropagation();
59-
expandCollapseTime = Date.now();
60-
}
46+
47+
/* Show search result options even if they are collapsed */
6148
function inputHandler(evt) {
6249
var s2data = s2inst.data("select2");
6350
if ($(this).val().trim().length > 0) {
@@ -71,12 +58,12 @@
7158
return s2inst;
7259
};
7360

74-
function buildSelect(treeData, $el) {
61+
function buildSelect(treeData, $el) { // build Select options according to Select-to-Tree specification
7562
function buildOptions(dataArr, curLevel, pup) {
7663
for (var i = 0; i < dataArr.length; i++) {
77-
var data = dataArr[i];
64+
var data = dataArr[i] || {};
7865
var $opt = $("<option></option>");
79-
$opt.text(data[treeData.labelFld || "name"]);
66+
$opt.text(data[treeData.labelFld || "text"]);
8067
$opt.val(data[treeData.valFld || "id"]);
8168
if($opt.val() === "") {
8269
$opt.prop("disabled", true);
@@ -108,12 +95,13 @@
10895

10996
function showHideSub(ele) {
11097
var curEle = ele;
98+
var $options = $(ele).parent(".select2-results__options");
11199
var shouldShow = true;
112100
do {
113-
var pup = $(curEle).attr("data-pup");
101+
var pup = ($(curEle).attr("data-pup") || "").replace(/'/g, "\\'");
114102
curEle = null;
115103
if (pup) {
116-
var pupEle = $(".select2-container li.select2-results__option[data-val='" + pup + "']");
104+
var pupEle = $options.find(".select2-results__option[data-val='" + pup + "']");
117105
if (pupEle.length > 0) {
118106
if (!pupEle.eq(0).hasClass("opened")) {
119107
$(ele).removeClass("showme");
@@ -126,10 +114,9 @@
126114
} while (curEle);
127115
if (shouldShow) $(ele).addClass("showme");
128116

129-
var val = $(ele).attr("data-val");
130-
$(".select2-container li.select2-results__option[data-pup='" + val + "']").each(function () {
117+
var val = ($(ele).attr("data-val") || "").replace(/'/g, "\\'");
118+
$options.find(".select2-results__option[data-pup='" + val + "']").each(function () {
131119
showHideSub(this);
132120
});
133121
}
134-
135122
})(jQuery);

0 commit comments

Comments
 (0)