Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# select2tree
extend select2 for treeview. 扩展select2,使它可以树形展示,可以缩放。

<a href="http://runjs.cn/detail/bezljwvl" target="_blank">See demo</a>

# 使用方法
* 与select2用法一致,只是在使用时$('select').select2()变成了$('select').select2tree()。
* option标签中指定parent属性即可实现树形展示,支持数据源乱序,展示下拉选项时将自动排序。
Expand All @@ -14,8 +12,8 @@ This is plugin for tree representation select2's dropdown. It allows any levels
Parent option should be referenced in children via ``parent`` attribute. You should set it like parent's ``value`` attribute - ``parent="parent_value_attribute"``.

### Example
![image](https://github.com/blackWins/select2tree/assets/34080651/93299959-bcad-436d-a781-b0a1e9d11a38)

[Look at demo](http://runjs.cn/detail/bezljwvl)

This files are required for correct working:
```
Expand Down Expand Up @@ -56,8 +54,6 @@ If you want to apply some values at the begining, use select2's event triggering

### Пример использования

[Посмотреть демо](http://runjs.cn/detail/bezljwvl)

Минимально необходимые файлы для работы плагина:

```
Expand Down
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "select2tree",
"version": "1.0.0",
"description": "extend select2 for treeview",
"main": "select2tree.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/blackWins/select2tree.git"
},
"keywords": [
"select2tree",
"select2",
"tree"
],
"author": "blackwinds",
"license": "ISC",
"bugs": {
"url": "https://github.com/blackWins/select2tree/issues"
},
"homepage": "https://github.com/blackWins/select2tree#readme"
}
240 changes: 147 additions & 93 deletions select2tree.js
Original file line number Diff line number Diff line change
@@ -1,101 +1,155 @@
(function($) {
$.fn.select2tree = function(options) {
var defaults = {
language: "zh-CN",
theme: "bootstrap"
};
var opts = $.extend(defaults, options);
opts.templateResult = function(data, container) {
if(data.element) {
//insert span element and add 'parent' property
var $wrapper = $("<span></span><span>" + data.text + "</span>");
var $element = $(data.element);
$(container).attr("val", $element.val())
if($element.attr("parent")) {
$(container).attr("parent", $element.attr("parent"));
}
return $wrapper;
} else {
return data.text;
}
};

$(this).select2(opts).on("select2:open", open);
};
(function ($) {

function moveOption(id) {
if(id) {
$(".select2-results__options li[parent=" + id + "]").insertAfter(".select2-results__options li[val=" + id + "]");
$(".select2-results__options li[parent=" + id + "]").each(function() {
moveOption($(this).attr("val"));
});
} else {
$(".select2-results__options li:not([parent])").appendTo(".select2-results__options ul");
$(".select2-results__options li:not([parent])").each(function() {
moveOption($(this).attr("val"));
});
}
}
let icon = {
type: "fa",
expand: "fa-chevron-right",
collapse: "fa-chevron-down"
};

//deal switch action
function switchAction(id, open) {
$(".select2-results__options li[parent='" + id + "']").each(function() {
switchAction($(this).attr("val"), open);
});
if(open) {
$(".select2-results__options li[val=" + id + "] span[class]:eq(0)").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-down");
$(".select2-results__options li[parent='" + id + "']").slideDown();
} else {
$(".select2-results__options li[val=" + id + "] span[class]:eq(0)").addClass("glyphicon-chevron-right").removeClass("glyphicon-chevron-down");
$(".select2-results__options li[parent='" + id + "']").slideUp();
}
}
$.fn.select2tree = function (options) {
var defaults = { language: "zh-CN", theme: "bootstrap" };
var opts = $.extend(defaults, options);
opts.templateResult = templateResult;
opts.templateSelection = templateSelection;
$(this).select2(opts).on("select2:open", open);
};

//get the level of li
function getLevel(id) {
var level = 0;
while($(".select2-results__options li[parent][val='" + id + "']").length > 0) {
id = $(".select2-results__options li[val='" + id + "']").attr("parent");
level++;
}
return level;
}
function templateSelection(selection, $this) {
var selectid = $this[0].id.split('-').slice(1, -1).join('-');
var v = $('#' + selectid).val(), arr = [];
if (v == '' || v == null || !v || v.indexOf(',') > 0) return selection.text;
do {
var node = $('#' + selectid + ' option[value=' + v + ']');
if (node.length != 1) {
break;
}
v = node.attr('parent');
arr.push(node.text());
} while (true)
return arr.length == 0 ? selection.text : arr.reverse().join('/ ');
}

function open() {
setTimeout(function() {
moveOption();
function templateResult(data, container) {
if (data.element) {
//insert span element and add 'parent' property
var $wrapper = $("<span style='width: 16px;height: 16px;'></span><span>" + data.text + "</span>");
var $element = $(data.element);
$(container).attr("val", $element.val())
if ($element.attr("parent")) {
$(container).attr("parent", $element.attr("parent"));
}
return $wrapper;
} else {
return data.text;
}
}

$(".select2-results__options li").each(function() {
var $this = $(this);
//loop li add some classes and properties
if($this.attr("parent")) {
$(this).siblings("li[val=" + $this.attr("parent") + "]").find("span:eq(0)").addClass("glyphicon glyphicon-chevron-down switch").css({
"padding": "0 10px",
"cursor": "default"
});
$(this).siblings("li[val=" + $this.attr("parent") + "]").find("span:eq(1)").css("font-weight", "bold");
}
//add gap for children
// if(!$this.attr("style")) {
// var paddingLeft = getLevel($this.attr("val")) * 2;
// $("li[parent='" + $this.attr("parent") + "']").css("padding-left", paddingLeft + "em");
// }
if(!$this.attr("style")) {
var paddingLeft = getLevel($this.attr("val")) * 2;
$("li[parent='" + $this.attr("parent") + "']").css("padding-left", paddingLeft + "em").css("display","none");
}
});
function processElements(selector, process) {
$(selector).each(function () {
process($(this));
});
}

//override mousedown for collapse/expand
$(".switch").mousedown(function() {
switchAction($(this).parent().attr("val"), $(this).hasClass("glyphicon-chevron-right"));
event.stopPropagation();
});
function moveOption(id) {
var selector = id ? ".select2-results__options li[parent=" + id + "]" : ".select2-results__options li:not([parent])";
if (id) {
$(selector).insertAfter(".select2-results__options li[val=" + id + "]");
}
else {
$(selector).appendTo(".select2-results__options ul");
}
processElements(selector, function ($element) {
moveOption($element.attr("val"));
});
}
//deal switch action
function switchAction(id, open) {
var $target = $(".select2-results__options li[val=" + id + "]");
if (open) {
$target.find("span[class]:eq(0)").removeClass(icon.expand).addClass(icon.collapse);
$(".select2-results__options li[parent='" + id + "']").slideDown();
} else {
$target.find("span[class]:eq(0)").removeClass(icon.collapse).addClass(icon.expand);
$(".select2-results__options li[parent='" + id + "']").slideUp();
processElements(".select2-results__options li[parent='" + id + "']", function ($element) {
switchAction($element.attr("val"), open);
});
}
}
//get the level of li
function getLevel(id) {
var level = 0;
var elements = $(".select2-results__options li[parent]");
while (elements.filter("[val='" + id + "']").length > 0) {
id = elements.filter("[val='" + id + "']").attr("parent");
level++;
}
return level;
}

//override mouseup to nothing
$(".switch").mouseup(function() {
return false;
});
}, 0);
}
function open(event) {
setTimeout(function () {
moveOption();
setClass(event);
//override mousedown for collapse/expand
$(".switch").mousedown(switchMouseDown);
//override mouseup to nothing
$(".switch").mouseup(switchMouseUp);
}, 0);
}

function getSlideDownValues(id) {
var v = $('#' + id).val(), arr = [];
if (v == '' || v == null || !v || v.indexOf(',') > 0) return null;
arr.push(v);
do {
var p = $('#' + id + ' option[value=' + v + ']').attr('parent');
if (p == '' || !p) {
break;
}
v = p;
arr.push(p);
} while (true)

return arr;
}

function setClass(event) {
var slideDownItems = getSlideDownValues(event.currentTarget.id);
//loop li add some classes and properties
$(".select2-results__options li").each(function () {
var $this = $(this);
var parent = $this.attr("parent");
var close = slideDownItems
&& $this.attr("parent")
&& !(slideDownItems.indexOf($this.attr("val")) != -1 || slideDownItems.indexOf(parent) != -1);
//add gap for children
if (!$this.attr("style")) {
var paddingLeft = getLevel($this.attr("val")) * 2;
processElements("li[parent='" + parent + "']", function ($element) {
$element.css({ "padding-left": paddingLeft + "em" });
});
}
if (close) {
$this.hide();
}
if (parent) {
var $siblings = $this.siblings("li[val=" + parent + "]");
$siblings.find("span:eq(0)").addClass(icon.type + " switch " + (close ? icon.expand : icon.collapse)).css({ "margin-right": "4px", "cursor": "default" });
$siblings.find("span:eq(1)").css("font-weight", "bold");
}
else {

}
});
}

function switchMouseDown(event) {
switchAction($(this).parent().attr("val"), $(this).hasClass(icon.expand));
event.stopPropagation();
}

function switchMouseUp() {
return false;
}
})(jQuery);