<commit_before>require('enyo');

/**
* Contains the declaration for the {@link module:enyo/VirtualDataRepeater~VirtualDataRepeater} kind.
* @module enyo/VirtualDataRepeater
*/

var
	kind = require('./kind');

var
	DataRepeater = require('./DataRepeater');

/**
* @class VirtualDataRepeater
* @extends module:enyo/DataRepeater~DataRepeater
* @public
*/
module.exports = kind({
	name: 'enyo.VirtualDataRepeater',
	kind: DataRepeater,
	numItems: 10,
	first: 0,
	// TODO: Decide whether we want to implement node reordering
	// reorderNodes: false,

	reset: function () {
		this.init();
		this.destroyClientControls();
		this.setExtent();
	},

	init: function () {
		this.orderedChildren = [],
		this.orderedChildren_alt = [],
		this.childrenByIndex = {},
		this.orderedModels = [],
		this.orderedModels_alt = [],
		this.needed = [],
		this.bullpen = [],
		this.hasInitialized = true;
	},

	setExtent: function(first, numItems) {
		var pf = this.first,
			pn = this.numItems;
		if (typeof first === 'number') {
			this.first = first;
		}
		if (typeof numItems === 'number') {
			this.numItems = numItems;
		}
		if (this.collection) {
			this.stabilizeExtent();
			if (!this.hasInitialized) {
				this.init();
			}
			this.doIt();
		}
		if (this.first !== pf) {
			this.notify('first', pf, this.first);
		}
		if (this.numItems !== pn) {
			this.notify('numItems', pn, this.numItems);
		}
	},
	
	refresh: function (immediate) {
		if (!this.hasInitialized) return this.reset();

		this.stabilizeExtent();

		var refresh = this.bindSafely(function() {
			this.doIt();
		});

		// refresh is used as the event handler for
		// collection resets so checking for truthy isn't
		// enough. it must be true.
		if(immediate === true) {
			refresh();
		} else {
			this.startJob('refreshing', refresh, 16);
		}
	},

	childForIndex: function(idx) {
		return this.childrenByIndex[idx];
	},

	childForModel: function(model) {
		var idx = this.orderedModels.indexOf(model);
		return this.orderedChildren[idx];
	},
	assignChild: function(model, index, child) {
		var s = this.isSelected(model),
			sc = child.selectedClass || 'selected';

		child.set('model', model);
		child.set('index', index);
		child.set('selected', s);
		child.show();
		child.addRemoveClass(sc, s);
		child.removeClass('enyo-vdr-first');
		child.removeClass('enyo-vdr-last');
		this.childrenByIndex[index] = child;
	},

	doIt: function() {
		var dd = this.get('data'),
			f = this.first,
			o = this.orderedChildren,
			o2 = this.orderedChildren_alt,
			om = this.orderedModels,
			omL = om.length,
			om2 = this.orderedModels_alt,
			n = this.numItems,
			needed = this.needed,
			b = this.bullpen,
			i, idx, m, ci, c, nNeeded, j, ln;
		for (i = 0; i < n; ++i) {
			idx = f + i;
			m = dd.at(idx);
			if (m) {
				ci = omL ? om.indexOf(m) : -1;
				if (ci >= 0) {
					c = o[ci];
					o.splice(ci, 1);
					om.splice(ci, 1);
					o2.push(c);
					c.set('index', idx);
				}
				else {
					needed.push(i);
				}
				om2.push(m);
			}
			else {
				break;
			}
		}
		nNeeded = needed.length;
		for (j = 0; j < nNeeded; ++j) {
			i = needed[j];
			idx = f + i;
			m = om2[i];
			c = om.pop() && o.pop() || b.pop();
			if (c) {
				this.assignChild(m, idx, c);
			}
			else {
				c = this.createComponent({model: m});
				this.assignChild(m, idx, c);
				// TODO: Rethink child lifecycle hooks (currently deploy / update / retire)<commit_msg>ENYO-1657: Another VDR selection fix<commit_after>require('enyo');

/**
* Contains the declaration for the {@link module:enyo/VirtualDataRepeater~VirtualDataRepeater} kind.
* @module enyo/VirtualDataRepeater
*/

var
	kind = require('./kind');

var
	DataRepeater = require('./DataRepeater');

/**
* @class VirtualDataRepeater
* @extends module:enyo/DataRepeater~DataRepeater
* @public
*/
module.exports = kind({
	name: 'enyo.VirtualDataRepeater',
	kind: DataRepeater,
	numItems: 10,
	first: 0,
	// TODO: Decide whether we want to implement node reordering
	// reorderNodes: false,

	reset: function () {
		this.init();
		this.destroyClientControls();
		this.setExtent();
	},

	init: function () {
		this.orderedChildren = [],
		this.orderedChildren_alt = [],
		this.childrenByIndex = {},
		this.orderedModels = [],
		this.orderedModels_alt = [],
		this.needed = [],
		this.bullpen = [],
		this.hasInitialized = true;
	},

	setExtent: function(first, numItems) {
		var pf = this.first,
			pn = this.numItems;
		if (typeof first === 'number') {
			this.first = first;
		}
		if (typeof numItems === 'number') {
			this.numItems = numItems;
		}
		if (this.collection) {
			this.stabilizeExtent();
			if (!this.hasInitialized) {
				this.init();
			}
			this.doIt();
		}
		if (this.first !== pf) {
			this.notify('first', pf, this.first);
		}
		if (this.numItems !== pn) {
			this.notify('numItems', pn, this.numItems);
		}
	},
	
	refresh: function (immediate) {
		if (!this.hasInitialized) return this.reset();

		this.stabilizeExtent();

		var refresh = this.bindSafely(function() {
			this.doIt();
		});

		// refresh is used as the event handler for
		// collection resets so checking for truthy isn't
		// enough. it must be true.
		if(immediate === true) {
			refresh();
		} else {
			this.startJob('refreshing', refresh, 16);
		}
	},

	childForIndex: function(idx) {
		return this.childrenByIndex[idx];
	},

	childForModel: function(model) {
		var idx = this.orderedModels.indexOf(model);
		return this.orderedChildren[idx];
	},

	assignChild: function(model, index, child) {
		var pMod = child.model,
			pIdx = child.index,
			sc = child.selectedClass || 'selected',
			s;

		if (pMod !== model) {
			child.set('model', model);
			s = this.isSelected(model);
			child.set('selected', s);
			child.addRemoveClass(sc, s);
		}

		if (pIdx !== index) {
			child.set('index', index);
			this.childrenByIndex[index] = child;
			if (this.childrenByIndex[pIdx] === child) {
				this.childrenByIndex[pIdx] = null;
			}
		}

		child.removeClass('enyo-vdr-first');
		child.removeClass('enyo-vdr-last');
		child.show();
	},

	doIt: function() {
		var dd = this.get('data'),
			f = this.first,
			o = this.orderedChildren,
			o2 = this.orderedChildren_alt,
			om = this.orderedModels,
			omL = om.length,
			om2 = this.orderedModels_alt,
			n = this.numItems,
			needed = this.needed,
			b = this.bullpen,
			i, idx, m, ci, c, nNeeded, j, ln;
		for (i = 0; i < n; ++i) {
			idx = f + i;
			m = dd.at(idx);
			if (m) {
				ci = omL ? om.indexOf(m) : -1;
				if (ci >= 0) {
					c = o[ci];
					o.splice(ci, 1);
					om.splice(ci, 1);
					o2.push(c);
					this.assignChild(m, idx, c);
				}
				else {
					needed.push(i);
				}
				om2.push(m);
			}
			else {
				break;
			}
		}
		nNeeded = needed.length;
		for (j = 0; j < nNeeded; ++j) {
			i = needed[j];
			idx = f + i;
			m = om2[i];
			c = om.pop() && o.pop() || b.pop();
			if (c) {
				this.assignChild(m, idx, c);
			}
			else {
				c = this.createComponent({model: m});
				this.assignChild(m, idx, c);
				// TODO: Rethink child lifecycle hooks (currently deploy / update / retire)
{'fraction_non_alphanumeric': 0.17008255052661542, 'fraction_numerical': 0.005123825789923143, 'mean_word_length': 3.033869115958668, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, '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': '2197434', 'n_tokens_mistral': 3054, 'n_tokens_neox': 2607, 'n_words': 572}