in src/Clients/Web/winjs/js/winjs.js [27390:27682]
(function () {
var i,
j,
resultsCount = results.length,
slotExisting,
slotBefore;
// If an index wasn't passed in, see if the indices of these items can be determined
if (typeof index !== "number") {
for (i = 0; i < resultsCount; i++) {
slotExisting = slotFromResult(results[i]);
if (slotExisting && slotExisting.index !== undefined) {
index = slotExisting.index + offset - i;
break;
}
}
}
// See if these results include the end of the list
if (typeof index === "number" && results[resultsCount - 1] === endMarker) {
// If the count wasn't known, it is now
count = index - offset + resultsCount - 1;
} else if (isNonNegativeNumber(count) && (index === undefined || index === null)) {
// If the index wasn't known, it is now
index = count - (resultsCount - 1) + offset;
}
// If the count is known, remove any mirage placeholders at the end
if (isNonNegativeNumber(count) && !removeMirageIndices(count, index - offset)) {
// "Forget" the count - a subsequent fetch or refresh will update the count and list end
count = undefined;
}
// Find any existing slots that correspond to the results, and check for contradictions
var offsetMap = new Array(resultsCount);
for (i = 0; i < resultsCount; i++) {
var slotBestMatch = null;
slotExisting = slotFromResult(results[i]);
if (slotExisting) {
// See if this item is currently adjacent to a different item, or has a different index
if ((i > 0 && !slotExisting.firstInSequence && slotExisting.prev.key && slotExisting.prev.key !== results[i - 1].key) ||
(typeof index === "number" && slotExisting.index !== undefined && slotExisting.index !== index - offset + i)) {
// A contradiction has been found, so we can't proceed further
beginRefresh();
return;
}
if (slotExisting === slotsStart || slotExisting === slotListEnd || slotExisting.bindingMap) {
// First choice is a slot with the given key and at least one binding (or an end of the list)
slotBestMatch = slotExisting;
}
}
if (typeof index === "number") {
slotExisting = indexMap[index - offset + i];
if (slotExisting) {
if (slotExisting.key && slotExisting.key !== results[i].key) {
// A contradiction has been found, so we can't proceed further
beginRefresh();
return;
}
if (!slotBestMatch && slotExisting.bindingMap) {
// Second choice is a slot with the given index and at least one binding
slotBestMatch = slotExisting;
}
}
}
if (i === offset) {
if ((slot.key && slot.key !== results[i].key) || (typeof slot.index === "number" && typeof index === "number" && slot.index !== index)) {
// A contradiction has been found, so we can't proceed further
beginRefresh();
return;
}
if (!slotBestMatch) {
// Third choice is the slot that was passed in
slotBestMatch = slot;
}
}
offsetMap[i] = slotBestMatch;
}
// Update items with known indices (and at least one binding) first, as they will not be merged with
// anything.
for (i = 0; i < resultsCount; i++) {
slotExisting = offsetMap[i];
if (slotExisting && slotExisting.index !== undefined && slotExisting !== slotsStart && slotExisting !== slotListEnd) {
matchSlot(slotExisting, results[i]);
}
}
var sequencePairsToMerge = [];
// Now process the sequences without indices
var firstSequence = true;
var slotBeforeSequence;
var slotAfterSequence;
for (i = 0; i < resultsCount; i++) {
slotExisting = offsetMap[i];
if (slotExisting && slotExisting !== slotListEnd) {
var iLast = i;
if (slotExisting.index === undefined) {
var insertionPoint = {};
promoteSlot(slotExisting, results[i], index - offset + i, insertionPoint);
// Find the extents of the sequence of slots that we can use
var slotFirstInSequence = slotExisting,
slotLastInSequence = slotExisting,
result;
for (j = i - 1; !slotFirstInSequence.firstInSequence; j--) {
// Keep going until we hit the start marker or a slot that we can't use or promote (it's ok
// if j leaves the results range).
result = results[j];
if (result === startMarker) {
break;
}
// Avoid assigning negative indices to slots
var index2 = index - offset + j;
if (index2 < 0) {
break;
}
if (promoteSlot(slotFirstInSequence.prev, result, index2, insertionPoint)) {
slotFirstInSequence = slotFirstInSequence.prev;
if (j >= 0) {
offsetMap[j] = slotFirstInSequence;
}
} else {
break;
}
}
for (j = i + 1; !slotLastInSequence.lastInSequence; j++) {
// Keep going until we hit the end marker or a slot that we can't use or promote (it's ok
// if j leaves the results range).
// If slotListEnd is in this sequence, it should not be separated from any predecessor
// slots, but they may need to be promoted.
result = results[j];
if ((result === endMarker || j === count) && slotLastInSequence.next !== slotListEnd) {
break;
}
if (slotLastInSequence.next === slotListEnd || promoteSlot(slotLastInSequence.next, result, index - offset + j, insertionPoint)) {
slotLastInSequence = slotLastInSequence.next;
if (j < resultsCount) {
offsetMap[j] = slotLastInSequence;
}
iLast = j;
if (slotLastInSequence === slotListEnd) {
break;
}
} else {
break;
}
}
slotBeforeSequence = (slotFirstInSequence.firstInSequence ? null : slotFirstInSequence.prev);
slotAfterSequence = (slotLastInSequence.lastInSequence ? null : slotLastInSequence.next);
if (slotBeforeSequence) {
splitSequence(slotBeforeSequence);
}
if (slotAfterSequence) {
splitSequence(slotLastInSequence);
}
// Move the sequence if necessary
if (typeof index === "number") {
if (slotLastInSequence === slotListEnd) {
// Instead of moving the list end, move the sequence before out of the way
if (slotBeforeSequence) {
moveSequenceAfter(slotListEnd, sequenceStart(slotBeforeSequence), slotBeforeSequence);
}
} else {
var slotInsertBefore = insertionPoint.slotNext;
if (!slotInsertBefore) {
slotInsertBefore = successorFromIndex(slotLastInSequence.index, indexMap, slotsStart, slotListEnd, true);
}
moveSequenceBefore(slotInsertBefore, slotFirstInSequence, slotLastInSequence);
}
if (slotFirstInSequence.prev.index === slotFirstInSequence.index - 1) {
mergeSequences(slotFirstInSequence.prev);
}
if (slotLastInSequence.next.index === slotLastInSequence.index + 1) {
mergeSequences(slotLastInSequence);
}
} else if (!firstSequence) {
slotBefore = offsetMap[i - 1];
if (slotBefore) {
if (slotFirstInSequence.prev !== slotBefore) {
if (slotLastInSequence === slotListEnd) {
// Instead of moving the list end, move the sequence before out of the way and
// the predecessor sequence into place.
if (slotBeforeSequence) {
moveSequenceAfter(slotListEnd, sequenceStart(slotBeforeSequence), slotBeforeSequence);
}
moveSequenceBefore(slotFirstInSequence, sequenceStart(slotBefore), slotBefore);
} else {
moveSequenceAfter(slotBefore, slotFirstInSequence, slotLastInSequence);
}
}
mergeSequences(slotBefore);
}
}
firstSequence = false;
if (refreshRequested) {
return;
}
sequencePairsToMerge.push({
slotBeforeSequence: slotBeforeSequence,
slotFirstInSequence: slotFirstInSequence,
slotLastInSequence: slotLastInSequence,
slotAfterSequence: slotAfterSequence
});
}
// See if the fetched slot needs to be merged
if (i === offset && slotExisting !== slot && !slotPermanentlyRemoved(slot)) {
slotBeforeSequence = (slot.firstInSequence ? null : slot.prev);
slotAfterSequence = (slot.lastInSequence ? null : slot.next);
sendMirageNotifications(slotExisting, slot, slotExisting.bindingMap);
mergeSlots(slotExisting, slot);
sequencePairsToMerge.push({
slotBeforeSequence: slotBeforeSequence,
slotFirstInSequence: slotExisting,
slotLastInSequence: slotExisting,
slotAfterSequence: slotAfterSequence
});
}
// Skip past all the other items in the sequence we just processed
i = iLast;
}
}
// If the count is known, set the index of the list end (wait until now because promoteSlot can sometimes
// delete it; do this before mergeSequencePairs so the list end can have slots inserted immediately before
// it).
if (isNonNegativeNumber(count) && slotListEnd.index !== count) {
changeSlotIndex(slotListEnd, count);
}
// Now that all the sequences have been moved, merge any colliding slots
mergeSequencePairs(sequencePairsToMerge);
// Match or cache any leftover items
for (i = 0; i < resultsCount; i++) {
// Find the first matched item
slotExisting = offsetMap[i];
if (slotExisting) {
for (j = i - 1; j >= 0; j--) {
var slotAfter = offsetMap[j + 1];
matchSlot(offsetMap[j] = (slotAfter.firstInSequence ? addSlotBefore(offsetMap[j + 1], indexMap) : slotAfter.prev), results[j]);
}
for (j = i + 1; j < resultsCount; j++) {
slotBefore = offsetMap[j - 1];
slotExisting = offsetMap[j];
if (!slotExisting) {
matchSlot(offsetMap[j] = (slotBefore.lastInSequence ? addSlotAfter(slotBefore, indexMap) : slotBefore.next), results[j]);
} else if (slotExisting.firstInSequence) {
// Adding the cached items may result in some sequences merging
if (slotExisting.prev !== slotBefore) {
moveSequenceAfter(slotBefore, slotExisting, sequenceEnd(slotExisting));
}
mergeSequences(slotBefore);
}
}
break;
}
}
// The description is no longer required
delete slot.description;
})();