Skip to content

Commit

Permalink
Merge pull request #1 from blackWins/blackWins-change
Browse files Browse the repository at this point in the history
optimize UI performance
  • Loading branch information
blackWins authored Sep 13, 2023
2 parents f3fad16 + b5f3164 commit 9d995e7
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 127 deletions.
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
269 changes: 147 additions & 122 deletions select2tree.js
Original file line number Diff line number Diff line change
@@ -1,130 +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;
});

//Expand the selected values to radio mode only
$(".select2-selection").off("mouseup");
$(".select2-selection").mouseup(function () {
var ariaowns = $(this).attr('aria-owns');
if (!ariaowns || ariaowns == null) return;
var selectid = ariaowns.split('-')[1];
//get current value
var val = $('#' + selectid).val();

if (val == '' || val == null || !val || val.indexOf(',') > 0) return;

var pval = [];
do {
var p = $('#' + selectid + ' option[value=' + val + ']').attr('parent');
if (p == '' || !p)
break;
pval.push(p);
val = p;
} while (true)

if (pval.length > 0) {
for (var i in pval.reverse()) {
switchAction(pval[i], true);
}
}
event.stopPropagation();
});

}, 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);

0 comments on commit 9d995e7

Please sign in to comment.