<commit_before>ko.bindingHandlers.virtualForEach = {
	init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
		var config = valueAccessor(),
			container = config.container || element,
			scrollTop = ko.observable(container.scrollTop),
			offsetHeight = ko.observable(container.offsetHeight);

		ko.utils.registerEventHandler(container, 'scroll', function () {
			scrollTop(container.scrollTop);
		});

		ko.utils.registerEventHandler(window, 'resize', function () {
			offsetHeight(container.offsetHeight);
		});

		config.data = ko.computed(function () {
			var items = ko.utils.unwrapObservable(config.allData),
				curScrollTop = scrollTop(),
				curOffsetHeight = offsetHeight(),
				curRowHeight = ko.utils.unwrapObservable(config.rowHeight),
				curRange = {
					first: Math.floor(curScrollTop / curRowHeight),
					last: Math.ceil((curScrollTop + curOffsetHeight) / curRowHeight)
				};

			element.style.paddingTop = curScrollTop + 'px';
			element.style.height = (items.length * curRowHeight - curScrollTop) + 'px';
			
			return items.slice(curRange.first, curRange.last);
		}).extend({throttle: 50});

		return ko.bindingHandlers.foreach.init.apply(ko.bindingHandlers.foreach, arguments);
	},
	update: ko.bindingHandlers.foreach.update
};
ko.virtualElements.allowedBindings.virtualForEach = true;<commit_msg>Optimized resize detection by handling in one event for all virtual foreachs and added eventedComputed for tracking and computing changes on events.<commit_after>(function () {

function eventedComputed(element, type, getValue) {
	var observable = ko.observable(),
		setValue = function () {
			observable(getValue.call(element));
		};

	ko.utils.registerEventHandler(element, type, setValue);
	setValue();

	return ko.computed(observable);
}

var windowHeight = eventedComputed(window, 'resize', function () {
	return this.document.documentElement.offsetHeight || this.innerHeight;
});

ko.bindingHandlers.virtualForEach = {
	init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
		var config = valueAccessor(),
			container = config.container || element,
			scrollTop = eventedComputed(container, 'scroll', function () {
				return this.scrollTop;
			}),
			offsetHeight = ko.computed(function () {
				windowHeight();
				return container.offsetHeight;
			});

		config.data = ko.computed(function () {
			console.log('update');

			var items = ko.utils.unwrapObservable(config.allData),
				curScrollTop = scrollTop(),
				curOffsetHeight = offsetHeight(),
				curRowHeight = ko.utils.unwrapObservable(config.rowHeight),
				curRange = {
					first: Math.floor(curScrollTop / curRowHeight),
					last: Math.ceil((curScrollTop + curOffsetHeight) / curRowHeight)
				};

			element.style.paddingTop = curScrollTop + 'px';
			element.style.height = (items.length * curRowHeight - curScrollTop) + 'px';
			
			return items.slice(curRange.first, curRange.last);
		}).extend({throttle: 50});

		return ko.bindingHandlers.foreach.init.apply(ko.bindingHandlers.foreach, arguments);
	},
	update: ko.bindingHandlers.foreach.update
};

ko.expressionRewriting.bindingRewriteValidators.virtualForEach = false;
ko.virtualElements.allowedBindings.virtualForEach = true;

})();
{'fraction_non_alphanumeric': 0.12557568314399756, 'fraction_numerical': 0.0012281240405280934, 'mean_word_length': 4.807486631016043, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6918784', 'n_tokens_mistral': 1075, 'n_tokens_neox': 947, 'n_words': 177}