WinJS.UI ui.js
This file has been truncated, but you can view the full file.
/// <loc filename="Metadata\ui_loc_oam.xml" format="messagebundle" /> | |
/*! | |
© Microsoft. All rights reserved. | |
This library is supported for use in Windows Store apps only. | |
Build: 1.0.9200.20498.win8_ldr.120817-1716 | |
Version: Microsoft.WinJS.1.0 | |
*/ | |
/// <reference path="ms-appx://Microsoft.WinJS.1.0/js/base.js" /> | |
/// <reference path="ms-appx://Microsoft.WinJS.1.0/js/ui.js" /> | |
(function animationsInit(WinJS) { | |
"use strict"; | |
var thisWinUI = WinJS.UI; | |
var mstransform = "transform"; | |
// Default to 11 pixel from the left (or right if RTL) | |
var defaultOffset = [{ top: "0px", left: "11px", rtlflip: true }]; | |
var OffsetArray = WinJS.Class.define (function OffsetArray_ctor(offset, keyframe, defOffset) { | |
// Constructor | |
defOffset = defOffset || defaultOffset; | |
if (Array.isArray(offset) && offset.length > 0) { | |
this.offsetArray = offset; | |
if (offset.length === 1) { | |
this.keyframe = checkKeyframe(offset[0], defOffset[0], keyframe); | |
} | |
} else if (offset && offset.hasOwnProperty("top") && offset.hasOwnProperty("left")) { | |
this.offsetArray = [offset]; | |
this.keyframe = checkKeyframe(offset, defOffset[0], keyframe); | |
} else { | |
this.offsetArray = defOffset; | |
this.keyframe = chooseKeyframe(defOffset[0], keyframe); | |
} | |
}, { // Public Members | |
getOffset: function (i) { | |
if (i >= this.offsetArray.length) { | |
i = this.offsetArray.length - 1; | |
} | |
return this.offsetArray[i]; | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
function checkKeyframe(offset, defOffset, keyframe) { | |
if (!keyframe || | |
offset.left !== defOffset.left || | |
offset.top !== defOffset.top || | |
(offset.rtlflip && !defOffset.rtlflip)) { | |
return null; | |
} | |
if (!offset.rtlflip) { | |
return keyframe; | |
} | |
return keyframeCallback(keyframe); | |
} | |
function chooseKeyframe(defOffset, keyframe) { | |
if (!keyframe || !defOffset.rtlflip) { | |
return keyframe; | |
} | |
return keyframeCallback(keyframe); | |
} | |
function keyframeCallback(keyframe) { | |
var keyframeRtl = keyframe + "-rtl"; | |
return function (i, elem) { | |
return window.getComputedStyle(elem).direction === "ltr" ? keyframe : keyframeRtl; | |
} | |
} | |
function makeArray(elements) | |
{ | |
if (Array.isArray(elements) || elements instanceof NodeList || elements instanceof HTMLCollection) { | |
return elements; | |
} else if (elements) { | |
return [elements]; | |
} else { | |
return []; | |
} | |
} | |
var isSnapped = function() { | |
if (WinJS.Utilities.hasWinRT) { | |
var appView = Windows.UI.ViewManagement.ApplicationView; | |
var snapped = Windows.UI.ViewManagement.ApplicationViewState.snapped; | |
isSnapped = function() { | |
return appView.value === snapped; | |
}; | |
} else { | |
isSnapped = function() { return false; } | |
} | |
return isSnapped(); | |
}; | |
function collectOffsetArray(elemArray) { | |
var offsetArray = []; | |
for (var i = 0; i < elemArray.length; i++) { | |
var offset = { | |
top: elemArray[i].offsetTop, | |
left: elemArray[i].offsetLeft | |
}; | |
var matrix = window.getComputedStyle(elemArray[i], null).transform.split(","); | |
if (matrix.length === 6) { | |
offset.left += parseFloat(matrix[4]); | |
offset.top += parseFloat(matrix[5]); | |
} | |
offsetArray.push(offset); | |
} | |
return offsetArray; | |
} | |
function staggerDelay(initialDelay, extraDelay, delayFactor, delayCap) { | |
return function (i) { | |
var ret = initialDelay; | |
for (var j = 0; j < i; j++) { | |
extraDelay *= delayFactor; | |
ret += extraDelay; | |
} | |
if (delayCap) { | |
ret = Math.min(ret, delayCap); | |
} | |
return ret; | |
}; | |
} | |
function makeOffsetsRelative(elemArray, offsetArray) { | |
for (var i = 0; i < offsetArray.length; i++) { | |
offsetArray[i].top -= elemArray[i].offsetTop; | |
offsetArray[i].left -= elemArray[i].offsetLeft; | |
} | |
} | |
function animTranslate2DTransform(elemArray, offsetArray, transition) { | |
makeOffsetsRelative(elemArray, offsetArray); | |
for (var i = 0; i < elemArray.length; i++) { | |
if (offsetArray[i].top !== 0 || offsetArray[i].left !== 0) { | |
elemArray[i].style.transform = "translate(" + offsetArray[i].left + "px, " + offsetArray[i].top + "px)"; | |
} | |
} | |
return thisWinUI.executeTransition(elemArray, transition); | |
} | |
function translateCallback(offsetArray, prefix) { | |
prefix = prefix || ""; | |
return function (i, elem) { | |
var offset = offsetArray.getOffset(i); | |
var left = offset.left; | |
if (offset.rtlflip && window.getComputedStyle(elem).direction === "rtl") { | |
left = left.toString(); | |
if (left.charAt(0) === "-") { | |
left = left.substring(1); | |
} else { | |
left = "-" + left; | |
} | |
} | |
return prefix + "translate(" + left + ", " + offset.top + ")"; | |
}; | |
} | |
function translateCallbackAnimate(offsetArray, suffix) | |
{ | |
suffix = suffix || ""; | |
return function (i, elem) { | |
var offset = offsetArray[i]; | |
return "translate(" + offset.left + "px, " + offset.top + "px) " + suffix; | |
}; | |
} | |
function keyframeCallbackAnimate(offsetArray, keyframe) | |
{ | |
return function (i, elem) { | |
var offset = offsetArray[i]; | |
return (offset.left === 0 && offset.top === 0) ? keyframe : null; | |
}; | |
} | |
function layoutTransition(LayoutTransition, target, affected, extra) | |
{ | |
var targetArray = makeArray(target); | |
var affectedArray = makeArray(affected); | |
var offsetArray = collectOffsetArray(affectedArray); | |
return new LayoutTransition(targetArray, affectedArray, offsetArray, extra); | |
} | |
var ExpandAnimation = WinJS.Class.define(function ExpandAnimation_ctor(revealedArray, affectedArray, offsetArray) { | |
// Constructor | |
this.revealedArray = revealedArray; | |
this.affectedArray = affectedArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
var promise1 = thisWinUI.executeAnimation( | |
this.revealedArray, | |
{ | |
keyframe: "WinJS-opacity-in", | |
property: "opacity", | |
delay: this.affectedArray.length > 0 ? 200 : 0, | |
duration: 167, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: 0, | |
to: 1 | |
}); | |
var promise2 = animTranslate2DTransform( | |
this.affectedArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 367, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var CollapseAnimation = WinJS.Class.define(function CollapseAnimation_ctor(hiddenArray, affectedArray, offsetArray) { | |
// Constructor | |
this.hiddenArray = hiddenArray; | |
this.affectedArray = affectedArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
var promise1 = thisWinUI.executeAnimation( | |
this.hiddenArray, | |
{ | |
keyframe: "WinJS-opacity-out", | |
property: "opacity", | |
delay: 0, | |
duration: 167, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: 1, | |
to: 0 | |
}); | |
var promise2 = animTranslate2DTransform( | |
this.affectedArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay: this.hiddenArray.length > 0 ? 167 : 0, | |
duration: 367, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var RepositionAnimation = WinJS.Class.define(function RepositionAnimation_ctor(target, elementArray, offsetArray) { | |
// Constructor | |
this.elementArray = elementArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
return animTranslate2DTransform( | |
this.elementArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay : staggerDelay(0, 33, 1, 250), | |
duration : 367, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var AddToListAnimation = WinJS.Class.define(function AddToListAnimation_ctor(addedArray, affectedArray, offsetArray) { | |
// Constructor | |
this.addedArray = addedArray; | |
this.affectedArray = affectedArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
var delay = this.affectedArray.length > 0 ? 240 : 0; | |
var promise1 = thisWinUI.executeAnimation( | |
this.addedArray, | |
[{ | |
keyframe: "WinJS-scale-up", | |
property: mstransform, | |
delay: delay, | |
duration: 120, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: "scale(0.85)", | |
to: "none" | |
}, | |
{ | |
keyframe: "WinJS-opacity-in", | |
property: "opacity", | |
delay: delay, | |
duration: 120, | |
timing: "linear", | |
from: 0, | |
to: 1 | |
}] | |
); | |
var promise2 = animTranslate2DTransform( | |
this.affectedArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 400, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var DeleteFromListAnimation = WinJS.Class.define(function DeleteFromListAnimation_ctor(deletedArray, remainingArray, offsetArray) { | |
// Constructor | |
this.deletedArray = deletedArray; | |
this.remainingArray = remainingArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
var promise1 = thisWinUI.executeAnimation( | |
this.deletedArray, | |
[{ | |
keyframe: "WinJS-scale-down", | |
property: mstransform, | |
delay: 0, | |
duration: 120, | |
timing: "cubic-bezier(0.11, 0.5, 0.24, .96)", | |
from: "none", | |
to: "scale(0.85)" | |
}, | |
{ | |
keyframe: "WinJS-opacity-out", | |
property: "opacity", | |
delay: 0, | |
duration: 120, | |
timing: "linear", | |
from: 1, | |
to: 0 | |
}]); | |
var promise2 = animTranslate2DTransform( | |
this.remainingArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay: this.deletedArray.length > 0 ? 60 : 0, | |
duration: 400, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var _UpdateListAnimation = WinJS.Class.define(function _UpdateListAnimation_ctor(addedArray, affectedArray, offsetArray, deleted) { | |
// Constructor | |
this.addedArray = addedArray; | |
this.affectedArray = affectedArray; | |
this.offsetArray = offsetArray; | |
var deletedArray = makeArray(deleted); | |
this.deletedArray = deletedArray; | |
this.deletedOffsetArray = collectOffsetArray(deletedArray); | |
},{ // Public Members | |
execute: function () { | |
makeOffsetsRelative(this.deletedArray, this.deletedOffsetArray); | |
var delay = 0; | |
var promise1 = thisWinUI.executeAnimation( | |
this.deletedArray, | |
[{ | |
keyframe: keyframeCallbackAnimate(this.deletedOffsetArray, "WinJS-scale-down"), | |
property: mstransform, | |
delay: 0, | |
duration: 120, | |
timing: "cubic-bezier(0.11, 0.5, 0.24, .96)", | |
from: translateCallbackAnimate(this.deletedOffsetArray), | |
to: translateCallbackAnimate(this.deletedOffsetArray, "scale(0.85)") | |
}, | |
{ | |
keyframe: "WinJS-opacity-out", | |
property: "opacity", | |
delay: 0, | |
duration: 120, | |
timing: "linear", | |
from: 1, | |
to: 0 | |
}]); | |
if (this.deletedArray.length > 0) { | |
delay += 60; | |
} | |
var promise2 = animTranslate2DTransform( | |
this.affectedArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay: delay, | |
duration: 400, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
if (this.affectedArray.length > 0) { | |
delay += 240; | |
} else if (delay) { | |
delay += 60; | |
} | |
var promise3 = thisWinUI.executeAnimation( | |
this.addedArray, | |
[{ | |
keyframe: "WinJS-scale-up", | |
property: mstransform, | |
delay: delay, | |
duration: 120, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: "scale(0.85)", | |
to: "none" | |
}, | |
{ | |
keyframe: "WinJS-opacity-in", | |
property: "opacity", | |
delay: delay, | |
duration: 120, | |
timing: "linear", | |
from: 0, | |
to: 1 | |
}] | |
); | |
return WinJS.Promise.join([promise1, promise2, promise3]); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var AddToSearchListAnimation = WinJS.Class.define(function AddToSearchListAnimation_ctor(addedArray, affectedArray, offsetArray) { | |
// Constructor | |
this.addedArray = addedArray; | |
this.affectedArray = affectedArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
var promise1 = thisWinUI.executeAnimation( | |
this.addedArray, | |
{ | |
keyframe: "WinJS-opacity-in", | |
property: "opacity", | |
delay: this.affectedArray.length > 0 ? 240 : 0, | |
duration: 117, | |
timing: "linear", | |
from: 0, | |
to: 1 | |
}); | |
var promise2 = animTranslate2DTransform( | |
this.affectedArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 400, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var DeleteFromSearchListAnimation = WinJS.Class.define(function DeleteFromSearchListAnimation_ctor(deletedArray, remainingArray, offsetArray) { | |
// Constructor | |
this.deletedArray = deletedArray; | |
this.remainingArray = remainingArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
var promise1 = thisWinUI.executeAnimation( | |
this.deletedArray, | |
{ | |
keyframe: "WinJS-opacity-out", | |
property: "opacity", | |
delay: 0, | |
duration: 93, | |
timing: "linear", | |
from: 1, | |
to: 0 | |
}); | |
var promise2 = animTranslate2DTransform( | |
this.remainingArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay: this.deletedArray.length > 0 ? 60 : 0, | |
duration: 400, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
var PeekAnimation = WinJS.Class.define(function PeekAnimation_ctor(target, elementArray, offsetArray) { | |
// Constructor | |
this.elementArray = elementArray; | |
this.offsetArray = offsetArray; | |
},{ // Public Members | |
execute: function () { | |
return animTranslate2DTransform( | |
this.elementArray, | |
this.offsetArray, | |
{ | |
property: mstransform, | |
delay : 0, | |
duration : 2000, | |
timing : "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
} | |
}, { // Static Members | |
supportedForProcessing: false, | |
}); | |
WinJS.Namespace.define("WinJS.UI.Animation", { | |
createExpandAnimation: function (revealed, affected) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createExpandAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createExpandAnimation"> | |
/// Creates an expand animation. | |
/// After creating the ExpandAnimation object, | |
/// modify the document to move the elements to their new positions, | |
/// then call the execute method on the ExpandAnimation object. | |
/// </summary> | |
/// <param name="revealed" locid="WinJS.UI.Animation.createExpandAnimation_p:revealed"> | |
/// Single element or collection of elements which were revealed. | |
/// </param> | |
/// <param name="affected" locid="WinJS.UI.Animation.createExpandAnimation_p:affected"> | |
/// Single element or collection of elements whose positions were | |
/// affected by the expand. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createExpandAnimation_returnValue"> | |
/// ExpandAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(ExpandAnimation, revealed, affected); | |
}, | |
createCollapseAnimation: function (hidden, affected) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createCollapseAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createCollapseAnimation"> | |
/// Creates a collapse animation. | |
/// After creating the CollapseAnimation object, | |
/// modify the document to move the elements to their new positions, | |
/// then call the execute method on the CollapseAnimation object. | |
/// </summary> | |
/// <param name="hidden" locid="WinJS.UI.Animation.createCollapseAnimation_p:hidden"> | |
/// Single element or collection of elements being removed from view. | |
/// When the animation completes, the application should hide the elements | |
/// or remove them from the document. | |
/// </param> | |
/// <param name="affected" locid="WinJS.UI.Animation.createCollapseAnimation_p:affected"> | |
/// Single element or collection of elements whose positions were | |
/// affected by the collapse. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createCollapseAnimation_returnValue"> | |
/// CollapseAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(CollapseAnimation, hidden, affected); | |
}, | |
createRepositionAnimation: function (element) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createRepositionAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createRepositionAnimation"> | |
/// Creates a reposition animation. | |
/// After creating the RepositionAnimation object, | |
/// modify the document to move the elements to their new positions, | |
/// then call the execute method on the RepositionAnimation object. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.createRepositionAnimation_p:element"> | |
/// Single element or collection of elements which were repositioned. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createRepositionAnimation_returnValue"> | |
/// RepositionAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(RepositionAnimation, null, element); | |
}, | |
fadeIn: function (shown) { | |
/// <signature helpKeyword="WinJS.UI.Animation.fadeIn"> | |
/// <summary locid="WinJS.UI.Animation.fadeIn"> | |
/// Execute a fade-in animation. | |
/// </summary> | |
/// <param name="shown" locid="WinJS.UI.Animation.fadeIn_p:element"> | |
/// Single element or collection of elements to fade in. | |
/// At the end of the animation, the opacity of the elements is 1. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.fadeIn_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return thisWinUI.executeTransition( | |
shown, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 250, | |
timing: "linear", | |
from: 0, | |
to: 1 | |
}); | |
}, | |
fadeOut: function (hidden) { | |
/// <signature helpKeyword="WinJS.UI.Animation.fadeOut"> | |
/// <summary locid="WinJS.UI.Animation.fadeOut"> | |
/// Execute a fade-out animation. | |
/// </summary> | |
/// <param name="hidden" locid="WinJS.UI.Animation.fadeOut_p:element"> | |
/// Single element or collection of elements to fade out. | |
/// At the end of the animation, the opacity of the elements is 0. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.fadeOut_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return thisWinUI.executeTransition( | |
hidden, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 167, | |
timing: "linear", | |
to: 0 | |
}); | |
}, | |
createAddToListAnimation: function (added, affected) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createAddToListAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createAddToListAnimation"> | |
/// Creates an animation for adding to a list. | |
/// After creating the AddToListAnimation object, | |
/// modify the document to move the elements to their new positions, | |
/// then call the execute method on the AddToListAnimation object. | |
/// </summary> | |
/// <param name="added" locid="WinJS.UI.Animation.createAddToListAnimation_p:added"> | |
/// Single element or collection of elements which were added. | |
/// </param> | |
/// <param name="affected" locid="WinJS.UI.Animation.createAddToListAnimation_p:affected"> | |
/// Single element or collection of elements whose positions were | |
/// affected by the add. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createAddToListAnimation_returnValue"> | |
/// AddToListAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(AddToListAnimation, added, affected); | |
}, | |
createDeleteFromListAnimation: function (deleted, remaining) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createDeleteFromListAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createDeleteFromListAnimation"> | |
/// Crestes an animation for deleting from a list. | |
/// After creating the DeleteFromListAnimation object, | |
/// modify the document to reflect the deletion, | |
/// then call the execute method on the DeleteFromListAnimation object. | |
/// </summary> | |
/// <param name="deleted" locid="WinJS.UI.Animation.createDeleteFromListAnimation_p:deleted"> | |
/// Single element or collection of elements which will be deleted. | |
/// When the animation completes, the application should hide the elements | |
/// or remove them from the document. | |
/// </param> | |
/// <param name="remaining" locid="WinJS.UI.Animation.createDeleteFromListAnimation_p:remaining"> | |
/// Single element or collection of elements whose positions were | |
/// affected by the deletion. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createDeleteFromListAnimation_returnValue"> | |
/// DeleteFromListAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(DeleteFromListAnimation, deleted, remaining); | |
}, | |
_createUpdateListAnimation: function (added, deleted, affected) { | |
return layoutTransition(_UpdateListAnimation, added, affected, deleted); | |
}, | |
createAddToSearchListAnimation: function (added, affected) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createAddToSearchListAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createAddToSearchListAnimation"> | |
/// Creates an animation for adding to a list of search results. | |
/// This is similar to an AddToListAnimation, but faster. | |
/// After creating the AddToSearchListAnimation object, | |
/// modify the document to move the elements to their new positions, | |
/// then call the execute method on the AddToSearchListAnimation object. | |
/// </summary> | |
/// <param name="added" locid="WinJS.UI.Animation.createAddToSearchListAnimation_p:added"> | |
/// Single element or collection of elements which were added. | |
/// </param> | |
/// <param name="affected" locid="WinJS.UI.Animation.createAddToSearchListAnimation_p:affected"> | |
/// Single element or collection of elements whose positions were | |
/// affected by the add. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createAddToSearchListAnimation_returnValue"> | |
/// AddToSearchListAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(AddToSearchListAnimation, added, affected); | |
}, | |
createDeleteFromSearchListAnimation: function (deleted, remaining) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createDeleteFromSearchListAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createDeleteFromSearchListAnimation"> | |
/// Creates an animation for deleting from a list of search results. | |
/// This is similar to an DeleteFromListAnimation, but faster. | |
/// After creating the DeleteFromSearchListAnimation object, | |
/// modify the document to move the elements to their new positions, | |
/// then call the execute method on the DeleteFromSearchListAnimation object. | |
/// </summary> | |
/// <param name="deleted" locid="WinJS.UI.Animation.createDeleteFromSearchListAnimation_p:deleted"> | |
/// Single element or collection of elements which will be deleted. | |
/// When the animation completes, the application should hide the elements | |
/// or remove them from the document. | |
/// </param> | |
/// <param name="remaining" locid="WinJS.UI.Animation.createDeleteFromSearchListAnimation_p:remaining"> | |
/// Single element or collection of elements whose positions were | |
/// affected by the deletion. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createDeleteFromSearchListAnimation_returnValue"> | |
/// DeleteFromSearchListAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(DeleteFromSearchListAnimation, deleted, remaining); | |
}, | |
showEdgeUI: function (element, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.showEdgeUI"> | |
/// <summary locid="WinJS.UI.Animation.showEdgeUI"> | |
/// Slides an element or elements into position at the edge of the screen. | |
/// This animation is designed for a small object like an appbar. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.showEdgeUI_p:element"> | |
/// Single element or collection of elements to be slid into position. | |
/// The elements should be at their final positions | |
/// at the time the function is called. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.showEdgeUI_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the starting point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.showEdgeUI_p:returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-showEdgeUI", [{ top: "-70px", left: "0px" }]); | |
return thisWinUI.executeAnimation( | |
element, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 367, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: offsetArray.keyframe || translateCallback(offsetArray), | |
to: "none" | |
}); | |
}, | |
showPanel: function (element, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.showPanel"> | |
/// <summary locid="WinJS.UI.Animation.showPanel"> | |
/// Slides an element or elements into position at the edge of the screen. | |
/// This animation is designed for a large object like a keyboard. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.showPanel_p:element"> | |
/// Single element or collection of elements to be slid into position. | |
/// The elements should be at their final positions | |
/// at the time the function is called. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.showPanel_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the starting point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.showPanel_returnValue"> | |
/// promise object | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-showPanel", [{ top: "0px", left: "364px", rtlflip: true }]); | |
return thisWinUI.executeAnimation( | |
element, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 550, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: offsetArray.keyframe || translateCallback(offsetArray), | |
to: "none" | |
}); | |
}, | |
hideEdgeUI: function (element, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.hideEdgeUI"> | |
/// <summary locid="WinJS.UI.Animation.hideEdgeUI"> | |
/// Slides an element or elements at the edge of the screen out of view. | |
/// This animation is designed for a small object like an appbar. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.hideEdgeUI_p:element"> | |
/// Single element or collection of elements to be slid out. | |
/// The elements should be at their onscreen positions | |
/// at the time the function is called. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.hideEdgeUI_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the ending point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.hideEdgeUI_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-hideEdgeUI", [{ top: "-70px", left: "0px" }]); | |
return thisWinUI.executeAnimation( | |
element, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 367, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: "none", | |
to: offsetArray.keyframe || translateCallback(offsetArray) | |
}); | |
}, | |
hidePanel: function (element, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.hidePanel"> | |
/// <summary locid="WinJS.UI.Animation.hidePanel"> | |
/// Slides an element or elements at the edge of the screen out of view. | |
/// This animation is designed for a large object like a keyboard. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.hidePanel_p:element"> | |
/// Single element or collection of elements to be slid out. | |
/// The elements should be at their onscreen positions | |
/// at the time the function is called. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.hidePanel_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the ending point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.hidePanel_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-hidePanel", [{ top: "0px", left: "364px", rtlflip: true }]); | |
return thisWinUI.executeAnimation( | |
element, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 550, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: "none", | |
to: offsetArray.keyframe || translateCallback(offsetArray) | |
}); | |
}, | |
showPopup: function (element, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.showPopup"> | |
/// <summary locid="WinJS.UI.Animation.showPopup"> | |
/// Displays an element or elements in the style of a popup. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.showPopup_p:element"> | |
/// Single element or collection of elements to be shown like a popup. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.showPopup_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the starting point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.showPopup_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-showPopup", [{ top: "50px", left: "0px" }]); | |
return thisWinUI.executeAnimation( | |
element, | |
[{ | |
keyframe: "WinJS-opacity-in", | |
property: "opacity", | |
delay: 83, | |
duration: 83, | |
timing: "linear", | |
from: 0, | |
to: 1 | |
}, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 367, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: offsetArray.keyframe || translateCallback(offsetArray), | |
to: "none" | |
}]); | |
}, | |
hidePopup: function (element) { | |
/// <signature helpKeyword="WinJS.UI.Animation.hidePopup"> | |
/// <summary locid="WinJS.UI.Animation.hidePopup"> | |
/// Removes a popup from the screen. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.hidePopup_p:element"> | |
/// Single element or collection of elements to be hidden like a popup. | |
/// When the animation completes, the application should hide the elements | |
/// or remove them from the document. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.hidePopup_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return thisWinUI.executeAnimation( | |
element, | |
{ | |
keyframe: "WinJS-opacity-out", | |
property: "opacity", | |
delay: 0, | |
duration: 83, | |
timing: "linear", | |
from: 1, | |
to: 0 | |
}); | |
}, | |
pointerDown: function (element) { | |
/// <signature helpKeyword="WinJS.UI.Animation.pointerDown"> | |
/// <summary locid="WinJS.UI.Animation.pointerDown"> | |
/// Execute a pointer-down animation. | |
/// Use the pointerUp animation to reverse the effect of this animation. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.pointerDown_p:element"> | |
/// Single element or collection of elements responding to the | |
/// pointer-down event. | |
/// At the end of the animation, the elements' properties have been | |
/// modified to reflect the pointer-down state. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.pointerDown_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return thisWinUI.executeTransition( | |
element, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 167, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "scale(0.975, 0.975)" | |
}); | |
}, | |
pointerUp: function (element) { | |
/// <signature helpKeyword="WinJS.UI.Animation.pointerUp"> | |
/// <summary locid="WinJS.UI.Animation.pointerUp"> | |
/// Execute a pointer-up animation. | |
/// This reverses the effect of a pointerDown animation. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.pointerUp_p:element"> | |
/// Single element or collection of elements responding to | |
/// the pointer-up event. | |
/// At the end of the animation, the elements' properties have been | |
/// returned to normal. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.pointerUp_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return thisWinUI.executeTransition( | |
element, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 167, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
}, | |
dragSourceStart: function (dragSource, affected) { | |
/// <signature helpKeyword="WinJS.UI.Animation.dragSourceStart"> | |
/// <summary locid="WinJS.UI.Animation.dragSourceStart"> | |
/// Execute a drag-start animation. | |
/// Use the dragSourceEnd animation to reverse the effects of this animation. | |
/// </summary> | |
/// <param name="dragSource" locid="WinJS.UI.Animation.dragSourceStart_p:dragSource"> | |
/// Single element or collection of elements being dragged. | |
/// At the end of the animation, the elements' properties have been | |
/// modified to reflect the drag state. | |
/// </param> | |
/// <param name="affected" locid="WinJS.UI.Animation.dragSourceStart_p:affected"> | |
/// Single element or collection of elements to highlight as not | |
/// being dragged. | |
/// At the end of the animation, the elements' properties have been | |
/// modified to reflect the drag state. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.dragSourceStart_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var promise1 = thisWinUI.executeTransition( | |
dragSource, | |
[{ | |
property: mstransform, | |
delay: 0, | |
duration: 240, | |
timing : "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "scale(1.05)" | |
}, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 240, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: 0.65 | |
}]); | |
var promise2 = thisWinUI.executeTransition( | |
affected, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 240, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "scale(0.95)" | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
dragSourceEnd: function (dragSource, offset, affected) { | |
/// <signature helpKeyword="WinJS.UI.Animation.dragSourceEnd"> | |
/// <summary locid="WinJS.UI.Animation.dragSourceEnd"> | |
/// Execute a drag-end animation. | |
/// This reverses the effect of the dragSourceStart animation. | |
/// </summary> | |
/// <param name="dragSource" locid="WinJS.UI.Animation.dragSourceEnd_p:dragSource"> | |
/// Single element or collection of elements no longer being dragged. | |
/// At the end of the animation, the elements' properties have been | |
/// returned to normal. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.dragSourceEnd_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the starting point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// dragSource parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <param name="affected" locid="WinJS.UI.Animation.dragSourceEnd_p:affected"> | |
/// Single element or collection of elements which were highlighted as not | |
/// being dragged. | |
/// At the end of the animation, the elements' properties have been | |
/// returned to normal. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.dragSourceEnd_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-dragSourceEnd"); | |
var promise1 = thisWinUI.executeTransition( | |
dragSource, | |
[{ | |
property: mstransform, | |
delay: 0, | |
duration : 500, | |
timing : "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" // this removes the scale | |
}, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 500, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: 1 | |
}]); | |
var promise2 = thisWinUI.executeAnimation( | |
dragSource, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 500, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: offsetArray.keyframe || translateCallback(offsetArray, "scale(1.05) "), | |
to: "none" | |
}); | |
var promise3 = thisWinUI.executeTransition( | |
affected, | |
{ | |
property: mstransform, | |
delay : 0, | |
duration : 500, | |
timing : "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
return WinJS.Promise.join([promise1, promise2, promise3]); | |
}, | |
enterContent: function (incoming, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.enterContent"> | |
/// <summary locid="WinJS.UI.Animation.enterContent"> | |
/// Execute an enter-content animation. | |
/// </summary> | |
/// <param name="incoming" locid="WinJS.UI.Animation.enterContent_p:incoming"> | |
/// Single element or collection of elements which represent | |
/// the incoming content. | |
/// At the end of the animation, the opacity of the elements is 1. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.enterContent_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the starting point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// incoming parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.enterContent_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray; | |
if (isSnapped()) { | |
offsetArray = new OffsetArray(offset, "WinJS-enterContent-snapped", [{ top: "0px", left: "20px", rtlflip: true }]); | |
} else { | |
offsetArray = new OffsetArray(offset, "WinJS-enterContent", [{ top: "0px", left: "40px", rtlflip: true }]); | |
} | |
var promise1 = thisWinUI.executeAnimation( | |
incoming, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 550, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: offsetArray.keyframe || translateCallback(offsetArray), | |
to: "none" | |
}); | |
var promise2 = thisWinUI.executeTransition( | |
incoming, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 170, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: 0, | |
to: 1 | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
exitContent: function (outgoing, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.exitContent"> | |
/// <summary locid="WinJS.UI.Animation.exitContent"> | |
/// Execute an exit-content animation. | |
/// </summary> | |
/// <param name="outgoing" locid="WinJS.UI.Animation.exitContent_p:outgoing"> | |
/// Single element or collection of elements which represent | |
/// the outgoing content. | |
/// At the end of the animation, the opacity of the elements is 0. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.exitContent_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the ending point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// outgoing parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.exitContent_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-exit", [{ top: "0px", left: "0px" }]); | |
var promise1 = thisWinUI.executeAnimation( | |
outgoing, | |
offset && { | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 117, | |
timing: "linear", | |
from: "none", | |
to: offsetArray.keyframe || translateCallback(offsetArray) | |
}); | |
var promise2 = thisWinUI.executeTransition( | |
outgoing, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 117, | |
timing: "linear", | |
to: 0 | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
dragBetweenEnter: function (target, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.dragBetweenEnter"> | |
/// <summary locid="WinJS.UI.Animation.dragBetweenEnter"> | |
/// Execute an animation which indicates that a dragged object | |
/// can be dropped between other elements. | |
/// Use the dragBetweenLeave animation to reverse the effects of this animation. | |
/// </summary> | |
/// <param name="target" locid="WinJS.UI.Animation.dragBetweenEnter_p:target"> | |
/// Single element or collection of elements (usually two) | |
/// that the dragged object can be dropped between. | |
/// At the end of the animation, the elements' properties have been | |
/// modified to reflect the drag-between state. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.dragBetweenEnter_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the ending point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.dragBetweenEnter_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, null, [{ top: "-40px", left: "0px" }, { top: "40px", left: "0px" }]); | |
return thisWinUI.executeTransition( | |
target, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 200, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: translateCallback(offsetArray, "scale(0.95) ") | |
}); | |
}, | |
dragBetweenLeave: function (target) { | |
/// <signature helpKeyword="WinJS.UI.Animation.dragBetweenLeave"> | |
/// <summary locid="WinJS.UI.Animation.dragBetweenLeave"> | |
/// Execute an animation which indicates that a dragged object | |
/// will no longer be dropped between other elements. | |
/// This reverses the effect of the dragBetweenEnter animation. | |
/// </summary> | |
/// <param name="target" locid="WinJS.UI.Animation.dragBetweenLeave_p:target"> | |
/// Single element or collection of elements (usually two) | |
/// that the dragged object no longer will be dropped between. | |
/// At the end of the animation, the elements' properties have been | |
/// set to the dragSourceStart state. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.dragBetweenLeave_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return thisWinUI.executeTransition( | |
target, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 200, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "scale(0.95)" | |
}); | |
}, | |
swipeSelect: function (selected, selection) { | |
/// <signature helpKeyword="WinJS.UI.Animation.swipeSelect"> | |
/// <summary locid="WinJS.UI.Animation.swipeSelect"> | |
/// Slide a swipe-selected object back into position when the | |
/// pointer is released, and show the selection mark. | |
/// </summary> | |
/// <param name="selected" locid="WinJS.UI.Animation.swipeSelect_p:selected"> | |
/// Single element or collection of elements being selected. | |
/// At the end of the animation, the elements' properties have been | |
/// returned to normal. | |
/// </param> | |
/// <param name="selection" locid="WinJS.UI.Animation.swipeSelect_p:selection"> | |
/// Single element or collection of elements that is the selection mark. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.swipeSelect_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var promise1 = thisWinUI.executeTransition( | |
selected, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 300, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
var promise2 = thisWinUI.executeAnimation( | |
selection, | |
{ | |
keyframe: "WinJS-opacity-in", | |
property: "opacity", | |
delay: 0, | |
duration: 300, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: 0, | |
to: 1 | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
swipeDeselect: function (deselected, selection) { | |
/// <signature helpKeyword="WinJS.UI.Animation.swipeDeselect"> | |
/// <summary locid="WinJS.UI.Animation.swipeDeselect"> | |
/// Slide a swipe-deselected object back into position when the | |
/// pointer is released, and hide the selection mark. | |
/// </summary> | |
/// <param name="deselected" locid="WinJS.UI.Animation.swipeDeselect_p:deselected"> | |
/// Single element or collection of elements being deselected. | |
/// At the end of the animation, the elements' properties have been | |
/// returned to normal. | |
/// </param> | |
/// <param name="selection" locid="WinJS.UI.Animation.swipeDeselect_p:selection"> | |
/// Single element or collection of elements that is the selection mark. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.swipeDeselect_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var promise1 = thisWinUI.executeTransition( | |
deselected, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 300, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: "" | |
}); | |
var promise2 = thisWinUI.executeAnimation( | |
selection, | |
{ | |
keyframe: "WinJS-opacity-out", | |
property: "opacity", | |
delay: 0, | |
duration: 300, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: 1, | |
to: 0 | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
swipeReveal: function (target, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.swipeReveal"> | |
/// <summary locid="WinJS.UI.Animation.swipeReveal"> | |
/// Reveal an object as the result of a swipe, or slide the | |
/// swipe-selected object back into position after the reveal. | |
/// </summary> | |
/// <param name="target" locid="WinJS.UI.Animation.swipeReveal_p:target"> | |
/// Single element or collection of elements being selected. | |
/// At the end of the animation, the elements' properties have been | |
/// modified to reflect the specified offset. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.swipeReveal_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the ending point of the animation. | |
/// When moving the object back into position, the offset should be | |
/// { top: "0px", left: "0px" }. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// The default value describes the motion for a reveal. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.swipeReveal_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, null, [{ top: "25px", left: "0px" }]); | |
return thisWinUI.executeTransition( | |
target, | |
{ | |
property: mstransform, | |
delay: 0, | |
duration: 300, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
to: translateCallback(offsetArray) | |
}); | |
}, | |
enterPage: function (element, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.enterPage"> | |
/// <summary locid="WinJS.UI.Animation.enterPage"> | |
/// Execute an enterPage animation. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.enterPage_p:element"> | |
/// Single element or collection of elements representing the | |
/// incoming page. | |
/// At the end of the animation, the opacity of the elements is 1. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.enterPage_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the starting point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// element parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.enterPage_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray; | |
if (isSnapped()) { | |
offsetArray = new OffsetArray(offset, "WinJS-enterPage-snapped", [{ top: "0px", left: "40px", rtlflip: true }]); | |
} else { | |
offsetArray = new OffsetArray(offset, "WinJS-enterPage", [{ top: "0px", left: "100px", rtlflip: true }]); | |
} | |
var promise1 = thisWinUI.executeAnimation( | |
element, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: staggerDelay(0, 83, 1, 333), | |
duration: 1000, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: offsetArray.keyframe || translateCallback(offsetArray), | |
to: "none" | |
}); | |
var promise2 = thisWinUI.executeTransition( | |
element, | |
{ | |
property: "opacity", | |
delay: staggerDelay(0, 83, 1, 333), | |
duration: 170, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: 0, | |
to: 1 | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
exitPage: function (outgoing, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.exitPage"> | |
/// <summary locid="WinJS.UI.Animation.exitPage"> | |
/// Execute an exitPage animation. | |
/// </summary> | |
/// <param name="outgoing" locid="WinJS.UI.Animation.exitPage_p:outgoing"> | |
/// Single element or collection of elements representing | |
/// the outgoing page. | |
/// At the end of the animation, the opacity of the elements is 0. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.exitPage_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the ending point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// outgoing parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.exitPage_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-exit", [{ top: "0px", left: "0px" }]); | |
var promise1 = thisWinUI.executeAnimation( | |
outgoing, | |
offset && { | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 117, | |
timing: "linear", | |
from: "none", | |
to: offsetArray.keyframe || translateCallback(offsetArray) | |
}); | |
var promise2 = thisWinUI.executeTransition( | |
outgoing, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 117, | |
timing: "linear", | |
to: 0 | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
crossFade: function (incoming, outgoing) { | |
/// <signature helpKeyword="WinJS.UI.Animation.crossFade"> | |
/// <summary locid="WinJS.UI.Animation.crossFade"> | |
/// Execute a crossFade animation. | |
/// </summary> | |
/// <param name="incoming" locid="WinJS.UI.Animation.crossFade_p:incoming"> | |
/// Single incoming element or collection of incoming elements. | |
/// At the end of the animation, the opacity of the elements is 1. | |
/// </param> | |
/// <param name="outgoing" locid="WinJS.UI.Animation.crossFade_p:outgoing"> | |
/// Single outgoing element or collection of outgoing elements. | |
/// At the end of the animation, the opacity of the elements is 0. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.crossFade_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var promise1 = thisWinUI.executeTransition( | |
incoming, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 167, | |
timing: "linear", | |
to: 1 | |
}); | |
var promise2 = thisWinUI.executeTransition( | |
outgoing, | |
{ | |
property: "opacity", | |
delay: 0, | |
duration: 167, | |
timing: "linear", | |
to: 0 | |
}); | |
return WinJS.Promise.join([promise1, promise2]); | |
}, | |
createPeekAnimation: function (element) { | |
/// <signature helpKeyword="WinJS.UI.Animation.createPeekAnimation"> | |
/// <summary locid="WinJS.UI.Animation.createPeekAnimation"> | |
/// Creates a peek animation. | |
/// After creating the PeekAnimation object, | |
/// modify the document to move the elements to their new positions, | |
/// then call the execute method on the PeekAnimation object. | |
/// </summary> | |
/// <param name="element" locid="WinJS.UI.Animation.createPeekAnimation_p:element"> | |
/// Single element or collection of elements to be repositioned for peek. | |
/// </param> | |
/// <returns type="{ execute: Function }" locid="WinJS.UI.Animation.createPeekAnimation_returnValue"> | |
/// PeekAnimation object whose execute method returns | |
/// a Promise that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
return layoutTransition(PeekAnimation, null, element); | |
}, | |
updateBadge: function (incoming, offset) { | |
/// <signature helpKeyword="WinJS.UI.Animation.updateBadge"> | |
/// <summary locid="WinJS.UI.Animation.updateBadge"> | |
/// Execute an updateBadge animation. | |
/// </summary> | |
/// <param name="incoming" locid="WinJS.UI.Animation.updateBadge_p:incoming"> | |
/// Single element or collection of elements representing the | |
/// incoming badge. | |
/// </param> | |
/// <param name="offset" locid="WinJS.UI.Animation.updateBadge_p:offset"> | |
/// Optional offset object or collection of offset objects | |
/// array describing the starting point of the animation. | |
/// If the number of offset objects is less than the length of the | |
/// incoming parameter, then the last value is repeated for all | |
/// remaining elements. | |
/// If this parameter is omitted, then a default value is used. | |
/// </param> | |
/// <returns type="WinJS.Promise" locid="WinJS.UI.Animation.updateBadge_returnValue"> | |
/// Promise object that completes when the animation is complete. | |
/// </returns> | |
/// </signature> | |
var offsetArray = new OffsetArray(offset, "WinJS-updateBadge", [{ top: "24px", left: "0px" }]); | |
return thisWinUI.executeAnimation( | |
incoming, | |
[{ | |
keyframe: "WinJS-opacity-in", | |
property: "opacity", | |
delay: 0, | |
duration: 367, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: 0, | |
to: 1 | |
}, | |
{ | |
keyframe: offsetArray.keyframe, | |
property: mstransform, | |
delay: 0, | |
duration: 1333, | |
timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", | |
from: offsetArray.keyframe || translateCallback(offsetArray), | |
to: "none" | |
}]); | |
} | |
}); | |
})(WinJS); | |
/*#DBG | |
var _ASSERT = function (condition) { | |
if (!condition) { | |
throw "ASSERT FAILED"; | |
} | |
}; | |
var _TRACE = function (text) { | |
if (window.console && console.log) { | |
console.log(text); | |
} | |
}; | |
#DBG*/ | |
// WinJS.Binding.ListDataSource | |
// | |
(function bindingListDataSourceInit(global, undefined) { | |
"use strict"; | |
var errors = { | |
get noLongerMeaningful() { return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.EditError.noLongerMeaningful)); } | |
}; | |
function findNextKey(list, index) { | |
var len = list.length; | |
while (index < len - 1) { | |
var item = list.getItem(++index); | |
if (item) { | |
return item.key; | |
} | |
} | |
return null; | |
} | |
function findPreviousKey(list, index) { | |
while (index > 0) { | |
var item = list.getItem(--index); | |
if (item) { | |
return item.key; | |
} | |
} | |
return null; | |
} | |
function subscribe(target, handlers) { | |
Object.keys(handlers).forEach(function (handler) { | |
target.addEventListener(handler, handlers[handler]); | |
}); | |
} | |
function unsubscribe(target, handlers) { | |
Object.keys(handlers).forEach(function (handler) { | |
target.removeEventListener(handler, handlers[handler]); | |
}); | |
} | |
var CompletePromise = WinJS.Promise.wrap().constructor; | |
var NullWrappedItem = WinJS.Class.derive(CompletePromise, | |
function () { | |
this._value = null; | |
}, { | |
release: function () { }, | |
retain: function () { return this; } | |
}, { | |
/* empty */ | |
}, { | |
supportedForProcessing: false, | |
} | |
); | |
var WrappedItem = WinJS.Class.derive(CompletePromise, | |
function (listBinding, item) { | |
this._value = item; | |
this._listBinding = listBinding; | |
}, { | |
handle: { | |
get: function () { return this._value.key; } | |
}, | |
index: { | |
get: function () { return this._value.index; } | |
}, | |
release: function () { | |
this._listBinding._release(this._value, this._listBinding._list.indexOfKey(this._value.key)); | |
}, | |
retain: function () { | |
this._listBinding._addRef(this._value, this._listBinding._list.indexOfKey(this._value.key)); | |
return this; | |
} | |
}, { | |
/* empty */ | |
}, { | |
supportedForProcessing: false, | |
} | |
); | |
var AsyncWrappedItem = WinJS.Class.derive(WinJS.Promise, | |
function (listBinding, item) { | |
var that = this; | |
this._item = item; | |
this._listBinding = listBinding; | |
WinJS.Promise.call(this, function (c) { | |
setImmediate(function () { | |
if (listBinding._released) { | |
that.cancel(); | |
return; | |
} | |
c(item); | |
}); | |
}); | |
}, { | |
handle: { | |
get: function () { return this._item.key; } | |
}, | |
index: { | |
get: function () { return this._item.index; } | |
}, | |
release: function () { | |
this._listBinding._release(this._item, this._listBinding._list.indexOfKey(this._item.key)); | |
}, | |
retain: function () { | |
this._listBinding._addRef(this._item, this._listBinding._list.indexOfKey(this._item.key)); | |
return this; | |
} | |
}, { | |
/* empty */ | |
}, { | |
supportedForProcessing: false, | |
} | |
); | |
function wrap(listBinding, item) { | |
return item ? new WrappedItem(listBinding, item) : new NullWrappedItem(); | |
} | |
function wrapAsync(listBinding, item) { | |
return item ? new AsyncWrappedItem(listBinding, item) : new NullWrappedItem(); | |
} | |
function cloneWithIndex(list, item, index) { | |
return item && list._annotateWithIndex(item, index); | |
} | |
var ListBinding = WinJS.Class.define( | |
function ListBinding_ctor(dataSource, list, notificationHandler) { | |
this._dataSource = dataSource; | |
this._list = list; | |
this._editsCount = 0; | |
this._notificationHandler = notificationHandler; | |
this._pos = -1; | |
this._retained = []; | |
this._retained.length = list.length; | |
this._retainedKeys = {}; | |
if (this._notificationHandler) { | |
var that = this; | |
this._handlers = { | |
itemchanged: function (event) { | |
var key = event.detail.key; | |
var index = event.detail.index; | |
var newItem = event.detail.newItem; | |
var oldItem = that._retained[index]; | |
if (oldItem) { | |
if (oldItem.index !== index) { | |
var oldIndex = oldItem.index; | |
oldItem.index = index; | |
if (that._notificationHandler.indexChanged) { | |
that._notificationHandler.indexChanged(newItem.key, index, oldIndex); | |
} | |
} | |
newItem = cloneWithIndex(list, newItem, index); | |
newItem._retainedCount = oldItem._retainedCount; | |
that._retained[index] = newItem; | |
that._retainedKeys[key] = newItem; | |
that._beginEdits(list.length); | |
if (notificationHandler && notificationHandler.changed) { | |
notificationHandler.changed( | |
newItem, | |
oldItem | |
); | |
} | |
that._endEdits(); | |
} | |
}, | |
iteminserted: function (event) { | |
var key = event.detail.key; | |
var index = event.detail.index; | |
that._beginEdits(list.length - 1); | |
if (index <= that._pos) { | |
that._pos = Math.min(that._pos + 1, list.length); | |
} | |
var retained = that._retained; | |
// create a hole for this thing and then immediately make it undefined | |
retained.splice(index, 0, 0); | |
delete retained[index]; | |
if (that._shouldNotify(index) || list.length === 1) { | |
if (notificationHandler && notificationHandler.inserted) { | |
notificationHandler.inserted( | |
wrap(that, cloneWithIndex(list, list.getItem(index), index)), | |
findPreviousKey(list, index), | |
findNextKey(list, index) | |
); | |
} | |
} | |
that._endEdits(); | |
}, | |
itemmoved: function (event) { | |
var key = event.detail.key; | |
var oldIndex = event.detail.oldIndex; | |
var newIndex = event.detail.newIndex; | |
that._beginEdits(list.length); | |
if (oldIndex < that._pos || newIndex <= that._pos) { | |
if (newIndex > that._pos) { | |
that._pos = Math.max(-1, that._pos - 1); | |
} else if (oldIndex > that._pos) { | |
that._pos = Math.min(that._pos + 1, list.length); | |
} | |
} | |
var retained = that._retained; | |
var item = retained.splice(oldIndex, 1)[0]; | |
retained.splice(newIndex, 0, item); | |
if (!item) { | |
delete retained[newIndex]; | |
item = cloneWithIndex(list, list.getItem(newIndex), newIndex); | |
} | |
item._moved = true; | |
that._addRef(item, newIndex); | |
that._endEdits(); | |
}, | |
itemremoved: function (event) { | |
var key = event.detail.key; | |
var index = event.detail.index; | |
that._beginEdits(list.length + 1); | |
if (index < that._pos) { | |
that._pos = Math.max(-1, that._pos - 1); | |
} | |
var retained = that._retained; | |
var retainedKeys = that._retainedKeys; | |
var wasRetained = index in retained; | |
retained.splice(index, 1); | |
delete retainedKeys[key]; | |
if (wasRetained && notificationHandler && notificationHandler.removed) { | |
notificationHandler.removed(key, false); | |
} | |
that._endEdits(); | |
}, | |
reload: function () { | |
that._retained = []; | |
that._retainedKeys = {}; | |
if (notificationHandler && notificationHandler.reload) { | |
notificationHandler.reload(); | |
} | |
} | |
}; | |
subscribe(this._list, this._handlers); | |
} | |
}, { | |
_addRef: function (item, index) { | |
if (index in this._retained) { | |
this._retained[index]._retainedCount++; | |
} else { | |
this._retained[index] = item; | |
this._retainedKeys[item.key] = item; | |
item._retainedCount = 1; | |
} | |
}, | |
_release: function (item, index) { | |
var retained = this._retained[index]; | |
if (retained) { | |
//#DBG _ASSERT(retained.key === item.key); | |
if (retained._retainedCount === 1) { | |
delete this._retained[index]; | |
delete this._retainedKeys[retained.key]; | |
} else { | |
retained._retainedCount--; | |
} | |
} | |
/*#DBG | |
// If an item isn't found in the retained map, it was either removed from retainedCount reaching zero, or removed from the map by a removed notification. | |
// We'll decrement the count here for debugging purposes. If retainedCount is less than zero, there's a refcounting error somewhere. | |
if (!retained) { | |
item._retainedCount--; | |
_ASSERT(item._retainedCount >= 0); | |
} | |
#DBG*/ | |
}, | |
_shouldNotify: function (index) { | |
var retained = this._retained; | |
return index in retained || index + 1 in retained || index - 1 in retained; | |
}, | |
_notifyCountChanged: function () { | |
var oldCount = this._countAtBeginEdits; | |
var newCount = this._list.length; | |
if (oldCount !== newCount) { | |
if (this._notificationHandler && this._notificationHandler.countChanged) { | |
this._notificationHandler.countChanged(newCount, oldCount); | |
} | |
} | |
}, | |
_notifyIndicesChanged: function () { | |
var retained = this._retained; | |
for (var i = 0, len = retained.length; i < len; i++) { | |
var item = retained[i]; | |
if (item && item.index !== i) { | |
var newIndex = i; | |
var oldIndex = item.index; | |
item.index = newIndex; | |
if (this._notificationHandler && this._notificationHandler.indexChanged) { | |
this._notificationHandler.indexChanged(item.key, newIndex, oldIndex); | |
} | |
} | |
} | |
}, | |
_notifyMoved: function () { | |
var retained = this._retained; | |
for (var i = 0, len = retained.length; i < len; i++) { | |
var item = retained[i]; | |
if (item && item._moved) { | |
item._moved = false; | |
this._release(item, i); | |
if (this._shouldNotify(i)) { | |
if (this._notificationHandler && this._notificationHandler.moved) { | |
this._notificationHandler.moved( | |
wrap(this, item), | |
findPreviousKey(this._list, i), | |
findNextKey(this._list, i) | |
); | |
} | |
} | |
} | |
} | |
}, | |
_beginEdits: function (length, explicit) { | |
this._editsCount++; | |
if (this._editsCount === 1 && this._notificationHandler) { | |
if (!explicit) { | |
// Batch all edits between now and the setImmediate firing. This has the effect | |
// of batching synchronous edits. | |
// | |
this._editsCount++; | |
var that = this; | |
setImmediate(function () { | |
that._endEdits(); | |
}); | |
} | |
if (this._notificationHandler && this._notificationHandler.beginNotifications) { | |
this._notificationHandler.beginNotifications(); | |
} | |
this._countAtBeginEdits = length; | |
} | |
}, | |
_endEdits: function () { | |
this._editsCount--; | |
if (this._editsCount === 0 && this._notificationHandler) { | |
this._notifyIndicesChanged(); | |
this._notifyMoved(); | |
this._notifyCountChanged(); | |
if (this._notificationHandler && this._notificationHandler.endNotifications) { | |
this._notificationHandler.endNotifications(); | |
} | |
} | |
}, | |
jumpToItem: function (item) { | |
var index = this._list.indexOfKey(item.handle); | |
if (index === -1) { | |
return WinJS.Promise.wrap(null); | |
} | |
this._pos = index; | |
return this.current(); | |
}, | |
current: function () { | |
return this.fromIndex(this._pos); | |
}, | |
previous: function () { | |
this._pos = Math.max(-1, this._pos - 1); | |
return this._fromIndex(this._pos, true); | |
}, | |
next: function () { | |
this._pos = Math.min(this._pos + 1, this._list.length); | |
return this._fromIndex(this._pos, true); | |
}, | |
releaseItem: function (item) { | |
if (item.release) { | |
item.release(); | |
} else { | |
this._release(item, this._list.indexOfKey(item.key)); | |
} | |
}, | |
release: function () { | |
if (this._notificationHandler) { | |
unsubscribe(this._list, this._handlers); | |
} | |
this._notificationHandler = null; | |
this._dataSource._releaseBinding(this); | |
this._released = true; | |
}, | |
first: function () { | |
return this.fromIndex(0); | |
}, | |
last: function () { | |
return this.fromIndex(this._list.length - 1); | |
}, | |
fromKey: function (key) { | |
var retainedKeys = this._retainedKeys; | |
var item; | |
if (key in retainedKeys) { | |
item = retainedKeys[key]; | |
} else { | |
item = cloneWithIndex(this._list, this._list.getItemFromKey(key), this._list.indexOfKey(key)); | |
} | |
return wrap(this, item); | |
}, | |
fromIndex: function (index) { | |
return this._fromIndex(index, false); | |
}, | |
_fromIndex: function (index, async) { | |
var retained = this._retained; | |
var item; | |
if (index in retained) { | |
item = retained[index]; | |
} else { | |
item = cloneWithIndex(this._list, this._list.getItem(index), index); | |
} | |
return async ? wrapAsync(this, item) : wrap(this, item); | |
}, | |
}, { | |
supportedForProcessing: false, | |
} | |
); | |
function insertAtStart(unused, data) { | |
// List ignores the key because its key management is internal | |
this._list.unshift(data); | |
return this.itemFromIndex(0); | |
} | |
function insertBefore(unused, data, nextKey) { | |
// List ignores the key because its key management is internal | |
var index = this._list.indexOfKey(nextKey); | |
if (index === -1) { | |
return errors.noLongerMeaningful; | |
} | |
this._list.splice(index, 0, data); | |
return this.itemFromIndex(index); | |
} | |
function insertAfter(unused, data, previousKey) { | |
// List ignores the key because its key management is internal | |
var index = this._list.indexOfKey(previousKey); | |
if (index === -1) { | |
return errors.noLongerMeaningful; | |
} | |
index += 1; | |
this._list.splice(index, 0, data); | |
return this.itemFromIndex(index); | |
} | |
function insertAtEnd(unused, data) { | |
// List ignores the key because its key management is internal | |
this._list.push(data); | |
return this.itemFromIndex(this._list.length - 1); | |
} | |
function change(key, newData) { | |
var index = this._list.indexOfKey(key); | |
if (index === -1) { | |
return errors.noLongerMeaningful; | |
} | |
this._list.setAt(index, newData); | |
return this.itemFromIndex(index); | |
} | |
function moveToStart(key) { | |
var sourceIndex = this._list.indexOfKey(key); | |
if (sourceIndex === -1) { | |
return errors.noLongerMeaningful; | |
} | |
var targetIndex = 0; | |
this._list.move(sourceIndex, targetIndex); | |
return this.itemFromIndex(targetIndex); | |
} | |
function moveBefore(key, nextKey) { | |
var sourceIndex = this._list.indexOfKey(key); | |
var targetIndex = this._list.indexOfKey(nextKey); | |
if (sourceIndex === -1 || targetIndex === -1) { | |
return errors.noLongerMeaningful; | |
} | |
targetIndex = sourceIndex < targetIndex ? targetIndex - 1 : targetIndex; | |
this._list.move(sourceIndex, targetIndex); | |
return this.itemFromIndex(targetIndex); | |
} | |
function moveAfter(key, previousKey) { | |
var sourceIndex = this._list.indexOfKey(key); | |
var targetIndex = this._list.indexOfKey(previousKey); | |
if (sourceIndex === -1 || targetIndex === -1) { | |
return errors.noLongerMeaningful; | |
} | |
targetIndex = sourceIndex <= targetIndex ? targetIndex : targetIndex + 1; | |
this._list.move(sourceIndex, targetIndex); | |
return this.itemFromIndex(targetIndex); | |
} | |
function moveToEnd(key) { | |
var sourceIndex = this._list.indexOfKey(key); | |
if (sourceIndex === -1) { | |
return errors.noLongerMeaningful; | |
} | |
var targetIndex = this._list.length - 1; | |
this._list.move(sourceIndex, targetIndex); | |
return this.itemFromIndex(targetIndex); | |
} | |
function remove(key) { | |
var index = this._list.indexOfKey(key); | |
if (index === -1) { | |
return errors.noLongerMeaningful; | |
} | |
this._list.splice(index, 1); | |
return WinJS.Promise.wrap(); | |
} | |
var bindingId = 0; | |
var DataSource = WinJS.Class.define( | |
function DataSource_ctor(list) { | |
this._bindings = []; | |
this._list = list; | |
if (list.unshift) { | |
this.insertAtStart = insertAtStart; | |
} | |
if (list.push) { | |
this.insertAtEnd = insertAtEnd; | |
} | |
if (list.setAt) { | |
this.change = change; | |
} | |
if (list.splice) { | |
this.insertAfter = insertAfter; | |
this.insertBefore = insertBefore; | |
this.remove = remove; | |
} | |
if (list.move) { | |
this.moveAfter = moveAfter; | |
this.moveBefore = moveBefore; | |
this.moveToEnd = moveToEnd; | |
this.moveToStart = moveToStart; | |
} | |
}, { | |
_releaseBinding: function (binding) { | |
delete this._bindings[binding._id]; | |
}, | |
addEventListener: function () { | |
// nop, we don't send statusChanged | |
}, | |
removeEventListener: function () { | |
// nop, we don't send statusChanged | |
}, | |
createListBinding: function (notificationHandler) { | |
var binding = new ListBinding(this, this._list, notificationHandler); | |
binding._id = (++bindingId); | |
this._bindings[binding._id] = binding; | |
return binding; | |
}, | |
getCount: function () { | |
return WinJS.Promise.wrap(this._list.length); | |
}, | |
itemFromKey: function (key) { | |
// Clone with a dummy index | |
var list = this._list, | |
item = cloneWithIndex(list, list.getItemFromKey(key), -1); | |
// Override the index property with a getter | |
Object.defineProperty(item, "index", { | |
get: function () { | |
return list.indexOfKey(key); | |
}, | |
enumerable: false, | |
configurable: true | |
}); | |
return WinJS.Promise.wrap(item); | |
}, | |
itemFromIndex: function (index) { | |
return WinJS.Promise.wrap(cloneWithIndex(this._list, this._list.getItem(index), index)); | |
}, | |
list: { | |
get: function () { return this._list; } | |
}, | |
beginEdits: function () { | |
var length = this._list.length; | |
this._bindings.forEach(function (binding) { | |
binding._beginEdits(length, true); | |
}); | |
}, | |
endEdits: function () { | |
this._bindings.forEach(function (binding) { | |
binding._endEdits(); | |
}); | |
}, | |
invalidateAll: function() { | |
return WinJS.Promise.wrap(); | |
}, | |
// | |
// insert* and change are not implemented as I don't understand how they are | |
// used by the controls since it is hard to fathom how they would be able | |
// to make up unique keys. Manual editing of the List is meant to go through | |
// the list itself. | |
// | |
// move* are implemented only if the underlying list supports move(). The | |
// GroupsListProjection for instance does not. | |
// | |
moveAfter: undefined, | |
moveBefore: undefined, | |
moveToEnd: undefined, | |
moveToStart: undefined | |
}, { | |
supportedForProcessing: false, | |
} | |
); | |
if (WinJS.Binding && WinJS.Binding.List) { | |
Object.defineProperty(Object.getPrototypeOf(Object.getPrototypeOf(WinJS.Binding.List.prototype)), "dataSource", { | |
get: function () { return (this._dataSource = this._dataSource || new DataSource(this)); } | |
}); | |
} | |
}(this)); | |
// Virtualized Data Source | |
(function listDataSourceInit(undefined) { | |
"use strict"; | |
var Promise = WinJS.Promise, | |
Signal = WinJS._Signal, | |
UI = WinJS.UI; | |
// Private statics | |
var strings = { | |
get listDataAdapterIsInvalid() { return WinJS.Resources._getWinJSString("ui/listDataAdapterIsInvalid").value; }, | |
get indexIsInvalid() { return WinJS.Resources._getWinJSString("ui/indexIsInvalid").value; }, | |
get keyIsInvalid() { return WinJS.Resources._getWinJSString("ui/keyIsInvalid").value; }, | |
get invalidItemReturned() { return WinJS.Resources._getWinJSString("ui/undefinedItemReturned").value; }, | |
get invalidKeyReturned() { return WinJS.Resources._getWinJSString("ui/invalidKeyReturned").value; }, | |
get invalidIndexReturned() { return WinJS.Resources._getWinJSString("ui/invalidIndexReturned").value; }, | |
get invalidCountReturned() { return WinJS.Resources._getWinJSString("ui/invalidCountReturned").value; }, | |
get invalidRequestedCountReturned() { return WinJS.Resources._getWinJSString("ui/invalidRequestedCountReturned").value; }, | |
}; | |
var statusChangedEvent = "statuschanged"; | |
function _baseDataSourceConstructor(listDataAdapter, options) { | |
/// <signature helpKeyword="WinJS.UI.VirtualizedDataSource._baseDataSourceConstructor"> | |
/// <summary locid="WinJS.UI.VirtualizedDataSource._baseDataSourceConstructor"> | |
/// Initializes the VirtualizedDataSource base class of a custom data source. | |
/// </summary> | |
/// <param name="listDataAdapter" type="IListDataAdapter" locid="WinJS.UI.VirtualizedDataSource._baseDataSourceConstructor_p:itemIndex"> | |
/// An object that implements IListDataAdapter and supplies data to the VirtualizedDataSource. | |
/// </param> | |
/// <param name="options" optional="true" type="Object" locid="WinJS.UI.VirtualizedDataSource._baseDataSourceConstructor_p:options"> | |
/// An object that contains properties that specify additonal options for the VirtualizedDataSource: | |
/// | |
/// cacheSize | |
/// A Number that specifies minimum number of unrequested items to cache in case they are requested. | |
/// | |
/// The options parameter is optional. | |
/// </param> | |
/// </signature> | |
// Private members | |
var listDataNotificationHandler, | |
cacheSize, | |
status, | |
statusPending, | |
statusChangePosted, | |
bindingMap, | |
nextListBindingID, | |
nextHandle, | |
nextListenerID, | |
getCountPromise, | |
resultsProcessed, | |
beginEditsCalled, | |
editsInProgress, | |
firstEditInProgress, | |
editQueue, | |
editsQueued, | |
synchronousEdit, | |
waitForRefresh, | |
dataNotificationsInProgress, | |
countDelta, | |
indexUpdateDeferred, | |
nextTempKey, | |
currentRefreshID, | |
fetchesPosted, | |
nextFetchID, | |
fetchesInProgress, | |
fetchCompleteCallbacks, | |
startMarker, | |
endMarker, | |
knownCount, | |
slotsStart, | |
slotListEnd, | |
slotsEnd, | |
handleMap, | |
keyMap, | |
indexMap, | |
releasedSlots, | |
lastSlotReleased, | |
reduceReleasedSlotCountPosted, | |
refreshRequested, | |
refreshInProgress, | |
refreshSignal, | |
refreshFetchesInProgress, | |
refreshItemsFetched, | |
refreshCount, | |
refreshStart, | |
refreshEnd, | |
keyFetchIDs, | |
refreshKeyMap, | |
refreshIndexMap, | |
deletedKeys, | |
synchronousProgress, | |
reentrantContinue, | |
synchronousRefresh, | |
reentrantRefresh; | |
/*#DBG | |
var totalSlots = 0; | |
function VERIFYLIST() { | |
_ASSERT(slotListEnd.lastInSequence); | |
_ASSERT(slotsEnd.firstInSequence); | |
checkListIntegrity(slotsStart, slotsEnd, keyMap, indexMap); | |
} | |
function VERIFYREFRESHLIST() { | |
checkListIntegrity(refreshStart, refreshEnd, refreshKeyMap, refreshIndexMap); | |
} | |
function checkListIntegrity(listStart, listEnd, keyMapForSlot, indexMapForSlot) { | |
if (UI.VirtualizedDataSource._internalValidation) { | |
var listEndReached, | |
slotWithoutIndexReached; | |
for (var slotCheck = listStart; slotCheck !== listEnd; slotCheck = slotCheck.next) { | |
_ASSERT(slotCheck.next); | |
_ASSERT(slotCheck.next.prev === slotCheck); | |
if (slotCheck.lastInSequence) { | |
_ASSERT(slotCheck.next.firstInSequence); | |
} | |
if (slotCheck !== listStart) { | |
_ASSERT(slotCheck.prev); | |
_ASSERT(slotCheck.prev.next === slotCheck); | |
if (slotCheck.firstInSequence) { | |
_ASSERT(slotCheck.prev.lastInSequence); | |
} | |
} | |
if (slotCheck.item || slotCheck.itemNew) { | |
_ASSERT(editsQueued || slotCheck.key); | |
} | |
if (slotCheck.key) { | |
_ASSERT(keyMapForSlot[slotCheck.key] === slotCheck); | |
if (slotCheck.item) { | |
_ASSERT(slotCheck.item.key === slotCheck.key); | |
} | |
} | |
if (typeof slotCheck.index === "number") { | |
_ASSERT(!listEndReached); | |
if (!indexUpdateDeferred) { | |
_ASSERT(indexMapForSlot[slotCheck.index] === slotCheck); | |
_ASSERT(slotCheck === listStart || slotCheck.prev.index < slotCheck.index); | |
_ASSERT(!slotCheck.firstInSequence || !slotCheck.prev || slotCheck.prev.index !== slotCheck.index - 1); | |
_ASSERT(!slotCheck.lastInSequence || !slotCheck.next || slotCheck.next.index !== slotCheck.index + 1); | |
if (slotCheck.item) { | |
_ASSERT(listStart === refreshStart || slotCheck.item.index === slotCheck.index); | |
} | |
} | |
} else { | |
slotWithoutIndexReached = true; | |
} | |
if (slotCheck === slotListEnd) { | |
listEndReached = true; | |
} | |
if (slotCheck.lastInSequence && !listEndReached && !indexUpdateDeferred) { | |
_ASSERT(!slotWithoutIndexReached); | |
} | |
} | |
} | |
} | |
function OUTPUTLIST() { | |
outputList("Main List", slotsStart); | |
} | |
function OUTPUTREFRESHLIST() { | |
outputList("Refresh List", refreshStart); | |
} | |
function outputList(header, slotFirst) { | |
_TRACE("-- " + header + " --"); | |
for (var slot = slotFirst; slot; slot = slot.next) { | |
var line = (slot.firstInSequence ? "[" : " "); | |
if (slot.index !== undefined && slot !== slotsStart && slot !== refreshStart) { | |
line += slot.index + ": "; | |
} | |
if (slot === slotsStart || slot === refreshStart) { | |
line += "{"; | |
} else if (slot === slotListEnd || slot === refreshEnd) { | |
line += "}"; | |
} else if (slot === slotsEnd) { | |
line += "-"; | |
} else { | |
line += (slot.key ? '"' + slot.key + '"' : "?"); | |
} | |
if (slot.bindingMap) { | |
line += " ("; | |
var first = true; | |
for (var listBindingID in slot.bindingMap) { | |
if (first) { | |
first = false; | |
} else { | |
line += ", "; | |
} | |
line += listBindingID; | |
} | |
line += ")"; | |
} | |
if (slot.itemNew) { | |
line += " itemNew"; | |
} | |
if (slot.item) { | |
line += " item"; | |
} | |
if (slot.fetchListeners) { | |
line += " fetching"; | |
} | |
if (slot.directFetchListeners) { | |
line += " directFetching"; | |
} | |
if (slot.indexRequested) { | |
line += " index"; | |
} | |
if (slot.keyRequested) { | |
line += " key"; | |
} | |
if (slot.description) { | |
line += " description=" + JSON.stringify(slot.description); | |
} | |
if (slotFetchInProgress(slot)) { | |
line += " now"; | |
} | |
if (typeof slot.handle === "string") { | |
line += " <" + slot.handle + ">"; | |
} | |
if (slot.lastInSequence) { | |
line += "]"; | |
} | |
_TRACE(line); | |
} | |
} | |
#DBG*/ | |
function isNonNegativeNumber(n) { | |
return (typeof n === "number") && n >= 0; | |
} | |
function isNonNegativeInteger(n) { | |
return isNonNegativeNumber(n) && n === Math.floor(n); | |
} | |
function validateIndexReturned(index) { | |
// Ensure that index is always undefined or a non-negative integer | |
if (index === null) { | |
index = undefined; | |
} else if (index !== undefined && !isNonNegativeInteger(index)) { | |
throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidIndexReturned", strings.invalidIndexReturned); | |
} | |
return index; | |
} | |
function validateCountReturned(count) { | |
// Ensure that count is always undefined or a non-negative integer | |
if (count === null) { | |
count = undefined; | |
} else if (count !== undefined && !isNonNegativeInteger(count) && count !== CountResult.unknown) { | |
throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidCountReturned", strings.invalidCountReturned); | |
} | |
return count; | |
} | |
// Slot List | |
function createSlot() { | |
var handle = (nextHandle++).toString(), | |
slotNew = { | |
handle: handle, | |
item: null, | |
itemNew: null, | |
fetchListeners: null, | |
cursorCount: 0, | |
bindingMap: null | |
}; | |
// Deliberately not initialized: | |
// - directFetchListeners | |
handleMap[handle] = slotNew; | |
return slotNew; | |
} | |
function createPrimarySlot() { | |
/*#DBG | |
totalSlots++; | |
#DBG*/ | |
return createSlot(); | |
} | |
function insertSlot(slot, slotNext) { | |
//#DBG _ASSERT(slotNext); | |
//#DBG _ASSERT(slotNext.prev); | |
slot.prev = slotNext.prev; | |
slot.next = slotNext; | |
slot.prev.next = slot; | |
slotNext.prev = slot; | |
} | |
function removeSlot(slot) { | |
//#DBG _ASSERT(slot.prev.next === slot); | |
//#DBG _ASSERT(slot.next.prev === slot); | |
//#DBG _ASSERT(slot !== slotsStart && slot !== slotListEnd && slot !== slotsEnd); | |
if (slot.lastInSequence) { | |
delete slot.lastInSequence; | |
slot.prev.lastInSequence = true; | |
} | |
if (slot.firstInSequence) { | |
delete slot.firstInSequence; | |
slot.next.firstInSequence = true; | |
} | |
slot.prev.next = slot.next; | |
slot.next.prev = slot.prev; | |
} | |
function sequenceStart(slot) { | |
while (!slot.firstInSequence) { | |
slot = slot.prev; | |
} | |
return slot; | |
} | |
function sequenceEnd(slot) { | |
while (!slot.lastInSequence) { | |
slot = slot.next; | |
} | |
return slot; | |
} | |
// Does a little careful surgery to the slot sequence from slotFirst to slotLast before slotNext | |
function moveSequenceBefore(slotNext, slotFirst, slotLast) { | |
//#DBG _ASSERT(slotFirst !== slotsStart && slotLast !== slotListEnd && slotLast !== slotsEnd); | |
//#DBG _ASSERT(slotFirst.firstInSequence && slotLast.lastInSequence); | |
//#DBG _ASSERT(slotNext.firstInSequence && slotNext.prev.lastInSequence); | |
slotFirst.prev.next = slotLast.next; | |
slotLast.next.prev = slotFirst.prev; | |
slotFirst.prev = slotNext.prev; | |
slotLast.next = slotNext; | |
slotFirst.prev.next = slotFirst; | |
slotNext.prev = slotLast; | |
return true; | |
} | |
// Does a little careful surgery to the slot sequence from slotFirst to slotLast after slotPrev | |
function moveSequenceAfter(slotPrev, slotFirst, slotLast) { | |
//#DBG _ASSERT(slotFirst !== slotsStart && slotLast !== slotsEnd); | |
//#DBG _ASSERT(slotFirst.firstInSequence && slotLast.lastInSequence); | |
//#DBG _ASSERT(slotPrev.lastInSequence && slotPrev.next.firstInSequence); | |
slotFirst.prev.next = slotLast.next; | |
slotLast.next.prev = slotFirst.prev; | |
slotFirst.prev = slotPrev; | |
slotLast.next = slotPrev.next; | |
slotPrev.next = slotFirst; | |
slotLast.next.prev = slotLast; | |
return true; | |
} | |
function mergeSequences(slotPrev) { | |
delete slotPrev.lastInSequence; | |
delete slotPrev.next.firstInSequence; | |
} | |
function splitSequence(slotPrev) { | |
var slotNext = slotPrev.next; | |
slotPrev.lastInSequence = true; | |
slotNext.firstInSequence = true; | |
if (slotNext === slotListEnd) { | |
// Clear slotListEnd's index, as that's now unknown | |
changeSlotIndex(slotListEnd, undefined); | |
} | |
} | |
// Inserts a slot in the middle of a sequence or between sequences. If the latter, mergeWithPrev and mergeWithNext | |
// parameters specify whether to merge the slot with the previous sequence, or next, or neither. | |
function insertAndMergeSlot(slot, slotNext, mergeWithPrev, mergeWithNext) { | |
insertSlot(slot, slotNext); | |
var slotPrev = slot.prev; | |
if (slotPrev.lastInSequence) { | |
//#DBG _ASSERT(slotNext.firstInSequence); | |
if (mergeWithPrev) { | |
delete slotPrev.lastInSequence; | |
} else { | |
slot.firstInSequence = true; | |
} | |
if (mergeWithNext) { | |
delete slotNext.firstInSequence; | |
} else { | |
slot.lastInSequence = true; | |
} | |
} | |
} | |
// Keys and Indices | |
function setSlotKey(slot, key) { | |
//#DBG _ASSERT(!slot.key); | |
//#DBG _ASSERT(!keyMap[key]); | |
slot.key = key; | |
// Add the slot to the keyMap, so it is possible to quickly find the slot given its key | |
keyMap[slot.key] = slot; | |
} | |
function setSlotIndex(slot, index, indexMapForSlot) { | |
// Tolerate NaN, so clients can pass (undefined - 1) or (undefined + 1) | |
if (+index === index) { | |
//#DBG _ASSERT(indexUpdateDeferred || !indexMapForSlot[index]); | |
slot.index = index; | |
// Add the slot to the indexMap, so it is possible to quickly find the slot given its index | |
indexMapForSlot[index] = slot; | |
if (!indexUpdateDeferred) { | |
// See if any sequences should be merged | |
if (slot.firstInSequence && slot.prev && slot.prev.index === index - 1) { | |
mergeSequences(slot.prev); | |
} | |
if (slot.lastInSequence && slot.next && slot.next.index === index + 1) { | |
mergeSequences(slot); | |
} | |
} | |
} | |
} | |
// Creates a new slot and adds it to the slot list before slotNext | |
function createAndAddSlot(slotNext, indexMapForSlot) { | |
var slotNew = (indexMapForSlot === indexMap ? createPrimarySlot() : createSlot()); | |
insertSlot(slotNew, slotNext); | |
return slotNew; | |
} | |
function createSlotSequence(slotNext, index, indexMapForSlot) { | |
//#DBG _ASSERT(slotNext.prev.lastInSequence); | |
//#DBG _ASSERT(slotNext.firstInSequence); | |
var slotNew = createAndAddSlot(slotNext, indexMapForSlot); | |
slotNew.firstInSequence = true; | |
slotNew.lastInSequence = true; | |
setSlotIndex(slotNew, index, indexMapForSlot); | |
return slotNew; | |
} | |
function createPrimarySlotSequence(slotNext, index) { | |
return createSlotSequence(slotNext, index, indexMap); | |
} | |
function addSlotBefore(slotNext, indexMapForSlot) { | |
//#DBG _ASSERT(slotNext.firstInSequence); | |
//#DBG _ASSERT(slotNext.prev.lastInSequence); | |
var slotNew = createAndAddSlot(slotNext, indexMapForSlot); | |
delete slotNext.firstInSequence; | |
// See if we've bumped into the previous sequence | |
if (slotNew.prev.index === slotNew.index - 1) { | |
delete slotNew.prev.lastInSequence; | |
} else { | |
slotNew.firstInSequence = true; | |
} | |
setSlotIndex(slotNew, slotNext.index - 1, indexMapForSlot); | |
return slotNew; | |
} | |
function addSlotAfter(slotPrev, indexMapForSlot) { | |
//#DBG _ASSERT(slotPrev !== slotListEnd); | |
//#DBG _ASSERT(slotPrev.lastInSequence); | |
//#DBG _ASSERT(slotPrev.next.firstInSequence); | |
var slotNew = createAndAddSlot(slotPrev.next, indexMapForSlot); | |
delete slotPrev.lastInSequence; | |
// See if we've bumped into the next sequence | |
if (slotNew.next.index === slotNew.index + 1) { | |
delete slotNew.next.firstInSequence; | |
} else { | |
slotNew.lastInSequence = true; | |
} | |
setSlotIndex(slotNew, slotPrev.index + 1, indexMapForSlot); | |
return slotNew; | |
} | |
function reinsertSlot(slot, slotNext, mergeWithPrev, mergeWithNext) { | |
insertAndMergeSlot(slot, slotNext, mergeWithPrev, mergeWithNext); | |
//#DBG _ASSERT(!keyMap[slot.key]); | |
keyMap[slot.key] = slot; | |
var index = slot.index; | |
if (slot.index !== undefined) { | |
indexMap[slot.index] = slot; | |
} | |
} | |
function removeSlotPermanently(slot) { | |
/*#DBG | |
_ASSERT(totalSlots > 0); | |
totalSlots--; | |
#DBG*/ | |
removeSlot(slot); | |
if (slot.key) { | |
delete keyMap[slot.key]; | |
} | |
if (slot.index !== undefined && indexMap[slot.index] === slot) { | |
delete indexMap[slot.index]; | |
} | |
var bindingMap = slot.bindingMap; | |
for (var listBindingID in bindingMap) { | |
var handle = bindingMap[listBindingID].handle; | |
if (handle && handleMap[handle] === slot) { | |
delete handleMap[handle]; | |
} | |
} | |
// Invalidating the slot's handle marks it as deleted | |
if (handleMap[slot.handle] === slot) { | |
delete handleMap[slot.handle]; | |
} | |
} | |
function slotPermanentlyRemoved(slot) { | |
return !handleMap[slot.handle]; | |
} | |
function successorFromIndex(index, indexMapForSlot, listStart, listEnd, skipPreviousIndex) { | |
//#DBG _ASSERT(index !== undefined); | |
// Try the previous index | |
var slotNext = (skipPreviousIndex ? null : indexMapForSlot[index - 1]); | |
if (slotNext && (slotNext.next !== listEnd || listEnd.firstInSequence)) { | |
// We want the successor | |
slotNext = slotNext.next; | |
} else { | |
// Try the next index | |
slotNext = indexMapForSlot[index + 1]; | |
if (!slotNext) { | |
// Resort to a linear search | |
slotNext = listStart.next; | |
var lastSequenceStart; | |
while (true) { | |
//#DBG _ASSERT(slotNext); | |
//#DBG _ASSERT(slotNext.index !== index); | |
if (slotNext.firstInSequence) { | |
lastSequenceStart = slotNext; | |
} | |
if (!(index >= slotNext.index) || slotNext === listEnd) { | |
break; | |
} | |
slotNext = slotNext.next; | |
} | |
if (slotNext === listEnd && !listEnd.firstInSequence) { | |
// Return the last insertion point between sequences, or undefined if none | |
slotNext = (lastSequenceStart && lastSequenceStart.index === undefined ? lastSequenceStart : undefined); | |
} | |
} | |
} | |
return slotNext; | |
} | |
// Slot Items | |
function isPlaceholder(slot) { | |
//#DBG _ASSERT(slot !== slotsStart && slot !== slotsEnd); | |
return !slot.item && !slot.itemNew && slot !== slotListEnd; | |
} | |
function defineHandleProperty(item, handle) { | |
Object.defineProperty(item, "handle", { | |
value: handle, | |
writable: false, | |
enumerable: false, | |
configurable: true | |
}); | |
} | |
function defineCommonItemProperties(item, slot, handle) { | |
defineHandleProperty(item, handle); | |
Object.defineProperty(item, "index", { | |
get: function () { | |
while (slot.slotMergedWith) { | |
slot = slot.slotMergedWith; | |
} | |
return slot.index; | |
}, | |
enumerable: false, | |
configurable: true | |
}); | |
} | |
function validateData(data) { | |
if (data === undefined) { | |
return data; | |
} else { | |
// Convert the data object to JSON to enforce the constraints we want. For example, we don't want | |
// functions, arrays with extra properties, DOM objects, cyclic or acyclic graphs, or undefined values. | |