/**
* Kendo UI v2016.1.112 (http://www.telerik.com/kendo-ui)
* Copyright 2016 Telerik AD. All rights reserved.
*
* Kendo UI commercial licenses may be obtained at
* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete
* If you do not own a commercial license, this file shall be governed by the trial license terms.
*/
(function (f, define) {
define('kendo.treeview', [
'kendo.data',
'kendo.treeview.draganddrop'
], f);
}(function () {
var __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'],
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, extend = $.extend, template = kendo.template, isArray = $.isArray, Widget = ui.Widget, HierarchicalDataSource = data.HierarchicalDataSource, proxy = $.proxy, keys = kendo.keys, NS = '.kendoTreeView', SELECT = 'select', CHECK = 'check', NAVIGATE = 'navigate', EXPAND = 'expand', CHANGE = 'change', ERROR = 'error', CHECKED = 'checked', INDETERMINATE = 'indeterminate', COLLAPSE = 'collapse', DRAGSTART = 'dragstart', DRAG = 'drag', DROP = 'drop', DRAGEND = 'dragend', DATABOUND = 'dataBound', CLICK = 'click', UNDEFINED = 'undefined', KSTATEHOVER = 'k-state-hover', KTREEVIEW = 'k-treeview', VISIBLE = ':visible', NODE = '.k-item', STRING = 'string', ARIASELECTED = 'aria-selected', ARIADISABLED = 'aria-disabled', TreeView, subGroup, nodeContents, nodeIcon, spriteRe, bindings = {
text: 'dataTextField',
url: 'dataUrlField',
spriteCssClass: 'dataSpriteCssClassField',
imageUrl: 'dataImageUrlField'
}, isDomElement = function (o) {
return typeof HTMLElement === 'object' ? o instanceof HTMLElement : o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === STRING;
};
function contentChild(filter) {
return function (node) {
var result = node.children('.k-animation-container');
if (!result.length) {
result = node;
}
return result.children(filter);
};
}
function templateNoWith(code) {
return kendo.template(code, { useWithBlock: false });
}
subGroup = contentChild('.k-group');
nodeContents = contentChild('.k-group,.k-content');
nodeIcon = function (node) {
return node.children('div').children('.k-icon');
};
function checkboxes(node) {
return node.find('> div .k-checkbox-wrapper [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) {
return this._insert(dataSource.data(), model, referenceNode.index() + 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 = $.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.children('.k-icon'), checkbox = node.children(':checkbox'), innerWrapper = wrapper.children('.k-in');
if (node.hasClass('k-treeview')) {
return;
}
if (!wrapper.length) {
wrapper = $('
').prependTo(node);
}
if (!toggleButton.length && group.length) {
toggleButton = $('').prependTo(wrapper);
} else if (!group.length || !group.children().length) {
toggleButton.remove();
group.remove();
}
if (checkbox.length) {
$('').appendTo(wrapper).append(checkbox);
}
if (!innerWrapper.length) {
innerWrapper = node.children('a').eq(0).addClass('k-in');
if (!innerWrapper.length) {
innerWrapper = $('');
}
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;
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._tabindex();
that.root.attr('role', 'tree');
that._dataSource(inferred);
that._attachEvents();
that._dragging();
if (!inferred) {
if (options.autoBind) {
that._progress(true);
that.dataSource.fetch();
}
} 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);
}
kendo.notify(that);
},
_attachEvents: function () {
var that = this, clickableItems = '.k-in:not(.k-state-selected,.k-state-disabled)', MOUSEENTER = 'mouseenter';
that.wrapper.on(MOUSEENTER + NS, '.k-in.k-state-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, proxy(that._click, that)).on('dblclick' + NS, '.k-in:not(.k-state-disabled)', proxy(that._toggleButtonClick, that)).on(CLICK + NS, '.k-plus,.k-minus', proxy(that._toggleButtonClick, that)).on('keydown' + NS, proxy(that._keydown, that)).on('focus' + NS, proxy(that._focus, that)).on('blur' + NS, proxy(that._blur, that)).on('mousedown' + NS, '.k-in,.k-checkbox-wrapper :checkbox,.k-plus,.k-minus', proxy(that._mousedown, that)).on('change' + NS, '.k-checkbox-wrapper :checkbox', proxy(that._checkboxChange, that)).on('click' + NS, '.k-checkbox-wrapper :checkbox', proxy(that._checkboxClick, that)).on('click' + NS, '.k-request-retry', proxy(that._retryRequest, that)).on('click' + NS, function (e) {
if (!$(e.target).is(':kendoFocusable')) {
that.focus();
}
});
},
_checkboxClick: function (e) {
var checkbox = $(e.target);
if (checkbox.data(INDETERMINATE)) {
checkbox.data(INDETERMINATE, false).prop(INDETERMINATE, false).prop(CHECKED, true);
this._checkboxChange(e);
}
},
_syncHtmlAndDataSource: function (root, dataSource) {
root = root || this.root;
dataSource = dataSource || this.dataSource;
var data = dataSource.view();
var uidAttr = kendo.attr('uid');
var expandedAttr = kendo.attr('expanded');
var inferCheckedState = this.options.checkboxes;
var items = root.children('li');
var i, item, dataItem;
for (i = 0; i < items.length; i++) {
dataItem = data[i];
item = items.eq(i);
item.attr('role', 'treeitem').attr(uidAttr, dataItem.uid);
dataItem.expanded = item.attr(expandedAttr) === 'true';
if (inferCheckedState) {
dataItem.checked = checkboxes(item).prop(CHECKED);
}
this._syncHtmlAndDataSource(item.children('ul'), dataItem.children);
}
},
_animation: function () {
var options = this.options, animationOptions = options.animation;
if (animationOptions === false) {
animationOptions = {
expand: { effects: {} },
collapse: {
hide: true,
effects: {}
}
};
} else if (!animationOptions.collapse || !('effects' in animationOptions.collapse)) {
animationOptions.collapse = extend({ reverse: true }, animationOptions.expand);
}
extend(animationOptions.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,
$angular: this.options.$angular,
autoScroll: this.options.autoScroll,
filter: 'div:not(.k-state-disabled) .k-in',
allowedContainers: '.k-treeview',
itemSelector: '.k-treeview .k-item',
hintText: proxy(this._hintText, this),
contains: function (source, destination) {
return $.contains(source, destination);
},
dropHintContainer: function (item) {
return item;
},
itemFromTarget: function (target) {
var item = target.closest('.k-top,.k-mid,.k-bot');
return {
item: item,
content: target.closest('.k-in'),
first: item.hasClass('k-top'),
last: item.hasClass('k-bot')
};
},
dropPositionFrom: function (dropHint) {
return dropHint.prevAll('.k-in').length > 0 ? 'after' : 'before';
},
dragstart: function (source) {
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) {
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;
function triggerDragEnd(source) {
widget.updateIndeterminate();
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;
}
},
_hintText: function (node) {
return this.templates.dragClue({
item: this.dataItem(node),
treeview: this.options
});
},
_templates: function () {
var that = this, options = that.options, fieldAccessor = proxy(that._fieldAccessor, that);
if (options.template && typeof options.template == STRING) {
options.template = template(options.template);
} else if (!options.template) {
options.template = templateNoWith('# var text = ' + fieldAccessor('text') + '(data.item); #' + '# if (typeof data.item.encoded != \'undefined\' && data.item.encoded === false) {#' + '#= text #' + '# } else { #' + '#: text #' + '# } #');
}
that._checkboxes();
that.templates = {
wrapperCssClass: function (group, item) {
var result = 'k-item', index = item.index;
if (group.firstLevel && index === 0) {
result += ' k-first';
}
if (index == group.length - 1) {
result += ' k-last';
}
return result;
},
cssClass: function (group, item) {
var result = '', index = item.index, groupLength = group.length - 1;
if (group.firstLevel && index === 0) {
result += 'k-top ';
}
if (index === 0 && index != groupLength) {
result += 'k-top';
} else if (index == groupLength) {
result += 'k-bot';
} else {
result += 'k-mid';
}
return result;
},
textClass: function (item) {
var result = 'k-in';
if (item.enabled === false) {
result += ' k-state-disabled';
}
if (item.selected === true) {
result += ' k-state-selected';
}
return result;
},
toggleButtonClass: function (item) {
var result = 'k-icon';
if (item.expanded !== true) {
result += ' k-plus';
} else {
result += ' k-minus';
}
if (item.enabled === false) {
result += '-disabled';
}
return result;
},
groupAttributes: function (group) {
var attributes = '';
if (!group.firstLevel) {
attributes = 'role=\'group\'';
}
return attributes + (group.expanded !== true ? ' style=\'display:none\'' : '');
},
groupCssClass: function (group) {
var cssClass = 'k-group';
if (group.firstLevel) {
cssClass += ' k-treeview-lines';
}
return cssClass;
},
dragClue: templateNoWith('#= data.treeview.template(data) #'),
group: templateNoWith('' + '#= data.renderItems(data) #' + '
'),
itemContent: templateNoWith('# var imageUrl = ' + fieldAccessor('imageUrl') + '(data.item); #' + '# var spriteCssClass = ' + fieldAccessor('spriteCssClass') + '(data.item); #' + '# if (imageUrl) { #' + '
' + '# } #' + '# if (spriteCssClass) { #' + '' + '# } #' + '#= data.treeview.template(data) #'),
itemElement: templateNoWith('# var item = data.item, r = data.r; #' + '# var url = ' + fieldAccessor('url') + '(item); #' + '' + '# if (item.hasChildren) { #' + '' + '# } #' + '# if (data.treeview.checkboxes) { #' + '' + '#= data.treeview.checkboxes.template(data) #' + '' + '# } #' + '# var tag = url ? \'a\' : \'span\'; #' + '# var textAttr = url ? \' href=\\\'\' + url + \'\\\'\' : \'\'; #' + '<#=tag# class=\'#= r.textClass(item) #\'#= textAttr #>' + '#= r.itemContent(data) #' + '#=tag#>' + '
'),
item: templateNoWith('# var item = data.item, r = data.r; #' + '' + '#= r.itemElement(data) #' + ''),
loading: templateNoWith(' #: data.messages.loading #'),
retry: templateNoWith('#: data.messages.requestFailed # ' + '')
};
},
items: function () {
return this.element.find('.k-item > div:first-child');
},
setDataSource: function (dataSource) {
var options = this.options;
options.dataSource = dataSource;
this._dataSource();
if (options.checkboxes && options.checkboxes.checkChildren) {
this.dataSource.one('change', $.proxy(this.updateIndeterminate, this, null));
}
if (this.options.autoBind) {
this.dataSource.fetch();
}
},
_bindDataSource: function () {
this._refreshHandler = proxy(this.refresh, this);
this._errorHandler = proxy(this._error, this);
this.dataSource.bind(CHANGE, this._refreshHandler);
this.dataSource.bind(ERROR, this._errorHandler);
},
_unbindDataSource: function () {
var dataSource = this.dataSource;
if (dataSource) {
dataSource.unbind(CHANGE, this._refreshHandler);
dataSource.unbind(ERROR, this._errorHandler);
}
},
_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,
EXPAND,
COLLAPSE,
SELECT,
CHANGE,
NAVIGATE,
CHECK
],
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
},
_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, result = '(function(item) {';
if (count === 0) {
result += 'return item[\'' + fieldName + '\'];';
} else {
result += 'var levels = [' + $.map(fieldBindings, function (x) {
return 'function(d){ return ' + kendo.expr(x) + '}';
}).join(',') + '];';
result += 'return levels[Math.min(item.level(), ' + count + '-1)](item)';
}
result += '})';
return result;
},
setOptions: function (options) {
Widget.fn.setOptions.call(this, options);
this._animation();
this._dragging();
this._templates();
},
_trigger: function (eventName, node) {
return this.trigger(eventName, { node: node.closest(NODE)[0] });
},
_setChecked: function (datasource, value) {
if (!datasource || !$.isFunction(datasource.view)) {
return;
}
for (var i = 0, nodes = datasource.view(); i < nodes.length; i++) {
nodes[i][CHECKED] = value;
if (nodes[i].children) {
this._setChecked(nodes[i].children, 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;
}
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;
if (subnodes.length) {
for (i = 0; i < subnodes.length; i++) {
this.updateIndeterminate(subnodes.eq(i));
}
checkbox = this._setIndeterminate(node);
if (checkbox && checkbox.prop(CHECKED)) {
this.dataItem(node).checked = true;
}
}
},
_bubbleIndeterminate: function (node) {
if (!node.length) {
return;
}
var parentNode = this.parent(node), checkbox;
if (parentNode.length) {
this._setIndeterminate(parentNode);
checkbox = parentNode.children('div').find('.k-checkbox-wrapper :checkbox');
if (checkbox.prop(INDETERMINATE) === false) {
this.dataItem(parentNode).set(CHECKED, checkbox.prop(CHECKED));
} else {
delete this.dataItem(parentNode).checked;
}
this._bubbleIndeterminate(parentNode);
}
},
_checkboxChange: function (e) {
var checkbox = $(e.target);
var isChecked = checkbox.prop(CHECKED);
var node = checkbox.closest(NODE);
var dataItem = this.dataItem(node);
if (dataItem.checked != isChecked) {
dataItem.set(CHECKED, isChecked);
this._trigger(CHECK, node);
}
},
_toggleButtonClick: function (e) {
this.toggle($(e.target).closest(NODE));
},
_mousedown: function (e) {
var node = $(e.currentTarget).closest(NODE);
this._clickTarget = node;
this.current(node);
},
_focusable: function (node) {
return node && node.length && node.is(':visible') && !node.find('.k-in:first').hasClass('k-state-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);
wrapper.focus();
for (i = 0; i < containers.length; i++) {
containers[i].scrollTop = offsets[i];
}
},
_blur: function () {
this.current().find('.k-in:first').removeClass('k-state-focused');
},
_enabled: function (node) {
return !node.children('div').children('.k-in').hasClass('k-state-disabled');
},
parent: function (node) {
var wrapperRe = /\bk-treeview\b/, itemRe = /\bk-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);
}
if (!that._enabled(result)) {
result = that._nextVisible(result);
}
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;
}
if (!that._enabled(result)) {
result = that._previousVisible(result);
}
return result;
},
_keydown: function (e) {
var that = this, key = e.keyCode, target, focused = that.current(), expanded = that._expanded(focused), checkbox = focused.find('.k-checkbox-wrapper:first :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 {
that.expand(focused);
}
} else if (!rtl && key == keys.LEFT || rtl && key == keys.RIGHT) {
if (expanded) {
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) {
if (!focused.find('.k-in:first').hasClass('k-state-selected')) {
if (!that._trigger(SELECT, focused)) {
that.select(focused);
}
}
} else if (key == keys.SPACEBAR && checkbox.length) {
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);
}
}
},
_click: function (e) {
var that = this, node = $(e.currentTarget), contents = nodeContents(node.closest(NODE)), href = node.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.hasClass('.k-state-selected') && !that._trigger(SELECT, node)) {
that.select(node);
}
},
_wrapper: function () {
var that = this, element = that.element, wrapper, root, wrapperClasses = 'k-widget k-treeview';
if (element.is('ul')) {
wrapper = element.wrap('').parent();
root = element;
} else {
wrapper = element;
root = wrapper.children('ul').eq(0);
}
that.wrapper = wrapper.addClass(wrapperClasses);
that.root = root;
},
_group: function (item) {
var that = this, firstLevel = item.hasClass(KTREEVIEW), group = {
firstLevel: firstLevel,
expanded: firstLevel || that._expanded(item)
}, groupElement = item.children('ul');
groupElement.addClass(that.templates.groupCssClass(group)).css('display', group.expanded ? '' : 'none');
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;
if (checkboxes) {
defaultTemplate = '';
checkboxes = extend({ template: defaultTemplate }, options.checkboxes);
if (typeof checkboxes.template == STRING) {
checkboxes.template = template(checkboxes.template);
}
options.checkboxes = checkboxes;
}
},
_updateNodeClasses: function (node, groupData, nodeData) {
var wrapper = node.children('div'), group = node.children('ul'), templates = this.templates;
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.children('.k-in').hasClass('k-state-disabled');
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.removeClass('k-first k-last').addClass(templates.wrapperCssClass(groupData, nodeData));
wrapper.removeClass('k-top k-mid k-bot').addClass(templates.cssClass(groupData, nodeData));
wrapper.children('.k-in').removeClass('k-in k-state-default k-state-disabled').addClass(templates.textClass(nodeData));
if (group.length || node.attr('data-hasChildren') == 'true') {
wrapper.children('.k-icon').removeClass('k-plus k-minus k-plus-disabled k-minus-disabled').addClass(templates.toggleButtonClass(nodeData));
group.addClass('k-group');
}
},
_processNodes: function (nodes, callback) {
var that = this;
that.element.find(nodes).each(function (index, item) {
callback.call(that, index, $(item).closest(NODE));
});
},
dataItem: function (node) {
var uid = $(node).closest(NODE).attr(kendo.attr('uid')), dataSource = this.dataSource;
return dataSource && dataSource.getByUid(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 = '', 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: item
});
}
node = $(nodeHtml);
if (!node.length) {
return;
}
that.angular('compile', function () {
return {
elements: node.get(),
data: nodeData.map(function (item) {
return { dataItem: item };
})
};
});
if (!group.length) {
group = $(that._renderGroup({ group: groupData })).appendTo(parentNode);
}
insertCallback(node, group);
if (parentNode.hasClass('k-item')) {
updateNodeHtml(parentNode);
that._updateNodeClasses(parentNode);
}
that._updateNodeClasses(node.prev().first());
that._updateNodeClasses(node.next().last());
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, !that._expanded(node.eq(i)));
}
}
}
return node;
},
_updateNodes: function (items, field) {
var that = this;
var i, node, nodeWrapper, item, isChecked, isCollapsed;
var context = {
treeview: that.options,
item: item
};
var render = field != 'expanded' && field != 'checked';
function setCheckedState(root, state) {
root.find('.k-checkbox-wrapper :checkbox').prop(CHECKED, state).data(INDETERMINATE, false).prop(INDETERMINATE, false);
}
if (field == 'selected') {
item = items[0];
node = that.findByUid(item.uid).find('.k-in:first').removeClass('k-state-hover').toggleClass('k-state-selected', item[field]).end();
if (item[field]) {
that.current(node);
}
node.attr(ARIASELECTED, !!item[field]);
} else {
var elements = $.map(items, function (item) {
return that.findByUid(item.uid).children('div');
});
if (render) {
that.angular('cleanup', function () {
return { elements: elements };
});
}
for (i = 0; i < items.length; i++) {
context.item = item = items[i];
nodeWrapper = elements[i];
node = nodeWrapper.parent();
if (render) {
nodeWrapper.children('.k-in').html(that.templates.itemContent(context));
}
if (field == CHECKED) {
isChecked = item[field];
setCheckedState(nodeWrapper, isChecked);
if (that.options.checkboxes.checkChildren) {
setCheckedState(node.children('.k-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-wrapper :checkbox').prop('disabled', !item[field]);
isCollapsed = !nodeContents(node).is(VISIBLE);
node.removeAttr(ARIADISABLED);
if (!item[field]) {
if (item.selected) {
item.set('selected', false);
}
if (item.expanded) {
item.set('expanded', false);
}
isCollapsed = true;
node.attr(ARIASELECTED, false).attr(ARIADISABLED, true);
}
that._updateNodeClasses(node, {}, {
enabled: item[field],
expanded: !isCollapsed
});
}
if (nodeWrapper.length) {
this.trigger('itemChange', {
item: nodeWrapper,
data: item,
ns: ui
});
}
}
if (render) {
that.angular('compile', function () {
return {
elements: elements,
data: $.map(items, function (item) {
return [{ dataItem: item }];
})
};
});
}
}
},
_appendItems: function (index, items, parentNode) {
var group = subGroup(parentNode);
var children = group.children();
var collapsed = !this._expanded(parentNode);
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);
if (this._expanded(parentNode)) {
this._updateNodeClasses(parentNode);
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('div'),
data: this.dataItem(child),
ns: ui
});
}
}
},
_refreshRoot: function (items) {
var groupHtml = this._renderGroup({
items: items,
group: {
firstLevel: true,
expanded: true
}
});
if (this.root.length) {
this._angularItems('cleanup');
var group = $(groupHtml);
this.root.attr('class', group.attr('class')).html(group.html());
} else {
this.root = this.wrapper.html(groupHtml).children('ul');
}
this.root.attr('role', 'tree');
var elements = this.root.children('.k-item');
for (var i = 0; i < items.length; i++) {
this.trigger('itemChange', {
item: elements.eq(i),
data: items[i],
ns: ui
});
}
this._angularItems('compile');
},
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 (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);
}
if (action != 'remove') {
for (i = 0; i < items.length; i++) {
if (!loadOnDemand || items[i].expanded) {
items[i].load();
}
}
}
this.trigger(DATABOUND, { node: node ? parentNode : undefined });
},
_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).addClass('k-i-refresh');
e.node.loaded(false);
} else {
this._progress(false);
this.element.html(retryHtml);
}
},
_retryRequest: function (e) {
e.preventDefault();
this.dataSource.fetch();
},
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) {
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, id = that._ariaId;
if (arguments.length > 0 && node && node.length) {
if (current) {
if (current[0].id === id) {
current.removeAttr('id');
}
current.find('.k-in:first').removeClass('k-state-focused');
}
current = that._current = $(node, element).closest(NODE);
current.find('.k-in:first').addClass('k-state-focused');
id = current[0].id || id;
if (id) {
that.wrapper.removeAttr('aria-activedescendant');
current.attr('id', id);
that.wrapper.attr('aria-activedescendant', id);
}
return;
}
if (!current) {
current = that._nextVisible($());
}
return current;
},
select: function (node) {
var that = this, element = that.element;
if (!arguments.length) {
return element.find('.k-state-selected').closest(NODE);
}
node = $(node, element).closest(NODE);
element.find('.k-state-selected').each(function () {
var dataItem = that.dataItem(this);
if (dataItem) {
dataItem.set('selected', false);
delete dataItem.selected;
} else {
$(this).removeClass('k-state-selected');
}
});
if (node.length) {
that.dataItem(node).set('selected', true);
}
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;
}
if (!this._trigger(direction, node)) {
this._expanded(node, expand);
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).is('.k-minus,.k-plus,.k-minus-disabled,.k-plus-disabled')) {
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._unbindDataSource();
if (that.dragging) {
that.dragging.destroy();
}
kendo.destroy(that.element);
that.root = that.wrapper = that.element = null;
},
_expanded: function (node, value) {
var expandedAttr = kendo.attr('expanded'), dataItem = this.dataItem(node);
if (arguments.length == 1) {
return node.attr(expandedAttr) === 'true' || dataItem && dataItem.expanded;
}
if (nodeContents(node).data('animating')) {
return;
}
if (dataItem) {
dataItem.set('expanded', value);
value = dataItem.expanded;
}
if (value) {
node.attr(expandedAttr, 'true');
node.attr('aria-expanded', 'true');
} else {
node.removeAttr(expandedAttr);
node.attr('aria-expanded', 'false');
}
},
_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();
}
} else {
nodeIcon(node).toggleClass('k-loading', showProgress).removeClass('k-i-refresh');
}
},
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 (node instanceof window.jQuery || 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) {
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);
}
var data = dataSource.data(), index = Math.max(data.length, 0);
return that._insert(data, model, index);
}
loadModel.then(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);
this.angular('cleanup', function () {
return { elements: node.get() };
});
parentNode = node.parent().parent();
prevSibling = node.prev();
nextSibling = node.next();
node[keepData ? 'detach' : 'remove']();
if (parentNode.hasClass('k-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-in').filter(function (i, element) {
return $(element).text() == text;
}).closest(NODE);
},
findByUid: function (uid) {
var items = this.element.find('.k-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) {
path = path.slice(0);
var treeview = this;
var dataSource = this.dataSource;
var node = dataSource.get(path[0]);
complete = complete || $.noop;
function tryExpand(node, complete, context) {
if (node && !node.loaded()) {
node.set('expanded', true);
} else {
complete.call(context);
}
}
while (path.length > 0 && node && (node.expanded || node.loaded())) {
node.set('expanded', true);
path.shift();
node = dataSource.get(path[0]);
}
if (!path.length) {
return complete.call(treeview);
}
dataSource.bind('change', function expandLevel(e) {
var id = e.node && e.node.id;
var node;
if (id && id === path[0]) {
path.shift();
if (path.length) {
node = dataSource.get(path[0]);
tryExpand(node, complete, treeview);
} else {
complete.call(treeview);
}
}
});
tryExpand(node, complete, treeview);
},
_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);
}
});
ui.plugin(TreeView);
}(window.kendo.jQuery));
return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
(a3 || a2)();
}));