@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,458 lines • 59.9 kB
JavaScript
Object.defineProperties(exports, {
__esModule: { value: true },
[Symbol.toStringTag]: { value: "Module" }
});
require("./kendo.icons.js");
require("./kendo.html.input.js");
require("./kendo.data-T0mqWOrQ.js");
require("./kendo.treeview.draganddrop.js");
//#region ../src/kendo.treeview.js
const __meta__ = {
id: "treeview",
name: "TreeView",
category: "web",
description: "The TreeView widget displays hierarchical data in a traditional tree structure,with support for interactive drag-and-drop operations.",
depends: [
"data",
"html.input",
"icons"
],
features: [{
id: "treeview-dragging",
name: "Drag & Drop",
description: "Support for drag & drop",
depends: ["treeview.draganddrop"]
}]
};
(function($, undefined) {
var kendo = window.kendo, ui = kendo.ui, data = kendo.data, encode = kendo.htmlEncode, sanitizeLink = kendo.sanitizeLink, extend = $.extend, template = kendo.template, isArray = Array.isArray, Widget = ui.Widget, HierarchicalDataSource = data.HierarchicalDataSource, keys = kendo.keys, NS = ".kendoTreeView", TEMP_NS = ".kendoTreeViewTemp", SELECT = "select", CHECK = "check", NAVIGATE = "navigate", EXPAND = "expand", CHANGE = "change", ERROR = "error", CHECKED = "checked", INDETERMINATE = "indeterminate", COLLAPSE = "collapse", DRAGSTART = "dragstart", PROGRESS = "progress", DRAG = "drag", DROP = "drop", DRAGEND = "dragend", DATABOUND = "dataBound", ITEMSLOADED = "itemsLoaded", LOADCOMPLETED = "loadCompleted", REQUESTEND = "requestEnd", CLICK = "click", KENDOKEYDOWN = "kendoKeydown", UNDEFINED = "undefined", KSTATEHOVER = "k-hover", KTREEVIEW = "k-treeview", VISIBLE = ":visible", NODE = ".k-treeview-item", ICON = "k-icon", TOGGLE_ICON_ELM = `<span></span>`, STRING = "string", ARIA_CHECKED = "aria-checked", ARIA_SELECTED = "aria-selected", ARIA_DISABLED = "aria-disabled", ARIA_EXPANDED = "aria-expanded", ARIA_ACTIVEDESCENDANT = "aria-activedescendant", ARIA_BUSY = "aria-busy", DISABLED = "k-disabled", TreeView, subGroup, nodeContents, nodeIcon, spriteRe, bindings = {
text: "dataTextField",
url: "dataUrlField",
icon: "dataIconField",
spriteCssClass: "dataSpriteCssClassField",
imageUrl: "dataImageUrlField",
attr: "dataAttrField",
imageAttr: "dataImageAttrField",
contentAttr: "dataContentAttrField",
linkAttr: "dataLinkAttrField"
}, isJQueryInstance = function(obj) {
return obj instanceof kendo.jQuery || window.jQuery && obj instanceof window.jQuery;
}, isDomElement = function(o) {
return typeof HTMLElement === "object" ? o instanceof HTMLElement : o && typeof o === "object" && o.nodeType === 1 && typeof o.nodeName === STRING;
};
const treeViewItemDefaultClasses = {
item: "k-treeview-item",
image: "k-image",
contentText: "k-treeview-leaf-text"
};
function contentChild(filter) {
return function(node) {
var result = node.children(".k-animation-container");
if (!result.length) result = node;
return result.children(filter);
};
}
subGroup = contentChild(".k-treeview-group");
nodeContents = contentChild(".k-treeview-group,.k-content");
nodeIcon = function(node) {
return node.children("span").find(`.k-treeview-toggle > span:first`);
};
function checkboxes(node) {
return node.find(".k-checkbox-wrap:first input[type=checkbox]");
}
function insertAction(indexOffset) {
return function(nodeData, referenceNode) {
referenceNode = referenceNode.closest(NODE);
var group = referenceNode.parent(), parentNode;
if (group.parent().is("li")) parentNode = group.parent();
return this._dataSourceMove(nodeData, group, parentNode, function(dataSource, model) {
var referenceItem = this.dataItem(referenceNode);
var referenceNodeIndex = referenceItem && referenceNode.parent().children().length !== referenceItem.parent().length ? referenceItem.parent().indexOf(referenceItem) : referenceNode.index();
return this._insert(dataSource.data(), model, referenceNodeIndex + indexOffset);
});
};
}
spriteRe = /k-sprite/;
function moveContents(node, container) {
var tmp;
while (node && node.nodeName.toLowerCase() != "ul") {
tmp = node;
node = node.nextSibling;
if (tmp.nodeType == 3) tmp.nodeValue = kendo.trim(tmp.nodeValue);
if (spriteRe.test(tmp.className)) container.insertBefore(tmp, container.firstChild);
else container.appendChild(tmp);
}
}
function updateNodeHtml(node) {
var wrapper = node.children("span.k-treeview-item-content"), group = node.children("ul"), toggleButton = wrapper.find(`.k-treeview-toggle > span`), checkbox = node.children("input[type=checkbox]"), innerWrapper = wrapper.children(".k-treeview-leaf");
if (node.hasClass("k-treeview")) return;
if (!wrapper.length) wrapper = $("<span />").prependTo(node);
if (!toggleButton.length && group.length) toggleButton = $(`<span class='k-treeview-toggle'>${TOGGLE_ICON_ELM}</span>`).prependTo(wrapper);
else if (!group.length || !group.children().length) {
toggleButton.parent().remove();
group.remove();
node.removeAttr(ARIA_EXPANDED);
}
if (checkbox.length) $("<span class='k-checkbox-wrap' />").appendTo(wrapper).append(checkbox);
if (!innerWrapper.length) {
innerWrapper = node.children("a").eq(0).addClass("k-treeview-leaf k-link");
if (!innerWrapper.length) innerWrapper = $("<span class='k-treeview-leaf' />");
innerWrapper.appendTo(wrapper);
if (wrapper.length) moveContents(wrapper[0].nextSibling, innerWrapper[0]);
}
}
TreeView = kendo.ui.DataBoundWidget.extend({
init: function(element, options) {
var that = this, inferred = false, hasDataSource = options && !!options.dataSource, list;
if (isArray(options)) options = { dataSource: options };
if (options && typeof options.loadOnDemand == UNDEFINED && isArray(options.dataSource)) options.loadOnDemand = false;
Widget.prototype.init.call(that, element, options);
element = that.element;
options = that.options;
that._dataSourceUids = {};
list = element.is("ul") && element || element.hasClass(KTREEVIEW) && element.children("ul");
inferred = !hasDataSource && list.length;
if (inferred) options.dataSource.list = list;
that._animation();
that._accessors();
that._templates();
if (!element.hasClass(KTREEVIEW)) {
that._wrapper();
if (list) {
that.root = element;
that._group(that.wrapper);
}
} else {
that.wrapper = element;
that.root = element.children("ul").eq(0);
}
that._applyCssClasses();
that._tabindex();
that.wrapper.find(">ul").attr("role", "tree");
that._dataSource(inferred);
that._attachEvents();
that._dragging();
if (!inferred) if (options.autoBind) {
that._progress(true);
that.dataSource.fetch(this._attemptLoadCompleted.bind(this));
} else {
that._progressHandler = that._requestStart.bind(that);
that.dataSource.bind(PROGRESS, that._progressHandler);
}
else that._syncHtmlAndDataSource();
if (options.checkboxes && options.checkboxes.checkChildren) that.updateIndeterminate();
if (that.element[0].id) that._ariaId = kendo.format("{0}_tv_active", that.element[0].id);
else that._ariaId = kendo.guid() + "_tv_active";
kendo.notify(that);
Widget.fn.endInit.call(this);
},
_attachEvents: function() {
var that = this, clickableItems = ".k-treeview-item-content:not(.k-selected,.k-disabled)", MOUSEENTER = "mouseenter";
that._clickHandler = that._click.bind(that);
that.wrapper.on(MOUSEENTER + NS, ".k-treeview-item-content.k-selected", function(e) {
e.preventDefault();
}).on(MOUSEENTER + NS, clickableItems, function() {
$(this).parent().addClass(KSTATEHOVER);
}).on("mouseleave" + NS, clickableItems, function() {
$(this).parent().removeClass(KSTATEHOVER);
}).on(CLICK + NS, clickableItems, that._clickHandler).on("dblclick" + NS, ".k-treeview-item-content:not(.k-disabled) .k-treeview-leaf", that._toggleButtonClick.bind(that)).on(CLICK + NS, `.k-treeview-toggle .${ICON}`, that._toggleButtonClick.bind(that)).on("keydown" + NS, that, that._keydown.bind(that)).on("keypress" + NS, that._keypress.bind(that)).on("focus" + NS, that._focus.bind(that)).on("blur" + NS, that._blur.bind(that)).on("mousedown" + NS, `.k-treeview-item-content,.k-checkbox-wrap :checkbox,.k-treeview-toggle .${ICON}`, that._mousedown.bind(that)).on("change" + NS, ".k-checkbox-wrap :checkbox", that._checkboxChange.bind(that)).on("click" + NS, ".k-request-retry", that._retryRequest.bind(that)).on("click" + NS, ".k-treeview-item-content.k-disabled .k-link", function(e) {
e.preventDefault();
}).on("click" + NS, function(e) {
var target = $(e.target);
if (!target.is(":kendoFocusable") && !target.find("input,select,textarea,button,object").is(":kendoFocusable")) that.focus();
});
},
_requestStart: function() {
this._progress(true);
},
_syncHtmlAndDataSource: function(root, dataSource, treeviewItemLevel) {
root = root || this.root;
dataSource = dataSource || this.dataSource;
treeviewItemLevel = treeviewItemLevel || 1;
let data = dataSource.view(), uidAttr = kendo.attr("uid"), expandedAttr = kendo.attr("expanded"), checkboxesEnabled = this.options.checkboxes, items = root.children("li"), i, item, dataItem, uid, itemCheckbox;
for (i = 0; i < items.length; i++) {
dataItem = data[i];
uid = dataItem.uid;
item = items.eq(i);
item.attr("role", "treeitem").attr(uidAttr, uid).attr(ARIA_SELECTED, item.children("span").hasClass("k-selected"));
item.css("--kendo-treeview-level", treeviewItemLevel);
dataItem.expanded = item.attr(expandedAttr) === "true";
if (dataItem.hasChildren) item.attr(ARIA_EXPANDED, dataItem.expanded);
if (checkboxesEnabled) {
itemCheckbox = checkboxes(item);
dataItem.checked = itemCheckbox.prop(CHECKED);
itemCheckbox.attr("id", "_" + uid);
itemCheckbox.next(".k-checkbox-label").attr("for", "_" + uid);
item.attr(ARIA_CHECKED, item.checked);
}
this._syncHtmlAndDataSource(item.children("ul"), dataItem.children, treeviewItemLevel + 1);
}
},
_animation: function() {
var options = this.options, animationOptions = options.animation, hasCollapseAnimation = animationOptions.collapse && "effects" in animationOptions.collapse, collapse = extend({}, animationOptions.expand, animationOptions.collapse);
if (!hasCollapseAnimation) collapse = extend(collapse, { reverse: true });
if (animationOptions === false) animationOptions = {
expand: { effects: {} },
collapse: {
hide: true,
effects: {}
}
};
animationOptions.collapse = extend(collapse, { hide: true });
options.animation = animationOptions;
},
_dragging: function() {
var enabled = this.options.dragAndDrop;
var dragging = this.dragging;
if (enabled && !dragging) {
var widget = this;
this.dragging = new ui.HierarchicalDragAndDrop(this.element, {
reorderable: true,
autoScroll: this.options.autoScroll,
filter: ".k-treeview-item-content:not(.k-disabled) .k-treeview-leaf",
allowedContainers: ".k-treeview",
itemSelector: ".k-treeview .k-treeview-item",
hintText: this._hintText.bind(this),
clickMoveClick: this.options.dragAndDrop.clickMoveClick === true ? true : false,
contains: function(source, destination) {
return $.contains(source, destination);
},
dropHintContainer: function(item) {
return item;
},
itemFromTarget: function(target) {
var item = target.closest(".k-treeview-item-content");
var treeviewItem = item.closest(".k-treeview-item");
var siblings = treeviewItem.parent().children(".k-treeview-item");
return {
item,
content: target.closest(".k-treeview-leaf"),
first: siblings.first().is(treeviewItem),
last: siblings.last().is(treeviewItem)
};
},
dropPositionFrom: function(dropHint) {
return dropHint.prevAll(".k-treeview-leaf").length > 0 ? "after" : "before";
},
dragstart: function(source) {
widget.wrapper.attr(kendo.attr("scrollable"), false);
return widget.trigger(DRAGSTART, { sourceNode: source[0] });
},
drag: function(options) {
widget.trigger(DRAG, {
originalEvent: options.originalEvent,
sourceNode: options.source[0],
dropTarget: options.target[0],
pageY: options.pageY,
pageX: options.pageX,
statusClass: options.status,
setStatusClass: options.setStatus
});
},
drop: function(options) {
var navigationTarget = $(options.dropTarget).closest("a");
if (navigationTarget && navigationTarget.attr("href")) widget._tempPreventNavigation(navigationTarget);
return widget.trigger(DROP, {
originalEvent: options.originalEvent,
sourceNode: options.source,
destinationNode: options.destination,
valid: options.valid,
setValid: function(state) {
this.valid = state;
options.setValid(state);
},
dropTarget: options.dropTarget,
dropPosition: options.position
});
},
dragend: function(options) {
var source = options.source;
var destination = options.destination;
var position = options.position;
widget.wrapper.removeAttr(kendo.attr("scrollable"));
function triggerDragEnd(source) {
if (widget.options.checkboxes && widget.options.checkboxes.checkChildren) widget.updateIndeterminate();
widget.current(source);
widget.element.focus();
widget.trigger(DRAGEND, {
originalEvent: options.originalEvent,
sourceNode: source && source[0],
destinationNode: destination[0],
dropPosition: position
});
}
if (position == "over") widget.append(source, destination, triggerDragEnd);
else {
if (position == "before") source = widget.insertBefore(source, destination);
else if (position == "after") source = widget.insertAfter(source, destination);
triggerDragEnd(source);
}
}
});
} else if (!enabled && dragging) {
dragging.destroy();
this.dragging = null;
}
},
_tempPreventNavigation: function(node) {
node.on(CLICK + NS + TEMP_NS, function(ev) {
ev.preventDefault();
node.off(CLICK + NS + TEMP_NS);
});
},
_hintText: function(node) {
return this.templates.dragClue({
item: this.dataItem(node),
treeview: this.options
});
},
_templates: function() {
let that = this, options = that.options, fieldAccessor = that._fieldAccessor.bind(that);
if (options.template && typeof options.template == STRING) options.template = template(options.template);
else if (!options.template) options.template = ({ item }) => {
let text = fieldAccessor("text")(item);
let contentAttributes = fieldAccessor("contentAttr")(item);
if (typeof item.encoded != "undefined" && item.encoded === false) return `<span ${that.templates.contentCssAttributes(contentAttributes)}>${text}</span>`;
return `<span ${that.templates.contentCssAttributes(contentAttributes)}>${encode(text)}</span>`;
};
that._checkboxes();
that.templates = {
setAttributes: function(item) {
return that.templates.setDefaultClasses(treeViewItemDefaultClasses.item, item.attr);
},
cssClass: function(group, item) {
var result = "k-treeview-item-content";
if (item.enabled === false) result += " k-disabled";
if (item.selected) result += " k-selected";
return result;
},
textClass: function(item, isLink) {
var result = "k-treeview-leaf";
if (isLink) result += " k-link";
return result;
},
checkboxClass: function(item) {
var result = "k-checkbox";
if (item.enabled === false) result += " k-disabled";
return result;
},
toggleButtonClass: function(item) {
var result = "k-treeview-toggle";
if (item.enabled === false) result += " k-disabled";
return result;
},
toggleIcon: function(icon, item) {
if (item.expanded !== true) return ui.icon(icon, { icon: `chevron-${kendo.support.isRtl(that.element) ? "left" : "right"}` });
else return ui.icon(icon, { icon: "chevron-down" });
},
groupAttributes: function(group) {
var attributes = "";
if (!group.firstLevel) attributes = "role='group'";
return attributes + (group.expanded !== true ? ` ${kendo.attr("style-display")}="none"` : "");
},
groupCssClass: function(group) {
var cssClass = "k-treeview-group";
if (group.firstLevel) cssClass += " k-treeview-lines";
return cssClass;
},
dragClue: (data) => data.treeview.template(data),
group: (data) => `<ul class='${data.r.groupCssClass(data.group)}'${data.r.groupAttributes(data.group)}>` + data.renderItems(data) + `</ul>`,
itemContent: (data) => {
let imageUrl = fieldAccessor("imageUrl")(data.item);
let imgAttributes = fieldAccessor("imageAttr")(data.item);
let spriteCssClass = fieldAccessor("spriteCssClass")(data.item);
let icon = fieldAccessor("icon")(data.item);
let result = "";
if (imageUrl) result += `<img ${that.templates.imageCssAttributes(imgAttributes)} alt='' src='${imageUrl}'>`;
if (icon) result += that.templates.iconTemplate(icon);
if (spriteCssClass) result += `<span class='k-sprite ${spriteCssClass}'></span>`;
result += data.treeview.template(data);
return result;
},
iconTemplate: (icon) => {
let iconHtml = "";
if (icon) iconHtml = ui.icon(icon);
return iconHtml;
},
itemElement: (data) => {
let item = data.item, r = data.r;
let url = fieldAccessor("url")(item), tag = url ? "a" : "span", textAttr = url ? " href=\"" + sanitizeLink(url) + "\"" : "";
let result = `<span class="${r.cssClass(data.group, item)}">`;
if (item.hasChildren) result += `<span class='${r.toggleButtonClass(item)}'>` + r.toggleIcon($(TOGGLE_ICON_ELM), item) + `</span>`;
if (data.treeview.checkboxes) result += `<span class='k-checkbox-wrap' role='presentation'>` + data.treeview.checkboxes.template(data) + `</span>`;
result += `<${tag} ${r.linkCssAttributes(item, !!url)} ${textAttr}>` + r.itemContent(data) + `</${tag}>`;
result += "</span>";
return result;
},
item: (data) => {
var item = data.item, r = data.r;
var result = `<li role='treeitem' data-treeview-level="${item.level ? item.level() + 1 : 1}" ${kendo.attr("uid")}="${item.uid}"${r.setAttributes(item.toJSON ? item.toJSON() : item)} `;
if (data.treeview.checkboxes) result += `aria-checked="${item.checked ? "true" : "false"}" `;
result += `aria-selected="${item.selected ? "true" : "false"}" ${item.enabled === false ? "aria-disabled=\"true\"" : ""}`;
if (item.hasChildren) result += `aria-expanded="${item.expanded ? "true" : "false"}" `;
result += `data-expanded="${item.expanded ? "true" : "false"}" >` + r.itemElement(data) + `</li>`;
return result;
},
loading: ({ messages }) => `<div class='k-icon k-i-loading'></div> ${encode(messages.loading)}`,
retry: ({ messages }) => `${encode(messages.requestFailed)} <button class='k-button k-request-retry'><span class='k-button-text'>${encode(messages.retry)}</span></button>`,
imageCssAttributes: function(imgAttributes) {
return that.templates.setDefaultClasses(treeViewItemDefaultClasses.image, imgAttributes);
},
contentCssAttributes: function(contentAttributes) {
return that.templates.setDefaultClasses(treeViewItemDefaultClasses.contentText, contentAttributes);
},
linkCssAttributes: function(item, isLink) {
return that.templates.setDefaultClasses(this.textClass(item, isLink), fieldAccessor("linkAttr")(item));
},
setDefaultClasses: function(defaultClasses, attributes) {
attributes = attributes && attributes.toJSON ? attributes.toJSON() : attributes || {};
if (!attributes["class"]) attributes["class"] = defaultClasses;
else attributes["class"] += " " + defaultClasses;
return that.templates.stringifyAttributes(attributes);
},
stringifyAttributes: function(attributes) {
let result = "";
for (let attr in attributes) if (attributes.hasOwnProperty(attr)) result += attr + "=\"" + attributes[attr] + "\" ";
return result;
}
};
},
items: function() {
return this.element.find(".k-treeview-item > span:first-child");
},
setDataSource: function(dataSource) {
var options = this.options;
options.dataSource = dataSource;
this._dataSourceUids = {};
this._dataSource();
if (options.checkboxes && options.checkboxes.checkChildren) this.dataSource.one("change", this.updateIndeterminate.bind(this, null));
if (this.options.autoBind) this.dataSource.fetch(this._attemptLoadCompleted.bind(this));
},
_bindDataSource: function() {
var that = this;
that._refreshHandler = that.refresh.bind(that);
that._errorHandler = that._error.bind(that);
that._loadCompletedHandler = that._loadCompleted.bind(that);
that._requestEndHandler = that._dsRequestEnd.bind(that);
that._loadedNodes = [];
that.dataSource.bind(CHANGE, that._refreshHandler);
that.dataSource.bind(ERROR, that._errorHandler);
that.dataSource.bind(ITEMSLOADED, that._loadCompletedHandler);
that.dataSource.bind(REQUESTEND, that._requestEndHandler);
},
_dsRequestEnd: function(e) {
var that = this;
setTimeout(function() {
if (e.type === "read" && !that._loadCompletedFired) that._attemptLoadCompleted();
});
},
_loadCompleted: function(e) {
var that = this;
that._loadedNodes = that._loadedNodes.concat(e.nodes);
if (!that.dataSource.loading() && that.options.loadOnDemand === false) {
that.trigger(LOADCOMPLETED, { nodes: that._loadedNodes });
that._loadedNodes = [];
}
},
_attemptLoadCompleted: function() {
var that = this, items = that.dataSource.view(), current, i;
if (that.options.loadOnDemand === false) {
for (i = 0; i < items.length; i++) {
current = items[i];
if (current.hasChildren && (!current.children || !current.children.data() || current.children.data().length === 0)) return;
}
that._loadCompletedFired = true;
that.trigger(LOADCOMPLETED, { nodes: [] });
}
},
_unbindDataSource: function() {
var dataSource = this.dataSource;
if (dataSource) {
dataSource.unbind(CHANGE, this._refreshHandler);
dataSource.unbind(PROGRESS, this._progressHandler);
dataSource.unbind(ERROR, this._errorHandler);
dataSource.unbind(ITEMSLOADED, this._loadCompletedHandler);
dataSource.unbind(REQUESTEND, this._requestEndHandler);
}
},
_dataSource: function(silentRead) {
var that = this, dataSource = that.options.dataSource;
function recursiveRead(data) {
for (var i = 0; i < data.length; i++) {
data[i]._initChildren();
data[i].children.fetch();
recursiveRead(data[i].children.view());
}
}
dataSource = isArray(dataSource) ? { data: dataSource } : dataSource;
that._unbindDataSource();
if (!dataSource.fields) dataSource.fields = [
{ field: "text" },
{ field: "url" },
{ field: "spriteCssClass" },
{ field: "icon" },
{ field: "imageUrl" }
];
that.dataSource = dataSource = HierarchicalDataSource.create(dataSource);
if (silentRead) {
dataSource.fetch();
recursiveRead(dataSource.view());
}
that._bindDataSource();
},
events: [
DRAGSTART,
DRAG,
DROP,
DRAGEND,
DATABOUND,
LOADCOMPLETED,
EXPAND,
COLLAPSE,
SELECT,
CHANGE,
NAVIGATE,
CHECK,
KENDOKEYDOWN
],
options: {
name: "TreeView",
dataSource: {},
animation: {
expand: {
effects: "expand:vertical",
duration: 200
},
collapse: { duration: 100 }
},
messages: {
loading: "Loading...",
requestFailed: "Request failed.",
retry: "Retry"
},
dragAndDrop: false,
checkboxes: false,
autoBind: true,
autoScroll: false,
loadOnDemand: true,
template: "",
dataTextField: null,
size: undefined
},
_accessors: function() {
var that = this, options = that.options, i, field, textField, element = that.element;
for (i in bindings) {
field = options[bindings[i]];
textField = element.attr(kendo.attr(i + "-field"));
if (!field && textField) field = textField;
if (!field) field = i;
if (!isArray(field)) field = [field];
options[bindings[i]] = field;
}
},
_fieldAccessor: function(fieldName) {
var fieldBindings = this.options[bindings[fieldName]], count = fieldBindings.length;
return (function(item) {
if (count === 0) return kendo.getter(fieldName)(item);
return $.map(fieldBindings, function(x) {
return function(d) {
return kendo.getter(x)(d);
};
})[Math.min(item.level(), count - 1)](item);
});
},
setOptions: function(options) {
Widget.fn.setOptions.call(this, options);
this._animation();
this._dragging();
this._accessors();
this._templates();
},
_trigger: function(eventName, node) {
return this.trigger(eventName, { node: node.closest(NODE)[0] });
},
_setChecked: function(datasource, value) {
if (!datasource || !kendo.isFunction(datasource.view)) return;
for (var i = 0, nodes = datasource.view(); i < nodes.length; i++) {
if (nodes[i].enabled !== false) this._setCheckedValue(nodes[i], value);
if (nodes[i].children) this._setChecked(nodes[i].children, value);
}
},
_setCheckedValue: function(node, value) {
node[CHECKED] = value;
},
_setIndeterminate: function(node) {
var group = subGroup(node), siblings, length, all = true, i;
if (!group.length) return;
siblings = checkboxes(group.children());
length = siblings.length;
if (!length) return;
else if (length > 1) {
for (i = 1; i < length; i++) if (siblings[i].checked != siblings[i - 1].checked || siblings[i].indeterminate || siblings[i - 1].indeterminate) {
all = false;
break;
}
} else all = !siblings[0].indeterminate;
node.attr(ARIA_CHECKED, all ? siblings[0].checked : "mixed");
return checkboxes(node).data(INDETERMINATE, !all).prop(INDETERMINATE, !all).prop(CHECKED, all && siblings[0].checked);
},
updateIndeterminate: function(node) {
node = node || this.wrapper;
var subnodes = subGroup(node).children();
var i;
var checkbox;
var dataItem;
if (subnodes.length) {
for (i = 0; i < subnodes.length; i++) this.updateIndeterminate(subnodes.eq(i));
if (node.is(".k-treeview")) return;
checkbox = this._setIndeterminate(node);
dataItem = this.dataItem(node);
if (checkbox && checkbox.prop(CHECKED)) dataItem.checked = true;
else if (dataItem) delete dataItem.checked;
}
},
_bubbleIndeterminate: function(node, skipDownward) {
if (!node.length) return;
if (!skipDownward) this.updateIndeterminate(node);
var parentNode = this.parent(node), checkbox;
if (parentNode.length) {
this._setIndeterminate(parentNode);
checkbox = parentNode.children("span").find(".k-checkbox-wrap input[type=checkbox]");
this._skip = true;
if (checkbox.prop(INDETERMINATE) === false) this.dataItem(parentNode).set(CHECKED, checkbox.prop(CHECKED));
else this.dataItem(parentNode).set(CHECKED, false);
this._skip = false;
this._bubbleIndeterminate(parentNode, true);
}
},
_checkboxChange: function(e) {
var that = this;
var checkbox = $(e.target);
var isChecked = checkbox.prop(CHECKED);
var node = checkbox.closest(NODE);
var dataItem = this.dataItem(node);
if (this._preventChange) return;
if (dataItem.checked != isChecked) {
dataItem.set(CHECKED, isChecked);
node.attr(ARIA_CHECKED, isChecked);
this._trigger(CHECK, node);
}
if (checkbox.is(":focus")) {
that._trigger(NAVIGATE, node);
that.focus();
}
},
_toggleButtonClick: function(e) {
var node = $(e.currentTarget).closest(NODE);
if (node.is("[aria-disabled='true']")) return;
this.toggle(node);
e.stopPropagation();
},
_mousedown: function(e) {
var that = this;
var currentTarget = $(e.currentTarget);
var node = $(e.currentTarget).closest(NODE);
var browser = kendo.support.browser;
if (node.is("[aria-disabled='true']")) return;
if ((browser.msie || browser.edge) && currentTarget.is(":checkbox")) if (currentTarget.prop(INDETERMINATE)) {
that._preventChange = false;
currentTarget.prop(CHECKED, !currentTarget.prop(CHECKED));
currentTarget.trigger(CHANGE);
currentTarget.on(CLICK + NS, function(e) {
e.preventDefault();
});
that._preventChange = true;
} else {
currentTarget.off(CLICK + NS);
that._preventChange = false;
}
that._clickTarget = node;
that.current(node);
},
_focusable: function(node) {
return node && node.length && node.is(":visible") && !node.children("span").hasClass(DISABLED);
},
_focus: function() {
var current = this.select(), clickTarget = this._clickTarget;
if (kendo.support.touch) return;
if (clickTarget && clickTarget.length) current = clickTarget;
if (!this._focusable(current)) current = this.current();
if (!this._focusable(current)) current = this._nextVisible($());
this.current(current);
},
focus: function() {
var wrapper = this.wrapper, scrollContainer = wrapper[0], containers = [], offsets = [], documentElement = document.documentElement, i;
do {
scrollContainer = scrollContainer.parentNode;
if (scrollContainer.scrollHeight > scrollContainer.clientHeight) {
containers.push(scrollContainer);
offsets.push(scrollContainer.scrollTop);
}
} while (scrollContainer != documentElement);
kendo.focusElement(wrapper);
for (i = 0; i < containers.length; i++) containers[i].scrollTop = offsets[i];
},
_blur: function() {
this.current().find(".k-focus").removeClass("k-focus");
},
_enabled: function(node) {
return !node.children("span").hasClass(DISABLED);
},
parent: function(node) {
var wrapperRe = /\bk-treeview\b(?!-)/, itemRe = /\bk-treeview-item\b(?!-)/, result, skipSelf;
if (typeof node == STRING) node = this.element.find(node);
if (!isDomElement(node)) node = node[0];
skipSelf = itemRe.test(node.className);
do {
node = node.parentNode;
if (itemRe.test(node.className)) if (skipSelf) result = node;
else skipSelf = true;
} while (!wrapperRe.test(node.className) && !result);
return $(result);
},
_nextVisible: function(node) {
var that = this, expanded = that._expanded(node), result;
function nextParent(node) {
while (node.length && !node.next().length) node = that.parent(node);
if (node.next().length) return node.next();
else return node;
}
if (!node.length || !node.is(":visible")) result = that.root.children().eq(0);
else if (expanded) {
result = subGroup(node).children().first();
if (!result.length) result = nextParent(node);
} else result = nextParent(node);
return result;
},
_previousVisible: function(node) {
var that = this, lastChild, result;
if (!node.length || node.prev().length) {
if (node.length) result = node.prev();
else result = that.root.children().last();
while (that._expanded(result)) {
lastChild = subGroup(result).children().last();
if (!lastChild.length) break;
result = lastChild;
}
} else result = that.parent(node) || node;
return result;
},
scrollTo: function(item) {
if (item && item.length > 0) item[0].scrollIntoView({ block: "nearest" });
},
_keydown: function(e) {
var that = this, key = e.keyCode, target, focused = that.current(), expanded = that._expanded(focused), checkbox = focused.find(".k-checkbox-wrap").first().find(":checkbox"), rtl = kendo.support.isRtl(that.element);
if (e.target != e.currentTarget) return;
if (!rtl && key == keys.RIGHT || rtl && key == keys.LEFT) {
if (expanded) target = that._nextVisible(focused);
else if (!focused.children("span").hasClass(DISABLED)) that.expand(focused);
} else if (!rtl && key == keys.LEFT || rtl && key == keys.RIGHT) if (expanded && !focused.children("span").hasClass(DISABLED)) that.collapse(focused);
else {
target = that.parent(focused);
if (!that._enabled(target)) target = undefined;
}
else if (key == keys.DOWN) target = that._nextVisible(focused);
else if (key == keys.UP) target = that._previousVisible(focused);
else if (key == keys.HOME) target = that._nextVisible($());
else if (key == keys.END) target = that._previousVisible($());
else if (key == keys.ENTER && !focused.children("span").hasClass(DISABLED)) {
if (!focused.children("span").hasClass("k-selected")) {
if (!that._trigger(SELECT, focused)) that.select(focused);
}
} else if (key == keys.SPACEBAR && checkbox.length) {
if (!focused.children("span").hasClass(DISABLED)) {
checkbox.prop(CHECKED, !checkbox.prop(CHECKED)).data(INDETERMINATE, false).prop(INDETERMINATE, false);
that._checkboxChange({ target: checkbox });
}
target = focused;
}
if (target) {
e.preventDefault();
if (focused[0] != target[0]) {
that._trigger(NAVIGATE, target);
that.current(target);
that.scrollTo(target);
}
}
},
_keypress: function(e) {
var that = this;
var delay = 300;
var focusedNode = that.current().get(0);
var matchToFocus;
var key = e.key;
if (!(key.length === 1)) return;
if (!that._match) that._match = "";
that._match += key;
clearTimeout(that._matchTimer);
that._matchTimer = setTimeout(function() {
that._match = "";
}, delay);
matchToFocus = focusedNode && that._matchNextByText(Array.prototype.indexOf.call(that.element.find(".k-treeview-item"), focusedNode), that._match);
if (!matchToFocus.length) matchToFocus = that._matchNextByText(-1, that._match);
if (matchToFocus.get(0) && matchToFocus.get(0) !== focusedNode) {
that._trigger(NAVIGATE, matchToFocus);
that.current(matchToFocus);
}
},
_matchNextByText: function(startIndex, text) {
return this.element.find(".k-treeview-item").filter(function(i, element) {
return i > startIndex && $(element).is(":visible") && $(element).find(".k-treeview-leaf").first().text().toLowerCase().indexOf(text) === 0;
}).eq(0).closest(NODE);
},
_click: function(e) {
var that = this, node = $(e.currentTarget), treeItem = node.closest(NODE), contents = nodeContents(treeItem), href = node.find(".k-link").attr("href"), shouldNavigate;
if (href) shouldNavigate = href == "#" || href.indexOf("#" + this.element.id + "-") >= 0;
else shouldNavigate = contents.length && !contents.children().length;
if (shouldNavigate) e.preventDefault();
if (!node.parent().hasClass("k-selected") && !that._trigger(SELECT, treeItem)) that.select(treeItem);
},
_wrapper: function() {
var that = this, element = that.element, wrapper, root, wrapperClasses = "k-treeview";
if (element.is("ul")) {
wrapper = element.wrap("<div />").parent();
root = element;
} else {
wrapper = element;
root = wrapper.children("ul").eq(0);
}
that.wrapper = wrapper.addClass(wrapperClasses);
that.root = root;
},
_getSelectedNode: function() {
return this.element.find(".k-treeview-item-content.k-selected").closest(NODE);
},
_group: function(item) {
var that = this, firstLevel = item.hasClass(KTREEVIEW), group = {
firstLevel,
expanded: firstLevel || that._expanded(item)
}, groupElement = item.children("ul");
groupElement.addClass(that.templates.groupCssClass(group)).css("display", group.expanded ? "" : "none");
if (!firstLevel) groupElement.attr("role", "group");
that._nodes(groupElement, group);
},
_nodes: function(groupElement, groupData) {
var that = this, nodes = groupElement.children("li"), nodeData;
groupData = extend({ length: nodes.length }, groupData);
nodes.each(function(i, node) {
node = $(node);
nodeData = {
index: i,
expanded: that._expanded(node)
};
updateNodeHtml(node);
that._updateNodeClasses(node, groupData, nodeData);
that._group(node);
});
},
_checkboxes: function() {
var options = this.options;
var checkboxes = options.checkboxes;
var defaultTemplate, checkbox;
if (checkboxes) {
defaultTemplate = kendo.html.renderCheckBox($("<input/>"), $.extend({}, options, {}));
defaultTemplate = defaultTemplate.replace(">", "");
checkbox = ({ item }) => defaultTemplate + ` id="_${item.uid}" aria-hidden="true" type="checkbox" tabindex="-1"${checkboxes.name ? "name=\"" + checkboxes.name + "\"" : ""} ${item.enabled === false ? "disabled" : ""} ${item.checked ? "checked" : ""}/>`;
checkboxes = extend({ template: checkbox }, options.checkboxes);
if (typeof checkboxes.template == STRING) checkboxes.template = template(checkboxes.template);
options.checkboxes = checkboxes;
}
},
_updateNodeClasses: function(node, groupData, nodeData) {
if (!node || !node.length) return;
var wrapper = node.children("span"), group = node.children("ul"), templates = this.templates, dataItem = this.dataItem(node);
if (node.hasClass("k-treeview")) return;
nodeData = nodeData || {};
nodeData.expanded = typeof nodeData.expanded != UNDEFINED ? nodeData.expanded : this._expanded(node);
nodeData.index = typeof nodeData.index != UNDEFINED ? nodeData.index : node.index();
nodeData.enabled = typeof nodeData.enabled != UNDEFINED ? nodeData.enabled : !wrapper.hasClass("k-disabled");
nodeData.selected = typeof nodeData.selected != UNDEFINED ? nodeData.selected : wrapper.hasClass("k-selected");
groupData = groupData || {};
groupData.firstLevel = typeof groupData.firstLevel != UNDEFINED ? groupData.firstLevel : node.parent().parent().hasClass(KTREEVIEW);
groupData.length = typeof groupData.length != UNDEFINED ? groupData.length : node.parent().children().length;
node.addClass("k-treeview-item");
var level = dataItem && dataItem.level ? dataItem.level() + 1 : null;
if (level === null && node[0].hasAttribute("data-treeview-level")) level = parseInt(node[0].getAttribute("data-treeview-level"), 10);
if (typeof level === "number" && !isNaN(level)) node[0].style.setProperty("--kendo-treeview-level", level);
node[0].removeAttribute("data-treeview-level");
wrapper.removeClass("k-treeview-top k-treeview-mid k-treeview-bot k-treeview-item-content k-disabled k-selected").addClass(templates.cssClass(groupData, nodeData));
wrapper.find(".k-checkbox").removeClass("k-checkbox k-disabled").addClass(templates.checkboxClass(nodeData));
var textWrap = wrapper.children(".k-treeview-leaf");
var isLink = textWrap[0] && textWrap[0].nodeName.toLowerCase() == "a";
textWrap.removeClass("k-treeview-leaf k-link").addClass(templates.textClass(nodeData, isLink));
if (group.length || node.attr("data-hasChildren") == "true") {
var toggleButton = wrapper.find(".k-treeview-toggle");
var toggleIcon = toggleButton.children(`span`);
toggleButton.removeClass("k-treeview-toggle k-disabled").addClass(templates.toggleButtonClass(nodeData));
templates.toggleIcon(toggleIcon, nodeData);
group.addClass("k-treeview-group");
}
},
_processNodes: function(nodes, callback) {
var that = this;
var items = that.element.find(nodes);
for (var i = 0; i < items.length; i++) callback.call(that, i, $(items[i]).closest(NODE));
},
dataItem: function(node) {
var uid = $(node).closest(NODE).attr(kendo.attr("uid")), dataSource = this.dataSource;
return dataSource && dataSource.getByUid(uid);
},
_dataItem: function(node) {
var uid = $(node).closest(NODE).attr(kendo.attr("uid"));
return this.dataSource && this._dataSourceUids[uid];
},
_insertNode: function(nodeData, index, parentNode, insertCallback, collapsed) {
var that = this, group = subGroup(parentNode), updatedGroupLength = group.children().length + 1, childrenData, groupData = {
firstLevel: parentNode.hasClass(KTREEVIEW),
expanded: !collapsed,
length: updatedGroupLength
}, node, i, item, nodeHtml = "", firstChild, lastChild, append = function(item, group) {
item.appendTo(group);
};
for (i = 0; i < nodeData.length; i++) {
item = nodeData[i];
item.index = index + i;
nodeHtml += that._renderItem({
group: groupData,
item
});
}
node = $(nodeHtml);
if (!node.length) return;
if (!group.length) {
group = $(that._renderGroup({ group: groupData }));
kendo.applyStylesFromKendoAttributes(group, ["display"]);
group.appendTo(parentNode);
parentNode.attr(ARIA_EXPANDED, true);
}
insertCallback(node, group);
if (parentNode.hasClass("k-treeview-item")) {
updateNodeHtml(parentNode);
that._updateNodeClasses(parentNode, groupData, { expanded: !collapsed });
}
firstChild = node.prev().first();
lastChild = node.next().last();
that._updateNodeClasses(firstChild, {}, { expanded: firstChild.attr(kendo.attr("expanded")) == "true" });
that._updateNodeClasses(lastChild, {}, { expanded: lastChild.attr(kendo.attr("expanded")) == "true" });
for (i = 0; i < nodeData.length; i++) {
item = nodeData[i];
if (item.hasChildren) {
childrenData = item.children.data();
if (childrenData.length) that._insertNode(childrenData, item.index, node.eq(i), append, !item.expanded);
}
}
return node;
},
_updateNodes: function(items, field) {
var that = this;
var i, node, nodeWrapper, item, isChecked, isCollapsed, kin;
var context = {
treeview: that.options,
item
};
var render = field != "expanded" && field != "checked";
function setCheckedState(root, state) {
if (root.is(".k-treeview-group")) root.find(".k-treeview-item:not([aria-disabled])").attr(ARIA_CHECKED, state);
root.find(".k-checkbox-wrap input[type=checkbox]:not([disabled])").prop(CHECKED, state).data(INDETERMINATE, false).prop(INDETERMINATE, false);
}
if (field == "selected") {
item = items[0];
node = that.findByUid(item.uid);
kin = node.children("span");
kin.removeClass("k-hover").toggleClass("k-selected", item[field]).end();
if (item[field]) that.current(node);
node.attr(ARIA_SELECTED, !!item[field]);
} else {
var elements = $.map(items, function(item) {
return that.findByUid(item.uid).children("span");
});
for (i = 0; i < items.length; i++) {
context.item = item = items[i];
nodeWrapper = elements[i];
node = nodeWrapper.parent();
if (render) {
if (kendo.unbind) kendo.unbind(nodeWrapper);
nodeWrapper.children(".k-treeview-leaf").html(that.templates.itemContent(context));
}
if (field == CHECKED) {
isChecked = item[field];
setCheckedState(nodeWrapper, isChecked);
node.attr(ARIA_CHECKED, isChecked);
if (that.options.checkboxes.checkChildren) {
setCheckedState(node.children(".k-treeview-group"), isChecked);
that._setChecked(item.children, isChecked);
that._bubbleIndeterminate(node);
}
} else if (field == "expanded") that._toggle(node, item, item[field]);
else if (field == "enabled") {
node.find(".k-checkbox-wrap input[type=checkbox]").prop("disabled", !item[field]);
isCollapsed = !nodeContents(node).is(VISIBLE);
node.removeAttr(ARIA_DISABLED);
if (!item[field]) {
if (item.selected) item.set("selected", false);
if (item.expanded) item.set("expanded", false);
isCollapsed = true;
node.attr(ARIA_SELECTED, false).attr(ARIA_DISABLED, true);
}
that._updateNodeClasses(node, {}, {
enabled: item[field],
expanded: !isCollapsed
});
}
if (nodeWrapper.length) this.trigger("itemChange", {
item: nodeWrapper,
data: item,
ns: ui
});
}
}
},
_appendItems: function(index, items, parentNode) {
var children = subGroup(parentNode).children();
var collapsed = !this._expanded(parentNode);
if (this.element === parentNode) {
var dataItems = this.dataSource.data();
var viewItems = this.dataSource.view();
index = (viewItems.length < dataItems.length ? viewItems : dataItems).indexOf(items[0]);
} else if (items.length) index = items[0].parent().indexOf(items[0]);
if (typeof index == UNDEFINED) index = children.length;
this._insertNode(items, index, parentNode, function(item, group) {
if (index >= children.length) item.appendTo(group);
else item.insertBefore(children.eq(index));
}, collapsed);
this._updateNodeClasses(parentNode, {}, { expanded: !collapsed });
if (!collapsed) subGroup(parentNode).css("display", "block");
},
_refreshChildren: function(parentNode, items, index) {
var i, children, child;
var options = this.options;
var loadOnDemand = options.loadOnDemand;
var checkChildren = options.checkboxes && options.checkboxes.checkChildren;
subGroup(parentNode).empty();
if (!items.length) updateNodeHtml(parentNode);
else {
this._appendItems(index, items, parentNode);
children = subGroup(parentNode).children();
if (loadOnDemand && checkChildren) this._bubbleIndeterminate(children.last());
for (i = 0; i < children.length; i++) {
child = children.eq(i);
this.trigger("itemChange", {
item: child.children("span"),
data: items[i],
ns: ui
});
}
}
},
_refreshRoot: function(items) {
var groupHtml = this._renderGroup({
items,
group: {
firstLevel: true,
expanded: true
}
});
if (this.root.length && this.root[0].parentElement) {
var group = $(groupHtml);
this.root.attr("class", group.attr("class")).html(group.html());
} else this.root = this.wrapper.html(groupHtml).children("ul");
var elements = this.root.children(".k-treeview-item");
for (var i = 0; i < items.length; i++) this.trigger("itemChange", {
item: elements.eq(i),
data: items[i],
ns: ui
});
},
refresh: function(e) {
var node = e.node;
var action = e.action;
var items = e.items;
var parentNode = this.wrapper;
var options = this.options;
var loadOnDemand = options.loadOnDemand;
var checkChildren = options.checkboxes && options.checkboxes.checkChildren;
var i;
if (this._skip) return;
for (i = 0; i < items.length; i++) this._dataSourceUids[items[i].uid] = items[i];
if (e.field) {
if (!items[0] || !items[0].level) return;
return this._updateNodes(items, e.field);
}
if (node) {
parentNode = this.findByUid(node.uid);
this._progress(parentNode, false);
}
if (checkChildren && action != "remove") {
var bubble = false;
for (i = 0; i < items.length; i++) if ("checked" in items[i]) {
bubble = true;
break;
}
if (!bubble && node && node.checked) for (i = 0; i < items.length; i++) items[i].checked = true;
}
if (action == "add") this._appendItems(e.index, items, parentNode);
else if (action == "remove") this._remove(this.findByUid(items[0].uid), false);
else if (action == "itemchange") this._updateNodes(items);
else if (action == "itemloaded") this._refreshChildren(parentNode, items, e.index);
else {
this._refreshRoot(items);
this.element.attr(ARIA_BUSY, false);
}
if (action != "remove") {
for (i = 0; i < items.length; i++) if (!loadOnDemand || items[i].expanded || items[i]._loaded) items[i].load();
}
this.wrapper.find(">ul").attr("role", "tree");
this._applyLevelStyles();
this.trigger(DATABOUND, { node: node ? parentNode : undefined });
if (this.dataSource.filter() && this.options.checkboxes.checkChildren) this.updateIndeterminate(parentNode);
},
_applyLevelStyles: function(root) {
(root || this.element).find("[data-treeview-level]").addBack("[data-treeview-level]").each(function() {
let level = this.getAttribute("data-treeview-level");
if (level == null) return;
if (this.style && typeof this.style.setProperty === "function") this.style.setProperty("--kendo-treeview-level", level);
this.removeAttribute("data-treeview-level");
});
},
_error: function(e) {
var node = e.node && this.findByUid(e.node.uid);
var retryHtml = this.templates.retry({ messages: this.options.messages });
if (node) {
this._progress(node, false);
this._expanded(node, false);
nodeIcon(node).replaceWith(ui.icon($(TOGGLE_ICON_ELM), { icon: "arrow-rotate-cw" }));
e.node.loaded(false);
} else {
this._progress(false);
this.dataSource.data([]);
this.element.html(retryHtml);
}
},
_retryRequest: function(e) {
e.preventDefault();
this.dataSource.fetch(this._attemptLoadCompleted.bind(this));
},
expand: function(nodes) {
this._processNodes(nodes, function(index, item) {
this.toggle(item, true);
});
},
collapse: function(nodes) {
this._processNodes(nodes, function(index, item) {
this.toggle(item, false);
});
},
enable: function(nodes, enable) {
if (typeof nodes === "boolean") {
enable = nodes;
nodes = this.items();
} else enable = arguments.length == 2 ? !!enable : true;
this._processNodes(nodes, function(index, item) {
this.dataItem(item).set("enabled", enable);
});
},
current: function(node) {
var that = this, current = that._current, element = that.element;
if (arguments.length > 0 && node && node.length) {
if (current) current.children("span").removeClass("k-focus");
current = that._current = $(node, element).closest(NODE);
current.children("span").addClass("k-focus");
that._updateActiveDescendant();
return;
}
if (!current) current = that._nextVisible($());
return current;
},
_updateActiveDescendant: function() {
var current = this._current, id = current[0].id || this._ariaId, prev = this.element.find("#" + this._ariaId);
if (prev.length > 0) prev.removeAttr("id");
this.root.removeAttr(ARIA_ACTIVEDESCENDANT);
current.attr("id", id);
this.root.attr(ARIA_ACTIVEDESCENDANT, id);
},
select: function(node) {
var that = this, element = that.element;
if (!arguments.length) return element.find(".k-treeview-item-content.k-selected").closest(NODE);
node = $(node, element).closest(NODE);
element.find(".k-treeview-item-content.k-selected").each(function() {
var item = $(this).closest(NODE);
var dataItem = that.dataItem(item);
if (dataItem) {
dataItem.set("selected", false);
delete dataItem.selected;
} else $(this).removeClass("k-selected");
});
if (node.length) {
that.dataItem(node).set("selected", true);
that._clickTarget = node;
}
that.trigger(CHANGE);
},
_toggle: function(node, dataItem, expand) {
var options = this.options;
var contents = nodeContents(node);
var direction = expand ? "expand" : "collapse";
var loaded;
if (contents.data("animating")) return;
loaded = dataItem && dataItem.loaded();
if (expand && !loaded) {
if (options.loadOnDemand) this._progress(node, true);
contents.remove();
dataItem.load();
} else {
this._updateNodeClasses(node, {}, { expanded: expand });
if (!expand) contents.css("height", contents.height()).css("height");
contents.kendoStop(true, true).kendoAnimate(extend({ reset: true }, options.animation[direction], { complete: function() {
if (expand) contents.css("height", "");
} }));
}
},
toggle: function(node, expand) {
node = $(node);
if (!nodeIcon(node)) return;
if (arguments.length == 1) expand = !this._expanded(node);
this._expanded(node, expand);
},
destroy: function() {
var that = this;
Widget.fn.destroy.call(that);
that.wrapper.off(NS);
that.wrapper.find(".k-checkbox-wrap :checkbox").off(NS);
that._clickHandler = null;
that._unbindDataSource();
if (that.dragging) that.dragging.destroy();
that._dataSourceUids = {};
kendo.destroy(that.element);
that.root = that.wrapper = that.element = null;
},
_expanded: function(node, value, force) {
var expandedAttr = kendo.attr("expanded");
var dataItem;
var expanded = value;
var direction = expanded ? "expand" : "collapse";
if (node.children().hasClass("k-hidden")) node.children().removeClass("k-hidden");
if (arguments.length == 1) {
dataItem = this._dataItem(node);
return node.attr(expandedAttr) === "true" || dataItem && dataItem.expanded;
}
dataItem = this.dataItem(node);
if (nodeContents(node).data("animating")) return;
if (force || !this._trigger(direction, node)) {
if (expanded) {
node.attr(expandedAttr, "true");
node.attr(ARIA_EXPANDED, "true");
} else {
node.removeAttr(expandedAttr);
node.attr(ARIA_EXPANDED, "false");
}
if (dataItem) {
dataItem.set("expanded", expanded);
expanded = dataItem.expanded;
}
}
},
_progress: function(node, showProgress) {
var element = this.element;
var loadingText = this.templates.loading({ messages: this.options.messages });
if (arguments.length == 1) {
showProgress = node;
if (showProgress) element.html(loadingText);
else element.empty();
this.element.attr(ARIA_BUSY, showProgress);
} else {
nodeIcon(node).replaceWith($(TOGGLE_ICON_ELM).toggleClass("k-i-loading", showProgress).toggleClass("k-icon", showProgress));
node.attr(ARIA_BUSY, showProgress);
}
},
text: function(node, text) {
var dataItem = this.dataItem(node), fieldBindings = this.options[bindings.text], level = dataItem.level(), length = fieldBindings.length, field = fieldBindings[Math.min(level, length - 1)];
if (text) dataItem.set(field, text);
else return dataItem[field];
},
_objectOrSelf: function(node) {
return $(node).closest("[data-role=treeview]").data("kendoTreeView") || this;
},
_dataSourceMove: function(nodeData, group, parentNode, callback) {
var referenceDataItem, destTreeview = this._objectOrSelf(parentNode || group), destDataSource = destTreeview.dataSource;
var loadPromise = $.Deferred().resolve().promise();
if (parentNode && parentNode[0] != destTreeview.element[0]) {
referenceDataItem = destTreeview.dataItem(parentNode);
if (!referenceDataItem.loaded()) {
destTreeview._progress(parentNode, true);
loadPromise = referenceDataItem.load();
}
if (parentNode != this.root) {
destDataSource = referenceDataItem.children;
if (!destDataSource || !(destDataSource instanceof HierarchicalDataSource)) {
referenceDataItem._initChildren();
referenceDataItem.loaded(true);
destDataSource = referenceDataItem.children;
}
}
}
nodeData = this._toObservableData(nodeData);
return callback.call(destTreeview, destDataSource, nodeData, loadPromise);
},
_toObservableData: function(node) {
var dataItem = node, dataSource, uid;
if (isJQueryInstance(node) || isDomElement(node)) {
dataSource = this._objectOrSelf(node).dataSource;
uid = $(node).attr(kendo.attr("uid"));
dataItem = dataSource.getByUid(uid);
if (dataItem) dataItem = dataSource.remove(dataItem);
}
return dataItem;
},
_insert: function(data, model, index) {
if (!(model instanceof kendo.data.ObservableArray)) {
if (!isArray(model)) model = [model];
} else model = model.toJSON();
var parentNode = data.parent();
if (parentNode && parentNode._initChildren) {
parentNode.hasChildren = true;
parentNode._initChildren();
}
data.splice.apply(data, [index, 0].concat(model));
return this.findByUid(data[index].uid);
},
insertAfter: insertAction(1),
insertBefore: insertAction(0),
append: function(nodeData, parentNode, success) {
var group = this.root;
if (parentNode && nodeData instanceof jQuery && parentNode[0] === nodeData[0]) return;
parentNode = parentNode && parentNode.length ? parentNode : null;
if (parentNode) group = subGroup(parentNode);
return this._dataSourceMove(nodeData, group, parentNode, function(dataSource, model, loadModel) {
var inserted;
var that = this;
function add() {
if (parentNode) that._expanded(parentNode, true, true);
var data = dataSource.data(), index = Math.max(data.length, 0);
return that._insert(data, model, index);
}
loadModel.done(function() {
inserted = add();
success = success || $.noop;
success(inserted);
});
return inserted || null;
});
},
_remove: function(node, keepData) {
var that = this, parentNode, prevSibling, nextSibling;
node = $(node, that.element);
if (node.attr("id") === that.root.attr(ARIA_ACTIVEDESCENDANT)) that.root.removeAttr(ARIA_ACTIVEDESCENDANT);
parentNode = node.parent().parent();
prevSibling = node.prev();
nextSibling = node.next();
node[keepData ? "detach" : "remove"]();
if (parentNode.hasClass("k-treeview-item")) {
updateNodeHtml(parentNode);
that._updateNodeClasses(parentNode);
}
that._updateNodeClasses(prevSibling);
that._updateNodeClasses(nextSibling);
return node;
},
remove: function(node) {
var dataItem = this.dataItem(node);
if (dataItem) this.dataSource.remove(dataItem);
},
detach: function(node) {
return this._remove(node, true);
},
findByText: function(text) {
return $(this.element).find(".k-treeview-leaf").filter(function(i, element) {
return $(element).text() == text;
}).closest(NODE);
},
findByUid: function(uid) {
var items = this.element.find(".k-treeview-item");
var uidAttr = kendo.attr("uid");
var result;
for (var i = 0; i < items.length; i++) if (items[i].getAttribute(uidAttr) == uid) {
result = items[i];
break;
}
return $(result);
},
expandPath: function(path, complete) {
var treeview = this;
var nodeIds = path.slice(0);
var callback = complete || $.noop;
function proceed() {
nodeIds.shift();
if (nodeIds.length) expand(nodeIds[0]).then(proceed);
else callback.call(treeview);
}
function expand(id) {
var result = $.Deferred();
var node = treeview.dataSource.get(id);
var expandedAttr = kendo.attr("expanded");
var nodeElement;
if (node) {
nodeElement = treeview.findByUid(node.uid);
if (node.loaded()) {
node.set("expanded", true);
nodeElement.attr(expandedAttr, true);
nodeElement.attr(ARIA_EXPANDED, true);
result.resolve();
} else {
treeview._progress(nodeElement, true);
node.load().then(function() {
node.set("expanded", true);
nodeElement.attr(expandedAttr, true);
nodeElement.attr(ARIA_EXPANDED, true);
result.resolve();
});
}
} else result.resolve();
return result.promise();
}
expand(nodeIds[0]).then(proceed);
},
_parentIds: function(node) {
var parent = node && node.parentNode();
var parents = [];
while (parent && parent.parentNode) {
parents.unshift(parent.id);
parent = parent.parentNode();
}
return parents;
},
expandTo: function(node) {
if (!(node instanceof kendo.data.Node)) node = this.dataSource.get(node);
var parents = this._parentIds(node);
this.expandPath(parents);
},
_renderItem: function(options) {
if (!options.group) options.group = {};
options.treeview = this.options;
options.r = this.templates;
return this.templates.item(options);
},
_renderGroup: function(options) {
var that = this;
options.renderItems = function(options) {
var html = "", i = 0, items = options.items, len = items ? items.length : 0, group = options.group;
group.length = len;
for (; i < len; i++) {
options.group = group;
options.item = items[i];
options.item.index = i;
html += that._renderItem(options);
}
return html;
};
options.r = that.templates;
return that.templates.group(options);
}
});
kendo.cssProperties.registerPrefix("TreeView", "k-treeview-");
ui.plugin(TreeView);
})(window.kendo.jQuery);
var kendo_treeview_default = kendo;
//#endregion
exports.__meta__ = __meta__;
exports.default = kendo_treeview_default;