(function (w, $) {
let Dcat = w.Dcat;
function Tree(opts) {
this.options = $.extend({
button: null,
table: null,
url: '',
perPage: '',
showNextPage: '',
pageQueryName: '',
parentIdQueryName: '',
tierQueryName: '',
showIcon: 'fa-angle-right',
hideIcon: 'fa-angle-down',
loadMoreIcon: '',
}, opts);
this.key = this.tier = this.row = this.data = this._req = null;
this._init();
}
Tree.prototype = {
_init: function () {
this._bindClick();
},
_bindClick: function () {
var _this = this,
opts = _this.options;
$(opts.button).off('click').click(function () {
if (_this._req) {
return;
}
var $this = $(this),
_i = $("i", this),
shown = _i.hasClass(opts.showIcon);
_this.key = $this.data('key');
_this.tier = $this.data('tier');
_this.row = $this.closest('tr');
if ($this.data('inserted') == '0') {
_this._request(1);
$this.data('inserted', 1);
}
_i.toggleClass(opts.showIcon + ' ' + opts.hideIcon);
var children = [];
getChildren(_this.row.nextAll(), _this.row).forEach(function (v) {
if (getTier(v) !== (_this.tier + 1)) {
return;
}
children.push(v);
shown ? $(v).show() : $(v).hide();
});
children.forEach(function (v) {
if (shown) {
return
}
var icon = $(v).find('a[data-tier=' + getTier(v) + '] i');
if (icon.hasClass(opts.hideIcon)) {
icon.parent().click();
}
})
})
},
_request: function (page, after) {
var _this = this,
row = _this.row,
key = _this.key,
tier = _this.tier,
tableSelector = _this.options.table;
if (_this._req) {
return;
}
_this._req = 1;
Dcat.loading();
var data = {
_token: Dcat.token,
};
data[_this.options.parentIdQueryName] = key;
data[_this.options.tierQueryName] = tier + 1;
data[_this.options.pageQueryName.replace(':key', key)] = page;
$.ajax({
url: _this.options.url,
type: 'GET',
data: data,
headers: {'X-PJAX': true},
success: function (resp) {
after && after();
Dcat.loading(false);
_this._req = 0;
// 获取最后一行
var children = getChildren(row.nextAll(), row);
row = children.length ? $(children.pop()) : row;
var _body = $('
'+resp+'
'),
_tbody = _body.find(tableSelector + ' tbody'),
lastPage = _body.find('last-page').text(),
nextPage = _body.find('next-page').text();
// 标记子节点行
_tbody.find('tr').each(function (_, v) {
$(v).attr('data-tier', tier + 1)
});
if (
_this.options.showNextPage
&& _tbody.find('tr').length == _this.options.perPage
&& lastPage >= page
) {
// 加载更多
let loadMore = $(
`
${_this.options.loadMoreIcon}
|
`
);
row.after(loadMore);
// 加载更多
loadMore.click(function () {
var _t = $(this);
_this._request(_t.data('page'), function () {
_t.remove();
});
});
}
// 附加子节点
row.after(_tbody.html());
// 附加子节点js脚本以及触发子节点js脚本执行
_body.find('script').each(function (_, v) {
row.after(v);
});
// 主动触发ready事件,执行子节点附带的js脚本
Dcat.triggerReady();
},
error:function(a, b, c){
after && after();
Dcat.loading(false);
_this._req = 0;
if (a.status != 404) {
Dcat.handleAjaxError(a, b, c);
}
}
});
}
};
function Orderable(opts) {
this.options = $.extend({
button: null,
url: '',
}, opts);
this.direction = this.key = this.tier = this.row = this._req = null;
this._init();
}
Orderable.prototype = {
_init: function () {
this._bindClick()
},
_bindClick: function () {
var _this = this;
$(_this.options.button).off('click').click(function () {
if (_this._req) {
return;
}
_this._req = 1;
Dcat.loading();
var $this = $(this);
_this.key = $this.data('id');
_this.direction = $this.data('direction');
_this.row = $this.closest('tr');
_this.tier = getTier(_this.row);
_this._request();
})
},
_request: function () {
var _this = this,
key = _this.key,
row = _this.row,
tier = _this.tier,
direction = _this.direction,
prevAll = row.prevAll(),
nextAll = row.nextAll(),
prev = row.prevAll('tr').first(),
next = row.nextAll('tr').first();
$.ajax({
type: 'POST',
url: _this.options.url.replace(':key', key),
data: {_method:'PUT', _token:Dcat.token, _orderable:direction},
success: function(data){
Dcat.loading(false);
_this._req = 0;
if (! data.status) {
return data.message && Dcat.warning(data.message);
}
Dcat.success(data.message);
if (direction) {
var prevRow = sibling(prevAll, tier);
if (swapable(prevRow, tier) && prev.length && getTier(prev) >= tier) {
prevRow.before(row);
// 把所有子节点上移
getChildren(nextAll, row).forEach(function (v) {
prevRow.before(v)
});
}
} else {
var nextRow = sibling(nextAll, tier),
nextRowChildren = nextRow ? getChildren(nextRow.nextAll(), nextRow) : [];
if (swapable(nextRow, tier) && next.length && getTier(next) >= tier) {
nextAll = row.nextAll();
if (nextRowChildren.length) {
nextRow = $(nextRowChildren.pop())
}
// 把所有子节点下移
var all = [];
getChildren(nextAll, row).forEach(function (v) {
all.unshift(v)
});
all.forEach(function(v) {
nextRow.after(v)
});
nextRow.after(row);
}
}
},
error: function (a, b, c) {
_this._req = 0;
Dcat.loading(false);
Dcat.handleAjaxError(a, b, c)
}
});
},
};
function isTr(v) {
return $(v).prop('tagName').toLocaleLowerCase() === 'tr'
}
function getTier(v) {
return parseInt($(v).data('tier') || 0);
}
function isChildren(parent, child) {
return getTier(child) > getTier(parent);
}
function getChildren(all, parent) {
var arr = [], isBreak = false, firstTr;
all.each(function (_, v) {
// 过滤非tr标签
if (! isTr(v) || isBreak) return;
firstTr || (firstTr = $(v));
// 非连续的子节点
if (firstTr && ! isChildren(parent, firstTr)) {
return;
}
if (isChildren(parent, v)) {
arr.push(v)
} else {
isBreak = true;
}
});
return arr;
}
function swapable(_o, tier) {
if (
_o
&& _o.length
&& tier === getTier(_o)
) {
return true
}
}
function sibling(all, tier) {
var next;
all.each(function (_, v) {
if (getTier(v) === tier && ! next && isTr(v)) {
next = $(v);
}
});
return next;
}
Dcat.grid.Tree = function (opts) {
return new Tree(opts);
};
Dcat.grid.Orderable = function (opts) {
return new Orderable(opts);
};
})(window, jQuery);