UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,418 lines (1,164 loc) 86.7 kB
import './kendo.data.js'; import './kendo.treeview.draganddrop.js'; import './kendo.html.input.js'; import './kendo.icons.js'; import './kendo.core.js'; import './kendo.licensing.js'; import '@progress/kendo-licensing'; import './kendo.data.odata.js'; import './kendo.data.xml.js'; import './kendo.draganddrop.js'; import './kendo.userevents.js'; import './kendo.html.base.js'; import './kendo.html.icon.js'; import '@progress/kendo-svg-icons'; 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$1) { 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", 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 : //DOM2 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("div").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("div"), 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 = $("<div />").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(); // render treeview if it's not already rendered if (!element.hasClass(KTREEVIEW)) { that._wrapper(); if (list) { that.root = element; that._group(that.wrapper); } } else { // otherwise just initialize properties 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); }, _attachEvents: function() { var that = this, clickableItems = ".k-treeview-leaf:not(.k-selected,.k-disabled)", MOUSEENTER = "mouseenter"; that._clickHandler = that._click.bind(that); that.wrapper .on(MOUSEENTER + NS, ".k-treeview-leaf.k-selected", function(e) { e.preventDefault(); }) .on(MOUSEENTER + NS, clickableItems, function() { $(this).addClass(KSTATEHOVER); }) .on("mouseleave" + NS, clickableItems, function() { $(this).removeClass(KSTATEHOVER); }) .on(CLICK + NS, clickableItems, that._clickHandler) .on("dblclick" + NS, ".k-treeview-leaf:not(.k-disabled)", 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-leaf,.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-link.k-disabled", 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) { root = root || this.root; dataSource = dataSource || this.dataSource; var 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.hasClass("k-selected")); 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); } }, _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: "div: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-top,.k-treeview-mid,.k-treeview-bot"); return { item: item, content: target.closest(".k-treeview-leaf"), first: item.hasClass("k-treeview-top"), last: item.hasClass("k-treeview-bot") }; }, 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 dropTarget = $(options.dropTarget); var navigationTarget = 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 }); } // perform reorder / move // different handling is necessary because append might be async in remote bound tree 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 = "", index = item.index, groupLength = group.length - 1; if (group.firstLevel && index === 0) { result += "k-treeview-top "; } if (index === 0 && index != groupLength) { result += (result.indexOf("k-treeview-top") != -1) ? "" : "k-treeview-top"; } else if (index == groupLength) { result += "k-treeview-bot"; } else { result += "k-treeview-mid"; } return result; }, textClass: function(item, isLink) { var result = "k-treeview-leaf"; if (isLink) { result += " k-link"; } if (item.enabled === false) { result += " k-disabled"; } if (item.selected === true) { result += " k-selected"; } 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: `caret-alt-${kendo.support.isRtl(that.element) ? 'left' : 'right'}` }); } else { return ui.icon(icon, { icon: 'caret-alt-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 result = ""; if (imageUrl) { result += `<img ${that.templates.imageCssAttributes(imgAttributes)} alt='' src='${imageUrl}'>`; } if (spriteCssClass) { result += `<span class='k-sprite ${spriteCssClass}'></span>`; } result += data.treeview.template(data); return result; }, 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 = `<div 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 += "</div>"; return result; }, item: (data) => { var item = data.item, r = data.r; var result = `<li role='treeitem'` + `${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-button-md k-rounded-md k-button-solid k-button-solid-base 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 > div: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() { // If there are no items to be loaded ensure event is triggered on dataBound 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, options = that.options, dataSource = 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: "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: "medium" }, _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; } }, // generates accessor function for a given field name, honoring the data*Field arrays _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) { // top-down update of inital indeterminate state for all nodes 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) { // bottom-up setting of indeterminate state of parent nodes if (!node.length) { return; } if (!skipDownward) { //update the indeterminate state of the node itself this.updateIndeterminate(node); } var parentNode = this.parent(node), checkbox; if (parentNode.length) { this._setIndeterminate(parentNode); checkbox = parentNode.children("div").find(".k-checkbox-wrap input[type=checkbox]"); this._skip = true; if (checkbox.prop(INDETERMINATE) === false) { this.dataItem(parentNode).set(CHECKED, checkbox.prop(CHECKED)); } else { // delete this.dataItem(parentNode).checked; 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); }, _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; } //IE does not trigger change for indeterminate checkboxes 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.find(".k-treeview-leaf").first().hasClass(DISABLED); }, _focus: function() { var current = this.select(), clickTarget = this._clickTarget; // suppress initial focus state on touch devices (until keyboard is used) 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-treeview-leaf").first().removeClass("k-focus"); }, _enabled: function(node) { return !node.children("div").children(".k-treeview-leaf").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(); // expanded node with no children 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.find(".k-treeview-leaf").first().hasClass(DISABLED)) { that.expand(focused); } } else if ((!rtl && key == keys.LEFT) || (rtl && key == keys.RIGHT)) { if (expanded && !focused.find(".k-treeview-leaf").first().hasClass(DISABLED)) { that.collapse(focused); } else { target = that.parent(focused); if (!that._enabled(target)) { target = undefined$1; } } } 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.find(".k-treeview-leaf").first().hasClass(DISABLED)) { if (!focused.find(".k-treeview-leaf").first().hasClass("k-selected")) { if (!that._trigger(SELECT, focused)) { that.select(focused); } } } else if (key == keys.SPACEBAR && checkbox.length) { if (!focused.find(".k-treeview-leaf").first().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; var isPrintable = key.length === 1; if (!isPrintable) { 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); }