/** * 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.virtuallist', ['kendo.data'], f); }(function () { var __meta__ = { id: 'virtuallist', name: 'VirtualList', category: 'framework', depends: ['data'], hidden: true }; (function ($, undefined) { var kendo = window.kendo, ui = kendo.ui, Widget = ui.Widget, DataBoundWidget = ui.DataBoundWidget, proxy = $.proxy, WRAPPER = 'k-virtual-wrap', VIRTUALLIST = 'k-virtual-list', CONTENT = 'k-virtual-content', LIST = 'k-list', HEADER = 'k-group-header', VIRTUALITEM = 'k-virtual-item', ITEM = 'k-item', HEIGHTCONTAINER = 'k-height-container', GROUPITEM = 'k-group', SELECTED = 'k-state-selected', FOCUSED = 'k-state-focused', HOVER = 'k-state-hover', CHANGE = 'change', CLICK = 'click', LISTBOUND = 'listBound', ITEMCHANGE = 'itemChange', ACTIVATE = 'activate', DEACTIVATE = 'deactivate', VIRTUAL_LIST_NS = '.VirtualList'; function lastFrom(array) { return array[array.length - 1]; } function toArray(value) { return value instanceof Array ? value : [value]; } function isPrimitive(dataItem) { return typeof dataItem === 'string' || typeof dataItem === 'number' || typeof dataItem === 'boolean'; } function getItemCount(screenHeight, listScreens, itemHeight) { return Math.ceil(screenHeight * listScreens / itemHeight); } function appendChild(parent, className, tagName) { var element = document.createElement(tagName || 'div'); if (className) { element.className = className; } parent.appendChild(element); return element; } function getDefaultItemHeight() { var mockList = $('
'), lineHeight; mockList.css({ position: 'absolute', left: '-200000px', visibility: 'hidden' }); mockList.appendTo(document.body); lineHeight = parseFloat(kendo.getComputedStyles(mockList.find('.k-item')[0], ['line-height'])['line-height']); mockList.remove(); return lineHeight; } function bufferSizes(screenHeight, listScreens, opposite) { return { down: screenHeight * opposite, up: screenHeight * (listScreens - 1 - opposite) }; } function listValidator(options, screenHeight) { var downThreshold = (options.listScreens - 1 - options.threshold) * screenHeight; var upThreshold = options.threshold * screenHeight; return function (list, scrollTop, lastScrollTop) { if (scrollTop > lastScrollTop) { return scrollTop - list.top < downThreshold; } else { return list.top === 0 || scrollTop - list.top > upThreshold; } }; } function scrollCallback(element, callback) { return function (force) { return callback(element.scrollTop, force); }; } function syncList(reorder) { return function (list, force) { reorder(list.items, list.index, force); return list; }; } function position(element, y) { if (kendo.support.browser.msie && kendo.support.browser.version < 10) { element.style.top = y + 'px'; } else { element.style.webkitTransform = 'translateY(' + y + 'px)'; element.style.transform = 'translateY(' + y + 'px)'; } } function map2(callback, templates) { return function (arr1, arr2) { for (var i = 0, len = arr1.length; i < len; i++) { callback(arr1[i], arr2[i], templates); if (arr2[i].item) { this.trigger(ITEMCHANGE, { item: $(arr1[i]), data: arr2[i].item, ns: kendo.ui }); } } }; } function reshift(items, diff) { var range; if (diff > 0) { range = items.splice(0, diff); items.push.apply(items, range); } else { range = items.splice(diff, -diff); items.unshift.apply(items, range); } return range; } function render(element, data, templates) { var itemTemplate = templates.template; element = $(element); if (!data.item) { itemTemplate = templates.placeholderTemplate; } this.angular('cleanup', function () { return { elements: [element] }; }); element.attr('data-uid', data.item ? data.item.uid : '').attr('data-offset-index', data.index).html(itemTemplate(data.item || {})); element.toggleClass(FOCUSED, data.current); element.toggleClass(SELECTED, data.selected); element.toggleClass('k-first', data.newGroup); element.toggleClass('k-loading-item', !data.item); if (data.index !== 0 && data.newGroup) { $('
').appendTo(element).html(templates.groupTemplate(data.group)); } if (data.top !== undefined) { position(element[0], data.top); } this.angular('compile', function () { return { elements: [element], data: [{ dataItem: data.item, group: data.group, newGroup: data.newGroup }] }; }); } function mapChangedItems(selected, itemsToMatch) { var itemsLength = itemsToMatch.length; var selectedLength = selected.length; var dataItem; var found; var i, j; var changed = []; var unchanged = []; if (selectedLength) { for (i = 0; i < selectedLength; i++) { dataItem = selected[i]; found = false; for (j = 0; j < itemsLength; j++) { if (dataItem === itemsToMatch[j]) { found = true; changed.push({ index: i, item: dataItem }); break; } } if (!found) { unchanged.push(dataItem); } } } return { changed: changed, unchanged: unchanged }; } var VirtualList = DataBoundWidget.extend({ init: function (element, options) { var that = this; that.bound(false); that._fetching = false; Widget.fn.init.call(that, element, options); if (!that.options.itemHeight) { that.options.itemHeight = getDefaultItemHeight(); } options = that.options; that.element.addClass(LIST + ' ' + VIRTUALLIST).attr('role', 'listbox'); that.content = that.element.wrap('
').parent(); that.wrapper = that.content.wrap('
').parent(); that.header = that.content.before('
').prev(); that.element.on('mouseenter' + VIRTUAL_LIST_NS, 'li:not(.k-loading-item)', function () { $(this).addClass(HOVER); }).on('mouseleave' + VIRTUAL_LIST_NS, 'li', function () { $(this).removeClass(HOVER); }); that._values = toArray(that.options.value); that._selectedDataItems = []; that._selectedIndexes = []; that._rangesList = {}; that._activeDeferred = null; that._promisesList = []; that._optionID = kendo.guid(); that.setDataSource(options.dataSource); that.content.on('scroll' + VIRTUAL_LIST_NS, kendo.throttle(function () { that._renderItems(); that._triggerListBound(); }, options.delay)); that._selectable(); }, options: { name: 'VirtualList', autoBind: true, delay: 100, height: null, listScreens: 4, threshold: 0.5, itemHeight: null, oppositeBuffer: 1, type: 'flat', selectable: false, value: [], dataValueField: null, template: '#:data#', placeholderTemplate: 'loading...', groupTemplate: '#:data#', fixedGroupTemplate: 'fixed header template', valueMapper: null }, events: [ CHANGE, CLICK, LISTBOUND, ITEMCHANGE, ACTIVATE, DEACTIVATE ], setOptions: function (options) { Widget.fn.setOptions.call(this, options); if (this._selectProxy && this.options.selectable === false) { this.element.off(CLICK, '.' + VIRTUALITEM, this._selectProxy); } else if (!this._selectProxy && this.options.selectable) { this._selectable(); } this.refresh(); }, items: function () { return $(this._items); }, destroy: function () { this.wrapper.off(VIRTUAL_LIST_NS); this.dataSource.unbind(CHANGE, this._refreshHandler); Widget.fn.destroy.call(this); }, setDataSource: function (source) { var that = this; var dataSource = source || {}; var value; dataSource = $.isArray(dataSource) ? { data: dataSource } : dataSource; dataSource = kendo.data.DataSource.create(dataSource); if (that.dataSource) { that.dataSource.unbind(CHANGE, that._refreshHandler); that._clean(); that.bound(false); that._deferValueSet = true; value = that.value(); that.value([]); that.mute(function () { that.value(value); }); } else { that._refreshHandler = $.proxy(that.refresh, that); } that.dataSource = dataSource.bind(CHANGE, that._refreshHandler); that.setDSFilter(dataSource.filter()); if (dataSource.view().length !== 0) { that.refresh(); } else if (that.options.autoBind) { dataSource.fetch(); } }, skip: function () { return this.dataSource.currentRangeStart(); }, _triggerListBound: function () { var that = this; var skip = that.skip(); if (that.bound() && !that._selectingValue && that._skip !== skip) { that._skip = skip; that.trigger(LISTBOUND); } }, _getValues: function (dataItems) { var getter = this._valueGetter; return $.map(dataItems, function (dataItem) { return getter(dataItem); }); }, refresh: function (e) { var that = this; var action = e && e.action; var isItemChange = action === 'itemchange'; var filtered = this.isFiltered(); var result; if (that._mute) { return; } that._deferValueSet = false; if (!that._fetching) { if (filtered) { that.focus(0); } that._createList(); if (!action && that._values.length && !filtered && !that.options.skipUpdateOnBind) { that._selectingValue = true; that.value(that._values, true).done(function () { that.bound(true); that._selectingValue = false; that._triggerListBound(); }); } else { that.bound(true); that._triggerListBound(); } } else { if (that._renderItems) { that._renderItems(true); } that._triggerListBound(); } if (isItemChange || action === 'remove') { result = mapChangedItems(that._selectedDataItems, e.items); if (result.changed.length) { if (isItemChange) { that.trigger('selectedItemChange', { items: result.changed }); } else { that.value(that._getValues(result.unchanged)); } } } that._fetching = false; }, removeAt: function (position) { this._selectedIndexes.splice(position, 1); this._values.splice(position, 1); return { position: position, dataItem: this._selectedDataItems.splice(position, 1)[0] }; }, setValue: function (value) { this._values = toArray(value); }, value: function (value, _forcePrefetch) { var that = this; if (value === undefined) { return that._values.slice(); } if (value === null) { value = []; } value = toArray(value); if (that.options.selectable === 'multiple' && that.select().length && value.length) { that.select(-1); } if (!that._valueDeferred || that._valueDeferred.state() === 'resolved') { that._valueDeferred = $.Deferred(); } if (!value.length) { that.select(-1); } that._values = value; if (that.bound() && !that._mute && !that._deferValueSet || _forcePrefetch) { that._prefetchByValue(value); } return that._valueDeferred; }, _prefetchByValue: function (value) { var that = this, dataView = that._dataView, valueGetter = that._valueGetter, item, match = false, forSelection = []; for (var i = 0; i < value.length; i++) { for (var idx = 0; idx < dataView.length; idx++) { item = dataView[idx].item; if (item) { match = isPrimitive(item) ? value[i] === item : value[i] === valueGetter(item); if (match) { forSelection.push(dataView[idx].index); } } } } if (forSelection.length === value.length) { that._values = []; that.select(forSelection); return; } if (typeof that.options.valueMapper === 'function') { that.options.valueMapper({ value: this.options.selectable === 'multiple' ? value : value[0], success: function (indexes) { that._values = []; that._selectedIndexes = []; that._selectedDataItems = []; indexes = toArray(indexes); if (!indexes.length) { indexes = [-1]; } that.select(indexes); } }); } else { throw new Error('valueMapper is not provided'); } }, deferredRange: function (index) { var dataSource = this.dataSource; var take = this.itemCount; var ranges = this._rangesList; var result = $.Deferred(); var defs = []; var low = Math.floor(index / take) * take; var high = Math.ceil(index / take) * take; var pages = high === low ? [high] : [ low, high ]; $.each(pages, function (_, skip) { var end = skip + take; var existingRange = ranges[skip]; var deferred; if (!existingRange || existingRange.end !== end) { deferred = $.Deferred(); ranges[skip] = { end: end, deferred: deferred }; dataSource._multiplePrefetch(skip, take, function () { deferred.resolve(); }); } else { deferred = existingRange.deferred; } defs.push(deferred); }); $.when.apply($, defs).then(function () { result.resolve(); }); return result; }, prefetch: function (indexes) { var that = this, take = this.itemCount, isEmptyList = !that._promisesList.length; if (!that._activeDeferred) { that._activeDeferred = $.Deferred(); that._promisesList = []; } $.each(indexes, function (_, index) { var rangeStart = Math.floor(index / take) * take; that._promisesList.push(that.deferredRange(rangeStart)); }); if (isEmptyList) { $.when.apply($, that._promisesList).done(function () { that._activeDeferred.resolve(); that._activeDeferred = null; that._promisesList = []; }); } return that._activeDeferred; }, _findDataItem: function (index) { var view = this.dataSource.view(), group; if (this.options.type === 'group') { for (var i = 0; i < view.length; i++) { group = view[i].items; if (group.length <= index) { index = index - group.length; } else { return group[index]; } } } return view[index]; }, selectedDataItems: function () { return this._selectedDataItems.slice(); }, scrollTo: function (y) { this.content.scrollTop(y); }, scrollToIndex: function (index) { this.scrollTo(index * this.options.itemHeight); }, focus: function (candidate) { var element, index, data, current, itemHeight = this.options.itemHeight, id = this._optionID, triggerEvent = true; if (candidate === undefined) { current = this.element.find('.' + FOCUSED); return current.length ? current : null; } if (typeof candidate === 'function') { data = this.dataSource.flatView(); for (var idx = 0; idx < data.length; idx++) { if (candidate(data[idx])) { candidate = idx; break; } } } if (candidate instanceof Array) { candidate = lastFrom(candidate); } if (isNaN(candidate)) { element = $(candidate); index = parseInt($(element).attr('data-offset-index'), 10); } else { index = candidate; element = this._getElementByIndex(index); } if (index === -1) { this.element.find('.' + FOCUSED).removeClass(FOCUSED); this._focusedIndex = undefined; return; } if (element.length) { if (element.hasClass(FOCUSED)) { triggerEvent = false; } if (this._focusedIndex !== undefined) { current = this._getElementByIndex(this._focusedIndex); current.removeClass(FOCUSED).removeAttr('id'); if (triggerEvent) { this.trigger(DEACTIVATE); } } this._focusedIndex = index; element.addClass(FOCUSED).attr('id', id); var position = this._getElementLocation(index); if (position === 'top') { this.scrollTo(index * itemHeight); } else if (position === 'bottom') { this.scrollTo(index * itemHeight + itemHeight - this.screenHeight); } else if (position === 'outScreen') { this.scrollTo(index * itemHeight); } if (triggerEvent) { this.trigger(ACTIVATE); } } else { this._focusedIndex = index; this.items().removeClass(FOCUSED); this.scrollToIndex(index); } }, focusIndex: function () { return this._focusedIndex; }, focusFirst: function () { this.scrollTo(0); this.focus(0); }, focusLast: function () { var lastIndex = this.dataSource.total(); this.scrollTo(this.heightContainer.offsetHeight); this.focus(lastIndex); }, focusPrev: function () { var index = this._focusedIndex; var current; if (!isNaN(index) && index > 0) { index -= 1; this.focus(index); current = this.focus(); if (current && current.hasClass('k-loading-item')) { index += 1; this.focus(index); } return index; } else { index = this.dataSource.total() - 1; this.focus(index); return index; } }, focusNext: function () { var index = this._focusedIndex; var lastIndex = this.dataSource.total() - 1; var current; if (!isNaN(index) && index < lastIndex) { index += 1; this.focus(index); current = this.focus(); if (current && current.hasClass('k-loading-item')) { index -= 1; this.focus(index); } return index; } else { index = 0; this.focus(index); return index; } }, _triggerChange: function (removed, added) { removed = removed || []; added = added || []; if (removed.length || added.length) { this.trigger(CHANGE, { removed: removed, added: added }); } }, select: function (candidate) { var that = this, indices, singleSelection = that.options.selectable !== 'multiple', prefetchStarted = !!that._activeDeferred, filtered = this.isFiltered(), isAlreadySelected, deferred, result, removed = []; if (candidate === undefined) { return that._selectedIndexes.slice(); } indices = that._getIndecies(candidate); isAlreadySelected = singleSelection && !filtered && lastFrom(indices) === lastFrom(this._selectedIndexes); removed = that._deselectCurrentValues(indices); if (removed.length || !indices.length || isAlreadySelected) { that._triggerChange(removed); if (that._valueDeferred) { that._valueDeferred.resolve(); } return; } if (indices.length === 1 && indices[0] === -1) { indices = []; } result = that._deselect(indices); removed = result.removed; indices = result.indices; if (singleSelection) { that._activeDeferred = null; prefetchStarted = false; if (indices.length) { indices = [lastFrom(indices)]; } } var done = function () { var added = that._select(indices); that.focus(indices); that._triggerChange(removed, added); if (that._valueDeferred) { that._valueDeferred.resolve(); } }; deferred = that.prefetch(indices); if (!prefetchStarted) { if (deferred) { deferred.done(done); } else { done(); } } }, bound: function (bound) { if (bound === undefined) { return this._listCreated; } this._listCreated = bound; }, mute: function (callback) { this._mute = true; proxy(callback(), this); this._mute = false; }, setDSFilter: function (filter) { this._lastDSFilter = $.extend({}, filter); }, isFiltered: function () { if (!this._lastDSFilter) { this.setDSFilter(this.dataSource.filter()); } return !kendo.data.Query.compareFilters(this.dataSource.filter(), this._lastDSFilter); }, skipUpdate: $.noop, _getElementByIndex: function (index) { return this.items().filter(function (idx, element) { return index === parseInt($(element).attr('data-offset-index'), 10); }); }, _clean: function () { this.result = undefined; this._lastScrollTop = undefined; this._skip = undefined; $(this.heightContainer).remove(); this.heightContainer = undefined; this.element.empty(); }, _height: function () { var hasData = !!this.dataSource.view().length, height = this.options.height, itemHeight = this.options.itemHeight, total = this.dataSource.total(); if (!hasData) { height = 0; } else if (height / itemHeight > total) { height = total * itemHeight; } return height; }, _screenHeight: function () { var height = this._height(), content = this.content; content.height(height); this.screenHeight = height; }, _getElementLocation: function (index) { var scrollTop = this.content.scrollTop(), screenHeight = this.screenHeight, itemHeight = this.options.itemHeight, yPosition = index * itemHeight, yDownPostion = yPosition + itemHeight, screenEnd = scrollTop + screenHeight, position; if (yPosition === scrollTop - itemHeight || yDownPostion > scrollTop && yPosition < scrollTop) { position = 'top'; } else if (yPosition === screenEnd || yPosition < screenEnd && screenEnd < yDownPostion) { position = 'bottom'; } else if (yPosition >= scrollTop && yPosition <= scrollTop + (screenHeight - itemHeight)) { position = 'inScreen'; } else { position = 'outScreen'; } return position; }, _templates: function () { var templates = { template: this.options.template, placeholderTemplate: this.options.placeholderTemplate, groupTemplate: this.options.groupTemplate, fixedGroupTemplate: this.options.fixedGroupTemplate }; for (var key in templates) { if (typeof templates[key] !== 'function') { templates[key] = kendo.template(templates[key]); } } this.templates = templates; }, _generateItems: function (element, count) { var items = [], item, itemHeight = this.options.itemHeight + 'px'; while (count-- > 0) { item = document.createElement('li'); item.tabIndex = -1; item.className = VIRTUALITEM + ' ' + ITEM; item.setAttribute('role', 'option'); item.style.height = itemHeight; item.style.minHeight = itemHeight; element.appendChild(item); items.push(item); } return items; }, _saveInitialRanges: function () { var ranges = this.dataSource._ranges; var deferred = $.Deferred(); deferred.resolve(); this._rangesList = {}; for (var i = 0; i < ranges.length; i++) { this._rangesList[ranges[i].start] = { end: ranges[i].end, deferred: deferred }; } }, _createList: function () { var that = this, content = that.content.get(0), options = that.options, dataSource = that.dataSource; if (that.bound()) { that._clean(); } that._saveInitialRanges(); that._screenHeight(); that._buildValueGetter(); that.itemCount = getItemCount(that.screenHeight, options.listScreens, options.itemHeight); if (that.itemCount > dataSource.total()) { that.itemCount = dataSource.total(); } that._templates(); that._items = that._generateItems(that.element[0], that.itemCount); that._setHeight(options.itemHeight * dataSource.total()); that.options.type = (dataSource.group() || []).length ? 'group' : 'flat'; if (that.options.type === 'flat') { that.header.hide(); } else { that.header.show(); } that.getter = that._getter(function () { that._renderItems(true); }); that._onScroll = function (scrollTop, force) { var getList = that._listItems(that.getter); return that._fixedHeader(scrollTop, getList(scrollTop, force)); }; that._renderItems = that._whenChanged(scrollCallback(content, that._onScroll), syncList(that._reorderList(that._items, $.proxy(render, that)))); that._renderItems(); that._calculateGroupPadding(that.screenHeight); }, _setHeight: function (height) { var currentHeight, heightContainer = this.heightContainer; if (!heightContainer) { heightContainer = this.heightContainer = appendChild(this.content[0], HEIGHTCONTAINER); } else { currentHeight = heightContainer.offsetHeight; } if (height !== currentHeight) { heightContainer.innerHTML = ''; while (height > 0) { var padHeight = Math.min(height, 250000); appendChild(heightContainer).style.height = padHeight + 'px'; height -= padHeight; } } }, _getter: function () { var lastRequestedRange = null, dataSource = this.dataSource, lastRangeStart = dataSource.skip(), type = this.options.type, pageSize = this.itemCount, flatGroups = {}; if (dataSource.pageSize() < pageSize) { this.mute(function () { dataSource.pageSize(pageSize); }); } return function (index, rangeStart) { var that = this; if (!dataSource.inRange(rangeStart, pageSize)) { if (lastRequestedRange !== rangeStart) { lastRequestedRange = rangeStart; lastRangeStart = rangeStart; if (that._getterDeferred) { that._getterDeferred.reject(); } that._getterDeferred = that.deferredRange(rangeStart); that._getterDeferred.then(function () { var firstItemIndex = that._indexConstraint(that.content[0].scrollTop); that._getterDeferred = null; if (rangeStart <= firstItemIndex && firstItemIndex <= rangeStart + pageSize) { that._fetching = true; dataSource.range(rangeStart, pageSize); } }); } return null; } else { if (lastRangeStart !== rangeStart) { this.mute(function () { dataSource.range(rangeStart, pageSize); lastRangeStart = rangeStart; }); } var result; if (type === 'group') { if (!flatGroups[rangeStart]) { var flatGroup = flatGroups[rangeStart] = []; var groups = dataSource.view(); for (var i = 0, len = groups.length; i < len; i++) { var group = groups[i]; for (var j = 0, groupLength = group.items.length; j < groupLength; j++) { flatGroup.push({ item: group.items[j], group: group.value }); } } } result = flatGroups[rangeStart][index - rangeStart]; } else { result = dataSource.view()[index - rangeStart]; } return result; } }; }, _fixedHeader: function (scrollTop, list) { var group = this.currentVisibleGroup, itemHeight = this.options.itemHeight, firstVisibleDataItemIndex = Math.floor((scrollTop - list.top) / itemHeight), firstVisibleDataItem = list.items[firstVisibleDataItemIndex]; if (firstVisibleDataItem && firstVisibleDataItem.item) { var firstVisibleGroup = firstVisibleDataItem.group; if (firstVisibleGroup !== group) { this.header[0].innerHTML = firstVisibleGroup || ''; this.currentVisibleGroup = firstVisibleGroup; } } return list; }, _itemMapper: function (item, index, value) { var listType = this.options.type, itemHeight = this.options.itemHeight, currentIndex = this._focusedIndex, selected = false, current = false, newGroup = false, group = null, match = false, valueGetter = this._valueGetter; if (listType === 'group') { if (item) { newGroup = index === 0 || this._currentGroup && this._currentGroup !== item.group; this._currentGroup = item.group; } group = item ? item.group : null; item = item ? item.item : null; } if (!this.isFiltered() && value.length && item) { for (var i = 0; i < value.length; i++) { match = isPrimitive(item) ? value[i] === item : value[i] === valueGetter(item); if (match) { value.splice(i, 1); selected = true; break; } } } if (currentIndex === index) { current = true; } return { item: item ? item : null, group: group, newGroup: newGroup, selected: selected, current: current, index: index, top: index * itemHeight }; }, _range: function (index) { var itemCount = this.itemCount, value = this._values.slice(), items = [], item; this._view = {}; this._currentGroup = null; for (var i = index, length = index + itemCount; i < length; i++) { item = this._itemMapper(this.getter(i, index), i, value); items.push(item); this._view[item.index] = item; } this._dataView = items; return items; }, _getDataItemsCollection: function (scrollTop, lastScrollTop) { var items = this._range(this._listIndex(scrollTop, lastScrollTop)); return { index: items.length ? items[0].index : 0, top: items.length ? items[0].top : 0, items: items }; }, _listItems: function () { var screenHeight = this.screenHeight, options = this.options; var theValidator = listValidator(options, screenHeight); return $.proxy(function (value, force) { var result = this.result, lastScrollTop = this._lastScrollTop; if (force || !result || !theValidator(result, value, lastScrollTop)) { result = this._getDataItemsCollection(value, lastScrollTop); } this._lastScrollTop = value; this.result = result; return result; }, this); }, _whenChanged: function (getter, callback) { var current; return function (force) { var theNew = getter(force); if (theNew !== current) { current = theNew; callback(theNew, force); } }; }, _reorderList: function (list, reorder) { var that = this; var length = list.length; var currentOffset = -Infinity; reorder = $.proxy(map2(reorder, this.templates), this); return function (list2, offset, force) { var diff = offset - currentOffset; var range, range2; if (force || Math.abs(diff) >= length) { range = list; range2 = list2; } else { range = reshift(list, diff); range2 = diff > 0 ? list2.slice(-diff) : list2.slice(0, -diff); } reorder(range, range2, that.bound()); currentOffset = offset; }; }, _bufferSizes: function () { var options = this.options; return bufferSizes(this.screenHeight, options.listScreens, options.oppositeBuffer); }, _indexConstraint: function (position) { var itemCount = this.itemCount, itemHeight = this.options.itemHeight, total = this.dataSource.total(); return Math.min(Math.max(total - itemCount, 0), Math.max(0, Math.floor(position / itemHeight))); }, _listIndex: function (scrollTop, lastScrollTop) { var buffers = this._bufferSizes(), position; position = scrollTop - (scrollTop > lastScrollTop ? buffers.down : buffers.up); return this._indexConstraint(position); }, _selectable: function () { if (this.options.selectable) { this._selectProxy = $.proxy(this, '_clickHandler'); this.element.on(CLICK + VIRTUAL_LIST_NS, '.' + VIRTUALITEM, this._selectProxy); } }, _getIndecies: function (candidate) { var result = [], data; if (typeof candidate === 'function') { data = this.dataSource.flatView(); for (var idx = 0; idx < data.length; idx++) { if (candidate(data[idx])) { result.push(idx); break; } } } if (typeof candidate === 'number') { result.push(candidate); } if (candidate instanceof jQuery) { candidate = parseInt(candidate.attr('data-offset-index'), 10); if (!isNaN(candidate)) { result.push(candidate); } } if (candidate instanceof Array) { result = candidate; } return result; }, _deselect: function (indices) { var removed = [], selectedIndex, dataItem, selectedIndexes = this._selectedIndexes, position = 0, selectable = this.options.selectable, removedindexesCounter = 0, item; indices = indices.slice(); if (selectable === true || !indices.length) { for (var idx = 0; idx < selectedIndexes.length; idx++) { if (selectedIndexes[idx] !== undefined) { this._getElementByIndex(selectedIndexes[idx]).removeClass(SELECTED); removed.push({ index: selectedIndexes[idx], position: idx, dataItem: this._selectedDataItems[idx] }); } } this._values = []; this._selectedDataItems = []; this._selectedIndexes = []; } else if (selectable === 'multiple') { for (var i = 0; i < indices.length; i++) { position = $.inArray(indices[i], selectedIndexes); selectedIndex = selectedIndexes[position]; if (selectedIndex !== undefined) { item = this._getElementByIndex(selectedIndex); if (!item.hasClass('k-state-selected')) { continue; } item.removeClass(SELECTED); this._values.splice(position, 1); this._selectedIndexes.splice(position, 1); dataItem = this._selectedDataItems.splice(position, 1)[0]; indices.splice(i, 1); removed.push({ index: selectedIndex, position: position + removedindexesCounter, dataItem: dataItem }); removedindexesCounter++; i--; } } } return { indices: indices, removed: removed }; }, _deselectCurrentValues: function (indices) { var children = this.element[0].children; var value, index, position; var values = this._values; var removed = []; var idx = 0; var j; if (this.options.selectable !== 'multiple' || !this.isFiltered()) { return []; } for (; idx < indices.length; idx++) { position = -1; index = indices[idx]; value = this._valueGetter(this._view[index].item); for (j = 0; j < values.length; j++) { if (value == values[j]) { position = j; break; } } if (position > -1) { removed.push(this.removeAt(position)); $(children[index]).removeClass('k-state-selected'); } } return removed; }, _select: function (indexes) { var that = this, singleSelection = this.options.selectable !== 'multiple', dataSource = this.dataSource, dataItem, oldSkip, take = this.itemCount, valueGetter = this._valueGetter, added = []; if (singleSelection) { that._selectedIndexes = []; that._selectedDataItems = []; that._values = []; } oldSkip = dataSource.skip(); $.each(indexes, function (_, index) { var page = index < take ? 1 : Math.floor(index / take) + 1; var skip = (page - 1) * take; that.mute(function () { dataSource.range(skip, take); dataItem = that._findDataItem([index - skip]); that._selectedIndexes.push(index); that._selectedDataItems.push(dataItem); that._values.push(isPrimitive(dataItem) ? dataItem : valueGetter(dataItem)); added.push({ index: index, dataItem: dataItem }); that._getElementByIndex(index).addClass(SELECTED); dataSource.range(oldSkip, take); }); }); return added; }, _clickHandler: function (e) { var item = $(e.currentTarget); if (!e.isDefaultPrevented() && item.attr('data-uid')) { this.trigger(CLICK, { item: item }); } }, _buildValueGetter: function () { this._valueGetter = kendo.getter(this.options.dataValueField); }, _calculateGroupPadding: function (height) { var firstItem = this.items().first(), groupHeader = this.header, padding = 0; if (groupHeader[0] && groupHeader[0].style.display !== 'none') { if (height !== 'auto') { padding = kendo.support.scrollbar(); } padding += parseFloat(firstItem.css('border-right-width'), 10) + parseFloat(firstItem.children('.k-group').css('right'), 10); groupHeader.css('padding-right', padding); } } }); kendo.ui.VirtualList = VirtualList; kendo.ui.plugin(VirtualList); }(window.kendo.jQuery)); return window.kendo; }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); }));