2929 lines
107 KiB
JavaScript
2929 lines
107 KiB
JavaScript
/// <loc filename="metadata\ui_loc_oam.xml" format="messagebundle" />
|
|
/// <reference path='base.js' />
|
|
|
|
/*
|
|
© Microsoft. All rights reserved.
|
|
|
|
This library is supported for use in Windows Tailored Apps only.
|
|
|
|
Build: 6.2.8059.0
|
|
Version: 0.5
|
|
*/
|
|
|
|
|
|
|
|
(function (WinJS, undefined) {
|
|
|
|
var DOMEventMixin = {
|
|
_domElement: null,
|
|
|
|
addEventListener: function (type, listener, useCapture) {
|
|
/// <summary locid="1">
|
|
/// Adds an event listener to the control.
|
|
/// </summary>
|
|
/// <param name="type" locid="2">
|
|
/// The type (name) of the event.
|
|
/// </param>
|
|
/// <param name="listener" locid="3">
|
|
/// The listener to invoke when the event gets raised.
|
|
/// </param>
|
|
/// <param name="useCapture" locid="4">
|
|
/// Specifies whether or not to initiate capture.
|
|
/// </param>
|
|
this._domElement.addEventListener(type, listener, useCapture || false);
|
|
},
|
|
dispatchEvent: function (type, eventProperties) {
|
|
/// <summary locid="5">
|
|
/// Raises an event of the specified type and with additional properties.
|
|
/// </summary>
|
|
/// <param name="type" locid="2">
|
|
/// The type (name) of the event.
|
|
/// </param>
|
|
/// <param name="eventProperties" locid="6">
|
|
/// The set of additional properties to be attached to the event object when the event is raised.
|
|
/// </param>
|
|
/// <returns locid="7">
|
|
/// Boolean indicating whether preventDefault was called on the event.
|
|
/// </returns>
|
|
var eventValue = document.createEvent("Event");
|
|
eventValue.initEvent(type, false, false);
|
|
eventValue.detail = eventProperties;
|
|
// @TODO, remove this when we remove WinJS.UI.Control, it is a breaking change.
|
|
//
|
|
if (typeof eventProperties === "object") {
|
|
Object.keys(eventProperties).forEach(function (key) {
|
|
eventValue[key] = eventProperties[key];
|
|
});
|
|
}
|
|
this._domElement.dispatchEvent(eventValue);
|
|
},
|
|
removeEventListener: function (type, listener, useCapture) {
|
|
/// <summary locid="8">
|
|
/// Removes an event listener from the control.
|
|
/// </summary>
|
|
/// <param name="type" locid="2">
|
|
/// The type (name) of the event.
|
|
/// </param>
|
|
/// <param name="listener" locid="9">
|
|
/// The listener to remove from the invoke list.
|
|
/// </param>
|
|
/// <param name="useCapture" locid="4">
|
|
/// Specifies whether or not to initiate capture.
|
|
/// </param>
|
|
this._domElement.removeEventListener(type, listener, useCapture || false);
|
|
}
|
|
};
|
|
|
|
function setOptions(control, options) {
|
|
/// <summary locid="10">
|
|
/// Applies the set of declaratively specified options (properties and events) on the specified control.
|
|
/// If the options property name begins with "on", the property value is a function and the control
|
|
/// supports addEventListener setControl will call addEventListener on the control.
|
|
/// </summary>
|
|
/// <param name="control" domElement="false" locid="11">
|
|
/// The control on which the properties and events are to be applied.
|
|
/// </param>
|
|
/// <param name="options" domElement="false" locid="12">
|
|
/// The set of options that were specified declaratively.
|
|
/// </param>
|
|
if (typeof options === "object") {
|
|
var keys = Object.keys(options);
|
|
for (var i = 0, len = keys.length; i < len; i++) {
|
|
var key = keys[i];
|
|
var value = options[key];
|
|
if (key.length > 2) {
|
|
var ch1 = key[0];
|
|
var ch2 = key[1];
|
|
if ((ch1 === 'o' || ch1 === 'O') && (ch2 === 'n' || ch2 === 'N')) {
|
|
if (typeof value === "function") {
|
|
if (control.addEventListener) {
|
|
control.addEventListener(key.substr(2), value);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
control[key] = value;
|
|
}
|
|
}
|
|
};
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI", {
|
|
DOMEventMixin: DOMEventMixin,
|
|
setOptions: setOptions
|
|
});
|
|
|
|
})(WinJS);
|
|
|
|
|
|
|
|
|
|
var InvalidHandler = "Invalid data-win-control attribute";
|
|
|
|
(function (WinJS, undefined) {
|
|
|
|
var processedAllCalled = false;
|
|
|
|
function activate(element, handler) {
|
|
return new WinJS.Promise(function (complete, error) {
|
|
try {
|
|
var options;
|
|
var optionsAttribute = element.getAttribute("data-win-options");
|
|
if (optionsAttribute) {
|
|
options = WinJS.UI._optionsParser(optionsAttribute);
|
|
}
|
|
|
|
var ctl;
|
|
var count = 1;
|
|
|
|
// handler is required to call complete if it takes that parameter
|
|
//
|
|
if (handler.length > 2) {
|
|
count++;
|
|
}
|
|
function checkComplete() {
|
|
count--;
|
|
if (count === 0) {
|
|
WinJS.UI.setControl(element, ctl);
|
|
complete(ctl);
|
|
}
|
|
}
|
|
|
|
// UNDONE: async exceptions from the handler get dropped on the floor...
|
|
//
|
|
ctl = new handler(element, options, checkComplete);
|
|
checkComplete();
|
|
}
|
|
catch (err) {
|
|
error(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
function processAllImpl(rootElement) {
|
|
return new WinJS.Promise(function (complete, error) {
|
|
msWriteProfilerMark("UI:processAll:S");
|
|
|
|
msWriteProfilerMark("UI:processAll:setup:S");
|
|
rootElement = rootElement || document.body;
|
|
|
|
var pending = 0;
|
|
var selector = "[data-win-control]";
|
|
var allElements = rootElement.querySelectorAll(selector);
|
|
var elements = [];
|
|
if (getControlHandler(rootElement)) {
|
|
elements.push(rootElement);
|
|
}
|
|
for (var i = 0, len = allElements.length; i < len; i++) {
|
|
elements.push(allElements[i]);
|
|
}
|
|
|
|
// bail early if there is nothing to process
|
|
//
|
|
if (elements.length === 0) { complete(); return; }
|
|
|
|
|
|
|
|
function checkAllComplete() {
|
|
pending = pending - 1;
|
|
if (pending < 0) {
|
|
complete();
|
|
}
|
|
}
|
|
|
|
msWriteProfilerMark("UI:processAll:setup:E");
|
|
// First go through and determine which elements to activate
|
|
//
|
|
msWriteProfilerMark("UI:processAll:findControls:S");
|
|
var controls = new Array(elements.length);
|
|
for (var i = 0, len = elements.length; i < len; i++) {
|
|
var element = elements[i];
|
|
var control;
|
|
var instance = WinJS.UI.getControl(element);
|
|
if (instance) {
|
|
control = instance.constructor;
|
|
// already activated, don't need to add to controls array
|
|
}
|
|
else {
|
|
controls[i] = control = getControlHandler(element);
|
|
}
|
|
if (control && control.isDeclarativeControlContainer) {
|
|
i += element.querySelectorAll(selector).length;
|
|
}
|
|
}
|
|
msWriteProfilerMark("UI:processAll:findControls:E");
|
|
|
|
// Now go through and activate those
|
|
//
|
|
msWriteProfilerMark("UI:processAll:activateControls:S");
|
|
for (var i = 0, len = elements.length; i < len; i++) {
|
|
var ctl = controls[i];
|
|
if (ctl) {
|
|
pending++;
|
|
activate(elements[i], ctl).then(checkAllComplete, function (err) { error(err); });
|
|
}
|
|
}
|
|
msWriteProfilerMark("UI:processAll:activateControls:E");
|
|
|
|
if (checkAllComplete) {
|
|
checkAllComplete();
|
|
}
|
|
msWriteProfilerMark("UI:processAll:E");
|
|
});
|
|
}
|
|
|
|
function getControlHandler(element) {
|
|
if (element.getAttribute) {
|
|
var evaluator = element.getAttribute("data-win-control");
|
|
if (evaluator) {
|
|
return WinJS.Utilities.getMember(evaluator.trim());
|
|
}
|
|
}
|
|
}
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI", {
|
|
|
|
getControl: function (element) {
|
|
/// <summary locid="13">
|
|
/// Given a DOM element, retrieves the associated Control.
|
|
/// </summary>
|
|
/// <param name="element" domElement="true" locid="14">
|
|
/// Element whose associated Control is requested.
|
|
/// </param>
|
|
/// <returns locid="15">
|
|
/// The control associated with the dom element.
|
|
/// </returns>
|
|
|
|
return element.winControl || element["data-win-control"];
|
|
},
|
|
|
|
processAll: function (rootElement) {
|
|
/// <summary locid="16">
|
|
/// Applies declarative control binding to all elements, starting optionally at rootElement.
|
|
/// </summary>
|
|
/// <param name="rootElement" domElement="true" locid="17">
|
|
/// Element to start searching at, if not specified, the entire document is searched.
|
|
/// </param>
|
|
/// <returns locid="18">
|
|
/// Promise which is fulfilled when all the controls have been ativated
|
|
/// </returns>
|
|
|
|
if (!processedAllCalled) {
|
|
return WinJS.Utilities.ready().then(function () {
|
|
processedAllCalled = true;
|
|
return processAllImpl(rootElement);
|
|
});
|
|
}
|
|
else {
|
|
return processAllImpl(rootElement);
|
|
}
|
|
},
|
|
|
|
process: function (element) {
|
|
/// <summary locid="19">
|
|
/// Applies declarative control binding to the specified element.
|
|
/// </summary>
|
|
/// <param name="element" domElement="true" locid="20">
|
|
/// Element to bind.
|
|
/// </param>
|
|
/// <returns locid="21">
|
|
/// The control which was activated
|
|
/// </returns>
|
|
|
|
var handler = getControlHandler(element);
|
|
if (!handler) {
|
|
return WinJS.Promise.as(); // undefined, no handler
|
|
}
|
|
else {
|
|
return activate(element, handler);
|
|
}
|
|
},
|
|
|
|
setControl: function (element, control) {
|
|
/// <summary locid="22">
|
|
/// Given a DOM element and a control attaches the control to the element
|
|
/// </summary>
|
|
/// <param name="element" domElement="true" locid="23">
|
|
/// Element to have control associated with.
|
|
/// </param>
|
|
/// <param name="control" locid="24">
|
|
/// Control to attach to element.
|
|
/// </param>
|
|
element.winControl = control;
|
|
element["data-win-control"] = control;
|
|
}
|
|
});
|
|
})(WinJS);
|
|
|
|
|
|
|
|
(function (WinJS, undefined) {
|
|
|
|
|
|
var QueryCollection = WinJS.Class.derive(Array, function(items) {
|
|
/// <summary locid="25">
|
|
/// QueryCollection is the result of a query selector and provides
|
|
/// various operations which perform actions over the elements of
|
|
/// the collection.
|
|
/// </summary>
|
|
/// <param name="items" locid="26">
|
|
/// Items to store in the collection.
|
|
/// </param>
|
|
if(items) {
|
|
this.include(items);
|
|
}
|
|
}, {
|
|
get: function(index) {
|
|
/// <summary locid="27">
|
|
/// Retrieve an item from the QueryCollection
|
|
/// </summary>
|
|
/// <param name="index" type="Number" locid="28">
|
|
/// Index of the item to be returned
|
|
/// </param>
|
|
/// <returns locid="29">
|
|
/// A single item from the collection
|
|
/// </returns>
|
|
return this[index];
|
|
},
|
|
setAttribute: function(name, value) {
|
|
/// <summary locid="30">
|
|
/// Set an attribute value on all the items in the collection.
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="31">
|
|
/// Name of the attribute to be set
|
|
/// </param>
|
|
/// <param name="value" type="String" locid="32">
|
|
/// Value of the attribute to be set
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
item.setAttribute(name, value);
|
|
});
|
|
return this;
|
|
},
|
|
getAttribute: function(name) {
|
|
/// <summary locid="34">
|
|
/// Gets an attribute value from the first element in the collection
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="31">
|
|
/// Name of the attribute to be set
|
|
/// </param>
|
|
/// <returns type="String" locid="35">
|
|
/// The value of the specified attribute
|
|
/// </returns>
|
|
if(this.length > 0) {
|
|
return this[0].getAttribute(name);
|
|
}
|
|
},
|
|
addClass: function(name) {
|
|
/// <summary locid="36">
|
|
/// Adds the specified class to all the elements in the collection
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="37">
|
|
/// Name of the class to be added
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
WinJS.Utilities.addClass(item, name);
|
|
});
|
|
return this;
|
|
},
|
|
hasClass: function(name) {
|
|
/// <summary locid="38">
|
|
/// Tests whether the specified class exists on the first element of the collection
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="39">
|
|
/// Name of the desired class
|
|
/// </param>
|
|
/// <returns type="Boolean" locid="40">
|
|
/// Whether or not the element has the specified class
|
|
/// </returns>
|
|
if(this.length > 0) {
|
|
return WinJS.Utilities.hasClass(this[0], name);
|
|
}
|
|
return false;
|
|
},
|
|
removeClass: function(name) {
|
|
/// <summary locid="41">
|
|
/// Removes the specified class to all the elements in the collection
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="42">
|
|
/// Name of the class to be removed
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
WinJS.Utilities.removeClass(item, name);
|
|
});
|
|
return this;
|
|
},
|
|
toggleClass: function(name) {
|
|
/// <summary locid="43">
|
|
/// Toggles the specified class on all the elements in the collection
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="44">
|
|
/// Name of the class to be toggled
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
WinJS.Utilities.toggleClass(item, name);
|
|
});
|
|
return this;
|
|
},
|
|
listen: function(eventType, listener, capture) {
|
|
/// <summary locid="45">
|
|
/// Registers the listener for the specified event on all the elements in the collection
|
|
/// </summary>
|
|
/// <param name="eventType" type="String" locid="46">
|
|
/// Name of the event to be listened to
|
|
/// </param>
|
|
/// <param name="listener" type="Function" locid="47">
|
|
/// Event handler function to be called when event is triggered
|
|
/// </param>
|
|
/// <param name="capture" type="Boolean" locid="48">
|
|
/// Capture value to be passed to addEventListener
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
item.addEventListener(eventType, listener, capture);
|
|
});
|
|
return this;
|
|
},
|
|
removeEventListener: function(eventType, listener, capture) {
|
|
/// <summary locid="49">
|
|
/// Unregisters the listener for the specified event on all the elements in the collection
|
|
/// </summary>
|
|
/// <param name="eventType" type="String" locid="50">
|
|
/// Name of the event being listened to
|
|
/// </param>
|
|
/// <param name="listener" type="Function" locid="47">
|
|
/// Event handler function to be called when event is triggered
|
|
/// </param>
|
|
/// <param name="capture" type="Boolean" locid="51">
|
|
/// Capture value to be passed to removeEventListener
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
item.removeEventListener(eventType, listener, capture);
|
|
});
|
|
return this;
|
|
},
|
|
setStyle: function(name, value) {
|
|
/// <summary locid="52">
|
|
/// Sets the specified style property for all the elements in the collection
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="53">
|
|
/// Name of the property on the style object associated each element
|
|
/// </param>
|
|
/// <param name="value" type="String" locid="54">
|
|
/// Value to be set to the specified property on the style object
|
|
/// associated with each element
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
item.style[name] = value;
|
|
});
|
|
return this;
|
|
},
|
|
clearStyle: function(name) {
|
|
/// <summary locid="55">
|
|
/// Clears the specified style property for all the elements in the collection.
|
|
/// </summary>
|
|
/// <param name="name" type="String" locid="56">
|
|
/// Name of the property on the style object associated each element to be cleared
|
|
/// </param>
|
|
/// <returns locid="33">
|
|
/// The QueryCollection instance to facilitate chaining
|
|
/// </returns>
|
|
this.forEach(function(item) {
|
|
item.style[name] = "";
|
|
});
|
|
return this;
|
|
},
|
|
query: function(query) {
|
|
/// <summary locid="57">
|
|
/// Executes a query selector against all the elements in the collection
|
|
/// and aggregates the result.
|
|
/// </summary>
|
|
/// <param name="query" type="String" locid="58">
|
|
/// Query selector string
|
|
/// </param>
|
|
/// <returns locid="59">
|
|
/// QueryCollection instance containing the aggregate results of
|
|
/// executing the query against all the elements in the collection
|
|
/// </returns>
|
|
var newCollection = new WinJS.Utilities.QueryCollection();
|
|
this.forEach(function(item) {
|
|
newCollection.include(item.querySelectorAll(query));
|
|
});
|
|
return newCollection;
|
|
},
|
|
include: function(items) {
|
|
/// <summary locid="60">
|
|
/// Includes a set of items in this QueryCollection
|
|
/// </summary>
|
|
/// <param name="items" locid="61">
|
|
/// The items to be included in the QueryCollection, may be an
|
|
/// Array-like object, a document fragment or a single item.
|
|
/// </param>
|
|
if (typeof items.length === "number") {
|
|
for (var i = 0; i < items.length; i++) {
|
|
this.push(items[i]);
|
|
}
|
|
} else if (items.DOCUMENT_FRAGMENT_NODE && items.nodeType === items.DOCUMENT_FRAGMENT_NODE) {
|
|
this.include(items.childNodes);
|
|
} else {
|
|
this.push(items);
|
|
}
|
|
}
|
|
});
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "Utilities", {
|
|
QueryCollection: QueryCollection,
|
|
query: function (query, element) {
|
|
/// <summary locid="62">
|
|
/// Execute a query selector against the specified element or the document
|
|
/// </summary>
|
|
/// <param name="query" type="String" locid="63">
|
|
/// Query selector to be executed
|
|
/// </param>
|
|
/// <param name="element" optional="true" type="HTMLElement" locid="64">
|
|
/// Element against which to execute the query. If not specified the
|
|
/// query is executed against the document.
|
|
/// </param>
|
|
/// <returns locid="65">
|
|
/// The QueryCollection instance containing the results of the query
|
|
/// </returns>
|
|
return new WinJS.Utilities.QueryCollection((element || document).querySelectorAll(query));
|
|
},
|
|
id: function (id) {
|
|
/// <summary locid="66">
|
|
/// Look up an element by id and wrap the result in a QueryCollection
|
|
/// </summary>
|
|
/// <param name="id" type="String" locid="67">
|
|
/// Id of the element
|
|
/// </param>
|
|
/// <returns locid="68">
|
|
/// QueryCollection instance containing the element if it was found
|
|
/// </returns>
|
|
var e = document.getElementById(id);
|
|
return new WinJS.Utilities.QueryCollection(e ? [e] : []);
|
|
},
|
|
children: function (element) {
|
|
/// <summary locid="69">
|
|
/// Create a QueryCollection instance out of the specified element's children.
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="70">
|
|
/// Element whose children are wrapped in a QueryCollection
|
|
/// </param>
|
|
/// <returns locid="71">
|
|
/// The QueryCollection instance
|
|
/// </returns>
|
|
return new WinJS.Utilities.QueryCollection(element.children);
|
|
}
|
|
});
|
|
})(WinJS);
|
|
|
|
|
|
|
|
(function (WinJS, undefined) {
|
|
|
|
function getClassName(e) {
|
|
var name = e.className || "";
|
|
if (typeof(name) == "string") {
|
|
return name;
|
|
}
|
|
else {
|
|
return name.baseVal || "";
|
|
}
|
|
};
|
|
function setClassName(e, value) {
|
|
// SVG elements (which use e.className.baseVal) are never undefined,
|
|
// so this logic makes the comparison a bit more compact.
|
|
//
|
|
var name = e.className || "";
|
|
if (typeof(name) == "string") {
|
|
e.className = value;
|
|
}
|
|
else {
|
|
e.className.baseVal = value;
|
|
}
|
|
return e;
|
|
};
|
|
function getDimension(element, property) {
|
|
return WinJS.Utilities.convertToPixels(element, window.getComputedStyle(element, null)[property]);
|
|
}
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "Utilities", {
|
|
_dataKey: "_msDataKey",
|
|
_pixelsRE: /^-?\d+(px)?$/i,
|
|
_numberRE: /^-?\d+/i,
|
|
|
|
Key: {
|
|
backspace: 8,
|
|
tab: 9,
|
|
enter: 13,
|
|
shift: 16,
|
|
ctrl: 17,
|
|
alt: 18,
|
|
pause: 19,
|
|
capsLock: 20,
|
|
escape: 27,
|
|
space: 32,
|
|
pageUp: 33,
|
|
pageDown: 34,
|
|
end: 35,
|
|
home: 36,
|
|
leftArrow: 37,
|
|
upArrow: 38,
|
|
rightArrow: 39,
|
|
downArrow: 40,
|
|
insert: 45,
|
|
deleteKey: 46,
|
|
num0: 48,
|
|
num1: 49,
|
|
num2: 50,
|
|
num3: 51,
|
|
num4: 52,
|
|
num5: 53,
|
|
num6: 54,
|
|
num7: 55,
|
|
num8: 56,
|
|
num9: 57,
|
|
a: 65,
|
|
b: 66,
|
|
c: 67,
|
|
d: 68,
|
|
e: 69,
|
|
f: 70,
|
|
g: 71,
|
|
h: 72,
|
|
i: 73,
|
|
j: 74,
|
|
k: 75,
|
|
l: 76,
|
|
m: 77,
|
|
n: 78,
|
|
o: 79,
|
|
p: 80,
|
|
q: 81,
|
|
r: 82,
|
|
s: 83,
|
|
t: 84,
|
|
u: 85,
|
|
v: 86,
|
|
w: 87,
|
|
x: 88,
|
|
y: 89,
|
|
z: 90,
|
|
leftWindows: 91,
|
|
rightWindows: 92,
|
|
numPad0: 96,
|
|
numPad1: 97,
|
|
numPad2: 98,
|
|
numPad3: 99,
|
|
numPad4: 100,
|
|
numPad5: 101,
|
|
numPad6: 102,
|
|
numPad7: 103,
|
|
numPad8: 104,
|
|
numPad9: 105,
|
|
multiply: 106,
|
|
add: 107,
|
|
subtract: 109,
|
|
decimalPoint: 110,
|
|
divide: 111,
|
|
F1: 112,
|
|
F2: 113,
|
|
F3: 114,
|
|
F4: 115,
|
|
F5: 116,
|
|
F6: 117,
|
|
F7: 118,
|
|
F8: 119,
|
|
F9: 120,
|
|
F10: 121,
|
|
F11: 122,
|
|
F12: 123,
|
|
numLock: 144,
|
|
scrollLock: 145,
|
|
semicolon: 186,
|
|
equal: 187,
|
|
comma: 188,
|
|
dash: 189,
|
|
period: 190,
|
|
forwardSlash: 191,
|
|
graveAccent: 192,
|
|
openBracket: 219,
|
|
backSlash: 220,
|
|
closeBracket: 221,
|
|
singleQuote: 222
|
|
},
|
|
|
|
data: function (element) {
|
|
/// <summary locid="72">
|
|
/// Get the data value associated with the specified element
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="73">
|
|
/// Element to which the data is associated.
|
|
/// </param>
|
|
/// <returns locid="74">
|
|
/// Value assoicated with the element
|
|
/// </returns>
|
|
if (!element[WinJS.Utilities._dataKey]) {
|
|
element[WinJS.Utilities._dataKey] = {};
|
|
}
|
|
return element[WinJS.Utilities._dataKey];
|
|
},
|
|
|
|
hasClass: function (e, name) {
|
|
/// <summary locid="75">
|
|
/// Test whether the given element has the specified class
|
|
/// </summary>
|
|
/// <param name="e" type="HTMLElement" locid="76">
|
|
/// Element to test for the presence of the named class
|
|
/// </param>
|
|
/// <param name="name" type="String" locid="77">
|
|
/// Name of the class to test for
|
|
/// </param>
|
|
/// <returns type="Boolean" locid="78">
|
|
/// Whether or not the specified element is annotated with the specified class.
|
|
/// </returns>
|
|
var className = getClassName(e);
|
|
var names = className.trim().split(" ");
|
|
var l = names.length;
|
|
for (var i = 0; i < l; i++) {
|
|
if (names[i] == name) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
addClass: function (e, name) {
|
|
/// <summary locid="79">
|
|
/// Add the specified class to the element
|
|
/// </summary>
|
|
/// <param name="e" type="HTMLElement" locid="80">
|
|
/// Element to which to add the class
|
|
/// </param>
|
|
/// <param name="name" type="String" locid="81">
|
|
/// Name of the class to add
|
|
/// </param>
|
|
/// <returns type="HTMLElement" locid="82">
|
|
/// The input element
|
|
/// </returns>
|
|
var className = getClassName(e);
|
|
var names = className.trim().split(" ");
|
|
var l = names.length;
|
|
var found = false;
|
|
for (var i = 0; i < l; i++) {
|
|
if (names[i] == name) {
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
if (l > 0 && names[0].length > 0) {
|
|
setClassName(e, className + " " + name);
|
|
}
|
|
else {
|
|
setClassName(e, className + name);
|
|
}
|
|
}
|
|
return e;
|
|
},
|
|
|
|
removeClass: function (e, name) {
|
|
/// <summary locid="83">
|
|
/// Remove the specified class from the given element
|
|
/// </summary>
|
|
/// <param name="e" type="HTMLElement" locid="84">
|
|
/// Element from which to remove the class
|
|
/// </param>
|
|
/// <param name="name" type="String" locid="85">
|
|
/// Name of the class to remove
|
|
/// </param>
|
|
/// <returns type="HTMLElement" locid="82">
|
|
/// The input element
|
|
/// </returns>
|
|
var names = getClassName(e).trim().split(" ");
|
|
setClassName(e, names.reduce(function (r, e) {
|
|
if (e == name) {
|
|
return r;
|
|
}
|
|
else if (r && r.length > 0) {
|
|
return r + " " + e;
|
|
}
|
|
else {
|
|
return e;
|
|
}
|
|
}, ""));
|
|
return e;
|
|
},
|
|
|
|
toggleClass: function (e, name) {
|
|
/// <summary locid="86">
|
|
/// Toggle the specified class on the given element
|
|
/// </summary>
|
|
/// <param name="e" type="HTMLElement" locid="87">
|
|
/// Element on which to toggle the class
|
|
/// </param>
|
|
/// <param name="name" type="String" locid="88">
|
|
/// Name of the class to toggle
|
|
/// </param>
|
|
/// <returns type="HTMLElement" locid="82">
|
|
/// The input element
|
|
/// </returns>
|
|
var className = getClassName(e);
|
|
var names = className.trim().split(" ");
|
|
var l = names.length;
|
|
var found = false;
|
|
for (var i = 0; i < l; i++) {
|
|
if (names[i] == name) {
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
if (l > 0 && names[0].length > 0) {
|
|
setClassName(e, className + " " + name);
|
|
}
|
|
else {
|
|
setClassName(e, className + name);
|
|
}
|
|
}
|
|
else {
|
|
setClassName(e, names.reduce(function (r, e) {
|
|
if (e == name) {
|
|
return r;
|
|
}
|
|
else if (r && r.length > 0) {
|
|
return r + " " + e;
|
|
}
|
|
else {
|
|
return e;
|
|
}
|
|
}, ""));
|
|
}
|
|
return e;
|
|
},
|
|
|
|
getRelativeLeft: function (element, parent) {
|
|
/// <summary locid="89">
|
|
/// Gets the left coordinate of the element relative to the specified parent.
|
|
/// </summary>
|
|
/// <param name="element" domElement="true" locid="90">
|
|
/// Element whose relative coordinate is needed.
|
|
/// </param>
|
|
/// <param name="parent" domElement="true" locid="91">
|
|
/// Element to which the coordinate will be relative to.
|
|
/// </param>
|
|
/// <returns locid="92">
|
|
/// Relative left co-ordinate.
|
|
/// </returns>
|
|
if (element === null)
|
|
return 0;
|
|
|
|
var left = element.offsetLeft;
|
|
var e = element.parentNode;
|
|
while (e !== null) {
|
|
left -= e.offsetLeft;
|
|
|
|
if (e === parent)
|
|
break;
|
|
e = e.parentNode;
|
|
}
|
|
|
|
return left;
|
|
},
|
|
|
|
getRelativeTop: function (element, parent) {
|
|
/// <summary locid="93">
|
|
/// Gets the top coordinate of the element relative to the specified parent.
|
|
/// </summary>
|
|
/// <param name="element" domElement="true" locid="90">
|
|
/// Element whose relative coordinate is needed.
|
|
/// </param>
|
|
/// <param name="parent" domElement="true" locid="91">
|
|
/// Element to which the coordinate will be relative to.
|
|
/// </param>
|
|
/// <returns locid="94">
|
|
/// Relative top co-ordinate.
|
|
/// </returns>
|
|
if (element === null)
|
|
return 0;
|
|
|
|
var top = element.offsetTop;
|
|
var e = element.parentNode;
|
|
while (e !== null) {
|
|
top -= e.offsetTop;
|
|
|
|
if (e === parent)
|
|
break;
|
|
e = e.parentNode;
|
|
}
|
|
|
|
return top;
|
|
},
|
|
|
|
empty: function (element) {
|
|
/// <summary locid="95">
|
|
/// Removes all the child nodes from the specified element.
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" domElement="true" locid="96">
|
|
/// The element whose child nodes will be removed.
|
|
/// </param>
|
|
/// <returns type="HTMLElement" locid="82">
|
|
/// The input element
|
|
/// </returns>
|
|
for (var i = element.childNodes.length - 1; i >= 0; i--) {
|
|
element.removeChild(element.childNodes.item(i));
|
|
}
|
|
return element;
|
|
},
|
|
|
|
_isDOMElement: function (element) {
|
|
return element &&
|
|
typeof element === "object" &&
|
|
typeof element.tagName === "string";
|
|
},
|
|
|
|
getContentWidth: function (element) {
|
|
/// <summary locid="97">
|
|
/// Get the width of the content of the element which does not include border and padding
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="98">
|
|
/// Element to compute the width of
|
|
/// </param>
|
|
/// <returns type="Number" locid="99">
|
|
/// Width of the element's content
|
|
/// </returns>
|
|
var border = getDimension(element, "borderLeftWidth") + getDimension(element, "borderRightWidth"),
|
|
padding = getDimension(element, "paddingLeft") + getDimension(element, "paddingRight");
|
|
return element.offsetWidth - border - padding;
|
|
},
|
|
|
|
getTotalWidth: function (element) {
|
|
/// <summary locid="100">
|
|
/// Get the width of the element including margins
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="98">
|
|
/// Element to compute the width of
|
|
/// </param>
|
|
/// <returns type="Number" locid="101">
|
|
/// Width of element including margins
|
|
/// </returns>
|
|
var margin = getDimension(element, "marginLeft") + getDimension(element, "marginRight");
|
|
return element.offsetWidth + margin;
|
|
},
|
|
|
|
getContentHeight: function (element) {
|
|
/// <summary locid="102">
|
|
/// Get the height of the content of the element which does not include border and padding
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="103">
|
|
/// Element to compute the height of
|
|
/// </param>
|
|
/// <returns type="Integer" locid="104">
|
|
/// Height of the element's content
|
|
/// </returns>
|
|
var border = getDimension(element, "borderTopWidth") + getDimension(element, "borderBottomWidth"),
|
|
padding = getDimension(element, "paddingTop") + getDimension(element, "paddingBottom");
|
|
return element.offsetHeight - border - padding;
|
|
},
|
|
|
|
getTotalHeight: function (element) {
|
|
/// <summary locid="105">
|
|
/// Get the height of the element including its margins
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="103">
|
|
/// Element to compute the height of
|
|
/// </param>
|
|
/// <returns type="Number" locid="106">
|
|
/// Height of element including margins
|
|
/// </returns>
|
|
var margin = getDimension(element, "marginTop") + getDimension(element, "marginBottom");
|
|
return element.offsetHeight + margin;
|
|
},
|
|
|
|
getPosition: function (element) {
|
|
/// <summary locid="107">
|
|
/// Get the position of the specified element
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="108">
|
|
/// Element for which the position is to be calculated
|
|
/// </param>
|
|
/// <returns type="Object" locid="109">
|
|
/// Object containing left, top, width and height properties for the element.
|
|
/// </returns>
|
|
var fromElement = element,
|
|
offsetParent = element.offsetParent,
|
|
top = element.offsetTop,
|
|
left = element.offsetLeft;
|
|
|
|
while ((element = element.parentNode) !== null &&
|
|
element !== document.body &&
|
|
element !== document.documentElement) {
|
|
top -= element.scrollTop;
|
|
left -= element.scrollLeft;
|
|
|
|
if (element === offsetParent) {
|
|
top += element.offsetTop;
|
|
left += element.offsetLeft;
|
|
|
|
offsetParent = element.offsetParent;
|
|
}
|
|
}
|
|
|
|
return {
|
|
left: left,
|
|
top: top,
|
|
width: fromElement.offsetWidth,
|
|
height: fromElement.offsetHeight
|
|
};
|
|
},
|
|
|
|
convertToPixels: function (element, value) {
|
|
/// <summary locid="110">
|
|
/// Convert a css positioning string to pixels
|
|
/// </summary>
|
|
/// <param name="element" type="HTMLElement" locid="111">
|
|
/// Element to use for conversion
|
|
/// </param>
|
|
/// <param name="value" type="String" locid="112">
|
|
/// Css positioning string to be converted
|
|
/// </param>
|
|
/// <returns type="Number" locid="113">
|
|
/// Input as pixels
|
|
/// </returns>
|
|
if (!this._pixelsRE.test(value) && this._numberRE.test(value)) {
|
|
var previousValue = element.style.left;
|
|
|
|
element.style.left = value;
|
|
value = element.style.pixelLeft;
|
|
|
|
element.style.left = previousValue;
|
|
|
|
return value;
|
|
} else {
|
|
return parseInt(value, 10) || 0;
|
|
}
|
|
},
|
|
|
|
generateID: function (idBase) {
|
|
/// <summary locid="114">
|
|
/// Generates a unique id for an element
|
|
/// </summary>
|
|
/// <param name="idBase" type="String" locid="115">
|
|
/// Prefix value
|
|
/// </param>
|
|
/// <returns type="String" locid="116">
|
|
/// Unique id string
|
|
/// </returns>
|
|
var id = idBase + (new Date()).getTime() + "-";
|
|
var rand = Math.random() + "";
|
|
id += rand.substring(2, rand.length);
|
|
return id;
|
|
}
|
|
|
|
});
|
|
})(WinJS);
|
|
|
|
|
|
|
|
(function (WinJS, globalObj, undefined) {
|
|
var loaderStateProp = "-ms-fragmentLoader-state";
|
|
|
|
// UNDONE: should we hoist this to a shared location?
|
|
//
|
|
var forEach = function (arrayLikeValue, action) {
|
|
for (var i = 0, l = arrayLikeValue.length; i < l; i++) {
|
|
action(arrayLikeValue[i], i);
|
|
}
|
|
};
|
|
var head = document.head || document.getElementsByTagName("head")[0];
|
|
var nextFragmentId = 1;
|
|
var scripts = {};
|
|
var styles = {};
|
|
var links = {};
|
|
var states = {};
|
|
var initialized = false;
|
|
|
|
function idFromHref(href) {
|
|
if (typeof (href) == "string") {
|
|
return href.toLowerCase();
|
|
}
|
|
else {
|
|
var id = WinJS.Utilities.data(href).fragmentId;
|
|
if (!id) {
|
|
id = nextFragmentId++;
|
|
WinJS.Utilities.data(href).fragmentId = id;
|
|
}
|
|
return id;
|
|
}
|
|
};
|
|
|
|
function addScript(scriptTag, fragmentHref, position) {
|
|
// We synthesize a name for inline scripts because today we put the
|
|
// inline scripts in the same processing pipeline as src scripts. If
|
|
// we seperated inline scripts into their own logic, we could simplify
|
|
// this somewhat.
|
|
//
|
|
var src = scriptTag.src;
|
|
if (!src) {
|
|
src = fragmentHref + "script[" + position + "]";
|
|
}
|
|
src = src.toLowerCase();
|
|
|
|
if (!(src in scripts)) {
|
|
scripts[src] = true;
|
|
var n = document.createElement("script");
|
|
if (scriptTag.language) {
|
|
n.setAttribute("language", "javascript");
|
|
}
|
|
if (scriptTag.type == "ms-deferred/javascript") {
|
|
n.setAttribute("type", "text/javascript");
|
|
}
|
|
else {
|
|
n.setAttribute("type", scriptTag.type);
|
|
}
|
|
if (scriptTag.id) {
|
|
n.setAttribute("id", scriptTag.id);
|
|
}
|
|
if (scriptTag.src) {
|
|
n.setAttribute("src", scriptTag.src);
|
|
}
|
|
else {
|
|
n.text = scriptTag.text;
|
|
}
|
|
head.appendChild(n);
|
|
}
|
|
};
|
|
|
|
function addStyle(styleTag, fragmentHref, position) {
|
|
var src = (fragmentHref + "script[" + position + "]").toLowerCase();
|
|
if (!(src in styles)) {
|
|
styles[src] = true;
|
|
head.appendChild(styleTag.cloneNode(true));
|
|
}
|
|
};
|
|
|
|
function addLink(styleTag) {
|
|
var src = styleTag.href.toLowerCase();
|
|
if (!(src in links)) {
|
|
links[src] = true;
|
|
var n = styleTag.cloneNode(false);
|
|
n.href = styleTag.href;
|
|
head.appendChild(n);
|
|
}
|
|
};
|
|
|
|
function controlStaticState(href) {
|
|
/// <summary locid="117">
|
|
/// PRIVATE METHOD: retrieves the static (not per-instance) state for a fragment at the
|
|
/// URL "href". Will complete either synchronously (for an already loaded
|
|
/// fragment) or asynchronously when the fragment is loaded and ready to be used.
|
|
/// </summary>
|
|
|
|
// UNDONE: cancellation
|
|
//
|
|
return new WinJS.Promise(function (c,e,p) {
|
|
var fragmentId = idFromHref(href);
|
|
|
|
var state = states[fragmentId];
|
|
|
|
var intervalId;
|
|
var tryCount = 4;
|
|
var callback = function () {
|
|
if (state.docfrag) {
|
|
if (state.loadScript) {
|
|
var load = WinJS.Utilities.getMember(state.loadScript);
|
|
if (load) {
|
|
msWriteProfilerMark("Fragment:cSS:makeDocFragNoHref:E");
|
|
c({load:load,state:states[fragmentId]});
|
|
if (intervalId) { clearInterval(intervalId); }
|
|
return true;
|
|
}
|
|
else if (!(tryCount--)) {
|
|
if (WinJS.validation) {
|
|
e("Unable to find function '" + state.loadScript + "'");
|
|
}
|
|
else {
|
|
c({state:states[fragmentId]});
|
|
}
|
|
if (intervalId) { clearInterval(intervalId); }
|
|
}
|
|
}
|
|
else {
|
|
msWriteProfilerMark("Fragment:cSS:makeDocFragNoHref:E");
|
|
c({state:states[fragmentId]});
|
|
if (intervalId) { clearInterval(intervalId); }
|
|
return true;
|
|
}
|
|
}
|
|
msWriteProfilerMark("Fragment:cSS:makeDocFragNoHref:E");
|
|
return false;
|
|
};
|
|
|
|
|
|
// If the state record was found, then we either are ready to
|
|
// roll immediately (everything is loaded & parsed) or are in
|
|
// process of loading. If possible, we want to directly invoke
|
|
// to avoid any flickering, however if we are still loading
|
|
// the content, we must wait.
|
|
//
|
|
if (state) {
|
|
if (!callback()) {
|
|
intervalId = setInterval(callback, 20);
|
|
}
|
|
|
|
return;
|
|
}
|
|
else {
|
|
states[fragmentId] = state = {};
|
|
}
|
|
|
|
if (typeof (href) === "string") {
|
|
msWriteProfilerMark("Fragment:cSS:makeDocFrag:S");
|
|
|
|
var temp = document.createElement('iframe');
|
|
document[loaderStateProp] = "loading";
|
|
temp.src = href;
|
|
temp.style.display = 'none';
|
|
|
|
var domContentLoaded = null;
|
|
|
|
var complete = function (load) {
|
|
// This is to work around a weird bug where removing the
|
|
// IFrame from the DOM triggers DOMContentLoaded a second time.
|
|
temp.contentDocument.removeEventListener("DOMContentLoaded", domContentLoaded, false);
|
|
temp.parentNode.removeChild(temp);
|
|
temp = null;
|
|
delete document[loaderStateProp];
|
|
msWriteProfilerMark("Fragment:cSS:makeDocFrag:E");
|
|
|
|
c({load:load, state:state});
|
|
};
|
|
|
|
domContentLoaded = function () {
|
|
controlStaticStateLoaded(href, temp, state).then(complete);
|
|
};
|
|
|
|
|
|
document.body.appendChild(temp);
|
|
temp.contentDocument.addEventListener("DOMContentLoaded", domContentLoaded, false);
|
|
}
|
|
else {
|
|
msWriteProfilerMark("Fragment:cSS:makeDocFragNoHref:S");
|
|
state.loadScript = href.getAttribute('data-win-fragmentLoad') || state.loadScript;
|
|
var fragment = document.createDocumentFragment();
|
|
while (href.childNodes.length > 0) {
|
|
fragment.appendChild(href.childNodes[0]);
|
|
};
|
|
state.docfrag = fragment;
|
|
if (!callback()) {
|
|
intervalId = setInterval(callback, 20);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
function controlStaticStateLoaded(href, temp, state) {
|
|
/// <summary locid="118">
|
|
/// PRIVATE METHOD: Once the control's static state has been loaded in the temporary iframe,
|
|
/// this method spelunks the iframe's document to retrieve all relevant information. Also,
|
|
/// this performs any needed fixups on the DOM (like adjusting relative URLs).
|
|
/// </summary>
|
|
|
|
// UNDONE: cancelation
|
|
//
|
|
return new WinJS.Promise(function (c,e,p) {
|
|
var cd = temp.contentDocument;
|
|
|
|
var links = cd.querySelectorAll('link[rel="stylesheet"], link[type="text/css"]');
|
|
state.styles = links;
|
|
forEach(links, addLink);
|
|
|
|
// NOTE: no need to cache the style objects, as they are unique per fragment
|
|
//
|
|
forEach(cd.querySelectorAll('style'), function (e,i) { addStyle(e, href, i); });
|
|
|
|
var localScripts = cd.getElementsByTagName('script');
|
|
state.scripts = localScripts;
|
|
|
|
forEach(localScripts, function (e,i) {
|
|
addScript(e, href, i);
|
|
});
|
|
|
|
var load;
|
|
var loadTags = cd.querySelectorAll('[data-win-fragmentLoad]');
|
|
if (loadTags && loadTags.length > 0) {
|
|
for (var i=0, l=loadTags.length; i<l; i++) {
|
|
if (loadTags[i].nodeName !== "BODY") {
|
|
load = loadTags[i].getAttribute('data-win-fragmentLoad');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
state.loadScript = load || state.loadScript
|
|
|
|
// UNDONE: figure out all the elements we should do URI fixups for
|
|
//
|
|
forEach(cd.body.getElementsByTagName('img'), function (e) {
|
|
e.src = e.href;
|
|
});
|
|
forEach(cd.body.getElementsByTagName('a'), function (e) {
|
|
// UNDONE: for # only anchor tags, we don't update the href... good design?
|
|
//
|
|
if (e.href !== "") {
|
|
var href = e.getAttribute("href");
|
|
if (href && href[0] != "#") {
|
|
e.href = e.href;
|
|
}
|
|
}
|
|
});
|
|
|
|
// strip inline scripts from the body, they got copied to the
|
|
// host document with the rest of the scripts above...
|
|
//
|
|
var localScripts = cd.body.getElementsByTagName("script");
|
|
while (localScripts.length > 0) {
|
|
localScripts[0].parentNode.removeChild(localScripts[0]);
|
|
}
|
|
|
|
var fragment = document.createDocumentFragment();
|
|
var imported = document.importNode(temp.contentDocument.body, true);
|
|
while(imported.childNodes.length > 0) {
|
|
fragment.appendChild(imported.childNodes[0]);
|
|
}
|
|
state.docfrag = fragment;
|
|
|
|
// huge ugly kludge
|
|
if (state.loadScript) {
|
|
var intervalId = setInterval(function () {
|
|
var load = WinJS.Utilities.getMember(state.loadScript);
|
|
if (load) {
|
|
c(load);
|
|
clearInterval(intervalId);
|
|
}
|
|
}, 20);
|
|
}
|
|
else {
|
|
c();
|
|
}
|
|
});
|
|
};
|
|
|
|
function initialize() {
|
|
/// <summary locid="119">
|
|
/// PRIVATE METHOD: Initializes the fragment loader with the list of scripts and
|
|
/// styles already present in the host document
|
|
/// </summary>
|
|
msWriteProfilerMark("Fragment:initialize:S");
|
|
if (initialized) { return; }
|
|
|
|
initialized = true;
|
|
|
|
msWriteProfilerMark("Fragment:initialize:getScripts:S");
|
|
var localScripts = head.querySelectorAll("script");
|
|
for (var i = 0, l = localScripts.length; i < l; i++) {
|
|
scripts[localScripts[i].src.toLowerCase()] = true;
|
|
}
|
|
msWriteProfilerMark("Fragment:initialize:getScripts:E");
|
|
|
|
|
|
msWriteProfilerMark("Fragment:initialize:getStylesheets:S");
|
|
var csss = head.querySelectorAll('link[rel="stylesheet"], link[type="text/css"]');
|
|
for (var i = 0, l = csss.length; i < l; i++) {
|
|
links[csss[i].href.toLowerCase()] = true;
|
|
}
|
|
msWriteProfilerMark("Fragment:initialize:getStylesheets:E");
|
|
|
|
msWriteProfilerMark("Fragment:initialize:E");
|
|
};
|
|
|
|
function renderFragment(href, options) {
|
|
/// <summary locid="120">
|
|
/// Returns the content of the fragment specified by "href"
|
|
/// The "options" record is optionally passed to the load handler for the fragment.
|
|
/// </summary>
|
|
/// <param name="href" type="String" locid="121">
|
|
/// URI for fragment
|
|
/// </param>
|
|
/// <param name="options" locid="122">
|
|
/// Fragment load options
|
|
/// </param>
|
|
/// <returns locid="123">
|
|
/// Promise which is completed when the fragment has been loaded.
|
|
/// If a target element was not specified the cloned fragment is the
|
|
/// completed value.
|
|
/// </returns>
|
|
return renderFragmentTo(href, options);
|
|
};
|
|
|
|
function renderFragmentTo(href, options, target) {
|
|
/// <summary locid="124">
|
|
/// Clones the contents of href into target.
|
|
/// The "options" record is optionally passed to the load handler for the fragment.
|
|
/// </summary>
|
|
/// <param name="href" type="String" locid="121">
|
|
/// URI for fragment
|
|
/// </param>
|
|
/// <param name="options" locid="122">
|
|
/// Fragment load options
|
|
/// </param>
|
|
/// <param name="target" type="HTMLElement" optional="true" locid="125">
|
|
/// Element which the fragment will be appended to
|
|
/// </param>
|
|
/// <returns locid="123">
|
|
/// Promise which is completed when the fragment has been loaded.
|
|
/// If a target element was not specified the cloned fragment is the
|
|
/// completed value.
|
|
/// </returns>
|
|
|
|
// UNDONE: support cancellation, route errors
|
|
//
|
|
msWriteProfilerMark("Fragment:clone:S");
|
|
initialize();
|
|
|
|
return controlStaticState(href).then(function (v) {
|
|
var load = v.load;
|
|
var state = v.state;
|
|
|
|
msWriteProfilerMark("Fragment:clone:cloneChildren:S");
|
|
var clonedFrag = state.docfrag.cloneNode(true);
|
|
msWriteProfilerMark("Fragment:clone:cloneChildren:E");
|
|
|
|
if (load) {
|
|
load(clonedFrag, options);
|
|
}
|
|
|
|
if (target) {
|
|
target.appendChild(clonedFrag);
|
|
msWriteProfilerMark("Fragment:clone:E");
|
|
}
|
|
else {
|
|
msWriteProfilerMark("Fragment:clone:E");
|
|
return clonedFrag;
|
|
}
|
|
});
|
|
};
|
|
|
|
function prepareFragment(href) {
|
|
/// <summary locid="126">
|
|
/// Starts loading the fragment at the specified location, returned promise will complete
|
|
/// when the fragment is ready to be cloned.
|
|
/// </summary>
|
|
/// <param name="href" type="String" locid="121">
|
|
/// URI for fragment
|
|
/// </param>
|
|
/// <returns locid="127">
|
|
/// Promise which is completed when the fragment has been prepared
|
|
/// </returns>
|
|
initialize();
|
|
return controlStaticState(href).then(function() { return; });
|
|
};
|
|
|
|
function unprepareFragment(href) {
|
|
/// <summary locid="128">
|
|
/// Removes any cached information about the fragment, this will not unload scripts
|
|
/// or styles referenced by the fragment.
|
|
/// </summary>
|
|
/// <param name="href" type="String" locid="121">
|
|
/// URI for fragment
|
|
/// </param>
|
|
delete states[idFromHref(href)];
|
|
};
|
|
|
|
function selfhost(load) {
|
|
/// <summary locid="129">
|
|
/// This is used in the fragment definition markup to allow a fragment to
|
|
/// be loaded as a stand alone page.
|
|
/// </summary>
|
|
/// <param name="load" type="Function" locid="130">
|
|
/// Function to be called when the fragment has loaded
|
|
/// </param>
|
|
if (globalObj.parent) {
|
|
if (globalObj.parent.document[loaderStateProp] != "loading") {
|
|
forEach(globalObj.document.querySelectorAll('head > script[type="ms-deferred/javascript"]'),
|
|
function (e) {
|
|
addScript(e);
|
|
});
|
|
|
|
globalObj.addEventListener("DOMContentLoaded", function (event) {
|
|
load(globalObj.document.body);
|
|
}, false);
|
|
}
|
|
}
|
|
};
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI.Fragments", {
|
|
clone: renderFragment,
|
|
cloneTo: renderFragmentTo,
|
|
load: prepareFragment,
|
|
unload: unprepareFragment,
|
|
fragmentAsDocumentReady: selfhost
|
|
});
|
|
})(WinJS, this);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Lexical grammar is defined in ECMA-262-5, section 7.
|
|
|
|
Lexical productions used in this grammar defined in ECMA-262-5:
|
|
|
|
Production Section
|
|
--------------------------------
|
|
Identifier 7.6
|
|
NullLiteral 7.8.1
|
|
BooleanLiteral 7.8.2
|
|
NumberLiteral 7.8.3
|
|
StringLiteral 7.8.4
|
|
|
|
*/
|
|
|
|
(function (global, undefined) {
|
|
|
|
var tokenType = {
|
|
leftBrace: 1, // {
|
|
rightBrace: 2, // }
|
|
leftBracket: 3, // [
|
|
rightBracket: 4, // ]
|
|
separator: 5, // ECMA-262-5, 7.2
|
|
colon: 6, // :
|
|
semicolon: 7, // ;
|
|
comma: 8, // ,
|
|
dot: 9, // .
|
|
nullLiteral: 10, // ECMA-262-5, 7.8.1 (null)
|
|
trueLiteral: 11, // ECMA-262-5, 7.8.2 (true)
|
|
falseLiteral: 12, // ECMA-262-5, 7.8.2 (false)
|
|
numberLiteral: 13, // ECMA-262-5, 7.8.3
|
|
stringLiteral: 14, // ECMA-262-5, 7.8.4
|
|
identifier: 15, // ECMA-262-5, 7.6
|
|
reservedWord: 16,
|
|
|
|
eof: 17,
|
|
error: 18
|
|
};
|
|
// debugging - this costs something like 20%
|
|
//
|
|
//Object.keys(tokenType).forEach(function (key) {
|
|
// tokenType[key] = key.toString();
|
|
//});
|
|
var tokens = {
|
|
leftBrace: { type: tokenType.leftBrace, length: 1 },
|
|
rightBrace: { type: tokenType.rightBrace, length: 1 },
|
|
leftBracket: { type: tokenType.leftBracket, length: 1 },
|
|
rightBracket: { type: tokenType.rightBracket, length: 1 },
|
|
colon: { type: tokenType.colon, length: 1 },
|
|
semicolon: { type: tokenType.semicolon, length: 1},
|
|
comma: { type: tokenType.comma, length: 1 },
|
|
dot: { type: tokenType.dot, length: 1 },
|
|
nullLiteral: { type: tokenType.nullLiteral, length: 4, value: null },
|
|
trueLiteral: { type: tokenType.trueLiteral, length: 4, value: true },
|
|
falseLiteral: { type: tokenType.falseLiteral, length: 5, value: false },
|
|
eof: { type: tokenType.eof, length: 0 }
|
|
};
|
|
|
|
function reservedWord(word) {
|
|
return { type: tokenType.reservedWord, length: word.length };
|
|
}
|
|
function reservedWordLookup(identifier) {
|
|
// Moving from a simple object literal lookup for reserved words to this
|
|
// switch was worth a non-trivial performance increase (5-7%) as this path
|
|
// gets taken for any identifier.
|
|
//
|
|
switch (identifier.charCodeAt(0)) {
|
|
case /*b*/98:
|
|
switch (identifier) {
|
|
case 'break':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*c*/99:
|
|
switch (identifier) {
|
|
case 'case':
|
|
case 'catch':
|
|
case 'class':
|
|
case 'const':
|
|
case 'continue':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*d*/100:
|
|
switch (identifier) {
|
|
case 'debugger':
|
|
case 'default':
|
|
case 'delete':
|
|
case 'do':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*e*/101:
|
|
switch (identifier) {
|
|
case 'else':
|
|
case 'enum':
|
|
case 'export':
|
|
case 'extends':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*f*/102:
|
|
switch (identifier) {
|
|
case 'false':
|
|
return tokens.falseLiteral;
|
|
|
|
case 'finally':
|
|
case 'for':
|
|
case 'function':
|
|
return reservedWord(identifier);
|
|
}
|
|
|
|
break;
|
|
case /*i*/105:
|
|
switch (identifier) {
|
|
case 'if':
|
|
case 'import':
|
|
case 'in':
|
|
case 'instanceof':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*n*/110:
|
|
switch (identifier) {
|
|
case 'null':
|
|
return tokens.nullLiteral;
|
|
|
|
case 'new':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*r*/114:
|
|
switch (identifier) {
|
|
case 'return':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*s*/115:
|
|
switch (identifier) {
|
|
case 'super':
|
|
case 'switch':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*t*/116:
|
|
switch (identifier) {
|
|
case 'true':
|
|
return tokens.trueLiteral;
|
|
|
|
case 'this':
|
|
case 'throw':
|
|
case 'try':
|
|
case 'typeof':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*v*/118:
|
|
switch (identifier) {
|
|
case 'var':
|
|
case 'void':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
|
|
case /*w*/119:
|
|
switch (identifier) {
|
|
case 'while':
|
|
case 'with':
|
|
return reservedWord(identifier);
|
|
}
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
var lexer = (function () {
|
|
function isIdentifierStartCharacter(code, text, offset, limit) {
|
|
// The ES5 spec decalares that identifiers consist of a bunch of unicode classes, without
|
|
// WinRT support for determining unicode class membership we are looking at 2500+ lines of
|
|
// javascript code to encode the relevant class tables. Instead we look for everything
|
|
// which is legal and < 0x7f, we exclude whitespace and line terminators, and then accept
|
|
// everything > 0x7f.
|
|
//
|
|
// Here's the ES5 production:
|
|
//
|
|
// Lu | Ll | Lt | Lm | Lo | Nl
|
|
// $
|
|
// _
|
|
// \ UnicodeEscapeSequence
|
|
//
|
|
switch (code) {
|
|
case (code >= /*a*/97 && code <= /*z*/122) && code:
|
|
case (code >= /*A*/65 && code <= /*Z*/90) && code:
|
|
case /*$*/36:
|
|
case /*_*/95:
|
|
return true;
|
|
|
|
case isWhitespace(code) && code:
|
|
case isLineTerminator(code) && code:
|
|
return false;
|
|
|
|
case (code > 0x7f) && code:
|
|
return true;
|
|
|
|
case /*\*/92:
|
|
if (offset + 4 < limit) {
|
|
if (text.charCodeAt(offset) === /*u*/117 &&
|
|
isHexDigit(text.charCodeAt(offset + 1)) &&
|
|
isHexDigit(text.charCodeAt(offset + 2)) &&
|
|
isHexDigit(text.charCodeAt(offset + 3)) &&
|
|
isHexDigit(text.charCodeAt(offset + 4))) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
/*
|
|
// Hand-inlined into readIdentifierPart
|
|
function isIdentifierPartCharacter(code) {
|
|
// See comment in isIdentifierStartCharacter.
|
|
//
|
|
// Mn | Mc | Nd | Pc
|
|
// <ZWNJ> | <ZWJ>
|
|
//
|
|
switch (code) {
|
|
case isIdentifierStartCharacter(code) && code:
|
|
case isDecimalDigit(code) && code:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
*/
|
|
function readIdentifierPart(text, offset, limit) {
|
|
var hasEscape = false;
|
|
while (offset < limit) {
|
|
var code = text.charCodeAt(offset);
|
|
switch (code) {
|
|
//case isIdentifierStartCharacter(code) && code:
|
|
case (code >= /*a*/97 && code <= /*z*/122) && code:
|
|
case (code >= /*A*/65 && code <= /*Z*/90) && code:
|
|
case /*$*/36:
|
|
case /*_*/95:
|
|
break;
|
|
|
|
case isWhitespace(code) && code:
|
|
case isLineTerminator(code) && code:
|
|
return hasEscape ? -offset : offset;
|
|
|
|
case (code > 0x7f) && code:
|
|
break;
|
|
|
|
//case isDecimalDigit(code) && code:
|
|
case (code >= /*0*/48 && code <= /*9*/57) && code:
|
|
break;
|
|
|
|
case /*\*/92:
|
|
if (offset + 5 < limit) {
|
|
if (text.charCodeAt(offset + 1) === /*u*/117 &&
|
|
isHexDigit(text.charCodeAt(offset + 2)) &&
|
|
isHexDigit(text.charCodeAt(offset + 3)) &&
|
|
isHexDigit(text.charCodeAt(offset + 4)) &&
|
|
isHexDigit(text.charCodeAt(offset + 5))) {
|
|
offset += 5;
|
|
hasEscape = true;
|
|
break;
|
|
}
|
|
}
|
|
return hasEscape ? -offset : offset;
|
|
|
|
default:
|
|
return hasEscape ? -offset : offset;
|
|
}
|
|
offset++;
|
|
}
|
|
return hasEscape ? -offset : offset;
|
|
}
|
|
function readIdentifierToken(text, offset, limit) {
|
|
var startOffset = offset;
|
|
offset = readIdentifierPart(text, offset, limit);
|
|
var hasEscape = false;
|
|
if (offset < 0) {
|
|
offset = -offset;
|
|
hasEscape = true;
|
|
}
|
|
var identifier = text.substr(startOffset, offset - startOffset);
|
|
if (hasEscape) {
|
|
identifier = eval('"' + identifier + '"');
|
|
}
|
|
var wordToken = reservedWordLookup(identifier);
|
|
if (wordToken) {
|
|
return wordToken;
|
|
}
|
|
return {
|
|
type: tokenType.identifier,
|
|
length: offset - startOffset,
|
|
value: identifier
|
|
};
|
|
}
|
|
function isHexDigit(code) {
|
|
switch (code) {
|
|
case (code >= /*0*/48 && code <= /*9*/57) && code:
|
|
case (code >= /*a*/97 && code <= /*f*/102) && code:
|
|
case (code >= /*A*/65 && code <= /*F*/70) && code:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
function readHexIntegerLiteral(text, offset, limit) {
|
|
while (offset < limit && isHexDigit(text.charCodeAt(offset))) {
|
|
offset++;
|
|
}
|
|
return offset;
|
|
}
|
|
function isDecimalDigit(code) {
|
|
switch (code) {
|
|
case (code >= /*0*/48 && code <= /*9*/57) && code:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
function readDecimalDigits(text, offset, limit) {
|
|
while (offset < limit && isDecimalDigit(text.charCodeAt(offset))) {
|
|
offset++;
|
|
}
|
|
return offset;
|
|
}
|
|
function readDecimalLiteral(text, offset, limit) {
|
|
offset = readDecimalDigits(text, offset, limit);
|
|
if (offset < limit && text.charCodeAt(offset) === /*.*/46 && offset + 1 < limit && isDecimalDigit(text.charCodeAt(offset + 1))) {
|
|
offset = readDecimalDigits(text, offset + 2, limit);
|
|
}
|
|
if (offset < limit) {
|
|
var code = text.charCodeAt(offset);
|
|
if (code === /*e*/101 || code === /*E*/69) {
|
|
var tempOffset = offset + 1;
|
|
if (tempOffset < limit) {
|
|
code = text.charCodeAt(tempOffset);
|
|
if (code === /*+*/43 || code === /*-*/45) {
|
|
tempOffset++;
|
|
}
|
|
offset = readDecimalDigits(text, tempOffset, limit);
|
|
}
|
|
}
|
|
}
|
|
return offset;
|
|
}
|
|
function readDecimalLiteralToken(text, start, offset, limit) {
|
|
var offset = readDecimalLiteral(text, offset, limit);
|
|
var length = offset - start;
|
|
return {
|
|
type: tokenType.numberLiteral,
|
|
length: length,
|
|
value: +text.substr(start, length)
|
|
};
|
|
}
|
|
function isLineTerminator(code) {
|
|
switch (code) {
|
|
case 0x000A: // line feed
|
|
case 0x000D: // carriage return
|
|
case 0x2028: // line separator
|
|
case 0x2029: // paragraph separator
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
function readStringLiteralToken(text, offset, limit) {
|
|
var startOffset = offset;
|
|
var quoteCharCode = text.charCodeAt(offset);
|
|
var hasEscape = false;
|
|
offset++;
|
|
while (offset < limit && !isLineTerminator(text.charCodeAt(offset))) {
|
|
if (offset + 1 < limit && text.charCodeAt(offset) === /*\*/92) {
|
|
hasEscape = true;
|
|
|
|
switch (text.charCodeAt(offset + 1)) {
|
|
case quoteCharCode:
|
|
case 0x000A: // line feed
|
|
case 0x2028: // line separator
|
|
case 0x2029: // paragraph separator
|
|
offset += 2;
|
|
continue;
|
|
|
|
case 0x000D: // carriage return
|
|
if (offset + 2 < limit && text.charCodeAt(offset + 2) === 0x000A) {
|
|
// Skip \r\n
|
|
offset += 3;
|
|
} else {
|
|
offset += 2;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
offset++;
|
|
if (text.charCodeAt(offset - 1) === quoteCharCode) {
|
|
break;
|
|
}
|
|
}
|
|
var length = offset - startOffset;
|
|
// If we don't have a terminating quote go through the escape path.
|
|
hasEscape = hasEscape || length === 1 || text.charCodeAt(offset - 1) !== quoteCharCode;
|
|
return {
|
|
type: tokenType.stringLiteral,
|
|
length: length,
|
|
value: (hasEscape
|
|
? eval(text.substr(startOffset, length))
|
|
: text.substr(startOffset + 1, length - 2))
|
|
};
|
|
}
|
|
function isWhitespace(code) {
|
|
switch (code) {
|
|
case 0x0009: // tab
|
|
case 0x000B: // vertical tab
|
|
case 0x000C: // form feed
|
|
case 0x0020: // space
|
|
case 0x00A0: // no-breaking space
|
|
case 0xFEFF: // BOM
|
|
return true;
|
|
|
|
// There are no category Zs between 0x00A0 and 0x1680.
|
|
//
|
|
case (code < 0x1680) && code:
|
|
return false;
|
|
|
|
// Unicode category Zs
|
|
//
|
|
case 0x1680:
|
|
case 0x180e:
|
|
case (code >= 0x2000 && code <= 0x200a) && code:
|
|
case 0x202f:
|
|
case 0x205f:
|
|
case 0x3000:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
// Hand-inlined isWhitespace.
|
|
function readWhitespace(text, offset, limit) {
|
|
while (offset < limit) {
|
|
var code = text.charCodeAt(offset);
|
|
switch (code) {
|
|
case 0x0009: // tab
|
|
case 0x000B: // vertical tab
|
|
case 0x000C: // form feed
|
|
case 0x0020: // space
|
|
case 0x00A0: // no-breaking space
|
|
case 0xFEFF: // BOM
|
|
break;
|
|
|
|
// There are no category Zs between 0x00A0 and 0x1680.
|
|
//
|
|
case (code < 0x1680) && code:
|
|
return offset;
|
|
|
|
// Unicode category Zs
|
|
//
|
|
case 0x1680:
|
|
case 0x180e:
|
|
case (code >= 0x2000 && code <= 0x200a) && code:
|
|
case 0x202f:
|
|
case 0x205f:
|
|
case 0x3000:
|
|
break;
|
|
|
|
default:
|
|
return offset;
|
|
}
|
|
offset++;
|
|
}
|
|
return offset;
|
|
}
|
|
function lex(result, text, offset, limit) {
|
|
while (offset < limit) {
|
|
var startOffset = offset;
|
|
var code = text.charCodeAt(offset++);
|
|
var type = undefined;
|
|
var token = undefined;
|
|
switch (code) {
|
|
case isWhitespace(code) && code:
|
|
case isLineTerminator(code) && code:
|
|
type = tokenType.separator;
|
|
offset = readWhitespace(text, offset, limit);
|
|
// don't include whitespace in the token stream.
|
|
continue;
|
|
|
|
case /*"*/34:
|
|
case /*'*/39:
|
|
token = readStringLiteralToken(text, offset - 1, limit);
|
|
break;
|
|
|
|
case /*+*/43:
|
|
case /*-*/45:
|
|
if (offset < limit) {
|
|
var afterSign = text.charCodeAt(offset);
|
|
if (afterSign === /*.*/46) {
|
|
var signOffset = offset + 1;
|
|
if (signOffset < limit && isDecimalDigit(text.charCodeAt(signOffset))) {
|
|
token = readDecimalLiteralToken(text, startOffset, signOffset, limit);
|
|
break;
|
|
}
|
|
} else if (isDecimalDigit(afterSign)) {
|
|
token = readDecimalLiteralToken(text, startOffset, offset, limit);
|
|
break;
|
|
}
|
|
}
|
|
type = tokenType.error;
|
|
break;
|
|
|
|
case /*,*/44:
|
|
token = tokens.comma;
|
|
break;
|
|
|
|
case /*.*/46:
|
|
token = tokens.dot;
|
|
if (offset < limit && isDecimalDigit(text.charCodeAt(offset))) {
|
|
token = readDecimalLiteralToken(text, startOffset, offset, limit);
|
|
}
|
|
break;
|
|
|
|
case /*0*/48:
|
|
var ch2 = (offset < limit ? text.charCodeAt(offset) : 0);
|
|
if (ch2 === /*x*/120 || ch2 === /*X*/88) {
|
|
var hexOffset = readHexIntegerLiteral(text, offset + 1, limit);
|
|
token = {
|
|
type: tokenType.numberLiteral,
|
|
length: hexOffset - startOffset,
|
|
value: +text.substr(startOffset, hexOffset - startOffset)
|
|
};
|
|
} else {
|
|
token = readDecimalLiteralToken(text, startOffset, offset, limit);
|
|
}
|
|
break;
|
|
|
|
case (code >= /*1*/49 && code <= /*9*/57) && code:
|
|
token = readDecimalLiteralToken(text, startOffset, offset, limit);
|
|
break;
|
|
|
|
case /*:*/58:
|
|
token = tokens.colon;
|
|
break;
|
|
|
|
case /*;*/59:
|
|
token = tokens.semicolon;
|
|
break;
|
|
|
|
case /*[*/91:
|
|
token = tokens.leftBracket;
|
|
break;
|
|
|
|
case /*]*/93:
|
|
token = tokens.rightBracket;
|
|
break;
|
|
|
|
case /*{*/123:
|
|
token = tokens.leftBrace;
|
|
break;
|
|
|
|
case /*}*/125:
|
|
token = tokens.rightBrace;
|
|
break;
|
|
|
|
default:
|
|
if (isIdentifierStartCharacter(code, text, offset, limit)) {
|
|
token = readIdentifierToken(text, offset - 1, limit);
|
|
break;
|
|
}
|
|
type = tokenType.error;
|
|
break;
|
|
}
|
|
|
|
if (token) {
|
|
offset += (token.length - 1);
|
|
} else {
|
|
token = { type: type, length: offset - startOffset };
|
|
}
|
|
result.push(token);
|
|
}
|
|
}
|
|
return function (text) {
|
|
var result = [];
|
|
lex(result, text, 0, text.length);
|
|
result.push(tokens.eof);
|
|
return result;
|
|
};
|
|
})();
|
|
lexer.tokenType = tokenType;
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI", {
|
|
_optionsLexer: lexer
|
|
});
|
|
})(this);
|
|
|
|
|
|
/*
|
|
Notation is described in ECMA-262-5 (ECMAScript Language Specification, 5th edition) section 5.
|
|
|
|
Lexical grammar is defined in ECMA-262-5, section 7.
|
|
|
|
Lexical productions used in this grammar defined in ECMA-262-5:
|
|
|
|
Production Section
|
|
--------------------------------
|
|
Identifier 7.6
|
|
NullLiteral 7.8.1
|
|
BooleanLiteral 7.8.2
|
|
NumberLiteral 7.8.3
|
|
StringLiteral 7.8.4
|
|
|
|
Syntactic grammar for the value of the data-win-options attribute.
|
|
|
|
OptionsLiteral:
|
|
ObjectLiteral
|
|
|
|
ObjectLiteral:
|
|
{ }
|
|
{ ObjectProperties }
|
|
|
|
ObjectProperties:
|
|
ObjectProperty
|
|
ObjectProperties, ObjectProperty
|
|
|
|
ObjectProperty:
|
|
PropertyName : Value
|
|
|
|
PropertyName: (from ECMA-262-6, 11.1.5)
|
|
StringLiteral
|
|
NumberLiteral
|
|
Identifier
|
|
|
|
ArrayLiteral:
|
|
[ ]
|
|
[ ArrayElements ]
|
|
|
|
ArrayElements:
|
|
Value
|
|
ArrayElements , Value
|
|
|
|
Value:
|
|
NullLiteral
|
|
NumberLiteral
|
|
BooleanLiteral
|
|
StringLiteral
|
|
ArrayLiteral
|
|
ObjectLiteral
|
|
IdentifierExpression
|
|
|
|
AccessExpression:
|
|
[ Value ]
|
|
. Identifier
|
|
|
|
AccessExpressions:
|
|
AccessExpression
|
|
AccessExpressions AccessExpression
|
|
|
|
IdentifierExpression:
|
|
Identifier
|
|
Identifier AccessExpressions
|
|
|
|
|
|
NOTE: We have factored the above grammar to allow the infrastructure to be used
|
|
by the BindingInterpreter as well. The BaseInterpreter does NOT provide an
|
|
implementation of _evaluateValue(), this is expected to be provided by the
|
|
derived class since right now the two have different grammars for Value
|
|
|
|
AccessExpression:
|
|
[ Value ]
|
|
. Identifier
|
|
|
|
AccessExpressions:
|
|
AccessExpression
|
|
AccessExpressions AccessExpression
|
|
|
|
Identifier:
|
|
Identifier (from ECMA-262-6, 7.6)
|
|
|
|
IdentifierExpression:
|
|
Identifier
|
|
Identifier AccessExpressions
|
|
|
|
Value:
|
|
*** Provided by concrete interpreter ***
|
|
|
|
*/
|
|
|
|
(function (global, undefined) {
|
|
|
|
var lexer = WinJS.UI._optionsLexer;
|
|
var tokenType = lexer.tokenType;
|
|
|
|
function tokenTypeName(type) {
|
|
var keys = Object.keys(tokenType);
|
|
for (var i = 0, len = keys.length; i < len; i++) {
|
|
if (type === tokenType[keys[i]]) {
|
|
return keys[i];
|
|
}
|
|
}
|
|
return "<unknown>";
|
|
}
|
|
|
|
var BaseInterpreter = WinJS.Class.define(null,
|
|
{
|
|
_error: function (message) {
|
|
var error = new Error(message);
|
|
error.name = "WinJS.UI.ParseError";
|
|
throw error;
|
|
},
|
|
_evaluateAccessExpression: function (value) {
|
|
switch (this._current.type) {
|
|
case tokenType.dot:
|
|
this._read();
|
|
return this._evaluateIdentifier(true, value);
|
|
|
|
case tokenType.leftBracket:
|
|
this._read();
|
|
var index = this._evaluateValue();
|
|
this._read(tokenType.rightBracket);
|
|
return value[index];
|
|
|
|
// default: is unreachable because all the callers are conditional on
|
|
// the next token being either a . or {
|
|
//
|
|
}
|
|
},
|
|
_evaluateAccessExpressions: function (value) {
|
|
while (true) {
|
|
switch (this._current.type) {
|
|
case tokenType.dot:
|
|
case tokenType.leftBracket:
|
|
value = this._evaluateAccessExpression(value);
|
|
break;
|
|
|
|
default:
|
|
return value;
|
|
}
|
|
}
|
|
},
|
|
_evaluateIdentifier: function (nested, value) {
|
|
var id = this._readIdentifier();
|
|
value = nested ? value[id] : (this._context[id] || global[id]);
|
|
return value;
|
|
},
|
|
_evaluateIdentifierExpression: function () {
|
|
var value = this._evaluateIdentifier(false);
|
|
|
|
switch (this._current.type) {
|
|
case tokenType.dot:
|
|
case tokenType.leftBracket:
|
|
return this._evaluateAccessExpressions(value);
|
|
|
|
default:
|
|
return value;
|
|
}
|
|
},
|
|
_initialize: function (tokens, context) {
|
|
this._tokens = tokens;
|
|
this._context = context;
|
|
this._pos = 0;
|
|
this._current = this._tokens[0];
|
|
},
|
|
_read: function (expected) {
|
|
if (expected && this._current.type !== expected) {
|
|
this._unexpectedToken(expected);
|
|
}
|
|
if (this._current !== tokenType.eof) {
|
|
this._current = this._tokens[++this._pos];
|
|
}
|
|
},
|
|
_readAccessExpression: function (parts) {
|
|
switch (this._current.type) {
|
|
case tokenType.dot:
|
|
this._read();
|
|
parts.push(this._readIdentifier());
|
|
return;
|
|
|
|
case tokenType.leftBracket:
|
|
this._read();
|
|
parts.push(this._evaluateValue());
|
|
this._read(tokenType.rightBracket);
|
|
return;
|
|
|
|
// default: is unreachable because all the callers are conditional on
|
|
// the next token being either a . or {
|
|
//
|
|
}
|
|
},
|
|
_readAccessExpressions: function (parts) {
|
|
while (true) {
|
|
switch (this._current.type) {
|
|
case tokenType.dot:
|
|
case tokenType.leftBracket:
|
|
this._readAccessExpression(parts);
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
_readIdentifier: function () {
|
|
var id = this._current.value;
|
|
this._read(tokenType.identifier);
|
|
return id;
|
|
},
|
|
_readIdentifierExpression: function () {
|
|
var parts = [];
|
|
parts.push(this._readIdentifier());
|
|
|
|
switch (this._current.type) {
|
|
case tokenType.dot:
|
|
case tokenType.leftBracket:
|
|
this._readAccessExpressions(parts);
|
|
break;
|
|
}
|
|
|
|
return parts;
|
|
},
|
|
_unexpectedToken: function (expected) {
|
|
if (expected) {
|
|
if (arguments.length == 1) {
|
|
this._error("Unexpected token: "
|
|
+ tokenTypeName(this._current.type)
|
|
+ ", expected token: "
|
|
+ tokenTypeName(expected)
|
|
);
|
|
} else {
|
|
var names = [];
|
|
for (var i = 0, len = arguments.length; i < len; i++) {
|
|
names.push(tokenTypeName(arguments[i]));
|
|
}
|
|
this._error("Unexpected token: "
|
|
+ tokenTypeName(this._current.type)
|
|
+ ", expected one of: "
|
|
+ names.join(", ")
|
|
);
|
|
}
|
|
} else {
|
|
this._error("Unexpected token: " + tokenTypeName(this._current.type));
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
var OptionsInterpreter = WinJS.Class.derive(BaseInterpreter,
|
|
function (tokens, context) {
|
|
this._initialize(tokens, context);
|
|
},
|
|
{
|
|
_error: function (message) {
|
|
var error = new Error("Invalid options record, expected to be in the format of an object literal. " + message);
|
|
error.name = "WinJS.UI.ParseError";
|
|
throw error;
|
|
},
|
|
_evaluateArrayLiteral: function () {
|
|
var a = [];
|
|
this._read(tokenType.leftBracket);
|
|
this._readArrayElements(a);
|
|
this._read(tokenType.rightBracket);
|
|
return a;
|
|
},
|
|
_evaluateObjectLiteral: function () {
|
|
var o = {};
|
|
this._read(tokenType.leftBrace);
|
|
this._readObjectProperties(o);
|
|
this._read(tokenType.rightBrace);
|
|
return o;
|
|
},
|
|
_evaluateOptionsLiteral: function () {
|
|
var value = this._evaluateValue();
|
|
if (this._current.type !== tokenType.eof) {
|
|
this._unexpectedToken(tokenType.eof);
|
|
}
|
|
return value;
|
|
},
|
|
_evaluateValue: function () {
|
|
switch (this._current.type) {
|
|
case tokenType.falseLiteral:
|
|
case tokenType.nullLiteral:
|
|
case tokenType.stringLiteral:
|
|
case tokenType.trueLiteral:
|
|
case tokenType.numberLiteral:
|
|
var value = this._current.value;
|
|
this._read();
|
|
return value;
|
|
|
|
case tokenType.leftBrace:
|
|
return this._evaluateObjectLiteral();
|
|
|
|
case tokenType.leftBracket:
|
|
return this._evaluateArrayLiteral();
|
|
|
|
case tokenType.identifier:
|
|
return this._evaluateIdentifierExpression();
|
|
|
|
default:
|
|
this._unexpectedToken(tokenType.falseLiteral, tokenType.nullLiteral, tokenType.stringLiteral,
|
|
tokenType.trueLiteral, tokenType.numberLiteral, tokenType.leftBrace, tokenType.leftBracket,
|
|
tokenType.identifier);
|
|
break;
|
|
}
|
|
},
|
|
_readArrayElements: function (a) {
|
|
var first = true;
|
|
var index = 0;
|
|
while (this._current.type !== tokenType.eof && this._current.type !== tokenType.rightBracket) {
|
|
if (!first) { this._read(tokenType.comma); }
|
|
a[index++] = this._evaluateValue();
|
|
first = false;
|
|
}
|
|
},
|
|
_readObjectProperties: function (o) {
|
|
var first = true;
|
|
while (this._current.type !== tokenType.eof && this._current.type !== tokenType.rightBrace) {
|
|
if (!first) { this._read(tokenType.comma); }
|
|
this._readObjectProperty(o);
|
|
first = false;
|
|
}
|
|
},
|
|
_readObjectProperty: function (o) {
|
|
switch (this._current.type) {
|
|
case tokenType.numberLiteral:
|
|
case tokenType.stringLiteral:
|
|
case tokenType.identifier:
|
|
var propertyName = this._current.value;
|
|
this._read();
|
|
this._read(tokenType.colon);
|
|
o[propertyName] = this._evaluateValue();
|
|
break;
|
|
|
|
default:
|
|
this._unexpectedToken(tokenType.numberLiteral, tokenType.stringLiteral, tokenType.identifier);
|
|
break;
|
|
}
|
|
},
|
|
|
|
run: function () {
|
|
return this._evaluateOptionsLiteral();
|
|
}
|
|
}
|
|
);
|
|
|
|
var parser = function (text, context) {
|
|
var tokens = lexer(text);
|
|
var interpreter = new OptionsInterpreter(tokens, context || {});
|
|
return interpreter.run();
|
|
};
|
|
parser._BaseInterpreter = BaseInterpreter;
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI", {
|
|
_optionsParser: parser
|
|
});
|
|
|
|
})(this);
|
|
|
|
|
|
|
|
|
|
(function (WinJS, undefined) {
|
|
function isSelectable(elem) {
|
|
var name = elem.tagName;
|
|
if (name === 'TEXTAREA' || name === 'INPUT') {
|
|
return true;
|
|
}
|
|
|
|
while (elem) {
|
|
if (elem.hasAttribute('data-win-selectable')
|
|
|| elem.contentEditable === 'true') {
|
|
return true;
|
|
}
|
|
elem = elem.parentElement;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function selectionHandler(e) {
|
|
if (!WinJS.UI._isSelectable(e.srcElement)) {
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
document.body.addEventListener('selectstart', selectionHandler, false);
|
|
}, false);
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI", {
|
|
_isSelectable: {value:isSelectable, writable:true, enumerable:true}
|
|
});
|
|
|
|
})(WinJS);
|
|
|
|
|
|
|
|
|
|
(function (WinJS, undefined) {
|
|
|
|
function TabHelperObject(element) {
|
|
function fireEvent(name) {
|
|
var event = document.createEvent('UIEvent');
|
|
event.initUIEvent(name, false, false, window, 1);
|
|
element.dispatchEvent(event);
|
|
};
|
|
|
|
function createCatcher(focusRule) {
|
|
var fragment = document.createElement("DIV");
|
|
fragment.tabIndex = 0;
|
|
fragment.attachEvent("onbeforeactivate", function (e) {
|
|
var hasFocus = focusRule(e);
|
|
fireEvent(hasFocus ? "onTabExit" : "onTabEnter");
|
|
e.cancelBubble = true;
|
|
return false;
|
|
});
|
|
return fragment;
|
|
};
|
|
|
|
var parent = element.parentNode;
|
|
|
|
// Insert prefix focus catcher
|
|
var catcherBegin = createCatcher(function (e) {
|
|
return e.shiftKey;
|
|
});
|
|
parent.insertBefore(catcherBegin, element);
|
|
|
|
// Insert postfix focus catcher
|
|
var catcherEnd = createCatcher(function (e) {
|
|
return !e.shiftKey;
|
|
});
|
|
parent.insertBefore(catcherEnd, element.nextSibling);
|
|
|
|
var refCount = 1;
|
|
this.addRef = function () {
|
|
refCount++;
|
|
};
|
|
this.release = function () {
|
|
if (--refCount === 0) {
|
|
if (catcherBegin.parentElement) {
|
|
parent.removeChild(catcherBegin);
|
|
}
|
|
if (catcherEnd.parentElement) {
|
|
parent.removeChild(catcherEnd);
|
|
}
|
|
}
|
|
return refCount;
|
|
};
|
|
}
|
|
|
|
WinJS.Namespace.define("WinJS.UI.TrackTabBehavior", {
|
|
attach: function (element) {
|
|
if (!element["win-trackTabHelperObject"]) {
|
|
element["win-trackTabHelperObject"] = new TabHelperObject(element);
|
|
} else {
|
|
element["win-trackTabHelperObject"].addRef();
|
|
}
|
|
},
|
|
|
|
detach: function (element) {
|
|
if (!element["win-trackTabHelperObject"].release()) {
|
|
delete element["win-trackTabHelperObject"];
|
|
}
|
|
}
|
|
});
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI", {
|
|
TabContainer: WinJS.Class.define(function (element, options) {
|
|
// TabContainer uses 2 TrackTabBehavior for its implementation: one for itself, another one for the active element.
|
|
// When onTabEnter is caught on TabContainer, it directly set focus on the active element.
|
|
// When onTabExit is caught on the active element (_tabExitHandler), it first prevents focus from being set on any element,
|
|
// effectively letting the focus skip any remaining items in the TabContainer. Then, when onTabExit is caught on
|
|
// TabContainer, it turns back on the possibility to receive focus on child elements.
|
|
this._element = element;
|
|
|
|
var that = this;
|
|
this._tabExitHandler = function () {
|
|
that._canFocus(false);
|
|
};
|
|
|
|
element.addEventListener("onTabEnter", function () {
|
|
if (that.childFocus) {
|
|
that.childFocus.focus();
|
|
} else {
|
|
that._canFocus(false);
|
|
}
|
|
});
|
|
|
|
element.addEventListener("onTabExit", function () {
|
|
that._canFocus(true);
|
|
});
|
|
|
|
WinJS.UI.TrackTabBehavior.attach(element);
|
|
}, {
|
|
|
|
// Public members
|
|
|
|
childFocus: {
|
|
/// <summary locid="131">
|
|
/// Specifies the active element under this container
|
|
/// </summary>
|
|
set: function (e) {
|
|
if (e != this._focusElement) {
|
|
if (this._focusElement) {
|
|
WinJS.UI.TrackTabBehavior.detach(this._focusElement);
|
|
this._focusElement.removeEventListener("onTabExit", this._tabExitHandler);
|
|
}
|
|
this._focusElement = e;
|
|
if (e) {
|
|
WinJS.UI.TrackTabBehavior.attach(e);
|
|
this._focusElement.addEventListener("onTabExit", this._tabExitHandler);
|
|
}
|
|
}
|
|
},
|
|
get: function () {
|
|
return this._focusElement;
|
|
}
|
|
},
|
|
|
|
// Private members
|
|
|
|
_element: null,
|
|
_skipper: function (e) {
|
|
e.cancelBubble = true;
|
|
return false;
|
|
},
|
|
_canFocus: function (canfocus) {
|
|
if (canfocus) {
|
|
this._element.detachEvent("onbeforeactivate", this._skipper);
|
|
} else {
|
|
this._element.attachEvent("onbeforeactivate", this._skipper);
|
|
}
|
|
},
|
|
|
|
_focusElement: null
|
|
|
|
})
|
|
});
|
|
})(WinJS);
|
|
|
|
|
|
(function (WinJS, undefined) {
|
|
var transitionRef = "WinJS.Animations.transition";
|
|
var styleRef = "WinJS.Animations.style";
|
|
function makeArray(elements) {
|
|
if (elements instanceof Array || elements instanceof NodeList || elements instanceof HTMLCollection) {
|
|
return elements;
|
|
} else if (elements) {
|
|
return [elements];
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
function addrefPVLAnimation(element, attrib) {
|
|
var ref;
|
|
if (element.getAttribute) {
|
|
ref = element.getAttribute(attrib);
|
|
if (!ref) {
|
|
ref = 1;
|
|
} else {
|
|
ref = parseInt(ref) + 1;
|
|
}
|
|
element.setAttribute(attrib, ref);
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
function releasePVLAnimation(element, attrib) {
|
|
var ref;
|
|
if (element.getAttribute) {
|
|
ref = element.getAttribute(attrib);
|
|
if (!ref) {
|
|
ref = 0;
|
|
} else {
|
|
ref = parseInt(ref) - 1;
|
|
}
|
|
if (ref === 0) {
|
|
element.removeAttribute(attrib);
|
|
} else {
|
|
element.setAttribute(attrib, ref);
|
|
}
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
var keyframeCounter = 0;
|
|
function getUniqueKeyframeName() {
|
|
return "WinJSUIAnimation" + ++keyframeCounter;
|
|
}
|
|
|
|
function getAnimationStaggerOffset(element, animArray, iElem) {
|
|
for (var i = 0; i < animArray.length; i++) {
|
|
if (iElem === 0) {
|
|
animArray[i].initialDelay = animArray[i].delay;
|
|
}
|
|
animArray[i].keyframe = getUniqueKeyframeName();
|
|
if (typeof animArray[i].stagger === "function") {
|
|
animArray[i].delay = animArray[i].stagger(iElem, animArray[i].initialDelay);
|
|
}
|
|
if (typeof animArray[i].fromCallback === "function") {
|
|
animArray[i].from = animArray[i].fromCallback(iElem);
|
|
}
|
|
if (typeof animArray[i].toCallback === "function") {
|
|
animArray[i].to = animArray[i].toCallback(iElem);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getTransitionStaggerTransform(transArray, iElem) {
|
|
for (var i = 0; i < transArray.length; i++) {
|
|
if (iElem === 0) {
|
|
transArray[i].initialDelay = transArray[i].delay;
|
|
}
|
|
if (typeof transArray[i].stagger === "function") {
|
|
transArray[i].delay = transArray[i].stagger(iElem, transArray[i].initialDelay);
|
|
}
|
|
if (typeof transArray[i].transitionCallback === "function") {
|
|
transArray[i].transition = transArray[i].transitionCallback(iElem);
|
|
}
|
|
}
|
|
}
|
|
|
|
function execElementTransition(elem, transitionArray) {
|
|
elem.style.msTransitionProperty = transitionArray.map(function (t) { return t.name; }).join(",");
|
|
elem.style.msTransitionDelay = transitionArray.map(function (t) { return t.delay + "ms"; }).join(",");
|
|
elem.style.msTransitionDuration = transitionArray.map(function (t) { return t.duration + "ms"; }).join(",");
|
|
elem.style.msTransitionTimingFunction = transitionArray.map(function (t) { return t.timing; }).join(",");
|
|
|
|
var promise = new WinJS.Promise(function (c, e, p) {
|
|
var onexecuteTransitionEnd = function (event) {
|
|
if (event.srcElement === elem) {
|
|
if (clearTransitionProperty(elem)) {
|
|
elem.removeEventListener(event.type, onexecuteTransitionEnd, false);
|
|
c(event); // complete after cleaning up the old transition
|
|
} else {
|
|
p(event);
|
|
}
|
|
}
|
|
};
|
|
|
|
var waitForTransitionEnd = false;
|
|
for (i = 0; i < transitionArray.length; i++) {
|
|
if (transitionArray[i].transition(elem)) {
|
|
waitForTransitionEnd = true;
|
|
addrefPVLAnimation(elem, transitionRef);
|
|
}
|
|
}
|
|
if (waitForTransitionEnd) {
|
|
elem.addEventListener("MSTransitionEnd", onexecuteTransitionEnd, false);
|
|
} else {
|
|
clearTransitionProperty(elem);
|
|
c();
|
|
}
|
|
});
|
|
return promise;
|
|
}
|
|
|
|
function clearAnimation(element) {
|
|
element.style.msAnimationName = null;
|
|
element.style.msAnimationDelay = null;
|
|
element.style.msAnimationDuration = null;
|
|
element.style.msAnimationTimingFunction = null;
|
|
element.style.msAnimationFillMode = "none";
|
|
}
|
|
|
|
function clearTransitionProperty(elem) {
|
|
if (releasePVLAnimation(elem, transitionRef) === 0) {
|
|
elem.style.msTransitionProperty = null;
|
|
elem.style.msTransitionDelay = null;
|
|
elem.style.msTransitionDuration = null;
|
|
elem.style.msTransitionTimingFunction = null;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function executeElementAnimation(elem, animArray, styleelm) {
|
|
var sheet = styleelm.sheet;
|
|
for (var i = 0; i < animArray.length; i++) {
|
|
var kf = "@-ms-keyframes " + animArray[i].keyframe + " { from {" + animArray[i].from + ";} to {" + animArray[i].to + ";}}";
|
|
sheet.insertRule(kf, sheet.cssRules.length);
|
|
addrefPVLAnimation(styleelm, styleRef);
|
|
}
|
|
elem.style.msAnimationDelay = animArray.map(function (a) { return a.delay + "ms"; }).join(",");
|
|
elem.style.msAnimationDuration = animArray.map(function (a) { return a.duration + "ms"; }).join(",");
|
|
elem.style.msAnimationTimingFunction = animArray.map(function (a) { return a.timing; }).join(",");
|
|
elem.style.msAnimationName = animArray.map(function (a) { return a.keyframe; }).join(",");
|
|
elem.style.msAnimationFillMode = "both";
|
|
|
|
var promise = new WinJS.Promise(function (c, e, p) {
|
|
var executeAnimationEnd = function (event) {
|
|
if (event.srcElement === elem) {
|
|
if ((releasePVLAnimation(styleelm, styleRef) === 0) && styleelm.parentElement) {
|
|
styleelm.parentElement.removeChild(styleelm);
|
|
}
|
|
promise._cEvents -= 1;
|
|
if (promise._cEvents === 0) {
|
|
clearAnimation(event.srcElement);
|
|
document.removeEventListener(event.type, executeAnimationEnd, false);
|
|
c(event); // complete after cleaning up the old animation
|
|
} else {
|
|
p(event);
|
|
}
|
|
}
|
|
};
|
|
document.addEventListener("MSAnimationEnd", executeAnimationEnd, false);
|
|
});
|
|
promise._cEvents = animArray.length;
|
|
return promise;
|
|
}
|
|
|
|
WinJS.Namespace.defineWithParent(WinJS, "UI", {
|
|
executeAnimation: function (element, animation) {
|
|
try {
|
|
var promiseArray = [];
|
|
var animArray = makeArray(animation);
|
|
var elemArray = makeArray(element);
|
|
var styleelm = document.createElement("STYLE");
|
|
document.documentElement.firstChild.appendChild(styleelm);
|
|
|
|
if (elemArray.length !== 0) {
|
|
for (var i = 0; i < elemArray.length; i++) {
|
|
if (elemArray[i] instanceof Array) {
|
|
for (var j = 0; j < elemArray[i].length; j++) {
|
|
getAnimationStaggerOffset(elemArray[i][j], animArray, i);
|
|
promiseArray.push(executeElementAnimation(elemArray[i][j], animArray, styleelm));
|
|
}
|
|
} else {
|
|
getAnimationStaggerOffset(elemArray[i], animArray, i);
|
|
promiseArray.push(executeElementAnimation(elemArray[i], animArray, styleelm));
|
|
}
|
|
}
|
|
} else {
|
|
return WinJS.Promise.wrap();
|
|
}
|
|
return WinJS.Promise.join(promiseArray);
|
|
} catch (e) {
|
|
return WinJS.Promise.wrapError(e);
|
|
}
|
|
},
|
|
|
|
executeTransition: function (element, transition) {
|
|
try {
|
|
var promiseArray = [];
|
|
var elemArray = makeArray(element);
|
|
var transArray = makeArray(transition);
|
|
if (elemArray.length !== 0) {
|
|
for (var i = 0; i < elemArray.length; i++) {
|
|
if (elemArray[i] instanceof Array) {
|
|
for (var j = 0; j < elemArray[i].length; j++) {
|
|
getTransitionStaggerTransform(transArray, i);
|
|
promiseArray.push(execElementTransition(elemArray[i][j], transArray));
|
|
}
|
|
} else {
|
|
getTransitionStaggerTransform(transArray, i);
|
|
promiseArray.push(execElementTransition(elemArray[i], transArray));
|
|
}
|
|
}
|
|
return WinJS.Promise.join(promiseArray);
|
|
} else {
|
|
return WinJS.Promise.wrap();
|
|
}
|
|
} catch (e) {
|
|
return WinJS.Promise.wrapError(e);
|
|
}
|
|
}
|
|
});
|
|
})(WinJS);
|
|
|